diff --git a/agentic-sap-workflows/ABAP/Z_CREATE_ONLINE_ORDER_IDOC_ABAPCODE.abap b/agentic-sap-workflows/ABAP/Z_CREATE_ONLINE_ORDER_IDOC_ABAPCODE.abap new file mode 100644 index 0000000..45d92fc --- /dev/null +++ b/agentic-sap-workflows/ABAP/Z_CREATE_ONLINE_ORDER_IDOC_ABAPCODE.abap @@ -0,0 +1,330 @@ + +FUNCTION z_create_onlineorder_idoc. +*"---------------------------------------------------------------------- +*"*"Local Interface: +*" IMPORTING +*" VALUE(IV_DIRECTION) TYPE CHAR01 DEFAULT 'O' +*" VALUE(IV_IDOCTYP) TYPE EDI_IDOCTP DEFAULT 'ZONLINEORDERIDOC' +*" VALUE(IV_MESTYP) TYPE EDIDC-MESTYP DEFAULT 'ZONLINEORDER' +*" VALUE(IV_SEGTP) TYPE EDIHSEGTYP DEFAULT 'ZONLINEORDER' +*" VALUE(IV_SNDPRT) TYPE EDIDC-SNDPRT OPTIONAL +*" VALUE(IV_SNDPRN) TYPE EDIDC-SNDPRN OPTIONAL +*" VALUE(IV_RCVPRT) TYPE EDIDC-RCVPRT OPTIONAL +*" VALUE(IV_RCVPRN) TYPE EDIDC-RCVPRN OPTIONAL +*" VALUE(IV_RCVPOR) TYPE EDIDC-RCVPOR OPTIONAL +*" EXPORTING +*" VALUE(EV_DOCNUM) TYPE EDIDC-DOCNUM +*" TABLES +*" IT_CSV STRUCTURE ZTY_CSV_LINE +*" ET_RETURN STRUCTURE BAPIRET2 +*" ET_DOCNUMS TYPE ZTY_DOCNUM_TT +*"---------------------------------------------------------------------- + + DATA: ls_ret TYPE bapiret2. + + " --- Validate direction once + IF iv_direction <> 'I' AND iv_direction <> 'O'. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '002'. + ls_ret-message = 'IV_DIRECTION must be I (inbound) or O (outbound).'. + ls_ret-message_v1 = 'I'. + ls_ret-message_v2 = 'O'. + APPEND ls_ret TO et_return. + RETURN. + ENDIF. + + " --- Ensure we have at least one row + IF it_csv[] IS INITIAL. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '003'. + ls_ret-message = 'IT_CSV must contain at least one line.'. + APPEND ls_ret TO et_return. + RETURN. + ENDIF. + + " ==================================================================== + " Main loop: each IT_CSV-LINE is one CSV record + " ==================================================================== + DATA: lv_idx TYPE i VALUE 0. + + LOOP AT it_csv INTO DATA(wa_csv). + lv_idx = lv_idx + 1. + + DATA(lv_csv) = CONV string( wa_csv-line ). " ZTY_CSV_LINE-LINE is CHAR2048 + + " --- Parse CSV into 14 tokens (quotes, commas-in-quotes, "" escape) + TYPES: string_tt TYPE STANDARD TABLE OF string WITH EMPTY KEY. + DATA: lt_tokens TYPE string_tt, + lv_len TYPE i, lv_pos TYPE i, lv_inq TYPE c LENGTH 1, + lv_c TYPE c LENGTH 1, lv_buf TYPE string. + + CLEAR: lt_tokens, lv_buf, lv_inq. + lv_len = strlen( lv_csv ). + lv_pos = 0. + + WHILE lv_pos < lv_len. + lv_c = lv_csv+lv_pos(1). + IF lv_c = '"'. + IF lv_inq IS INITIAL. + lv_inq = 'X'. + ELSE. + DATA(lv_next) = lv_pos + 1. + IF lv_next < lv_len AND lv_csv+lv_next(1) = '"'. + CONCATENATE lv_buf '"' INTO lv_buf. + lv_pos = lv_pos + 1. + ELSE. + CLEAR lv_inq. + ENDIF. + ENDIF. + ELSEIF lv_c = ',' AND lv_inq IS INITIAL. + APPEND lv_buf TO lt_tokens. + CLEAR lv_buf. + ELSE. + CONCATENATE lv_buf lv_c INTO lv_buf. + ENDIF. + lv_pos = lv_pos + 1. + ENDWHILE. + APPEND lv_buf TO lt_tokens. + + IF lines( lt_tokens ) <> 14. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '032'. + ls_ret-message = |Row { lv_idx }: CSV must contain exactly 14 comma-separated values.| . + APPEND ls_ret TO et_return. + CONTINUE. + ENDIF. + + " --- Map tokens + DATA: lv_order_id TYPE string, + lv_order_date_text TYPE string, + lv_customer_id TYPE string, + lv_product TYPE string, + lv_quantity_txt TYPE string, + lv_unit_price_txt TYPE string, + lv_ship_addr TYPE string, + lv_pay_method TYPE string, + lv_order_status TYPE string, + lv_tracking TYPE string, + lv_items_in_cart_txt TYPE string, + lv_coupon_code TYPE string, + lv_ref_source TYPE string, + lv_total_price_txt TYPE string. + + READ TABLE lt_tokens INDEX 1 INTO lv_order_id. + READ TABLE lt_tokens INDEX 2 INTO lv_order_date_text. + READ TABLE lt_tokens INDEX 3 INTO lv_customer_id. + READ TABLE lt_tokens INDEX 4 INTO lv_product. + READ TABLE lt_tokens INDEX 5 INTO lv_quantity_txt. + READ TABLE lt_tokens INDEX 6 INTO lv_unit_price_txt. + READ TABLE lt_tokens INDEX 7 INTO lv_ship_addr. + READ TABLE lt_tokens INDEX 8 INTO lv_pay_method. + READ TABLE lt_tokens INDEX 9 INTO lv_order_status. + READ TABLE lt_tokens INDEX 10 INTO lv_tracking. + READ TABLE lt_tokens INDEX 11 INTO lv_items_in_cart_txt. + READ TABLE lt_tokens INDEX 12 INTO lv_coupon_code. + READ TABLE lt_tokens INDEX 13 INTO lv_ref_source. + READ TABLE lt_tokens INDEX 14 INTO lv_total_price_txt. + + " --- Date parse to DATS + DATA: lv_order_date TYPE d, + lv_ok TYPE abap_bool VALUE abap_false. + + IF strlen( lv_order_date_text ) = 10 AND lv_order_date_text+4(1) = '-' AND lv_order_date_text+7(1) = '-'. + DATA(lv_iso) = lv_order_date_text. + REPLACE ALL OCCURRENCES OF '-' IN lv_iso WITH ''. + IF strlen( lv_iso ) = 8. + lv_order_date = lv_iso. + lv_ok = abap_true. + ENDIF. + ELSEIF strlen( lv_order_date_text ) = 8 AND lv_order_date_text CO '0123456789'. + lv_order_date = lv_order_date_text. + lv_ok = abap_true. + ENDIF. + + IF lv_ok = abap_false. + CALL FUNCTION 'DATE_CONV_EXT_TO_INT' + EXPORTING + i_date_ext = lv_order_date_text + IMPORTING + e_date_int = lv_order_date + EXCEPTIONS + invalid_date = 1 + OTHERS = 2. + IF sy-subrc = 0. + lv_ok = abap_true. + ENDIF. + ENDIF. + + IF lv_ok = abap_false OR lv_order_date IS INITIAL. + lv_order_date = sy-datum. + CLEAR ls_ret. + ls_ret-type = 'W'. + ls_ret-id = 'ZORD'. + ls_ret-number = '004'. + ls_ret-message = |Row { lv_idx }: Order date '{ lv_order_date_text }' not recognized; defaulted to SY-DATUM.|. + APPEND ls_ret TO et_return. + ENDIF. + + " --- Segment fill (typed) + DATA: ls_seg TYPE zonlineorder. + CLEAR ls_seg. + ls_seg-order_id = lv_order_id. + ls_seg-order_date = lv_order_date. + ls_seg-customer_id = lv_customer_id. + ls_seg-product = lv_product. + WRITE lv_quantity_txt TO ls_seg-quantity. + WRITE lv_unit_price_txt TO ls_seg-unit_price DECIMALS 2. + ls_seg-ship_address = lv_ship_addr. + ls_seg-payment_method = lv_pay_method. + ls_seg-order_status = lv_order_status. + ls_seg-tracking_number = lv_tracking. + WRITE lv_items_in_cart_txt TO ls_seg-items_in_cart. + ls_seg-coupon_code = lv_coupon_code. + ls_seg-referral_source = lv_ref_source. + WRITE lv_total_price_txt TO ls_seg-total_price DECIMALS 2. + + " --- Branch: inbound vs outbound + IF iv_direction = 'I'. + " Inbound (status 64) + DATA: lt_data TYPE STANDARD TABLE OF edidd WITH DEFAULT KEY, + ls_data TYPE edidd, + ls_ctrl TYPE edidc. + CLEAR: lt_data, ls_data, ls_ctrl. + + ls_data-segnam = iv_segtp. + ls_data-sdata = ls_seg. + APPEND ls_data TO lt_data. + + ls_ctrl-mestyp = iv_mestyp. + ls_ctrl-idoctp = iv_idoctyp. + ls_ctrl-direct = '2'. + ls_ctrl-rcvprt = 'LS'. + ls_ctrl-rcvprn = 'LOCAL'. + ls_ctrl-sndprt = 'LS'. + ls_ctrl-sndprn = 'LOCAL'. + + CALL FUNCTION 'IDOC_INBOUND_WRITE_TO_DB' + TABLES + t_data_records = lt_data + CHANGING + pc_control_record = ls_ctrl + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc = 0. + ev_docnum = ls_ctrl-docnum. + CLEAR ls_ret. + ls_ret-type = 'S'. + ls_ret-id = 'ZORD'. + ls_ret-number = '010'. + ls_ret-message = |Row { lv_idx }: Inbound IDoc created (status 64). DOCNUM={ ev_docnum }.|. + APPEND ls_ret TO et_return. + ELSE. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '011'. + ls_ret-message = |Row { lv_idx }: IDOC_INBOUND_WRITE_TO_DB failed.|. + APPEND ls_ret TO et_return. + ENDIF. + + ELSE. + +" --- Outbound (create & dispatch all, return all DOCNUMs) ------------- +DATA: ls_ctrl_o TYPE edidc, " EDI_DC40 + ls_data_o TYPE edidd, + t_ctrl_o TYPE STANDARD TABLE OF edidc WITH DEFAULT KEY, + t_data_o TYPE STANDARD TABLE OF edidd WITH DEFAULT KEY. + +CLEAR: ls_ctrl_o, ls_data_o. +CLEAR: t_ctrl_o, t_data_o. + +" Segment record +ls_data_o-segnam = iv_segtp. " <-- ensure consistency: IV_SEGTYP vs IV_SEGTP +ls_data_o-sdata = ls_seg. +APPEND ls_data_o TO t_data_o. + +" Control record (outbound) +ls_ctrl_o-mestyp = iv_mestyp. +ls_ctrl_o-idoctp = iv_idoctyp. +ls_ctrl_o-direct = '1'. +ls_ctrl_o-sndprt = COND #( WHEN iv_sndprt IS INITIAL THEN 'LS' ELSE iv_sndprt ). +ls_ctrl_o-sndprn = COND #( WHEN iv_sndprn IS INITIAL THEN 'LOCAL' ELSE iv_sndprn ). +ls_ctrl_o-rcvprt = COND #( WHEN iv_rcvprt IS INITIAL THEN 'LS' ELSE iv_rcvprt ). +ls_ctrl_o-rcvprn = COND #( WHEN iv_rcvprn IS INITIAL THEN 'LOCAL' ELSE iv_rcvprn ). +ls_ctrl_o-rcvpor = iv_rcvpor. + +" Append control to the comm table BEFORE calling the FM +APPEND ls_ctrl_o TO t_ctrl_o. + +" Create IDoc(s) → status 30 +CALL FUNCTION 'MASTER_IDOC_DISTRIBUTE' + EXPORTING + master_idoc_control = ls_ctrl_o + TABLES + communication_idoc_control = t_ctrl_o + master_idoc_data = t_data_o + EXCEPTIONS + error_in_idoc_control = 1 + error_writing_idoc_status = 2 + error_in_idoc_data = 3 + sending_logical_system_unknown = 4 + OTHERS = 5. + +IF sy-subrc = 0. + + " Collect all DOCNUMs from t_ctrl_o + REFRESH et_docnums. + CLEAR ev_docnum. + + LOOP AT t_ctrl_o INTO ls_ctrl_o WHERE docnum IS NOT INITIAL. + APPEND ls_ctrl_o-docnum TO et_docnums. " et_docnums is STANDARD TABLE OF EDI_DOCNUM + ev_docnum = ls_ctrl_o-docnum. " keep last for convenience + ENDLOOP. + + " Optional: dispatch each IDoc immediately (avoid status 30) + "LOOP AT et_docnums ASSIGNING FIELD-SYMBOL(). + "CALL FUNCTION 'IDOC_START_OUTBOUND' + " EXPORTING + " idoc_number = + " EXCEPTIONS + " OTHERS = 1. + "ENDLOOP. + + CALL FUNCTION 'DB_COMMIT'. + CALL FUNCTION 'DEQUEUE_ALL'. " or EDI_DOCUMENT_DEQUEUE_LATER for individual IDocs + COMMIT WORK AND WAIT. + + DATA(lv_cnt) = lines( et_docnums ). + DATA(lv_msg) = |Outbound IDoc(s) created and dispatched. Count={ lv_cnt }.|. + CLEAR ls_ret. + ls_ret-type = 'S'. + ls_ret-id = 'ZORD'. + ls_ret-number = '020'. + ls_ret-message = lv_msg. + APPEND ls_ret TO et_return. + +ELSE. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '021'. + ls_ret-message = |MASTER_IDOC_DISTRIBUTE failed (SY-SUBRC={ sy-subrc }).|. + APPEND ls_ret TO et_return. +ENDIF. + + + ENDIF. + + ENDLOOP. + + " Commit once at the end (batch-friendly) + COMMIT WORK AND WAIT. + +ENDFUNCTION. \ No newline at end of file diff --git a/agentic-sap-workflows/ABAP/Z_GET_ORDERS_ANALYSIS_ABAPCODE.abap b/agentic-sap-workflows/ABAP/Z_GET_ORDERS_ANALYSIS_ABAPCODE.abap new file mode 100644 index 0000000..9638d79 --- /dev/null +++ b/agentic-sap-workflows/ABAP/Z_GET_ORDERS_ANALYSIS_ABAPCODE.abap @@ -0,0 +1,44 @@ +FUNCTION Z_GET_ORDERS_ANALYSIS. +*"---------------------------------------------------------------------- +*"*"Local Interface: +*" IMPORTING +*" VALUE(DEST) TYPE CHAR20 DEFAULT 'YOURDESTINATION' +*" EXPORTING +*" VALUE(EXCEPTIONMSG) TYPE ZCHAR1000 +*" VALUE(ANALYSIS) TYPE STRING +*" TABLES +*" IT_CSV STRUCTURE ZTY_CSV_LINE +*" CHANGING +*" VALUE(RETURN) TYPE BAPIRET2 OPTIONAL +*" EXCEPTIONS +*" SENDEXCEPTIONTOSAPSERVER +*"---------------------------------------------------------------------- + +* Calls remote function Z_GET_ORDERS_ANALYSIS, passing IT_CSV and returning ANALYSIS and RETURN. +*----------------------------------------------------------------------- + +CALL FUNCTION 'Z_GET_ORDERS_ANALYSIS' DESTINATION DEST + IMPORTING + ANALYSIS = ANALYSIS + TABLES + IT_CSV = IT_CSV + CHANGING + RETURN = RETURN + EXCEPTIONS + SENDEXCEPTIONTOSAPSERVER = 1 + system_failure = 2 MESSAGE EXCEPTIONMSG + communication_failure = 3 MESSAGE EXCEPTIONMSG + OTHERS = 4. + +CASE sy-subrc. + WHEN 0. + EXCEPTIONMSG = 'ok'. + WHEN 1. + EXCEPTIONMSG = |Exception from workflow: SENDEXCEPTIONTOSAPSERVER { sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv4 } |. + WHEN 2 OR 3. + EXCEPTIONMSG = |System or communication failure while calling Z_GET_ORDERS_ANALYSIS: { sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv4 } |. + WHEN OTHERS. + EXCEPTIONMSG = |Error in workflow: { sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv4 } |. +ENDCASE. + +ENDFUNCTION. \ No newline at end of file diff --git a/agentic-sap-workflows/ABAP/Z_GET_ORDERS_ANALYSIS_EXCEPTIONMESSAGE_ABAPCODE.abap b/agentic-sap-workflows/ABAP/Z_GET_ORDERS_ANALYSIS_EXCEPTIONMESSAGE_ABAPCODE.abap new file mode 100644 index 0000000..5db4fe6 --- /dev/null +++ b/agentic-sap-workflows/ABAP/Z_GET_ORDERS_ANALYSIS_EXCEPTIONMESSAGE_ABAPCODE.abap @@ -0,0 +1,55 @@ +FUNCTION Z_GET_ORDERS_ANALYSIS. +*"---------------------------------------------------------------------- +*"*"Local Interface: +*" IMPORTING +*" VALUE(DEST) TYPE CHAR20 DEFAULT 'YOURDESTINATION' +*" EXPORTING +*" VALUE(EXCEPTIONMSG) TYPE ZCHAR1000 +*" VALUE(ANALYSIS) TYPE STRING +*" TABLES +*" IT_CSV STRUCTURE ZTY_CSV_LINE +*" CHANGING +*" VALUE(RETURN) TYPE BAPIRET2 OPTIONAL +*" EXCEPTIONS +*" SENDEXCEPTIONTOSAPSERVER +*"---------------------------------------------------------------------- + +* SUBMITs ZCREATE_ONLINEORDER_IDOC for each CSV line, passing parameters. +*----------------------------------------------------------------------- + +TRY. +CALL FUNCTION 'Z_GET_ORDERS_ANALYSIS' DESTINATION DEST + IMPORTING + ANALYSIS = ANALYSIS + EXCEPTIONMSG = EXCEPTIONMSG + TABLES + IT_CSV = IT_CSV + CHANGING + RETURN = RETURN + EXCEPTIONS + system_failure = 1 + communication_failure = 2. + +CATCH +cx_root INTO DATA(lx_any). "Optional for other exceptions + +ENDTRY. + +IF sy-subrc <> 0. + +DATA: lv_text TYPE string. + +CALL FUNCTION 'FORMAT_MESSAGE' + EXPORTING + id = sy-msgid + NO = sy-msgno + v1 = sy-msgv1 + v2 = sy-msgv2 + v3 = sy-msgv3 + v4 = sy-msgv4 + IMPORTING + msg = EXCEPTIONMSG. + +ENDIF. + +ENDFUNCTION. \ No newline at end of file diff --git a/agentic-sap-workflows/ABAP/Z_GET_ORDERS_ANALYSIS_NAMEDEXCEPTION_ABAPCODE.abap b/agentic-sap-workflows/ABAP/Z_GET_ORDERS_ANALYSIS_NAMEDEXCEPTION_ABAPCODE.abap new file mode 100644 index 0000000..591d99c --- /dev/null +++ b/agentic-sap-workflows/ABAP/Z_GET_ORDERS_ANALYSIS_NAMEDEXCEPTION_ABAPCODE.abap @@ -0,0 +1,45 @@ +FUNCTION Z_GET_ORDERS_ANALYSIS. +*"---------------------------------------------------------------------- +*"*"Local Interface: +*" IMPORTING +*" VALUE(DEST) TYPE CHAR20 DEFAULT 'YOURDESTINATION' +*" EXPORTING +*" VALUE(EXCEPTIONMSG) TYPE ZCHAR1000 +*" VALUE(ANALYSIS) TYPE STRING +*" TABLES +*" IT_CSV STRUCTURE ZTY_CSV_LINE +*" CHANGING +*" VALUE(RETURN) TYPE BAPIRET2 OPTIONAL +*" EXCEPTIONS +*" SENDEXCEPTIONTOSAPSERVER +*"---------------------------------------------------------------------- + +* SUBMITs ZCREATE_ONLINEORDER_IDOC for each CSV line, passing parameters. +*----------------------------------------------------------------------- + +CALL FUNCTION 'Z_GET_ORDERS_ANALYSIS' DESTINATION DEST + IMPORTING + ANALYSIS = ANALYSIS + EXCEPTIONMSG = EXCEPTIONMSG + TABLES + IT_CSV = IT_CSV + CHANGING + RETURN = RETURN + EXCEPTIONS + SENDEXCEPTIONTOSAPSERVER = 1 + YOUR_EXCEPTION_NAME_HERE = 2 + system_failure = 3 MESSAGE EXCEPTIONMSG + communication_failure = 4 MESSAGE EXCEPTIONMSG + OTHERS = 5. + +CASE sy-subrc. + WHEN 0. + EXCEPTIONMSG = 'ok'. + WHEN 1 or 2. + EXCEPTIONMSG = |Exception from workflow: { sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv4 } |. + WHEN 3 or 4. + WHEN OTHERS. + EXCEPTIONMSG = |Error in workflow: { sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv4 } |. +ENDCASE. + +ENDFUNCTION. \ No newline at end of file diff --git a/agentic-sap-workflows/ABAP/zchar1000.doma.xml b/agentic-sap-workflows/ABAP/zchar1000.doma.xml new file mode 100644 index 0000000..8866d8f --- /dev/null +++ b/agentic-sap-workflows/ABAP/zchar1000.doma.xml @@ -0,0 +1,15 @@ + + + + + + ZCHAR1000 + E + CHAR + 001000 + 001000 + Large fixed length string + + + + diff --git a/agentic-sap-workflows/ABAP/zchar1000.dtel.xml b/agentic-sap-workflows/ABAP/zchar1000.dtel.xml new file mode 100644 index 0000000..c8e5178 --- /dev/null +++ b/agentic-sap-workflows/ABAP/zchar1000.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZCHAR1000 + E + ZCHAR1000 + large fixed-size string + E + D + + + + diff --git a/agentic-sap-workflows/Online-Store-Orders-Sample.csv b/agentic-sap-workflows/Online-Store-Orders-Sample.csv new file mode 100644 index 0000000..471f8a8 --- /dev/null +++ b/agentic-sap-workflows/Online-Store-Orders-Sample.csv @@ -0,0 +1,20 @@ +OrderID,Date,CustomerID,Product,Quantity,UnitPrice,ShippingAddress,PaymentMethod,OrderStatus,TrackingNumber,ItemsInCart,CouponCode,ReferralSource,TotalPrice +ORD200000,1/4/2023,C72649,Monitor,5,570.62,928 Main St,Debit Card,Shipped,TRK37947903,7,SAVE10,Instagram,2853.1 +ORD200001,8/23/2024,C75739,Phone,2,151.35,823 Main St,Online,Shipped,TRK91186779,3,SAVE10,Referral,302.7 +ORD200002,2/27/2024,C81728,Tablet,5,550.68,512 Main St,Credit Card,Cancelled,TRK42903982,8,FREESHIP,Email,2753.4 +ORD200000,1/4/2023,C72649,Monitor,5,570.62,928 Main St,Debit Card,Shipped,TRK37947903,7,SAVE10,Instagram,2853.1 +ORD200001,8/23/2024,C75739,Phone,2,151.35,823 Main St,Online,Shipped,TRK91186779,3,SAVE10,Referral,302.7 +ORD200002,2/27/2024,C81728,Tablet,5,550.68,512 Main St,Credit Card,Cancelled,TRK42903982,8,FREESHIP,Email,2753.4 +ORD200003,10/15/2023,C33540,Chair,1,273.19,275 Main St,Debit Card,Returned,TRK62788070,5,SAVE10,Facebook,273.19 +ORD200004,5/8/2025,C81840,Printer,4,626.01,668 Main St,Online,Delivered,TRK29241424,8,SAVE10,Email,2504.04 +ORD200005,10/23/2023,C37249,Phone,2,245.86,934 Main St,Credit Card,Shipped,TRK72976927,4,SAVE10,Instagram,491.72 +ORD200006,6/17/2025,C83492,Laptop,1,664.42,986 Main St,Gift Card,Returned,TRK96417362,6,SAVE10,Facebook,664.42 +ORD200007,5/12/2023,C41460,Monitor,5,149.55,706 Main St,Cash,Shipped,TRK78809193,9,FREESHIP,Facebook,747.75 +ORD200008,4/2/2025,C26817,Phone,2,134.28,904 Main St,Gift Card,Cancelled,TRK61042692,2,,Email,268.56 +ORD200009,11/21/2023,C31946,Desk,4,509.38,102 Main St,Credit Card,Shipped,TRK33478363,6,SAVE10,Google,2037.52 +ORD200010,12/29/2023,C43443,Tablet,5,625.97,333 Main St,Credit Card,Returned,TRK98859248,9,WINTER15,Instagram,3129.85 +ORD200011,2/17/2024,C93861,Monitor,3,49.14,831 Main St,Online,Returned,TRK48234646,7,SAVE10,Email,147.42 +ORD200012,10/15/2024,C38785,Monitor,2,180.5,179 Main St,Debit Card,Pending,TRK20419991,6,FREESHIP,Referral,361 +ORD200013,8/30/2023,C88348,Laptop,3,201.49,903 Main St,Credit Card,Returned,TRK81913874,4,FREESHIP,Facebook,604.47 +ORD200014,3/27/2023,C98474,Tablet,2,393.33,980 Main St,Debit Card,Pending,TRK79186539,3,SAVE10,Instagram,786.66 +ORD200015,7/17/2023,C39416,Printer,1,473.96,942 Main St,Cash,Delivered,TRK54930938,3,,Google,473.96 diff --git a/agentic-sap-workflows/Online-Store-Orders.csv b/agentic-sap-workflows/Online-Store-Orders.csv new file mode 100644 index 0000000..c23acb5 --- /dev/null +++ b/agentic-sap-workflows/Online-Store-Orders.csv @@ -0,0 +1,1201 @@ +OrderID,Date,CustomerID,Product,Quantity,UnitPrice,ShippingAddress,PaymentMethod,OrderStatus,TrackingNumber,ItemsInCart,CouponCode,ReferralSource,TotalPrice +ORD200000,2023-01-04,C72649,Monitor,5,570.62,928 Main St,Debit Card,Shipped,TRK37947903,7,SAVE10,Instagram,2853.1 +ORD200001,2024-08-23,C75739,Phone,2,151.35,823 Main St,Online,Shipped,TRK91186779,3,SAVE10,Referral,302.7 +ORD200002,2024-02-27,C81728,Tablet,5,550.68,512 Main St,Credit Card,Cancelled,TRK42903982,8,FREESHIP,Email,2753.4 +ORD200003,2023-10-15,C33540,Chair,1,273.19,275 Main St,Debit Card,Returned,TRK62788070,5,SAVE10,Facebook,273.19 +ORD200004,2025-05-08,C81840,Printer,4,626.01,668 Main St,Online,Delivered,TRK29241424,8,SAVE10,Email,2504.04 +ORD200005,2023-10-23,C37249,Phone,2,245.86,934 Main St,Credit Card,Shipped,TRK72976927,4,SAVE10,Instagram,491.72 +ORD200006,2025-06-17,C83492,Laptop,1,664.42,986 Main St,Gift Card,Returned,TRK96417362,6,SAVE10,Facebook,664.42 +ORD200007,2023-05-12,C41460,Monitor,5,149.55,706 Main St,Cash,Shipped,TRK78809193,9,FREESHIP,Facebook,747.75 +ORD200008,2025-04-02,C26817,Phone,2,134.28,904 Main St,Gift Card,Cancelled,TRK61042692,2,,Email,268.56 +ORD200009,2023-11-21,C31946,Desk,4,509.38,102 Main St,Credit Card,Shipped,TRK33478363,6,SAVE10,Google,2037.52 +ORD200010,2023-12-29,C43443,Tablet,5,625.97,333 Main St,Credit Card,Returned,TRK98859248,9,WINTER15,Instagram,3129.85 +ORD200011,2024-02-17,C93861,Monitor,3,49.14,831 Main St,Online,Returned,TRK48234646,7,SAVE10,Email,147.42 +ORD200012,2024-10-15,C38785,Monitor,2,180.5,179 Main St,Debit Card,Pending,TRK20419991,6,FREESHIP,Referral,361 +ORD200013,2023-08-30,C88348,Laptop,3,201.49,903 Main St,Credit Card,Returned,TRK81913874,4,FREESHIP,Facebook,604.47 +ORD200014,2023-03-27,C98474,Tablet,2,393.33,980 Main St,Debit Card,Pending,TRK79186539,3,SAVE10,Instagram,786.66 +ORD200015,2023-07-17,C39416,Printer,1,473.96,942 Main St,Cash,Delivered,TRK54930938,3,,Google,473.96 +ORD200016,2023-01-24,C28976,Printer,2,533.81,914 Main St,Credit Card,Pending,TRK13194259,3,FREESHIP,Email,1067.62 +ORD200017,2024-03-02,C60672,Tablet,1,423.4,382 Main St,Debit Card,Shipped,TRK11972116,3,,Referral,423.4 +ORD200018,2025-03-26,C84329,Desk,1,431.44,891 Main St,Gift Card,Pending,TRK65191045,3,SAVE10,Facebook,431.44 +ORD200019,2023-01-23,C14552,Monitor,5,224,273 Main St,Cash,Returned,TRK59101365,9,SAVE10,Google,1120 +ORD200020,2023-05-08,C54829,Chair,5,62.51,587 Main St,Cash,Pending,TRK16718651,9,WINTER15,Instagram,312.55 +ORD200021,2024-11-17,C99023,Monitor,4,342.95,569 Main St,Cash,Delivered,TRK52646983,6,,Google,1371.8 +ORD200022,2023-01-29,C34416,Monitor,2,49.62,633 Main St,Online,Pending,TRK75937350,2,SAVE10,Google,99.24 +ORD200023,2025-04-09,C42372,Phone,4,273.25,755 Main St,Debit Card,Cancelled,TRK36168083,5,FREESHIP,Referral,1093 +ORD200024,2024-10-30,C17470,Laptop,2,230.95,956 Main St,Online,Delivered,TRK28775057,3,WINTER15,Referral,461.9 +ORD200025,2024-07-24,C42577,Monitor,1,399.98,709 Main St,Debit Card,Delivered,TRK69423327,3,WINTER15,Email,399.98 +ORD200026,2024-03-06,C21944,Laptop,5,59.55,296 Main St,Online,Delivered,TRK80276812,6,,Referral,297.75 +ORD200027,2024-02-22,C97593,Printer,1,472.74,881 Main St,Online,Shipped,TRK89117573,6,WINTER15,Google,472.74 +ORD200028,2023-11-21,C59823,Phone,4,160.07,568 Main St,Online,Pending,TRK65895539,5,,Email,640.28 +ORD200029,2024-09-20,C33260,Desk,3,423.53,930 Main St,Credit Card,Delivered,TRK59744090,6,SAVE10,Referral,1270.59 +ORD200030,2025-03-22,C44267,Monitor,2,426.7,895 Main St,Online,Pending,TRK54751444,5,SAVE10,Referral,853.4 +ORD200031,2023-06-30,C26445,Chair,3,500.08,996 Main St,Debit Card,Returned,TRK31229981,6,,Facebook,1500.24 +ORD200032,2023-05-01,C12388,Tablet,5,536.72,830 Main St,Cash,Delivered,TRK99261395,10,,Email,2683.6 +ORD200033,2023-06-05,C52184,Chair,1,162.77,912 Main St,Online,Cancelled,TRK73312471,4,WINTER15,Facebook,162.77 +ORD200034,2023-01-07,C67195,Chair,4,576.52,926 Main St,Credit Card,Pending,TRK55467915,5,WINTER15,Facebook,2306.08 +ORD200035,2024-12-07,C50304,Monitor,2,465.15,128 Main St,Online,Shipped,TRK46850888,2,SAVE10,Facebook,930.3 +ORD200036,2025-05-08,C59337,Laptop,2,534.43,465 Main St,Debit Card,Pending,TRK50961250,5,,Facebook,1068.86 +ORD200037,2024-10-14,C10054,Laptop,2,76.74,409 Main St,Cash,Returned,TRK94005261,7,SAVE10,Instagram,153.48 +ORD200038,2024-12-19,C15924,Laptop,1,245.89,549 Main St,Debit Card,Delivered,TRK14835975,3,SAVE10,Google,245.89 +ORD200039,2025-02-27,C96664,Printer,3,256.46,666 Main St,Credit Card,Delivered,TRK85508960,4,SAVE10,Referral,769.38 +ORD200040,2023-08-20,C84766,Desk,2,344.02,267 Main St,Online,Delivered,TRK78967923,4,FREESHIP,Instagram,688.04 +ORD200041,2023-12-05,C20212,Monitor,3,611.45,657 Main St,Gift Card,Pending,TRK69733327,4,FREESHIP,Instagram,1834.35 +ORD200042,2024-05-06,C28712,Printer,2,151.66,980 Main St,Cash,Cancelled,TRK40772558,6,,Instagram,303.32 +ORD200043,2023-12-14,C60572,Chair,3,499.21,871 Main St,Online,Cancelled,TRK20351666,8,,Instagram,1497.63 +ORD200044,2025-04-21,C73225,Phone,2,550.18,996 Main St,Gift Card,Returned,TRK73848522,3,FREESHIP,Referral,1100.36 +ORD200045,2024-02-10,C17388,Chair,1,317.25,157 Main St,Debit Card,Returned,TRK47077395,1,SAVE10,Facebook,317.25 +ORD200046,2024-06-26,C43212,Monitor,4,550.14,223 Main St,Debit Card,Pending,TRK25100762,4,FREESHIP,Instagram,2200.56 +ORD200047,2023-07-19,C38134,Desk,2,209.94,323 Main St,Credit Card,Returned,TRK42450754,3,FREESHIP,Email,419.88 +ORD200048,2023-08-26,C12408,Monitor,2,80.77,464 Main St,Debit Card,Shipped,TRK38938858,4,,Google,161.54 +ORD200049,2023-10-07,C11985,Printer,1,30.44,633 Main St,Credit Card,Shipped,TRK53272402,1,SAVE10,Email,30.44 +ORD200050,2023-07-31,C96494,Tablet,1,179.22,446 Main St,Online,Cancelled,TRK14675049,6,FREESHIP,Instagram,179.22 +ORD200051,2024-12-30,C36778,Tablet,1,388.33,434 Main St,Cash,Returned,TRK67610289,2,SAVE10,Facebook,388.33 +ORD200052,2024-09-08,C30513,Tablet,1,586.44,232 Main St,Online,Returned,TRK64320429,5,SAVE10,Facebook,586.44 +ORD200053,2024-05-18,C67551,Phone,4,488.78,512 Main St,Online,Returned,TRK94992552,5,FREESHIP,Google,1955.12 +ORD200054,2025-03-27,C48120,Chair,1,280.25,623 Main St,Online,Pending,TRK11014449,5,WINTER15,Email,280.25 +ORD200055,2025-06-24,C95984,Printer,3,344.4,565 Main St,Online,Cancelled,TRK67434829,3,,Facebook,1033.2 +ORD200056,2023-05-21,C54298,Tablet,3,479.21,566 Main St,Cash,Cancelled,TRK62902341,5,WINTER15,Referral,1437.63 +ORD200057,2023-01-22,C88036,Printer,5,314.27,842 Main St,Cash,Returned,TRK52470128,6,SAVE10,Instagram,1571.35 +ORD200058,2023-01-15,C60190,Phone,4,474.69,202 Main St,Gift Card,Cancelled,TRK70857868,6,SAVE10,Google,1898.76 +ORD200059,2024-09-11,C97603,Chair,4,593.27,811 Main St,Online,Shipped,TRK47055028,5,,Facebook,2373.08 +ORD200060,2024-08-21,C39256,Desk,1,417.1,634 Main St,Debit Card,Returned,TRK23412025,3,FREESHIP,Referral,417.1 +ORD200061,2024-03-24,C61618,Desk,4,122.2,104 Main St,Cash,Delivered,TRK43458485,7,FREESHIP,Facebook,488.8 +ORD200062,2023-08-22,C36497,Desk,2,43.15,691 Main St,Debit Card,Pending,TRK12102911,3,WINTER15,Email,86.3 +ORD200063,2025-02-02,C96695,Chair,1,564.86,813 Main St,Debit Card,Shipped,TRK64283851,6,WINTER15,Referral,564.86 +ORD200064,2025-06-25,C49720,Printer,3,130.61,752 Main St,Debit Card,Cancelled,TRK55785217,4,FREESHIP,Facebook,391.83 +ORD200065,2023-12-30,C97735,Monitor,5,81.7,385 Main St,Credit Card,Delivered,TRK13743703,6,,Instagram,408.5 +ORD200066,2024-11-15,C18104,Chair,5,127.18,715 Main St,Cash,Cancelled,TRK15488568,9,SAVE10,Referral,635.9 +ORD200067,2024-12-09,C25587,Printer,4,12.1,440 Main St,Debit Card,Cancelled,TRK55105323,8,,Google,48.4 +ORD200068,2023-12-11,C41598,Chair,3,490.92,709 Main St,Credit Card,Pending,TRK81665940,5,FREESHIP,Email,1472.76 +ORD200069,2023-05-11,C43338,Monitor,3,478.65,552 Main St,Online,Shipped,TRK35241775,4,,Referral,1435.95 +ORD200070,2023-05-26,C25123,Desk,1,629.21,384 Main St,Gift Card,Pending,TRK27812282,2,FREESHIP,Instagram,629.21 +ORD200071,2025-06-10,C37454,Monitor,3,434.45,923 Main St,Credit Card,Pending,TRK28252730,4,,Referral,1303.35 +ORD200072,2024-12-22,C19451,Tablet,4,589.44,942 Main St,Gift Card,Returned,TRK87787793,5,,Facebook,2357.76 +ORD200073,2023-05-03,C17269,Monitor,4,433.45,129 Main St,Gift Card,Cancelled,TRK79608389,4,,Facebook,1733.8 +ORD200074,2023-06-24,C25382,Phone,5,90.87,622 Main St,Cash,Pending,TRK64691287,5,,Instagram,454.35 +ORD200075,2023-09-26,C80651,Tablet,3,398.17,917 Main St,Debit Card,Delivered,TRK14846720,5,SAVE10,Email,1194.51 +ORD200076,2024-03-31,C58638,Laptop,4,382.88,239 Main St,Cash,Cancelled,TRK38224871,6,WINTER15,Email,1531.52 +ORD200077,2024-05-24,C50121,Phone,1,583.18,348 Main St,Credit Card,Returned,TRK79810059,5,,Google,583.18 +ORD200078,2024-08-06,C32029,Printer,4,175.36,146 Main St,Debit Card,Delivered,TRK68535532,4,FREESHIP,Instagram,701.44 +ORD200079,2025-03-10,C76700,Tablet,2,311.91,103 Main St,Online,Shipped,TRK13036341,2,,Facebook,623.82 +ORD200080,2023-06-27,C29041,Phone,3,589.56,591 Main St,Online,Returned,TRK28840655,6,,Facebook,1768.68 +ORD200081,2023-06-08,C29314,Monitor,2,394.3,496 Main St,Cash,Shipped,TRK59876213,6,FREESHIP,Email,788.6 +ORD200082,2024-01-05,C65799,Tablet,4,565.2,971 Main St,Debit Card,Shipped,TRK66906607,9,SAVE10,Google,2260.8 +ORD200083,2023-08-22,C15681,Laptop,4,540.41,989 Main St,Credit Card,Cancelled,TRK75112172,6,,Referral,2161.64 +ORD200084,2023-08-28,C64160,Monitor,2,165.49,967 Main St,Online,Shipped,TRK34121529,4,WINTER15,Instagram,330.98 +ORD200085,2024-09-09,C14553,Tablet,3,146.73,768 Main St,Cash,Delivered,TRK93538334,8,FREESHIP,Email,440.19 +ORD200086,2024-06-19,C88205,Printer,5,643.03,447 Main St,Online,Cancelled,TRK93504166,5,FREESHIP,Referral,3215.15 +ORD200087,2024-10-10,C91245,Tablet,3,225.11,915 Main St,Cash,Shipped,TRK46976391,4,SAVE10,Facebook,675.33 +ORD200088,2025-06-05,C75439,Desk,3,114.81,318 Main St,Gift Card,Cancelled,TRK19831653,7,,Google,344.43 +ORD200089,2025-02-25,C17181,Printer,5,455.33,291 Main St,Credit Card,Cancelled,TRK78912978,8,FREESHIP,Google,2276.65 +ORD200090,2023-09-18,C36540,Chair,4,182.08,611 Main St,Gift Card,Delivered,TRK35828122,4,SAVE10,Email,728.32 +ORD200091,2023-03-15,C98216,Laptop,5,492.75,196 Main St,Cash,Shipped,TRK40986666,6,WINTER15,Referral,2463.75 +ORD200092,2024-06-10,C29568,Printer,4,48.61,203 Main St,Online,Shipped,TRK46531075,7,FREESHIP,Facebook,194.44 +ORD200093,2023-01-14,C97262,Desk,4,431.01,837 Main St,Credit Card,Returned,TRK65990229,7,,Referral,1724.04 +ORD200094,2023-02-11,C79821,Chair,1,531.18,781 Main St,Gift Card,Returned,TRK12780193,6,WINTER15,Instagram,531.18 +ORD200095,2023-03-24,C76761,Printer,4,117.51,839 Main St,Debit Card,Returned,TRK60179774,7,,Referral,470.04 +ORD200096,2024-06-01,C93007,Phone,2,232.83,103 Main St,Gift Card,Delivered,TRK85696091,7,,Instagram,465.66 +ORD200097,2025-01-21,C15624,Tablet,5,619.52,922 Main St,Debit Card,Pending,TRK40621141,9,,Email,3097.6 +ORD200098,2023-01-14,C70921,Printer,2,228.54,533 Main St,Debit Card,Pending,TRK54983109,3,,Email,457.08 +ORD200099,2025-04-12,C30477,Printer,1,201.58,717 Main St,Debit Card,Cancelled,TRK51829648,2,WINTER15,Email,201.58 +ORD200100,2023-02-17,C74866,Phone,3,664.79,743 Main St,Online,Delivered,TRK53783265,6,,Facebook,1994.37 +ORD200101,2023-11-25,C15283,Printer,1,381.02,152 Main St,Cash,Shipped,TRK19286291,6,,Google,381.02 +ORD200102,2023-03-08,C18037,Laptop,2,70.34,944 Main St,Gift Card,Cancelled,TRK47362236,3,FREESHIP,Email,140.68 +ORD200103,2025-01-25,C62656,Phone,4,218.43,514 Main St,Credit Card,Cancelled,TRK86296459,9,SAVE10,Email,873.72 +ORD200104,2024-07-30,C65744,Phone,1,582.04,647 Main St,Gift Card,Delivered,TRK39906058,1,FREESHIP,Email,582.04 +ORD200105,2024-10-24,C72290,Printer,3,185.4,810 Main St,Gift Card,Cancelled,TRK68792129,7,,Facebook,556.2 +ORD200106,2023-09-08,C73514,Desk,3,465.05,126 Main St,Credit Card,Cancelled,TRK96777924,3,SAVE10,Email,1395.15 +ORD200107,2023-03-27,C16775,Printer,5,670.75,848 Main St,Gift Card,Shipped,TRK34392124,8,FREESHIP,Instagram,3353.75 +ORD200108,2024-12-28,C33099,Laptop,5,48.38,522 Main St,Gift Card,Delivered,TRK28522330,9,WINTER15,Email,241.9 +ORD200109,2023-09-17,C51157,Desk,3,592.87,131 Main St,Gift Card,Shipped,TRK18674578,3,FREESHIP,Referral,1778.61 +ORD200110,2024-04-21,C74562,Tablet,1,220.77,388 Main St,Gift Card,Pending,TRK32062079,5,FREESHIP,Instagram,220.77 +ORD200111,2025-05-07,C95271,Desk,3,309.22,620 Main St,Online,Cancelled,TRK74904969,7,FREESHIP,Google,927.66 +ORD200112,2023-01-01,C81366,Monitor,1,410.6,423 Main St,Online,Cancelled,TRK17062206,2,WINTER15,Referral,410.6 +ORD200113,2024-01-17,C65905,Laptop,5,190.08,605 Main St,Cash,Shipped,TRK73954365,9,FREESHIP,Instagram,950.4 +ORD200114,2025-01-27,C77272,Monitor,5,498.48,115 Main St,Online,Pending,TRK29708128,8,SAVE10,Google,2492.4 +ORD200115,2023-11-27,C32580,Phone,5,374.99,122 Main St,Online,Shipped,TRK23670394,9,SAVE10,Facebook,1874.95 +ORD200116,2023-03-19,C47761,Printer,4,291.35,109 Main St,Credit Card,Cancelled,TRK66669207,6,WINTER15,Facebook,1165.4 +ORD200117,2023-03-08,C49187,Tablet,1,535.5,593 Main St,Gift Card,Cancelled,TRK81888598,5,WINTER15,Referral,535.5 +ORD200118,2023-10-09,C27898,Printer,5,502.71,807 Main St,Gift Card,Shipped,TRK61957665,7,FREESHIP,Google,2513.55 +ORD200119,2025-06-11,C14683,Desk,2,534.67,187 Main St,Debit Card,Shipped,TRK47373682,7,FREESHIP,Referral,1069.34 +ORD200120,2023-04-11,C58108,Tablet,4,629.34,986 Main St,Cash,Cancelled,TRK66218053,4,WINTER15,Instagram,2517.36 +ORD200121,2023-11-30,C89822,Desk,1,410.78,673 Main St,Cash,Cancelled,TRK24138598,1,FREESHIP,Instagram,410.78 +ORD200122,2024-04-15,C96787,Laptop,2,533.02,588 Main St,Gift Card,Shipped,TRK30422853,2,,Facebook,1066.04 +ORD200123,2023-07-06,C86064,Desk,3,278.04,727 Main St,Online,Delivered,TRK62182901,5,,Instagram,834.12 +ORD200124,2024-07-28,C97148,Printer,4,283.79,563 Main St,Online,Pending,TRK85321126,8,,Google,1135.16 +ORD200125,2024-11-06,C91099,Phone,2,512.65,758 Main St,Credit Card,Shipped,TRK81846174,5,SAVE10,Email,1025.3 +ORD200126,2025-05-03,C55606,Desk,4,275.5,353 Main St,Gift Card,Shipped,TRK68250319,8,FREESHIP,Google,1102 +ORD200127,2023-08-10,C71486,Desk,3,469.32,365 Main St,Debit Card,Shipped,TRK73929833,3,,Google,1407.96 +ORD200128,2023-02-17,C86408,Tablet,4,21.07,244 Main St,Gift Card,Delivered,TRK41432648,4,FREESHIP,Google,84.28 +ORD200129,2023-10-27,C52751,Laptop,4,263.93,427 Main St,Debit Card,Shipped,TRK72481234,4,FREESHIP,Facebook,1055.72 +ORD200130,2025-01-22,C29059,Desk,3,501.3,513 Main St,Online,Cancelled,TRK88360704,3,WINTER15,Facebook,1503.9 +ORD200131,2023-01-08,C72862,Tablet,1,84.8,606 Main St,Gift Card,Pending,TRK51648833,5,,Instagram,84.8 +ORD200132,2023-03-28,C96257,Tablet,4,450.75,583 Main St,Credit Card,Shipped,TRK13137948,6,WINTER15,Email,1803 +ORD200133,2025-06-20,C87432,Chair,4,302.05,636 Main St,Debit Card,Cancelled,TRK68969625,6,SAVE10,Google,1208.2 +ORD200134,2025-06-23,C16253,Laptop,2,199.7,583 Main St,Cash,Pending,TRK17354894,4,,Email,399.4 +ORD200135,2023-08-04,C79909,Printer,2,68.81,642 Main St,Gift Card,Shipped,TRK86742257,5,SAVE10,Referral,137.62 +ORD200136,2024-04-27,C73370,Laptop,1,44.35,595 Main St,Gift Card,Cancelled,TRK67820278,1,SAVE10,Instagram,44.35 +ORD200137,2024-11-26,C50682,Monitor,2,250.98,598 Main St,Credit Card,Delivered,TRK12242337,5,,Google,501.96 +ORD200138,2023-12-21,C21905,Tablet,1,298.06,478 Main St,Debit Card,Pending,TRK31863841,3,WINTER15,Google,298.06 +ORD200139,2023-04-10,C61440,Phone,1,583.9,714 Main St,Cash,Returned,TRK33114521,1,,Email,583.9 +ORD200140,2025-05-31,C33110,Chair,3,528.14,388 Main St,Online,Delivered,TRK38624225,3,FREESHIP,Email,1584.42 +ORD200141,2023-11-18,C80004,Printer,3,684.14,151 Main St,Cash,Cancelled,TRK66230753,3,WINTER15,Instagram,2052.42 +ORD200142,2023-09-06,C86374,Desk,5,272.77,573 Main St,Cash,Pending,TRK79451491,7,WINTER15,Email,1363.85 +ORD200143,2024-06-13,C66521,Chair,4,400.07,933 Main St,Online,Shipped,TRK34654244,5,,Referral,1600.28 +ORD200144,2023-08-04,C63365,Desk,5,219.78,895 Main St,Credit Card,Pending,TRK80100887,8,,Facebook,1098.9 +ORD200145,2024-03-02,C85929,Printer,3,146.91,798 Main St,Credit Card,Delivered,TRK29318610,6,FREESHIP,Google,440.73 +ORD200146,2025-04-30,C84645,Tablet,2,411.49,404 Main St,Credit Card,Returned,TRK68893369,4,,Instagram,822.98 +ORD200147,2025-05-06,C46316,Laptop,2,465.18,893 Main St,Credit Card,Cancelled,TRK16196000,2,SAVE10,Google,930.36 +ORD200148,2024-12-15,C35100,Phone,2,319.91,139 Main St,Credit Card,Cancelled,TRK56853491,3,WINTER15,Google,639.82 +ORD200149,2023-12-27,C39671,Laptop,1,217.56,174 Main St,Debit Card,Delivered,TRK47153818,3,,Facebook,217.56 +ORD200150,2023-12-13,C25503,Phone,2,105.57,981 Main St,Debit Card,Returned,TRK29878837,5,WINTER15,Google,211.14 +ORD200151,2023-12-01,C32960,Printer,5,444.76,947 Main St,Debit Card,Returned,TRK91226500,7,,Email,2223.8 +ORD200152,2025-01-02,C77736,Chair,2,399.04,659 Main St,Cash,Cancelled,TRK90329250,3,FREESHIP,Referral,798.08 +ORD200153,2024-12-18,C71570,Chair,4,534.48,437 Main St,Online,Returned,TRK95992269,9,WINTER15,Instagram,2137.92 +ORD200154,2023-07-20,C73587,Phone,4,408.21,727 Main St,Credit Card,Pending,TRK13955543,9,,Instagram,1632.84 +ORD200155,2023-02-27,C62740,Phone,1,424.4,446 Main St,Online,Shipped,TRK20706408,6,WINTER15,Referral,424.4 +ORD200156,2024-11-08,C58808,Chair,2,269.83,651 Main St,Online,Delivered,TRK24451893,4,SAVE10,Email,539.66 +ORD200157,2025-02-21,C50422,Monitor,2,564.58,636 Main St,Online,Returned,TRK71227815,4,WINTER15,Facebook,1129.16 +ORD200158,2024-05-16,C23334,Tablet,1,331.06,737 Main St,Credit Card,Pending,TRK46335144,5,WINTER15,Instagram,331.06 +ORD200159,2023-10-31,C48965,Printer,1,299.35,819 Main St,Credit Card,Cancelled,TRK50921780,5,WINTER15,Email,299.35 +ORD200160,2023-02-17,C38669,Monitor,4,101.32,240 Main St,Cash,Pending,TRK81738254,7,,Referral,405.28 +ORD200161,2024-03-29,C35091,Monitor,1,211.14,513 Main St,Credit Card,Cancelled,TRK53784452,1,SAVE10,Facebook,211.14 +ORD200162,2023-07-27,C82313,Chair,3,65.86,917 Main St,Online,Pending,TRK79854624,8,WINTER15,Google,197.58 +ORD200163,2025-06-24,C99589,Tablet,1,641.39,277 Main St,Online,Cancelled,TRK16695001,1,,Referral,641.39 +ORD200164,2023-12-28,C70566,Desk,5,536.58,667 Main St,Gift Card,Pending,TRK49673411,5,SAVE10,Google,2682.9 +ORD200165,2024-09-14,C60355,Monitor,2,500.29,226 Main St,Online,Returned,TRK30155194,7,WINTER15,Google,1000.58 +ORD200166,2025-03-04,C28889,Chair,3,86.29,565 Main St,Cash,Delivered,TRK23791726,6,WINTER15,Instagram,258.87 +ORD200167,2023-05-27,C88304,Chair,2,384.14,219 Main St,Online,Returned,TRK44268941,2,WINTER15,Email,768.28 +ORD200168,2025-01-04,C49517,Printer,1,594.96,878 Main St,Cash,Returned,TRK78551375,6,,Facebook,594.96 +ORD200169,2024-04-07,C35785,Printer,1,427.82,732 Main St,Online,Delivered,TRK78923089,2,WINTER15,Email,427.82 +ORD200170,2025-04-04,C80223,Desk,4,662.94,535 Main St,Cash,Cancelled,TRK68632951,8,SAVE10,Instagram,2651.76 +ORD200171,2023-08-15,C20448,Tablet,2,148.22,336 Main St,Credit Card,Delivered,TRK67379895,7,WINTER15,Instagram,296.44 +ORD200172,2025-04-06,C34134,Printer,1,254.12,365 Main St,Online,Delivered,TRK43074303,1,WINTER15,Email,254.12 +ORD200173,2024-03-24,C95901,Phone,3,664.46,806 Main St,Online,Delivered,TRK56989066,4,FREESHIP,Google,1993.38 +ORD200174,2024-04-16,C51145,Printer,4,600.81,790 Main St,Debit Card,Delivered,TRK59154274,9,SAVE10,Email,2403.24 +ORD200175,2025-02-08,C78170,Chair,5,68.34,332 Main St,Debit Card,Pending,TRK71410605,6,WINTER15,Referral,341.7 +ORD200176,2025-06-28,C80151,Tablet,4,430.83,553 Main St,Gift Card,Pending,TRK88251529,8,WINTER15,Referral,1723.32 +ORD200177,2023-08-05,C55632,Chair,5,431.69,354 Main St,Credit Card,Pending,TRK13003066,10,,Facebook,2158.45 +ORD200178,2024-04-11,C53070,Chair,4,512.06,283 Main St,Online,Delivered,TRK49791755,5,SAVE10,Google,2048.24 +ORD200179,2024-11-24,C27401,Laptop,3,539.91,500 Main St,Credit Card,Delivered,TRK14332053,8,,Email,1619.73 +ORD200180,2023-03-18,C87216,Tablet,5,316.07,970 Main St,Cash,Returned,TRK18713727,10,,Google,1580.35 +ORD200181,2024-08-31,C38966,Printer,5,404.39,247 Main St,Online,Shipped,TRK17205146,10,,Referral,2021.95 +ORD200182,2025-03-19,C16612,Desk,1,600.54,596 Main St,Debit Card,Pending,TRK96188223,4,WINTER15,Google,600.54 +ORD200183,2024-04-18,C39246,Monitor,5,186.28,258 Main St,Debit Card,Delivered,TRK16658182,8,SAVE10,Email,931.4 +ORD200184,2024-04-04,C65180,Tablet,4,214.54,231 Main St,Gift Card,Cancelled,TRK39255469,7,,Referral,858.16 +ORD200185,2025-02-02,C46877,Laptop,1,210.7,572 Main St,Online,Shipped,TRK96935978,2,WINTER15,Referral,210.7 +ORD200186,2023-12-07,C30334,Phone,2,133.55,322 Main St,Cash,Pending,TRK66388885,7,FREESHIP,Facebook,267.1 +ORD200187,2023-02-08,C21227,Chair,1,590.87,689 Main St,Gift Card,Returned,TRK79129657,6,FREESHIP,Referral,590.87 +ORD200188,2025-03-15,C97715,Chair,2,363.91,927 Main St,Gift Card,Shipped,TRK19515949,2,FREESHIP,Referral,727.82 +ORD200189,2023-07-05,C48939,Printer,5,429.45,597 Main St,Gift Card,Cancelled,TRK62786764,5,WINTER15,Email,2147.25 +ORD200190,2024-08-31,C35483,Printer,3,223.7,725 Main St,Cash,Returned,TRK79638203,3,SAVE10,Email,671.1 +ORD200191,2025-03-08,C51494,Laptop,2,488.87,505 Main St,Online,Cancelled,TRK58520306,4,FREESHIP,Google,977.74 +ORD200192,2023-08-11,C58410,Desk,1,645.46,151 Main St,Gift Card,Cancelled,TRK19749672,5,SAVE10,Google,645.46 +ORD200193,2023-07-21,C11644,Printer,1,46.66,429 Main St,Cash,Cancelled,TRK81320339,6,,Google,46.66 +ORD200194,2024-06-08,C53501,Monitor,1,249.57,899 Main St,Cash,Shipped,TRK90144892,3,FREESHIP,Google,249.57 +ORD200195,2024-04-22,C63619,Chair,3,619.21,801 Main St,Debit Card,Cancelled,TRK65385674,6,,Email,1857.63 +ORD200196,2025-01-24,C40882,Desk,4,217.13,719 Main St,Cash,Delivered,TRK64165503,8,WINTER15,Email,868.52 +ORD200197,2023-08-27,C80135,Laptop,5,221.51,723 Main St,Cash,Returned,TRK95222269,5,WINTER15,Referral,1107.55 +ORD200198,2024-06-11,C37594,Laptop,4,340.3,926 Main St,Cash,Cancelled,TRK94405162,8,SAVE10,Referral,1361.2 +ORD200199,2025-01-23,C87524,Phone,1,625,358 Main St,Online,Returned,TRK21114341,5,WINTER15,Google,625 +ORD200200,2025-06-07,C97681,Tablet,5,433.26,895 Main St,Credit Card,Delivered,TRK37531040,9,SAVE10,Google,2166.3 +ORD200201,2023-06-18,C10126,Monitor,2,674.9,146 Main St,Online,Shipped,TRK75607531,4,SAVE10,Facebook,1349.8 +ORD200202,2025-02-06,C36938,Monitor,3,253.98,636 Main St,Credit Card,Cancelled,TRK52522904,3,FREESHIP,Email,761.94 +ORD200203,2025-01-21,C99173,Printer,3,356.84,172 Main St,Online,Shipped,TRK89849342,5,SAVE10,Instagram,1070.52 +ORD200204,2023-09-05,C99775,Laptop,4,413.71,478 Main St,Gift Card,Cancelled,TRK21638425,9,FREESHIP,Facebook,1654.84 +ORD200205,2023-03-04,C19266,Desk,3,147.39,609 Main St,Debit Card,Returned,TRK58357269,3,,Email,442.17 +ORD200206,2024-04-16,C31072,Laptop,4,229.1,729 Main St,Gift Card,Returned,TRK77172975,8,WINTER15,Email,916.4 +ORD200207,2025-03-18,C54595,Phone,1,121.96,999 Main St,Debit Card,Delivered,TRK44416659,3,,Google,121.96 +ORD200208,2024-10-08,C87777,Desk,2,408.32,597 Main St,Online,Shipped,TRK29003608,3,FREESHIP,Facebook,816.64 +ORD200209,2023-08-29,C35854,Tablet,5,187.97,706 Main St,Cash,Returned,TRK30615168,9,SAVE10,Google,939.85 +ORD200210,2024-12-05,C93821,Chair,3,358.48,513 Main St,Gift Card,Delivered,TRK10658539,7,FREESHIP,Facebook,1075.44 +ORD200211,2025-01-03,C54390,Printer,3,193.58,185 Main St,Gift Card,Pending,TRK83853742,7,FREESHIP,Email,580.74 +ORD200212,2023-06-20,C53215,Monitor,1,265.38,367 Main St,Credit Card,Cancelled,TRK34751835,6,WINTER15,Email,265.38 +ORD200213,2023-04-20,C71122,Laptop,1,634.4,317 Main St,Cash,Cancelled,TRK54757882,6,SAVE10,Email,634.4 +ORD200214,2024-08-21,C29483,Desk,4,305.72,673 Main St,Online,Delivered,TRK89423603,5,,Facebook,1222.88 +ORD200215,2023-08-10,C26767,Printer,1,303.6,432 Main St,Cash,Shipped,TRK24585307,5,FREESHIP,Facebook,303.6 +ORD200216,2025-04-15,C70492,Monitor,4,496,811 Main St,Online,Cancelled,TRK84625405,8,WINTER15,Google,1984 +ORD200217,2024-05-20,C61549,Desk,4,321.51,908 Main St,Cash,Returned,TRK65596914,9,,Google,1286.04 +ORD200218,2023-04-28,C11665,Tablet,3,112.46,882 Main St,Gift Card,Shipped,TRK10993930,6,SAVE10,Instagram,337.38 +ORD200219,2025-05-02,C48946,Laptop,5,61.97,457 Main St,Cash,Delivered,TRK99387220,6,SAVE10,Email,309.85 +ORD200220,2023-07-18,C79506,Laptop,2,373.17,497 Main St,Credit Card,Pending,TRK95188748,6,SAVE10,Referral,746.34 +ORD200221,2024-02-23,C93473,Tablet,5,639.37,552 Main St,Debit Card,Pending,TRK50003989,6,SAVE10,Google,3196.85 +ORD200222,2023-05-04,C43124,Chair,4,693.36,931 Main St,Online,Shipped,TRK17293348,8,,Instagram,2773.44 +ORD200223,2024-09-11,C22783,Phone,4,692.91,673 Main St,Credit Card,Pending,TRK55009149,9,SAVE10,Instagram,2771.64 +ORD200224,2023-09-23,C18567,Printer,4,91.46,507 Main St,Cash,Cancelled,TRK17554673,9,SAVE10,Referral,365.84 +ORD200225,2024-03-13,C99879,Phone,3,273.96,692 Main St,Debit Card,Returned,TRK50246700,8,SAVE10,Google,821.88 +ORD200226,2025-06-27,C31501,Desk,3,588.05,242 Main St,Gift Card,Delivered,TRK93063929,8,,Instagram,1764.15 +ORD200227,2023-11-02,C93220,Monitor,2,365.17,353 Main St,Online,Cancelled,TRK89023251,4,FREESHIP,Facebook,730.34 +ORD200228,2023-05-17,C57867,Chair,4,385.92,579 Main St,Credit Card,Cancelled,TRK92055007,8,,Instagram,1543.68 +ORD200229,2025-03-28,C62622,Tablet,1,562.61,762 Main St,Credit Card,Delivered,TRK70997648,3,WINTER15,Facebook,562.61 +ORD200230,2023-12-16,C94595,Desk,4,61.91,948 Main St,Gift Card,Delivered,TRK24497305,6,WINTER15,Email,247.64 +ORD200231,2023-11-05,C30955,Phone,4,41.9,327 Main St,Gift Card,Pending,TRK46898848,9,FREESHIP,Instagram,167.6 +ORD200232,2023-05-19,C20731,Printer,4,444.44,610 Main St,Debit Card,Cancelled,TRK75568437,8,WINTER15,Google,1777.76 +ORD200233,2024-08-24,C30168,Phone,3,311.33,146 Main St,Cash,Cancelled,TRK73699939,3,WINTER15,Instagram,933.99 +ORD200234,2024-11-26,C79842,Printer,4,236.41,337 Main St,Debit Card,Pending,TRK26957950,7,SAVE10,Google,945.64 +ORD200235,2023-02-20,C32854,Desk,1,65.45,815 Main St,Cash,Pending,TRK30009218,2,WINTER15,Google,65.45 +ORD200236,2023-01-01,C14847,Monitor,1,318.81,562 Main St,Debit Card,Pending,TRK39663243,3,WINTER15,Email,318.81 +ORD200237,2024-03-14,C88645,Monitor,3,583.72,783 Main St,Credit Card,Shipped,TRK74097570,5,FREESHIP,Facebook,1751.16 +ORD200238,2024-12-13,C66149,Desk,4,384.32,770 Main St,Credit Card,Pending,TRK76307307,6,WINTER15,Google,1537.28 +ORD200239,2024-12-11,C20256,Tablet,3,538.74,456 Main St,Online,Shipped,TRK71127943,6,FREESHIP,Email,1616.22 +ORD200240,2023-07-12,C14983,Tablet,1,17.24,255 Main St,Online,Pending,TRK93444157,2,FREESHIP,Instagram,17.24 +ORD200241,2023-05-16,C20817,Chair,5,615.67,407 Main St,Online,Pending,TRK44164590,6,SAVE10,Email,3078.35 +ORD200242,2023-05-09,C94921,Printer,2,219.1,134 Main St,Online,Pending,TRK97794327,4,SAVE10,Referral,438.2 +ORD200243,2025-05-09,C54725,Chair,2,144.66,506 Main St,Online,Cancelled,TRK30601940,7,FREESHIP,Google,289.32 +ORD200244,2023-02-16,C98096,Desk,2,317.77,838 Main St,Debit Card,Cancelled,TRK51518631,4,WINTER15,Facebook,635.54 +ORD200245,2025-04-20,C12667,Laptop,1,223.3,306 Main St,Online,Returned,TRK25390491,1,,Facebook,223.3 +ORD200246,2024-08-30,C55354,Desk,2,342.11,164 Main St,Gift Card,Shipped,TRK15439493,2,WINTER15,Instagram,684.22 +ORD200247,2023-07-20,C14600,Printer,2,220.9,785 Main St,Gift Card,Shipped,TRK84984764,4,,Email,441.8 +ORD200248,2023-07-02,C97187,Laptop,1,670.54,471 Main St,Cash,Shipped,TRK62283713,6,FREESHIP,Referral,670.54 +ORD200249,2024-02-07,C39106,Printer,1,546.19,245 Main St,Cash,Pending,TRK35464433,5,FREESHIP,Referral,546.19 +ORD200250,2023-04-05,C93379,Desk,3,42.95,318 Main St,Gift Card,Returned,TRK67954150,8,SAVE10,Email,128.85 +ORD200251,2025-05-15,C93175,Monitor,4,14.69,814 Main St,Cash,Cancelled,TRK32995144,9,,Email,58.76 +ORD200252,2024-09-20,C19648,Phone,4,668.36,821 Main St,Gift Card,Cancelled,TRK51297879,5,FREESHIP,Facebook,2673.44 +ORD200253,2024-03-23,C14891,Chair,4,413.74,743 Main St,Gift Card,Returned,TRK79471534,7,FREESHIP,Instagram,1654.96 +ORD200254,2023-12-26,C10866,Monitor,3,263.19,770 Main St,Online,Delivered,TRK34809583,5,,Instagram,789.57 +ORD200255,2024-05-13,C47283,Monitor,1,263.96,806 Main St,Gift Card,Returned,TRK56235117,2,SAVE10,Google,263.96 +ORD200256,2025-06-30,C94323,Chair,5,75.81,463 Main St,Gift Card,Returned,TRK22663277,10,WINTER15,Instagram,379.05 +ORD200257,2024-04-23,C89732,Phone,1,406.22,712 Main St,Credit Card,Cancelled,TRK41059233,5,SAVE10,Referral,406.22 +ORD200258,2024-02-26,C87764,Tablet,2,103.41,294 Main St,Online,Shipped,TRK94082469,2,FREESHIP,Referral,206.82 +ORD200259,2023-06-11,C20977,Chair,4,435.12,636 Main St,Credit Card,Delivered,TRK54991561,9,SAVE10,Instagram,1740.48 +ORD200260,2023-05-17,C12245,Monitor,2,407.79,153 Main St,Debit Card,Shipped,TRK22000463,3,,Google,815.58 +ORD200261,2025-05-28,C68976,Phone,5,173.65,460 Main St,Gift Card,Delivered,TRK25491356,9,SAVE10,Email,868.25 +ORD200262,2023-01-10,C69476,Phone,4,249.07,642 Main St,Credit Card,Returned,TRK65869386,5,WINTER15,Referral,996.28 +ORD200263,2023-03-25,C71040,Phone,4,434.85,250 Main St,Credit Card,Pending,TRK41397604,4,WINTER15,Google,1739.4 +ORD200264,2024-08-03,C71035,Tablet,1,436.77,977 Main St,Cash,Returned,TRK19599578,5,FREESHIP,Google,436.77 +ORD200265,2023-12-22,C20752,Printer,1,572.13,150 Main St,Debit Card,Cancelled,TRK22298450,4,SAVE10,Google,572.13 +ORD200266,2024-06-08,C38840,Chair,4,583.07,589 Main St,Credit Card,Cancelled,TRK48484633,6,FREESHIP,Referral,2332.28 +ORD200267,2025-04-17,C84480,Chair,5,468.51,803 Main St,Debit Card,Delivered,TRK62361867,9,,Facebook,2342.55 +ORD200268,2023-08-11,C37032,Phone,2,423.88,655 Main St,Debit Card,Delivered,TRK48639226,7,SAVE10,Referral,847.76 +ORD200269,2023-11-25,C48942,Tablet,4,663.67,129 Main St,Credit Card,Pending,TRK29355120,7,FREESHIP,Google,2654.68 +ORD200270,2023-06-04,C13540,Printer,4,309.91,127 Main St,Debit Card,Shipped,TRK81087373,5,WINTER15,Google,1239.64 +ORD200271,2023-03-28,C59572,Monitor,1,542.07,791 Main St,Cash,Shipped,TRK16792991,6,WINTER15,Referral,542.07 +ORD200272,2023-09-19,C29758,Chair,2,399.32,119 Main St,Online,Pending,TRK12990043,6,WINTER15,Instagram,798.64 +ORD200273,2024-10-27,C11849,Tablet,2,238.25,974 Main St,Online,Cancelled,TRK91195261,7,FREESHIP,Email,476.5 +ORD200274,2023-02-04,C50967,Phone,2,182.4,884 Main St,Gift Card,Cancelled,TRK65300814,5,SAVE10,Referral,364.8 +ORD200275,2023-11-04,C80735,Chair,2,65.07,360 Main St,Credit Card,Cancelled,TRK99880231,4,SAVE10,Google,130.14 +ORD200276,2025-03-29,C99050,Printer,2,600.57,654 Main St,Debit Card,Returned,TRK56927089,3,WINTER15,Instagram,1201.14 +ORD200277,2024-09-09,C11210,Chair,5,90.92,910 Main St,Credit Card,Delivered,TRK44929965,9,SAVE10,Facebook,454.6 +ORD200278,2024-11-18,C46015,Laptop,5,362.46,299 Main St,Cash,Delivered,TRK46598430,6,FREESHIP,Instagram,1812.3 +ORD200279,2023-10-20,C69167,Chair,3,55.01,263 Main St,Online,Pending,TRK12425655,7,WINTER15,Email,165.03 +ORD200280,2023-03-27,C55388,Tablet,3,404.62,740 Main St,Gift Card,Delivered,TRK75741001,6,FREESHIP,Instagram,1213.86 +ORD200281,2023-07-27,C87181,Desk,4,654.79,195 Main St,Cash,Pending,TRK60093390,9,,Referral,2619.16 +ORD200282,2025-04-22,C30411,Printer,4,637.79,375 Main St,Gift Card,Cancelled,TRK71810536,9,FREESHIP,Google,2551.16 +ORD200283,2025-02-28,C39638,Laptop,4,540.33,990 Main St,Cash,Shipped,TRK69745608,6,,Google,2161.32 +ORD200284,2023-02-16,C27203,Laptop,5,208.17,516 Main St,Credit Card,Returned,TRK22023906,6,SAVE10,Facebook,1040.85 +ORD200285,2025-06-10,C67583,Phone,1,338.31,974 Main St,Online,Delivered,TRK93281700,3,,Google,338.31 +ORD200286,2025-04-07,C70554,Monitor,3,139.45,187 Main St,Gift Card,Returned,TRK61086952,8,WINTER15,Google,418.35 +ORD200287,2023-11-24,C70437,Chair,4,655.18,630 Main St,Online,Shipped,TRK26628830,5,,Facebook,2620.72 +ORD200288,2023-03-12,C97643,Laptop,4,512.75,537 Main St,Debit Card,Returned,TRK60831391,8,WINTER15,Google,2051 +ORD200289,2023-07-26,C17136,Chair,4,160.49,333 Main St,Credit Card,Shipped,TRK55362541,8,WINTER15,Referral,641.96 +ORD200290,2023-05-05,C24901,Chair,3,99.9,258 Main St,Cash,Delivered,TRK14029489,8,FREESHIP,Facebook,299.7 +ORD200291,2024-05-12,C61521,Phone,2,345.01,670 Main St,Credit Card,Delivered,TRK93676567,6,FREESHIP,Google,690.02 +ORD200292,2025-01-15,C39639,Monitor,1,65.95,185 Main St,Credit Card,Delivered,TRK31042152,5,,Facebook,65.95 +ORD200293,2023-02-16,C33220,Tablet,4,463.04,564 Main St,Gift Card,Returned,TRK40450219,9,,Instagram,1852.16 +ORD200294,2025-04-01,C65414,Phone,2,297.71,208 Main St,Online,Shipped,TRK67562517,7,SAVE10,Referral,595.42 +ORD200295,2023-01-25,C49009,Printer,5,107.48,278 Main St,Debit Card,Cancelled,TRK46285799,9,FREESHIP,Email,537.4 +ORD200296,2024-06-19,C48453,Desk,5,638.8,434 Main St,Debit Card,Cancelled,TRK52110494,10,WINTER15,Referral,3194 +ORD200297,2023-02-22,C68078,Desk,2,493.88,252 Main St,Credit Card,Returned,TRK64862812,7,SAVE10,Instagram,987.76 +ORD200298,2023-12-19,C19402,Printer,4,301.17,267 Main St,Online,Cancelled,TRK97825212,6,,Email,1204.68 +ORD200299,2024-01-20,C30711,Monitor,1,278.66,856 Main St,Gift Card,Cancelled,TRK42696593,2,FREESHIP,Instagram,278.66 +ORD200300,2024-09-02,C39000,Phone,1,287.46,894 Main St,Debit Card,Returned,TRK33753945,3,FREESHIP,Facebook,287.46 +ORD200301,2023-05-11,C31105,Chair,1,583.99,726 Main St,Cash,Cancelled,TRK40149095,2,SAVE10,Email,583.99 +ORD200302,2023-05-16,C29432,Chair,3,468.74,121 Main St,Cash,Pending,TRK44142517,4,FREESHIP,Instagram,1406.22 +ORD200303,2024-12-07,C48531,Tablet,1,30.54,368 Main St,Debit Card,Returned,TRK95462192,1,,Google,30.54 +ORD200304,2024-10-18,C86762,Monitor,5,408.73,326 Main St,Gift Card,Delivered,TRK75686292,10,FREESHIP,Instagram,2043.65 +ORD200305,2023-11-25,C63822,Laptop,4,126.89,235 Main St,Cash,Pending,TRK59353216,9,FREESHIP,Instagram,507.56 +ORD200306,2024-06-07,C70495,Printer,2,57.07,238 Main St,Debit Card,Returned,TRK65511225,3,SAVE10,Instagram,114.14 +ORD200307,2023-07-01,C92407,Laptop,3,557.41,135 Main St,Online,Delivered,TRK11755610,4,,Email,1672.23 +ORD200308,2023-12-11,C75888,Printer,3,448.9,790 Main St,Debit Card,Returned,TRK98467398,7,SAVE10,Instagram,1346.7 +ORD200309,2023-10-03,C63153,Chair,4,549.76,625 Main St,Debit Card,Delivered,TRK38033305,4,FREESHIP,Facebook,2199.04 +ORD200310,2024-02-24,C85863,Printer,3,132.48,968 Main St,Online,Shipped,TRK16094218,4,,Referral,397.44 +ORD200311,2025-05-17,C71698,Desk,5,489.37,274 Main St,Online,Returned,TRK34786818,8,,Instagram,2446.85 +ORD200312,2025-05-24,C35397,Printer,5,66.31,579 Main St,Gift Card,Pending,TRK64742535,7,FREESHIP,Referral,331.55 +ORD200313,2023-07-09,C67687,Chair,2,434.3,978 Main St,Cash,Delivered,TRK22838735,7,SAVE10,Instagram,868.6 +ORD200314,2023-10-04,C29931,Desk,4,153.09,540 Main St,Online,Delivered,TRK48712417,4,FREESHIP,Referral,612.36 +ORD200315,2025-05-12,C59139,Tablet,5,91.67,301 Main St,Online,Cancelled,TRK45507090,9,FREESHIP,Email,458.35 +ORD200316,2023-10-02,C66078,Desk,4,275.28,101 Main St,Gift Card,Shipped,TRK86474559,9,WINTER15,Facebook,1101.12 +ORD200317,2023-04-10,C88370,Monitor,2,139.95,339 Main St,Online,Returned,TRK22575151,5,,Instagram,279.9 +ORD200318,2024-07-27,C93375,Chair,3,148.72,317 Main St,Debit Card,Cancelled,TRK95706967,7,SAVE10,Google,446.16 +ORD200319,2023-12-02,C53049,Laptop,2,563.06,413 Main St,Cash,Returned,TRK48974907,6,,Instagram,1126.12 +ORD200320,2024-12-19,C55590,Printer,1,625.51,772 Main St,Credit Card,Shipped,TRK48792951,1,FREESHIP,Facebook,625.51 +ORD200321,2023-08-09,C47086,Phone,4,152.29,135 Main St,Debit Card,Cancelled,TRK44194358,6,WINTER15,Google,609.16 +ORD200322,2024-06-14,C48646,Phone,5,231.82,339 Main St,Debit Card,Delivered,TRK18233748,6,SAVE10,Facebook,1159.1 +ORD200323,2025-01-26,C29416,Laptop,1,150.17,414 Main St,Debit Card,Returned,TRK63820842,1,SAVE10,Referral,150.17 +ORD200324,2024-06-13,C13525,Tablet,3,70.93,847 Main St,Debit Card,Returned,TRK70193221,5,,Referral,212.79 +ORD200325,2023-06-29,C53545,Desk,3,361.39,665 Main St,Credit Card,Shipped,TRK61123177,8,,Referral,1084.17 +ORD200326,2024-07-01,C65986,Laptop,5,670.48,273 Main St,Gift Card,Returned,TRK98353867,5,SAVE10,Facebook,3352.4 +ORD200327,2023-07-25,C17302,Phone,1,359.99,385 Main St,Gift Card,Cancelled,TRK43940016,5,SAVE10,Email,359.99 +ORD200328,2023-02-28,C18404,Tablet,5,674.04,546 Main St,Online,Cancelled,TRK89401624,7,SAVE10,Google,3370.2 +ORD200329,2024-12-25,C88371,Chair,4,283.16,306 Main St,Credit Card,Shipped,TRK63224811,6,,Google,1132.64 +ORD200330,2024-06-02,C38068,Desk,5,260.53,532 Main St,Gift Card,Pending,TRK54059198,5,SAVE10,Instagram,1302.65 +ORD200331,2023-04-15,C78724,Printer,3,422.13,187 Main St,Online,Delivered,TRK25703134,7,SAVE10,Facebook,1266.39 +ORD200332,2024-07-03,C26163,Desk,5,125.02,607 Main St,Debit Card,Pending,TRK67499316,9,SAVE10,Google,625.1 +ORD200333,2024-04-16,C87124,Phone,1,198.51,818 Main St,Credit Card,Returned,TRK52086740,5,WINTER15,Instagram,198.51 +ORD200334,2024-03-26,C90348,Chair,4,224.75,728 Main St,Online,Delivered,TRK20635777,7,WINTER15,Facebook,899 +ORD200335,2025-03-03,C58721,Tablet,3,205.86,978 Main St,Gift Card,Shipped,TRK34801199,4,,Email,617.58 +ORD200336,2023-12-29,C88174,Laptop,1,18.2,441 Main St,Debit Card,Pending,TRK10143345,4,SAVE10,Instagram,18.2 +ORD200337,2023-05-29,C77763,Tablet,3,502.77,599 Main St,Debit Card,Returned,TRK66980447,8,WINTER15,Email,1508.31 +ORD200338,2023-11-08,C53627,Phone,5,305.49,704 Main St,Debit Card,Shipped,TRK64112352,10,,Referral,1527.45 +ORD200339,2024-04-10,C84563,Printer,2,236.33,398 Main St,Online,Pending,TRK62422797,3,SAVE10,Instagram,472.66 +ORD200340,2023-04-23,C76207,Laptop,5,521.25,826 Main St,Cash,Cancelled,TRK25569378,8,,Email,2606.25 +ORD200341,2024-09-23,C94671,Tablet,1,167.15,293 Main St,Gift Card,Shipped,TRK61357272,5,WINTER15,Email,167.15 +ORD200342,2025-06-24,C69994,Monitor,5,466.42,619 Main St,Gift Card,Returned,TRK95935805,5,,Referral,2332.1 +ORD200343,2023-02-26,C64638,Printer,1,527.57,919 Main St,Debit Card,Pending,TRK64087938,3,FREESHIP,Facebook,527.57 +ORD200344,2025-03-06,C95623,Tablet,3,623.34,248 Main St,Online,Cancelled,TRK67558189,3,SAVE10,Instagram,1870.02 +ORD200345,2023-12-07,C24751,Tablet,5,501.26,259 Main St,Gift Card,Shipped,TRK37285406,10,FREESHIP,Referral,2506.3 +ORD200346,2024-12-06,C31764,Tablet,1,655.09,876 Main St,Cash,Pending,TRK44680433,6,,Referral,655.09 +ORD200347,2024-02-03,C83556,Printer,4,264.79,380 Main St,Credit Card,Pending,TRK21109187,5,SAVE10,Google,1059.16 +ORD200348,2024-03-13,C24369,Laptop,3,359.73,885 Main St,Debit Card,Returned,TRK72633998,7,FREESHIP,Email,1079.19 +ORD200349,2023-11-30,C39648,Chair,1,465.33,824 Main St,Gift Card,Delivered,TRK56016905,2,FREESHIP,Google,465.33 +ORD200350,2023-06-03,C13296,Chair,2,54.41,495 Main St,Online,Shipped,TRK60127216,6,,Instagram,108.82 +ORD200351,2025-02-15,C94248,Laptop,1,64.66,494 Main St,Debit Card,Delivered,TRK89406816,4,,Instagram,64.66 +ORD200352,2023-08-31,C26637,Chair,5,173.96,995 Main St,Debit Card,Pending,TRK59546992,8,WINTER15,Instagram,869.8 +ORD200353,2025-03-28,C16012,Tablet,1,630.82,171 Main St,Online,Delivered,TRK15195225,5,FREESHIP,Google,630.82 +ORD200354,2023-07-11,C31772,Phone,1,693.41,992 Main St,Debit Card,Shipped,TRK11970357,4,,Instagram,693.41 +ORD200355,2025-06-03,C18353,Tablet,3,433.33,677 Main St,Credit Card,Cancelled,TRK78766533,4,FREESHIP,Referral,1299.99 +ORD200356,2023-05-06,C26966,Printer,5,374.58,907 Main St,Gift Card,Cancelled,TRK83889574,10,FREESHIP,Instagram,1872.9 +ORD200357,2023-07-08,C74982,Laptop,5,408.56,398 Main St,Debit Card,Delivered,TRK98700702,8,FREESHIP,Instagram,2042.8 +ORD200358,2024-04-07,C70633,Tablet,2,183.67,747 Main St,Online,Cancelled,TRK82540521,3,SAVE10,Google,367.34 +ORD200359,2023-06-09,C95643,Desk,4,606.57,303 Main St,Debit Card,Delivered,TRK23286689,5,WINTER15,Referral,2426.28 +ORD200360,2024-06-06,C53810,Phone,4,589.57,779 Main St,Cash,Pending,TRK34630612,8,,Instagram,2358.28 +ORD200361,2024-06-29,C53464,Printer,5,659.85,197 Main St,Credit Card,Delivered,TRK32743531,9,SAVE10,Facebook,3299.25 +ORD200362,2023-06-27,C53697,Monitor,4,206.84,312 Main St,Cash,Cancelled,TRK60476656,5,WINTER15,Instagram,827.36 +ORD200363,2024-05-24,C31668,Laptop,5,113.87,871 Main St,Credit Card,Pending,TRK42584392,6,SAVE10,Email,569.35 +ORD200364,2023-11-24,C85282,Phone,5,628.74,740 Main St,Cash,Cancelled,TRK86767206,9,FREESHIP,Facebook,3143.7 +ORD200365,2025-02-14,C56796,Phone,1,678.38,607 Main St,Credit Card,Cancelled,TRK74263180,4,SAVE10,Referral,678.38 +ORD200366,2023-02-10,C95213,Printer,3,602.24,603 Main St,Debit Card,Pending,TRK40630538,8,,Referral,1806.72 +ORD200367,2024-04-25,C13108,Laptop,5,658.77,712 Main St,Gift Card,Pending,TRK82284400,10,FREESHIP,Instagram,3293.85 +ORD200368,2023-05-01,C85322,Monitor,3,271.02,403 Main St,Credit Card,Cancelled,TRK89728869,6,,Google,813.06 +ORD200369,2024-12-22,C43545,Monitor,5,375.25,216 Main St,Gift Card,Pending,TRK73937402,9,SAVE10,Email,1876.25 +ORD200370,2025-05-03,C80649,Phone,1,312.11,870 Main St,Online,Cancelled,TRK41143313,4,WINTER15,Facebook,312.11 +ORD200371,2023-01-05,C59752,Phone,5,307.76,179 Main St,Gift Card,Pending,TRK82229639,9,FREESHIP,Google,1538.8 +ORD200372,2025-02-14,C53645,Chair,3,483.53,166 Main St,Cash,Returned,TRK12123939,4,,Referral,1450.59 +ORD200373,2023-01-02,C60178,Laptop,3,341.15,969 Main St,Cash,Pending,TRK84505143,4,FREESHIP,Instagram,1023.45 +ORD200374,2024-09-16,C20286,Monitor,1,571.9,129 Main St,Gift Card,Pending,TRK67648338,1,WINTER15,Instagram,571.9 +ORD200375,2025-01-16,C87547,Monitor,4,95.03,400 Main St,Online,Shipped,TRK71027262,8,FREESHIP,Facebook,380.12 +ORD200376,2023-08-24,C64549,Monitor,5,201.22,341 Main St,Debit Card,Pending,TRK20788231,6,FREESHIP,Facebook,1006.1 +ORD200377,2024-07-22,C24884,Monitor,1,260.26,625 Main St,Online,Pending,TRK44538419,5,WINTER15,Instagram,260.26 +ORD200378,2024-02-01,C62666,Chair,5,64.5,148 Main St,Credit Card,Pending,TRK91029390,8,WINTER15,Instagram,322.5 +ORD200379,2024-09-21,C47284,Phone,3,297.67,500 Main St,Online,Shipped,TRK85756094,6,,Google,893.01 +ORD200380,2024-04-20,C35355,Printer,4,331.9,127 Main St,Cash,Pending,TRK52935059,5,SAVE10,Instagram,1327.6 +ORD200381,2023-06-07,C29467,Chair,1,191.76,223 Main St,Credit Card,Returned,TRK98103385,1,FREESHIP,Instagram,191.76 +ORD200382,2025-01-30,C26718,Printer,4,263.09,272 Main St,Debit Card,Shipped,TRK91702525,8,SAVE10,Google,1052.36 +ORD200383,2023-01-20,C18944,Chair,4,393.8,837 Main St,Credit Card,Pending,TRK45275439,7,SAVE10,Email,1575.2 +ORD200384,2024-11-24,C35628,Chair,3,553.57,147 Main St,Credit Card,Returned,TRK45688220,4,FREESHIP,Facebook,1660.71 +ORD200385,2023-10-31,C56851,Chair,5,191.63,752 Main St,Gift Card,Delivered,TRK65290904,6,FREESHIP,Facebook,958.15 +ORD200386,2023-04-28,C12421,Tablet,1,93.02,373 Main St,Online,Returned,TRK32588504,4,,Email,93.02 +ORD200387,2024-06-27,C25316,Printer,2,39.53,904 Main St,Credit Card,Shipped,TRK55423551,3,WINTER15,Google,79.06 +ORD200388,2023-12-28,C22657,Printer,3,633.97,152 Main St,Cash,Pending,TRK49157047,7,WINTER15,Facebook,1901.91 +ORD200389,2023-12-17,C29703,Desk,4,697.5,558 Main St,Cash,Shipped,TRK40543461,7,FREESHIP,Referral,2790 +ORD200390,2023-07-14,C55996,Printer,5,508.69,885 Main St,Cash,Delivered,TRK30547638,10,FREESHIP,Google,2543.45 +ORD200391,2025-01-16,C60037,Laptop,2,527.46,516 Main St,Debit Card,Cancelled,TRK82009557,3,FREESHIP,Referral,1054.92 +ORD200392,2024-02-28,C95100,Phone,1,627.2,197 Main St,Online,Delivered,TRK47366265,1,WINTER15,Email,627.2 +ORD200393,2024-07-14,C39906,Printer,1,75.01,921 Main St,Credit Card,Returned,TRK24632134,3,,Google,75.01 +ORD200394,2023-07-05,C70148,Desk,5,529.55,359 Main St,Gift Card,Shipped,TRK34848650,10,,Facebook,2647.75 +ORD200395,2025-04-25,C30010,Phone,3,127.41,830 Main St,Gift Card,Delivered,TRK35386084,7,SAVE10,Referral,382.23 +ORD200396,2023-12-01,C99217,Tablet,5,287.13,778 Main St,Online,Shipped,TRK82004594,10,SAVE10,Email,1435.65 +ORD200397,2023-09-28,C30184,Monitor,1,427.06,987 Main St,Online,Cancelled,TRK86674704,1,WINTER15,Referral,427.06 +ORD200398,2024-09-04,C50275,Phone,5,53.93,729 Main St,Gift Card,Shipped,TRK98925264,7,SAVE10,Instagram,269.65 +ORD200399,2024-01-07,C64641,Tablet,5,423.93,319 Main St,Debit Card,Returned,TRK32012588,5,FREESHIP,Facebook,2119.65 +ORD200400,2024-09-28,C56266,Desk,4,160.22,304 Main St,Debit Card,Returned,TRK60088901,9,WINTER15,Instagram,640.88 +ORD200401,2025-04-09,C98635,Printer,1,538.68,197 Main St,Debit Card,Returned,TRK14225465,6,,Referral,538.68 +ORD200402,2023-04-09,C83026,Printer,5,337.38,858 Main St,Gift Card,Shipped,TRK79746259,5,,Referral,1686.9 +ORD200403,2024-11-10,C28893,Tablet,1,620.21,740 Main St,Online,Returned,TRK98333066,1,FREESHIP,Referral,620.21 +ORD200404,2023-03-09,C45482,Monitor,2,99.1,440 Main St,Cash,Delivered,TRK54571699,6,,Instagram,198.2 +ORD200405,2025-01-26,C97774,Monitor,4,451.97,603 Main St,Online,Cancelled,TRK64664424,7,WINTER15,Email,1807.88 +ORD200406,2023-12-10,C11657,Tablet,4,66.1,572 Main St,Cash,Returned,TRK50284486,9,WINTER15,Google,264.4 +ORD200407,2023-08-13,C85993,Tablet,4,547.32,250 Main St,Cash,Returned,TRK72547640,8,FREESHIP,Instagram,2189.28 +ORD200408,2025-01-01,C11906,Printer,3,412.53,536 Main St,Online,Pending,TRK31140158,6,WINTER15,Google,1237.59 +ORD200409,2023-06-28,C45187,Desk,5,84.13,767 Main St,Online,Delivered,TRK12320793,9,SAVE10,Google,420.65 +ORD200410,2024-01-18,C37375,Tablet,2,518.23,184 Main St,Debit Card,Shipped,TRK52470162,5,,Email,1036.46 +ORD200411,2024-06-19,C66567,Desk,2,39.51,981 Main St,Online,Shipped,TRK21174822,5,,Facebook,79.02 +ORD200412,2025-04-11,C42451,Tablet,5,133.01,246 Main St,Credit Card,Returned,TRK31313343,10,,Facebook,665.05 +ORD200413,2023-10-08,C13923,Tablet,1,118.8,123 Main St,Online,Delivered,TRK87598790,6,SAVE10,Email,118.8 +ORD200414,2025-05-04,C11829,Desk,2,139.57,797 Main St,Cash,Delivered,TRK84229257,4,WINTER15,Facebook,279.14 +ORD200415,2025-04-06,C62169,Chair,1,184.15,655 Main St,Gift Card,Shipped,TRK64558985,5,FREESHIP,Facebook,184.15 +ORD200416,2023-07-18,C20881,Laptop,2,644.05,652 Main St,Gift Card,Cancelled,TRK26263902,5,WINTER15,Referral,1288.1 +ORD200417,2023-10-24,C44492,Laptop,5,55.41,954 Main St,Online,Cancelled,TRK51429869,5,,Google,277.05 +ORD200418,2023-01-11,C74169,Printer,1,310.93,862 Main St,Online,Cancelled,TRK66144809,3,,Facebook,310.93 +ORD200419,2024-04-17,C70999,Tablet,2,216.66,885 Main St,Debit Card,Pending,TRK75644156,6,FREESHIP,Instagram,433.32 +ORD200420,2024-11-29,C11921,Phone,1,452.7,439 Main St,Debit Card,Shipped,TRK91362635,5,FREESHIP,Instagram,452.7 +ORD200421,2023-10-15,C50683,Chair,2,288.21,769 Main St,Debit Card,Cancelled,TRK53032122,5,,Email,576.42 +ORD200422,2023-06-05,C76140,Phone,4,206.6,914 Main St,Gift Card,Returned,TRK25861469,6,WINTER15,Referral,826.4 +ORD200423,2024-07-20,C94311,Printer,4,685.2,195 Main St,Gift Card,Cancelled,TRK97308771,6,WINTER15,Google,2740.8 +ORD200424,2023-04-12,C49491,Chair,5,22.94,339 Main St,Cash,Pending,TRK64012257,10,,Email,114.7 +ORD200425,2023-03-09,C40648,Laptop,2,301.88,488 Main St,Gift Card,Returned,TRK25325993,5,WINTER15,Email,603.76 +ORD200426,2025-03-16,C40967,Monitor,5,57.45,315 Main St,Cash,Cancelled,TRK24839296,10,,Facebook,287.25 +ORD200427,2024-12-18,C25406,Desk,1,161.24,379 Main St,Credit Card,Pending,TRK70952564,3,WINTER15,Instagram,161.24 +ORD200428,2024-11-26,C77085,Chair,4,262.58,895 Main St,Online,Cancelled,TRK57227640,8,WINTER15,Email,1050.32 +ORD200429,2024-12-19,C38126,Printer,4,515.19,522 Main St,Credit Card,Pending,TRK90838498,9,SAVE10,Facebook,2060.76 +ORD200430,2023-06-07,C87448,Phone,1,450.07,433 Main St,Gift Card,Shipped,TRK44134016,6,FREESHIP,Google,450.07 +ORD200431,2024-10-06,C62312,Printer,1,52.54,651 Main St,Debit Card,Cancelled,TRK59623037,6,WINTER15,Facebook,52.54 +ORD200432,2023-09-04,C58443,Tablet,2,424.32,662 Main St,Credit Card,Returned,TRK77163738,6,,Referral,848.64 +ORD200433,2023-08-26,C36613,Monitor,3,631.64,785 Main St,Credit Card,Returned,TRK13282106,3,FREESHIP,Facebook,1894.92 +ORD200434,2023-10-22,C73893,Printer,5,327.68,384 Main St,Credit Card,Returned,TRK85939879,6,,Facebook,1638.4 +ORD200435,2023-05-27,C48601,Printer,1,414.47,101 Main St,Debit Card,Returned,TRK97868309,3,FREESHIP,Instagram,414.47 +ORD200436,2023-02-11,C14568,Laptop,4,221.33,651 Main St,Online,Pending,TRK73545796,5,,Google,885.32 +ORD200437,2024-04-18,C63378,Phone,1,512.39,955 Main St,Online,Delivered,TRK20863705,2,FREESHIP,Instagram,512.39 +ORD200438,2025-01-03,C77800,Tablet,3,459.34,436 Main St,Gift Card,Pending,TRK27439574,3,SAVE10,Instagram,1378.02 +ORD200439,2024-09-08,C91155,Tablet,1,146.32,321 Main St,Online,Shipped,TRK36260319,4,WINTER15,Facebook,146.32 +ORD200440,2024-11-05,C60215,Desk,4,83.6,978 Main St,Debit Card,Pending,TRK31727767,4,SAVE10,Facebook,334.4 +ORD200441,2023-12-13,C52915,Printer,2,328.54,475 Main St,Gift Card,Returned,TRK79466982,6,FREESHIP,Email,657.08 +ORD200442,2024-05-06,C72588,Chair,5,314.94,661 Main St,Cash,Pending,TRK43410829,8,SAVE10,Instagram,1574.7 +ORD200443,2024-05-14,C61668,Chair,2,69.64,813 Main St,Cash,Returned,TRK58970302,6,,Facebook,139.28 +ORD200444,2024-06-08,C79508,Printer,1,135.17,585 Main St,Online,Shipped,TRK61882353,6,FREESHIP,Instagram,135.17 +ORD200445,2024-03-23,C94569,Phone,1,487.21,227 Main St,Cash,Delivered,TRK31351770,3,SAVE10,Referral,487.21 +ORD200446,2023-10-18,C89592,Laptop,5,509.58,262 Main St,Online,Delivered,TRK49442402,6,FREESHIP,Instagram,2547.9 +ORD200447,2024-04-07,C48207,Printer,2,416.81,356 Main St,Cash,Returned,TRK45355655,2,,Facebook,833.62 +ORD200448,2023-09-04,C16776,Laptop,2,160,854 Main St,Cash,Pending,TRK12860600,4,SAVE10,Instagram,320 +ORD200449,2024-08-26,C91518,Tablet,3,253.05,286 Main St,Online,Pending,TRK48688724,3,,Instagram,759.15 +ORD200450,2024-01-15,C36408,Monitor,5,615.1,160 Main St,Gift Card,Returned,TRK94023253,10,WINTER15,Instagram,3075.5 +ORD200451,2023-04-01,C14837,Monitor,1,183.18,647 Main St,Debit Card,Cancelled,TRK17501136,6,SAVE10,Email,183.18 +ORD200452,2023-07-23,C36467,Printer,1,75.78,581 Main St,Cash,Pending,TRK20863987,5,SAVE10,Google,75.78 +ORD200453,2025-05-02,C15017,Tablet,1,675.57,492 Main St,Cash,Shipped,TRK51241924,1,WINTER15,Facebook,675.57 +ORD200454,2024-11-27,C54759,Laptop,1,109.29,686 Main St,Debit Card,Cancelled,TRK75583042,5,FREESHIP,Google,109.29 +ORD200455,2024-03-26,C58341,Phone,1,639.83,874 Main St,Debit Card,Pending,TRK32856728,2,SAVE10,Referral,639.83 +ORD200456,2023-06-26,C94479,Desk,5,62.81,259 Main St,Credit Card,Shipped,TRK69089975,9,SAVE10,Facebook,314.05 +ORD200457,2025-05-25,C50236,Desk,4,615.83,545 Main St,Online,Returned,TRK67692578,4,WINTER15,Instagram,2463.32 +ORD200458,2024-07-02,C31412,Monitor,4,510.58,196 Main St,Credit Card,Returned,TRK61946127,7,WINTER15,Email,2042.32 +ORD200459,2024-07-24,C90142,Desk,1,334.39,433 Main St,Credit Card,Returned,TRK39717191,2,,Instagram,334.39 +ORD200460,2024-10-06,C83548,Laptop,1,144.25,474 Main St,Cash,Returned,TRK93822942,2,WINTER15,Referral,144.25 +ORD200461,2024-06-08,C29697,Tablet,1,401.82,407 Main St,Credit Card,Shipped,TRK47776482,5,FREESHIP,Google,401.82 +ORD200462,2025-03-31,C22991,Phone,1,252.68,731 Main St,Online,Cancelled,TRK32796086,1,,Referral,252.68 +ORD200463,2023-05-26,C25276,Laptop,5,662.78,214 Main St,Debit Card,Shipped,TRK14011732,9,SAVE10,Instagram,3313.9 +ORD200464,2023-03-14,C39176,Tablet,4,434.42,739 Main St,Online,Cancelled,TRK71418686,6,FREESHIP,Google,1737.68 +ORD200465,2024-02-26,C58773,Printer,5,513.49,391 Main St,Gift Card,Cancelled,TRK65438300,8,,Google,2567.45 +ORD200466,2023-07-18,C37412,Phone,1,432.47,895 Main St,Cash,Delivered,TRK97829604,4,FREESHIP,Referral,432.47 +ORD200467,2024-08-30,C36492,Desk,1,45.94,572 Main St,Cash,Cancelled,TRK44350440,2,WINTER15,Email,45.94 +ORD200468,2025-06-21,C90110,Phone,1,418.36,998 Main St,Credit Card,Delivered,TRK60203957,5,FREESHIP,Email,418.36 +ORD200469,2023-11-26,C13877,Chair,5,676.98,893 Main St,Cash,Cancelled,TRK17254691,5,,Facebook,3384.9 +ORD200470,2023-09-29,C25149,Tablet,4,263.62,672 Main St,Cash,Shipped,TRK33538608,5,SAVE10,Email,1054.48 +ORD200471,2025-04-19,C52717,Desk,5,551.27,395 Main St,Online,Cancelled,TRK27625571,7,FREESHIP,Referral,2756.35 +ORD200472,2023-01-06,C60029,Chair,3,508.12,796 Main St,Credit Card,Cancelled,TRK86461316,8,FREESHIP,Referral,1524.36 +ORD200473,2025-02-25,C28552,Chair,2,14.93,449 Main St,Online,Shipped,TRK71597160,4,,Facebook,29.86 +ORD200474,2023-11-15,C72293,Printer,3,229.34,398 Main St,Credit Card,Shipped,TRK84378003,6,SAVE10,Referral,688.02 +ORD200475,2025-04-19,C29844,Tablet,2,438.62,363 Main St,Cash,Cancelled,TRK91642337,3,SAVE10,Facebook,877.24 +ORD200476,2024-01-15,C77872,Phone,2,513.59,867 Main St,Online,Returned,TRK19292184,4,FREESHIP,Referral,1027.18 +ORD200477,2025-03-05,C56564,Phone,2,253.74,481 Main St,Online,Shipped,TRK13166044,5,SAVE10,Google,507.48 +ORD200478,2024-11-01,C16758,Tablet,3,62.77,914 Main St,Gift Card,Shipped,TRK88544431,6,FREESHIP,Referral,188.31 +ORD200479,2023-02-18,C87011,Monitor,4,25.29,943 Main St,Credit Card,Pending,TRK21429162,8,,Google,101.16 +ORD200480,2023-06-16,C21147,Chair,1,335.1,126 Main St,Debit Card,Pending,TRK93171043,6,FREESHIP,Referral,335.1 +ORD200481,2023-04-23,C94568,Laptop,4,484.85,317 Main St,Debit Card,Delivered,TRK58653915,5,WINTER15,Referral,1939.4 +ORD200482,2025-03-02,C35852,Monitor,3,381.41,989 Main St,Online,Pending,TRK22302049,6,,Instagram,1144.23 +ORD200483,2023-01-18,C66462,Phone,5,347.92,982 Main St,Cash,Pending,TRK52743700,6,WINTER15,Google,1739.6 +ORD200484,2024-05-29,C29092,Chair,4,15.01,767 Main St,Cash,Cancelled,TRK90455340,6,,Facebook,60.04 +ORD200485,2023-08-01,C46651,Chair,3,404.79,764 Main St,Cash,Shipped,TRK67679195,6,SAVE10,Instagram,1214.37 +ORD200486,2023-02-03,C88981,Printer,4,611.26,558 Main St,Cash,Shipped,TRK75267873,5,SAVE10,Referral,2445.04 +ORD200487,2023-03-09,C40136,Printer,3,346.52,211 Main St,Credit Card,Pending,TRK92924852,3,SAVE10,Google,1039.56 +ORD200488,2024-12-05,C81573,Chair,1,36.65,556 Main St,Online,Cancelled,TRK96522994,1,WINTER15,Email,36.65 +ORD200489,2023-09-05,C11940,Tablet,3,149.34,589 Main St,Gift Card,Cancelled,TRK85466461,7,WINTER15,Email,448.02 +ORD200490,2024-07-22,C50097,Chair,5,467.81,539 Main St,Online,Cancelled,TRK62785150,10,,Facebook,2339.05 +ORD200491,2023-01-05,C98168,Phone,5,420.7,481 Main St,Cash,Pending,TRK56423359,5,WINTER15,Facebook,2103.5 +ORD200492,2023-10-25,C39074,Laptop,5,606.52,103 Main St,Debit Card,Shipped,TRK13027036,6,SAVE10,Instagram,3032.6 +ORD200493,2025-01-28,C84908,Phone,1,420.26,372 Main St,Credit Card,Pending,TRK64135970,4,FREESHIP,Facebook,420.26 +ORD200494,2023-07-19,C64516,Laptop,3,505.79,459 Main St,Debit Card,Pending,TRK63920573,3,FREESHIP,Referral,1517.37 +ORD200495,2025-06-05,C63827,Phone,4,493.73,947 Main St,Debit Card,Pending,TRK35730581,6,SAVE10,Facebook,1974.92 +ORD200496,2025-03-14,C93618,Printer,3,201.21,249 Main St,Online,Cancelled,TRK66129326,3,SAVE10,Google,603.63 +ORD200497,2024-10-24,C93948,Printer,3,112.29,454 Main St,Gift Card,Shipped,TRK77358113,6,,Google,336.87 +ORD200498,2023-07-12,C73961,Tablet,4,132.56,306 Main St,Cash,Returned,TRK32607173,8,WINTER15,Instagram,530.24 +ORD200499,2023-04-06,C18138,Printer,3,539.46,520 Main St,Credit Card,Shipped,TRK20289483,4,SAVE10,Facebook,1618.38 +ORD200500,2024-04-07,C79475,Laptop,5,508.59,169 Main St,Cash,Returned,TRK42168516,8,WINTER15,Facebook,2542.95 +ORD200501,2024-02-04,C88546,Desk,4,203.46,226 Main St,Credit Card,Pending,TRK19867754,7,SAVE10,Referral,813.84 +ORD200502,2023-05-20,C69332,Monitor,3,565.25,745 Main St,Debit Card,Returned,TRK65718848,7,SAVE10,Email,1695.75 +ORD200503,2023-08-31,C64554,Tablet,3,136.84,498 Main St,Online,Pending,TRK95384568,4,FREESHIP,Facebook,410.52 +ORD200504,2025-06-11,C11676,Monitor,2,464.5,805 Main St,Online,Cancelled,TRK35726395,2,WINTER15,Instagram,929 +ORD200505,2023-06-11,C36014,Printer,2,434.97,558 Main St,Online,Shipped,TRK97246526,7,,Email,869.94 +ORD200506,2023-07-25,C23279,Monitor,2,43.67,696 Main St,Cash,Returned,TRK58039693,4,WINTER15,Instagram,87.34 +ORD200507,2023-07-05,C86481,Phone,1,171.59,546 Main St,Credit Card,Pending,TRK87513944,5,WINTER15,Email,171.59 +ORD200508,2025-05-14,C39550,Phone,1,558.27,976 Main St,Online,Delivered,TRK24120267,1,,Referral,558.27 +ORD200509,2023-02-15,C68937,Laptop,2,425.03,560 Main St,Cash,Returned,TRK31908657,2,WINTER15,Google,850.06 +ORD200510,2024-12-16,C72533,Printer,1,376.76,389 Main St,Debit Card,Delivered,TRK51288986,5,SAVE10,Email,376.76 +ORD200511,2024-03-15,C11415,Monitor,5,575.24,267 Main St,Cash,Delivered,TRK65061457,7,WINTER15,Email,2876.2 +ORD200512,2024-09-27,C14114,Desk,3,568.02,856 Main St,Online,Pending,TRK63290700,3,FREESHIP,Instagram,1704.06 +ORD200513,2025-02-09,C64128,Tablet,3,94.88,533 Main St,Gift Card,Shipped,TRK37053575,8,,Referral,284.64 +ORD200514,2023-04-16,C15629,Printer,3,304.15,492 Main St,Gift Card,Shipped,TRK64926044,3,WINTER15,Instagram,912.45 +ORD200515,2023-03-14,C67561,Phone,3,553.52,160 Main St,Gift Card,Shipped,TRK75900717,4,FREESHIP,Facebook,1660.56 +ORD200516,2024-04-07,C47022,Monitor,3,166.99,208 Main St,Cash,Returned,TRK28855040,8,,Facebook,500.97 +ORD200517,2024-04-09,C55205,Tablet,4,198.35,943 Main St,Cash,Cancelled,TRK88141634,7,FREESHIP,Google,793.4 +ORD200518,2025-06-13,C30686,Printer,4,403.58,319 Main St,Online,Pending,TRK59807273,9,SAVE10,Referral,1614.32 +ORD200519,2025-05-10,C71797,Laptop,4,464.29,941 Main St,Debit Card,Returned,TRK66010667,5,SAVE10,Email,1857.16 +ORD200520,2023-03-10,C66332,Monitor,3,635.98,959 Main St,Cash,Returned,TRK27063398,5,,Referral,1907.94 +ORD200521,2024-02-25,C82318,Phone,1,528.06,991 Main St,Credit Card,Shipped,TRK37534165,2,,Facebook,528.06 +ORD200522,2024-04-20,C66254,Chair,1,515.32,740 Main St,Gift Card,Cancelled,TRK82843861,1,FREESHIP,Email,515.32 +ORD200523,2025-02-18,C65083,Desk,4,657.79,652 Main St,Credit Card,Returned,TRK60937148,6,WINTER15,Google,2631.16 +ORD200524,2023-10-25,C44778,Phone,1,153,103 Main St,Credit Card,Returned,TRK92617366,4,,Referral,153 +ORD200525,2023-12-03,C54499,Monitor,1,668.48,160 Main St,Debit Card,Shipped,TRK18061555,1,SAVE10,Email,668.48 +ORD200526,2024-02-29,C91201,Desk,2,46.5,837 Main St,Cash,Returned,TRK63526023,7,WINTER15,Google,93 +ORD200527,2024-08-19,C27202,Chair,5,653.47,967 Main St,Credit Card,Cancelled,TRK75406128,10,SAVE10,Referral,3267.35 +ORD200528,2025-02-26,C32011,Chair,1,628.89,686 Main St,Credit Card,Returned,TRK70997744,2,SAVE10,Referral,628.89 +ORD200529,2024-04-07,C21181,Tablet,2,675.1,938 Main St,Cash,Pending,TRK50363421,4,FREESHIP,Google,1350.2 +ORD200530,2024-07-18,C98450,Chair,4,89.41,613 Main St,Online,Pending,TRK14809530,9,,Google,357.64 +ORD200531,2024-07-02,C64502,Desk,5,320.01,722 Main St,Gift Card,Delivered,TRK14914388,6,,Referral,1600.05 +ORD200532,2025-05-03,C47365,Laptop,2,41,369 Main St,Online,Delivered,TRK42207882,7,,Email,82 +ORD200533,2023-03-05,C66349,Desk,1,565.85,715 Main St,Gift Card,Returned,TRK63550793,1,FREESHIP,Facebook,565.85 +ORD200534,2024-06-06,C73289,Chair,3,648.59,906 Main St,Debit Card,Cancelled,TRK70872738,4,SAVE10,Email,1945.77 +ORD200535,2024-07-24,C48649,Monitor,3,68.12,332 Main St,Online,Cancelled,TRK45821445,3,FREESHIP,Email,204.36 +ORD200536,2024-06-09,C18724,Chair,1,616.1,124 Main St,Cash,Returned,TRK52508861,6,,Email,616.1 +ORD200537,2025-03-23,C68553,Tablet,3,247.47,385 Main St,Online,Delivered,TRK58218971,4,SAVE10,Facebook,742.41 +ORD200538,2024-05-24,C61280,Phone,3,490.74,100 Main St,Cash,Shipped,TRK95487711,3,WINTER15,Email,1472.22 +ORD200539,2025-02-18,C53277,Desk,3,531.72,473 Main St,Gift Card,Delivered,TRK17653832,7,SAVE10,Google,1595.16 +ORD200540,2024-01-29,C87281,Laptop,5,648.65,852 Main St,Online,Pending,TRK81765057,7,,Referral,3243.25 +ORD200541,2023-08-07,C69009,Printer,5,456.06,879 Main St,Cash,Pending,TRK61295842,10,,Instagram,2280.3 +ORD200542,2023-11-14,C49726,Tablet,1,17.98,934 Main St,Cash,Cancelled,TRK20739460,6,FREESHIP,Email,17.98 +ORD200543,2024-03-09,C37531,Desk,5,269.86,354 Main St,Cash,Shipped,TRK93877673,6,WINTER15,Facebook,1349.3 +ORD200544,2024-03-10,C48713,Printer,5,31.96,373 Main St,Credit Card,Returned,TRK96334419,5,FREESHIP,Referral,159.8 +ORD200545,2023-12-19,C74138,Monitor,2,98.47,964 Main St,Cash,Returned,TRK74091695,3,,Instagram,196.94 +ORD200546,2024-03-01,C82399,Monitor,1,158.68,928 Main St,Credit Card,Returned,TRK77177284,6,WINTER15,Instagram,158.68 +ORD200547,2023-08-20,C40427,Phone,1,613.98,411 Main St,Online,Delivered,TRK25392280,4,FREESHIP,Facebook,613.98 +ORD200548,2024-01-05,C17103,Printer,3,426.12,922 Main St,Online,Delivered,TRK64398650,5,WINTER15,Instagram,1278.36 +ORD200549,2025-02-25,C34266,Monitor,4,629.88,550 Main St,Debit Card,Cancelled,TRK56378197,8,WINTER15,Instagram,2519.52 +ORD200550,2023-10-29,C97485,Laptop,4,228.91,573 Main St,Cash,Shipped,TRK81794737,4,FREESHIP,Google,915.64 +ORD200551,2023-05-18,C23947,Laptop,1,120.98,353 Main St,Debit Card,Delivered,TRK74812710,6,WINTER15,Email,120.98 +ORD200552,2023-09-30,C21665,Chair,4,425.18,560 Main St,Online,Returned,TRK29890761,8,WINTER15,Facebook,1700.72 +ORD200553,2023-08-23,C82550,Phone,2,333.83,828 Main St,Gift Card,Cancelled,TRK74103758,4,FREESHIP,Referral,667.66 +ORD200554,2025-05-30,C61943,Laptop,2,492.9,610 Main St,Cash,Returned,TRK66126496,5,FREESHIP,Instagram,985.8 +ORD200555,2023-01-07,C88933,Tablet,1,92.04,333 Main St,Cash,Shipped,TRK89306964,2,,Facebook,92.04 +ORD200556,2023-01-28,C30923,Laptop,1,654.27,932 Main St,Gift Card,Pending,TRK82609328,2,SAVE10,Facebook,654.27 +ORD200557,2023-06-29,C56969,Tablet,1,56.2,130 Main St,Debit Card,Pending,TRK40719215,1,WINTER15,Facebook,56.2 +ORD200558,2024-07-16,C76766,Phone,4,628.12,485 Main St,Online,Delivered,TRK32052962,6,WINTER15,Instagram,2512.48 +ORD200559,2024-04-15,C22981,Desk,3,157.4,454 Main St,Debit Card,Cancelled,TRK10115285,7,WINTER15,Email,472.2 +ORD200560,2023-01-31,C33634,Monitor,4,588.85,524 Main St,Gift Card,Pending,TRK93168008,7,,Email,2355.4 +ORD200561,2023-01-31,C96822,Printer,2,494.78,198 Main St,Online,Shipped,TRK89180077,2,,Google,989.56 +ORD200562,2023-10-06,C76675,Laptop,3,663.93,922 Main St,Gift Card,Returned,TRK28043915,6,FREESHIP,Email,1991.79 +ORD200563,2023-12-12,C12039,Laptop,1,132.68,844 Main St,Debit Card,Returned,TRK68645763,1,SAVE10,Referral,132.68 +ORD200564,2025-04-08,C93309,Desk,5,364.28,734 Main St,Credit Card,Cancelled,TRK99446987,5,WINTER15,Google,1821.4 +ORD200565,2023-05-14,C62042,Tablet,5,307.98,214 Main St,Online,Pending,TRK42605492,10,,Facebook,1539.9 +ORD200566,2024-04-18,C83223,Phone,4,162.71,167 Main St,Cash,Cancelled,TRK54339083,7,FREESHIP,Email,650.84 +ORD200567,2024-09-30,C92575,Chair,5,492.94,153 Main St,Cash,Shipped,TRK53579227,10,FREESHIP,Email,2464.7 +ORD200568,2023-03-10,C29072,Laptop,2,343.99,312 Main St,Online,Delivered,TRK72334047,4,,Google,687.98 +ORD200569,2025-03-22,C25783,Desk,5,250.68,672 Main St,Cash,Shipped,TRK13289741,8,SAVE10,Instagram,1253.4 +ORD200570,2024-12-27,C63727,Desk,2,362.14,122 Main St,Debit Card,Pending,TRK13611021,2,SAVE10,Instagram,724.28 +ORD200571,2024-11-23,C42365,Tablet,1,214.08,867 Main St,Gift Card,Returned,TRK39563288,2,WINTER15,Google,214.08 +ORD200572,2023-11-11,C27438,Printer,1,70.32,341 Main St,Cash,Returned,TRK69125497,4,WINTER15,Facebook,70.32 +ORD200573,2023-01-25,C13205,Chair,5,421.42,522 Main St,Debit Card,Cancelled,TRK30686578,7,,Instagram,2107.1 +ORD200574,2024-01-24,C29685,Chair,5,384.69,275 Main St,Credit Card,Pending,TRK97733212,6,FREESHIP,Email,1923.45 +ORD200575,2023-06-07,C74005,Chair,5,448.15,528 Main St,Gift Card,Returned,TRK61640534,7,SAVE10,Google,2240.75 +ORD200576,2024-05-29,C14457,Laptop,5,79.08,747 Main St,Cash,Pending,TRK42517811,8,,Facebook,395.4 +ORD200577,2023-01-22,C77046,Tablet,4,185.41,967 Main St,Online,Returned,TRK44401497,9,WINTER15,Google,741.64 +ORD200578,2024-10-10,C50415,Monitor,5,566.07,587 Main St,Credit Card,Delivered,TRK41345634,6,SAVE10,Instagram,2830.35 +ORD200579,2023-06-04,C73999,Tablet,2,187.88,413 Main St,Online,Shipped,TRK67919507,4,WINTER15,Facebook,375.76 +ORD200580,2023-11-14,C71076,Monitor,2,255.99,340 Main St,Credit Card,Delivered,TRK65148292,4,SAVE10,Instagram,511.98 +ORD200581,2024-11-11,C44674,Laptop,1,627.34,942 Main St,Online,Delivered,TRK87158684,1,,Referral,627.34 +ORD200582,2024-02-19,C15228,Tablet,3,474.14,558 Main St,Gift Card,Shipped,TRK33860620,8,WINTER15,Google,1422.42 +ORD200583,2025-06-15,C27072,Chair,3,154.37,996 Main St,Gift Card,Delivered,TRK29750379,4,,Instagram,463.11 +ORD200584,2025-03-21,C15257,Chair,4,145.05,626 Main St,Online,Delivered,TRK28779938,6,SAVE10,Google,580.2 +ORD200585,2023-08-20,C91486,Tablet,4,67.08,907 Main St,Cash,Returned,TRK79617136,8,WINTER15,Google,268.32 +ORD200586,2024-11-10,C17389,Monitor,1,522.08,905 Main St,Gift Card,Returned,TRK98857880,5,FREESHIP,Referral,522.08 +ORD200587,2023-06-12,C18820,Monitor,5,514.6,347 Main St,Gift Card,Delivered,TRK91547425,10,FREESHIP,Instagram,2573 +ORD200588,2024-12-10,C61849,Monitor,4,577.82,811 Main St,Credit Card,Delivered,TRK47613918,9,,Google,2311.28 +ORD200589,2025-02-10,C84041,Laptop,2,500.8,900 Main St,Cash,Delivered,TRK84920444,3,FREESHIP,Referral,1001.6 +ORD200590,2023-09-10,C55757,Printer,2,461.13,175 Main St,Gift Card,Returned,TRK27356242,4,,Email,922.26 +ORD200591,2024-11-18,C18187,Laptop,1,605.28,470 Main St,Gift Card,Shipped,TRK50528185,3,FREESHIP,Referral,605.28 +ORD200592,2024-04-23,C42306,Phone,3,204.27,938 Main St,Online,Returned,TRK15499648,4,,Google,612.81 +ORD200593,2023-08-02,C51024,Monitor,1,489.8,636 Main St,Gift Card,Shipped,TRK31375086,4,FREESHIP,Facebook,489.8 +ORD200594,2024-02-21,C40140,Phone,5,72.64,598 Main St,Credit Card,Cancelled,TRK12671989,7,,Email,363.2 +ORD200595,2025-01-10,C72596,Printer,2,385.16,491 Main St,Online,Pending,TRK83870446,7,SAVE10,Email,770.32 +ORD200596,2023-06-12,C91805,Desk,3,606.41,653 Main St,Debit Card,Returned,TRK34504030,7,FREESHIP,Facebook,1819.23 +ORD200597,2024-11-25,C40538,Desk,2,211.82,700 Main St,Gift Card,Cancelled,TRK29821356,4,WINTER15,Email,423.64 +ORD200598,2024-04-26,C60329,Desk,5,495.35,826 Main St,Credit Card,Pending,TRK59069987,5,,Facebook,2476.75 +ORD200599,2023-06-30,C28740,Chair,3,556.99,123 Main St,Online,Cancelled,TRK33642221,4,FREESHIP,Facebook,1670.97 +ORD200600,2023-05-26,C87051,Printer,1,72.31,460 Main St,Gift Card,Cancelled,TRK82056333,1,FREESHIP,Facebook,72.31 +ORD200601,2023-10-02,C12479,Monitor,5,24.82,529 Main St,Credit Card,Shipped,TRK73935314,10,,Referral,124.1 +ORD200602,2024-03-05,C35852,Tablet,4,26.04,982 Main St,Online,Pending,TRK64660134,5,SAVE10,Instagram,104.16 +ORD200603,2024-10-04,C26223,Tablet,1,657.07,800 Main St,Cash,Pending,TRK50900547,4,SAVE10,Google,657.07 +ORD200604,2025-06-22,C99214,Chair,3,32.62,252 Main St,Debit Card,Delivered,TRK81368481,6,,Facebook,97.86 +ORD200605,2024-05-10,C49605,Monitor,2,228.91,892 Main St,Debit Card,Shipped,TRK95620066,4,SAVE10,Referral,457.82 +ORD200606,2024-11-06,C85018,Laptop,3,274.75,783 Main St,Cash,Cancelled,TRK54128886,3,SAVE10,Google,824.25 +ORD200607,2025-05-31,C96434,Printer,4,634.05,282 Main St,Cash,Shipped,TRK56730647,6,SAVE10,Google,2536.2 +ORD200608,2024-07-24,C32956,Laptop,5,543.16,788 Main St,Online,Cancelled,TRK73140103,6,SAVE10,Instagram,2715.8 +ORD200609,2025-01-27,C41137,Chair,3,449.13,809 Main St,Cash,Returned,TRK52732162,5,WINTER15,Referral,1347.39 +ORD200610,2024-06-16,C60361,Desk,5,389.62,623 Main St,Cash,Returned,TRK83566924,7,FREESHIP,Facebook,1948.1 +ORD200611,2023-04-21,C36688,Desk,1,305.17,700 Main St,Gift Card,Returned,TRK35720426,3,WINTER15,Referral,305.17 +ORD200612,2023-06-02,C51811,Chair,3,445.12,339 Main St,Gift Card,Cancelled,TRK82377939,8,,Google,1335.36 +ORD200613,2024-12-19,C62405,Laptop,2,230.36,154 Main St,Online,Returned,TRK14721763,4,WINTER15,Email,460.72 +ORD200614,2024-03-08,C77363,Phone,1,96.81,807 Main St,Gift Card,Cancelled,TRK12439827,3,,Referral,96.81 +ORD200615,2025-03-07,C97218,Monitor,5,460.14,252 Main St,Credit Card,Returned,TRK52632065,10,WINTER15,Facebook,2300.7 +ORD200616,2024-10-17,C43919,Tablet,3,601.6,984 Main St,Credit Card,Cancelled,TRK73113192,7,SAVE10,Facebook,1804.8 +ORD200617,2024-02-08,C57093,Tablet,3,184.47,834 Main St,Online,Cancelled,TRK75469057,4,,Referral,553.41 +ORD200618,2024-09-03,C50565,Tablet,1,411.34,399 Main St,Debit Card,Returned,TRK97981418,5,,Instagram,411.34 +ORD200619,2024-07-16,C38845,Laptop,1,532.89,764 Main St,Gift Card,Pending,TRK47637374,2,,Referral,532.89 +ORD200620,2024-03-27,C84834,Tablet,3,136.34,866 Main St,Debit Card,Returned,TRK90136001,8,SAVE10,Referral,409.02 +ORD200621,2023-10-22,C37455,Phone,5,476.01,146 Main St,Credit Card,Delivered,TRK82685594,7,WINTER15,Google,2380.05 +ORD200622,2024-11-02,C27078,Desk,5,236.38,128 Main St,Credit Card,Returned,TRK89314307,7,,Facebook,1181.9 +ORD200623,2023-06-16,C91941,Printer,3,396,269 Main St,Gift Card,Cancelled,TRK21330732,4,FREESHIP,Instagram,1188 +ORD200624,2024-01-16,C25967,Tablet,5,341.96,747 Main St,Debit Card,Delivered,TRK88559278,6,,Email,1709.8 +ORD200625,2023-09-24,C22123,Tablet,1,672.89,519 Main St,Credit Card,Pending,TRK43250279,1,WINTER15,Email,672.89 +ORD200626,2024-03-01,C45671,Tablet,2,657.48,769 Main St,Online,Shipped,TRK18179773,5,SAVE10,Referral,1314.96 +ORD200627,2023-08-06,C53334,Chair,3,498.68,879 Main St,Online,Returned,TRK31724421,4,FREESHIP,Email,1496.04 +ORD200628,2023-03-26,C18717,Printer,5,558.63,861 Main St,Cash,Pending,TRK58568806,8,FREESHIP,Referral,2793.15 +ORD200629,2023-07-07,C50137,Phone,3,19.73,840 Main St,Online,Pending,TRK91836131,3,,Referral,59.19 +ORD200630,2023-06-23,C51481,Monitor,5,248.84,140 Main St,Debit Card,Cancelled,TRK33437701,10,,Instagram,1244.2 +ORD200631,2024-08-31,C99128,Chair,3,46.11,360 Main St,Gift Card,Returned,TRK32426808,5,WINTER15,Referral,138.33 +ORD200632,2023-05-02,C67260,Laptop,5,678.16,463 Main St,Gift Card,Delivered,TRK38229104,7,WINTER15,Facebook,3390.8 +ORD200633,2024-04-10,C79533,Laptop,5,601.72,921 Main St,Gift Card,Cancelled,TRK54711422,5,WINTER15,Instagram,3008.6 +ORD200634,2024-04-25,C66906,Printer,2,259.32,117 Main St,Gift Card,Delivered,TRK31633755,2,WINTER15,Referral,518.64 +ORD200635,2023-12-13,C12818,Chair,3,63.68,434 Main St,Cash,Returned,TRK40879983,6,,Facebook,191.04 +ORD200636,2023-10-05,C60384,Laptop,4,371.07,336 Main St,Cash,Cancelled,TRK92080037,7,WINTER15,Facebook,1484.28 +ORD200637,2024-09-29,C92294,Chair,4,306.35,784 Main St,Gift Card,Shipped,TRK23585765,7,WINTER15,Referral,1225.4 +ORD200638,2023-10-15,C66840,Tablet,4,578.27,547 Main St,Online,Delivered,TRK76929637,9,WINTER15,Email,2313.08 +ORD200639,2023-01-20,C22534,Chair,1,529.19,391 Main St,Cash,Cancelled,TRK17415798,5,,Referral,529.19 +ORD200640,2024-02-27,C46509,Chair,2,587.49,647 Main St,Gift Card,Returned,TRK24241664,6,SAVE10,Referral,1174.98 +ORD200641,2024-06-30,C71680,Printer,4,567.57,814 Main St,Debit Card,Pending,TRK47386650,9,WINTER15,Google,2270.28 +ORD200642,2024-04-29,C15063,Chair,5,85.22,527 Main St,Credit Card,Cancelled,TRK10329390,7,FREESHIP,Email,426.1 +ORD200643,2024-08-26,C77122,Laptop,1,438.37,647 Main St,Cash,Cancelled,TRK75814880,4,SAVE10,Referral,438.37 +ORD200644,2023-11-15,C86524,Chair,2,366.23,961 Main St,Cash,Shipped,TRK62490506,2,WINTER15,Email,732.46 +ORD200645,2023-01-02,C82990,Laptop,2,150.05,727 Main St,Credit Card,Cancelled,TRK68574801,4,SAVE10,Facebook,300.1 +ORD200646,2023-10-27,C98761,Chair,4,498.51,804 Main St,Debit Card,Shipped,TRK43262630,4,SAVE10,Google,1994.04 +ORD200647,2025-04-24,C54409,Desk,3,339.39,667 Main St,Cash,Returned,TRK67671316,7,FREESHIP,Google,1018.17 +ORD200648,2025-01-18,C89674,Monitor,2,575.83,182 Main St,Online,Delivered,TRK45902512,3,WINTER15,Referral,1151.66 +ORD200649,2023-12-23,C45899,Monitor,2,642.98,153 Main St,Debit Card,Returned,TRK32932093,7,FREESHIP,Email,1285.96 +ORD200650,2023-05-18,C74499,Desk,2,372.23,518 Main St,Gift Card,Delivered,TRK93767278,7,SAVE10,Email,744.46 +ORD200651,2024-11-12,C81192,Chair,3,646.34,429 Main St,Debit Card,Pending,TRK76931118,5,,Google,1939.02 +ORD200652,2024-06-05,C71473,Chair,5,341.84,328 Main St,Online,Shipped,TRK94857335,8,FREESHIP,Instagram,1709.2 +ORD200653,2024-02-25,C59338,Printer,3,690.3,747 Main St,Credit Card,Shipped,TRK12902764,6,WINTER15,Google,2070.9 +ORD200654,2023-06-12,C62661,Tablet,3,382.37,863 Main St,Debit Card,Returned,TRK25748100,8,,Instagram,1147.11 +ORD200655,2023-03-14,C22101,Chair,2,132.6,262 Main St,Debit Card,Cancelled,TRK70711522,4,WINTER15,Email,265.2 +ORD200656,2024-01-18,C51404,Monitor,2,189.06,835 Main St,Gift Card,Shipped,TRK85682500,7,SAVE10,Facebook,378.12 +ORD200657,2023-12-24,C19384,Tablet,4,87.79,532 Main St,Cash,Cancelled,TRK33207064,6,FREESHIP,Instagram,351.16 +ORD200658,2025-04-18,C86864,Printer,2,46.36,670 Main St,Gift Card,Returned,TRK15323191,4,SAVE10,Google,92.72 +ORD200659,2024-10-26,C24301,Phone,2,642.04,964 Main St,Gift Card,Delivered,TRK55000075,4,WINTER15,Email,1284.08 +ORD200660,2024-10-19,C43842,Chair,2,651.57,933 Main St,Debit Card,Shipped,TRK54084424,7,WINTER15,Facebook,1303.14 +ORD200661,2025-02-28,C63657,Tablet,3,424.89,116 Main St,Debit Card,Cancelled,TRK86378984,6,FREESHIP,Google,1274.67 +ORD200662,2023-01-28,C98332,Laptop,3,438.89,985 Main St,Cash,Returned,TRK85744797,3,,Facebook,1316.67 +ORD200663,2024-04-15,C59774,Monitor,1,72.6,941 Main St,Debit Card,Cancelled,TRK87635135,6,FREESHIP,Instagram,72.6 +ORD200664,2024-12-19,C14847,Laptop,4,194.75,188 Main St,Cash,Shipped,TRK46492755,5,,Facebook,779 +ORD200665,2023-05-02,C83653,Tablet,4,231.26,253 Main St,Online,Shipped,TRK32619935,6,WINTER15,Google,925.04 +ORD200666,2024-08-31,C35711,Monitor,4,327.12,788 Main St,Credit Card,Cancelled,TRK45281495,4,,Email,1308.48 +ORD200667,2023-05-03,C10477,Laptop,1,466.42,172 Main St,Gift Card,Pending,TRK41505339,5,SAVE10,Email,466.42 +ORD200668,2024-07-05,C61257,Monitor,2,253.67,981 Main St,Cash,Returned,TRK25226070,3,WINTER15,Facebook,507.34 +ORD200669,2023-02-05,C60547,Desk,1,257,812 Main St,Debit Card,Cancelled,TRK65694249,5,,Referral,257 +ORD200670,2024-04-18,C14576,Desk,4,539.2,747 Main St,Credit Card,Pending,TRK21637540,8,FREESHIP,Google,2156.8 +ORD200671,2023-06-15,C49282,Chair,5,50.74,737 Main St,Gift Card,Cancelled,TRK88653901,7,WINTER15,Google,253.7 +ORD200672,2023-05-09,C14017,Phone,2,624.16,984 Main St,Debit Card,Shipped,TRK71009446,2,SAVE10,Instagram,1248.32 +ORD200673,2023-02-21,C46504,Tablet,2,372.92,131 Main St,Credit Card,Delivered,TRK95024356,7,SAVE10,Email,745.84 +ORD200674,2024-01-09,C56928,Laptop,4,358.75,860 Main St,Gift Card,Delivered,TRK57792939,9,SAVE10,Facebook,1435 +ORD200675,2024-08-06,C97749,Desk,3,342.02,906 Main St,Debit Card,Pending,TRK90233116,5,,Email,1026.06 +ORD200676,2025-06-23,C90431,Laptop,2,422.34,985 Main St,Credit Card,Cancelled,TRK44151723,4,FREESHIP,Instagram,844.68 +ORD200677,2025-04-03,C56722,Tablet,5,22.07,179 Main St,Online,Cancelled,TRK78778569,7,FREESHIP,Instagram,110.35 +ORD200678,2024-11-24,C40863,Chair,3,163.13,457 Main St,Gift Card,Shipped,TRK20553345,5,WINTER15,Facebook,489.39 +ORD200679,2023-02-02,C40798,Tablet,3,360.66,304 Main St,Online,Returned,TRK66106697,5,FREESHIP,Instagram,1081.98 +ORD200680,2023-08-27,C16702,Monitor,3,463.39,694 Main St,Credit Card,Returned,TRK16953491,3,,Facebook,1390.17 +ORD200681,2024-01-30,C38262,Tablet,1,155.27,548 Main St,Debit Card,Shipped,TRK47300502,6,,Email,155.27 +ORD200682,2023-07-23,C50274,Monitor,3,509.42,449 Main St,Credit Card,Cancelled,TRK91729086,5,FREESHIP,Google,1528.26 +ORD200683,2025-05-18,C91591,Desk,4,652.48,887 Main St,Cash,Pending,TRK23554043,5,FREESHIP,Instagram,2609.92 +ORD200684,2024-09-22,C96583,Printer,4,34.84,288 Main St,Credit Card,Shipped,TRK64353241,8,,Email,139.36 +ORD200685,2025-02-07,C64579,Desk,1,234.37,638 Main St,Debit Card,Shipped,TRK10276565,5,FREESHIP,Email,234.37 +ORD200686,2023-10-09,C41903,Desk,3,53.6,525 Main St,Cash,Pending,TRK59112382,4,WINTER15,Facebook,160.8 +ORD200687,2023-09-13,C19742,Tablet,1,332.09,408 Main St,Gift Card,Returned,TRK68845230,5,FREESHIP,Instagram,332.09 +ORD200688,2024-03-06,C20077,Monitor,4,593.22,154 Main St,Credit Card,Cancelled,TRK36415742,8,WINTER15,Facebook,2372.88 +ORD200689,2023-08-29,C13186,Tablet,2,444.84,787 Main St,Online,Shipped,TRK56967415,7,,Facebook,889.68 +ORD200690,2024-07-12,C29318,Monitor,1,24.48,128 Main St,Gift Card,Returned,TRK88666721,1,,Instagram,24.48 +ORD200691,2024-11-24,C36137,Laptop,3,239.08,396 Main St,Cash,Shipped,TRK57376416,8,,Google,717.24 +ORD200692,2023-01-23,C25534,Desk,5,196.84,319 Main St,Credit Card,Delivered,TRK68347402,5,WINTER15,Instagram,984.2 +ORD200693,2025-03-12,C62070,Monitor,1,176.58,674 Main St,Debit Card,Returned,TRK10267127,4,,Referral,176.58 +ORD200694,2023-10-02,C92049,Printer,4,666.52,619 Main St,Cash,Shipped,TRK32287092,8,FREESHIP,Email,2666.08 +ORD200695,2024-11-23,C52604,Printer,5,101.3,553 Main St,Online,Shipped,TRK48839788,7,FREESHIP,Email,506.5 +ORD200696,2023-07-02,C22429,Chair,4,151.2,965 Main St,Gift Card,Pending,TRK38572927,9,WINTER15,Facebook,604.8 +ORD200697,2025-02-04,C27430,Printer,5,94.85,788 Main St,Cash,Shipped,TRK45025840,6,WINTER15,Email,474.25 +ORD200698,2023-01-04,C44366,Laptop,2,388.22,169 Main St,Cash,Delivered,TRK48658394,2,WINTER15,Instagram,776.44 +ORD200699,2023-11-13,C36813,Laptop,3,614.15,897 Main St,Gift Card,Cancelled,TRK84088900,3,,Facebook,1842.45 +ORD200700,2024-09-25,C40201,Laptop,2,92.91,555 Main St,Cash,Returned,TRK30198779,3,WINTER15,Instagram,185.82 +ORD200701,2024-06-23,C75456,Monitor,3,92.22,115 Main St,Credit Card,Delivered,TRK90519490,5,FREESHIP,Email,276.66 +ORD200702,2024-06-09,C33315,Printer,3,562.55,154 Main St,Debit Card,Returned,TRK43589369,6,,Email,1687.65 +ORD200703,2023-03-22,C89336,Desk,1,92.79,799 Main St,Cash,Pending,TRK47665103,3,WINTER15,Email,92.79 +ORD200704,2023-06-03,C96034,Desk,4,30.27,819 Main St,Online,Delivered,TRK87261034,9,FREESHIP,Google,121.08 +ORD200705,2025-03-30,C50114,Monitor,2,49.08,420 Main St,Debit Card,Returned,TRK20214786,7,FREESHIP,Instagram,98.16 +ORD200706,2025-03-02,C85330,Desk,5,228.09,969 Main St,Gift Card,Returned,TRK97693301,9,FREESHIP,Facebook,1140.45 +ORD200707,2024-11-01,C31761,Chair,4,650.04,989 Main St,Gift Card,Cancelled,TRK17628852,6,SAVE10,Facebook,2600.16 +ORD200708,2025-03-04,C25268,Printer,1,665.11,788 Main St,Cash,Pending,TRK20481215,3,FREESHIP,Instagram,665.11 +ORD200709,2024-12-07,C17132,Desk,1,386.03,855 Main St,Online,Pending,TRK37504692,4,FREESHIP,Google,386.03 +ORD200710,2024-07-22,C48790,Laptop,5,21.54,113 Main St,Gift Card,Returned,TRK19086608,10,,Google,107.7 +ORD200711,2024-07-04,C61070,Tablet,2,475.78,632 Main St,Online,Shipped,TRK90764894,2,WINTER15,Google,951.56 +ORD200712,2024-01-09,C56969,Tablet,2,68.4,993 Main St,Gift Card,Pending,TRK10513339,7,FREESHIP,Email,136.8 +ORD200713,2025-06-21,C65056,Tablet,4,532.49,638 Main St,Online,Cancelled,TRK31705278,6,SAVE10,Facebook,2129.96 +ORD200714,2023-04-21,C84888,Laptop,1,51.73,278 Main St,Debit Card,Pending,TRK23612847,1,FREESHIP,Facebook,51.73 +ORD200715,2024-07-26,C68266,Printer,3,653.63,281 Main St,Online,Delivered,TRK96161062,7,FREESHIP,Email,1960.89 +ORD200716,2024-06-13,C84115,Chair,3,454.29,891 Main St,Credit Card,Pending,TRK25466842,4,WINTER15,Google,1362.87 +ORD200717,2023-10-16,C50087,Chair,3,122.11,707 Main St,Online,Delivered,TRK31143760,4,WINTER15,Email,366.33 +ORD200718,2023-04-08,C16790,Laptop,4,64.74,718 Main St,Gift Card,Cancelled,TRK91791367,8,SAVE10,Google,258.96 +ORD200719,2024-01-21,C46920,Laptop,2,681.06,703 Main St,Debit Card,Shipped,TRK86403837,3,FREESHIP,Facebook,1362.12 +ORD200720,2023-09-21,C12740,Desk,5,128.95,305 Main St,Cash,Pending,TRK98506513,10,FREESHIP,Instagram,644.75 +ORD200721,2024-03-18,C46557,Desk,2,118.59,890 Main St,Credit Card,Delivered,TRK56110689,2,,Email,237.18 +ORD200722,2024-11-15,C58156,Printer,1,95.1,516 Main St,Gift Card,Pending,TRK49719458,1,WINTER15,Instagram,95.1 +ORD200723,2023-12-09,C14455,Desk,3,54.95,385 Main St,Cash,Returned,TRK50933724,8,SAVE10,Referral,164.85 +ORD200724,2024-10-18,C63150,Printer,3,136.97,326 Main St,Credit Card,Returned,TRK19348078,4,FREESHIP,Referral,410.91 +ORD200725,2023-03-12,C95269,Chair,2,194.85,372 Main St,Gift Card,Returned,TRK45670926,5,,Referral,389.7 +ORD200726,2024-10-25,C18105,Laptop,4,583.02,338 Main St,Online,Delivered,TRK94006117,4,FREESHIP,Facebook,2332.08 +ORD200727,2024-09-29,C29063,Chair,5,95.75,379 Main St,Online,Shipped,TRK92745947,8,SAVE10,Instagram,478.75 +ORD200728,2024-07-29,C10154,Desk,4,325.76,827 Main St,Gift Card,Shipped,TRK79793300,8,WINTER15,Email,1303.04 +ORD200729,2023-09-08,C36997,Phone,4,186.41,819 Main St,Gift Card,Pending,TRK92794872,6,SAVE10,Google,745.64 +ORD200730,2025-02-22,C77357,Phone,1,474.6,407 Main St,Debit Card,Delivered,TRK91943923,4,SAVE10,Email,474.6 +ORD200731,2024-06-07,C71310,Printer,5,584.46,308 Main St,Credit Card,Returned,TRK48292586,8,,Email,2922.3 +ORD200732,2025-03-07,C80987,Laptop,1,132.05,787 Main St,Online,Delivered,TRK42187776,2,,Google,132.05 +ORD200733,2023-12-04,C90757,Tablet,4,494.84,694 Main St,Cash,Returned,TRK87991608,8,SAVE10,Email,1979.36 +ORD200734,2024-01-23,C51898,Printer,4,224.61,630 Main St,Credit Card,Returned,TRK19767885,6,WINTER15,Facebook,898.44 +ORD200735,2024-06-28,C94508,Monitor,4,44.07,359 Main St,Debit Card,Pending,TRK13443264,6,,Email,176.28 +ORD200736,2024-02-09,C59441,Monitor,5,418.53,696 Main St,Credit Card,Pending,TRK66186874,6,FREESHIP,Google,2092.65 +ORD200737,2024-01-03,C91029,Phone,4,532.87,972 Main St,Cash,Pending,TRK25501930,9,FREESHIP,Instagram,2131.48 +ORD200738,2025-06-04,C96261,Phone,2,485.37,264 Main St,Credit Card,Shipped,TRK44998396,5,SAVE10,Email,970.74 +ORD200739,2024-06-13,C35123,Phone,4,386.73,513 Main St,Cash,Delivered,TRK58979275,4,SAVE10,Facebook,1546.92 +ORD200740,2024-07-20,C10892,Desk,2,377.47,433 Main St,Cash,Pending,TRK76154554,7,,Google,754.94 +ORD200741,2025-01-23,C99683,Monitor,5,332.64,945 Main St,Gift Card,Delivered,TRK87305883,10,,Referral,1663.2 +ORD200742,2024-11-30,C41974,Laptop,3,699.93,726 Main St,Cash,Returned,TRK48051468,7,SAVE10,Google,2099.79 +ORD200743,2024-09-30,C23978,Monitor,1,576.35,549 Main St,Gift Card,Returned,TRK87090813,1,WINTER15,Instagram,576.35 +ORD200744,2024-06-12,C10642,Tablet,2,461.37,200 Main St,Cash,Delivered,TRK98725693,5,SAVE10,Google,922.74 +ORD200745,2023-03-02,C73813,Printer,4,111.3,364 Main St,Debit Card,Pending,TRK89906749,7,FREESHIP,Email,445.2 +ORD200746,2025-02-24,C32183,Desk,3,661.89,551 Main St,Online,Cancelled,TRK76287027,6,WINTER15,Referral,1985.67 +ORD200747,2025-03-12,C54277,Tablet,2,259.58,940 Main St,Debit Card,Delivered,TRK26500181,7,FREESHIP,Instagram,519.16 +ORD200748,2024-07-15,C56553,Tablet,3,70.81,249 Main St,Credit Card,Shipped,TRK37667360,8,FREESHIP,Referral,212.43 +ORD200749,2025-04-13,C17551,Laptop,1,518.39,997 Main St,Debit Card,Pending,TRK88797170,4,FREESHIP,Instagram,518.39 +ORD200750,2023-01-14,C14737,Tablet,4,145.41,637 Main St,Credit Card,Returned,TRK10295115,7,FREESHIP,Email,581.64 +ORD200751,2023-01-24,C35168,Tablet,2,599.86,455 Main St,Gift Card,Pending,TRK76960854,7,FREESHIP,Facebook,1199.72 +ORD200752,2024-10-03,C82217,Phone,4,429.37,299 Main St,Credit Card,Delivered,TRK33305694,8,FREESHIP,Google,1717.48 +ORD200753,2024-04-24,C42270,Phone,2,241.49,864 Main St,Debit Card,Returned,TRK72697796,7,FREESHIP,Instagram,482.98 +ORD200754,2025-05-31,C48846,Printer,2,452.05,983 Main St,Credit Card,Returned,TRK52804097,3,WINTER15,Email,904.1 +ORD200755,2023-06-13,C54160,Desk,3,336.71,658 Main St,Credit Card,Pending,TRK60515972,4,,Email,1010.13 +ORD200756,2024-06-27,C14080,Phone,1,283.69,202 Main St,Gift Card,Shipped,TRK93163682,6,,Google,283.69 +ORD200757,2024-02-22,C81074,Desk,1,157.72,597 Main St,Debit Card,Delivered,TRK91105190,2,FREESHIP,Google,157.72 +ORD200758,2023-03-26,C69021,Tablet,3,624.84,917 Main St,Credit Card,Cancelled,TRK57148510,8,WINTER15,Facebook,1874.52 +ORD200759,2023-07-24,C96283,Desk,3,308.01,366 Main St,Cash,Pending,TRK91784124,3,FREESHIP,Facebook,924.03 +ORD200760,2025-02-18,C96636,Desk,1,39.56,283 Main St,Debit Card,Cancelled,TRK73324346,5,,Google,39.56 +ORD200761,2023-06-02,C37235,Desk,4,37.76,217 Main St,Debit Card,Delivered,TRK67789367,7,,Google,151.04 +ORD200762,2024-09-17,C12444,Phone,3,76.96,611 Main St,Cash,Returned,TRK97621403,8,FREESHIP,Email,230.88 +ORD200763,2023-04-06,C79142,Laptop,1,569.96,533 Main St,Online,Delivered,TRK30915955,4,FREESHIP,Email,569.96 +ORD200764,2024-03-10,C35983,Laptop,5,627.43,806 Main St,Credit Card,Cancelled,TRK14016163,10,FREESHIP,Email,3137.15 +ORD200765,2023-10-06,C36150,Laptop,2,534.91,281 Main St,Debit Card,Returned,TRK96249043,5,SAVE10,Google,1069.82 +ORD200766,2023-01-22,C91454,Printer,2,278.88,494 Main St,Debit Card,Pending,TRK99985340,3,FREESHIP,Referral,557.76 +ORD200767,2025-04-18,C19368,Tablet,2,323.22,517 Main St,Credit Card,Delivered,TRK80436037,7,,Instagram,646.44 +ORD200768,2023-09-04,C35987,Tablet,5,653.46,165 Main St,Cash,Cancelled,TRK28918815,9,WINTER15,Email,3267.3 +ORD200769,2023-07-06,C13366,Printer,4,678.55,568 Main St,Cash,Delivered,TRK98691410,5,,Email,2714.2 +ORD200770,2024-02-11,C72166,Desk,1,314.38,227 Main St,Online,Returned,TRK67733444,6,,Google,314.38 +ORD200771,2024-06-12,C20357,Phone,3,692.44,272 Main St,Debit Card,Cancelled,TRK82236408,8,FREESHIP,Google,2077.32 +ORD200772,2024-07-28,C33802,Monitor,1,604.87,461 Main St,Online,Delivered,TRK25799478,4,,Instagram,604.87 +ORD200773,2025-06-28,C99205,Phone,2,512.33,415 Main St,Cash,Cancelled,TRK48904015,7,,Facebook,1024.66 +ORD200774,2025-04-15,C29701,Chair,3,20.54,257 Main St,Credit Card,Cancelled,TRK42266846,3,FREESHIP,Instagram,61.62 +ORD200775,2023-03-04,C73941,Phone,2,625.22,569 Main St,Online,Cancelled,TRK22051900,5,,Google,1250.44 +ORD200776,2023-08-21,C69168,Tablet,1,21.19,482 Main St,Cash,Returned,TRK10446197,5,WINTER15,Google,21.19 +ORD200777,2025-03-21,C66116,Chair,5,64.49,633 Main St,Online,Cancelled,TRK41967983,7,,Facebook,322.45 +ORD200778,2023-04-28,C85059,Laptop,4,246.85,316 Main St,Credit Card,Shipped,TRK56503740,8,WINTER15,Google,987.4 +ORD200779,2023-12-01,C18076,Phone,3,588.74,751 Main St,Debit Card,Pending,TRK26661705,8,FREESHIP,Email,1766.22 +ORD200780,2024-03-31,C41284,Laptop,4,184.48,661 Main St,Online,Cancelled,TRK73613128,4,WINTER15,Google,737.92 +ORD200781,2024-01-10,C43524,Phone,5,524.26,934 Main St,Gift Card,Delivered,TRK51479426,5,FREESHIP,Referral,2621.3 +ORD200782,2024-08-11,C58063,Monitor,2,493.63,167 Main St,Online,Returned,TRK50548869,6,SAVE10,Referral,987.26 +ORD200783,2025-05-26,C19937,Printer,1,438.34,281 Main St,Gift Card,Returned,TRK46990083,5,FREESHIP,Facebook,438.34 +ORD200784,2025-05-16,C21191,Laptop,1,325.81,232 Main St,Credit Card,Pending,TRK85771230,1,WINTER15,Referral,325.81 +ORD200785,2023-07-29,C45862,Chair,1,176.1,342 Main St,Credit Card,Pending,TRK53089983,1,SAVE10,Instagram,176.1 +ORD200786,2023-08-23,C39130,Chair,5,45.31,774 Main St,Online,Cancelled,TRK99583414,8,,Referral,226.55 +ORD200787,2024-03-17,C18167,Desk,4,221.96,193 Main St,Cash,Delivered,TRK36841089,7,,Google,887.84 +ORD200788,2023-11-02,C47307,Chair,2,601.43,761 Main St,Online,Pending,TRK43516112,5,FREESHIP,Instagram,1202.86 +ORD200789,2023-08-17,C57276,Tablet,5,691.28,183 Main St,Online,Delivered,TRK75899752,10,SAVE10,Email,3456.4 +ORD200790,2024-09-14,C38928,Laptop,4,417.89,302 Main St,Gift Card,Pending,TRK96636009,4,,Google,1671.56 +ORD200791,2024-01-13,C49710,Chair,4,409.28,956 Main St,Cash,Pending,TRK92591237,8,,Email,1637.12 +ORD200792,2023-06-16,C41709,Desk,2,356.35,746 Main St,Debit Card,Returned,TRK90995294,6,WINTER15,Facebook,712.7 +ORD200793,2024-04-15,C91255,Chair,5,170.22,769 Main St,Debit Card,Delivered,TRK69599961,8,,Referral,851.1 +ORD200794,2023-03-09,C76653,Printer,4,384.85,988 Main St,Online,Delivered,TRK77052196,9,FREESHIP,Instagram,1539.4 +ORD200795,2024-11-20,C95667,Laptop,4,115.77,586 Main St,Online,Pending,TRK41266666,7,SAVE10,Instagram,463.08 +ORD200796,2025-04-29,C33313,Phone,3,579.55,882 Main St,Gift Card,Returned,TRK13349970,8,WINTER15,Facebook,1738.65 +ORD200797,2023-02-27,C36825,Laptop,2,438.76,426 Main St,Debit Card,Returned,TRK72557318,2,,Facebook,877.52 +ORD200798,2025-05-19,C20861,Phone,5,488.35,968 Main St,Debit Card,Returned,TRK89372013,9,FREESHIP,Email,2441.75 +ORD200799,2023-04-16,C26364,Laptop,4,328.56,803 Main St,Debit Card,Returned,TRK78924436,4,FREESHIP,Email,1314.24 +ORD200800,2025-03-28,C34686,Tablet,1,68.39,412 Main St,Online,Returned,TRK99468332,3,WINTER15,Facebook,68.39 +ORD200801,2023-05-03,C97593,Printer,4,595.62,738 Main St,Debit Card,Pending,TRK58443593,8,FREESHIP,Facebook,2382.48 +ORD200802,2024-02-17,C84331,Chair,5,644.64,205 Main St,Gift Card,Cancelled,TRK34440714,6,FREESHIP,Email,3223.2 +ORD200803,2023-08-20,C88775,Monitor,5,397.81,223 Main St,Debit Card,Returned,TRK45098068,5,SAVE10,Referral,1989.05 +ORD200804,2024-01-01,C76362,Chair,3,236.5,916 Main St,Online,Delivered,TRK11868618,8,FREESHIP,Email,709.5 +ORD200805,2024-10-15,C59278,Laptop,5,472.01,178 Main St,Gift Card,Cancelled,TRK14590037,10,SAVE10,Email,2360.05 +ORD200806,2023-09-01,C55819,Chair,5,253.75,740 Main St,Online,Pending,TRK13775054,9,WINTER15,Instagram,1268.75 +ORD200807,2024-11-10,C82344,Monitor,3,676.21,260 Main St,Online,Delivered,TRK70957219,5,SAVE10,Google,2028.63 +ORD200808,2024-02-13,C65565,Desk,3,134.05,192 Main St,Credit Card,Shipped,TRK80383756,3,,Google,402.15 +ORD200809,2024-04-09,C80416,Desk,5,217.43,752 Main St,Debit Card,Shipped,TRK54385892,10,SAVE10,Instagram,1087.15 +ORD200810,2023-05-31,C23637,Tablet,1,553.56,644 Main St,Credit Card,Cancelled,TRK16749863,5,,Referral,553.56 +ORD200811,2023-11-05,C24769,Laptop,2,28.55,864 Main St,Gift Card,Shipped,TRK44538305,7,SAVE10,Email,57.1 +ORD200812,2024-01-26,C81547,Phone,2,255.26,803 Main St,Credit Card,Cancelled,TRK88437123,6,FREESHIP,Google,510.52 +ORD200813,2025-03-15,C12813,Laptop,5,292.54,263 Main St,Debit Card,Cancelled,TRK36131660,8,FREESHIP,Email,1462.7 +ORD200814,2024-12-11,C50732,Chair,4,147.51,979 Main St,Debit Card,Pending,TRK21082461,4,WINTER15,Instagram,590.04 +ORD200815,2024-08-04,C41320,Printer,3,569.84,920 Main St,Gift Card,Cancelled,TRK77539180,8,WINTER15,Instagram,1709.52 +ORD200816,2024-02-21,C55286,Tablet,5,574.79,497 Main St,Credit Card,Pending,TRK39058734,8,WINTER15,Referral,2873.95 +ORD200817,2023-10-05,C87994,Chair,4,598.19,430 Main St,Credit Card,Delivered,TRK98883971,7,WINTER15,Email,2392.76 +ORD200818,2023-03-02,C25580,Phone,4,390.84,860 Main St,Credit Card,Cancelled,TRK58781638,9,WINTER15,Referral,1563.36 +ORD200819,2024-09-28,C66196,Phone,2,398.45,650 Main St,Debit Card,Cancelled,TRK38104650,7,SAVE10,Google,796.9 +ORD200820,2023-05-27,C35377,Phone,5,623.81,171 Main St,Cash,Returned,TRK17342157,6,FREESHIP,Email,3119.05 +ORD200821,2024-12-14,C40771,Laptop,4,174.49,259 Main St,Credit Card,Delivered,TRK56310345,5,SAVE10,Facebook,697.96 +ORD200822,2025-03-15,C20624,Phone,1,479.56,923 Main St,Gift Card,Returned,TRK45123395,1,SAVE10,Google,479.56 +ORD200823,2024-10-07,C27070,Laptop,4,653.13,973 Main St,Credit Card,Shipped,TRK83842481,8,WINTER15,Instagram,2612.52 +ORD200824,2023-08-29,C18826,Monitor,3,481.1,664 Main St,Credit Card,Returned,TRK12530495,3,FREESHIP,Facebook,1443.3 +ORD200825,2025-03-26,C23899,Desk,5,271.69,543 Main St,Online,Returned,TRK88914760,7,FREESHIP,Instagram,1358.45 +ORD200826,2025-03-08,C43249,Printer,3,463.81,283 Main St,Online,Returned,TRK32469820,8,WINTER15,Email,1391.43 +ORD200827,2023-05-25,C95856,Tablet,2,639.88,432 Main St,Cash,Delivered,TRK58829625,5,WINTER15,Instagram,1279.76 +ORD200828,2024-07-24,C86266,Chair,4,404.58,510 Main St,Cash,Shipped,TRK64576020,5,FREESHIP,Instagram,1618.32 +ORD200829,2023-02-05,C39551,Monitor,1,76.93,685 Main St,Debit Card,Delivered,TRK68358007,6,WINTER15,Instagram,76.93 +ORD200830,2024-12-11,C90310,Tablet,4,190.64,853 Main St,Cash,Delivered,TRK70028457,5,SAVE10,Email,762.56 +ORD200831,2023-12-18,C20124,Printer,2,88.73,140 Main St,Online,Pending,TRK61346824,5,,Google,177.46 +ORD200832,2024-03-12,C63372,Chair,5,485.71,903 Main St,Online,Pending,TRK14661811,10,SAVE10,Referral,2428.55 +ORD200833,2025-03-14,C90595,Phone,5,78.29,508 Main St,Credit Card,Shipped,TRK96573803,5,WINTER15,Referral,391.45 +ORD200834,2024-04-11,C98483,Printer,5,22.14,456 Main St,Cash,Returned,TRK22084320,10,,Instagram,110.7 +ORD200835,2024-03-26,C16429,Desk,1,679.65,390 Main St,Debit Card,Shipped,TRK73888013,6,FREESHIP,Google,679.65 +ORD200836,2023-02-02,C31810,Phone,1,178.44,328 Main St,Credit Card,Cancelled,TRK58725886,2,FREESHIP,Google,178.44 +ORD200837,2025-06-14,C88029,Chair,5,655.55,282 Main St,Online,Delivered,TRK59701278,5,,Email,3277.75 +ORD200838,2024-04-11,C57798,Desk,4,577.08,384 Main St,Online,Pending,TRK68797566,8,,Facebook,2308.32 +ORD200839,2023-08-24,C82858,Chair,3,197.97,551 Main St,Online,Cancelled,TRK90618490,5,,Google,593.91 +ORD200840,2024-01-14,C60699,Chair,3,411.95,672 Main St,Credit Card,Delivered,TRK88660574,7,FREESHIP,Referral,1235.85 +ORD200841,2024-09-19,C94658,Printer,2,443.22,742 Main St,Credit Card,Delivered,TRK51732528,5,,Facebook,886.44 +ORD200842,2025-05-07,C78305,Laptop,3,364.14,396 Main St,Online,Pending,TRK88312618,7,WINTER15,Referral,1092.42 +ORD200843,2025-05-13,C43538,Desk,3,430.06,534 Main St,Gift Card,Cancelled,TRK20961563,8,FREESHIP,Instagram,1290.18 +ORD200844,2024-12-04,C47486,Chair,1,320.92,883 Main St,Online,Returned,TRK75984759,5,FREESHIP,Facebook,320.92 +ORD200845,2023-10-08,C24212,Phone,3,107.36,808 Main St,Gift Card,Delivered,TRK68894675,5,FREESHIP,Google,322.08 +ORD200846,2024-07-04,C24765,Desk,2,359.86,646 Main St,Debit Card,Cancelled,TRK43977698,4,,Referral,719.72 +ORD200847,2024-11-18,C48176,Printer,4,434.23,670 Main St,Online,Shipped,TRK90560300,8,FREESHIP,Email,1736.92 +ORD200848,2023-01-01,C54675,Chair,2,645.85,634 Main St,Online,Shipped,TRK18049633,5,,Referral,1291.7 +ORD200849,2025-06-09,C16675,Printer,4,214.35,664 Main St,Debit Card,Cancelled,TRK12756945,7,WINTER15,Referral,857.4 +ORD200850,2025-04-27,C38557,Monitor,3,638.5,890 Main St,Debit Card,Cancelled,TRK14832238,4,FREESHIP,Instagram,1915.5 +ORD200851,2023-12-12,C80183,Laptop,1,365.57,146 Main St,Online,Cancelled,TRK20814598,5,SAVE10,Email,365.57 +ORD200852,2024-10-24,C39530,Desk,3,568.05,618 Main St,Gift Card,Pending,TRK69000497,6,SAVE10,Google,1704.15 +ORD200853,2023-10-16,C10002,Printer,3,490.01,894 Main St,Cash,Returned,TRK94641152,4,SAVE10,Facebook,1470.03 +ORD200854,2025-06-13,C56938,Laptop,3,372.6,356 Main St,Credit Card,Delivered,TRK67735987,7,WINTER15,Referral,1117.8 +ORD200855,2023-05-25,C41331,Monitor,5,240.61,785 Main St,Credit Card,Shipped,TRK94198179,10,FREESHIP,Email,1203.05 +ORD200856,2024-06-03,C94698,Phone,1,586.62,871 Main St,Debit Card,Shipped,TRK95768773,5,,Facebook,586.62 +ORD200857,2024-03-10,C56506,Phone,3,257.84,185 Main St,Online,Delivered,TRK86808324,4,,Instagram,773.52 +ORD200858,2023-08-20,C22167,Tablet,5,435.66,891 Main St,Online,Pending,TRK70269748,9,,Facebook,2178.3 +ORD200859,2024-08-28,C11127,Chair,5,261.33,154 Main St,Credit Card,Returned,TRK73285507,5,SAVE10,Referral,1306.65 +ORD200860,2024-01-23,C69542,Printer,1,422.54,876 Main St,Cash,Delivered,TRK20746505,1,SAVE10,Google,422.54 +ORD200861,2023-03-19,C93276,Desk,5,330.45,230 Main St,Gift Card,Shipped,TRK44165913,10,FREESHIP,Google,1652.25 +ORD200862,2023-12-02,C37969,Desk,3,120.82,799 Main St,Credit Card,Shipped,TRK69852386,5,SAVE10,Referral,362.46 +ORD200863,2024-05-20,C98276,Phone,1,14.06,471 Main St,Credit Card,Pending,TRK74207282,5,SAVE10,Referral,14.06 +ORD200864,2023-05-03,C14240,Desk,1,491.11,592 Main St,Credit Card,Delivered,TRK58095246,4,SAVE10,Facebook,491.11 +ORD200865,2023-04-30,C72241,Monitor,4,677.37,156 Main St,Cash,Pending,TRK76270481,8,SAVE10,Google,2709.48 +ORD200866,2024-07-26,C39664,Desk,5,189.25,693 Main St,Debit Card,Cancelled,TRK39917741,10,WINTER15,Email,946.25 +ORD200867,2024-05-26,C53252,Printer,4,142.58,351 Main St,Cash,Delivered,TRK65831261,4,FREESHIP,Facebook,570.32 +ORD200868,2024-06-29,C70452,Monitor,4,316.32,309 Main St,Debit Card,Delivered,TRK42985882,7,,Facebook,1265.28 +ORD200869,2024-03-17,C29905,Desk,2,533.95,790 Main St,Online,Delivered,TRK16788127,5,WINTER15,Google,1067.9 +ORD200870,2025-06-01,C78725,Phone,4,470.09,541 Main St,Debit Card,Delivered,TRK72001139,4,FREESHIP,Google,1880.36 +ORD200871,2024-05-16,C93768,Tablet,3,324.3,720 Main St,Debit Card,Pending,TRK22024707,8,FREESHIP,Email,972.9 +ORD200872,2023-07-10,C59169,Chair,4,629.34,172 Main St,Cash,Shipped,TRK90883858,7,,Email,2517.36 +ORD200873,2024-05-12,C53488,Desk,3,136.84,448 Main St,Cash,Delivered,TRK27365050,3,SAVE10,Facebook,410.52 +ORD200874,2023-10-31,C92180,Chair,2,488.9,632 Main St,Cash,Delivered,TRK93315929,7,FREESHIP,Facebook,977.8 +ORD200875,2023-08-03,C25918,Laptop,5,133.39,203 Main St,Credit Card,Delivered,TRK66473392,6,FREESHIP,Referral,666.95 +ORD200876,2024-06-09,C90363,Chair,5,608.91,200 Main St,Gift Card,Pending,TRK21534173,6,SAVE10,Google,3044.55 +ORD200877,2024-07-25,C43867,Tablet,1,524.06,269 Main St,Debit Card,Pending,TRK97319127,3,FREESHIP,Email,524.06 +ORD200878,2023-06-01,C73873,Desk,2,330.69,393 Main St,Online,Cancelled,TRK56423132,5,SAVE10,Google,661.38 +ORD200879,2025-04-08,C56622,Phone,2,547.67,932 Main St,Gift Card,Shipped,TRK86373987,3,,Instagram,1095.34 +ORD200880,2025-03-12,C85074,Laptop,4,233.7,506 Main St,Online,Shipped,TRK63133878,8,SAVE10,Facebook,934.8 +ORD200881,2023-01-03,C59579,Tablet,2,448.85,386 Main St,Credit Card,Pending,TRK48000034,6,,Instagram,897.7 +ORD200882,2025-06-28,C43335,Phone,2,274.12,533 Main St,Cash,Delivered,TRK91848650,6,FREESHIP,Referral,548.24 +ORD200883,2025-05-13,C43595,Printer,5,561.48,451 Main St,Online,Delivered,TRK25317348,9,FREESHIP,Facebook,2807.4 +ORD200884,2024-05-15,C71471,Chair,1,595.54,817 Main St,Gift Card,Shipped,TRK52137079,4,,Instagram,595.54 +ORD200885,2024-04-07,C61090,Laptop,4,515.59,387 Main St,Credit Card,Shipped,TRK36388962,7,FREESHIP,Google,2062.36 +ORD200886,2023-10-25,C29620,Phone,1,460.13,792 Main St,Credit Card,Returned,TRK22046456,1,,Google,460.13 +ORD200887,2024-12-19,C67932,Chair,3,171.66,857 Main St,Debit Card,Delivered,TRK88547534,7,,Google,514.98 +ORD200888,2024-07-23,C14427,Laptop,2,266.95,833 Main St,Credit Card,Pending,TRK58024529,3,,Instagram,533.9 +ORD200889,2024-10-27,C36725,Monitor,5,650.72,350 Main St,Credit Card,Cancelled,TRK16808790,8,WINTER15,Email,3253.6 +ORD200890,2023-08-11,C51921,Laptop,3,439.53,943 Main St,Debit Card,Pending,TRK85741716,5,,Google,1318.59 +ORD200891,2023-11-11,C36534,Monitor,3,654.54,918 Main St,Cash,Returned,TRK38952138,7,SAVE10,Referral,1963.62 +ORD200892,2024-06-04,C72043,Desk,1,394.53,480 Main St,Cash,Shipped,TRK40896408,2,FREESHIP,Referral,394.53 +ORD200893,2023-03-21,C99533,Monitor,1,678.01,696 Main St,Cash,Pending,TRK55701253,4,FREESHIP,Referral,678.01 +ORD200894,2023-05-23,C90852,Tablet,3,575.01,852 Main St,Online,Cancelled,TRK37551831,8,WINTER15,Instagram,1725.03 +ORD200895,2023-11-09,C81882,Chair,3,154.64,832 Main St,Debit Card,Pending,TRK62371264,6,WINTER15,Facebook,463.92 +ORD200896,2024-10-18,C85466,Desk,3,147.29,102 Main St,Gift Card,Shipped,TRK66764177,3,FREESHIP,Google,441.87 +ORD200897,2024-09-03,C87995,Laptop,4,481.48,358 Main St,Gift Card,Delivered,TRK38730545,5,SAVE10,Instagram,1925.92 +ORD200898,2025-03-05,C44619,Monitor,3,158.37,742 Main St,Cash,Shipped,TRK66662528,6,,Referral,475.11 +ORD200899,2025-04-23,C99904,Printer,2,323.37,552 Main St,Online,Pending,TRK83843411,3,SAVE10,Instagram,646.74 +ORD200900,2025-02-07,C52342,Laptop,5,73.83,991 Main St,Debit Card,Pending,TRK67342586,9,,Instagram,369.15 +ORD200901,2024-04-28,C44277,Tablet,1,458.63,839 Main St,Debit Card,Returned,TRK79321479,4,WINTER15,Referral,458.63 +ORD200902,2024-07-13,C61162,Monitor,4,180.25,813 Main St,Debit Card,Cancelled,TRK76712124,7,,Facebook,721 +ORD200903,2023-05-17,C80868,Monitor,3,473.49,205 Main St,Credit Card,Pending,TRK56186636,7,,Email,1420.47 +ORD200904,2025-02-05,C16693,Monitor,4,237.43,262 Main St,Cash,Cancelled,TRK41146508,8,WINTER15,Referral,949.72 +ORD200905,2023-11-23,C67818,Laptop,1,442.39,101 Main St,Gift Card,Pending,TRK81978113,6,FREESHIP,Facebook,442.39 +ORD200906,2024-09-03,C49938,Monitor,1,62.12,141 Main St,Cash,Returned,TRK80175572,2,,Email,62.12 +ORD200907,2024-08-04,C90898,Desk,5,298.39,583 Main St,Gift Card,Cancelled,TRK52935170,7,WINTER15,Referral,1491.95 +ORD200908,2025-05-06,C35117,Desk,2,697.93,332 Main St,Credit Card,Cancelled,TRK27155709,2,SAVE10,Google,1395.86 +ORD200909,2024-05-27,C60203,Tablet,2,291.85,569 Main St,Cash,Shipped,TRK76525279,5,FREESHIP,Instagram,583.7 +ORD200910,2024-05-31,C36174,Printer,3,308.98,348 Main St,Cash,Delivered,TRK26397548,3,SAVE10,Instagram,926.94 +ORD200911,2024-08-13,C80872,Desk,5,396.86,593 Main St,Cash,Cancelled,TRK43967487,9,SAVE10,Instagram,1984.3 +ORD200912,2024-01-22,C67604,Desk,2,139.69,318 Main St,Online,Returned,TRK85545920,7,FREESHIP,Email,279.38 +ORD200913,2023-02-16,C45599,Printer,5,475.95,505 Main St,Credit Card,Returned,TRK62277685,8,WINTER15,Facebook,2379.75 +ORD200914,2025-02-10,C70352,Desk,1,626.6,955 Main St,Gift Card,Returned,TRK51589589,4,WINTER15,Facebook,626.6 +ORD200915,2024-02-16,C20643,Laptop,4,502.99,939 Main St,Debit Card,Shipped,TRK30736692,4,WINTER15,Referral,2011.96 +ORD200916,2024-06-21,C35669,Printer,5,578.83,165 Main St,Cash,Returned,TRK13928455,6,,Referral,2894.15 +ORD200917,2025-01-20,C65524,Laptop,5,383.82,836 Main St,Credit Card,Returned,TRK19315310,7,FREESHIP,Google,1919.1 +ORD200918,2025-06-24,C74359,Laptop,5,368.25,706 Main St,Online,Delivered,TRK18250450,5,,Instagram,1841.25 +ORD200919,2025-02-07,C92086,Printer,2,374.6,187 Main St,Online,Shipped,TRK23357668,3,FREESHIP,Referral,749.2 +ORD200920,2025-03-12,C26137,Tablet,2,428.09,978 Main St,Credit Card,Returned,TRK98110407,6,,Instagram,856.18 +ORD200921,2023-07-24,C90573,Tablet,1,438.93,144 Main St,Gift Card,Cancelled,TRK90075720,3,SAVE10,Referral,438.93 +ORD200922,2024-06-17,C81857,Desk,2,563.82,487 Main St,Credit Card,Pending,TRK79737732,3,,Instagram,1127.64 +ORD200923,2023-02-11,C91582,Printer,3,649.93,836 Main St,Credit Card,Pending,TRK99938245,7,WINTER15,Facebook,1949.79 +ORD200924,2025-03-22,C81319,Printer,5,268.43,991 Main St,Cash,Returned,TRK55330558,5,SAVE10,Email,1342.15 +ORD200925,2024-12-20,C78500,Monitor,5,502.47,304 Main St,Online,Shipped,TRK97460884,10,WINTER15,Email,2512.35 +ORD200926,2024-03-20,C67533,Desk,1,26.95,672 Main St,Cash,Delivered,TRK14566395,1,WINTER15,Email,26.95 +ORD200927,2023-02-14,C35566,Laptop,4,64.69,638 Main St,Debit Card,Shipped,TRK10003020,7,WINTER15,Google,258.76 +ORD200928,2024-05-09,C77166,Laptop,3,247.11,821 Main St,Debit Card,Returned,TRK18896595,3,WINTER15,Referral,741.33 +ORD200929,2024-10-16,C67936,Tablet,2,536.25,553 Main St,Debit Card,Pending,TRK71803414,3,,Email,1072.5 +ORD200930,2024-12-16,C59554,Phone,2,456.04,382 Main St,Debit Card,Returned,TRK28182447,4,FREESHIP,Email,912.08 +ORD200931,2024-01-01,C14005,Printer,2,40.23,623 Main St,Credit Card,Cancelled,TRK87567926,4,SAVE10,Google,80.46 +ORD200932,2023-03-26,C26118,Laptop,2,72.39,168 Main St,Online,Delivered,TRK15334251,7,WINTER15,Instagram,144.78 +ORD200933,2023-01-26,C59685,Monitor,2,394.16,255 Main St,Online,Shipped,TRK43718093,2,,Referral,788.32 +ORD200934,2025-06-01,C40304,Laptop,4,119.84,692 Main St,Gift Card,Shipped,TRK85790948,8,FREESHIP,Referral,479.36 +ORD200935,2023-11-24,C39593,Phone,3,692.71,398 Main St,Credit Card,Delivered,TRK62405253,3,FREESHIP,Instagram,2078.13 +ORD200936,2024-01-12,C50612,Chair,4,56.66,737 Main St,Online,Delivered,TRK44140968,4,SAVE10,Instagram,226.64 +ORD200937,2024-01-16,C39791,Chair,2,298.53,536 Main St,Debit Card,Cancelled,TRK46221436,5,WINTER15,Email,597.06 +ORD200938,2023-07-12,C39017,Chair,3,331.46,696 Main St,Credit Card,Cancelled,TRK91155214,6,WINTER15,Referral,994.38 +ORD200939,2025-04-16,C48510,Laptop,2,521.4,212 Main St,Cash,Delivered,TRK53152886,7,SAVE10,Instagram,1042.8 +ORD200940,2023-03-27,C74003,Printer,4,305.32,679 Main St,Online,Cancelled,TRK91525779,4,SAVE10,Google,1221.28 +ORD200941,2023-07-17,C91155,Printer,5,111.7,599 Main St,Credit Card,Cancelled,TRK82162952,9,FREESHIP,Email,558.5 +ORD200942,2023-09-29,C17591,Tablet,1,479.76,882 Main St,Credit Card,Pending,TRK56070470,1,,Email,479.76 +ORD200943,2023-12-27,C43330,Monitor,3,193.49,355 Main St,Gift Card,Returned,TRK71594838,6,FREESHIP,Facebook,580.47 +ORD200944,2024-12-16,C32687,Laptop,2,426.22,448 Main St,Online,Delivered,TRK98284560,7,WINTER15,Google,852.44 +ORD200945,2023-08-20,C79722,Tablet,5,276.44,619 Main St,Gift Card,Shipped,TRK29976438,10,FREESHIP,Referral,1382.2 +ORD200946,2024-05-04,C65021,Phone,2,404.96,546 Main St,Cash,Shipped,TRK20626179,4,SAVE10,Email,809.92 +ORD200947,2023-09-07,C85520,Phone,4,465.66,119 Main St,Online,Returned,TRK65994177,9,FREESHIP,Email,1862.64 +ORD200948,2024-06-21,C94569,Phone,2,594.07,739 Main St,Gift Card,Cancelled,TRK79269291,2,,Google,1188.14 +ORD200949,2023-11-09,C55778,Desk,5,110.38,319 Main St,Cash,Pending,TRK93797108,10,,Referral,551.9 +ORD200950,2024-05-31,C19722,Laptop,1,596.24,891 Main St,Credit Card,Returned,TRK78094361,4,FREESHIP,Instagram,596.24 +ORD200951,2024-07-22,C74928,Printer,2,306.24,589 Main St,Online,Returned,TRK39845914,4,FREESHIP,Email,612.48 +ORD200952,2025-02-27,C49111,Monitor,3,503.39,225 Main St,Online,Pending,TRK45303393,5,,Facebook,1510.17 +ORD200953,2023-02-06,C43721,Phone,1,131.61,971 Main St,Cash,Shipped,TRK89392104,2,FREESHIP,Facebook,131.61 +ORD200954,2024-10-22,C68609,Chair,3,443.44,240 Main St,Gift Card,Shipped,TRK58273778,3,FREESHIP,Google,1330.32 +ORD200955,2023-01-23,C82068,Chair,1,408.13,164 Main St,Gift Card,Shipped,TRK25779180,3,WINTER15,Instagram,408.13 +ORD200956,2024-04-11,C21191,Phone,2,160.98,381 Main St,Debit Card,Delivered,TRK86246309,3,SAVE10,Referral,321.96 +ORD200957,2023-01-12,C73575,Monitor,5,643.89,851 Main St,Cash,Returned,TRK23387612,8,WINTER15,Facebook,3219.45 +ORD200958,2023-05-13,C82685,Desk,3,158.66,537 Main St,Gift Card,Delivered,TRK70184320,7,WINTER15,Email,475.98 +ORD200959,2024-04-13,C73996,Tablet,2,143.82,856 Main St,Credit Card,Returned,TRK74579570,6,SAVE10,Instagram,287.64 +ORD200960,2023-12-11,C87687,Laptop,3,379.07,312 Main St,Gift Card,Pending,TRK60383805,3,WINTER15,Google,1137.21 +ORD200961,2024-11-11,C55464,Phone,1,601.36,532 Main St,Online,Shipped,TRK81178598,1,,Facebook,601.36 +ORD200962,2024-09-06,C12459,Phone,2,142.08,838 Main St,Gift Card,Delivered,TRK30674085,4,SAVE10,Referral,284.16 +ORD200963,2024-03-11,C88075,Chair,5,530.34,970 Main St,Online,Shipped,TRK42832976,9,FREESHIP,Google,2651.7 +ORD200964,2023-08-20,C18583,Phone,5,364.42,778 Main St,Credit Card,Cancelled,TRK43084595,10,SAVE10,Referral,1822.1 +ORD200965,2025-06-18,C70412,Laptop,4,578.28,791 Main St,Gift Card,Cancelled,TRK22192783,5,FREESHIP,Email,2313.12 +ORD200966,2025-05-20,C58503,Monitor,5,280.52,290 Main St,Credit Card,Cancelled,TRK12981657,7,WINTER15,Facebook,1402.6 +ORD200967,2025-05-06,C52879,Tablet,5,638.92,502 Main St,Credit Card,Returned,TRK67403284,5,FREESHIP,Google,3194.6 +ORD200968,2024-02-08,C67870,Monitor,4,412.2,664 Main St,Credit Card,Shipped,TRK72602178,6,WINTER15,Referral,1648.8 +ORD200969,2025-06-05,C19439,Desk,1,440.34,675 Main St,Gift Card,Shipped,TRK25383993,2,WINTER15,Facebook,440.34 +ORD200970,2024-09-07,C72664,Desk,1,627.15,241 Main St,Cash,Delivered,TRK86694331,5,SAVE10,Instagram,627.15 +ORD200971,2024-05-27,C32650,Monitor,2,605.26,934 Main St,Cash,Cancelled,TRK66648743,4,WINTER15,Referral,1210.52 +ORD200972,2024-06-09,C66438,Laptop,1,90.27,816 Main St,Cash,Delivered,TRK32035271,5,SAVE10,Facebook,90.27 +ORD200973,2025-06-09,C70010,Desk,5,230.77,141 Main St,Online,Pending,TRK50594008,10,WINTER15,Referral,1153.85 +ORD200974,2023-09-27,C30722,Desk,5,266.78,274 Main St,Gift Card,Cancelled,TRK52088168,5,,Email,1333.9 +ORD200975,2023-05-18,C70529,Desk,1,105.92,974 Main St,Gift Card,Returned,TRK82165408,6,SAVE10,Email,105.92 +ORD200976,2024-04-04,C18984,Tablet,3,589.3,650 Main St,Credit Card,Returned,TRK49298239,6,WINTER15,Referral,1767.9 +ORD200977,2023-01-28,C85841,Chair,4,649.47,608 Main St,Cash,Pending,TRK99820544,8,SAVE10,Google,2597.88 +ORD200978,2024-06-25,C41508,Printer,4,107.49,993 Main St,Cash,Delivered,TRK61047536,5,,Google,429.96 +ORD200979,2023-05-31,C75018,Monitor,3,669.06,299 Main St,Cash,Delivered,TRK51794806,7,SAVE10,Facebook,2007.18 +ORD200980,2023-10-14,C84320,Chair,3,69.65,107 Main St,Cash,Delivered,TRK81093218,7,WINTER15,Instagram,208.95 +ORD200981,2023-11-26,C12609,Phone,4,136.83,490 Main St,Debit Card,Pending,TRK56379337,8,SAVE10,Email,547.32 +ORD200982,2024-09-06,C64935,Monitor,1,304.11,707 Main St,Gift Card,Shipped,TRK42969065,2,SAVE10,Referral,304.11 +ORD200983,2024-11-24,C67528,Monitor,4,296.28,110 Main St,Gift Card,Shipped,TRK60865210,5,SAVE10,Email,1185.12 +ORD200984,2025-02-28,C44176,Desk,1,77.64,706 Main St,Credit Card,Shipped,TRK68704764,1,FREESHIP,Facebook,77.64 +ORD200985,2024-07-20,C92788,Desk,1,243.71,948 Main St,Gift Card,Delivered,TRK83835361,6,SAVE10,Google,243.71 +ORD200986,2024-09-07,C69213,Laptop,4,644.96,533 Main St,Credit Card,Pending,TRK67837331,7,FREESHIP,Email,2579.84 +ORD200987,2025-06-05,C67387,Phone,5,283.73,436 Main St,Gift Card,Pending,TRK54120003,8,FREESHIP,Instagram,1418.65 +ORD200988,2025-02-04,C90318,Desk,2,629.56,818 Main St,Gift Card,Cancelled,TRK52765043,5,WINTER15,Instagram,1259.12 +ORD200989,2023-03-23,C49995,Laptop,4,246.11,559 Main St,Credit Card,Pending,TRK33212013,4,SAVE10,Instagram,984.44 +ORD200990,2023-11-19,C52313,Phone,2,418.26,913 Main St,Debit Card,Pending,TRK67368559,2,SAVE10,Google,836.52 +ORD200991,2024-05-09,C10211,Desk,5,127.18,598 Main St,Debit Card,Cancelled,TRK68938335,10,FREESHIP,Google,635.9 +ORD200992,2024-08-27,C97907,Printer,3,586.21,933 Main St,Gift Card,Pending,TRK89637569,4,WINTER15,Referral,1758.63 +ORD200993,2024-04-06,C61384,Monitor,3,267.45,576 Main St,Gift Card,Delivered,TRK33323210,5,WINTER15,Instagram,802.35 +ORD200994,2024-06-27,C27613,Tablet,4,615.65,971 Main St,Debit Card,Delivered,TRK63701318,9,WINTER15,Google,2462.6 +ORD200995,2023-11-18,C99271,Monitor,2,113.29,959 Main St,Cash,Pending,TRK87832736,5,SAVE10,Facebook,226.58 +ORD200996,2024-04-28,C28648,Monitor,4,473.86,101 Main St,Debit Card,Delivered,TRK92240846,7,SAVE10,Facebook,1895.44 +ORD200997,2023-11-27,C26210,Laptop,3,444.75,805 Main St,Cash,Delivered,TRK40616861,6,SAVE10,Facebook,1334.25 +ORD200998,2023-05-19,C90350,Phone,2,183.67,783 Main St,Debit Card,Cancelled,TRK22824230,6,SAVE10,Google,367.34 +ORD200999,2023-12-24,C61957,Printer,1,483.38,652 Main St,Cash,Pending,TRK43983841,6,FREESHIP,Google,483.38 +ORD201000,2023-06-21,C90132,Printer,5,260.93,582 Main St,Online,Delivered,TRK52664903,9,SAVE10,Email,1304.65 +ORD201001,2023-12-08,C31371,Printer,2,253.68,122 Main St,Gift Card,Shipped,TRK19554327,6,,Referral,507.36 +ORD201002,2025-06-19,C83911,Tablet,4,699.88,944 Main St,Cash,Pending,TRK33188106,5,WINTER15,Referral,2799.52 +ORD201003,2023-01-11,C84700,Printer,5,319.97,582 Main St,Cash,Shipped,TRK14706969,7,SAVE10,Google,1599.85 +ORD201004,2025-06-09,C87529,Chair,4,246.91,296 Main St,Online,Pending,TRK15739505,8,SAVE10,Referral,987.64 +ORD201005,2023-03-02,C38065,Printer,3,392.85,426 Main St,Credit Card,Returned,TRK11448295,6,,Google,1178.55 +ORD201006,2024-05-27,C27435,Tablet,5,420.98,860 Main St,Cash,Delivered,TRK91458233,7,SAVE10,Facebook,2104.9 +ORD201007,2024-03-20,C46651,Monitor,2,73.26,839 Main St,Cash,Pending,TRK60444502,4,WINTER15,Facebook,146.52 +ORD201008,2023-01-13,C62557,Monitor,3,410.88,257 Main St,Cash,Delivered,TRK12742366,8,FREESHIP,Instagram,1232.64 +ORD201009,2023-09-02,C54494,Tablet,2,176.46,696 Main St,Credit Card,Delivered,TRK95958645,2,FREESHIP,Email,352.92 +ORD201010,2023-03-31,C33729,Monitor,3,659.57,533 Main St,Credit Card,Cancelled,TRK35649833,6,SAVE10,Email,1978.71 +ORD201011,2024-12-03,C47823,Phone,2,478.36,654 Main St,Online,Shipped,TRK22271097,3,,Google,956.72 +ORD201012,2024-12-03,C84570,Printer,4,30.05,301 Main St,Online,Returned,TRK12551882,6,,Facebook,120.2 +ORD201013,2025-04-26,C91123,Laptop,4,300.56,842 Main St,Cash,Cancelled,TRK49568409,9,FREESHIP,Facebook,1202.24 +ORD201014,2024-02-04,C92548,Tablet,5,226.45,160 Main St,Debit Card,Returned,TRK21682892,6,FREESHIP,Email,1132.25 +ORD201015,2024-01-26,C97454,Printer,2,349.4,892 Main St,Online,Shipped,TRK73249329,2,SAVE10,Instagram,698.8 +ORD201016,2023-12-29,C20257,Tablet,5,268.78,669 Main St,Debit Card,Delivered,TRK62135578,7,WINTER15,Email,1343.9 +ORD201017,2024-08-25,C51694,Chair,2,680.85,953 Main St,Gift Card,Delivered,TRK83122112,6,FREESHIP,Referral,1361.7 +ORD201018,2023-07-08,C77499,Laptop,3,182.48,209 Main St,Cash,Delivered,TRK20703086,3,,Instagram,547.44 +ORD201019,2024-04-06,C28386,Desk,1,277.09,293 Main St,Cash,Returned,TRK32954229,2,SAVE10,Referral,277.09 +ORD201020,2024-04-22,C50211,Tablet,2,26.5,312 Main St,Online,Delivered,TRK47787981,3,SAVE10,Instagram,53 +ORD201021,2023-10-23,C74519,Phone,3,315.27,309 Main St,Credit Card,Cancelled,TRK97351945,4,SAVE10,Email,945.81 +ORD201022,2025-02-24,C19071,Tablet,3,450.98,396 Main St,Credit Card,Shipped,TRK66537096,8,SAVE10,Referral,1352.94 +ORD201023,2024-09-23,C65251,Laptop,5,233.67,291 Main St,Cash,Shipped,TRK32059025,10,,Referral,1168.35 +ORD201024,2024-01-29,C90612,Chair,3,367.75,731 Main St,Cash,Pending,TRK93022878,7,FREESHIP,Facebook,1103.25 +ORD201025,2025-05-17,C28406,Chair,1,23.53,174 Main St,Gift Card,Delivered,TRK98841457,2,FREESHIP,Instagram,23.53 +ORD201026,2023-05-01,C55454,Monitor,1,677.48,807 Main St,Online,Delivered,TRK13281370,1,WINTER15,Facebook,677.48 +ORD201027,2024-05-21,C93467,Laptop,4,554.83,983 Main St,Cash,Returned,TRK77377373,6,,Google,2219.32 +ORD201028,2023-02-17,C60042,Desk,4,440.31,610 Main St,Cash,Cancelled,TRK84651559,6,,Instagram,1761.24 +ORD201029,2025-03-01,C44733,Desk,1,87.06,851 Main St,Credit Card,Shipped,TRK41500198,4,FREESHIP,Email,87.06 +ORD201030,2023-10-02,C61773,Phone,4,245.28,176 Main St,Credit Card,Delivered,TRK12936357,6,WINTER15,Email,981.12 +ORD201031,2023-02-28,C59183,Phone,5,664.51,136 Main St,Debit Card,Pending,TRK18129706,8,SAVE10,Email,3322.55 +ORD201032,2023-04-20,C26188,Chair,1,618.68,990 Main St,Online,Delivered,TRK61634201,6,WINTER15,Referral,618.68 +ORD201033,2024-12-24,C20338,Monitor,1,370.85,331 Main St,Gift Card,Delivered,TRK30654048,2,FREESHIP,Referral,370.85 +ORD201034,2024-06-16,C84524,Printer,4,517.98,766 Main St,Cash,Cancelled,TRK76751888,8,FREESHIP,Facebook,2071.92 +ORD201035,2023-11-12,C70315,Laptop,4,506.11,911 Main St,Cash,Cancelled,TRK97732085,5,,Referral,2024.44 +ORD201036,2024-05-31,C98278,Phone,3,413.83,552 Main St,Gift Card,Shipped,TRK49684737,8,SAVE10,Facebook,1241.49 +ORD201037,2023-12-13,C32347,Printer,1,249.81,408 Main St,Cash,Pending,TRK54073964,1,SAVE10,Google,249.81 +ORD201038,2025-03-15,C77961,Tablet,3,362.53,422 Main St,Debit Card,Returned,TRK28969024,5,,Facebook,1087.59 +ORD201039,2025-06-28,C49137,Desk,2,299.23,177 Main St,Credit Card,Cancelled,TRK79362428,2,WINTER15,Instagram,598.46 +ORD201040,2023-11-15,C13169,Tablet,1,536.07,932 Main St,Debit Card,Delivered,TRK66288666,5,FREESHIP,Google,536.07 +ORD201041,2023-02-11,C21167,Monitor,4,558.9,948 Main St,Gift Card,Shipped,TRK97737564,9,WINTER15,Google,2235.6 +ORD201042,2024-12-09,C59724,Tablet,2,409.75,414 Main St,Debit Card,Shipped,TRK67878272,2,WINTER15,Facebook,819.5 +ORD201043,2025-01-11,C43965,Tablet,2,179.96,675 Main St,Gift Card,Shipped,TRK94346739,5,,Instagram,359.92 +ORD201044,2025-06-22,C63018,Printer,1,38.49,215 Main St,Credit Card,Delivered,TRK52335337,4,FREESHIP,Referral,38.49 +ORD201045,2024-09-20,C11893,Laptop,5,316.4,671 Main St,Gift Card,Returned,TRK72012758,7,,Email,1582 +ORD201046,2024-10-07,C85421,Tablet,3,547.15,466 Main St,Online,Shipped,TRK16524006,4,WINTER15,Instagram,1641.45 +ORD201047,2023-06-23,C81726,Chair,4,540.34,394 Main St,Gift Card,Shipped,TRK69872994,6,WINTER15,Referral,2161.36 +ORD201048,2024-09-09,C57601,Monitor,4,73.65,889 Main St,Debit Card,Shipped,TRK21153699,9,,Google,294.6 +ORD201049,2024-07-18,C60575,Desk,5,391.86,587 Main St,Credit Card,Shipped,TRK44468232,6,,Instagram,1959.3 +ORD201050,2023-08-20,C70659,Laptop,5,69.7,722 Main St,Online,Returned,TRK49663597,9,,Instagram,348.5 +ORD201051,2025-03-05,C35043,Monitor,5,26.43,820 Main St,Gift Card,Shipped,TRK65097450,5,FREESHIP,Facebook,132.15 +ORD201052,2023-09-11,C12301,Tablet,1,531.74,493 Main St,Online,Shipped,TRK25145796,1,WINTER15,Google,531.74 +ORD201053,2024-09-15,C32798,Phone,2,496.62,679 Main St,Online,Pending,TRK37375451,2,SAVE10,Instagram,993.24 +ORD201054,2023-11-29,C42949,Printer,1,660.66,447 Main St,Debit Card,Delivered,TRK46415143,3,WINTER15,Instagram,660.66 +ORD201055,2023-10-23,C10787,Monitor,4,274.82,932 Main St,Debit Card,Delivered,TRK91512567,9,WINTER15,Email,1099.28 +ORD201056,2024-06-14,C26152,Phone,2,486.35,790 Main St,Online,Pending,TRK49382455,6,SAVE10,Referral,972.7 +ORD201057,2024-09-24,C46210,Laptop,3,428.88,535 Main St,Debit Card,Shipped,TRK81611937,3,WINTER15,Facebook,1286.64 +ORD201058,2023-09-08,C32943,Desk,2,412.14,127 Main St,Credit Card,Returned,TRK26949106,2,FREESHIP,Instagram,824.28 +ORD201059,2024-09-22,C73629,Desk,1,265.64,601 Main St,Credit Card,Returned,TRK11492924,3,WINTER15,Instagram,265.64 +ORD201060,2024-05-07,C38024,Tablet,2,273.43,824 Main St,Cash,Shipped,TRK93370912,7,WINTER15,Referral,546.86 +ORD201061,2025-01-29,C25445,Laptop,5,131.7,830 Main St,Cash,Shipped,TRK12402431,8,FREESHIP,Google,658.5 +ORD201062,2023-08-23,C13501,Chair,5,85.52,301 Main St,Gift Card,Cancelled,TRK65149372,5,,Facebook,427.6 +ORD201063,2024-06-19,C42108,Desk,2,320.68,336 Main St,Credit Card,Shipped,TRK58407918,5,FREESHIP,Referral,641.36 +ORD201064,2025-02-12,C32121,Laptop,4,198.81,654 Main St,Cash,Returned,TRK96074264,9,FREESHIP,Referral,795.24 +ORD201065,2023-10-30,C47778,Printer,5,666.8,488 Main St,Debit Card,Delivered,TRK79504329,7,SAVE10,Referral,3334 +ORD201066,2023-12-20,C10791,Desk,1,355.09,674 Main St,Debit Card,Cancelled,TRK20321248,5,SAVE10,Instagram,355.09 +ORD201067,2023-06-06,C78959,Phone,2,316.2,384 Main St,Online,Returned,TRK37426359,2,,Instagram,632.4 +ORD201068,2024-08-03,C29914,Laptop,1,133.39,469 Main St,Debit Card,Shipped,TRK22073506,2,SAVE10,Referral,133.39 +ORD201069,2023-02-25,C70506,Monitor,1,454.23,255 Main St,Gift Card,Returned,TRK12518384,3,,Facebook,454.23 +ORD201070,2024-09-06,C46873,Desk,4,491.29,496 Main St,Debit Card,Pending,TRK10926575,6,,Email,1965.16 +ORD201071,2025-06-24,C94037,Phone,2,255.14,216 Main St,Cash,Shipped,TRK47536985,2,,Google,510.28 +ORD201072,2023-02-26,C88644,Monitor,1,392.61,977 Main St,Gift Card,Cancelled,TRK14900878,4,SAVE10,Referral,392.61 +ORD201073,2024-10-11,C69471,Tablet,4,362.06,294 Main St,Debit Card,Returned,TRK11107152,4,,Facebook,1448.24 +ORD201074,2024-05-10,C21437,Phone,1,222.73,120 Main St,Online,Returned,TRK81624772,4,,Google,222.73 +ORD201075,2024-08-31,C40949,Monitor,2,552.63,609 Main St,Debit Card,Delivered,TRK43066749,7,WINTER15,Instagram,1105.26 +ORD201076,2023-05-08,C99116,Laptop,4,686.61,176 Main St,Cash,Shipped,TRK52711973,6,,Referral,2746.44 +ORD201077,2025-03-07,C57861,Printer,3,305.16,115 Main St,Credit Card,Cancelled,TRK47775217,8,SAVE10,Referral,915.48 +ORD201078,2023-03-18,C62627,Desk,1,41.09,881 Main St,Online,Returned,TRK90060232,4,WINTER15,Email,41.09 +ORD201079,2024-06-20,C89979,Phone,5,634,144 Main St,Gift Card,Delivered,TRK99055909,8,,Email,3170 +ORD201080,2023-01-20,C70613,Laptop,5,464.74,438 Main St,Gift Card,Delivered,TRK33140293,7,,Referral,2323.7 +ORD201081,2023-04-21,C55636,Monitor,4,425.6,494 Main St,Credit Card,Pending,TRK85897054,5,FREESHIP,Google,1702.4 +ORD201082,2023-10-06,C96595,Chair,3,573.22,177 Main St,Debit Card,Pending,TRK59779174,5,SAVE10,Email,1719.66 +ORD201083,2024-07-09,C68508,Chair,1,123.28,895 Main St,Credit Card,Delivered,TRK98960285,3,SAVE10,Email,123.28 +ORD201084,2023-01-08,C45175,Phone,1,70.82,128 Main St,Gift Card,Pending,TRK41792296,1,WINTER15,Instagram,70.82 +ORD201085,2023-05-21,C28049,Printer,2,646.69,404 Main St,Debit Card,Shipped,TRK91426444,7,WINTER15,Instagram,1293.38 +ORD201086,2023-12-23,C46967,Tablet,2,513.42,401 Main St,Online,Pending,TRK91439791,5,WINTER15,Instagram,1026.84 +ORD201087,2025-03-23,C84134,Laptop,4,693.07,530 Main St,Online,Shipped,TRK48659380,8,SAVE10,Instagram,2772.28 +ORD201088,2023-11-30,C49831,Desk,3,491.43,213 Main St,Gift Card,Shipped,TRK21232601,6,WINTER15,Instagram,1474.29 +ORD201089,2025-03-15,C13324,Tablet,2,599.74,440 Main St,Gift Card,Shipped,TRK66967997,2,,Instagram,1199.48 +ORD201090,2023-02-25,C61225,Monitor,2,650.25,996 Main St,Gift Card,Returned,TRK37022954,6,,Instagram,1300.5 +ORD201091,2024-10-08,C16400,Laptop,3,209.48,123 Main St,Debit Card,Pending,TRK57771859,4,,Email,628.44 +ORD201092,2023-08-21,C38642,Laptop,5,209.2,930 Main St,Debit Card,Delivered,TRK47744396,6,WINTER15,Email,1046 +ORD201093,2023-06-09,C86773,Phone,4,197.36,557 Main St,Gift Card,Returned,TRK22612240,9,FREESHIP,Instagram,789.44 +ORD201094,2023-06-28,C66093,Printer,4,648.91,615 Main St,Credit Card,Shipped,TRK54950785,6,SAVE10,Instagram,2595.64 +ORD201095,2024-04-23,C33051,Phone,2,441.54,397 Main St,Online,Delivered,TRK92929755,2,SAVE10,Email,883.08 +ORD201096,2025-05-03,C18169,Tablet,2,464.92,782 Main St,Debit Card,Returned,TRK49482923,2,,Facebook,929.84 +ORD201097,2024-12-26,C81370,Monitor,5,506.45,344 Main St,Gift Card,Shipped,TRK99682998,7,WINTER15,Google,2532.25 +ORD201098,2023-06-17,C91103,Monitor,4,255.86,155 Main St,Credit Card,Delivered,TRK91653000,7,,Email,1023.44 +ORD201099,2024-09-19,C21953,Laptop,2,125.23,272 Main St,Cash,Cancelled,TRK60774796,3,FREESHIP,Email,250.46 +ORD201100,2023-08-17,C15146,Laptop,5,38.11,428 Main St,Debit Card,Cancelled,TRK79790530,6,WINTER15,Instagram,190.55 +ORD201101,2025-06-08,C43546,Monitor,3,161.97,904 Main St,Cash,Pending,TRK85871121,4,SAVE10,Email,485.91 +ORD201102,2024-06-03,C98474,Chair,4,347.17,997 Main St,Debit Card,Shipped,TRK86192984,8,,Instagram,1388.68 +ORD201103,2023-04-24,C90292,Laptop,4,276.32,129 Main St,Online,Delivered,TRK26270357,5,,Google,1105.28 +ORD201104,2024-07-25,C17075,Tablet,4,314.76,850 Main St,Online,Shipped,TRK63547510,8,,Instagram,1259.04 +ORD201105,2024-01-08,C12487,Tablet,3,475.69,884 Main St,Gift Card,Cancelled,TRK23324770,3,FREESHIP,Google,1427.07 +ORD201106,2023-03-12,C34555,Chair,1,372.8,903 Main St,Cash,Cancelled,TRK72859458,6,SAVE10,Facebook,372.8 +ORD201107,2025-06-30,C25110,Tablet,2,63.21,282 Main St,Online,Cancelled,TRK80963328,4,SAVE10,Google,126.42 +ORD201108,2023-03-20,C35136,Laptop,1,634.94,462 Main St,Online,Cancelled,TRK49753703,5,WINTER15,Instagram,634.94 +ORD201109,2024-04-08,C62277,Printer,4,77.47,474 Main St,Gift Card,Returned,TRK32026174,7,SAVE10,Instagram,309.88 +ORD201110,2024-02-25,C12472,Chair,3,84.31,912 Main St,Credit Card,Shipped,TRK36103184,3,SAVE10,Email,252.93 +ORD201111,2023-05-06,C24047,Monitor,4,234.45,362 Main St,Online,Cancelled,TRK91338580,9,FREESHIP,Instagram,937.8 +ORD201112,2023-10-13,C76929,Desk,1,356.81,563 Main St,Online,Delivered,TRK80694400,1,WINTER15,Instagram,356.81 +ORD201113,2023-03-19,C52914,Desk,4,209.99,168 Main St,Cash,Delivered,TRK80819053,8,,Google,839.96 +ORD201114,2023-03-16,C55164,Tablet,3,659.88,609 Main St,Gift Card,Cancelled,TRK79610967,3,,Google,1979.64 +ORD201115,2025-06-20,C70426,Laptop,2,336.32,562 Main St,Online,Returned,TRK89687816,3,,Google,672.64 +ORD201116,2023-10-14,C69149,Printer,2,531.49,562 Main St,Credit Card,Delivered,TRK61265132,7,WINTER15,Facebook,1062.98 +ORD201117,2024-05-20,C78684,Chair,3,588.44,858 Main St,Gift Card,Shipped,TRK95779073,8,WINTER15,Google,1765.32 +ORD201118,2024-05-24,C58168,Phone,3,251.48,359 Main St,Credit Card,Returned,TRK99102265,4,,Email,754.44 +ORD201119,2024-11-24,C99024,Laptop,1,684.65,250 Main St,Credit Card,Delivered,TRK24675988,1,FREESHIP,Email,684.65 +ORD201120,2025-05-10,C22919,Tablet,1,195.86,267 Main St,Online,Pending,TRK82416295,3,,Facebook,195.86 +ORD201121,2023-05-28,C98354,Phone,3,50.34,393 Main St,Gift Card,Returned,TRK43070888,3,FREESHIP,Instagram,151.02 +ORD201122,2023-06-07,C38840,Monitor,5,678.19,766 Main St,Online,Returned,TRK32496970,8,,Facebook,3390.95 +ORD201123,2023-04-14,C68936,Tablet,3,554.25,843 Main St,Debit Card,Shipped,TRK73163634,6,WINTER15,Referral,1662.75 +ORD201124,2023-05-09,C33744,Chair,4,576.87,888 Main St,Gift Card,Returned,TRK40245983,5,,Instagram,2307.48 +ORD201125,2023-10-16,C23555,Desk,4,408.36,156 Main St,Gift Card,Cancelled,TRK67210247,4,FREESHIP,Referral,1633.44 +ORD201126,2024-07-22,C34337,Phone,5,190.11,325 Main St,Cash,Delivered,TRK36195559,7,SAVE10,Google,950.55 +ORD201127,2025-03-15,C69396,Printer,3,602.75,920 Main St,Credit Card,Shipped,TRK33155049,6,SAVE10,Email,1808.25 +ORD201128,2023-08-17,C49198,Monitor,3,646.79,447 Main St,Cash,Cancelled,TRK10883354,5,WINTER15,Google,1940.37 +ORD201129,2023-06-11,C43911,Chair,4,418.71,239 Main St,Cash,Pending,TRK37495481,8,FREESHIP,Instagram,1674.84 +ORD201130,2025-02-16,C24347,Laptop,2,323.45,533 Main St,Credit Card,Returned,TRK27233265,5,FREESHIP,Instagram,646.9 +ORD201131,2024-07-18,C21043,Phone,1,694.5,195 Main St,Credit Card,Pending,TRK41691086,3,WINTER15,Facebook,694.5 +ORD201132,2024-12-02,C58858,Chair,2,337.32,948 Main St,Credit Card,Cancelled,TRK30406357,4,SAVE10,Email,674.64 +ORD201133,2024-04-09,C20670,Printer,2,467.91,432 Main St,Gift Card,Returned,TRK76731303,5,WINTER15,Facebook,935.82 +ORD201134,2024-06-08,C90993,Desk,4,38.28,950 Main St,Debit Card,Cancelled,TRK53964711,4,WINTER15,Facebook,153.12 +ORD201135,2023-12-28,C11473,Printer,2,73.41,562 Main St,Online,Shipped,TRK97793275,2,SAVE10,Google,146.82 +ORD201136,2023-09-24,C71899,Tablet,3,668.33,799 Main St,Gift Card,Pending,TRK34856025,4,WINTER15,Facebook,2004.99 +ORD201137,2024-07-29,C48577,Printer,4,410.21,841 Main St,Cash,Pending,TRK59911645,5,WINTER15,Instagram,1640.84 +ORD201138,2023-12-18,C13100,Desk,4,294.41,188 Main St,Debit Card,Pending,TRK55565668,4,,Instagram,1177.64 +ORD201139,2025-03-01,C70659,Chair,3,501.82,568 Main St,Gift Card,Cancelled,TRK28290825,4,FREESHIP,Email,1505.46 +ORD201140,2024-06-24,C49838,Printer,2,552.83,904 Main St,Credit Card,Cancelled,TRK38297718,3,,Referral,1105.66 +ORD201141,2025-02-16,C11998,Chair,3,498.66,382 Main St,Cash,Cancelled,TRK26707221,6,,Email,1495.98 +ORD201142,2024-08-23,C23405,Phone,4,695.1,484 Main St,Debit Card,Returned,TRK83678708,8,,Email,2780.4 +ORD201143,2023-04-03,C41132,Chair,1,381.61,114 Main St,Debit Card,Pending,TRK51040137,5,,Email,381.61 +ORD201144,2023-02-16,C88463,Desk,5,507.94,292 Main St,Online,Cancelled,TRK88749996,9,,Facebook,2539.7 +ORD201145,2025-05-12,C28152,Desk,3,571.53,821 Main St,Debit Card,Delivered,TRK59642814,6,FREESHIP,Facebook,1714.59 +ORD201146,2024-10-03,C36383,Monitor,5,421.44,286 Main St,Cash,Pending,TRK93336357,5,SAVE10,Instagram,2107.2 +ORD201147,2025-01-02,C19759,Chair,2,588.3,234 Main St,Online,Pending,TRK22515454,2,FREESHIP,Email,1176.6 +ORD201148,2024-06-25,C54886,Phone,1,355.15,442 Main St,Cash,Returned,TRK66241930,2,SAVE10,Email,355.15 +ORD201149,2024-07-25,C27305,Chair,2,695.29,957 Main St,Credit Card,Pending,TRK28789916,6,FREESHIP,Instagram,1390.58 +ORD201150,2023-02-20,C17921,Desk,4,302.65,119 Main St,Credit Card,Cancelled,TRK79291524,8,SAVE10,Referral,1210.6 +ORD201151,2023-01-29,C94381,Chair,2,608.04,962 Main St,Cash,Cancelled,TRK69804304,4,,Google,1216.08 +ORD201152,2023-11-09,C25162,Tablet,2,344.18,533 Main St,Credit Card,Shipped,TRK42183078,7,,Referral,688.36 +ORD201153,2024-12-16,C98317,Monitor,4,696.71,276 Main St,Debit Card,Shipped,TRK37172138,4,,Instagram,2786.84 +ORD201154,2025-06-11,C53631,Monitor,3,198.63,593 Main St,Cash,Pending,TRK67589167,8,SAVE10,Instagram,595.89 +ORD201155,2023-08-13,C41478,Printer,4,534.57,667 Main St,Credit Card,Delivered,TRK62068126,6,FREESHIP,Facebook,2138.28 +ORD201156,2023-07-19,C20512,Laptop,4,690.78,980 Main St,Credit Card,Shipped,TRK98234737,9,,Referral,2763.12 +ORD201157,2024-05-29,C25841,Monitor,3,301.55,242 Main St,Debit Card,Delivered,TRK21451375,5,FREESHIP,Google,904.65 +ORD201158,2023-04-20,C82781,Monitor,4,27.42,661 Main St,Debit Card,Pending,TRK20605418,4,SAVE10,Referral,109.68 +ORD201159,2024-02-23,C66112,Desk,4,466.7,874 Main St,Debit Card,Returned,TRK60955607,8,,Instagram,1866.8 +ORD201160,2024-09-04,C40466,Desk,1,541.64,449 Main St,Debit Card,Shipped,TRK70255168,5,SAVE10,Email,541.64 +ORD201161,2023-10-16,C32570,Phone,1,11.39,826 Main St,Cash,Cancelled,TRK35969968,6,WINTER15,Email,11.39 +ORD201162,2025-03-11,C29405,Phone,2,224.37,251 Main St,Debit Card,Delivered,TRK33125798,3,WINTER15,Referral,448.74 +ORD201163,2024-06-11,C30643,Laptop,3,306.29,966 Main St,Credit Card,Returned,TRK19477485,7,WINTER15,Instagram,918.87 +ORD201164,2024-01-08,C65890,Tablet,5,315.57,340 Main St,Debit Card,Delivered,TRK64530489,6,WINTER15,Email,1577.85 +ORD201165,2023-07-14,C36992,Chair,3,223.79,617 Main St,Debit Card,Pending,TRK63460217,3,,Google,671.37 +ORD201166,2023-07-31,C95568,Chair,3,324.47,971 Main St,Cash,Delivered,TRK37075292,4,WINTER15,Email,973.41 +ORD201167,2023-10-17,C17966,Printer,2,92.87,360 Main St,Credit Card,Pending,TRK31169396,5,FREESHIP,Facebook,185.74 +ORD201168,2023-04-08,C89559,Laptop,2,331.42,297 Main St,Credit Card,Delivered,TRK82838108,6,WINTER15,Google,662.84 +ORD201169,2024-12-23,C15849,Chair,1,525.43,643 Main St,Cash,Cancelled,TRK26794546,2,SAVE10,Instagram,525.43 +ORD201170,2023-08-03,C94257,Printer,2,697.19,762 Main St,Cash,Returned,TRK40220743,7,FREESHIP,Email,1394.38 +ORD201171,2023-08-28,C39911,Phone,4,518.4,699 Main St,Credit Card,Delivered,TRK80431998,7,SAVE10,Facebook,2073.6 +ORD201172,2025-02-04,C28828,Desk,3,131.96,745 Main St,Credit Card,Pending,TRK32550359,8,,Instagram,395.88 +ORD201173,2024-10-04,C82921,Monitor,1,208.36,703 Main St,Online,Shipped,TRK31079911,4,FREESHIP,Email,208.36 +ORD201174,2023-11-27,C50159,Printer,3,222.34,105 Main St,Credit Card,Returned,TRK53737452,5,WINTER15,Email,667.02 +ORD201175,2024-09-10,C62512,Printer,3,91.74,368 Main St,Debit Card,Returned,TRK24139954,8,FREESHIP,Referral,275.22 +ORD201176,2023-08-13,C39260,Tablet,2,213.83,374 Main St,Debit Card,Cancelled,TRK55587314,2,WINTER15,Email,427.66 +ORD201177,2023-04-27,C23917,Printer,1,127.55,433 Main St,Cash,Shipped,TRK44434536,3,SAVE10,Referral,127.55 +ORD201178,2024-09-08,C65107,Monitor,1,70.24,456 Main St,Credit Card,Cancelled,TRK10261578,4,FREESHIP,Google,70.24 +ORD201179,2023-01-08,C84630,Laptop,5,518.55,907 Main St,Credit Card,Cancelled,TRK48054997,6,WINTER15,Instagram,2592.75 +ORD201180,2023-10-31,C42235,Chair,4,298.36,722 Main St,Debit Card,Pending,TRK49379882,8,FREESHIP,Google,1193.44 +ORD201181,2023-07-27,C70246,Desk,3,158.74,293 Main St,Online,Pending,TRK45708320,7,FREESHIP,Instagram,476.22 +ORD201182,2025-06-14,C18473,Chair,2,420.29,700 Main St,Gift Card,Returned,TRK97834202,3,SAVE10,Google,840.58 +ORD201183,2023-04-05,C12607,Desk,1,281.52,460 Main St,Gift Card,Shipped,TRK83653396,6,WINTER15,Referral,281.52 +ORD201184,2023-09-27,C10222,Laptop,1,204.08,979 Main St,Gift Card,Returned,TRK86297895,4,,Google,204.08 +ORD201185,2024-07-08,C77344,Chair,1,343.31,777 Main St,Gift Card,Returned,TRK20605055,6,SAVE10,Google,343.31 +ORD201186,2023-11-18,C65497,Monitor,1,163.32,676 Main St,Cash,Shipped,TRK83702761,6,WINTER15,Facebook,163.32 +ORD201187,2024-03-13,C26340,Desk,2,184.6,562 Main St,Gift Card,Delivered,TRK59962703,7,WINTER15,Email,369.2 +ORD201188,2023-10-07,C75619,Printer,2,371.29,924 Main St,Gift Card,Shipped,TRK23086941,5,WINTER15,Facebook,742.58 +ORD201189,2024-08-17,C96136,Tablet,5,389.22,149 Main St,Cash,Cancelled,TRK60856682,7,,Referral,1946.1 +ORD201190,2025-06-08,C46886,Desk,3,616.39,754 Main St,Credit Card,Shipped,TRK82791646,6,FREESHIP,Instagram,1849.17 +ORD201191,2025-02-10,C44148,Desk,4,376.43,809 Main St,Gift Card,Pending,TRK67872709,5,WINTER15,Instagram,1505.72 +ORD201192,2024-02-28,C72007,Chair,3,432.85,999 Main St,Online,Pending,TRK16240916,4,,Instagram,1298.55 +ORD201193,2025-06-16,C45104,Tablet,1,687.89,348 Main St,Cash,Returned,TRK38559816,1,FREESHIP,Email,687.89 +ORD201194,2023-11-19,C29885,Printer,3,189.44,725 Main St,Cash,Pending,TRK62067865,4,FREESHIP,Email,568.32 +ORD201195,2024-06-20,C21126,Desk,1,107.04,392 Main St,Credit Card,Cancelled,TRK38009181,6,FREESHIP,Google,107.04 +ORD201196,2024-03-04,C20095,Monitor,2,662.53,778 Main St,Online,Cancelled,TRK69207593,5,,Facebook,1325.06 +ORD201197,2023-07-13,C79674,Tablet,2,436.84,275 Main St,Online,Delivered,TRK88039356,2,FREESHIP,Instagram,873.68 +ORD201198,2024-08-22,C64753,Chair,4,262.52,509 Main St,Debit Card,Cancelled,TRK71683331,4,WINTER15,Instagram,1050.08 +ORD201199,2023-06-11,C57502,Tablet,4,560.58,201 Main St,Gift Card,Returned,TRK51116746,6,SAVE10,Referral,2242.32 \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/Analysis.htm b/agentic-sap-workflows/Samples/Analysis.htm new file mode 100644 index 0000000..d880615 --- /dev/null +++ b/agentic-sap-workflows/Samples/Analysis.htm @@ -0,0 +1,1011 @@ + + + + + + + + + + + + + + + + + + + +
+ +

From: Emmanuel +Abram-Profeta

+ +

Sent: Thursday, +January 22, 2026 5:45 PM

+ +

To: Emmanuel +Abram-Profeta

+ +

Subject: Analysis

+ +

 

+ +

Analysis of Trends +and Predictions

+ +

Data Cleaned: +Orders Excluded (ORD200000, ORD200001, ORD200002, ORD200007, ORD200008, +ORD200015)

+ +
+ +
+ +
+ +

Key Trends

+ +

1. Order Status +Trend (Shipped, Delivered, Returned, Cancelled, Pending): - Shipped +Orders: - Majority of the orders were successfully shipped +(e.g., phones, desks), indicating efficient logistics for in-stock products. - Returned +Orders: - Consumer electronics like monitors, laptops, and +tablets had higher tendencies to be returned. - Cancelled Orders: +- These were minimal, typically seen for higher-price items like tablets and +phones. - Pending Orders: - A few orders, especially mid-2024 and +early 2023, were in pending status. This points to potential payment or +logistical bottlenecks during this period.

+ +

2. Product Trends:
+- Most Frequently Purchased Products:
+- Monitor, Phones, and Tablets accounted for the highest +demand, purchased in bulk quantities (e.g., monitors purchased in quantities of +3-5 per order).
+- High-ticket Items:
+- Computers (e.g., laptops) and printers contributed disproportionately high +revenues despite being ordered in smaller quantities.

+ +

3. Price Trends:
+- High-ticket items like tablets ($625.97, $550.68) and laptops ($664.42) drive +significant revenue.
+- Accessories, such as chairs or monitors with lower price points +($49.14$570.62), were sold in bulk but contributed less per order.
+- Discounts (e.g., coupons like SAVE10 or FREESHIP) +likely stimulated these sales volumes, as seen frequently throughout 20232024.

+ +

4. Customer Payment Methods:
+- Credit cards and debit cards dominate the payment methods (~70% of +transactions).
+- There's minimal use of Gift Cards or Cash for +transactional purposes.

+ +

5. Seasonality & Time Patterns:
+- High demand observed around October 2023 and late Q3/Q4 periods, +which aligns with pre-holiday and holiday seasons.
+- Orders peak around August and October, potentially tied to back-to-school +shopping and year-end discounts.

+ +

6. Referral Sources:
+- Social Media (Instagram and Facebook) generated +significant customer referrals.
+- Other notable sources included Email campaigns and Google search, +reflecting effective marketing efforts across digital channels.

+ +
+ +
+ +
+ +

Predictions:

+ +


+1. Product Demand:
+- Phones and Tablets will continue to drive demand as +customers maintain high interest in these portable electronics. It's likely +that Monitors will also experience sustained growth due to +work-from-home and gaming trends.
+- Laptops may contribute to large sales spikes during +back-to-school sales in August 2024 and the holiday season.

+ +

2. Order Status Improvements Needed:
+- Returns and cancellations primarily involve laptops and tablets, +signaling a potential dissatisfaction with either product quality or mismatch +expectations. Improving these areas (e.g., refined product descriptions) can +minimize cancellations/returns.

+ +

3. Discount Strategies:
+- Coupons like SAVE10 or FREESHIP have shown effectiveness +in driving bulk purchases for low-to-mid-priced items; marketing efforts using +similar coupons should yield positive returns.
+- Consider introducing seasonal coupons (e.g., WINTER15) +around holiday periods to boost sales momentum.

+ +

4. Revenue Forecast (20242025):
+- Based on current patterns, 2024 Q3/Q4 sales revenues are expected to rise, +driven by phone and monitor sales.
+- Continued growth can be expected if marketing pushes emphasize product +categories already performing well.

+ +

5. Shipping and Logistics:
+- Efficient performance in shipments should foster repeat customers. However, pending and +returned orders should be minimized through proactive customer +service interventions.

+ +

6. Seasonal Marketing Push:
+- Focus advertisements on prominent Referral Sources: Instagram and Email. +Crafting targeted campaigns for high-demand periods in Q3 and Q4 of each year +will maximize engagement and conversion rates.

+ +
+ + + + diff --git a/agentic-sap-workflows/Samples/Analysis2.htm b/agentic-sap-workflows/Samples/Analysis2.htm new file mode 100644 index 0000000..e092855 --- /dev/null +++ b/agentic-sap-workflows/Samples/Analysis2.htm @@ -0,0 +1,953 @@ + + + + + + + + + + + + + + + + + + + +
+ +

From: Emmanuel +Abram-Profeta

+ +

Sent: Saturday, +February 14, 2026 11:36 AM

+ +

To: Emmanuel +Abram-Profeta

+ +

Subject: Analysis

+ +

 

+ +

After excluding the specified `OrderIDs`, the remaining data in the dataset +includes the orders with the following observations. Below is an analysis based +on the filtered dataset:

+ +

Cleaned Dataset:

+ +


+| OrderID | Date | CustomerID | Product | Quantity | UnitPrice | +ShippingAddress | PaymentMethod | OrderStatus | TrackingNumber | ItemsInCart | +CouponCode | ReferralSource | TotalPrice |
+|-------------|------------|------------|-----------|----------|-----------|-----------------|---------------|-------------|----------------|-------------|------------|----------------|------------|
+| ORD200003 | 10/15/2023 | C33540 | Chair | 1 | 273.19 | 275 Main St | Debit +Card | Returned | TRK62788070 | 5 | SAVE10 | Facebook | 273.19 |
+| ORD200004 | 5/8/2025 | C81840 | Printer | 4 | 626.01 | 668 Main St | Online | +Delivered | TRK29241424 | 8 | SAVE10 | Email | 2504.04 |
+| ORD200005 | 10/23/2023 | C37249 | Phone | 2 | 245.86 | 934 Main St | Credit +Card | Shipped | TRK72976927 | 4 | SAVE10 | Instagram | 491.72 |
+| ORD200009 | 11/21/2023 | C31946 | Desk | 4 | 509.38 | 102 Main St | Credit +Card | Shipped | TRK33478363 | 6 | SAVE10 | Google | 2037.52 |
+| ORD200010 | 12/29/2023 | C43443 | Tablet | 5 | 625.97 | 333 Main St | Credit +Card | Returned | TRK98859248 | 9 | WINTER15 | Instagram | 3129.85 |
+| ORD200011 | 2/17/2024 | C93861 | Monitor | 3 | 49.14 | 831 Main St | Online | +Returned | TRK48234646 | 7 | SAVE10 | Email | 147.42 |
+| ORD200012 | 10/15/2024 | C38785 | Monitor | 2 | 180.5 | 179 Main St | Debit +Card | Pending | TRK20419991 | 6 | FREESHIP | Referral | 361 |
+| ORD200013 | 8/30/2023 | C88348 | Laptop | 3 | 201.49 | 903 Main St | Credit +Card | Returned | TRK81913874 | 4 | FREESHIP | Facebook | 604.47 |
+| ORD200014 | 3/27/2023 | C98474 | Tablet | 2 | 393.33 | 980 Main St | Debit +Card | Pending | TRK79186539 | 3 | SAVE10 | Instagram | 786.66 |

+ +
+ +
+ +
+ +

Observed Trends:

+ +


+1. Order Status Distribution:
+- Delivered: 1 order
+- Shipped: 2 orders
+- Returned: 4 orders
+- Pending: 2 orders
+- There is a relatively high proportion (44.44%) of orders that were returned. +This could indicate potential issues with product quality, customer +satisfaction, or other logistical issues.
+
+2. Top Products Ordered:
+- Most Ordered Product Categories:
+- Tablets and Monitors are popular products with 7 units +ordered.
+- Phones and Desks are also moderately popular with 6 and +4 units ordered, respectively.
+
+3. Popular Coupon Codes and Referral Sources:
+- The most used coupon code is "SAVE10," accounting for 6/9 (~67%) of +all coupons used.
+- Referral sources indicate that Instagram and Facebook are key marketing channels, +with 2 and 2 respective referrals found in this dataset.

+ +

4. Payment Method Trends:
+- Credit Card: 4 orders
+- Debit Card: 3 orders
+- Online: 2 orders
+- Others: No Cash purchases were made after excluding certain orders; +indicating low cash transaction preference.
+
+5. Total Revenue:
+- The revenue from orders amounted to $9,335.90.

+ +
+ +
+ +
+ +

Predictions and +Insights:

+ +


+1. The relatively high return rate (44.44%) indicates +that efforts might be needed to assess product quality or better match customer +expectations with reality (e.g., product descriptions or images).
+2. Instagram, Email, and Facebook referrals are responsible +for most traffic. Focusing marketing campaigns on these platforms continues to +be a good strategy to attract customers.
+3. The SAVE10 coupon code is the most popular among customers. +Expanding the usage of similar promotions like SAVE15 or introducing +customer-specific loyalty programs could drive more sales.
+4. The presence of returned chairs, tablets, laptops, and monitors suggests potential +issues with these products. Detailed user surveys or longer +return policies may improve customer retention.

+ +
+ +
+ +
+ +

Would +you like me to further refine the analysis based on specific metrics (e.g., +profitability per product, customer segmentation)? Let me know!

+ +
+ + + + diff --git a/agentic-sap-workflows/Samples/Analysis2_files/colorschememapping.xml b/agentic-sap-workflows/Samples/Analysis2_files/colorschememapping.xml new file mode 100644 index 0000000..6a0069c --- /dev/null +++ b/agentic-sap-workflows/Samples/Analysis2_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/Analysis2_files/filelist.xml b/agentic-sap-workflows/Samples/Analysis2_files/filelist.xml new file mode 100644 index 0000000..dde9ea0 --- /dev/null +++ b/agentic-sap-workflows/Samples/Analysis2_files/filelist.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/Analysis2_files/themedata.thmx b/agentic-sap-workflows/Samples/Analysis2_files/themedata.thmx new file mode 100644 index 0000000..f3afc8f Binary files /dev/null and b/agentic-sap-workflows/Samples/Analysis2_files/themedata.thmx differ diff --git a/agentic-sap-workflows/Samples/Analysis_files/colorschememapping.xml b/agentic-sap-workflows/Samples/Analysis_files/colorschememapping.xml new file mode 100644 index 0000000..6a0069c --- /dev/null +++ b/agentic-sap-workflows/Samples/Analysis_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/Analysis_files/filelist.xml b/agentic-sap-workflows/Samples/Analysis_files/filelist.xml new file mode 100644 index 0000000..ad84124 --- /dev/null +++ b/agentic-sap-workflows/Samples/Analysis_files/filelist.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/Analysis_files/themedata.thmx b/agentic-sap-workflows/Samples/Analysis_files/themedata.thmx new file mode 100644 index 0000000..f3afc8f Binary files /dev/null and b/agentic-sap-workflows/Samples/Analysis_files/themedata.thmx differ diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data.htm b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data.htm new file mode 100644 index 0000000..88b7970 --- /dev/null +++ b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data.htm @@ -0,0 +1,1256 @@ + + + + + + + + + + + + + + + + + + + +
+ +

From: Emmanuel +Abram-Profeta

+ +

Sent: Thursday, +January 22, 2026 5:44 PM

+ +

To: Emmanuel +Abram-Profeta

+ +

Subject: CSV +document from SAP contains invalid data

+ +

 

+ +

Validation Summary

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Validation results based + on rules: PaymentMethod exists, PaymentMethod not "Cash", + OrderStatus != "Cancelled", CouponCode non-empty, OrderID unique + (Date not validated)

+
+

OrderID

+
+

PaymentMethod exists

+
+

PaymentMethod not + "Cash"

+
+

OrderStatus != + "Cancelled"

+
+

CouponCode non-empty

+
+

OrderID unique

+
+

Overall

+
+

Notes

+
+

ORD200000

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Fail

+
+

Fail

+
+

Duplicate + OrderID appears twice.

+
+

ORD200001

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Fail

+
+

Fail

+
+

Duplicate + OrderID appears twice.

+
+

ORD200002

+
+

Pass

+
+

Pass

+
+

Fail

+
+

Pass

+
+

Fail

+
+

Fail

+
+

OrderStatus + is "Cancelled" and OrderID duplicated.

+
+

ORD200003

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200004

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200005

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200006

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200007

+
+

Pass

+
+

Fail

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Fail

+
+

PaymentMethod + cannot be "Cash".

+
+

ORD200008

+
+

Pass

+
+

Pass

+
+

Fail

+
+

Fail

+
+

Pass

+
+

Fail

+
+

OrderStatus + is "Cancelled" and CouponCode is empty.

+
+

ORD200009

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200010

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200011

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200012

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200013

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200014

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

Pass

+
+

ORD200015

+
+

Pass

+
+

Fail

+
+

Pass

+
+

Fail

+
+

Pass

+
+

Fail

+
+

PaymentMethod + cannot be "Cash" and CouponCode is empty.

+
+ +

 

+ +

Invalid order ids:

+ +

ORD200000,ORD200001,ORD200002,ORD200007,ORD200008,ORD200015

+ +

 

+ +

CSV payload:

+ +

ORD200000,1/4/2023,C72649,Monitor,5,570.62,928 Main +St,Debit Card,Shipped,TRK37947903,7,SAVE10,Instagram,2853.1 +ORD200001,8/23/2024,C75739,Phone,2,151.35,823 Main +St,Online,Shipped,TRK91186779,3,SAVE10,Referral,302.7 +ORD200002,2/27/2024,C81728,Tablet,5,550.68,512 Main St,Credit +Card,Cancelled,TRK42903982,8,FREESHIP,Email,2753.4 +ORD200000,1/4/2023,C72649,Monitor,5,570.62,928 Main St,Debit +Card,Shipped,TRK37947903,7,SAVE10,Instagram,2853.1 +ORD200001,8/23/2024,C75739,Phone,2,151.35,823 Main St,Online,Shipped,TRK91186779,3,SAVE10,Referral,302.7 +ORD200002,2/27/2024,C81728,Tablet,5,550.68,512 Main St,Credit +Card,Cancelled,TRK42903982,8,FREESHIP,Email,2753.4 +ORD200007,5/12/2023,C41460,Monitor,5,149.55,706 Main +St,Cash,Shipped,TRK78809193,9,FREESHIP,Facebook,747.75 +ORD200008,4/2/2025,C26817,Phone,2,134.28,904 Main St,Gift +Card,Cancelled,TRK61042692,2,,Email,268.56 +ORD200015,7/17/2023,C39416,Printer,1,473.96,942 Main +St,Cash,Delivered,TRK54930938,3,,Google,473.96

+ +
+ + + + diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2.htm b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2.htm new file mode 100644 index 0000000..334caf4 --- /dev/null +++ b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2.htm @@ -0,0 +1,1253 @@ + + + + + + + + + + + + + + + + + + + +
+ +

From: Emmanuel +Abram-Profeta

+ +

Sent: Saturday, +February 14, 2026 11:35 AM

+ +

To: Emmanuel +Abram-Profeta

+ +

Subject: CSV +document from SAP contains invalid data

+ +

 

+ +

Validation Summary

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

OrderID

+
+

PaymentMethod Exists

+
+

PaymentMethod Not + "Cash"

+
+

OrderStatus Not + "Cancelled"

+
+

CouponCode Present

+
+

OrderID Unique

+
+

Overall

+
+

Notes

+
+

ORD200000

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

No

+
+

Fail

+
+

Duplicate + OrderID appears twice.

+
+

ORD200001

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

No

+
+

Fail

+
+

Duplicate + OrderID appears twice.

+
+

ORD200002

+
+

Yes

+
+

Yes

+
+

No

+
+

Yes

+
+

No

+
+

Fail

+
+

Cancelled + status and duplicate OrderID.

+
+

ORD200003

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200004

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200005

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200006

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200007

+
+

Yes

+
+

No

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Fail

+
+

PaymentMethod + is "Cash".

+
+

ORD200008

+
+

Yes

+
+

Yes

+
+

No

+
+

No

+
+

Yes

+
+

Fail

+
+

Cancelled + status and empty CouponCode.

+
+

ORD200009

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200010

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200011

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200012

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200013

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200014

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Yes

+
+

Pass

+
+

ORD200015

+
+

Yes

+
+

No

+
+

Yes

+
+

No

+
+

Yes

+
+

Fail

+
+

PaymentMethod + is "Cash" and empty CouponCode.

+
+ +

 

+ +

Invalid order ids:

+ +

ORD200000,ORD200001,ORD200002,ORD200007,ORD200008,ORD200015

+ +

 

+ +

CSV payload:

+ +

ORD200000,1/4/2023,C72649,Monitor,5,570.62,928 Main +St,Debit Card,Shipped,TRK37947903,7,SAVE10,Instagram,2853.1 +ORD200001,8/23/2024,C75739,Phone,2,151.35,823 Main +St,Online,Shipped,TRK91186779,3,SAVE10,Referral,302.7 +ORD200002,2/27/2024,C81728,Tablet,5,550.68,512 Main St,Credit +Card,Cancelled,TRK42903982,8,FREESHIP,Email,2753.4 +ORD200000,1/4/2023,C72649,Monitor,5,570.62,928 Main St,Debit +Card,Shipped,TRK37947903,7,SAVE10,Instagram,2853.1 +ORD200001,8/23/2024,C75739,Phone,2,151.35,823 Main St,Online,Shipped,TRK91186779,3,SAVE10,Referral,302.7 +ORD200002,2/27/2024,C81728,Tablet,5,550.68,512 Main St,Credit +Card,Cancelled,TRK42903982,8,FREESHIP,Email,2753.4 +ORD200007,5/12/2023,C41460,Monitor,5,149.55,706 Main +St,Cash,Shipped,TRK78809193,9,FREESHIP,Facebook,747.75 +ORD200008,4/2/2025,C26817,Phone,2,134.28,904 Main St,Gift +Card,Cancelled,TRK61042692,2,,Email,268.56 +ORD200015,7/17/2023,C39416,Printer,1,473.96,942 Main +St,Cash,Delivered,TRK54930938,3,,Google,473.96

+ +
+ + + + diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2_files/colorschememapping.xml b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2_files/colorschememapping.xml new file mode 100644 index 0000000..6a0069c --- /dev/null +++ b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2_files/filelist.xml b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2_files/filelist.xml new file mode 100644 index 0000000..9aa4477 --- /dev/null +++ b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2_files/filelist.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2_files/themedata.thmx b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2_files/themedata.thmx new file mode 100644 index 0000000..f3afc8f Binary files /dev/null and b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example2_files/themedata.thmx differ diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3.htm b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3.htm new file mode 100644 index 0000000..7f70e3c --- /dev/null +++ b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3.htm @@ -0,0 +1,1077 @@ + + + + + + + + + + + + + + + + + + + +
+ +

From: Emmanuel +Abram-Profeta

+ +

Sent: Sunday, +February 15, 2026 12:41 AM

+ +

To: Emmanuel +Abram-Profeta

+ +

Subject: CSV +document from SAP contains invalid data

+ +

 

+ +

Validation Summary

+ +

CSV Payload +Validation Summary

+ +

Validation rules applied from /Shared +Documents/SAPBlogMaterial/DemoArtifacts/ValidationRules.txt:

+ +
    +
  • PaymentMethod must exist and cannot be + "Cash".
  • +
  • OrderStatus must be different from + "Cancelled".
  • +
  • CouponCode must have at least 1 character.
  • +
  • OrderID must be unique in the CSV array.
  • +
  • Date field not validated.
  • +
+ +

Dataset stats: Total rows = 19; Passed rows = 10; Failed rows = 9; Distinct +OrderIDs failing = 6.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

OrderID

+
+

Number of Rows Affected

+
+

Failed Rules

+
+

ORD200000

+
+

2

+
+

OrderID + must be unique in the CSV array (duplicate OrderID appears multiple times).

+
+

ORD200001

+
+

2

+
+

OrderID + must be unique in the CSV array (duplicate OrderID appears multiple times).

+
+

ORD200002

+
+

2

+
+

OrderStatus + must be different from "Cancelled"; OrderID must be unique in the + CSV array.

+
+

ORD200007

+
+

1

+
+

PaymentMethod + cannot be "Cash".

+
+

ORD200008

+
+

1

+
+

OrderStatus + must be different from "Cancelled"; CouponCode must have at least 1 + character.

+
+

ORD200015

+
+

1

+
+

PaymentMethod + cannot be "Cash"; CouponCode must have at least 1 character.

+
+ +

Failed OrderIDs (CSV): +ORD200000,ORD200001,ORD200002,ORD200007,ORD200008,ORD200015

+ +

Note: The invalid CSV rows for the failed OrderIDs are provided as a +separate CSV (original rows, no header).

+ +

 

+ +

Invalid order ids:

+ +

ORD200000,ORD200001,ORD200002,ORD200007,ORD200008,ORD200015

+ +

 

+ +

CSV payload:

+ +

ORD200000,1/4/2023,C72649,Monitor,5,570.62,928 Main +St,Debit Card,Shipped,TRK37947903,7,SAVE10,Instagram,2853.1 +ORD200001,8/23/2024,C75739,Phone,2,151.35,823 Main +St,Online,Shipped,TRK91186779,3,SAVE10,Referral,302.7 +ORD200002,2/27/2024,C81728,Tablet,5,550.68,512 Main St,Credit +Card,Cancelled,TRK42903982,8,FREESHIP,Email,2753.4 +ORD200000,1/4/2023,C72649,Monitor,5,570.62,928 Main St,Debit +Card,Shipped,TRK37947903,7,SAVE10,Instagram,2853.1 +ORD200001,8/23/2024,C75739,Phone,2,151.35,823 Main St,Online,Shipped,TRK91186779,3,SAVE10,Referral,302.7 +ORD200002,2/27/2024,C81728,Tablet,5,550.68,512 Main St,Credit +Card,Cancelled,TRK42903982,8,FREESHIP,Email,2753.4 +ORD200007,5/12/2023,C41460,Monitor,5,149.55,706 Main +St,Cash,Shipped,TRK78809193,9,FREESHIP,Facebook,747.75 +ORD200008,4/2/2025,C26817,Phone,2,134.28,904 Main St,Gift +Card,Cancelled,TRK61042692,2,,Email,268.56 +ORD200015,7/17/2023,C39416,Printer,1,473.96,942 Main +St,Cash,Delivered,TRK54930938,3,,Google,473.96

+ +
+ + + + diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3_files/colorschememapping.xml b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3_files/colorschememapping.xml new file mode 100644 index 0000000..6a0069c --- /dev/null +++ b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3_files/filelist.xml b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3_files/filelist.xml new file mode 100644 index 0000000..3f843b0 --- /dev/null +++ b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3_files/filelist.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3_files/themedata.thmx b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3_files/themedata.thmx new file mode 100644 index 0000000..f3afc8f Binary files /dev/null and b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_example3_files/themedata.thmx differ diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_files/colorschememapping.xml b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_files/colorschememapping.xml new file mode 100644 index 0000000..6a0069c --- /dev/null +++ b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_files/filelist.xml b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_files/filelist.xml new file mode 100644 index 0000000..35f25f8 --- /dev/null +++ b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_files/filelist.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_files/themedata.thmx b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_files/themedata.thmx new file mode 100644 index 0000000..f3afc8f Binary files /dev/null and b/agentic-sap-workflows/Samples/CSV document from SAP contains invalid data_files/themedata.thmx differ diff --git a/agentic-sap-workflows/Samples/ValidationErrorsReport.txt b/agentic-sap-workflows/Samples/ValidationErrorsReport.txt new file mode 100644 index 0000000..6168fd1 --- /dev/null +++ b/agentic-sap-workflows/Samples/ValidationErrorsReport.txt @@ -0,0 +1,47 @@ +DOCNUM: 0000000002552570 | OrderID: ORD200007 | Failed Rules: PaymentMethod: PaymentMethod field value cannot be “Cash”. +DOCNUM: 0000000002552565 OrderID: ORD200002 Failed Rules: OrderStatus: OrderStatus field value must be different from “Cancelled”. +DOCNUM: 0000000002552567 | OrderID: ORD200004 | Failed rules: None +DOCNUM: 0000000002552563 OrderId: ORD200000 FailedRules: None +DOCNUM: 0000000002552562 | OrderID: ORD200002 | Failed Rules: OrderStatus: OrderStatus field value must be different from 'Cancelled'. +DOCNUM: 0000000002552573 OrderId: ORD200010 FailedRules: None +DOCNUM: 0000000002552568 OrderId: ORD200005 - No validation failures +DOCNUM: 0000000002552574 OrderId: ORD200011 Failed Rules: None +DOCNUM: 0000000002552566 OrderID: ORD200003 Failed Rules: None +DOCNUM: 0000000002552576 OrderID: ORD200013 - No validation rules failed +DOCNUM: 0000000002552575, OrderId: ORD200012, Failed rules: None +DOCNUM: 0000000002552578 | OrderId: ORD200015 | Failed Rules: PaymentMethod - PaymentMethod field value cannot be "Cash". +DOCNUM: 0000000002552572 | OrderID: ORD200009 | Failed rules: None +DOCNUM: 0000000002552561 | OrderId: ORD200001 | FailedRules: None +DOCNUM: 0000000002552560 | OrderId: ORD200000 | No validation rule failures +DOCNUM: 0000000002552564 OrderId: ORD200001 - No validation failures +DOCNUM: 0000000002552569 OrderID: ORD200006 FailedRules: None +DOCNUM: 0000000002552571 | OrderID: ORD200008 | Failed rules: OrderStatus must be different from “Cancelled”. +DOCNUM: 0000000002552577 OrderID: ORD200014 - No validation rule failures. +DOCNUM: 0000000002552605 OrderID: ORD200004 - FailedRules: None +DOCNUM: 0000000002552607 OrderId: ORD200006 FailedRules: None +DOCNUM: 0000000002552603 OrderId: ORD200002 Failed Rules: OrderStatus: OrderStatus field value must be different from “Cancelled”. +DOCNUM: 0000000002552610 OrderId: ORD200009 - No validation rule failures. +DOCNUM: 0000000002552612 OrderID: ORD200011 FailedRules: None +DOCNUM: 0000000002552608 | OrderId: ORD200007 | Failed Rules: PaymentMethod: PaymentMethod field value cannot be “Cash”. +DOCNUM: 0000000002552616 | OrderId: ORD200015 | FailedRules: PaymentMethod: PaymentMethod field value cannot be “Cash”. +DOCNUM: 0000000002552615 OrderId: ORD200014 | Failed Rules: None +DOCNUM: 0000000002552599 OrderId: ORD200001 No validation failures +DOCNUM: 0000000002552601 OrderId: ORD200000 FailedRules: None +DOCNUM: 0000000002552611 | OrderID: ORD200010 | Failed validation rules: None +DOCNUM: 0000000002552606 OrderId: ORD200005 Failed rules: None +DOCNUM: 0000000002552598 | OrderId: ORD200000 | No validation failures +DOCNUM: 0000000002552600 | OrderID: ORD200002 | Failed validations: OrderStatus must be different from 'Cancelled'. +DOCNUM: 0000000002552614 OrderID: ORD200013 Failed Rules: None +DOCNUM: 0000000002552602 | OrderID: ORD200001 | No validation rule failures +DOCNUM: 0000000002552604 OrderId: ORD200003 FailedRules: None +DOCNUM: 0000000002552613, OrderID: ORD200012, Failed Rules: None +DOCNUM: 0000000002552609 OrderID: ORD200008 Failed Rules: OrderStatus must be different from 'Cancelled'. +DOCNUM: 0000000002552623 OrderID: ORD200007 Failed rules: PaymentMethod field value cannot be "Cash". +DOCNUM: 0000000002552617 | OrderID: ORD200000 | FailedRules: None +DOCNUM: 0000000002552621 OrderId: ORD200001 FailedRules: None +DOCNUM: 0000000002552619 | OrderID: ORD200002 | Failed Rules: OrderStatus field value must be different from 'Cancelled'. +DOCNUM: 0000000002552620 OrderID: ORD200000 - No validation failures. +DOCNUM: 0000000002552622 OrderID: ORD200002 | Failed Rules: OrderStatus: OrderStatus field value must be different from “Cancelled”. +DOCNUM: 0000000002552625 OrderID: ORD200015 Failed Rules: PaymentMethod field value cannot be "Cash". +DOCNUM: 0000000002552618 OrderId: ORD200001 Failed rules: None +DOCNUM: 0000000002552624 | OrderID: ORD200008 | Failed rules: OrderStatus: OrderStatus field value must be different from “Cancelled”. diff --git a/agentic-sap-workflows/Schemas/AzureOpenAIResultsSchema.json b/agentic-sap-workflows/Schemas/AzureOpenAIResultsSchema.json new file mode 100644 index 0000000..296c4aa --- /dev/null +++ b/agentic-sap-workflows/Schemas/AzureOpenAIResultsSchema.json @@ -0,0 +1,245 @@ +{ + "type": "object", + "properties": { + "choices": { + "type": "array", + "items": { + "type": "object", + "properties": { + "content_filter_results": { + "type": "object", + "properties": { + "hate": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "protected_material_code": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "detected": { + "type": "boolean" + } + } + }, + "protected_material_text": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "detected": { + "type": "boolean" + } + } + }, + "self_harm": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "sexual": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "violence": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + } + } + }, + "finish_reason": { + "type": "string" + }, + "index": { + "type": "integer" + }, + "logprobs": {}, + "message": { + "type": "object", + "properties": { + "annotations": { + "type": "array" + }, + "content": { + "type": "string" + }, + "refusal": {}, + "role": { + "type": "string" + } + } + } + }, + "required": [ + "content_filter_results", + "finish_reason", + "index", + "logprobs", + "message" + ] + } + }, + "created": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "model": { + "type": "string" + }, + "object": { + "type": "string" + }, + "prompt_filter_results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "prompt_index": { + "type": "integer" + }, + "content_filter_results": { + "type": "object", + "properties": { + "hate": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "jailbreak": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "detected": { + "type": "boolean" + } + } + }, + "self_harm": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "sexual": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "violence": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + } + } + } + }, + "required": [ + "prompt_index", + "content_filter_results" + ] + } + }, + "system_fingerprint": { + "type": "string" + }, + "usage": { + "type": "object", + "properties": { + "completion_tokens": { + "type": "integer" + }, + "completion_tokens_details": { + "type": "object", + "properties": { + "accepted_prediction_tokens": { + "type": "integer" + }, + "audio_tokens": { + "type": "integer" + }, + "reasoning_tokens": { + "type": "integer" + }, + "rejected_prediction_tokens": { + "type": "integer" + } + } + }, + "prompt_tokens": { + "type": "integer" + }, + "prompt_tokens_details": { + "type": "object", + "properties": { + "audio_tokens": { + "type": "integer" + }, + "cached_tokens": { + "type": "integer" + } + } + }, + "total_tokens": { + "type": "integer" + } + } + } + } +} \ No newline at end of file diff --git a/agentic-sap-workflows/Schemas/RFCTypes.xsd b/agentic-sap-workflows/Schemas/RFCTypes.xsd new file mode 100644 index 0000000..8e05e78 --- /dev/null +++ b/agentic-sap-workflows/Schemas/RFCTypes.xsd @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/agentic-sap-workflows/Schemas/Z_GET_ORDERS_ANALYSIS.xsd b/agentic-sap-workflows/Schemas/Z_GET_ORDERS_ANALYSIS.xsd new file mode 100644 index 0000000..10bdbc0 --- /dev/null +++ b/agentic-sap-workflows/Schemas/Z_GET_ORDERS_ANALYSIS.xsd @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/agentic-sap-workflows/Schemas/Z_GET_ORDERS_ANALYSISResponse.xsd b/agentic-sap-workflows/Schemas/Z_GET_ORDERS_ANALYSISResponse.xsd new file mode 100644 index 0000000..d166a7a --- /dev/null +++ b/agentic-sap-workflows/Schemas/Z_GET_ORDERS_ANALYSISResponse.xsd @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/agentic-sap-workflows/ValidationRules.txt b/agentic-sap-workflows/ValidationRules.txt new file mode 100644 index 0000000..3a719f3 --- /dev/null +++ b/agentic-sap-workflows/ValidationRules.txt @@ -0,0 +1,11 @@ +Validation Rules + +Here are the validation rules we want to enforce. It is to ensure the quality of the order data that we save. The format is: +Field name: condition. + +PaymentMethod: PaymentMethod field value must exist. +PaymentMethod: PaymentMethod field value cannot be “Cash”. +OrderStatus: OrderStatus field value must be different from “Cancelled”. +CouponCode: CouponCode field value must have at least 1 character. +OrderID: OrderID field value must be unique in the CSV array. +Do not validate the Date field. diff --git a/agentic-sap-workflows/Workflows/AgenticIDocFilteringWorkflow.json b/agentic-sap-workflows/Workflows/AgenticIDocFilteringWorkflow.json new file mode 100644 index 0000000..a0e193d --- /dev/null +++ b/agentic-sap-workflows/Workflows/AgenticIDocFilteringWorkflow.json @@ -0,0 +1,455 @@ +{ + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "actions": { + "Validate_requested_action": { + "type": "If", + "expression": { + "and": [ + { + "equals": [ + "@triggerBody()?['rfcServerContext']?['FunctionName']", + "IDOC_INBOUND_ASYNCHRONOUS" + ] + } + ] + }, + "actions": {}, + "else": { + "actions": { + "Send_exception_to_SAP_server": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "SendExceptionToSapServerErrorMessage": "Unexpected action in request: @{triggerBody()?['rfcServerContext']?['FunctionName']}" + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "sendExceptionToSapServer", + "serviceProviderId": "/serviceProviders/sap" + } + } + }, + "Terminate": { + "type": "Terminate", + "inputs": { + "runStatus": "Failed", + "runError": { + "code": "Unexpected action requested", + "message": "Action @{triggerBody()?['rfcServerContext']?['FunctionName']}was not expected." + } + }, + "runAfter": { + "Send_exception_to_SAP_server": [ + "SUCCEEDED" + ] + } + } + } + }, + "runAfter": {} + }, + "Data_Validation_Agent": { + "type": "Agent", + "inputs": { + "parameters": { + "deploymentId": "gpt-5-3", + "messages": [ + { + "role": "system", + "content": "You are a data analyst. You make sure that the received CSV data from SAP follows the validation rules.\n\nPlease follow business process:\n1) Get validation rules. Rules are defined in @{parameters('ValidationRules')}\n2) Validate the CSV data @{outputs('Create_CSV_data')}with the validation rules from the validation document.\n3) Save validation output in the following format:\nDOCNUM: @{variables('DOCNUM')} followed by OrderId and the validations rules that failed. " + } + ], + "agentModelType": "AzureOpenAI", + "agentModelSettings": { + "agentHistoryReductionSettings": { + "agentHistoryReductionType": "maximumTokenCountReduction", + "maximumTokenCount": 128000 + }, + "deploymentModelProperties": { + "name": "gpt-5-3", + "format": "OpenAI", + "version": "2025-04-14" + } + } + }, + "modelConfigurations": { + "model1": { + "referenceName": "agent-2" + } + } + }, + "tools": { + "Get_validation_rules": { + "actions": { + "Get_validation_document": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "sharepointonline" + } + }, + "method": "get", + "path": "/datasets/@{encodeURIComponent(encodeURIComponent('https://microsoft.sharepoint.com/teams/LogicApps'))}/GetFileContentByPath", + "queries": { + "path": "@parameters('ValidationRules')", + "inferContentType": true, + "queryParametersSingleEncoded": true + } + } + } + }, + "description": "Get validation rules" + }, + "Get_CSV_payload": { + "actions": { + "CSV_data": { + "type": "Compose", + "inputs": "@agentParameters('CSV Payload')" + } + }, + "description": "Get CSV payload", + "agentParameterSchema": { + "type": "object", + "properties": { + "CSV Payload": { + "type": "string", + "description": "The CSV payload received from SAP and that we validate based on the validation rules." + } + }, + "required": [ + "CSV Payload" + ] + } + }, + "Summarize_CSV_payload_review": { + "actions": { + "VerificationInfo": { + "type": "Compose", + "inputs": "@agentParameters('VerificationInfo')" + }, + "Save_verification_info": { + "type": "SetVariable", + "inputs": { + "name": "FailedVerificationInfo", + "value": "@concat(outputs('VerificationInfo'),'\r\n')" + }, + "runAfter": { + "VerificationInfo": [ + "SUCCEEDED" + ] + } + } + }, + "description": "Save validation failures", + "agentParameterSchema": { + "type": "object", + "properties": { + "VerificationInfo": { + "type": "string", + "description": "Line containing the DOCNUM value and the corresponding validations for the corresponding CSV payload. The line format should be:\nDOCNUM: @{variables('DOCNUM')} followed by OrderId and the rules that failed." + } + }, + "required": [ + "VerificationInfo" + ] + } + } + }, + "runAfter": { + "Initializations": [ + "SUCCEEDED" + ] + }, + "limit": { + "count": 100 + } + }, + "Create_CSV_data": { + "type": "Compose", + "inputs": "@concat('OrderID,Date,CustomerID,Product,Quantity,UnitPrice,ShippingAddress,PaymentMethod,OrderStatus,TrackingNumber,ItemsInCart,CouponCode,ReferralSource,TotalPrice\r\n',\njoin(\n xpath(\n xml(triggerBody()?['content']),\n '/*[local-name()=\"Receive\"]/*[local-name()=\"idocData\"]/*[local-name()=\"ZONLINEORDER000\"]/*[\r\n local-name()=\"ORDER_ID\" or\r\n local-name()=\"ORDER_DATE\" or\r\n local-name()=\"CUSTOMER_ID\" or\r\n local-name()=\"PRODUCT\" or\r\n local-name()=\"QUANTITY\" or\r\n local-name()=\"UNIT_PRICE\" or\r\n local-name()=\"SHIP_ADDRESS\" or\r\n local-name()=\"PAYMENT_METHOD\" or\r\n local-name()=\"ORDER_STATUS\" or\r\n local-name()=\"TRACKING_NUMBER\" or\r\n local-name()=\"ITEMS_IN_CART\" or\r\n local-name()=\"COUPON_CODE\" or\r\n local-name()=\"REFERRAL_SOURCE\" or\r\n local-name()=\"TOTAL_PRICE\"\r\n ]/text()'\n ),\n ','\n))\n", + "runAfter": { + "Validate_requested_action": [ + "SUCCEEDED" + ] + } + }, + "Initializations": { + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "FailedVerificationInfo", + "type": "string" + }, + { + "name": "ValidationErrors", + "type": "string", + "value": "@{concat('ValidationErrors', formatDateTime(utcNow(), 'yyyyMMdd'), '.txt')}" + }, + { + "name": "DOCNUM", + "type": "string", + "value": "@{xpath(xml(triggerBody()?['content']), 'string(/*[local-name()=\"Receive\"] /*[local-name()=\"idocData\"] /*[local-name()=\"EDI_DC40\"] /*[local-name()=\"DOCNUM\"])')}" + } + ] + }, + "runAfter": { + "Create_CSV_data": [ + "SUCCEEDED" + ] + } + }, + "Initialize_variables": { + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "leaseId", + "type": "string" + }, + { + "name": "statusCode", + "type": "string" + } + ] + }, + "runAfter": { + "Data_Validation_Agent": [ + "SUCCEEDED" + ] + } + }, + "Check_whether_blob_exists": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "containerName": "onlinestoreorders", + "blobName": "@variables('ValidationErrors')" + }, + "serviceProviderConfiguration": { + "connectionName": "AzureBlob", + "operationId": "blobExists", + "serviceProviderId": "/serviceProviders/AzureBlob" + } + }, + "runAfter": { + "Initialize_variables": [ + "SUCCEEDED" + ] + } + }, + "Does_blob_exist": { + "type": "If", + "expression": { + "and": [ + { + "equals": [ + "@body('Check_whether_blob_exists')?['isBlobExists']", + true + ] + } + ] + }, + "actions": {}, + "else": { + "actions": { + "Create_blob_for_appending": { + "type": "Http", + "inputs": { + "uri": "YOURBLOBURIHERE", + "method": "PUT", + "headers": { + "x-ms-version": "2023-11-03", + "x-ms-date": "@{formatDateTime(utcNow(),'r')}", + "x-ms-blob-type": "AppendBlob", + "Content-Length": "0" + }, + "authentication": { + "type": "ManagedServiceIdentity", + "audience": "https://storage.azure.com/" + }, + "retryPolicy": { + "type": "exponential", + "count": 50, + "interval": "PT10S", + "minimumInterval": "PT10S", + "maximumInterval": "PT120S" + } + }, + "runtimeConfiguration": { + "contentTransfer": { + "transferMode": "Chunked" + } + } + } + } + }, + "runAfter": { + "Check_whether_blob_exists": [ + "SUCCEEDED" + ] + } + }, + "Until_lease_is_acquired": { + "type": "Until", + "expression": "@not(equals(variables('statusCode'), string(409)))", + "limit": { + "count": 120, + "timeout": "PT15M" + }, + "actions": { + "Acquire_validation_errors_blob_lease": { + "type": "Http", + "inputs": { + "uri": "YOURBLOBURIHERE?comp=lease", + "method": "PUT", + "headers": { + "x-ms-lease-action": "acquire", + "x-ms-lease-duration": "30", + "x-ms-version": "2023-11-03", + "x-ms-date": "@{formatDateTime(utcNow(),'r')}" + }, + "authentication": { + "type": "ManagedServiceIdentity", + "audience": "https://storage.azure.com/" + } + }, + "runAfter": { + "Delay": [ + "SUCCEEDED" + ] + }, + "runtimeConfiguration": { + "contentTransfer": { + "transferMode": "Chunked" + } + } + }, + "Delay": { + "type": "Wait", + "inputs": { + "interval": { + "count": "@rand(1,10)", + "unit": "Second" + } + } + }, + "Set_status_code": { + "type": "SetVariable", + "inputs": { + "name": "statusCode", + "value": "@{outputs('Acquire_validation_errors_blob_lease')?['statusCode']}" + }, + "runAfter": { + "Acquire_validation_errors_blob_lease": [ + "SUCCEEDED", + "FAILED", + "TIMEDOUT", + "SKIPPED" + ] + } + } + }, + "runAfter": { + "Does_blob_exist": [ + "SUCCEEDED" + ] + } + }, + "Save_lease_id": { + "type": "SetVariable", + "inputs": { + "name": "leaseId", + "value": "@outputs('Acquire_validation_errors_blob_lease')?['headers']['x-ms-lease-id']" + }, + "runAfter": { + "Until_lease_is_acquired": [ + "SUCCEEDED" + ] + } + }, + "Append_verification_results": { + "type": "Http", + "inputs": { + "uri": "YOURBLOBNAMEHERE with append", + "method": "PUT", + "headers": { + "x-ms-version": "2023-11-03", + "Content-Length": "@{length(variables('FailedVerificationInfo'))}", + "content-type": "text/plain", + "x-ms-lease-id": "@{outputs('Acquire_validation_errors_blob_lease')?['headers']['x-ms-lease-id']}" + }, + "body": "@variables('FailedVerificationInfo')", + "authentication": { + "type": "ManagedServiceIdentity", + "audience": "https://storage.azure.com/" + } + }, + "runAfter": { + "Save_lease_id": [ + "SUCCEEDED" + ] + }, + "runtimeConfiguration": { + "contentTransfer": { + "transferMode": "Chunked" + } + } + }, + "Release_the_lease": { + "type": "Http", + "inputs": { + "uri": "YOURBLOBNAMEHERE with proper parameters to release the lease", + "method": "PUT", + "headers": { + "x-ms-lease-action": "release", + "x-ms-version": "2023-11-03", + "x-ms-date": "@{formatDateTime(utcNow(),'r')}", + "x-ms-lease-id": "@{variables('leaseId')}" + }, + "authentication": { + "type": "ManagedServiceIdentity", + "audience": "https://storage.azure.com/" + } + }, + "runAfter": { + "Append_verification_results": [ + "SUCCEEDED" + ] + }, + "runtimeConfiguration": { + "contentTransfer": { + "transferMode": "Chunked" + } + } + } + }, + "outputs": {}, + "triggers": { + "When_a_message_is_received": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "idocFormat": "MicrosoftLobNamespaceXml", + "DegreeOfParallelism": 100, + "GatewayHost": "YOURHOSTNAMEHERE", + "GatewayService": "YOURGATEWAYSERVICEHERE", + "ProgramId": "YOURPROGRAMIDHERE", + "ReceiveIDocsWithUnreleasedSegmentsV2": true, + "GatewayWithoutWorkProcess": false + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "SapTrigger", + "serviceProviderId": "/serviceProviders/sap" + } + }, + "conditions": [] + } + } + }, + "kind": "Stateful" +} \ No newline at end of file diff --git a/agentic-sap-workflows/Workflows/AgenticSalesPredictionAndAnalysisParseWithSchema.json b/agentic-sap-workflows/Workflows/AgenticSalesPredictionAndAnalysisParseWithSchema.json new file mode 100644 index 0000000..638b4f7 --- /dev/null +++ b/agentic-sap-workflows/Workflows/AgenticSalesPredictionAndAnalysisParseWithSchema.json @@ -0,0 +1,725 @@ +{ + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "actions": { + "Validate_requested_action": { + "type": "If", + "expression": { + "and": [ + { + "equals": [ + "@triggerBody()?['rfcServerContext']?['FunctionName']", + "Z_GET_ORDERS_ANALYSIS" + ] + } + ] + }, + "actions": {}, + "else": { + "actions": { + "Send_exception_to_SAP_server": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "SendExceptionToSapServerErrorMessage": "Unexpected action in request: @{triggerBody()?['rfcServerContext']?['FunctionName']}" + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "sendExceptionToSapServer", + "serviceProviderId": "/serviceProviders/sap" + } + } + }, + "Terminate": { + "type": "Terminate", + "inputs": { + "runStatus": "Failed", + "runError": { + "code": "Unexpected action requested", + "message": "Action @{triggerBody()?['rfcServerContext']?['FunctionName']}was not expected." + } + }, + "runAfter": { + "Send_exception_to_SAP_server": [ + "SUCCEEDED" + ] + } + } + } + }, + "runAfter": {} + }, + "Email_analysis": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "office365" + } + }, + "method": "post", + "body": { + "To": "@parameters('EmailTo')", + "Subject": "Analysis", + "Body": "

@{outputs('Format_markdown_to_html')['html']}

", + "Importance": "Normal" + }, + "path": "/v2/Mail" + }, + "runAfter": { + "Process_analysis_results": [ + "SUCCEEDED" + ] + } + }, + "Respond_to_SAP_server": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "body": "0000000000@{outputs('Format_markdown_to_html')['html']}

]]>
" + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "respondToSapServer", + "serviceProviderId": "/serviceProviders/sap" + } + }, + "runAfter": { + "Process_analysis_results": [ + "SUCCEEDED" + ] + } + }, + "Data_Validation_Agent": { + "type": "Agent", + "inputs": { + "parameters": { + "deploymentId": "gpt-5-3", + "messages": [ + { + "role": "system", + "content": "You are a data analyst. You make sure that the received CSV payload from SAP follows the validation rules.\n\nPlease follow business process:\n1) Get validation rules. Rules are defined in @{parameters('ValidationRules')}\n2) Get CSV payload\n3) Summarize the CSV payload review. Ensure that you use the validation rules from the validation document." + } + ], + "agentModelType": "AzureOpenAI", + "agentModelSettings": { + "agentHistoryReductionSettings": { + "agentHistoryReductionType": "maximumTokenCountReduction", + "maximumTokenCount": 128000 + }, + "deploymentModelProperties": { + "name": "gpt-5-3", + "format": "OpenAI", + "version": "2025-04-14" + } + } + }, + "modelConfigurations": { + "model1": { + "referenceName": "agent-2" + } + } + }, + "tools": { + "Get_validation_rules": { + "actions": { + "Get_validation_document": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "sharepointonline" + } + }, + "method": "get", + "path": "/datasets/@{encodeURIComponent(encodeURIComponent('https://microsoft.sharepoint.com/teams/LogicApps'))}/GetFileContentByPath", + "queries": { + "path": "@parameters('ValidationRules')", + "inferContentType": true, + "queryParametersSingleEncoded": true + } + } + } + }, + "description": "Get validation rules" + }, + "Get_CSV_payload": { + "actions": { + "CSV_payload": { + "type": "Compose", + "inputs": "@outputs('Create_CSV_payload')" + } + }, + "description": "Get CSV payload", + "agentParameterSchema": { + "type": "object", + "properties": { + "CSV Payload": { + "type": "string", + "description": "The CSV payload received from SAP and that we validate based on the validation rules." + } + }, + "required": [ + "CSV Payload" + ] + } + }, + "Summarize_CSV_payload_review": { + "actions": { + "Summary": { + "type": "Compose", + "inputs": "@agentParameters('Validation summary')" + }, + "Invalid_order_ids": { + "type": "Compose", + "inputs": "@agentParameters('InvalidOrderIds')", + "runAfter": { + "Summary": [ + "SUCCEEDED" + ] + } + }, + "Invalid_CSV_payload": { + "type": "Compose", + "inputs": "@agentParameters('Invalid CSV payload')", + "runAfter": { + "Save_invalid_order_ids": [ + "SUCCEEDED" + ] + } + }, + "Save_invalid_order_ids": { + "type": "SetVariable", + "inputs": { + "name": "ArrayOfInvalidOrderIDs", + "value": "@split(agentParameters('InvalidOrderIds'), ',')" + }, + "runAfter": { + "Invalid_order_ids": [ + "SUCCEEDED" + ] + } + }, + "Transform_CSV_to_XML": { + "type": "JavaScriptCode", + "inputs": { + "code": "const lines = workflowContext.actions.Invalid_CSV_payload.outputs.split('\\n');\n\nfunction xmlEscape(value) {\n return String(value)\n .replace(/&/g, \"&\")\n .replace(//g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n // NOTE: We keep empty strings to produce nodes as requested.\n const xml = lines\n .map(line => `${xmlEscape(line)}`)\n .join(\"\");\n\n return { xml };\n" + }, + "runAfter": { + "Send_verification_summary": [ + "SUCCEEDED" + ] + } + }, + "Send_verification_summary": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "office365" + } + }, + "method": "post", + "body": { + "To": "@parameters('EmailTo')", + "Subject": "CSV document from SAP contains invalid data", + "Body": "

Validation Summary

@{agentParameters('Validation summary')}


Invalid order ids:

@{agentParameters('InvalidOrderIds')}


CSV payload:

@{agentParameters('Invalid CSV payload')}

", + "Importance": "Normal" + }, + "path": "/v2/Mail" + }, + "runAfter": { + "Invalid_CSV_payload": [ + "SUCCEEDED" + ] + } + }, + "[RFC]_Create_all_IDocs": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "inputBodyType": "XML", + "rfcName": "Z_CREATE_ONLINEORDER_IDOC", + "outputBodyType": "XML", + "body": "\nO\nLS\nBTSSERVER\nLS\nBTSSERVER\n @{outputs('Transform_CSV_to_XML')}\n \n\n\n" + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "callRfc", + "serviceProviderId": "/serviceProviders/sap" + } + }, + "runAfter": { + "Transform_CSV_to_XML": [ + "SUCCEEDED" + ] + } + } + }, + "description": "This tool will summarize the CSV payload review", + "agentParameterSchema": { + "type": "object", + "properties": { + "Validation summary": { + "type": "string", + "description": "The AI summary provided by the LLM after the CSV payload was reviewed against the validation rules.The expected format is an HTML table. Create a list of all orderids that have failed. Create a CSV document that contains the original CSV payload but only for the orderid values that failed validation, and each row on a separate line. Include title row only in the email body." + }, + "InvalidOrderIds": { + "type": "string", + "description": "The orderid values contained in the AI summary provided by the LLM and that failed validation. The format is CSV." + }, + "Invalid CSV payload": { + "type": "string", + "description": "The original CSV rows of the CSV payload for the orderid values that failed validation. Each row must be on a separate line. Keep the title row only for the email body and remove it otherwise." + } + }, + "required": [ + "Validation summary", + "InvalidOrderIds", + "Invalid CSV payload" + ] + } + } + }, + "runAfter": { + "Create_CSV_payload": [ + "SUCCEEDED" + ] + }, + "limit": { + "count": 100 + } + }, + "Process_analysis_results": { + "type": "Scope", + "actions": { + "Parse_results": { + "type": "ParseJson", + "inputs": { + "content": "@body('Analyze_data')['choices'][0]", + "schema": { + "type": "object", + "properties": { + "choices": { + "type": "array", + "items": { + "type": "object", + "properties": { + "content_filter_results": { + "type": "object", + "properties": { + "hate": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "protected_material_code": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "detected": { + "type": "boolean" + } + } + }, + "protected_material_text": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "detected": { + "type": "boolean" + } + } + }, + "self_harm": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "sexual": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "violence": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + } + } + }, + "finish_reason": { + "type": "string" + }, + "index": { + "type": "integer" + }, + "logprobs": {}, + "message": { + "type": "object", + "properties": { + "annotations": { + "type": "array" + }, + "content": { + "type": "string" + }, + "refusal": {}, + "role": { + "type": "string" + } + } + } + }, + "required": [ + "content_filter_results", + "finish_reason", + "index", + "logprobs", + "message" + ] + } + }, + "created": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "model": { + "type": "string" + }, + "object": { + "type": "string" + }, + "prompt_filter_results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "prompt_index": { + "type": "integer" + }, + "content_filter_results": { + "type": "object", + "properties": { + "hate": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "jailbreak": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "detected": { + "type": "boolean" + } + } + }, + "self_harm": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "sexual": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "violence": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + } + } + } + }, + "required": [ + "prompt_index", + "content_filter_results" + ] + } + }, + "system_fingerprint": { + "type": "string" + }, + "usage": { + "type": "object", + "properties": { + "completion_tokens": { + "type": "integer" + }, + "completion_tokens_details": { + "type": "object", + "properties": { + "accepted_prediction_tokens": { + "type": "integer" + }, + "audio_tokens": { + "type": "integer" + }, + "reasoning_tokens": { + "type": "integer" + }, + "rejected_prediction_tokens": { + "type": "integer" + } + } + }, + "prompt_tokens": { + "type": "integer" + }, + "prompt_tokens_details": { + "type": "object", + "properties": { + "audio_tokens": { + "type": "integer" + }, + "cached_tokens": { + "type": "integer" + } + } + }, + "total_tokens": { + "type": "integer" + } + } + } + } + } + } + }, + "Extract_analysis": { + "type": "Compose", + "inputs": "@body('Parse_results')['message']['content']", + "runAfter": { + "Parse_results": [ + "SUCCEEDED" + ] + } + }, + "Format_markdown_to_html": { + "type": "JavaScriptCode", + "inputs": { + "code": "const raw = workflowContext.actions.Extract_analysis.outputs;\n\n// Basic HTML escaping for safety (keeps blocks clean)\nconst escapeHtml = s => s.replace(/[&<>\"]/g, c => ({'&':'&','<':'<','>':'>','\"':'"'}[c]));\n\n// Normalize line endings\nlet md = raw; // raw.replace(/\\r\\n/g, '\\n').trim();\n\n// Convert code blocks (``` ... ```)\nmd = md.replace(/```([\\s\\S]*?)```/g, (m, p1) => `
${escapeHtml(p1)}
`);\n\n// Horizontal rules --- or ***\n//md = md.replace(/(?:^|\\n)---+(?:\\n|$)/g, '\\n
\\n');\nmd = md.replace(/(?:^|\\n)---+(?:\\n|$)/g, '
');\n\n// Headings ###### to #\nfor (let i = 6; i >= 1; i--) {\n const re = new RegExp(`(?:^|\\\\n)${'#'.repeat(i)}\\\\s+(.+?)\\\\s*(?=\\\\n|$)`, 'g');\n //md = md.replace(re, (m, p1) => `\\n${p1.trim()}`);\n md = md.replace(re, (m, p1) => `${p1.trim()}`);\n}\n\n// Bold and italic\nmd = md.replace(/\\*\\*([^*]+)\\*\\*/g, '$1');\nmd = md.replace(/\\*([^*]+)\\*/g, '$1');\n\n// Unordered lists (lines starting with -, *, +)\nmd = md.replace(/(?:^|\\n)([-*+]\\s.+(?:\\n[-*+]\\s.+)*)/g, (m) => {\n const items = m.trim().split(/\\n/).map(l => l.replace(/^[-*+]\\s+/, '').trim());\n //return '\\n
    \\n' + items.map(i => `
  • ${i}
  • `).join('\\n') + '\\n
';\n return '\\n
    ' + items.map(i => `
  • ${i}
  • `).join('\\n') + '
';\n});\n\n// Paragraphs: wrap remaining text blocks in

...

\nconst blocks = md.split(/\\n{2,}/).map(b => {\n if (/^|^
    |^
    |^/.test(b.trim())) return b;\n  return `

    ${b.replace(/\\n/g, '
    ')}

    `;\n});\n//const html = blocks.join('\\n');\nconst html = blocks.join('');\n\nreturn { html };\n" + }, + "runAfter": { + "Extract_analysis": [ + "SUCCEEDED" + ] + } + } + }, + "runAfter": { + "Analyze_data": [ + "SUCCEEDED" + ] + } + }, + "Parse_Z_GET_ORDERS_ANALYSIS_request": { + "type": "XmlParse", + "inputs": { + "content": "@triggerBody()?['content']", + "schema": { + "source": "LogicApp", + "name": "Z_GET_ORDERS_ANALYSIS.xsd" + }, + "xmlReaderSettings": { + "dtdProcessing": "Prohibit", + "xmlNormalization": true, + "ignoreWhitespace": true, + "ignoreProcessingInstructions": true + }, + "jsonWriterSettings": { + "ignoreAttributes": true, + "useFullyQualifiedNames": false + } + }, + "runAfter": { + "Validate_requested_action": [ + "SUCCEEDED" + ] + } + }, + "Analyze_data": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "azureopenai-2" + } + }, + "method": "post", + "body": { + "messages": [ + { + "role": "system", + "content": "You are a data analyst. Analyze the following dataset and provide trends and predictions. Do not include the rows corresponding to the excluded orderids in the analysis." + }, + { + "role": "user", + "content": "@{outputs('Create_CSV_payload')}" + }, + { + "role": "user", + "content": "Excluded orderids: @{join(variables('ArrayOfInvalidOrderIDs'),',')}" + } + ], + "temperature": 1, + "top_p": 1, + "stream": false, + "max_tokens": 16384, + "presence_penalty": 0, + "frequency_penalty": 0, + "n": 1, + "seed": 0, + "logprobs": false, + "response_format": { + "type": "text" + } + }, + "path": "/2024-02-15-preview/deployments/@{encodeURIComponent('gpt-4o-5')}/chat/completions", + "queries": { + "api-version": "2025-01-01-preview" + } + }, + "runAfter": { + "Data_Validation_Agent": [ + "SUCCEEDED" + ] + } + }, + "Create_CSV_payload": { + "type": "Compose", + "inputs": "@join(variables('CSVPayload'),'\r\n')", + "runAfter": { + "For_each_CSV_row": [ + "SUCCEEDED" + ] + } + }, + "For_each_CSV_row": { + "type": "foreach", + "foreach": "@outputs('Parse_Z_GET_ORDERS_ANALYSIS_request')?['body']?['json']?['IT_CSV']", + "actions": { + "Append_to_CSV_payload": { + "type": "AppendToArrayVariable", + "inputs": { + "name": "CSVPayload", + "value": "@item()?['LINE']" + } + } + }, + "runAfter": { + "Initialize_variables": [ + "SUCCEEDED" + ] + }, + "runtimeConfiguration": { + "concurrency": { + "repetitions": 1 + } + } + }, + "Initialize_variables": { + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "ArrayOfInvalidOrderIDs", + "type": "array" + }, + { + "name": "CSVpayload", + "type": "array" + } + ] + }, + "runAfter": { + "Parse_Z_GET_ORDERS_ANALYSIS_request": [ + "SUCCEEDED" + ] + } + } + }, + "outputs": {}, + "triggers": { + "When_a_message_is_received": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "idocFormat": "MicrosoftLobNamespaceXml", + "DegreeOfParallelism": 1, + "GatewayHost": "YOURGATEWAYHOSTHERE", + "GatewayService": "YOURGATEWAYSERVICEHERE", + "ProgramId": "YOURPROGRAMIDHERE", + "ReceiveIDocsWithUnreleasedSegmentsV2": true, + "GatewayWithoutWorkProcess": false + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "SapTrigger", + "serviceProviderId": "/serviceProviders/sap" + } + } + } + } + }, + "kind": "Stateful" +} \ No newline at end of file diff --git a/agentic-sap-workflows/Workflows/AgenticSalesPredictionAndAnalysisWorkflow.json b/agentic-sap-workflows/Workflows/AgenticSalesPredictionAndAnalysisWorkflow.json new file mode 100644 index 0000000..dcc2847 --- /dev/null +++ b/agentic-sap-workflows/Workflows/AgenticSalesPredictionAndAnalysisWorkflow.json @@ -0,0 +1,673 @@ +{ + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "actions": { + "Validate_requested_action": { + "type": "If", + "expression": { + "and": [ + { + "equals": [ + "@triggerBody()?['rfcServerContext']?['FunctionName']", + "Z_GET_ORDERS_ANALYSIS" + ] + } + ] + }, + "actions": {}, + "else": { + "actions": { + "Send_exception_to_SAP_server": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "SendExceptionToSapServerErrorMessage": "Unexpected action in request: @{triggerBody()?['rfcServerContext']?['FunctionName']}" + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "sendExceptionToSapServer", + "serviceProviderId": "/serviceProviders/sap" + } + } + }, + "Terminate": { + "type": "Terminate", + "inputs": { + "runStatus": "Failed", + "runError": { + "code": "Unexpected action requested", + "message": "Action @{triggerBody()?['rfcServerContext']?['FunctionName']}was not expected." + } + }, + "runAfter": { + "Send_exception_to_SAP_server": [ + "SUCCEEDED" + ] + } + } + } + }, + "runAfter": {} + }, + "Email_analysis": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "office365" + } + }, + "method": "post", + "body": { + "To": "@parameters('EmailTo')", + "Subject": "Analysis", + "Body": "

    @{outputs('Format_markdown_to_html')['html']}

    ", + "Importance": "Normal" + }, + "path": "/v2/Mail" + }, + "runAfter": { + "Process_analysis_results": [ + "SUCCEEDED" + ] + } + }, + "Respond_to_SAP_server": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "body": "0000000000@{outputs('Format_markdown_to_html')['html']}

    ]]>
    " + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "respondToSapServer", + "serviceProviderId": "/serviceProviders/sap" + } + }, + "runAfter": { + "Process_analysis_results": [ + "SUCCEEDED" + ] + } + }, + "Analyze_data": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "azureopenai-2" + } + }, + "method": "post", + "body": { + "messages": [ + { + "role": "system", + "content": "You are a data analyst. Analyze the following dataset and provide trends and predictions. Do not include the rows corresponding to the excluded orderids in the analysis." + }, + { + "role": "user", + "content": "@{outputs('Create_CSV_payload')}" + }, + { + "role": "user", + "content": "Excluded orderids: @{join(variables('ArrayOfInvalidOrderIDs'),',')}." + } + ], + "temperature": 1, + "top_p": 1, + "stream": false, + "max_tokens": 16384, + "presence_penalty": 0, + "frequency_penalty": 0, + "n": 1, + "seed": 0, + "logprobs": false, + "response_format": { + "type": "text" + } + }, + "path": "/2024-02-15-preview/deployments/@{encodeURIComponent('gpt-4o-5')}/chat/completions", + "queries": { + "api-version": "2025-01-01-preview" + } + }, + "runAfter": { + "Data_Validation_Agent": [ + "SUCCEEDED" + ] + } + }, + "Data_Validation_Agent": { + "type": "Agent", + "inputs": { + "parameters": { + "deploymentId": "gpt-5-3", + "messages": [ + { + "role": "system", + "content": "You are a data analyst. You make sure that the received CSV payload from SAP follows the validation rules.\n\nPlease follow business process:\n1) Get validation rules. Rules are defined in @{parameters('ValidationRules')}\n2) Get CSV payload\n3) Summarize the CSV payload review. Ensure that you use the validation rules from the validation document." + } + ], + "agentModelType": "AzureOpenAI", + "agentModelSettings": { + "agentHistoryReductionSettings": { + "agentHistoryReductionType": "maximumTokenCountReduction", + "maximumTokenCount": 128000 + }, + "deploymentModelProperties": { + "name": "gpt-5-3", + "format": "OpenAI", + "version": "2025-04-14" + } + } + }, + "modelConfigurations": { + "model1": { + "referenceName": "agent-2" + } + } + }, + "tools": { + "Get_validation_rules": { + "actions": { + "Get_validation_document": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "sharepointonline" + } + }, + "method": "get", + "path": "/datasets/@{encodeURIComponent(encodeURIComponent('https://microsoft.sharepoint.com/teams/LogicApps'))}/GetFileContentByPath", + "queries": { + "path": "@parameters('ValidationRules')", + "inferContentType": true, + "queryParametersSingleEncoded": true + } + } + } + }, + "description": "Get validation rules" + }, + "Get_CSV_payload": { + "actions": { + "CSV_payload": { + "type": "Compose", + "inputs": "@outputs('Create_CSV_payload')" + } + }, + "description": "Get CSV payload", + "agentParameterSchema": { + "type": "object", + "properties": { + "CSV Payload": { + "type": "string", + "description": "The CSV payload received from SAP and that we validate based on the validation rules." + } + }, + "required": [ + "CSV Payload" + ] + } + }, + "Summarize_CSV_payload_review": { + "actions": { + "Summary": { + "type": "Compose", + "inputs": "@agentParameters('Validation summary')" + }, + "Invalid_order_ids": { + "type": "Compose", + "inputs": "@agentParameters('InvalidOrderIds')", + "runAfter": { + "Summary": [ + "SUCCEEDED" + ] + } + }, + "Invalid_CSV_payload": { + "type": "Compose", + "inputs": "@agentParameters('Invalid CSV payload')", + "runAfter": { + "Save_invalid_order_ids": [ + "SUCCEEDED" + ] + } + }, + "Save_invalid_order_ids": { + "type": "SetVariable", + "inputs": { + "name": "ArrayOfInvalidOrderIDs", + "value": "@split(agentParameters('InvalidOrderIds'), ',')" + }, + "runAfter": { + "Invalid_order_ids": [ + "SUCCEEDED" + ] + } + }, + "Transform_CSV_to_XML": { + "type": "JavaScriptCode", + "inputs": { + "code": "const lines = workflowContext.actions.Invalid_CSV_payload.outputs.split('\\n');\n\nfunction xmlEscape(value) {\n return String(value)\n .replace(/&/g, \"&\")\n .replace(//g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n// NOTE: we don't want to keep empty lines (which can be produced by reading the blobs)\n// the reason being that if the recipient uses a schema to validate the xml,\n// it may reject it if it does not allow empty nodes.\nconst xml = lines\n .filter(line => line && line.trim() !== '') // keep only non-empty lines\n .map(line => `${xmlEscape(line)}`)\n .join('');\n\n return { xml };" + }, + "runAfter": { + "Send_verification_summary": [ + "SUCCEEDED" + ] + } + }, + "Send_verification_summary": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "office365" + } + }, + "method": "post", + "body": { + "To": "@parameters('EmailTo')", + "Subject": "CSV document from SAP contains invalid data", + "Body": "

    Validation Summary

    @{agentParameters('Validation summary')}


    Invalid order ids:

    @{agentParameters('InvalidOrderIds')}


    CSV payload:

    @{agentParameters('Invalid CSV payload')}

    ", + "Importance": "Normal" + }, + "path": "/v2/Mail" + }, + "runAfter": { + "Invalid_CSV_payload": [ + "SUCCEEDED" + ] + } + }, + "[RFC]_Create_all_IDocs": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "inputBodyType": "XML", + "rfcName": "Z_CREATE_ONLINEORDER_IDOC", + "outputBodyType": "XML", + "body": "\nO\nLS\nBTSSERVER\nLS\nBTSSERVER\n @{outputs('Transform_CSV_to_XML')}\n \n\n\n" + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "callRfc", + "serviceProviderId": "/serviceProviders/sap" + } + }, + "runAfter": { + "Transform_CSV_to_XML": [ + "SUCCEEDED" + ] + } + } + }, + "description": "This tool will summarize the CSV payload review", + "agentParameterSchema": { + "type": "object", + "properties": { + "Validation summary": { + "type": "string", + "description": "The AI summary provided by the LLM after the CSV payload was reviewed against the validation rules.The expected format is an HTML table. Create a list of all orderids that have failed. Create a CSV document that contains the original CSV payload but only for the orderid values that failed validation, and each row on a separate line. Include title row only in the email body." + }, + "InvalidOrderIds": { + "type": "string", + "description": "The orderid values contained in the AI summary provided by the LLM and that failed validation. The format is CSV." + }, + "Invalid CSV payload": { + "type": "string", + "description": "The original CSV rows of the CSV payload for the orderid values that failed validation. Each row must be on a separate line. Keep the title row only for the email body and remove it otherwise." + } + }, + "required": [ + "Validation summary", + "InvalidOrderIds", + "Invalid CSV payload" + ] + } + } + }, + "runAfter": { + "Initialize_array_of_invalid_order_ids": [ + "SUCCEEDED" + ] + }, + "limit": { + "count": 100 + } + }, + "Process_analysis_results": { + "type": "Scope", + "actions": { + "Parse_results": { + "type": "ParseJson", + "inputs": { + "content": "@body('Analyze_data')['choices'][0]", + "schema": { + "type": "object", + "properties": { + "choices": { + "type": "array", + "items": { + "type": "object", + "properties": { + "content_filter_results": { + "type": "object", + "properties": { + "hate": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "protected_material_code": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "detected": { + "type": "boolean" + } + } + }, + "protected_material_text": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "detected": { + "type": "boolean" + } + } + }, + "self_harm": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "sexual": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "violence": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + } + } + }, + "finish_reason": { + "type": "string" + }, + "index": { + "type": "integer" + }, + "logprobs": {}, + "message": { + "type": "object", + "properties": { + "annotations": { + "type": "array" + }, + "content": { + "type": "string" + }, + "refusal": {}, + "role": { + "type": "string" + } + } + } + }, + "required": [ + "content_filter_results", + "finish_reason", + "index", + "logprobs", + "message" + ] + } + }, + "created": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "model": { + "type": "string" + }, + "object": { + "type": "string" + }, + "prompt_filter_results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "prompt_index": { + "type": "integer" + }, + "content_filter_results": { + "type": "object", + "properties": { + "hate": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "jailbreak": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "detected": { + "type": "boolean" + } + } + }, + "self_harm": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "sexual": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + }, + "violence": { + "type": "object", + "properties": { + "filtered": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + } + } + } + } + }, + "required": [ + "prompt_index", + "content_filter_results" + ] + } + }, + "system_fingerprint": { + "type": "string" + }, + "usage": { + "type": "object", + "properties": { + "completion_tokens": { + "type": "integer" + }, + "completion_tokens_details": { + "type": "object", + "properties": { + "accepted_prediction_tokens": { + "type": "integer" + }, + "audio_tokens": { + "type": "integer" + }, + "reasoning_tokens": { + "type": "integer" + }, + "rejected_prediction_tokens": { + "type": "integer" + } + } + }, + "prompt_tokens": { + "type": "integer" + }, + "prompt_tokens_details": { + "type": "object", + "properties": { + "audio_tokens": { + "type": "integer" + }, + "cached_tokens": { + "type": "integer" + } + } + }, + "total_tokens": { + "type": "integer" + } + } + } + } + } + } + }, + "Extract_analysis": { + "type": "Compose", + "inputs": "@body('Parse_results')['message']['content']", + "runAfter": { + "Parse_results": [ + "SUCCEEDED" + ] + } + }, + "Format_markdown_to_html": { + "type": "JavaScriptCode", + "inputs": { + "code": "const raw = workflowContext.actions.Extract_analysis.outputs;\n\n// Basic HTML escaping for safety (keeps blocks clean)\nconst escapeHtml = s => s.replace(/[&<>\"]/g, c => ({'&':'&','<':'<','>':'>','\"':'"'}[c]));\n\n// Normalize line endings\nlet md = raw; // raw.replace(/\\r\\n/g, '\\n').trim();\n\n// Convert code blocks (``` ... ```)\nmd = md.replace(/```([\\s\\S]*?)```/g, (m, p1) => `
    ${escapeHtml(p1)}
    `);\n\n// Horizontal rules --- or ***\n//md = md.replace(/(?:^|\\n)---+(?:\\n|$)/g, '\\n
    \\n');\nmd = md.replace(/(?:^|\\n)---+(?:\\n|$)/g, '
    ');\n\n// Headings ###### to #\nfor (let i = 6; i >= 1; i--) {\n const re = new RegExp(`(?:^|\\\\n)${'#'.repeat(i)}\\\\s+(.+?)\\\\s*(?=\\\\n|$)`, 'g');\n //md = md.replace(re, (m, p1) => `\\n${p1.trim()}`);\n md = md.replace(re, (m, p1) => `${p1.trim()}`);\n}\n\n// Bold and italic\nmd = md.replace(/\\*\\*([^*]+)\\*\\*/g, '$1');\nmd = md.replace(/\\*([^*]+)\\*/g, '$1');\n\n// Unordered lists (lines starting with -, *, +)\nmd = md.replace(/(?:^|\\n)([-*+]\\s.+(?:\\n[-*+]\\s.+)*)/g, (m) => {\n const items = m.trim().split(/\\n/).map(l => l.replace(/^[-*+]\\s+/, '').trim());\n //return '\\n
      \\n' + items.map(i => `
    • ${i}
    • `).join('\\n') + '\\n
    ';\n return '\\n
      ' + items.map(i => `
    • ${i}
    • `).join('\\n') + '
    ';\n});\n\n// Paragraphs: wrap remaining text blocks in

    ...

    \nconst blocks = md.split(/\\n{2,}/).map(b => {\n if (/^|^
      |^
      |^/.test(b.trim())) return b;\n  return `

      ${b.replace(/\\n/g, '
      ')}

      `;\n});\n//const html = blocks.join('\\n');\nconst html = blocks.join('');\n\nreturn { html };\n" + }, + "runAfter": { + "Extract_analysis": [ + "SUCCEEDED" + ] + } + } + }, + "runAfter": { + "Analyze_data": [ + "SUCCEEDED" + ] + } + }, + "Create_CSV_payload": { + "type": "Compose", + "inputs": "@\njoin(\n xpath(\n xml(triggerBody()?['content']),\n '/*[local-name()=\"Z_GET_ORDERS_ANALYSIS\"]/*[local-name()=\"IT_CSV\"]/*[local-name()=\"ZTY_CSV_LINE\"]/*[local-name()=\"LINE\"]/text()'\n ),\n '\r\n')\n", + "runAfter": { + "Validate_requested_action": [ + "SUCCEEDED" + ] + } + }, + "Initialize_array_of_invalid_order_ids": { + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "ArrayOfInvalidOrderIDs", + "type": "array" + } + ] + }, + "runAfter": { + "Create_CSV_payload": [ + "SUCCEEDED" + ] + } + } + }, + "outputs": {}, + "triggers": { + "When_a_message_is_received": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "idocFormat": "MicrosoftLobNamespaceXml", + "DegreeOfParallelism": 1, + "GatewayHost": "YOURGATEWAYHOSTHERE", + "GatewayService": "YOURGATEWAYSERVICEHERE", + "ProgramId": "YOURPROGRAMIDHERE", + "ReceiveIDocsWithUnreleasedSegmentsV2": true, + "GatewayWithoutWorkProcess": false + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "SapTrigger", + "serviceProviderId": "/serviceProviders/sap" + } + } + } + } + }, + "kind": "Stateful" +} \ No newline at end of file diff --git a/agentic-sap-workflows/Workflows/SendCustomerOrdersSpreadsheetsWorkflow.json b/agentic-sap-workflows/Workflows/SendCustomerOrdersSpreadsheetsWorkflow.json new file mode 100644 index 0000000..6d81ed4 --- /dev/null +++ b/agentic-sap-workflows/Workflows/SendCustomerOrdersSpreadsheetsWorkflow.json @@ -0,0 +1,175 @@ +{ + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "actions": { + "Read_CSV_orders_from_blob": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "containerName": "onlinestoreorders", + "blobName": "@parameters('DataFileName')" + }, + "serviceProviderConfiguration": { + "connectionName": "AzureBlob", + "operationId": "readBlob", + "serviceProviderId": "/serviceProviders/AzureBlob" + } + }, + "runAfter": {} + }, + "Extract_rows": { + "type": "Compose", + "inputs": "@split(string(body('Read_CSV_orders_from_blob')?['content']), '\r\n')", + "runAfter": { + "Read_CSV_orders_from_blob": [ + "SUCCEEDED" + ] + } + }, + "Transform_CSV_to_XML": { + "type": "JavaScriptCode", + "inputs": { + "code": "const lines = workflowContext.actions.Extract_rows.outputs;\n\nfunction xmlEscape(value) {\n return String(value)\n .replace(/&/g, \"&\")\n .replace(//g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n// NOTE: we don't want to keep empty lines (which can be produced by reading the blobs)\n// the reason being that if the recipient uses a schema to validate the xml,\n// it may reject it if it does not allow empty nodes.\nconst xml = lines\n .filter(line => line && line.trim() !== '') // keep only non-empty lines\n .map(line => `${xmlEscape(line)}`)\n .join('');\n\n return { xml };" + }, + "runAfter": { + "Extract_rows": [ + "SUCCEEDED" + ] + } + }, + "[RFC]_Call_Z_GET_ORDERS_ANALYSIS": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "inputBodyType": "XML", + "rfcName": "Z_GET_ORDERS_ANALYSIS", + "outputBodyType": "XML", + "body": "@{outputs('Transform_CSV_to_XML')['xml']}" + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "callRfc", + "serviceProviderId": "/serviceProviders/sap" + } + }, + "runAfter": { + "Transform_CSV_to_XML": [ + "SUCCEEDED" + ] + } + }, + "Save_EXCEPTION_message": { + "type": "Compose", + "inputs": "@xpath(body('[RFC]_Call_Z_GET_ORDERS_ANALYSIS')?['content'], \r\n 'string(/*[local-name()=\"Z_GET_ORDERS_ANALYSISResponse\"]/*[local-name()=\"EXCEPTIONMSG\"])')\r\n", + "runAfter": { + "[RFC]_Call_Z_GET_ORDERS_ANALYSIS": [ + "SUCCEEDED" + ] + } + }, + "Save_RETURN_message": { + "type": "Compose", + "inputs": "@xpath(body('[RFC]_Call_Z_GET_ORDERS_ANALYSIS')?['content'], \r\n 'string(/*[local-name()=\"Z_GET_ORDERS_ANALYSISResponse\"]/*[local-name()=\"RETURN\"]/*[local-name()=\"MESSAGE\"])')", + "runAfter": { + "Save_EXCEPTION_message": [ + "SUCCEEDED" + ] + } + }, + "Has_errors": { + "type": "If", + "expression": { + "or": [ + { + "not": { + "equals": [ + "@outputs('Save_EXCEPTION_message')", + "ok" + ] + } + }, + { + "equals": [ + "@not(empty(outputs('Save_RETURN_message')))", + true + ] + } + ] + }, + "actions": { + "Set_email_body_(failure)": { + "type": "SetVariable", + "inputs": { + "name": "EmailBody", + "value": "@concat(\r\n 'Error message: ', outputs('Save_RETURN_message'), ', details: ',\r\n xpath(body('[RFC]_Call_Z_GET_ORDERS_ANALYSIS')?['content'], 'string(//*[local-name()=\"MESSAGE_V1\"])'),\r\n xpath(body('[RFC]_Call_Z_GET_ORDERS_ANALYSIS')?['content'], 'string(//*[local-name()=\"MESSAGE_V2\"])'),\r\n xpath(body('[RFC]_Call_Z_GET_ORDERS_ANALYSIS')?['content'], 'string(//*[local-name()=\"MESSAGE_V3\"])'),\r\n xpath(body('[RFC]_Call_Z_GET_ORDERS_ANALYSIS')?['content'], 'string(//*[local-name()=\"MESSAGE_V4\"])'),\r\n '; ',\r\n 'Exception message: ', outputs('Save_EXCEPTION_message'), '.')" + } + } + }, + "else": { + "actions": { + "Set_email_body_(success)": { + "type": "SetVariable", + "inputs": { + "name": "EmailBody", + "value": "@xpath(body('[RFC]_Call_Z_GET_ORDERS_ANALYSIS')?['content'], \n 'string(/*[local-name()=\"Z_GET_ORDERS_ANALYSISResponse\"]/*[local-name()=\"ANALYSIS\"])')" + } + } + } + }, + "runAfter": { + "Initialize_email_body": [ + "SUCCEEDED" + ] + } + }, + "Send_an_email_(V2)": { + "type": "ApiConnection", + "inputs": { + "host": { + "connection": { + "referenceName": "office365" + } + }, + "method": "post", + "body": { + "To": "@parameters('EmailTo')", + "Subject": "Received Analysis", + "Body": "

      @{variables('EmailBody')}

      ", + "Importance": "Normal" + }, + "path": "/v2/Mail" + }, + "runAfter": { + "Has_errors": [ + "SUCCEEDED" + ] + } + }, + "Initialize_email_body": { + "type": "InitializeVariable", + "inputs": { + "variables": [ + { + "name": "EmailBody", + "type": "string" + } + ] + }, + "runAfter": { + "Save_RETURN_message": [ + "SUCCEEDED" + ] + } + } + }, + "outputs": {}, + "triggers": { + "When_an_HTTP_request_is_received": { + "type": "Request", + "kind": "Http" + } + } + }, + "kind": "Stateful" +} \ No newline at end of file diff --git a/agentic-sap-workflows/Workflows/SendCustomerOrdersWorkflow.json b/agentic-sap-workflows/Workflows/SendCustomerOrdersWorkflow.json new file mode 100644 index 0000000..4df387f --- /dev/null +++ b/agentic-sap-workflows/Workflows/SendCustomerOrdersWorkflow.json @@ -0,0 +1,72 @@ +{ + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "actions": { + "Read_CSV_orders_from_blob": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "containerName": "onlinestoreorders", + "blobName": "@parameters('DataFileName')" + }, + "serviceProviderConfiguration": { + "connectionName": "AzureBlob", + "operationId": "readBlob", + "serviceProviderId": "/serviceProviders/AzureBlob" + } + }, + "runAfter": {} + }, + "Extract_rows": { + "type": "Compose", + "inputs": "@split(string(body('Read_CSV_orders_from_blob')?['content']), '\r\n')", + "runAfter": { + "Read_CSV_orders_from_blob": [ + "SUCCEEDED" + ] + } + }, + "Transform_CSV_to_XML": { + "type": "JavaScriptCode", + "inputs": { + "code": "const lines = workflowContext.actions.Extract_rows.outputs;\n\nfunction xmlEscape(value) {\n return String(value)\n .replace(/&/g, \"&\")\n .replace(//g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n// NOTE: we don't want to keep empty lines (which can be produced by reading the blobs)\n// the reason being that if the recipient uses a schema to validate the xml,\n// it may reject it if it does not allow empty nodes.\nconst xml = lines\n .filter(line => line && line.trim() !== '') // keep only non-empty lines\n .map(line => `${xmlEscape(line)}`)\n .join('');\n\n return { xml };" + }, + "runAfter": { + "Extract_rows": [ + "SUCCEEDED" + ] + } + }, + "[RFC]_Create_all_IDocs": { + "type": "ServiceProvider", + "inputs": { + "parameters": { + "inputBodyType": "XML", + "rfcName": "Z_CREATE_ONLINEORDER_IDOC ", + "outputBodyType": "XML", + "body": "\nO\nLS\nBTSSERVER\nLS\nBTSSERVER\n @{outputs('Transform_CSV_to_XML')['xml']}\n \n\n\n" + }, + "serviceProviderConfiguration": { + "connectionName": "sap", + "operationId": "callRfc", + "serviceProviderId": "/serviceProviders/sap" + } + }, + "runAfter": { + "Transform_CSV_to_XML": [ + "SUCCEEDED" + ] + } + } + }, + "outputs": {}, + "triggers": { + "When_an_HTTP_request_is_received": { + "type": "Request", + "kind": "Http" + } + } + }, + "kind": "Stateful" +} \ No newline at end of file diff --git a/agentic-sap-workflows/abapgitexported/.abapgit.xml b/agentic-sap-workflows/abapgitexported/.abapgit.xml new file mode 100644 index 0000000..7c0506a --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/.abapgit.xml @@ -0,0 +1,10 @@ + + + + + E + /src/ + PREFIX + + + diff --git a/agentic-sap-workflows/abapgitexported/src/package.devc.xml b/agentic-sap-workflows/abapgitexported/src/package.devc.xml new file mode 100644 index 0000000..730c94d --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/package.devc.xml @@ -0,0 +1,10 @@ + + + + + + General package for Logic Apps + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/z1lis01container.idoc.xml b/agentic-sap-workflows/abapgitexported/src/z1lis01container.idoc.xml new file mode 100644 index 0000000..09fc62d --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/z1lis01container.idoc.xml @@ -0,0 +1,48 @@ + + + + + + + Test custom idoc for a Z1LIS01 segment type + X + 750 + Z1LIS01CONTAINER + Z1LIS01CONTAINER + + + + 0001 + Z1PMMVIDS + 0000000001 + 0000000100 + 02 + + + 0002 + Z1MATEXT + 0000000001 + 0000000100 + 02 + + + 0003 + Z1OPER + X + 0000000001 + 0000000100 + 02 + + + 0004 + Z1LIS01 + X + 0000000001 + 0000000100 + 02 + + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/z1text2.tabl.xml b/agentic-sap-workflows/abapgitexported/src/z1text2.tabl.xml new file mode 100644 index 0000000..b9f8b0b --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/z1text2.tabl.xml @@ -0,0 +1,51 @@ + + + + + + Z1TEXT2 + E + INTTAB + Segment type similar to Z1TEXT + E + 1 + + + + LINE + 0 + C + 000160 + CHAR + 000080 + CHAR + + + + + + Z1TEXT2 + Segment type similar to Z1TEXT + + + Z1TEXT2 + Z2TEXT2000 + 750 + X + 0001 + 0080 + + + + Z1TEXT2 + 0001 + LINE + CHAR80 + 0080 + + + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/z_create_onlineorder_idoc.abap b/agentic-sap-workflows/abapgitexported/src/z_create_onlineorder_idoc.abap new file mode 100644 index 0000000..6fad5ec --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/z_create_onlineorder_idoc.abap @@ -0,0 +1,329 @@ +FUNCTION z_create_onlineorder_idoc. +*"---------------------------------------------------------------------- +*"*"Local Interface: +*" IMPORTING +*" VALUE(IV_DIRECTION) TYPE CHAR01 DEFAULT 'O' +*" VALUE(IV_IDOCTYP) TYPE EDI_IDOCTP DEFAULT 'ZONLINEORDERIDOC' +*" VALUE(IV_MESTYP) TYPE EDIDC-MESTYP DEFAULT 'ZONLINEORDER' +*" VALUE(IV_SEGTP) TYPE EDIHSEGTYP DEFAULT 'ZONLINEORDER' +*" VALUE(IV_SNDPRT) TYPE EDIDC-SNDPRT OPTIONAL +*" VALUE(IV_SNDPRN) TYPE EDIDC-SNDPRN OPTIONAL +*" VALUE(IV_RCVPRT) TYPE EDIDC-RCVPRT OPTIONAL +*" VALUE(IV_RCVPRN) TYPE EDIDC-RCVPRN OPTIONAL +*" VALUE(IV_RCVPOR) TYPE EDIDC-RCVPOR OPTIONAL +*" EXPORTING +*" VALUE(EV_DOCNUM) TYPE EDIDC-DOCNUM +*" TABLES +*" IT_CSV STRUCTURE ZTY_CSV_LINE +*" ET_RETURN STRUCTURE BAPIRET2 +*" ET_DOCNUMS TYPE ZTY_DOCNUM_TT +*"---------------------------------------------------------------------- + + DATA: ls_ret TYPE bapiret2. + + " --- Validate direction once + IF iv_direction <> 'I' AND iv_direction <> 'O'. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '002'. + ls_ret-message = 'IV_DIRECTION must be I (inbound) or O (outbound).'. + ls_ret-message_v1 = 'I'. + ls_ret-message_v2 = 'O'. + APPEND ls_ret TO et_return. + RETURN. + ENDIF. + + " --- Ensure we have at least one row + IF it_csv[] IS INITIAL. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '003'. + ls_ret-message = 'IT_CSV must contain at least one line.'. + APPEND ls_ret TO et_return. + RETURN. + ENDIF. + + " ==================================================================== + " Main loop: each IT_CSV-LINE is one CSV record + " ==================================================================== + DATA: lv_idx TYPE i VALUE 0. + + LOOP AT it_csv INTO DATA(wa_csv). + lv_idx = lv_idx + 1. + + DATA(lv_csv) = CONV string( wa_csv-line ). " ZTY_CSV_LINE-LINE is CHAR2048 + + " --- Parse CSV into 14 tokens (quotes, commas-in-quotes, "" escape) + TYPES: string_tt TYPE STANDARD TABLE OF string WITH EMPTY KEY. + DATA: lt_tokens TYPE string_tt, + lv_len TYPE i, lv_pos TYPE i, lv_inq TYPE c LENGTH 1, + lv_c TYPE c LENGTH 1, lv_buf TYPE string. + + CLEAR: lt_tokens, lv_buf, lv_inq. + lv_len = strlen( lv_csv ). + lv_pos = 0. + + WHILE lv_pos < lv_len. + lv_c = lv_csv+lv_pos(1). + IF lv_c = '"'. + IF lv_inq IS INITIAL. + lv_inq = 'X'. + ELSE. + DATA(lv_next) = lv_pos + 1. + IF lv_next < lv_len AND lv_csv+lv_next(1) = '"'. + CONCATENATE lv_buf '"' INTO lv_buf. + lv_pos = lv_pos + 1. + ELSE. + CLEAR lv_inq. + ENDIF. + ENDIF. + ELSEIF lv_c = ',' AND lv_inq IS INITIAL. + APPEND lv_buf TO lt_tokens. + CLEAR lv_buf. + ELSE. + CONCATENATE lv_buf lv_c INTO lv_buf. + ENDIF. + lv_pos = lv_pos + 1. + ENDWHILE. + APPEND lv_buf TO lt_tokens. + + IF lines( lt_tokens ) <> 14. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '032'. + ls_ret-message = |Row { lv_idx }: CSV must contain exactly 14 comma-separated values.| . + APPEND ls_ret TO et_return. + CONTINUE. + ENDIF. + + " --- Map tokens + DATA: lv_order_id TYPE string, + lv_order_date_text TYPE string, + lv_customer_id TYPE string, + lv_product TYPE string, + lv_quantity_txt TYPE string, + lv_unit_price_txt TYPE string, + lv_ship_addr TYPE string, + lv_pay_method TYPE string, + lv_order_status TYPE string, + lv_tracking TYPE string, + lv_items_in_cart_txt TYPE string, + lv_coupon_code TYPE string, + lv_ref_source TYPE string, + lv_total_price_txt TYPE string. + + READ TABLE lt_tokens INDEX 1 INTO lv_order_id. + READ TABLE lt_tokens INDEX 2 INTO lv_order_date_text. + READ TABLE lt_tokens INDEX 3 INTO lv_customer_id. + READ TABLE lt_tokens INDEX 4 INTO lv_product. + READ TABLE lt_tokens INDEX 5 INTO lv_quantity_txt. + READ TABLE lt_tokens INDEX 6 INTO lv_unit_price_txt. + READ TABLE lt_tokens INDEX 7 INTO lv_ship_addr. + READ TABLE lt_tokens INDEX 8 INTO lv_pay_method. + READ TABLE lt_tokens INDEX 9 INTO lv_order_status. + READ TABLE lt_tokens INDEX 10 INTO lv_tracking. + READ TABLE lt_tokens INDEX 11 INTO lv_items_in_cart_txt. + READ TABLE lt_tokens INDEX 12 INTO lv_coupon_code. + READ TABLE lt_tokens INDEX 13 INTO lv_ref_source. + READ TABLE lt_tokens INDEX 14 INTO lv_total_price_txt. + + " --- Date parse to DATS + DATA: lv_order_date TYPE d, + lv_ok TYPE abap_bool VALUE abap_false. + + IF strlen( lv_order_date_text ) = 10 AND lv_order_date_text+4(1) = '-' AND lv_order_date_text+7(1) = '-'. + DATA(lv_iso) = lv_order_date_text. + REPLACE ALL OCCURRENCES OF '-' IN lv_iso WITH ''. + IF strlen( lv_iso ) = 8. + lv_order_date = lv_iso. + lv_ok = abap_true. + ENDIF. + ELSEIF strlen( lv_order_date_text ) = 8 AND lv_order_date_text CO '0123456789'. + lv_order_date = lv_order_date_text. + lv_ok = abap_true. + ENDIF. + + IF lv_ok = abap_false. + CALL FUNCTION 'DATE_CONV_EXT_TO_INT' + EXPORTING + i_date_ext = lv_order_date_text + IMPORTING + e_date_int = lv_order_date + EXCEPTIONS + invalid_date = 1 + OTHERS = 2. + IF sy-subrc = 0. + lv_ok = abap_true. + ENDIF. + ENDIF. + + IF lv_ok = abap_false OR lv_order_date IS INITIAL. + lv_order_date = sy-datum. + CLEAR ls_ret. + ls_ret-type = 'W'. + ls_ret-id = 'ZORD'. + ls_ret-number = '004'. + ls_ret-message = |Row { lv_idx }: Order date '{ lv_order_date_text }' not recognized; defaulted to SY-DATUM.|. + APPEND ls_ret TO et_return. + ENDIF. + + " --- Segment fill (typed) + DATA: ls_seg TYPE zonlineorder. + CLEAR ls_seg. + ls_seg-order_id = lv_order_id. + ls_seg-order_date = lv_order_date. + ls_seg-customer_id = lv_customer_id. + ls_seg-product = lv_product. + WRITE lv_quantity_txt TO ls_seg-quantity. + WRITE lv_unit_price_txt TO ls_seg-unit_price DECIMALS 2. + ls_seg-ship_address = lv_ship_addr. + ls_seg-payment_method = lv_pay_method. + ls_seg-order_status = lv_order_status. + ls_seg-tracking_number = lv_tracking. + WRITE lv_items_in_cart_txt TO ls_seg-items_in_cart. + ls_seg-coupon_code = lv_coupon_code. + ls_seg-referral_source = lv_ref_source. + WRITE lv_total_price_txt TO ls_seg-total_price DECIMALS 2. + + " --- Branch: inbound vs outbound + IF iv_direction = 'I'. + " Inbound (status 64) + DATA: lt_data TYPE STANDARD TABLE OF edidd WITH DEFAULT KEY, + ls_data TYPE edidd, + ls_ctrl TYPE edidc. + CLEAR: lt_data, ls_data, ls_ctrl. + + ls_data-segnam = iv_segtp. + ls_data-sdata = ls_seg. + APPEND ls_data TO lt_data. + + ls_ctrl-mestyp = iv_mestyp. + ls_ctrl-idoctp = iv_idoctyp. + ls_ctrl-direct = '2'. + ls_ctrl-rcvprt = 'LS'. + ls_ctrl-rcvprn = 'LOCAL'. + ls_ctrl-sndprt = 'LS'. + ls_ctrl-sndprn = 'LOCAL'. + + CALL FUNCTION 'IDOC_INBOUND_WRITE_TO_DB' + TABLES + t_data_records = lt_data + CHANGING + pc_control_record = ls_ctrl + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc = 0. + ev_docnum = ls_ctrl-docnum. + CLEAR ls_ret. + ls_ret-type = 'S'. + ls_ret-id = 'ZORD'. + ls_ret-number = '010'. + ls_ret-message = |Row { lv_idx }: Inbound IDoc created (status 64). DOCNUM={ ev_docnum }.|. + APPEND ls_ret TO et_return. + ELSE. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '011'. + ls_ret-message = |Row { lv_idx }: IDOC_INBOUND_WRITE_TO_DB failed.|. + APPEND ls_ret TO et_return. + ENDIF. + + ELSE. + +" --- Outbound (create & dispatch all, return all DOCNUMs) ------------- +DATA: ls_ctrl_o TYPE edidc, " EDI_DC40 + ls_data_o TYPE edidd, + t_ctrl_o TYPE STANDARD TABLE OF edidc WITH DEFAULT KEY, + t_data_o TYPE STANDARD TABLE OF edidd WITH DEFAULT KEY. + +CLEAR: ls_ctrl_o, ls_data_o. +CLEAR: t_ctrl_o, t_data_o. + +" Segment record +ls_data_o-segnam = iv_segtp. " <-- ensure consistency: IV_SEGTYP vs IV_SEGTP +ls_data_o-sdata = ls_seg. +APPEND ls_data_o TO t_data_o. + +" Control record (outbound) +ls_ctrl_o-mestyp = iv_mestyp. +ls_ctrl_o-idoctp = iv_idoctyp. +ls_ctrl_o-direct = '1'. +ls_ctrl_o-sndprt = COND #( WHEN iv_sndprt IS INITIAL THEN 'LS' ELSE iv_sndprt ). +ls_ctrl_o-sndprn = COND #( WHEN iv_sndprn IS INITIAL THEN 'LOCAL' ELSE iv_sndprn ). +ls_ctrl_o-rcvprt = COND #( WHEN iv_rcvprt IS INITIAL THEN 'LS' ELSE iv_rcvprt ). +ls_ctrl_o-rcvprn = COND #( WHEN iv_rcvprn IS INITIAL THEN 'LOCAL' ELSE iv_rcvprn ). +ls_ctrl_o-rcvpor = iv_rcvpor. + +" Append control to the comm table BEFORE calling the FM +APPEND ls_ctrl_o TO t_ctrl_o. + +" Create IDoc(s) → status 30 +CALL FUNCTION 'MASTER_IDOC_DISTRIBUTE' + EXPORTING + master_idoc_control = ls_ctrl_o + TABLES + communication_idoc_control = t_ctrl_o + master_idoc_data = t_data_o + EXCEPTIONS + error_in_idoc_control = 1 + error_writing_idoc_status = 2 + error_in_idoc_data = 3 + sending_logical_system_unknown = 4 + OTHERS = 5. + +IF sy-subrc = 0. + + " Collect all DOCNUMs from t_ctrl_o + REFRESH et_docnums. + CLEAR ev_docnum. + + LOOP AT t_ctrl_o INTO ls_ctrl_o WHERE docnum IS NOT INITIAL. + APPEND ls_ctrl_o-docnum TO et_docnums. " et_docnums is STANDARD TABLE OF EDI_DOCNUM + ev_docnum = ls_ctrl_o-docnum. " keep last for convenience + ENDLOOP. + + " Optional: dispatch each IDoc immediately (avoid status 30) + "LOOP AT et_docnums ASSIGNING FIELD-SYMBOL(). + "CALL FUNCTION 'IDOC_START_OUTBOUND' + " EXPORTING + " idoc_number = + " EXCEPTIONS + " OTHERS = 1. + "ENDLOOP. + + CALL FUNCTION 'DB_COMMIT'. + CALL FUNCTION 'DEQUEUE_ALL'. " or EDI_DOCUMENT_DEQUEUE_LATER for individual IDocs + COMMIT WORK AND WAIT. + + DATA(lv_cnt) = lines( et_docnums ). + DATA(lv_msg) = |Outbound IDoc(s) created and dispatched. Count={ lv_cnt }.|. + CLEAR ls_ret. + ls_ret-type = 'S'. + ls_ret-id = 'ZORD'. + ls_ret-number = '020'. + ls_ret-message = lv_msg. + APPEND ls_ret TO et_return. + +ELSE. + CLEAR ls_ret. + ls_ret-type = 'E'. + ls_ret-id = 'ZORD'. + ls_ret-number = '021'. + ls_ret-message = |MASTER_IDOC_DISTRIBUTE failed (SY-SUBRC={ sy-subrc }).|. + APPEND ls_ret TO et_return. +ENDIF. + + + ENDIF. + + ENDLOOP. + + " Commit once at the end (batch-friendly) + COMMIT WORK AND WAIT. + +ENDFUNCTION. diff --git a/agentic-sap-workflows/abapgitexported/src/z_get_orders_analysis.abap b/agentic-sap-workflows/abapgitexported/src/z_get_orders_analysis.abap new file mode 100644 index 0000000..7eebee6 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/z_get_orders_analysis.abap @@ -0,0 +1,39 @@ +FUNCTION Z_GET_ORDERS_ANALYSIS. +*"---------------------------------------------------------------------- +*"*"Local Interface: +*" IMPORTING +*" VALUE(DEST) TYPE CHAR20 DEFAULT 'YOURDESTINATION' +*" EXPORTING +*" VALUE(EXCEPTIONMSG) TYPE ZCHAR1000 +*" VALUE(ANALYSIS) TYPE STRING +*" TABLES +*" IT_CSV STRUCTURE ZTY_CSV_LINE +*" CHANGING +*" VALUE(RETURN) TYPE BAPIRET2 OPTIONAL +*" EXCEPTIONS +*" SENDEXCEPTIONTOSAPSERVER +*"---------------------------------------------------------------------- +CALL FUNCTION 'Z_GET_ORDERS_ANALYSIS' DESTINATION DEST + IMPORTING + ANALYSIS = ANALYSIS + TABLES + IT_CSV = IT_CSV + CHANGING + RETURN = RETURN + EXCEPTIONS + SENDEXCEPTIONTOSAPSERVER = 1 + system_failure = 2 MESSAGE EXCEPTIONMSG + communication_failure = 3 MESSAGE EXCEPTIONMSG + OTHERS = 4. + +CASE sy-subrc. + WHEN 0. + EXCEPTIONMSG = 'ok'. + WHEN 1. + EXCEPTIONMSG = |Exception from workflow: SENDEXCEPTIONTOSAPSERVER { sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv4 } |. + WHEN 2 or 3. + WHEN OTHERS. + EXCEPTIONMSG = |Error in workflow: { sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv4 } |. +ENDCASE. + +ENDFUNCTION. diff --git a/agentic-sap-workflows/abapgitexported/src/zabapgit_standalone.prog.abap b/agentic-sap-workflows/abapgitexported/src/zabapgit_standalone.prog.abap new file mode 100644 index 0000000..bf4f9e0 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zabapgit_standalone.prog.abap @@ -0,0 +1,147060 @@ +REPORT zabapgit_standalone LINE-SIZE 100. + +* See http://www.abapgit.org + +******************************************************************************** +* The MIT License (MIT) +* +* Copyright (c) 2014 abapGit Contributors +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +******************************************************************************** + +INTERFACE zif_abapgit_version DEFERRED. +INTERFACE zif_abapgit_definitions DEFERRED. +INTERFACE zif_abapgit_xml_output DEFERRED. +INTERFACE zif_abapgit_xml_input DEFERRED. +INTERFACE zif_abapgit_log DEFERRED. +INTERFACE zif_abapgit_popups DEFERRED. +INTERFACE zif_abapgit_frontend_services DEFERRED. +INTERFACE zif_abapgit_services_repo DEFERRED. +INTERFACE zif_abapgit_services_git DEFERRED. +INTERFACE zif_abapgit_progress DEFERRED. +INTERFACE zif_abapgit_gui_diff_extra DEFERRED. +INTERFACE zif_abapgit_gui_diff DEFERRED. +INTERFACE zif_abapgit_html_table DEFERRED. +INTERFACE zif_abapgit_html_popup DEFERRED. +INTERFACE zif_abapgit_html_form DEFERRED. +INTERFACE zif_abapgit_gui_render_item DEFERRED. +INTERFACE zif_abapgit_gui_page_title DEFERRED. +INTERFACE zif_abapgit_gui_menu_provider DEFERRED. +INTERFACE zif_abapgit_flow_logic DEFERRED. +INTERFACE zif_abapgit_flow_exit DEFERRED. +INTERFACE zif_abapgit_html_viewer DEFERRED. +INTERFACE zif_abapgit_html DEFERRED. +INTERFACE zif_abapgit_gui_services DEFERRED. +INTERFACE zif_abapgit_gui_renderable DEFERRED. +INTERFACE zif_abapgit_gui_modal DEFERRED. +INTERFACE zif_abapgit_gui_html_processor DEFERRED. +INTERFACE zif_abapgit_gui_hotkeys DEFERRED. +INTERFACE zif_abapgit_gui_hotkey_ctl DEFERRED. +INTERFACE zif_abapgit_gui_event_handler DEFERRED. +INTERFACE zif_abapgit_gui_event DEFERRED. +INTERFACE zif_abapgit_gui_error_handler DEFERRED. +INTERFACE zif_abapgit_gui_asset_manager DEFERRED. +INTERFACE zif_abapgit_repo_srv DEFERRED. +INTERFACE zif_abapgit_repo_online DEFERRED. +INTERFACE zif_abapgit_repo_listener DEFERRED. +INTERFACE zif_abapgit_repo_checksums DEFERRED. +INTERFACE zif_abapgit_repo DEFERRED. +INTERFACE zif_abapgit_dot_abapgit DEFERRED. +INTERFACE zif_abapgit_status_calc DEFERRED. +INTERFACE zif_abapgit_stage_logic DEFERRED. +INTERFACE zif_abapgit_merge DEFERRED. +INTERFACE zif_abapgit_object_filter DEFERRED. +INTERFACE zif_abapgit_persistence DEFERRED. +INTERFACE zif_abapgit_persist_user DEFERRED. +INTERFACE zif_abapgit_persist_settings DEFERRED. +INTERFACE zif_abapgit_persist_repo_cs DEFERRED. +INTERFACE zif_abapgit_persist_repo DEFERRED. +INTERFACE zif_abapgit_persist_packages DEFERRED. +INTERFACE zif_abapgit_persist_background DEFERRED. +INTERFACE zif_abapgit_objects DEFERRED. +INTERFACE zif_abapgit_object DEFERRED. +INTERFACE zif_abapgit_comparator DEFERRED. +INTERFACE zif_abapgit_lxe_texts DEFERRED. +INTERFACE zif_abapgit_longtexts DEFERRED. +INTERFACE zif_abapgit_lang_definitions DEFERRED. +INTERFACE zif_abapgit_i18n_file DEFERRED. +INTERFACE zif_abapgit_object_tabl DEFERRED. +INTERFACE zif_abapgit_sap_report DEFERRED. +INTERFACE zif_abapgit_sap_package DEFERRED. +INTERFACE zif_abapgit_sap_namespace DEFERRED. +INTERFACE zif_abapgit_function_module DEFERRED. +INTERFACE zif_abapgit_field_rules DEFERRED. +INTERFACE zif_abapgit_oo_object_fnc DEFERRED. +INTERFACE zif_abapgit_gui_jumper DEFERRED. +INTERFACE zif_abapgit_object_enhs DEFERRED. +INTERFACE zif_abapgit_object_enho DEFERRED. +INTERFACE zif_abapgit_ecatt_upload DEFERRED. +INTERFACE zif_abapgit_ecatt_download DEFERRED. +INTERFACE zif_abapgit_ecatt DEFERRED. +INTERFACE zif_abapgit_tadir DEFERRED. +INTERFACE zif_abapgit_aff_types_v1 DEFERRED. +INTERFACE zif_abapgit_aff_oo_types_v1 DEFERRED. +INTERFACE zif_abapgit_aff_intf_v1 DEFERRED. +INTERFACE zif_abapgit_aff_type_mapping DEFERRED. +INTERFACE zif_abapgit_aff_registry DEFERRED. +INTERFACE zif_abapgit_ajson_types DEFERRED. +INTERFACE zif_abapgit_ajson_ref_init DEFERRED. +INTERFACE zif_abapgit_ajson_mapping DEFERRED. +INTERFACE zif_abapgit_ajson_iterator DEFERRED. +INTERFACE zif_abapgit_ajson_filter DEFERRED. +INTERFACE zif_abapgit_ajson DEFERRED. +INTERFACE zif_abapgit_code_inspector DEFERRED. +INTERFACE zif_abapgit_http_response DEFERRED. +INTERFACE zif_abapgit_http_agent DEFERRED. +INTERFACE zif_abapgit_pr_enum_provider DEFERRED. +INTERFACE zif_abapgit_git_transport DEFERRED. +INTERFACE zif_abapgit_git_definitions DEFERRED. +INTERFACE zif_abapgit_git_branch_list DEFERRED. +INTERFACE zif_abapgit_gitv2_porcelain DEFERRED. +INTERFACE zif_abapgit_exit DEFERRED. +INTERFACE zif_abapgit_auth DEFERRED. +INTERFACE zif_abapgit_user_record DEFERRED. +INTERFACE zif_abapgit_environment DEFERRED. +INTERFACE zif_abapgit_diff DEFERRED. +INTERFACE zif_abapgit_diff3 DEFERRED. +INTERFACE zif_abapgit_data_supporter DEFERRED. +INTERFACE zif_abapgit_data_serializer DEFERRED. +INTERFACE zif_abapgit_data_deserializer DEFERRED. +INTERFACE zif_abapgit_data_config DEFERRED. +INTERFACE zif_abapgit_default_transport DEFERRED. +INTERFACE zif_abapgit_cts_api DEFERRED. +INTERFACE zif_abapgit_background DEFERRED. +INTERFACE zif_abapgit_apack_definitions DEFERRED. +CLASS zcl_abapgit_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_xml_pretty DEFINITION DEFERRED. +CLASS zcl_abapgit_xml_output DEFINITION DEFERRED. +CLASS zcl_abapgit_xml_input DEFINITION DEFERRED. +CLASS zcl_abapgit_xml DEFINITION DEFERRED. +CLASS zcl_abapgit_utils DEFINITION DEFERRED. +CLASS zcl_abapgit_timer DEFINITION DEFERRED. +CLASS zcl_abapgit_string_map DEFINITION DEFERRED. +CLASS zcl_abapgit_string_buffer DEFINITION DEFERRED. +CLASS zcl_abapgit_path DEFINITION DEFERRED. +CLASS zcl_abapgit_log DEFINITION DEFERRED. +CLASS zcl_abapgit_convert DEFINITION DEFERRED. +CLASS zcl_abapgit_ui_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_popups DEFINITION DEFERRED. +CLASS zcl_abapgit_password_dialog DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_hotkey_ctl DEFINITION DEFERRED. +CLASS zcl_abapgit_frontend_services DEFINITION DEFERRED. +CLASS zcl_abapgit_frontend_no_gui DEFINITION DEFERRED. +CLASS zcl_abapgit_services_repo DEFINITION DEFERRED. +CLASS zcl_abapgit_services_git DEFINITION DEFERRED. +CLASS zcl_abapgit_services_abapgit DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_router DEFINITION DEFERRED. +CLASS zcl_abapgit_progress DEFINITION DEFERRED. +CLASS zcl_abapgit_popup_tag_list DEFINITION DEFERRED. +CLASS zcl_abapgit_popup_pull_request DEFINITION DEFERRED. +CLASS zcl_abapgit_popup_code_insp DEFINITION DEFERRED. +CLASS zcl_abapgit_popup_branch_list DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_tutorial DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_tags DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_stage DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_run_bckg DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_repo_view DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_repo_over DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_pull DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_merge_sel DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_merge_res DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_merge DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_ex_pckage DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_ex_object DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_debuginfo DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_data DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_cpackage DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_commit DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_chg_pckg DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_sett_repo DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_sett_remo DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_sett_pers DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_sett_locl DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_sett_info DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_sett_glob DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_sett_bckg DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_cr_repo DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_addonline DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_addofflin DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_patch DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_diff_file DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_diff_base DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_diff DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_db_entry DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_db DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_whereused DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_syntax DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_runit DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_codi_base DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_code_insp DEFINITION DEFERRED. +CLASS zcl_abapgit_log_viewer DEFINITION DEFERRED. +CLASS zcl_abapgit_html_toolbar DEFINITION DEFERRED. +CLASS zcl_abapgit_html_table DEFINITION DEFERRED. +CLASS zcl_abapgit_html_form_utils DEFINITION DEFERRED. +CLASS zcl_abapgit_html_form DEFINITION DEFERRED. +CLASS zcl_abapgit_html_action_utils DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_picklist DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_hoc DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_menus DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_in_page_modal DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_component DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_chunk_lib DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_buttons DEFINITION DEFERRED. +CLASS zcl_abapgit_exception_viewer DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_flowcons DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_flow DEFINITION DEFERRED. +CLASS zcl_abapgit_flow_page_utils DEFINITION DEFERRED. +CLASS zcl_abapgit_flow_logic DEFINITION DEFERRED. +CLASS zcl_abapgit_flow_git DEFINITION DEFERRED. +CLASS zcl_abapgit_flow_exit DEFINITION DEFERRED. +CLASS zcl_abapgit_ui_core_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_html_viewer_gui DEFINITION DEFERRED. +CLASS zcl_abapgit_html_parts DEFINITION DEFERRED. +CLASS zcl_abapgit_html DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_utils DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_html_processor DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_event DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_css_processor DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_asset_manager DEFINITION DEFERRED. +CLASS zcl_abapgit_gui DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_page_template DEFINITION DEFERRED. +CLASS zcl_abapgit_syntax_xml DEFINITION DEFERRED. +CLASS zcl_abapgit_syntax_txt DEFINITION DEFERRED. +CLASS zcl_abapgit_syntax_po DEFINITION DEFERRED. +CLASS zcl_abapgit_syntax_json DEFINITION DEFERRED. +CLASS zcl_abapgit_syntax_js DEFINITION DEFERRED. +CLASS zcl_abapgit_syntax_highlighter DEFINITION DEFERRED. +CLASS zcl_abapgit_syntax_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_syntax_css DEFINITION DEFERRED. +CLASS zcl_abapgit_syntax_abap DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_status DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_srv DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_online DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_offline DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_cs_migration DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_content_list DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_checksums DEFINITION DEFERRED. +CLASS zcl_abapgit_repo DEFINITION DEFERRED. +CLASS zcl_abapgit_dot_abapgit DEFINITION DEFERRED. +CLASS zcl_abapgit_zip DEFINITION DEFERRED. +CLASS zcl_abapgit_version DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_requirements DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_news DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_labels DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_item_state DEFINITION DEFERRED. +CLASS zcl_abapgit_status_calc DEFINITION DEFERRED. +CLASS zcl_abapgit_stage_logic DEFINITION DEFERRED. +CLASS zcl_abapgit_stage DEFINITION DEFERRED. +CLASS zcl_abapgit_merge DEFINITION DEFERRED. +CLASS zcl_abapgit_repo_filter DEFINITION DEFERRED. +CLASS zcl_abapgit_object_filter_tran DEFINITION DEFERRED. +CLASS zcl_abapgit_object_filter_obj DEFINITION DEFERRED. +CLASS zcl_abapgit_persistence_user DEFINITION DEFERRED. +CLASS zcl_abapgit_persistence_repo DEFINITION DEFERRED. +CLASS zcl_abapgit_persistence_db DEFINITION DEFERRED. +CLASS zcl_abapgit_persist_settings DEFINITION DEFERRED. +CLASS zcl_abapgit_persist_packages DEFINITION DEFERRED. +CLASS zcl_abapgit_persist_migrate DEFINITION DEFERRED. +CLASS zcl_abapgit_persist_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_persist_background DEFINITION DEFERRED. +CLASS zcl_abapgit_migrations DEFINITION DEFERRED. +CLASS zcl_abapgit_objects_super DEFINITION DEFERRED. +CLASS zcl_abapgit_objects_program DEFINITION DEFERRED. +CLASS zcl_abapgit_objects_generic DEFINITION DEFERRED. +CLASS zcl_abapgit_objects_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_objects_bridge DEFINITION DEFERRED. +CLASS zcl_abapgit_objects DEFINITION DEFERRED. +CLASS zcl_abapgit_object_xslt DEFINITION DEFERRED. +CLASS zcl_abapgit_object_xinx DEFINITION DEFERRED. +CLASS zcl_abapgit_object_webi DEFINITION DEFERRED. +CLASS zcl_abapgit_object_wdyn DEFINITION DEFERRED. +CLASS zcl_abapgit_object_wdya DEFINITION DEFERRED. +CLASS zcl_abapgit_object_wdcc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_wdca DEFINITION DEFERRED. +CLASS zcl_abapgit_object_wapa DEFINITION DEFERRED. +CLASS zcl_abapgit_object_w3xx_super DEFINITION DEFERRED. +CLASS zcl_abapgit_object_w3mi DEFINITION DEFERRED. +CLASS zcl_abapgit_object_w3ht DEFINITION DEFERRED. +CLASS zcl_abapgit_object_view DEFINITION DEFERRED. +CLASS zcl_abapgit_object_vcls DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ueno DEFINITION DEFERRED. +CLASS zcl_abapgit_object_udmo DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ucsa DEFINITION DEFERRED. +CLASS zcl_abapgit_object_type DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ttyp DEFINITION DEFERRED. +CLASS zcl_abapgit_object_tran DEFINITION DEFERRED. +CLASS zcl_abapgit_object_tobj DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sxsd DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sxci DEFINITION DEFERRED. +CLASS zcl_abapgit_object_suso DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sush DEFINITION DEFERRED. +CLASS zcl_abapgit_object_susc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sucu DEFINITION DEFERRED. +CLASS zcl_abapgit_object_styl DEFINITION DEFERRED. +CLASS zcl_abapgit_object_stvi DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ssst DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ssfo DEFINITION DEFERRED. +CLASS zcl_abapgit_object_srvd DEFINITION DEFERRED. +CLASS zcl_abapgit_object_srvb DEFINITION DEFERRED. +CLASS zcl_abapgit_object_srfc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sqsc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sprx DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sppf DEFINITION DEFERRED. +CLASS zcl_abapgit_object_splo DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sots DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sod2 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sod1 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sobj DEFINITION DEFERRED. +CLASS zcl_abapgit_object_smtg DEFINITION DEFERRED. +CLASS zcl_abapgit_object_smim DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sktd DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sicf DEFINITION DEFERRED. +CLASS zcl_abapgit_object_shma DEFINITION DEFERRED. +CLASS zcl_abapgit_object_shlp DEFINITION DEFERRED. +CLASS zcl_abapgit_object_shi8 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_shi5 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_shi3 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sfsw DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sfpi DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sfpf DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sfbs DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sfbf DEFINITION DEFERRED. +CLASS zcl_abapgit_object_scvi DEFINITION DEFERRED. +CLASS zcl_abapgit_object_scp1 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_saxx_super DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sapc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_samc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_prog DEFINITION DEFERRED. +CLASS zcl_abapgit_object_prag DEFINITION DEFERRED. +CLASS zcl_abapgit_object_pinf DEFINITION DEFERRED. +CLASS zcl_abapgit_object_pers DEFINITION DEFERRED. +CLASS zcl_abapgit_object_pdxx_super DEFINITION DEFERRED. +CLASS zcl_abapgit_object_pdts DEFINITION DEFERRED. +CLASS zcl_abapgit_object_para DEFINITION DEFERRED. +CLASS zcl_abapgit_object_otgr DEFINITION DEFERRED. +CLASS zcl_abapgit_object_odso DEFINITION DEFERRED. +CLASS zcl_abapgit_object_oa2p DEFINITION DEFERRED. +CLASS zcl_abapgit_object_nspc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_nrob DEFINITION DEFERRED. +CLASS zcl_abapgit_object_msag DEFINITION DEFERRED. +CLASS zcl_abapgit_object_jobd DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iwvb DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iwsv DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iwsg DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iwpr DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iwom DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iwmo DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iobj DEFINITION DEFERRED. +CLASS zcl_abapgit_object_intf DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iext DEFINITION DEFERRED. +CLASS zcl_abapgit_object_idoc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iaxu DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iatu DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iasp DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iarp DEFINITION DEFERRED. +CLASS zcl_abapgit_object_iamu DEFINITION DEFERRED. +CLASS zcl_abapgit_object_http DEFINITION DEFERRED. +CLASS zcl_abapgit_object_g4bs DEFINITION DEFERRED. +CLASS zcl_abapgit_object_g4ba DEFINITION DEFERRED. +CLASS zcl_abapgit_object_fugs DEFINITION DEFERRED. +CLASS zcl_abapgit_object_fugr DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ftgl DEFINITION DEFERRED. +CLASS zcl_abapgit_object_form DEFINITION DEFERRED. +CLASS zcl_abapgit_object_fdt0 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ensc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enqu DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enhs DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enho DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enhc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ecvo DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ectd DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ectc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ecsp DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ecsd DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ecatt_super DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ecat DEFINITION DEFERRED. +CLASS zcl_abapgit_object_dtel DEFINITION DEFERRED. +CLASS zcl_abapgit_object_dtdc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_dsys DEFINITION DEFERRED. +CLASS zcl_abapgit_object_drul DEFINITION DEFERRED. +CLASS zcl_abapgit_object_doma DEFINITION DEFERRED. +CLASS zcl_abapgit_object_docv DEFINITION DEFERRED. +CLASS zcl_abapgit_object_doct DEFINITION DEFERRED. +CLASS zcl_abapgit_object_dial DEFINITION DEFERRED. +CLASS zcl_abapgit_object_devc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ddlx DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ddls DEFINITION DEFERRED. +CLASS zcl_abapgit_object_dcls DEFINITION DEFERRED. +CLASS zcl_abapgit_object_cus2 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_cus1 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_cus0 DEFINITION DEFERRED. +CLASS zcl_abapgit_object_cmpt DEFINITION DEFERRED. +CLASS zcl_abapgit_object_cmod DEFINITION DEFERRED. +CLASS zcl_abapgit_object_clas DEFINITION DEFERRED. +CLASS zcl_abapgit_object_chdo DEFINITION DEFERRED. +CLASS zcl_abapgit_object_char DEFINITION DEFERRED. +CLASS zcl_abapgit_object_bdef DEFINITION DEFERRED. +CLASS zcl_abapgit_object_avas DEFINITION DEFERRED. +CLASS zcl_abapgit_object_avar DEFINITION DEFERRED. +CLASS zcl_abapgit_object_auth DEFINITION DEFERRED. +CLASS zcl_abapgit_object_asfc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_area DEFINITION DEFERRED. +CLASS zcl_abapgit_object_aqsg DEFINITION DEFERRED. +CLASS zcl_abapgit_object_aqqu DEFINITION DEFERRED. +CLASS zcl_abapgit_object_aqbg DEFINITION DEFERRED. +CLASS zcl_abapgit_object_apis DEFINITION DEFERRED. +CLASS zcl_abapgit_object_amsd DEFINITION DEFERRED. +CLASS zcl_abapgit_object_aifc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_acid DEFINITION DEFERRED. +CLASS zcl_abapgit_sots_handler DEFINITION DEFERRED. +CLASS zcl_abapgit_sotr_handler DEFINITION DEFERRED. +CLASS zcl_abapgit_properties_file DEFINITION DEFERRED. +CLASS zcl_abapgit_po_file DEFINITION DEFERRED. +CLASS zcl_abapgit_lxe_texts DEFINITION DEFERRED. +CLASS zcl_abapgit_longtexts DEFINITION DEFERRED. +CLASS zcl_abapgit_i18n_params DEFINITION DEFERRED. +CLASS zcl_abapgit_object_tabl_ddl DEFINITION DEFERRED. +CLASS zcl_abapgit_object_tabl_compar DEFINITION DEFERRED. +CLASS zcl_abapgit_object_tabl DEFINITION DEFERRED. +CLASS zcl_abapgit_sap_report DEFINITION DEFERRED. +CLASS zcl_abapgit_sap_package DEFINITION DEFERRED. +CLASS zcl_abapgit_sap_namespace DEFINITION DEFERRED. +CLASS zcl_abapgit_function_module DEFINITION DEFERRED. +CLASS zcl_abapgit_field_rules DEFINITION DEFERRED. +CLASS zcl_abapgit_oo_serializer DEFINITION DEFERRED. +CLASS zcl_abapgit_oo_interface DEFINITION DEFERRED. +CLASS zcl_abapgit_oo_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_oo_class DEFINITION DEFERRED. +CLASS zcl_abapgit_oo_base DEFINITION DEFERRED. +CLASS zcl_abapgit_gui_jumper DEFINITION DEFERRED. +CLASS zcl_abapgit_adt_link DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enhs_hook_d DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enhs_badi_d DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enho_wdyn DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enho_wdyc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enho_intf DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enho_hook DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enho_fugr DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enho_clif DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enho_class DEFINITION DEFERRED. +CLASS zcl_abapgit_object_enho_badi DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_val_obj_upl DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_val_obj_down DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_system_upl DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_system_downl DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_sp_upload DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_sp_download DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_script_upl DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_script_downl DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_helper DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_data_upload DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_data_downl DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_config_upl DEFINITION DEFERRED. +CLASS zcl_abapgit_ecatt_config_downl DEFINITION DEFERRED. +CLASS zcl_abapgit_tadir DEFINITION DEFERRED. +CLASS zcl_abapgit_serialize DEFINITION DEFERRED. +CLASS zcl_abapgit_objects_files DEFINITION DEFERRED. +CLASS zcl_abapgit_objects_compare DEFINITION DEFERRED. +CLASS zcl_abapgit_objects_check DEFINITION DEFERRED. +CLASS zcl_abapgit_objects_activation DEFINITION DEFERRED. +CLASS zcl_abapgit_item_graph DEFINITION DEFERRED. +CLASS zcl_abapgit_folder_logic DEFINITION DEFERRED. +CLASS zcl_abapgit_filename_logic DEFINITION DEFERRED. +CLASS zcl_abapgit_file_deserialize DEFINITION DEFERRED. +CLASS zcl_abapgit_dependencies DEFINITION DEFERRED. +CLASS zcl_abapgit_object_uist DEFINITION DEFERRED. +CLASS zcl_abapgit_object_uipg DEFINITION DEFERRED. +CLASS zcl_abapgit_object_uiad DEFINITION DEFERRED. +CLASS zcl_abapgit_object_swcr DEFINITION DEFERRED. +CLASS zcl_abapgit_object_smbc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sajt DEFINITION DEFERRED. +CLASS zcl_abapgit_object_sajc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_ront DEFINITION DEFERRED. +CLASS zcl_abapgit_object_nont DEFINITION DEFERRED. +CLASS zcl_abapgit_object_gsmp DEFINITION DEFERRED. +CLASS zcl_abapgit_object_evtb DEFINITION DEFERRED. +CLASS zcl_abapgit_object_eeec DEFINITION DEFERRED. +CLASS zcl_abapgit_object_dteb DEFINITION DEFERRED. +CLASS zcl_abapgit_object_dsfi DEFINITION DEFERRED. +CLASS zcl_abapgit_object_dsfd DEFINITION DEFERRED. +CLASS zcl_abapgit_object_drty DEFINITION DEFERRED. +CLASS zcl_abapgit_object_dras DEFINITION DEFERRED. +CLASS zcl_abapgit_object_cota DEFINITION DEFERRED. +CLASS zcl_abapgit_object_common_aff DEFINITION DEFERRED. +CLASS zcl_abapgit_object_chkv DEFINITION DEFERRED. +CLASS zcl_abapgit_object_chko DEFINITION DEFERRED. +CLASS zcl_abapgit_object_chkc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_cdbo DEFINITION DEFERRED. +CLASS zcl_abapgit_object_bgqc DEFINITION DEFERRED. +CLASS zcl_abapgit_object_aplo DEFINITION DEFERRED. +CLASS zcl_abapgit_json_path DEFINITION DEFERRED. +CLASS zcl_abapgit_json_handler DEFINITION DEFERRED. +CLASS zcl_abapgit_aff_registry DEFINITION DEFERRED. +CLASS zcl_abapgit_aff_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_ajson_utilities DEFINITION DEFERRED. +CLASS zcl_abapgit_ajson_ref_init_lib DEFINITION DEFERRED. +CLASS zcl_abapgit_ajson_mapping DEFINITION DEFERRED. +CLASS zcl_abapgit_ajson_filter_lib DEFINITION DEFERRED. +CLASS zcl_abapgit_ajson DEFINITION DEFERRED. +CLASS zcl_abapgit_where_used_tools DEFINITION DEFERRED. +CLASS zcl_abapgit_code_inspector DEFINITION DEFERRED. +CLASS zcl_abapgit_url DEFINITION DEFERRED. +CLASS zcl_abapgit_proxy_config DEFINITION DEFERRED. +CLASS zcl_abapgit_proxy_auth DEFINITION DEFERRED. +CLASS zcl_abapgit_login_manager DEFINITION DEFERRED. +CLASS zcl_abapgit_http_digest DEFINITION DEFERRED. +CLASS zcl_abapgit_http_client DEFINITION DEFERRED. +CLASS zcl_abapgit_http_agent DEFINITION DEFERRED. +CLASS zcl_abapgit_http DEFINITION DEFERRED. +CLASS zcl_abapgit_pr_enumerator DEFINITION DEFERRED. +CLASS zcl_abapgit_pr_enum_github DEFINITION DEFERRED. +CLASS zcl_abapgit_pr_enum_gitea DEFINITION DEFERRED. +CLASS zcl_abapgit_git_url DEFINITION DEFERRED. +CLASS zcl_abapgit_zlib_stream DEFINITION DEFERRED. +CLASS zcl_abapgit_zlib_huffman DEFINITION DEFERRED. +CLASS zcl_abapgit_zlib_convert DEFINITION DEFERRED. +CLASS zcl_abapgit_zlib DEFINITION DEFERRED. +CLASS zcl_abapgit_hash DEFINITION DEFERRED. +CLASS zcl_abapgit_git_utils DEFINITION DEFERRED. +CLASS zcl_abapgit_git_transport DEFINITION DEFERRED. +CLASS zcl_abapgit_git_time DEFINITION DEFERRED. +CLASS zcl_abapgit_git_tag DEFINITION DEFERRED. +CLASS zcl_abapgit_git_porcelain DEFINITION DEFERRED. +CLASS zcl_abapgit_git_pack DEFINITION DEFERRED. +CLASS zcl_abapgit_git_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_git_delta DEFINITION DEFERRED. +CLASS zcl_abapgit_git_commit DEFINITION DEFERRED. +CLASS zcl_abapgit_git_branch_utils DEFINITION DEFERRED. +CLASS zcl_abapgit_git_branch_list DEFINITION DEFERRED. +CLASS zcl_abapgit_git_add_patch DEFINITION DEFERRED. +CLASS zcl_abapgit_gitv2_porcelain DEFINITION DEFERRED. +CLASS zcl_abapgit_exit DEFINITION DEFERRED. +CLASS zcl_abapgit_auth DEFINITION DEFERRED. +CLASS zcl_abapgit_user_record DEFINITION DEFERRED. +CLASS zcl_abapgit_settings DEFINITION DEFERRED. +CLASS zcl_abapgit_language DEFINITION DEFERRED. +CLASS zcl_abapgit_feature DEFINITION DEFERRED. +CLASS zcl_abapgit_environment DEFINITION DEFERRED. +CLASS zcl_abapgit_env_injector DEFINITION DEFERRED. +CLASS zcl_abapgit_env_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_abap_language_vers DEFINITION DEFERRED. +CLASS zcl_abapgit_diff_std DEFINITION DEFERRED. +CLASS zcl_abapgit_diff_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_diff_diff3 DEFINITION DEFERRED. +CLASS zcl_abapgit_diff DEFINITION DEFERRED. +CLASS zcl_abapgit_diff3 DEFINITION DEFERRED. +CLASS zcl_abapgit_data_utils DEFINITION DEFERRED. +CLASS zcl_abapgit_data_supporter DEFINITION DEFERRED. +CLASS zcl_abapgit_data_serializer DEFINITION DEFERRED. +CLASS zcl_abapgit_data_injector DEFINITION DEFERRED. +CLASS zcl_abapgit_data_factory DEFINITION DEFERRED. +CLASS zcl_abapgit_data_deserializer DEFINITION DEFERRED. +CLASS zcl_abapgit_data_config DEFINITION DEFERRED. +CLASS zcl_abapgit_transport_objects DEFINITION DEFERRED. +CLASS zcl_abapgit_transport_mass DEFINITION DEFERRED. +CLASS zcl_abapgit_transport_2_branch DEFINITION DEFERRED. +CLASS zcl_abapgit_transport DEFINITION DEFERRED. +CLASS zcl_abapgit_default_transport DEFINITION DEFERRED. +CLASS zcl_abapgit_cts_api DEFINITION DEFERRED. +CLASS zcl_abapgit_background_push_fi DEFINITION DEFERRED. +CLASS zcl_abapgit_background_push_au DEFINITION DEFERRED. +CLASS zcl_abapgit_background_pull DEFINITION DEFERRED. +CLASS zcl_abapgit_background DEFINITION DEFERRED. +CLASS zcl_abapgit_apack_writer DEFINITION DEFERRED. +CLASS zcl_abapgit_apack_reader DEFINITION DEFERRED. +CLASS zcl_abapgit_apack_migration DEFINITION DEFERRED. +CLASS zcl_abapgit_apack_helper DEFINITION DEFERRED. +CLASS zcx_abapgit_ajson_error DEFINITION + inheriting from CX_STATIC_CHECK + final + create public . + +public section. + + interfaces IF_T100_MESSAGE . + + types: + ty_rc type c length 4 . + + constants: + begin of ZCX_AJSON_ERROR, + msgid type symsgid value '00', + msgno type symsgno value '001', + attr1 type scx_attrname value 'A1', + attr2 type scx_attrname value 'A2', + attr3 type scx_attrname value 'A3', + attr4 type scx_attrname value 'A4', + end of ZCX_AJSON_ERROR . + data RC type TY_RC read-only . + data MESSAGE type STRING read-only . + data LOCATION type STRING read-only . + data A1 type SYMSGV read-only . + data A2 type SYMSGV read-only . + data A3 type SYMSGV read-only . + data A4 type SYMSGV read-only . + + methods CONSTRUCTOR + importing + !TEXTID like IF_T100_MESSAGE=>T100KEY optional + !PREVIOUS like PREVIOUS optional + !RC type TY_RC optional + !MESSAGE type STRING optional + !LOCATION type STRING optional + !A1 type SYMSGV optional + !A2 type SYMSGV optional + !A3 type SYMSGV optional + !A4 type SYMSGV optional . + class-methods RAISE + importing + !IV_MSG type STRING + !IV_LOCATION type STRING optional + !IS_NODE type ANY optional + raising + zcx_abapgit_ajson_error . + methods SET_LOCATION + importing + !IV_LOCATION type STRING optional + !IS_NODE type ANY optional + preferred parameter IV_LOCATION . +protected section. +private section. + types: + begin of ty_message_parts, + a1 like a1, + a2 like a1, + a3 like a1, + a4 like a1, + end of ty_message_parts. +ENDCLASS. +CLASS zcx_abapgit_ajson_error IMPLEMENTATION. +method CONSTRUCTOR. +CALL METHOD SUPER->CONSTRUCTOR +EXPORTING +PREVIOUS = PREVIOUS +. +me->RC = RC . +me->MESSAGE = MESSAGE . +me->LOCATION = LOCATION . +me->A1 = A1 . +me->A2 = A2 . +me->A3 = A3 . +me->A4 = A4 . +clear me->textid. +if textid is initial. + IF_T100_MESSAGE~T100KEY = ZCX_AJSON_ERROR . +else. + IF_T100_MESSAGE~T100KEY = TEXTID. +endif. +endmethod. +method raise. + + data lx type ref to zcx_abapgit_ajson_error. + + create object lx exporting message = iv_msg. + lx->set_location( + iv_location = iv_location + is_node = is_node ). + raise exception lx. + +endmethod. +method set_location. + + data ls_msg type ty_message_parts. + data lv_location type string. + data lv_tmp type string. + field-symbols type string. + field-symbols type string. + + if iv_location is not initial. + lv_location = iv_location. + elseif is_node is not initial. + assign component 'PATH' of structure is_node to . + assign component 'NAME' of structure is_node to . + if is assigned and is assigned. + lv_location = && . + endif. + endif. + + if lv_location is not initial. + lv_tmp = message && | @{ lv_location }|. + else. + lv_tmp = message. + endif. + + ls_msg = lv_tmp. + + location = lv_location. + a1 = ls_msg-a1. + a2 = ls_msg-a2. + a3 = ls_msg-a3. + a4 = ls_msg-a4. + +endmethod. +ENDCLASS. + +"! abapGit general error +CLASS zcx_abapgit_exception DEFINITION + INHERITING FROM cx_static_check + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES if_t100_message . + + TYPES: + BEGIN OF ty_scr_info, + program TYPE progname, + include TYPE progname, + line TYPE i, + END OF ty_scr_info. + + CONSTANTS: + BEGIN OF c_section_text, + cause TYPE string VALUE `Cause`, + system_response TYPE string VALUE `System response`, + what_to_do TYPE string VALUE `Procedure`, + sys_admin TYPE string VALUE `System administration`, + END OF c_section_text . + CONSTANTS: + BEGIN OF c_section_token, + cause TYPE string VALUE `&CAUSE&`, + system_response TYPE string VALUE `&SYSTEM_RESPONSE&`, + what_to_do TYPE string VALUE `&WHAT_TO_DO&`, + sys_admin TYPE string VALUE `&SYS_ADMIN&`, + END OF c_section_token . + + CLASS-DATA null TYPE string. + + DATA msgv1 TYPE symsgv READ-ONLY . + DATA msgv2 TYPE symsgv READ-ONLY . + DATA msgv3 TYPE symsgv READ-ONLY . + DATA msgv4 TYPE symsgv READ-ONLY . + DATA mv_longtext TYPE string READ-ONLY. + DATA mt_callstack TYPE abap_callstack READ-ONLY. + DATA mi_log TYPE REF TO zif_abapgit_log READ-ONLY. + DATA ms_src_info TYPE ty_scr_info READ-ONLY. + + "! Raise exception with text + "! @parameter iv_text | Text + "! @parameter ix_previous | Previous exception + "! @parameter ii_log | Log + "! @parameter iv_longtext | Longtext + "! @raising zcx_abapgit_exception | Exception + CLASS-METHODS raise + IMPORTING + !iv_text TYPE clike + !ix_previous TYPE REF TO cx_root OPTIONAL + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + !iv_longtext TYPE csequence OPTIONAL + RAISING + zcx_abapgit_exception . + "! Raise exception with T100 message + "!

      + "! Will default to sy-msg* variables. These need to be set right before calling this method. + "!

      + "! @parameter iv_msgid | Message ID + "! @parameter iv_msgno | Message number + "! @parameter iv_msgv1 | Message variable 1 + "! @parameter iv_msgv2 | Message variable 2 + "! @parameter iv_msgv3 | Message variable 3 + "! @parameter iv_msgv4 | Message variable 4 + "! @parameter ii_log | Log + "! @parameter ix_previous | Previous exception + "! @parameter iv_longtext | Longtext + "! @raising zcx_abapgit_exception | Exception + CLASS-METHODS raise_t100 + IMPORTING + !iv_msgid TYPE symsgid DEFAULT sy-msgid + !iv_msgno TYPE symsgno DEFAULT sy-msgno + !iv_msgv1 TYPE symsgv DEFAULT sy-msgv1 + !iv_msgv2 TYPE symsgv DEFAULT sy-msgv2 + !iv_msgv3 TYPE symsgv DEFAULT sy-msgv3 + !iv_msgv4 TYPE symsgv DEFAULT sy-msgv4 + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + !ix_previous TYPE REF TO cx_root OPTIONAL + !iv_longtext TYPE csequence OPTIONAL + RAISING + zcx_abapgit_exception . + "! Raise with text from previous exception + "! @parameter ix_previous | Previous exception + "! @parameter iv_longtext | Longtext + "! @raising zcx_abapgit_exception | Exception + CLASS-METHODS raise_with_text + IMPORTING + !ix_previous TYPE REF TO cx_root + !iv_longtext TYPE csequence OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !textid LIKE if_t100_message=>t100key OPTIONAL + !previous LIKE previous OPTIONAL + !log TYPE REF TO zif_abapgit_log OPTIONAL + !msgv1 TYPE symsgv OPTIONAL + !msgv2 TYPE symsgv OPTIONAL + !msgv3 TYPE symsgv OPTIONAL + !msgv4 TYPE symsgv OPTIONAL + !longtext TYPE csequence OPTIONAL . + + METHODS get_source_position + REDEFINITION . + METHODS if_message~get_longtext + REDEFINITION . + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_generic_error_msg TYPE string VALUE `An error occurred (ZCX_ABAPGIT_EXCEPTION)`. + + METHODS save_callstack . + METHODS itf_to_string + IMPORTING + !it_itf TYPE tline_tab + RETURNING + VALUE(rv_result) TYPE string . + METHODS get_t100_longtext_itf + RETURNING + VALUE(rt_itf) TYPE tline_tab . + METHODS remove_empty_section + IMPORTING + !iv_tabix_from TYPE i + !iv_tabix_to TYPE i + CHANGING + !ct_itf TYPE tline_tab . + METHODS replace_section_head_with_text + CHANGING + !cs_itf TYPE tline . + CLASS-METHODS remove_newlines_from_string + IMPORTING + iv_string TYPE string + RETURNING + VALUE(rv_result) TYPE string. +ENDCLASS. +CLASS zcx_abapgit_exception IMPLEMENTATION. + METHOD constructor ##ADT_SUPPRESS_GENERATION. + + super->constructor( previous = previous ). + + me->msgv1 = msgv1. + me->msgv2 = msgv2. + me->msgv3 = msgv3. + me->msgv4 = msgv4. + mi_log = log. + mv_longtext = longtext. + + CLEAR me->textid. + + IF textid IS INITIAL. + if_t100_message~t100key = if_t100_message=>default_textid. + ELSE. + if_t100_message~t100key = textid. + ENDIF. + + save_callstack( ). + + " Save for debugger + get_source_position( + IMPORTING + program_name = ms_src_info-program + include_name = ms_src_info-include + source_line = ms_src_info-line ). + + ENDMETHOD. + METHOD get_source_position. + + FIELD-SYMBOLS: LIKE LINE OF mt_callstack. + + READ TABLE mt_callstack ASSIGNING + INDEX 1. + IF sy-subrc = 0. + program_name = -mainprogram. + include_name = -include. + source_line = -line. + ELSE. + super->get_source_position( + IMPORTING + program_name = program_name + include_name = include_name + source_line = source_line ). + ENDIF. + + ENDMETHOD. + METHOD get_t100_longtext_itf. + + DATA: lv_docu_key TYPE doku_obj. + + FIELD-SYMBOLS TYPE any. + + lv_docu_key = if_t100_message~t100key-msgid && if_t100_message~t100key-msgno. + + CALL FUNCTION 'DOCU_GET' + EXPORTING + id = 'NA' + langu = sy-langu + object = lv_docu_key + typ = 'E' + TABLES + line = rt_itf + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc = 0. + ASSIGN me->(if_t100_message~t100key-attr1) TO . + IF sy-subrc = 0. + REPLACE ALL OCCURRENCES OF '&V1&' IN TABLE rt_itf WITH . + ENDIF. + ASSIGN me->(if_t100_message~t100key-attr2) TO . + IF sy-subrc = 0. + REPLACE ALL OCCURRENCES OF '&V2&' IN TABLE rt_itf WITH . + ENDIF. + ASSIGN me->(if_t100_message~t100key-attr3) TO . + IF sy-subrc = 0. + REPLACE ALL OCCURRENCES OF '&V3&' IN TABLE rt_itf WITH . + ENDIF. + ASSIGN me->(if_t100_message~t100key-attr4) TO . + IF sy-subrc = 0. + REPLACE ALL OCCURRENCES OF '&V4&' IN TABLE rt_itf WITH . + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD if_message~get_longtext. + DATA: lv_preserve_newlines_handled TYPE abap_bool VALUE abap_false. + + IF mv_longtext IS NOT INITIAL. + result = mv_longtext. + ELSEIF if_t100_message~t100key IS NOT INITIAL. + result = itf_to_string( get_t100_longtext_itf( ) ). + ELSE. + result = super->get_longtext( preserve_newlines ). + lv_preserve_newlines_handled = abap_true. + ENDIF. + + IF lv_preserve_newlines_handled = abap_false AND preserve_newlines = abap_false. + result = remove_newlines_from_string( result ). + ENDIF. + ENDMETHOD. + METHOD itf_to_string. + + CONSTANTS: lc_format_section TYPE string VALUE 'U1'. + + DATA: + lt_stream TYPE TABLE OF tdline, + lt_string TYPE TABLE OF string, + lt_itf TYPE tline_tab, + lv_has_content TYPE abap_bool, + lv_tabix_from TYPE syst-tabix, + lv_tabix_to TYPE syst-tabix. + + FIELD-SYMBOLS: TYPE tline, + TYPE tline. + + lt_itf = it_itf. + + " You should remember that we replace the U1 format because + " that preserves the section header of longtexts. + LOOP AT lt_itf ASSIGNING + WHERE tdformat = lc_format_section. + + CLEAR: + lv_has_content, + lv_tabix_to. + + lv_tabix_from = sy-tabix. + + LOOP AT lt_itf ASSIGNING + FROM sy-tabix + 1. + + IF -tdformat = lc_format_section. + lv_tabix_to = sy-tabix. + EXIT. + ELSEIF -tdline IS NOT INITIAL. + lv_has_content = abap_true. + ENDIF. + + ENDLOOP. + + IF lv_has_content = abap_false. + remove_empty_section( + EXPORTING + iv_tabix_from = lv_tabix_from + iv_tabix_to = lv_tabix_to + CHANGING + ct_itf = lt_itf ). + CONTINUE. + ENDIF. + + replace_section_head_with_text( CHANGING cs_itf = ). + + ENDLOOP. + + CALL FUNCTION 'CONVERT_ITF_TO_STREAM_TEXT' + EXPORTING + lf = 'X' + IMPORTING + stream_lines = lt_string + TABLES + itf_text = lt_itf + text_stream = lt_stream. + + rv_result = concat_lines_of( + table = lt_string + sep = cl_abap_char_utilities=>newline ). + + ENDMETHOD. + METHOD raise. + + IF iv_text IS INITIAL. + cl_message_helper=>set_msg_vars_for_clike( c_generic_error_msg ). + ELSE. + cl_message_helper=>set_msg_vars_for_clike( iv_text ). + ENDIF. + + raise_t100( + ii_log = ii_log + ix_previous = ix_previous + iv_longtext = iv_longtext ). + + ENDMETHOD. + METHOD raise_t100. + DATA: ls_t100_key TYPE scx_t100key. + + ls_t100_key-msgid = iv_msgid. + ls_t100_key-msgno = iv_msgno. + ls_t100_key-attr1 = 'MSGV1'. + ls_t100_key-attr2 = 'MSGV2'. + ls_t100_key-attr3 = 'MSGV3'. + ls_t100_key-attr4 = 'MSGV4'. + + IF iv_msgid IS INITIAL. + CLEAR ls_t100_key. + ENDIF. + + RAISE EXCEPTION TYPE zcx_abapgit_exception + EXPORTING + textid = ls_t100_key + log = ii_log + msgv1 = iv_msgv1 + msgv2 = iv_msgv2 + msgv3 = iv_msgv3 + msgv4 = iv_msgv4 + previous = ix_previous + longtext = iv_longtext. + ENDMETHOD. + METHOD raise_with_text. + raise( + iv_text = ix_previous->get_text( ) + ix_previous = ix_previous + iv_longtext = iv_longtext ). + ENDMETHOD. + METHOD remove_empty_section. + IF iv_tabix_to BETWEEN iv_tabix_from AND lines( ct_itf ). + DELETE ct_itf FROM iv_tabix_from TO iv_tabix_to. + ELSE. + DELETE ct_itf FROM iv_tabix_from. + ENDIF. + ENDMETHOD. + METHOD remove_newlines_from_string. + rv_result = iv_string. + + REPLACE ALL OCCURRENCES OF ` ` && cl_abap_char_utilities=>cr_lf IN rv_result WITH ` `. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN rv_result WITH ` `. + REPLACE ALL OCCURRENCES OF ` ` && cl_abap_char_utilities=>newline IN rv_result WITH ` `. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN rv_result WITH ` `. + ENDMETHOD. + METHOD replace_section_head_with_text. + + CASE cs_itf-tdline. + WHEN c_section_token-cause. + cs_itf-tdline = c_section_text-cause. + WHEN c_section_token-system_response. + cs_itf-tdline = c_section_text-system_response. + WHEN c_section_token-what_to_do. + cs_itf-tdline = c_section_text-what_to_do. + WHEN c_section_token-sys_admin. + cs_itf-tdline = c_section_text-sys_admin. + ENDCASE. + + ENDMETHOD. + METHOD save_callstack. + + FIELD-SYMBOLS: LIKE LINE OF mt_callstack. + + CALL FUNCTION 'SYSTEM_CALLSTACK' + IMPORTING + callstack = mt_callstack. + + " You should remember that the first lines are from zcx_abapgit_exception + " and are removed so that highest level in the callstack is the position where + " the exception is raised. + " + " For the merged report it's hard to do that, because zcx_abapgit_exception + " isn't visible in the callstack. Therefore we have to check the Events. + LOOP AT mt_callstack ASSIGNING . + + IF -mainprogram CP |ZCX_ABAPGIT_EXCEPTION*| " full + OR -blockname = `SAVE_CALLSTACK` " merged + OR -blockname = `CONSTRUCTOR` " merged + OR -blockname CP `RAISE*`. "merged + DELETE TABLE mt_callstack FROM . + ELSE. + EXIT. + ENDIF. + + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcx_abapgit_cancel DEFINITION + INHERITING FROM zcx_abapgit_exception + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !textid LIKE if_t100_message=>t100key OPTIONAL + !previous LIKE previous OPTIONAL + !log TYPE REF TO zif_abapgit_log OPTIONAL + !msgv1 TYPE symsgv OPTIONAL + !msgv2 TYPE symsgv OPTIONAL + !msgv3 TYPE symsgv OPTIONAL + !msgv4 TYPE symsgv OPTIONAL + !longtext TYPE csequence OPTIONAL. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcx_abapgit_cancel IMPLEMENTATION. + METHOD constructor ##ADT_SUPPRESS_GENERATION. + super->constructor( + previous = previous + log = log + msgv1 = msgv1 + msgv2 = msgv2 + msgv3 = msgv3 + msgv4 = msgv4 + longtext = longtext ). + + CLEAR me->textid. + + IF textid IS INITIAL. + if_t100_message~t100key = if_t100_message=>default_textid. + ELSE. + if_t100_message~t100key = textid. + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS zcx_abapgit_not_found DEFINITION + INHERITING FROM cx_static_check + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !textid LIKE textid OPTIONAL + !previous LIKE previous OPTIONAL. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcx_abapgit_not_found IMPLEMENTATION. + METHOD constructor ##ADT_SUPPRESS_GENERATION. + super->constructor( + textid = textid + previous = previous ). + ENDMETHOD. +ENDCLASS. + +CLASS zcx_abapgit_type_not_supported DEFINITION + INHERITING FROM zcx_abapgit_exception + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS constructor + IMPORTING + textid LIKE if_t100_message=>t100key OPTIONAL + previous LIKE previous OPTIONAL + log TYPE REF TO zif_abapgit_log OPTIONAL + msgv1 TYPE symsgv OPTIONAL + msgv2 TYPE symsgv OPTIONAL + msgv3 TYPE symsgv OPTIONAL + msgv4 TYPE symsgv OPTIONAL + longtext TYPE csequence OPTIONAL + obj_type TYPE trobjtype. + + METHODS get_text REDEFINITION. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA mv_obj_type TYPE trobjtype. +ENDCLASS. +CLASS zcx_abapgit_type_not_supported IMPLEMENTATION. + + METHOD constructor ##ADT_SUPPRESS_GENERATION. + + super->constructor( + textid = textid + previous = previous + log = log + msgv1 = msgv1 + msgv2 = msgv2 + msgv3 = msgv3 + msgv4 = msgv4 + longtext = longtext ). + + mv_obj_type = obj_type. + + ENDMETHOD. + METHOD get_text. + result = |Object type { mv_obj_type } is not supported by this system|. + ENDMETHOD. + +ENDCLASS. + +INTERFACE zif_abapgit_background . + TYPES: + BEGIN OF ty_settings, + key TYPE string, + value TYPE string, + END OF ty_settings . + TYPES: + ty_settings_tt TYPE STANDARD TABLE OF ty_settings WITH DEFAULT KEY . + + CLASS-METHODS get_description + RETURNING + VALUE(rv_description) TYPE string . + CLASS-METHODS get_settings + CHANGING + ct_settings TYPE ty_settings_tt . + METHODS run + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + !ii_log TYPE REF TO zif_abapgit_log + !it_settings TYPE ty_settings_tt OPTIONAL + RAISING + zcx_abapgit_exception . +ENDINTERFACE. + +INTERFACE zif_abapgit_default_transport. + + TYPES: BEGIN OF ty_get, + trfunction TYPE c LENGTH 1, + ordernum TYPE trkorr, + END OF ty_get. + + METHODS set + IMPORTING + iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception. + + METHODS reset + RAISING + zcx_abapgit_exception. + + METHODS get + RETURNING + VALUE(rs_default_task) TYPE ty_get + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_diff3. +************************************************************************ +* ABAP Diff3 Interface +* +* https://github.com/Marc-Bernard-Tools/ABAP-Diff3 +* +* This is a port of JavaScript (https://github.com/bhousel/node-diff3, MIT license) +* https://github.com/bhousel/node-diff3/blob/main/index.d.ts as of 2021-05-04 +* +* Copyright 2022 Marc Bernard +* SPDX-License-Identifier: MIT +************************************************************************ + + TYPES ty_number TYPE i. + + TYPES: + ty_numbers TYPE STANDARD TABLE OF ty_number WITH DEFAULT KEY. + + TYPES: + BEGIN OF ty_number_number, + key TYPE ty_number, + len TYPE ty_number, + END OF ty_number_number. + + TYPES: + BEGIN OF ty_lcs_result, + key TYPE i, + buffer1index TYPE ty_number, + buffer2index TYPE ty_number, + chain TYPE i, " ref to ilcsresult-key + END OF ty_lcs_result. + TYPES: + ty_lcs_result_t TYPE SORTED TABLE OF ty_lcs_result WITH UNIQUE KEY key. + + TYPES: + BEGIN OF ty_comm_result, + common TYPE string_table, + BEGIN OF diff, + buffer1 TYPE string_table, + buffer2 TYPE string_table, + END OF diff, + END OF ty_comm_result. + TYPES: + ty_comm_result_t TYPE STANDARD TABLE OF ty_comm_result WITH DEFAULT KEY. + + TYPES: + BEGIN OF ty_diff_indices_result, + buffer1 TYPE ty_number_number, + buffer1content TYPE string_table, + buffer2 TYPE ty_number_number, + buffer2content TYPE string_table, + END OF ty_diff_indices_result. + TYPES: + ty_diff_indices_result_t TYPE STANDARD TABLE OF ty_diff_indices_result WITH DEFAULT KEY. + + TYPES: + BEGIN OF ty_chunk, + offset TYPE ty_number, + length TYPE ty_number, + chunk TYPE string_table, + END OF ty_chunk. + + TYPES: + BEGIN OF ty_patch_result, + buffer1 TYPE ty_chunk, + buffer2 TYPE ty_chunk, + END OF ty_patch_result. + TYPES: + ty_patch_result_t TYPE STANDARD TABLE OF ty_patch_result WITH DEFAULT KEY. + + TYPES: + BEGIN OF ty_stable_region, + buffer TYPE c LENGTH 1, + buffer_start TYPE ty_number, + buffer_length TYPE ty_number, + buffer_content TYPE string_table, + END OF ty_stable_region. + TYPES: + BEGIN OF ty_unstable_region, + a_start TYPE ty_number, + a_length TYPE ty_number, + a_content TYPE string_table, + b_start TYPE ty_number, + b_length TYPE ty_number, + b_content TYPE string_table, + o_start TYPE ty_number, + o_length TYPE ty_number, + o_content TYPE string_table, + END OF ty_unstable_region. + + TYPES: + BEGIN OF ty_region, + stable TYPE abap_bool, + stable_region TYPE ty_stable_region, + unstable_region TYPE ty_unstable_region, + END OF ty_region. + TYPES: + ty_region_t TYPE STANDARD TABLE OF ty_region WITH DEFAULT KEY. + + TYPES: + BEGIN OF ty_merge_region, + ok TYPE string_table, + BEGIN OF conflict, + a TYPE string_table, + a_index TYPE ty_number, + o TYPE string_table, + o_index TYPE ty_number, + b TYPE string_table, + b_index TYPE ty_number, + END OF conflict, + END OF ty_merge_region. + TYPES: + ty_merge_region_t TYPE STANDARD TABLE OF ty_merge_region WITH DEFAULT KEY. + + TYPES: + BEGIN OF ty_merge_result, + conflict TYPE abap_bool, + result TYPE string_table, + END OF ty_merge_result. + + TYPES: + BEGIN OF ty_labels, + a TYPE string, + o TYPE string, + x TYPE string, + b TYPE string, + END OF ty_labels. + + "! Expects two arrays, finds longest common sequence + METHODS lcs + IMPORTING + !it_buffer1 TYPE string_table + !it_buffer2 TYPE string_table + RETURNING + VALUE(rt_result) TYPE ty_lcs_result_t. + + "! We apply the LCS to build a 'comm'-style picture of the + "! differences between buffer1 and buffer2. + METHODS diff_comm + IMPORTING + !it_buffer1 TYPE string_table + !it_buffer2 TYPE string_table + RETURNING + VALUE(rt_result) TYPE ty_comm_result_t. + + "! We apply the LCS to give a simple representation of the + "! offsets and lengths of mismatched chunks in the input + "! buffers. This is used by diff3MergeRegions. + METHODS diff_indices + IMPORTING + !it_buffer1 TYPE string_table + !it_buffer2 TYPE string_table + RETURNING + VALUE(rt_result) TYPE ty_diff_indices_result_t. + + "! We apply the LCS to build a JSON representation of a + "! diff(1)-style patch. + METHODS diff_patch + IMPORTING + !it_buffer1 TYPE string_table + !it_buffer2 TYPE string_table + RETURNING + VALUE(rt_result) TYPE ty_patch_result_t. + + METHODS patch + IMPORTING + !it_buffer TYPE string_table + !it_patchres TYPE ty_patch_result_t + RETURNING + VALUE(rt_result) TYPE string_table. + + "! Takes the output of diffPatch(), and removes extra information from it. + "! It can still be used by patch(), below, but can no longer be inverted. + METHODS strip_patch + IMPORTING + !it_patchres TYPE ty_patch_result_t + RETURNING + VALUE(rt_result) TYPE ty_patch_result_t. + + "! Takes the output of diffPatch(), and inverts the sense of it, so that it + "! can be applied to buffer2 to give buffer1 rather than the other way around. + METHODS invert_patch + IMPORTING + !it_patchres TYPE ty_patch_result_t + RETURNING + VALUE(rt_result) TYPE ty_patch_result_t. + + "! Given three buffers, A, O, and B, where both A and B are + "! independently derived from O, returns a fairly complicated + "! internal representation of merge decisions it's taken. The + "! interested reader may wish to consult + "! + "! Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. + "! 'A Formal Investigation of ' In Arvind and Prasad, + "! editors, Foundations of Software Technology and Theoretical + "! Computer Science (FSTTCS), December 2007. + "! + "! (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf) + METHODS diff3_merge_regions + IMPORTING + !it_a TYPE string_table + !it_o TYPE string_table + !it_b TYPE string_table + RETURNING + VALUE(rt_result) TYPE ty_region_t. + + "! Applies the output of diff3MergeRegions to actually + "! construct the merged buffer; the returned result alternates + "! between 'ok' and 'conflict' blocks. + "! A "false conflict" is where `a` and `b` both change the same from `o` + METHODS diff3_merge + IMPORTING + !it_a TYPE string_table + !it_o TYPE string_table + !it_b TYPE string_table + !iv_exclude_false_conflicts TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rt_result) TYPE ty_merge_region_t. + + METHODS merge + IMPORTING + !it_a TYPE string_table + !it_o TYPE string_table + !it_b TYPE string_table + !iv_exclude_false_conflicts TYPE abap_bool DEFAULT abap_true + !is_labels TYPE ty_labels OPTIONAL + RETURNING + VALUE(rs_result) TYPE ty_merge_result. + + METHODS merge_diff3 + IMPORTING + !it_a TYPE string_table + !it_o TYPE string_table + !it_b TYPE string_table + !iv_exclude_false_conflicts TYPE abap_bool DEFAULT abap_true + !is_labels TYPE ty_labels OPTIONAL + RETURNING + VALUE(rs_result) TYPE ty_merge_result. + + METHODS merge_dig_in + IMPORTING + !it_a TYPE string_table + !it_o TYPE string_table + !it_b TYPE string_table + !iv_exclude_false_conflicts TYPE abap_bool DEFAULT abap_true + !is_labels TYPE ty_labels OPTIONAL + RETURNING + VALUE(rs_result) TYPE ty_merge_result. + +ENDINTERFACE. + +INTERFACE zif_abapgit_environment. + TYPES: + BEGIN OF ty_release_sp, + release TYPE c LENGTH 10, + sp TYPE c LENGTH 10, + END OF ty_release_sp, + ty_system_language_filter TYPE RANGE OF spras. + + METHODS is_sap_cloud_platform + RETURNING + VALUE(rv_result) TYPE abap_bool. + METHODS is_merged + RETURNING + VALUE(rv_result) TYPE abap_bool. + METHODS is_repo_object_changes_allowed + RETURNING + VALUE(rv_result) TYPE abap_bool. + METHODS compare_with_inactive + RETURNING + VALUE(rv_result) TYPE abap_bool. + METHODS is_restart_required + RETURNING + VALUE(rv_result) TYPE abap_bool. + METHODS is_sap_object_allowed + RETURNING + VALUE(rv_allowed) TYPE abap_bool. + METHODS get_basis_release + RETURNING + VALUE(rs_result) TYPE ty_release_sp. + METHODS get_system_language_filter + RETURNING + VALUE(rt_system_language_filter) TYPE ty_system_language_filter. + METHODS is_variant_maintenance + RETURNING + VALUE(rv_is_variant_maintenance) TYPE abap_bool. + METHODS init_parallel_processing + IMPORTING + iv_group TYPE clike + RETURNING + VALUE(rv_free_work_processes) TYPE i. + METHODS check_parallel_processing + IMPORTING + iv_group TYPE clike + RETURNING + VALUE(rv_checked) TYPE abap_bool. + METHODS get_available_user_sessions + RETURNING + VALUE(rv_sessions) TYPE i. + +ENDINTERFACE. + +INTERFACE zif_abapgit_user_record. + + METHODS get_name + IMPORTING + iv_username TYPE sy-uname + RETURNING + VALUE(rv_name) TYPE string. + + METHODS get_email + IMPORTING + iv_username TYPE sy-uname + RETURNING + VALUE(rv_email) TYPE string. + + METHODS get_title + IMPORTING + iv_username TYPE sy-uname + RETURNING + VALUE(rv_title) TYPE string. + +ENDINTERFACE. + +INTERFACE zif_abapgit_auth. + + TYPES: ty_authorization TYPE string. + + CONSTANTS: BEGIN OF c_authorization, + startup TYPE ty_authorization VALUE 'STARTUP', + uninstall TYPE ty_authorization VALUE 'UNINSTALL', + create_repo TYPE ty_authorization VALUE 'CREATE_REPO', + transport_to_branch TYPE ty_authorization VALUE 'TRANSPORT_TO_BRANCH', + update_local_checksum TYPE ty_authorization VALUE 'UPDATE_LOCAL_CHECKSUM', + END OF c_authorization. + + METHODS: + is_allowed + IMPORTING iv_authorization TYPE ty_authorization + iv_param TYPE string OPTIONAL + RETURNING VALUE(rv_allowed) TYPE abap_bool. + +ENDINTERFACE. + +INTERFACE zif_abapgit_git_definitions . +* this interface is self contained +* only references to built in types +* git does not know the concept of TADIR objects, only knows files + TYPES: + ty_type TYPE c LENGTH 6 . + TYPES: + ty_bitbyte TYPE c LENGTH 8 . + TYPES: + ty_sha1 TYPE c LENGTH 40 . + TYPES: ty_sha1_tt TYPE STANDARD TABLE OF ty_sha1 WITH DEFAULT KEY . + TYPES: + ty_adler32 TYPE x LENGTH 4 . + + TYPES ty_item_state TYPE c LENGTH 1. + TYPES: + BEGIN OF ty_file_signature, + path TYPE string, + filename TYPE string, + sha1 TYPE ty_sha1, + END OF ty_file_signature . + TYPES: + ty_file_signatures_tt TYPE STANDARD TABLE OF + ty_file_signature WITH DEFAULT KEY . + TYPES: + ty_file_signatures_ts TYPE SORTED TABLE OF + ty_file_signature WITH UNIQUE KEY path filename . + TYPES: + BEGIN OF ty_file. + INCLUDE TYPE ty_file_signature. + TYPES: data TYPE xstring, + END OF ty_file . + TYPES: + ty_files_tt TYPE STANDARD TABLE OF ty_file WITH DEFAULT KEY + WITH UNIQUE SORTED KEY file_path COMPONENTS path filename + WITH NON-UNIQUE SORTED KEY file COMPONENTS filename. + + TYPES ty_git_branch_type TYPE c LENGTH 2 . + TYPES: + BEGIN OF ty_git_branch, + sha1 TYPE ty_sha1, + name TYPE string, + type TYPE ty_git_branch_type, + is_head TYPE abap_bool, + display_name TYPE string, + END OF ty_git_branch . + TYPES: + ty_git_branch_list_tt TYPE STANDARD TABLE OF ty_git_branch WITH DEFAULT KEY + WITH NON-UNIQUE SORTED KEY name_key + COMPONENTS name. + TYPES: + BEGIN OF ty_git_tag, + sha1 TYPE ty_sha1, + object TYPE ty_sha1, + name TYPE string, + type TYPE ty_git_branch_type, + display_name TYPE string, + tagger_name TYPE string, + tagger_email TYPE string, + message TYPE string, + body TYPE string, + END OF ty_git_tag . + TYPES: + BEGIN OF ty_git_user, + name TYPE string, + email TYPE string, + END OF ty_git_user . + TYPES: + BEGIN OF ty_comment, + committer TYPE ty_git_user, + author TYPE ty_git_user, + comment TYPE string, + END OF ty_comment . + + TYPES: + ty_chmod TYPE c LENGTH 6 . + + CONSTANTS: + BEGIN OF c_chmod, + file TYPE ty_chmod VALUE '100644', + executable TYPE ty_chmod VALUE '100755', + dir TYPE ty_chmod VALUE '40000 ', + submodule TYPE ty_chmod VALUE '160000', + symbolic_link TYPE ty_chmod VALUE '120000', + END OF c_chmod . + + TYPES: + BEGIN OF ty_expanded, + path TYPE string, + name TYPE string, + sha1 TYPE ty_sha1, + chmod TYPE ty_chmod, + END OF ty_expanded . + TYPES: + ty_expanded_tt TYPE STANDARD TABLE OF ty_expanded WITH DEFAULT KEY + WITH NON-UNIQUE SORTED KEY path_name COMPONENTS path name. + + TYPES: + BEGIN OF ty_create, + name TYPE string, + parent TYPE string, + END OF ty_create . + TYPES: + BEGIN OF ty_commit, + sha1 TYPE ty_sha1, + parent1 TYPE ty_sha1, + parent2 TYPE ty_sha1, + author TYPE string, + email TYPE string, + time TYPE string, + message TYPE string, + body TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + branch TYPE string, + merge TYPE string, + tags TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + create TYPE STANDARD TABLE OF ty_create WITH DEFAULT KEY, + compressed TYPE abap_bool, + END OF ty_commit . + TYPES: + ty_commit_tt TYPE STANDARD TABLE OF ty_commit WITH DEFAULT KEY . + + CONSTANTS: + BEGIN OF c_type, + commit TYPE ty_type VALUE 'commit', "#EC NOTEXT + tree TYPE ty_type VALUE 'tree', "#EC NOTEXT + ref_d TYPE ty_type VALUE 'ref_d', "#EC NOTEXT + tag TYPE ty_type VALUE 'tag', "#EC NOTEXT + blob TYPE ty_type VALUE 'blob', "#EC NOTEXT + END OF c_type . + + CONSTANTS: + BEGIN OF c_git_branch_type, + branch TYPE ty_git_branch_type VALUE 'HD', + lightweight_tag TYPE ty_git_branch_type VALUE 'TG', + annotated_tag TYPE ty_git_branch_type VALUE 'AT', + other TYPE ty_git_branch_type VALUE 'ZZ', + END OF c_git_branch_type . + CONSTANTS c_head_name TYPE string VALUE 'HEAD' ##NO_TEXT. + CONSTANTS: + BEGIN OF c_git_branch, + main TYPE string VALUE 'refs/heads/main', + prefix TYPE string VALUE 'refs/', + heads_prefix TYPE string VALUE 'refs/heads/', + heads TYPE string VALUE 'refs/heads/*', + tags_prefix TYPE string VALUE 'refs/tags/', + tags TYPE string VALUE 'refs/tags/*', + peel TYPE string VALUE '^{}', + END OF c_git_branch. + + TYPES ty_head_type TYPE c LENGTH 1. + CONSTANTS: + BEGIN OF c_head_types, + all TYPE ty_head_type VALUE 'A', + branch TYPE ty_head_type VALUE 'B', + tag TYPE ty_head_type VALUE 'T', + commit TYPE ty_head_type VALUE 'C', + pull_request TYPE ty_head_type VALUE 'P', + END OF c_head_types. + +ENDINTERFACE. + +INTERFACE zif_abapgit_data_config . + TYPES: + ty_data_type TYPE c LENGTH 4 . + TYPES: + BEGIN OF ty_config, + type TYPE ty_data_type, + name TYPE tadir-obj_name, + skip_initial TYPE abap_bool, + where TYPE string_table, + END OF ty_config . + TYPES: + ty_config_tt TYPE SORTED TABLE OF ty_config WITH UNIQUE KEY type name . + + CONSTANTS c_default_path TYPE string VALUE '/data/' ##NO_TEXT. + CONSTANTS c_default_format TYPE string VALUE 'json' ##NO_TEXT. + CONSTANTS c_config TYPE string VALUE 'conf' ##NO_TEXT. + CONSTANTS: + BEGIN OF c_data_type, + tabu TYPE ty_data_type VALUE 'TABU', + vdat TYPE ty_data_type VALUE 'VDAT', + cdat TYPE ty_data_type VALUE 'CDAT', + tdat TYPE ty_data_type VALUE 'TDAT', + END OF c_data_type . + + METHODS add_config + IMPORTING + !is_config TYPE ty_config + RAISING + zcx_abapgit_exception . + METHODS from_json + IMPORTING + !it_files TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + METHODS get_configs + RETURNING + VALUE(rt_configs) TYPE ty_config_tt . + METHODS remove_config + IMPORTING + !is_config TYPE ty_config + RAISING + zcx_abapgit_exception . + METHODS to_json + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + METHODS update_config + IMPORTING + !is_config TYPE ty_config + RAISING + zcx_abapgit_exception . +ENDINTERFACE. + +INTERFACE zif_abapgit_data_serializer . + METHODS serialize + IMPORTING + !ii_config TYPE REF TO zif_abapgit_data_config + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . +ENDINTERFACE. + +INTERFACE zif_abapgit_data_supporter. + + TYPES: + BEGIN OF ty_object, + type TYPE zif_abapgit_data_config=>ty_config-type, + name TYPE zif_abapgit_data_config=>ty_config-name, + END OF ty_object. + TYPES: + ty_objects TYPE SORTED TABLE OF ty_object WITH UNIQUE KEY type name. + + METHODS is_object_supported + IMPORTING + !iv_type TYPE ty_object-type + !iv_name TYPE ty_object-name + RETURNING + VALUE(rv_supported) TYPE abap_bool. + +ENDINTERFACE. + +INTERFACE zif_abapgit_git_branch_list. + + METHODS find_by_name + IMPORTING + !iv_branch_name TYPE clike + RETURNING + VALUE(rs_branch) TYPE zif_abapgit_git_definitions=>ty_git_branch + RAISING + zcx_abapgit_exception . + METHODS get_head_symref + RETURNING + VALUE(rv_head_symref) TYPE string . + METHODS get_all + RETURNING + VALUE(rt_branches) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt + RAISING + zcx_abapgit_exception . + METHODS get_branches_only + RETURNING + VALUE(rt_branches) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt + RAISING + zcx_abapgit_exception . + METHODS get_tags_only + RETURNING + VALUE(rt_tags) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_git_transport . + METHODS branches + IMPORTING + iv_url TYPE string + RETURNING + VALUE(ri_branch_list) TYPE REF TO zif_abapgit_git_branch_list + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_pr_enum_provider . + + TYPES: + BEGIN OF ty_pull_request, + base_url TYPE string, + number TYPE string, + title TYPE string, + user TYPE string, + head_url TYPE string, + head_branch TYPE string, + created_at TYPE string, " TODO change to D after date parsing fixed + is_for_upstream TYPE abap_bool, + draft TYPE abap_bool, + html_url TYPE string, + END OF ty_pull_request. + TYPES: + ty_pull_requests TYPE STANDARD TABLE OF ty_pull_request WITH KEY base_url number. + + METHODS list_pull_requests + RETURNING + VALUE(rt_pulls) TYPE ty_pull_requests + RAISING + zcx_abapgit_exception. + + METHODS create_repository + IMPORTING + iv_description TYPE string OPTIONAL + iv_is_org TYPE abap_bool DEFAULT abap_true + iv_private TYPE abap_bool DEFAULT abap_true + iv_auto_init TYPE abap_bool DEFAULT abap_true + RAISING + zcx_abapgit_exception. + + METHODS create_initial_branch + IMPORTING + iv_readme TYPE string OPTIONAL + iv_branch_name TYPE string DEFAULT 'main' + RETURNING + VALUE(rv_branch_name) TYPE string + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_http_agent . + + CONSTANTS: + BEGIN OF c_methods, + get TYPE string VALUE 'GET', + post TYPE string VALUE 'POST', + put TYPE string VALUE 'PUT', + delete TYPE string VALUE 'DELETE', + patch TYPE string VALUE 'PATCH', + END OF c_methods. + + METHODS global_headers + RETURNING + VALUE(ro_global_headers) TYPE REF TO zcl_abapgit_string_map. + + METHODS request + IMPORTING + !iv_url TYPE string + !iv_method TYPE string DEFAULT c_methods-get + !io_query TYPE REF TO zcl_abapgit_string_map OPTIONAL + !io_headers TYPE REF TO zcl_abapgit_string_map OPTIONAL + !iv_payload TYPE any OPTIONAL " can be string, xstring + RETURNING + VALUE(ri_response) TYPE REF TO zif_abapgit_http_response + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_http_response . + METHODS data + RETURNING + VALUE(rv_data) TYPE xstring . + METHODS cdata + RETURNING + VALUE(rv_data) TYPE string . + METHODS json + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error . + METHODS is_ok + RETURNING + VALUE(rv_yes) TYPE abap_bool . + METHODS code + RETURNING + VALUE(rv_code) TYPE i . + METHODS error + RETURNING + VALUE(rv_message) TYPE string . + METHODS headers + RETURNING + VALUE(ro_headers) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + METHODS close . +ENDINTERFACE. + +INTERFACE zif_abapgit_code_inspector . + + TYPES: BEGIN OF ty_result, + objtype TYPE tadir-object, + objname TYPE tadir-obj_name, + sobjtype TYPE c LENGTH 4, + sobjname TYPE c LENGTH 40, + kind TYPE c LENGTH 1, + line TYPE n LENGTH 6, + col TYPE n LENGTH 4, + code TYPE c LENGTH 10, + test TYPE c LENGTH 30, + text TYPE string, + param1 TYPE c LENGTH 80, + param2 TYPE c LENGTH 20, + param3 TYPE c LENGTH 20, + param4 TYPE c LENGTH 20, + detail TYPE xstring, + author TYPE c LENGTH 12, + END OF ty_result. + + TYPES ty_results TYPE STANDARD TABLE OF ty_result WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_variant, + name TYPE sci_chkv, + description TYPE string, + END OF ty_variant. + + TYPES ty_variants TYPE STANDARD TABLE OF ty_variant WITH DEFAULT KEY. + + METHODS run + IMPORTING + !iv_variant TYPE sci_chkv + !iv_save TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_list) TYPE ty_results + RAISING + zcx_abapgit_exception . + + METHODS is_successful + RETURNING + VALUE(rv_success) TYPE abap_bool . + + METHODS get_summary + RETURNING + VALUE(rv_summary) TYPE string. + + METHODS validate_check_variant + IMPORTING + !iv_check_variant_name TYPE sci_chkv + RAISING + zcx_abapgit_exception. + + METHODS list_global_variants + RETURNING + VALUE(rt_list) TYPE ty_variants. +ENDINTERFACE. + +INTERFACE zif_abapgit_ajson_iterator. + + METHODS has_next + RETURNING + VALUE(rv_yes) TYPE abap_bool. + + METHODS next + RETURNING + VALUE(ri_item) TYPE REF TO zif_abapgit_ajson. + +ENDINTERFACE. + +INTERFACE zif_abapgit_ajson_types. + + TYPES: + ty_node_type TYPE string. + + CONSTANTS: + BEGIN OF node_type, + boolean TYPE ty_node_type VALUE 'bool', + string TYPE ty_node_type VALUE 'str', + number TYPE ty_node_type VALUE 'num', + null TYPE ty_node_type VALUE 'null', + array TYPE ty_node_type VALUE 'array', + object TYPE ty_node_type VALUE 'object', + END OF node_type. + + TYPES: + BEGIN OF ty_node, + path TYPE string, + name TYPE string, + type TYPE ty_node_type, + value TYPE string, + index TYPE i, + order TYPE i, + children TYPE i, + END OF ty_node. + TYPES: + ty_nodes_tt TYPE STANDARD TABLE OF ty_node WITH KEY path name. + TYPES: + ty_nodes_ts TYPE SORTED TABLE OF ty_node + WITH UNIQUE KEY path name + WITH NON-UNIQUE SORTED KEY array_index COMPONENTS path index + WITH NON-UNIQUE SORTED KEY item_order COMPONENTS path order. + + TYPES: + BEGIN OF ty_path_name, + path TYPE string, + name TYPE string, + END OF ty_path_name. + +ENDINTERFACE. + +INTERFACE zif_abapgit_ajson. + + CONSTANTS version TYPE string VALUE 'v1.1.13'. "#EC NOTEXT + CONSTANTS origin TYPE string VALUE 'https://github.com/sbcgua/ajson'. "#EC NOTEXT + CONSTANTS license TYPE string VALUE 'MIT'. "#EC NOTEXT + + TYPES: + BEGIN OF ty_opts, + read_only TYPE abap_bool, + keep_item_order TYPE abap_bool, + format_datetime TYPE abap_bool, + to_abap_corresponding_only TYPE abap_bool, + END OF ty_opts. + + " DATA + + DATA mt_json_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts READ-ONLY. + + " CLONING + + METHODS clone + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + METHODS filter + IMPORTING + ii_filter TYPE REF TO zif_abapgit_ajson_filter + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + METHODS map + IMPORTING + ii_mapper TYPE REF TO zif_abapgit_ajson_mapping + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + " METHODS + + METHODS freeze. + METHODS keep_item_order + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. + METHODS format_datetime + IMPORTING + iv_use_iso TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. + METHODS to_abap_corresponding_only + IMPORTING + iv_enable TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. + METHODS opts + RETURNING + VALUE(rs_opts) TYPE ty_opts. + + " METHODS ex.reader + + METHODS is_empty + RETURNING + VALUE(rv_yes) TYPE abap_bool. + + METHODS exists + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_exists) TYPE abap_bool. + + METHODS members + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rt_members) TYPE string_table. + + METHODS get + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_value) TYPE string. + + METHODS get_node_type + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_node_type) TYPE zif_abapgit_ajson_types=>ty_node_type. + + METHODS get_boolean + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_value) TYPE abap_bool. + + METHODS get_integer + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_value) TYPE i. + + METHODS get_number + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_value) TYPE f. + + METHODS get_date + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_value) TYPE d. + + METHODS get_timestamp + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_value) TYPE timestamp. + + METHODS get_timestampl + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_value) TYPE timestampl. + + METHODS get_string + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_value) TYPE string. + + METHODS slice + IMPORTING + iv_path TYPE string + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. + + METHODS to_abap + IMPORTING + iv_corresponding TYPE abap_bool DEFAULT abap_false + ii_refs_initiator TYPE REF TO zif_abapgit_ajson_ref_init OPTIONAL + EXPORTING + ev_container TYPE any + RAISING + zcx_abapgit_ajson_error. + + METHODS array_to_string_table + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rt_string_table) TYPE string_table + RAISING + zcx_abapgit_ajson_error. + + " METHODS ex.writer + + METHODS clear + RAISING + zcx_abapgit_ajson_error. + + METHODS set + IMPORTING + iv_path TYPE string + iv_val TYPE any + iv_ignore_empty TYPE abap_bool DEFAULT abap_true + iv_node_type TYPE zif_abapgit_ajson_types=>ty_node_type OPTIONAL + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS setx + IMPORTING + iv_param TYPE string + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS set_boolean + IMPORTING + iv_path TYPE string + iv_val TYPE any + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS set_string + IMPORTING + iv_path TYPE string + iv_val TYPE clike + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS set_integer + IMPORTING + iv_path TYPE string + iv_val TYPE i + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS set_date + IMPORTING + iv_path TYPE string + iv_val TYPE d + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS set_timestamp + IMPORTING + iv_path TYPE string + iv_val TYPE timestamp + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS set_timestampl + IMPORTING + iv_path TYPE string + iv_val TYPE timestampl + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS set_null + IMPORTING + iv_path TYPE string + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS delete + IMPORTING + iv_path TYPE string + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS touch_array + IMPORTING + iv_path TYPE string + iv_clear TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS push + IMPORTING + iv_path TYPE string + iv_val TYPE any + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS stringify + IMPORTING + iv_indent TYPE i DEFAULT 0 + RETURNING + VALUE(rv_json) TYPE string + RAISING + zcx_abapgit_ajson_error. + +ENDINTERFACE. + +INTERFACE zif_abapgit_ajson_filter. + + TYPES ty_filter_tab TYPE STANDARD TABLE OF REF TO zif_abapgit_ajson_filter WITH KEY table_line. + TYPES ty_visit_type TYPE i. + + CONSTANTS: + BEGIN OF visit_type, + value TYPE ty_visit_type VALUE 0, + open TYPE ty_visit_type VALUE 1, + close TYPE ty_visit_type VALUE 2, + END OF visit_type. + + METHODS keep_node + IMPORTING + is_node TYPE zif_abapgit_ajson_types=>ty_node + iv_visit TYPE ty_visit_type DEFAULT visit_type-value + RETURNING + VALUE(rv_keep) TYPE abap_bool + RAISING + zcx_abapgit_ajson_error. + +ENDINTERFACE. + +INTERFACE zif_abapgit_ajson_mapping. + + TYPES: + BEGIN OF ty_mapping_field, " deprecated, will be removed + abap TYPE string, + json TYPE string, + END OF ty_mapping_field, + ty_mapping_fields TYPE STANDARD TABLE OF ty_mapping_field + WITH UNIQUE SORTED KEY abap COMPONENTS abap + WITH UNIQUE SORTED KEY json COMPONENTS json. + + TYPES: + BEGIN OF ty_rename, + from TYPE string, + to TYPE string, + END OF ty_rename, + tty_rename_map TYPE STANDARD TABLE OF ty_rename + WITH UNIQUE SORTED KEY by_name COMPONENTS from. + + TYPES: + ty_table_of TYPE STANDARD TABLE OF REF TO zif_abapgit_ajson_mapping. + + METHODS to_abap " deprecated, will be removed + IMPORTING + !iv_path TYPE string + !iv_name TYPE string + RETURNING + VALUE(rv_result) TYPE string. + + METHODS to_json " deprecated, will be removed + IMPORTING + !iv_path TYPE string + !iv_name TYPE string + RETURNING + VALUE(rv_result) TYPE string. + + METHODS rename_node + IMPORTING + !is_node TYPE zif_abapgit_ajson_types=>ty_node + CHANGING + !cv_name TYPE zif_abapgit_ajson_types=>ty_node-name. + +ENDINTERFACE. + +INTERFACE zif_abapgit_ajson_ref_init. + + TYPES: + BEGIN OF ty_data_ref, + path TYPE string, + name TYPE string, + dref TYPE REF TO data, + END OF ty_data_ref. + TYPES: + tty_data_refs TYPE STANDARD TABLE OF ty_data_ref + WITH UNIQUE SORTED KEY by_path COMPONENTS path name. + + METHODS get_data_ref + IMPORTING + !is_node TYPE zif_abapgit_ajson_types=>ty_node + RETURNING + VALUE(ro_ref) TYPE REF TO data. + +ENDINTERFACE. + +INTERFACE zif_abapgit_aff_registry . + + METHODS: + "! Returns TRUE if the object type is supported by ABAP file formats (AFF) in abapGit.
      + "! Either there is a (standalone AFF capable) object handler, + "! or object handler calls the AFF framework in newer ABAP systems. + is_supported_object_type + IMPORTING + iv_obj_type TYPE tadir-object + RETURNING + VALUE(rv_result) TYPE abap_bool. +ENDINTERFACE. + +INTERFACE zif_abapgit_aff_type_mapping . + METHODS: + "! Convert from AFF to abapGit data + "! + "! @parameter iv_data | ABAP data as AFF type + "! @parameter iv_object_name | Name of object + "! @parameter es_data | ABAP data as abapGit type + to_abapgit + IMPORTING iv_data TYPE data + iv_object_name TYPE sobj_name + EXPORTING es_data TYPE data, + + "! Converts to AFF specific meta data + "! + "! @parameter iv_data | (meta-)data of the object + "! @parameter es_data | aff data of the object, e.g. zif_abapgit_aff_intf_v1=>ty_main + to_aff + IMPORTING iv_data TYPE data + EXPORTING es_data TYPE data. +ENDINTERFACE. + +INTERFACE zif_abapgit_aff_types_v1. + + TYPES ty_format_version TYPE string. + + TYPES ty_abap_language_version TYPE c LENGTH 1. + + TYPES ty_abap_language_version_cloud TYPE c LENGTH 1. + + TYPES ty_abap_language_version_src TYPE c LENGTH 1. + + CONSTANTS: + BEGIN OF co_abap_language_version_src, + standard TYPE ty_abap_language_version_src VALUE 'X', + key_user TYPE ty_abap_language_version_src VALUE '2', + cloud_development TYPE ty_abap_language_version_src VALUE '5', + END OF co_abap_language_version_src. + + CONSTANTS: + BEGIN OF co_abap_language_version, + standard TYPE ty_abap_language_version VALUE space, + key_user TYPE ty_abap_language_version VALUE '2', + cloud_development TYPE ty_abap_language_version VALUE '5', + END OF co_abap_language_version. + + CONSTANTS: + BEGIN OF co_abap_language_version_cloud, + standard TYPE ty_abap_language_version_cloud VALUE space, + cloud_development TYPE ty_abap_language_version_cloud VALUE '5', + END OF co_abap_language_version_cloud. + + TYPES ty_description_60 TYPE c LENGTH 60. + TYPES ty_description_100 TYPE c LENGTH 100. + + TYPES ty_object_name_30 TYPE c LENGTH 30. + + TYPES ty_original_language TYPE sy-langu. + + TYPES: + BEGIN OF ty_header_60_src, + description TYPE ty_description_60, + original_language TYPE ty_original_language, + abap_language_version TYPE ty_abap_language_version_src, + END OF ty_header_60_src. + + TYPES: + BEGIN OF ty_header_60_cloud, + description TYPE ty_description_60, + original_language TYPE ty_original_language, + abap_language_version TYPE ty_abap_language_version_cloud, + END OF ty_header_60_cloud. + + TYPES: + BEGIN OF ty_header_60, + description TYPE ty_description_60, + original_language TYPE ty_original_language, + abap_language_version TYPE ty_abap_language_version, + END OF ty_header_60. + + TYPES: + BEGIN OF ty_header_60_no_abap_lv, + description TYPE ty_description_60, + original_language TYPE ty_original_language, + END OF ty_header_60_no_abap_lv. + + TYPES: + BEGIN OF ty_header_100, + description TYPE ty_description_100, + original_language TYPE ty_original_language, + abap_language_version TYPE ty_abap_language_version, + END OF ty_header_100. + + TYPES: + BEGIN OF ty_header_only_description, + description TYPE ty_description_60, + END OF ty_header_only_description. + + TYPES ty_option TYPE c LENGTH 2. + + CONSTANTS: + BEGIN OF co_option, + equals TYPE ty_option VALUE 'EQ', + between TYPE ty_option VALUE 'BT', + greater_than TYPE ty_option VALUE 'GT', + contains_pattern TYPE ty_option VALUE 'CP', + not_equal TYPE ty_option VALUE 'NE', + not_between TYPE ty_option VALUE 'NB', + not_contains_pattern TYPE ty_option VALUE 'NP', + greater_equal TYPE ty_option VALUE 'GE', + less_than TYPE ty_option VALUE 'LT', + less_equal TYPE ty_option VALUE 'LE', + END OF co_option. + + TYPES ty_sign TYPE c LENGTH 1. + + CONSTANTS: + BEGIN OF co_sign, + include TYPE ty_sign VALUE 'I', + exclude TYPE ty_sign VALUE 'E', + END OF co_sign. + +ENDINTERFACE. + +INTERFACE zif_abapgit_aff_oo_types_v1. + + TYPES: + BEGIN OF ty_component_description, + name TYPE zif_abapgit_aff_types_v1=>ty_object_name_30, + description TYPE zif_abapgit_aff_types_v1=>ty_description_60, + END OF ty_component_description, + + ty_component_descriptions TYPE SORTED TABLE OF ty_component_description WITH UNIQUE KEY name. + TYPES: + BEGIN OF ty_method, + name TYPE zif_abapgit_aff_types_v1=>ty_object_name_30, + description TYPE zif_abapgit_aff_types_v1=>ty_description_60, + parameters TYPE ty_component_descriptions, + exceptions TYPE ty_component_descriptions, + END OF ty_method, + ty_methods TYPE SORTED TABLE OF ty_method WITH UNIQUE KEY name. + + TYPES: + BEGIN OF ty_event, + name TYPE zif_abapgit_aff_types_v1=>ty_object_name_30, + description TYPE zif_abapgit_aff_types_v1=>ty_description_60, + parameters TYPE ty_component_descriptions, + END OF ty_event, + ty_events TYPE SORTED TABLE OF ty_event WITH UNIQUE KEY name. + + TYPES: + BEGIN OF ty_descriptions, + types TYPE ty_component_descriptions, + attributes TYPE ty_component_descriptions, + events TYPE ty_events, + methods TYPE ty_methods, + END OF ty_descriptions. + +ENDINTERFACE. + +INTERFACE zif_abapgit_aff_intf_v1. + + TYPES ty_category TYPE n LENGTH 2. + + CONSTANTS: + BEGIN OF co_category, + general TYPE ty_category VALUE '00', + classic_badi TYPE ty_category VALUE '01', + business_static_components TYPE ty_category VALUE '51', + business_instance_components TYPE ty_category VALUE '52', + db_procedure_proxy TYPE ty_category VALUE '65', + web_dynpro_runtime TYPE ty_category VALUE '80', + enterprise_service TYPE ty_category VALUE '90', + END OF co_category. + + TYPES: + BEGIN OF ty_main, + format_version TYPE zif_abapgit_aff_types_v1=>ty_format_version, + header TYPE zif_abapgit_aff_types_v1=>ty_header_60_src, + category TYPE ty_category, + proxy TYPE abap_bool, + descriptions TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions, + END OF ty_main. + +ENDINTERFACE. + +INTERFACE zif_abapgit_ecatt . + + " downport missing types + + TYPES: + ty_invert_validation TYPE c LENGTH 1, + ty_error_prio TYPE n LENGTH 1, + ty_impl_name TYPE c LENGTH 30, + ty_impl_type TYPE c LENGTH 1, + ty_impl_subtype TYPE c LENGTH 4, + ty_package TYPE c LENGTH 255, + BEGIN OF ty_impl_det, + impl_name TYPE ty_impl_name, + impl_type TYPE ty_impl_type, + impl_subtype TYPE ty_impl_subtype, + impl_package TYPE ty_package, + END OF ty_impl_det. + + TYPES: + BEGIN OF ty_bus_msg. + INCLUDE TYPE etobj_key. + TYPES: + bus_msg_no TYPE c LENGTH 1, " ty_msg_no + arbgb TYPE arbgb, + msgnr TYPE msgnr, + bus_msg_text TYPE string, "ty_bus_msg_text + otr_key TYPE sotr_conc, + msg_type TYPE c LENGTH 4, "ty_msg_type + END OF ty_bus_msg, + + ty_bus_msgs TYPE STANDARD TABLE OF ty_bus_msg. + +ENDINTERFACE. + +INTERFACE zif_abapgit_ecatt_download . + + METHODS: + get_xml_stream + RETURNING + VALUE(rv_xml_stream) TYPE xstring. + +ENDINTERFACE. + +INTERFACE zif_abapgit_ecatt_upload . + METHODS: + set_stream_for_upload + IMPORTING + iv_xml TYPE xstring. + +ENDINTERFACE. + +INTERFACE zif_abapgit_object_enho. + + METHODS: + deserialize + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + iv_package TYPE devclass + RAISING zcx_abapgit_exception, + serialize + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_output + ii_enh_tool TYPE REF TO if_enh_tool + RAISING zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_object_enhs. + + METHODS: + deserialize + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + iv_package TYPE devclass + ii_enh_spot_tool TYPE REF TO if_enh_spot_tool + RAISING zcx_abapgit_exception, + + serialize + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_output + ii_enh_spot_tool TYPE REF TO if_enh_spot_tool + RAISING zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_field_rules. + + TYPES ty_fill_rule TYPE c LENGTH 2. + + CONSTANTS: + BEGIN OF c_fill_rule, + date TYPE ty_fill_rule VALUE 'DT', + time TYPE ty_fill_rule VALUE 'TM', + timestamp TYPE ty_fill_rule VALUE 'TS', + user TYPE ty_fill_rule VALUE 'UR', + client TYPE ty_fill_rule VALUE 'CT', + package TYPE ty_fill_rule VALUE 'PK', + abap_language_version TYPE ty_fill_rule VALUE 'AL', + END OF c_fill_rule. + + METHODS add + IMPORTING + iv_table TYPE tabname + iv_field TYPE fieldname + iv_fill_rule TYPE ty_fill_rule + RETURNING + VALUE(ro_self) TYPE REF TO zif_abapgit_field_rules. + + METHODS apply_clear_logic + IMPORTING + iv_table TYPE tabname + CHANGING + ct_data TYPE STANDARD TABLE. + + METHODS apply_fill_logic + IMPORTING + iv_table TYPE tabname + iv_package TYPE devclass + iv_abap_language_version TYPE uccheck OPTIONAL + CHANGING + ct_data TYPE STANDARD TABLE. + +ENDINTERFACE. + +INTERFACE zif_abapgit_function_module. + + METHODS: + function_exists + IMPORTING + iv_function_module_name TYPE clike + RETURNING + VALUE(rv_exists) TYPE abap_bool. + +ENDINTERFACE. + +INTERFACE zif_abapgit_lang_definitions. + + TYPES: + BEGIN OF ty_tpool. + INCLUDE TYPE textpool. + TYPES: split TYPE c LENGTH 8, + END OF ty_tpool, + ty_tpool_tt TYPE STANDARD TABLE OF ty_tpool WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_i18n_tpool, + language TYPE langu, + textpool TYPE ty_tpool_tt, + END OF ty_i18n_tpool, + ty_i18n_tpools TYPE STANDARD TABLE OF ty_i18n_tpool. + + TYPES: BEGIN OF ty_i18n_line, + language TYPE langu, + lines TYPE tlinetab, + END OF ty_i18n_line, + ty_i18n_lines TYPE STANDARD TABLE OF ty_i18n_line WITH KEY language. + + TYPES: ty_langus TYPE STANDARD TABLE OF langu. + +ENDINTERFACE. + +INTERFACE zif_abapgit_lxe_texts . + +* type LXE_PCX_S1 inlined to be compatible with open-abap and ABAP Cloud + TYPES: BEGIN OF ty_text_pair, + textkey TYPE c LENGTH 32, + s_text TYPE c LENGTH 255, + t_text TYPE c LENGTH 255, + unitmlt TYPE i, + uppcase TYPE c LENGTH 4, + texttype TYPE c LENGTH 1, + END OF ty_text_pair. + + TYPES ty_text_pairs TYPE STANDARD TABLE OF ty_text_pair WITH DEFAULT KEY. + + METHODS serialize + IMPORTING + !iv_object_type TYPE tadir-object + !iv_object_name TYPE tadir-obj_name + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params + !ii_xml TYPE REF TO zif_abapgit_xml_output + !io_files TYPE REF TO zcl_abapgit_objects_files + RAISING + zcx_abapgit_exception . + METHODS deserialize + IMPORTING + !iv_object_type TYPE tadir-object + !iv_object_name TYPE tadir-obj_name + !iv_package TYPE tadir-devclass + !ii_xml TYPE REF TO zif_abapgit_xml_input + !io_files TYPE REF TO zcl_abapgit_objects_files + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_i18n_file. + + TYPES ty_table_of TYPE STANDARD TABLE OF REF TO zif_abapgit_i18n_file WITH DEFAULT KEY. + + METHODS render + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_abapgit_exception. + + METHODS translate + CHANGING + cv_changed TYPE abap_bool + ct_text_pairs TYPE zif_abapgit_lxe_texts=>ty_text_pairs + RAISING + zcx_abapgit_exception. + + METHODS ext + RETURNING + VALUE(rv_ext) TYPE string. + + METHODS lang + RETURNING + VALUE(rv_lang) TYPE laiso. + + METHODS lang_suffix + RETURNING + VALUE(rv_lang_suffix) TYPE string. + +ENDINTERFACE. + +INTERFACE zif_abapgit_comparator . + TYPES: + BEGIN OF ty_result, + text TYPE string, + END OF ty_result . + + METHODS compare + IMPORTING + !ii_local TYPE REF TO zif_abapgit_xml_input + !ii_remote TYPE REF TO zif_abapgit_xml_input + !ii_log TYPE REF TO zif_abapgit_log + RETURNING + VALUE(rs_result) TYPE ty_result + RAISING + zcx_abapgit_exception . +ENDINTERFACE. + +INTERFACE zif_abapgit_persist_packages. + + TYPES: + BEGIN OF ty_package, + devclass TYPE scompkdtln-devclass, + component TYPE scompkdtln-component, + comp_posid TYPE scompkdtln-comp_posid, + END OF ty_package, + ty_packages TYPE HASHED TABLE OF ty_package WITH UNIQUE KEY devclass. + + METHODS modify + IMPORTING + !iv_package TYPE scompkdtln-devclass + !iv_component TYPE scompkdtln-component OPTIONAL + !iv_comp_posid TYPE scompkdtln-comp_posid OPTIONAL + RAISING + zcx_abapgit_exception. + + METHODS read + IMPORTING + !iv_package TYPE scompkdtln-devclass + RETURNING + VALUE(rs_package) TYPE ty_package. + +ENDINTERFACE. + +INTERFACE zif_abapgit_persist_settings. + + METHODS modify + IMPORTING + !io_settings TYPE REF TO zcl_abapgit_settings + RAISING + zcx_abapgit_exception . + METHODS read + RETURNING + VALUE(ro_settings) TYPE REF TO zcl_abapgit_settings . + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_asset_manager . + + TYPES: + BEGIN OF ty_web_asset, + url TYPE string, + type TYPE c LENGTH 50, + subtype TYPE c LENGTH 50, + content TYPE xstring, + is_cacheable TYPE abap_bool, + END OF ty_web_asset . + TYPES: + ty_web_assets TYPE STANDARD TABLE OF ty_web_asset WITH DEFAULT KEY . + + METHODS get_all_assets + RETURNING + VALUE(rt_assets) TYPE ty_web_assets + RAISING + zcx_abapgit_exception. + + METHODS get_asset + IMPORTING + iv_url TYPE string + RETURNING + VALUE(rs_asset) TYPE ty_web_asset + RAISING + zcx_abapgit_exception. + + METHODS get_text_asset + IMPORTING + iv_url TYPE string + iv_assert_subtype TYPE string OPTIONAL + RETURNING + VALUE(rv_asset) TYPE string + RAISING + zcx_abapgit_exception. + + METHODS register_asset + IMPORTING + !iv_url TYPE string + !iv_type TYPE string + !iv_cacheable TYPE abap_bool DEFAULT abap_true + !iv_mime_name TYPE wwwdatatab-objid OPTIONAL + !iv_base64 TYPE string OPTIONAL + !iv_inline TYPE string OPTIONAL + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_error_handler . + + METHODS handle_error + IMPORTING + ix_error TYPE REF TO zcx_abapgit_exception + RETURNING + VALUE(rv_handled) TYPE abap_bool. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_event_handler . + + TYPES: + BEGIN OF ty_handling_result, + page TYPE REF TO zif_abapgit_gui_renderable, + state TYPE i, + END OF ty_handling_result. + + METHODS on_event + IMPORTING + ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE ty_handling_result + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_hotkeys . + + TYPES: + BEGIN OF ty_hotkey_with_descr, + ui_component TYPE string, + action TYPE string, + hotkey TYPE string, + description TYPE string, + END OF ty_hotkey_with_descr . + TYPES: + ty_hotkeys_with_descr TYPE STANDARD TABLE OF ty_hotkey_with_descr + WITH DEFAULT KEY + WITH UNIQUE SORTED KEY action COMPONENTS ui_component action . + + METHODS get_hotkey_actions + RETURNING + VALUE(rt_hotkey_actions) TYPE ty_hotkeys_with_descr + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_hotkey_ctl. + METHODS register_hotkeys + IMPORTING + !it_hotkeys TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr. + METHODS reset. + METHODS get_registered_hotkeys + RETURNING + VALUE(rt_registered_hotkeys) TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr + RAISING + zcx_abapgit_exception. + METHODS set_visible + IMPORTING + iv_visible TYPE abap_bool. +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_html_processor . + + METHODS process + IMPORTING + !iv_html TYPE string + !ii_gui_services TYPE REF TO zif_abapgit_gui_services + RETURNING + VALUE(rv_html) TYPE string + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_modal . + + METHODS is_modal + RETURNING + VALUE(rv_yes) TYPE abap_bool. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_renderable . + + METHODS render + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_services . + METHODS cache_asset + IMPORTING + !iv_text TYPE string OPTIONAL + !iv_xdata TYPE xstring OPTIONAL + !iv_url TYPE string OPTIONAL + !iv_type TYPE c + !iv_subtype TYPE c + RETURNING + VALUE(rv_url) TYPE string + RAISING + zcx_abapgit_exception . + " Notes: + " - page_asset is supposed to be not cacheable + " - add mime64 if needed (supposedly won't be needed) + METHODS register_page_asset + IMPORTING + !iv_url TYPE string + !iv_type TYPE string + !iv_mime_name TYPE wwwdatatab-objid OPTIONAL + !iv_inline TYPE string OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS register_event_handler + IMPORTING + !ii_event_handler TYPE REF TO zif_abapgit_gui_event_handler . + METHODS get_current_page_name + RETURNING + VALUE(rv_page_name) TYPE string . + METHODS get_hotkeys_ctl + RETURNING + VALUE(ri_hotkey_ctl) TYPE REF TO zif_abapgit_gui_hotkey_ctl . + METHODS get_html_parts + RETURNING + VALUE(ro_parts) TYPE REF TO zcl_abapgit_html_parts . + METHODS get_log + IMPORTING + !iv_create_new TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log . + +ENDINTERFACE. + +INTERFACE zif_abapgit_html. + + TYPES: + BEGIN OF ty_data_attr, + name TYPE string, + value TYPE string, + END OF ty_data_attr, + ty_data_attrs TYPE STANDARD TABLE OF ty_data_attr WITH KEY name. + + CONSTANTS: + BEGIN OF c_action_type, + sapevent TYPE c VALUE 'E', + url TYPE c VALUE 'U', + onclick TYPE c VALUE 'C', + separator TYPE c VALUE 'S', + dummy TYPE c VALUE '_', + END OF c_action_type . + CONSTANTS: + BEGIN OF c_html_opt, + strong TYPE c VALUE 'E', + cancel TYPE c VALUE 'C', + crossout TYPE c VALUE 'X', + END OF c_html_opt . + + TYPES: + ty_table_of TYPE STANDARD TABLE OF REF TO zif_abapgit_html WITH DEFAULT KEY. + + DATA mv_chunk_title TYPE string READ-ONLY. " Primarily for debug of postponed html parts + + METHODS set_title + IMPORTING + iv_title TYPE string + RETURNING + VALUE(ri_self) TYPE REF TO zif_abapgit_html. + + METHODS add + IMPORTING + !ig_chunk TYPE any + RETURNING + VALUE(ri_self) TYPE REF TO zif_abapgit_html. + + METHODS render + IMPORTING + !iv_no_indent_jscss TYPE abap_bool DEFAULT abap_false + !iv_no_line_breaks TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rv_html) TYPE string . + + METHODS is_empty + RETURNING + VALUE(rv_yes) TYPE abap_bool . + + METHODS add_a + IMPORTING + !iv_txt TYPE string + !iv_act TYPE string + !iv_query TYPE string OPTIONAL + !iv_typ TYPE c DEFAULT c_action_type-sapevent + !iv_opt TYPE clike OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_id TYPE string OPTIONAL + !iv_style TYPE string OPTIONAL + !iv_title TYPE string OPTIONAL + RETURNING + VALUE(ri_self) TYPE REF TO zif_abapgit_html. + + METHODS add_checkbox + IMPORTING + iv_id TYPE string + iv_checked TYPE abap_bool OPTIONAL + RETURNING + VALUE(ri_self) TYPE REF TO zif_abapgit_html. + + METHODS a + IMPORTING + !iv_txt TYPE string + !iv_act TYPE string + !iv_query TYPE string OPTIONAL + !iv_typ TYPE c DEFAULT zif_abapgit_html=>c_action_type-sapevent + !iv_opt TYPE clike OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_id TYPE string OPTIONAL + !iv_style TYPE string OPTIONAL + !iv_title TYPE string OPTIONAL + RETURNING + VALUE(rv_str) TYPE string . + + METHODS icon + IMPORTING + !iv_name TYPE string + !iv_hint TYPE string OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_onclick TYPE string OPTIONAL + RETURNING + VALUE(rv_str) TYPE string . + + METHODS add_icon + IMPORTING + !iv_name TYPE string + !iv_hint TYPE string OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_onclick TYPE string OPTIONAL + RETURNING + VALUE(ri_self) TYPE REF TO zif_abapgit_html. + + METHODS wrap + IMPORTING + !iv_tag TYPE string + !iv_content TYPE string OPTIONAL + !ii_content TYPE REF TO zif_abapgit_html OPTIONAL + !iv_id TYPE string OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_hint TYPE string OPTIONAL + !iv_style TYPE string OPTIONAL + !iv_format_single_line TYPE abap_bool DEFAULT abap_false + !is_data_attr TYPE ty_data_attr OPTIONAL + !it_data_attrs TYPE ty_data_attrs OPTIONAL + RETURNING + VALUE(ri_self) TYPE REF TO zif_abapgit_html. + + METHODS td + IMPORTING + !iv_content TYPE string OPTIONAL + !ii_content TYPE REF TO zif_abapgit_html OPTIONAL + !iv_id TYPE string OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_hint TYPE string OPTIONAL + !iv_style TYPE string OPTIONAL + !iv_format_single_line TYPE abap_bool DEFAULT abap_true + !is_data_attr TYPE ty_data_attr OPTIONAL + !it_data_attrs TYPE ty_data_attrs OPTIONAL + PREFERRED PARAMETER iv_content + RETURNING + VALUE(ri_self) TYPE REF TO zif_abapgit_html. + + METHODS th + IMPORTING + !iv_content TYPE string OPTIONAL + !ii_content TYPE REF TO zif_abapgit_html OPTIONAL + !iv_id TYPE string OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_hint TYPE string OPTIONAL + !iv_style TYPE string OPTIONAL + !iv_format_single_line TYPE abap_bool DEFAULT abap_true + !is_data_attr TYPE ty_data_attr OPTIONAL + !it_data_attrs TYPE ty_data_attrs OPTIONAL + PREFERRED PARAMETER iv_content + RETURNING + VALUE(ri_self) TYPE REF TO zif_abapgit_html. + + METHODS div + IMPORTING + !iv_content TYPE string OPTIONAL + !ii_content TYPE REF TO zif_abapgit_html OPTIONAL + !iv_id TYPE string OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_style TYPE string OPTIONAL + !is_data_attr TYPE ty_data_attr OPTIONAL + !it_data_attrs TYPE ty_data_attrs OPTIONAL + PREFERRED PARAMETER iv_content + RETURNING + VALUE(ri_self) TYPE REF TO zif_abapgit_html. + +ENDINTERFACE. + +INTERFACE zif_abapgit_html_viewer . + TYPES: + ty_char256 TYPE c LENGTH 256 . + TYPES: + ty_post_data TYPE STANDARD TABLE OF ty_char256 WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_name_value, + name TYPE c LENGTH 30, + value TYPE c LENGTH 250, + END OF ty_name_value . + TYPES: + ty_query_table TYPE STANDARD TABLE OF ty_name_value WITH DEFAULT KEY . + + CONSTANTS c_id_sapevent TYPE i VALUE 1 ##NO_TEXT. + + EVENTS sapevent + EXPORTING + VALUE(action) TYPE c OPTIONAL + VALUE(frame) TYPE c OPTIONAL + VALUE(getdata) TYPE c OPTIONAL + VALUE(postdata) TYPE ty_post_data OPTIONAL + VALUE(query_table) TYPE ty_query_table OPTIONAL . + + METHODS load_data + IMPORTING + !iv_url TYPE string OPTIONAL + !iv_type TYPE c DEFAULT 'text' + !iv_subtype TYPE c DEFAULT 'html' + !iv_size TYPE i DEFAULT 0 + EXPORTING + !ev_assigned_url TYPE string + CHANGING + !ct_data_table TYPE STANDARD TABLE + RAISING + zcx_abapgit_exception . + METHODS set_registered_events + IMPORTING + !it_events TYPE cntl_simple_events + RAISING + zcx_abapgit_exception . + METHODS show_url + IMPORTING + !iv_url TYPE string + RAISING + zcx_abapgit_exception . + METHODS free . + METHODS close_document . + METHODS get_url + RETURNING + VALUE(rv_url) TYPE string . + METHODS back . + METHODS set_visiblity + IMPORTING + !iv_visible TYPE abap_bool . + METHODS set_focus RAISING zcx_abapgit_exception. +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_event . + + DATA mv_action TYPE string READ-ONLY. + DATA mv_getdata TYPE string READ-ONLY. + DATA mt_postdata TYPE zif_abapgit_html_viewer=>ty_post_data READ-ONLY. + DATA mi_gui_services TYPE REF TO zif_abapgit_gui_services READ-ONLY. + DATA mv_current_page_name TYPE string. + + METHODS query + RETURNING + VALUE(ro_string_map) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + + METHODS form_data + RETURNING + VALUE(ro_string_map) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_menu_provider . + + METHODS get_menu + RETURNING + VALUE(ro_toolbar) TYPE REF TO zcl_abapgit_html_toolbar + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_page_title . + + METHODS get_page_title + RETURNING + VALUE(rv_title) TYPE string. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_render_item . + + METHODS render + IMPORTING + iv_item TYPE any + iv_index TYPE i + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_html_form . + + TYPES: + BEGIN OF ty_subitem, + label TYPE string, + value TYPE string, + readonly TYPE abap_bool, + END OF ty_subitem . + TYPES: + ty_subitems TYPE STANDARD TABLE OF ty_subitem WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_field, + type TYPE i, + name TYPE string, + label TYPE string, + hint TYPE string, + dblclick TYPE string, + click TYPE string, + placeholder TYPE string, + required TYPE string, + upper_case TYPE abap_bool, + item_class TYPE string, + error TYPE string, + default_value TYPE string, + side_action TYPE string, + subitems TYPE ty_subitems, + readonly TYPE abap_bool, + password TYPE abap_bool, + condense TYPE abap_bool, + min TYPE i, + max TYPE i, + rows TYPE i, + cols TYPE i, + END OF ty_field . + TYPES: + ty_fields TYPE STANDARD TABLE OF ty_field + WITH DEFAULT KEY + WITH UNIQUE SORTED KEY by_name COMPONENTS name . + TYPES: + BEGIN OF ty_command, + label TYPE string, + action TYPE string, + cmd_type TYPE i, + END OF ty_command . + + CONSTANTS c_rows TYPE string VALUE 'rows'. + CONSTANTS: + BEGIN OF c_cmd_type, + input TYPE i VALUE 1, + input_main TYPE i VALUE 2, + link TYPE i VALUE 3, + button TYPE i VALUE 4, + END OF c_cmd_type . + CONSTANTS: + BEGIN OF c_field_type, + text TYPE i VALUE 1, + radio TYPE i VALUE 2, + checkbox TYPE i VALUE 3, + field_group TYPE i VALUE 4, + number TYPE i VALUE 5, + textarea TYPE i VALUE 6, + table TYPE i VALUE 7, + hidden TYPE i VALUE 8, + END OF c_field_type . + +ENDINTERFACE. + +INTERFACE zif_abapgit_html_popup . + + METHODS create_picklist + RETURNING + VALUE(ro_picklist) TYPE REF TO zcl_abapgit_gui_picklist + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_html_table . + + TYPES: + BEGIN OF ty_row_attrs, + css_class TYPE string, + data TYPE zif_abapgit_html=>ty_data_attr, + END OF ty_row_attrs. + + TYPES: + BEGIN OF ty_cell_render, + css_class TYPE string, + content TYPE string, + html TYPE REF TO zif_abapgit_html, + END OF ty_cell_render. + + TYPES: + BEGIN OF ty_sorting_state, + column_id TYPE string, + descending TYPE abap_bool, + END OF ty_sorting_state. + + METHODS get_row_attrs + IMPORTING + iv_table_id TYPE string + iv_row_index TYPE i + is_row TYPE any + RETURNING + VALUE(rs_attrs) TYPE ty_row_attrs + RAISING + zcx_abapgit_exception. + + METHODS render_cell + IMPORTING + iv_table_id TYPE string + iv_row_index TYPE i + is_row TYPE any + iv_column_id TYPE string + iv_value TYPE any + RETURNING + VALUE(rs_render) TYPE ty_cell_render + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_diff. + + TYPES: + BEGIN OF ty_file_diff, + path TYPE string, + filename TYPE string, + obj_type TYPE string, + obj_name TYPE string, + lstate TYPE c LENGTH 1, + rstate TYPE c LENGTH 1, + fstate TYPE c LENGTH 1, " FILE state - Abstraction for shorter ifs + o_diff TYPE REF TO zif_abapgit_diff, + changed_by TYPE syuname, + type TYPE string, + END OF ty_file_diff. + TYPES: + ty_file_diffs TYPE STANDARD TABLE OF ty_file_diff + WITH NON-UNIQUE DEFAULT KEY + WITH NON-UNIQUE SORTED KEY secondary + COMPONENTS path filename. + +ENDINTERFACE. + +INTERFACE zif_abapgit_progress . + METHODS show + IMPORTING + !iv_current TYPE i + !iv_text TYPE csequence . + METHODS set_total + IMPORTING + !iv_total TYPE i . + METHODS off . +ENDINTERFACE. + +INTERFACE zif_abapgit_services_repo . + + TYPES: + BEGIN OF ty_repo_params, + name TYPE string, + url TYPE string, + package TYPE devclass, + branch_name TYPE string, + display_name TYPE string, + folder_logic TYPE string, + labels TYPE string, + ignore_subpackages TYPE abap_bool, + main_lang_only TYPE abap_bool, + abap_lang_vers TYPE string, + END OF ty_repo_params . + +ENDINTERFACE. + +INTERFACE zif_abapgit_frontend_services. + + TYPES: + ty_char1 TYPE c LENGTH 1, + ty_gui_release TYPE n LENGTH 4, + ty_gui_sp TYPE n LENGTH 2, + ty_gui_patch TYPE n LENGTH 2. + + METHODS file_upload + IMPORTING + !iv_path TYPE string + RETURNING + VALUE(rv_xstr) TYPE xstring + RAISING + zcx_abapgit_exception. + + METHODS file_download + IMPORTING + !iv_path TYPE string + !iv_xstr TYPE xstring + RAISING + zcx_abapgit_exception . + + METHODS show_file_save_dialog + IMPORTING + !iv_title TYPE string + !iv_extension TYPE string + !iv_default_filename TYPE string + RETURNING + VALUE(rv_path) TYPE string + RAISING + zcx_abapgit_exception. + + METHODS show_file_open_dialog + IMPORTING + !iv_title TYPE string + !iv_extension TYPE string + !iv_default_filename TYPE string + RETURNING + VALUE(rv_path) TYPE string + RAISING + zcx_abapgit_exception. + + METHODS clipboard_export + IMPORTING + iv_no_auth_check TYPE abap_bool DEFAULT abap_false + VALUE(it_data) TYPE STANDARD TABLE + RAISING + zcx_abapgit_exception. + + METHODS execute + IMPORTING + !iv_document TYPE string OPTIONAL + !iv_application TYPE string OPTIONAL + !iv_parameter TYPE string OPTIONAL + !iv_default_directory TYPE string OPTIONAL + !iv_maximized TYPE string OPTIONAL + !iv_minimized TYPE string OPTIONAL + !iv_synchronous TYPE string OPTIONAL + !iv_operation TYPE string DEFAULT 'OPEN' + RAISING + zcx_abapgit_exception. + + METHODS get_system_directory + CHANGING + !cv_system_directory TYPE string + RAISING + zcx_abapgit_exception. + + METHODS directory_browse + IMPORTING + iv_window_title TYPE string OPTIONAL + iv_initial_folder TYPE string OPTIONAL + CHANGING + cv_selected_folder TYPE string + RAISING + zcx_abapgit_exception. + + METHODS get_file_separator + CHANGING + cv_file_separator TYPE ty_char1 + RAISING + zcx_abapgit_exception. + + METHODS get_gui_version + EXPORTING + ev_gui_release TYPE ty_gui_release + ev_gui_sp TYPE ty_gui_sp + ev_gui_patch TYPE ty_gui_patch + ev_gui_version_string TYPE string + RAISING + zcx_abapgit_exception. + + METHODS directory_exist + IMPORTING + iv_directory TYPE string + RETURNING + VALUE(rv_exists) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS directory_create + IMPORTING + iv_directory TYPE string + CHANGING + cv_rc TYPE i + RAISING + zcx_abapgit_exception. + + METHODS gui_is_available + RETURNING + VALUE(rv_gui_is_available) TYPE abap_bool. + + METHODS is_sapgui_for_java + RETURNING + VALUE(rv_result) TYPE abap_bool. + + METHODS is_sapgui_for_windows + RETURNING + VALUE(rv_result) TYPE abap_bool. + + METHODS is_webgui + RETURNING + VALUE(rv_is_webgui) TYPE abap_bool. + + METHODS open_ie_devtools + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_definitions . + + TYPES: + ty_string_tt TYPE STANDARD TABLE OF string WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_item_signature, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + devclass TYPE devclass, + END OF ty_item_signature . + TYPES: + BEGIN OF ty_obj_namespace, + namespace TYPE trnspace-namespace, + obj_without_namespace TYPE tadir-obj_name, + END OF ty_obj_namespace. + TYPES: + BEGIN OF ty_item. + INCLUDE TYPE ty_item_signature. + TYPES: + srcsystem TYPE tadir-srcsystem, + origlang TYPE tadir-masterlang, + inactive TYPE abap_bool, + abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version, + END OF ty_item . + TYPES: + ty_items_tt TYPE STANDARD TABLE OF ty_item WITH DEFAULT KEY . + TYPES: + ty_items_ts TYPE SORTED TABLE OF ty_item WITH UNIQUE KEY obj_type obj_name . + TYPES: + BEGIN OF ty_file_item, + file TYPE zif_abapgit_git_definitions=>ty_file, + item TYPE ty_item, + END OF ty_file_item . + TYPES: + ty_files_item_tt TYPE STANDARD TABLE OF ty_file_item WITH DEFAULT KEY . + TYPES: + ty_files_item_by_file_tt TYPE SORTED TABLE OF ty_file_item WITH UNIQUE KEY file-path file-filename. + TYPES: + ty_yes_no TYPE c LENGTH 1, + ty_yes_no_partial TYPE c LENGTH 1. + TYPES: + BEGIN OF ty_overwrite. + INCLUDE TYPE ty_item. + TYPES: + state TYPE c LENGTH 2, + action TYPE i, + icon TYPE icon_d, + text TYPE string, + decision TYPE ty_yes_no, + END OF ty_overwrite . + TYPES: + ty_overwrite_tt TYPE STANDARD TABLE OF ty_overwrite WITH DEFAULT KEY + WITH UNIQUE HASHED KEY object_type_and_name + COMPONENTS obj_type obj_name . + TYPES: + BEGIN OF ty_requirements, + met TYPE ty_yes_no, + decision TYPE ty_yes_no, + END OF ty_requirements . + TYPES: + BEGIN OF ty_dependencies, + met TYPE ty_yes_no, + decision TYPE ty_yes_no, + END OF ty_dependencies . + TYPES: + BEGIN OF ty_transport_type, + request TYPE trfunction, + task TYPE trfunction, + END OF ty_transport_type . + TYPES: + BEGIN OF ty_transport, + required TYPE abap_bool, + transport TYPE trkorr, + type TYPE ty_transport_type, + END OF ty_transport . + TYPES: + BEGIN OF ty_deserialize_checks, + overwrite TYPE ty_overwrite_tt, + warning_package TYPE ty_overwrite_tt, + data_loss TYPE ty_overwrite_tt, + requirements TYPE ty_requirements, + dependencies TYPE ty_dependencies, + transport TYPE ty_transport, + customizing TYPE ty_transport, + END OF ty_deserialize_checks . + TYPES: + BEGIN OF ty_delete_checks, + transport TYPE ty_transport, + END OF ty_delete_checks . + TYPES: + BEGIN OF ty_metadata, + class TYPE string, + version TYPE string, + END OF ty_metadata . + TYPES: + BEGIN OF ty_repo_file, + path TYPE string, + filename TYPE string, + is_changed TYPE abap_bool, + rstate TYPE zif_abapgit_git_definitions=>ty_item_state, + lstate TYPE zif_abapgit_git_definitions=>ty_item_state, + END OF ty_repo_file . + TYPES: + ty_repo_file_tt TYPE STANDARD TABLE OF ty_repo_file WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_object, + sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + type TYPE zif_abapgit_git_definitions=>ty_type, + data TYPE xstring, + adler32 TYPE zif_abapgit_git_definitions=>ty_adler32, + index TYPE i, + END OF ty_object . + TYPES: + ty_objects_tt TYPE STANDARD TABLE OF ty_object WITH DEFAULT KEY + WITH NON-UNIQUE SORTED KEY sha COMPONENTS sha1 + WITH NON-UNIQUE SORTED KEY type COMPONENTS type sha1 . + TYPES: + BEGIN OF ty_tadir, + pgmid TYPE tadir-pgmid, + object TYPE tadir-object, + obj_name TYPE tadir-obj_name, + devclass TYPE tadir-devclass, + korrnum TYPE tadir-korrnum, " used by ZCL_ABAPGIT_DEPENDENCIES->RESOLVE + delflag TYPE tadir-delflag, + genflag TYPE tadir-genflag, + path TYPE string, + srcsystem TYPE tadir-srcsystem, + masterlang TYPE tadir-masterlang, + END OF ty_tadir . + TYPES: + ty_tadir_tt TYPE STANDARD TABLE OF ty_tadir WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_result, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + inactive TYPE abap_bool, + path TYPE string, + filename TYPE string, + package TYPE devclass, + match TYPE abap_bool, + lstate TYPE zif_abapgit_git_definitions=>ty_item_state, + rstate TYPE zif_abapgit_git_definitions=>ty_item_state, + packmove TYPE abap_bool, + srcsystem TYPE tadir-srcsystem, + origlang TYPE tadir-masterlang, + END OF ty_result . + TYPES: + ty_results_tt TYPE STANDARD TABLE OF ty_result WITH DEFAULT KEY + WITH NON-UNIQUE SORTED KEY sec_key + COMPONENTS obj_type obj_name. + TYPES: + ty_results_ts_path TYPE HASHED TABLE OF ty_result WITH UNIQUE KEY path filename . + TYPES: + BEGIN OF ty_stage_files, + local TYPE ty_files_item_tt, + remote TYPE zif_abapgit_git_definitions=>ty_files_tt, + status TYPE ty_results_ts_path, + END OF ty_stage_files . + + TYPES: + BEGIN OF ty_transport_to_branch, + branch_name TYPE string, + commit_text TYPE string, + END OF ty_transport_to_branch . + + TYPES: + BEGIN OF ty_diff, + patch_flag TYPE abap_bool, + new_num TYPE c LENGTH 6, + new TYPE string, + result TYPE c LENGTH 1, + old_num TYPE c LENGTH 6, + old TYPE string, + short TYPE abap_bool, + beacon TYPE i, + END OF ty_diff . + TYPES: + ty_diffs_tt TYPE STANDARD TABLE OF ty_diff + WITH DEFAULT KEY + WITH NON-UNIQUE SORTED KEY new_num COMPONENTS new_num + WITH NON-UNIQUE SORTED KEY old_num COMPONENTS old_num. + TYPES: + BEGIN OF ty_count, + insert TYPE i, + delete TYPE i, + update TYPE i, + END OF ty_count . + TYPES: + BEGIN OF ty_ancestor, + commit TYPE zif_abapgit_git_definitions=>ty_sha1, + tree TYPE zif_abapgit_git_definitions=>ty_sha1, + time TYPE string, + body TYPE string, + END OF ty_ancestor . + TYPES: + BEGIN OF ty_repo_item, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + inactive TYPE abap_bool, + sortkey TYPE i, + path TYPE string, + is_dir TYPE abap_bool, + changes TYPE i, + lstate TYPE zif_abapgit_git_definitions=>ty_item_state, + rstate TYPE zif_abapgit_git_definitions=>ty_item_state, + files TYPE ty_repo_file_tt, + changed_by TYPE syuname, + transport TYPE trkorr, + packmove TYPE abap_bool, + srcsystem TYPE tadir-srcsystem, + origlang TYPE tadir-masterlang, + END OF ty_repo_item . + TYPES: + ty_repo_item_tt TYPE STANDARD TABLE OF ty_repo_item WITH DEFAULT KEY . + + TYPES: + ty_dokil_tt TYPE STANDARD TABLE OF dokil + WITH NON-UNIQUE DEFAULT KEY . + TYPES: + ty_proxy_bypass_url TYPE c LENGTH 255, + ty_range_proxy_bypass_url TYPE RANGE OF ty_proxy_bypass_url. + TYPES: + BEGIN OF ty_version, + major TYPE i, + minor TYPE i, + patch TYPE i, + prerelase TYPE string, + prerelase_patch TYPE i, + END OF ty_version. + TYPES ty_sci_result TYPE c LENGTH 1. + CONSTANTS: + BEGIN OF c_sci_result, + no_run TYPE ty_sci_result VALUE '', + failed TYPE ty_sci_result VALUE 'F', + warning TYPE ty_sci_result VALUE 'W', + passed TYPE ty_sci_result VALUE 'P', + END OF c_sci_result. + CONSTANTS: + BEGIN OF c_diff, + unchanged TYPE c LENGTH 1 VALUE ' ', + insert TYPE c LENGTH 1 VALUE 'I', + delete TYPE c LENGTH 1 VALUE 'D', + update TYPE c LENGTH 1 VALUE 'U', + END OF c_diff . + CONSTANTS: + BEGIN OF c_state, " https://git-scm.com/docs/git-status + unchanged TYPE zif_abapgit_git_definitions=>ty_item_state VALUE '', + added TYPE zif_abapgit_git_definitions=>ty_item_state VALUE 'A', + modified TYPE zif_abapgit_git_definitions=>ty_item_state VALUE 'M', + deleted TYPE zif_abapgit_git_definitions=>ty_item_state VALUE 'D', + mixed TYPE zif_abapgit_git_definitions=>ty_item_state VALUE '*', + END OF c_state . + CONSTANTS c_english TYPE spras VALUE 'E' ##NO_TEXT. + CONSTANTS c_root_dir TYPE string VALUE '/' ##NO_TEXT. + CONSTANTS c_dot_abapgit TYPE string VALUE '.abapgit.xml' ##NO_TEXT. + CONSTANTS c_author_regex TYPE string VALUE '^(.+) <(.*)> (\d{10})\s?.\d{4}$' ##NO_TEXT. + CONSTANTS: + BEGIN OF c_action, + abapgit_home TYPE string VALUE 'abapgit_home', + bg_update TYPE string VALUE 'bg_update', + change_order_by TYPE string VALUE 'change_order_by', + changelog TYPE string VALUE 'changelog', + clipboard TYPE string VALUE 'clipboard', + db_display TYPE string VALUE 'db_display', + db_edit TYPE string VALUE 'db_edit', + direction TYPE string VALUE 'direction', + documentation TYPE string VALUE 'documentation', + flow TYPE string VALUE 'flow', + git_branch_create TYPE string VALUE 'git_branch_create', + git_branch_delete TYPE string VALUE 'git_branch_delete', + git_branch_merge TYPE string VALUE 'git_branch_merge', + git_branch_switch TYPE string VALUE 'git_branch_switch', + git_commit TYPE string VALUE 'git_commit', + git_pull TYPE string VALUE 'git_pull', + git_tag_create TYPE string VALUE 'git_tag_create', + git_tag_delete TYPE string VALUE 'git_tag_delete', + git_tag_switch TYPE string VALUE 'git_tag_switch', + go_back TYPE string VALUE 'go_back', + go_background TYPE string VALUE 'go_background', + go_background_run TYPE string VALUE 'go_background_run', + go_commit TYPE string VALUE 'go_commit', + go_db TYPE string VALUE 'go_db', + go_debuginfo TYPE string VALUE 'go_debuginfo', + go_explore TYPE string VALUE 'go_explore', + go_file_diff TYPE string VALUE 'go_file_diff', + go_home TYPE string VALUE 'go_home', + go_patch TYPE string VALUE 'go_patch', + go_repo TYPE string VALUE 'go_repo', + go_repo_diff TYPE string VALUE 'go_repo_diff', + go_settings TYPE string VALUE 'go_settings', + go_settings_personal TYPE string VALUE 'go_settings_personal', + go_stage TYPE string VALUE 'go_stage', + go_stage_transport TYPE string VALUE 'go_stage_transport', + go_tutorial TYPE string VALUE 'go_tutorial', + goto_message TYPE string VALUE 'goto_message', + goto_source TYPE string VALUE 'goto_source', + homepage TYPE string VALUE 'homepage', + ie_devtools TYPE string VALUE 'ie_devtools', + jump TYPE string VALUE 'jump', + jump_transaction TYPE string VALUE 'jump_transaction', + jump_transport TYPE string VALUE 'jump_transport', + jump_user TYPE string VALUE 'jump_user', + performance_test TYPE string VALUE 'performance_test', + repo_activate_objects TYPE string VALUE 'repo_activate_objects', + repo_add_all_obj_to_trans_req TYPE string VALUE 'repo_add_all_obj_to_trans_req', + repo_background TYPE string VALUE 'repo_background', + repo_change_package TYPE string VALUE 'repo_change_package', + repo_code_inspector TYPE string VALUE 'repo_code_inspector', + repo_delete_objects TYPE string VALUE 'repo_delete_objects', + repo_infos TYPE string VALUE 'repo_infos', + repo_local_settings TYPE string VALUE 'repo_local_settings', + repo_log TYPE string VALUE 'repo_log', + repo_newoffline TYPE string VALUE 'repo_newoffline', + repo_newonline TYPE string VALUE 'repo_newonline', + repo_open_in_master_lang TYPE string VALUE 'repo_open_in_master_lang', + repo_purge TYPE string VALUE 'repo_purge', + repo_refresh TYPE string VALUE 'repo_refresh', + repo_refresh_checksums TYPE string VALUE 'repo_refresh_checksums', + repo_remote_settings TYPE string VALUE 'repo_remote_settings', + repo_remove TYPE string VALUE 'repo_remove', + repo_settings TYPE string VALUE 'repo_settings', + repo_syntax_check TYPE string VALUE 'repo_syntax_check', + repo_toggle_fav TYPE string VALUE 'repo_toggle_fav', + repo_transport_to_branch TYPE string VALUE 'repo_transport_to_branch', + rfc_compare TYPE string VALUE 'rfc_compare', + show_callstack TYPE string VALUE 'show_callstack', + show_hotkeys TYPE string VALUE 'show_hotkeys', + sponsor TYPE string VALUE 'sponsor', + toggle_favorites TYPE string VALUE 'toggle_favorites', + url TYPE string VALUE 'url', + where_used TYPE string VALUE 'where_used', + zip_export TYPE string VALUE 'zip_export', + zip_export_transport TYPE string VALUE 'zip_export_transport', + zip_import TYPE string VALUE 'zip_import', + zip_object TYPE string VALUE 'zip_object', + zip_package TYPE string VALUE 'zip_package', + zip_transport TYPE string VALUE 'zip_transport', + END OF c_action. + CONSTANTS c_spagpa_param_repo_key TYPE c LENGTH 20 VALUE 'REPO_KEY' ##NO_TEXT. + CONSTANTS c_spagpa_param_package TYPE c LENGTH 20 VALUE 'PACKAGE' ##NO_TEXT. + CONSTANTS c_yes TYPE ty_yes_no VALUE 'Y'. + CONSTANTS c_no TYPE ty_yes_no VALUE 'N'. + CONSTANTS c_partial TYPE ty_yes_no_partial VALUE 'P'. + + TYPES: + ty_method TYPE c LENGTH 1 . + TYPES: + BEGIN OF ty_stage, + file TYPE zif_abapgit_git_definitions=>ty_file, + method TYPE ty_method, + status TYPE ty_result, + END OF ty_stage . + TYPES: + ty_stage_tt TYPE SORTED TABLE OF ty_stage + WITH UNIQUE KEY file-path file-filename . + + CONSTANTS: + BEGIN OF c_method, + add TYPE ty_method VALUE 'A', + rm TYPE ty_method VALUE 'R', + ignore TYPE ty_method VALUE 'I', + skip TYPE ty_method VALUE '?', + END OF c_method . + + TYPES: + ty_sap_langu_tab TYPE STANDARD TABLE OF langu WITH DEFAULT KEY. + TYPES: + ty_languages TYPE STANDARD TABLE OF laiso WITH DEFAULT KEY. + TYPES: + BEGIN OF ty_i18n_params, + main_language TYPE sy-langu, + main_language_only TYPE abap_bool, + translation_languages TYPE ty_languages, + use_lxe TYPE abap_bool, + suppress_po_comments TYPE abap_bool, + END OF ty_i18n_params . + TYPES ty_trrngtrkor_tt TYPE RANGE OF trkorr. + + CONSTANTS c_multiple_transports TYPE trkorr VALUE 'MULTIPLE'. + +ENDINTERFACE. + +INTERFACE zif_abapgit_apack_definitions . + TYPES: + BEGIN OF ty_dependency, + group_id TYPE string, + artifact_id TYPE string, + version TYPE string, + sem_version TYPE zif_abapgit_definitions=>ty_version, + git_url TYPE string, + target_package TYPE devclass, + END OF ty_dependency, + ty_dependencies TYPE STANDARD TABLE OF ty_dependency + WITH NON-UNIQUE DEFAULT KEY, + + ty_repository_type TYPE string, + + BEGIN OF ty_descriptor_wo_dependencies, + group_id TYPE string, + artifact_id TYPE string, + version TYPE string, + sem_version TYPE zif_abapgit_definitions=>ty_version, + repository_type TYPE ty_repository_type, + git_url TYPE string, + END OF ty_descriptor_wo_dependencies, + + BEGIN OF ty_descriptor. + INCLUDE TYPE ty_descriptor_wo_dependencies. + TYPES: + dependencies TYPE ty_dependencies, + END OF ty_descriptor, + + ty_descriptors TYPE STANDARD TABLE OF ty_descriptor WITH NON-UNIQUE DEFAULT KEY. + + TYPES: + BEGIN OF ty_manifest_declaration, + clsname TYPE seoclsname, + devclass TYPE devclass, + END OF ty_manifest_declaration, + ty_manifest_declarations TYPE STANDARD TABLE OF ty_manifest_declaration WITH DEFAULT KEY. + + CONSTANTS c_dot_apack_manifest TYPE string VALUE '.apack-manifest.xml' ##NO_TEXT. + CONSTANTS c_repository_type_abapgit TYPE ty_repository_type VALUE 'abapGit' ##NO_TEXT. + CONSTANTS c_apack_interface_sap TYPE seoclsname VALUE 'IF_APACK_MANIFEST' ##NO_TEXT. + CONSTANTS c_apack_interface_cust TYPE seoclsname VALUE 'ZIF_APACK_MANIFEST' ##NO_TEXT. + CONSTANTS c_apack_interface_nspc TYPE seoclsname VALUE '/*/IF_APACK_MANIFEST' ##NO_TEXT. +ENDINTERFACE. + +INTERFACE zif_abapgit_cts_api . + TYPES: + BEGIN OF ty_transport, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + trkorr TYPE trkorr, + END OF ty_transport . + TYPES: + ty_transport_list TYPE SORTED TABLE OF ty_transport WITH NON-UNIQUE KEY obj_type obj_name . + TYPES: + ty_trkorr_tt TYPE STANDARD TABLE OF trkorr WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_transport_key, + object TYPE e071k-object, + objname TYPE e071k-objname, + tabkey TYPE e071k-tabkey, + END OF ty_transport_key . + TYPES: + BEGIN OF ty_transport_data, + trstatus TYPE e070-trstatus, + as4date TYPE d, + keys TYPE STANDARD TABLE OF ty_transport_key WITH DEFAULT KEY, + END OF ty_transport_data . + TYPES: + BEGIN OF ty_transport_obj, + object TYPE e071-object, + obj_name TYPE e071-obj_name, + END OF ty_transport_obj . + TYPES: + ty_transport_obj_tt TYPE STANDARD TABLE OF ty_transport_obj WITH DEFAULT KEY . + + CONSTANTS: + BEGIN OF c_transport_type, + wb_request TYPE c LENGTH 1 VALUE 'K', "workbench request + wb_repair TYPE c LENGTH 1 VALUE 'R', "workbench repair + wb_task TYPE c LENGTH 1 VALUE 'S', "workbench task + cust_request TYPE c LENGTH 1 VALUE 'W', "customizing request + cust_task TYPE c LENGTH 1 VALUE 'Q', "customizing task + END OF c_transport_type . + CONSTANTS: + BEGIN OF c_transport_category, + workbench TYPE c LENGTH 4 VALUE 'SYST', + customizing TYPE c LENGTH 4 VALUE 'CUST', + END OF c_transport_category . + CONSTANTS: + BEGIN OF c_transport_mode, + insert TYPE c LENGTH 1 VALUE 'I', + delete TYPE c LENGTH 1 VALUE 'D', + END OF c_transport_mode . + CONSTANTS: + BEGIN OF c_transport_status, + modifiable TYPE c LENGTH 1 VALUE 'D', + END OF c_transport_status . + + METHODS confirm_transport_messages + RETURNING + VALUE(rv_messages_confirmed) TYPE abap_bool . + + METHODS create_transport_entries + IMPORTING + !iv_transport TYPE trkorr + !it_table_ins TYPE ANY TABLE OPTIONAL + !it_table_upd TYPE ANY TABLE OPTIONAL + !it_table_del TYPE ANY TABLE OPTIONAL + !iv_tabname TYPE tabname + RAISING + zcx_abapgit_exception . + + METHODS get_r3tr_obj_for_limu_obj + IMPORTING + !iv_object TYPE tadir-object + !iv_obj_name TYPE trobj_name + EXPORTING + !ev_object TYPE tadir-object + !ev_obj_name TYPE trobj_name + RAISING + zcx_abapgit_exception . + + METHODS get_transports_for_list + IMPORTING + !it_items TYPE zif_abapgit_definitions=>ty_items_tt + RETURNING + VALUE(rt_transports) TYPE ty_transport_list + RAISING + zcx_abapgit_exception . + + "! Returns the transport request / task the object is currently in + "! @parameter is_item | Object + "! @parameter rv_transport | Transport request / task + "! @raising zcx_abapgit_exception | Object is not in a transport + METHODS get_transport_for_object + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RETURNING + VALUE(rv_transport) TYPE trkorr + RAISING + zcx_abapgit_exception . + + METHODS insert_transport_object + IMPORTING + !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object TYPE tadir-object + !iv_obj_name TYPE csequence + !iv_package TYPE devclass + !iv_transport TYPE trkorr OPTIONAL + !iv_language TYPE sy-langu DEFAULT sy-langu + !iv_mode TYPE c DEFAULT 'I' + EXPORTING + !ev_object TYPE tadir-object + !ev_obj_name TYPE trobj_name + RAISING + zcx_abapgit_exception . + + "! Check if change recording is possible for the given package + "! @parameter iv_package | Package + "! @parameter rv_possible | Change recording is possible + "! @raising zcx_abapgit_exception | Package could not be loaded + METHODS is_chrec_possible_for_package + IMPORTING + !iv_package TYPE devclass + RETURNING + VALUE(rv_possible) TYPE abap_bool + RAISING + zcx_abapgit_exception . + + TYPES ty_user_range TYPE RANGE OF sy-uname. + TYPES ty_date_range TYPE RANGE OF sy-datum. + + METHODS list_open_requests + IMPORTING + !it_user TYPE ty_user_range OPTIONAL + !it_date TYPE ty_date_range OPTIONAL + RETURNING + VALUE(rt_trkorr) TYPE ty_trkorr_tt + RAISING + zcx_abapgit_exception . + + METHODS list_r3tr_by_request + IMPORTING + !iv_request TYPE trkorr + RETURNING + VALUE(rt_list) TYPE ty_transport_obj_tt + RAISING + zcx_abapgit_exception . + + METHODS read + IMPORTING + !iv_trkorr TYPE trkorr + RETURNING + VALUE(rs_request) TYPE ty_transport_data + RAISING + zcx_abapgit_exception . + + METHODS read_description + IMPORTING + !iv_trkorr TYPE trkorr + RETURNING + VALUE(rv_description) TYPE string . + + METHODS read_user + IMPORTING + !iv_trkorr TYPE trkorr + RETURNING + VALUE(rv_uname) TYPE uname . + + METHODS validate_transport_request + IMPORTING + !iv_transport_request TYPE trkorr + RAISING + zcx_abapgit_exception . + + METHODS change_transport_type + IMPORTING + !iv_transport_request TYPE trkorr + !iv_transport_type_from TYPE trfunction + !iv_transport_type_to TYPE trfunction + RAISING + zcx_abapgit_exception. +ENDINTERFACE. + +INTERFACE zif_abapgit_data_deserializer . + TYPES: BEGIN OF ty_result, + type TYPE zif_abapgit_data_config=>ty_config-type, + name TYPE zif_abapgit_data_config=>ty_config-name, + deletes TYPE REF TO data, + updates TYPE REF TO data, + inserts TYPE REF TO data, + file TYPE zif_abapgit_git_definitions=>ty_file_signature, + config TYPE zif_abapgit_git_definitions=>ty_file_signature, + in_repo TYPE abap_bool, + END OF ty_result. + TYPES: ty_results TYPE STANDARD TABLE OF ty_result WITH KEY type name. + + METHODS deserialize_check + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !ii_config TYPE REF TO zif_abapgit_data_config + RETURNING + VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks-customizing + RAISING + zcx_abapgit_exception . + + METHODS deserialize + IMPORTING + !iv_package TYPE devclass + !ii_config TYPE REF TO zif_abapgit_data_config + !it_files TYPE zif_abapgit_git_definitions=>ty_files_tt + RETURNING + VALUE(rt_result) TYPE ty_results + RAISING + zcx_abapgit_exception . + + METHODS actualize + IMPORTING + !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks + !it_result TYPE ty_results + RETURNING + VALUE(rt_accessed_files) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RAISING + zcx_abapgit_exception . +ENDINTERFACE. + +INTERFACE zif_abapgit_diff. + +* assumes data is UTF8 based with newlines + METHODS create + IMPORTING + !iv_new TYPE xstring + !iv_old TYPE xstring + !iv_ignore_indentation TYPE abap_bool DEFAULT abap_false + !iv_ignore_comments TYPE abap_bool DEFAULT abap_false + !iv_ignore_case TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_diff) TYPE REF TO zif_abapgit_diff + RAISING + zcx_abapgit_exception. + + METHODS get + RETURNING + VALUE(rt_diff) TYPE zif_abapgit_definitions=>ty_diffs_tt. + + METHODS stats + RETURNING + VALUE(rs_count) TYPE zif_abapgit_definitions=>ty_count. + + METHODS set_patch_new + IMPORTING + !iv_line_new TYPE i + !iv_patch_flag TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS set_patch_old + IMPORTING + !iv_line_old TYPE i + !iv_patch_flag TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS get_beacons + RETURNING + VALUE(rt_beacons) TYPE zif_abapgit_definitions=>ty_string_tt. + + METHODS is_line_patched + IMPORTING + iv_index TYPE i + RETURNING + VALUE(rv_patched) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS set_patch_by_old_diff + IMPORTING + is_diff_old TYPE zif_abapgit_definitions=>ty_diff + iv_patch_flag TYPE abap_bool. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gitv2_porcelain . + + METHODS list_branches + IMPORTING + !iv_url TYPE string + !iv_prefix TYPE string OPTIONAL + RETURNING + VALUE(ro_list) TYPE REF TO zif_abapgit_git_branch_list + RAISING + zcx_abapgit_exception . + + METHODS list_no_blobs + IMPORTING + !iv_url TYPE string + !iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1 + RETURNING + VALUE(rt_expanded) TYPE zif_abapgit_git_definitions=>ty_expanded_tt + RAISING + zcx_abapgit_exception . + + METHODS list_no_blobs_multi + IMPORTING + !iv_url TYPE string + !it_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt + RETURNING + VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception . + + METHODS commits_last_year + IMPORTING + !iv_url TYPE string + !it_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt + RETURNING + VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception . + + METHODS fetch_blob + IMPORTING + !iv_url TYPE string + !iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1 + RETURNING + VALUE(rv_blob) TYPE xstring + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_tadir . + METHODS get_object_package + IMPORTING + !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object TYPE tadir-object + !iv_obj_name TYPE tadir-obj_name + RETURNING + VALUE(rv_devclass) TYPE tadir-devclass + RAISING + zcx_abapgit_exception . + + METHODS read + IMPORTING + !iv_package TYPE tadir-devclass + !iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false + !iv_only_local_objects TYPE abap_bool DEFAULT abap_false + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit OPTIONAL + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + !it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt OPTIONAL + !iv_check_exists TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + + METHODS read_single + IMPORTING + !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object TYPE tadir-object + !iv_obj_name TYPE tadir-obj_name + RETURNING + VALUE(rs_tadir) TYPE zif_abapgit_definitions=>ty_tadir. + + METHODS insert_single + IMPORTING + !iv_pgmid TYPE csequence DEFAULT 'R3TR' + !iv_object TYPE csequence + !iv_obj_name TYPE csequence + !iv_package TYPE csequence OPTIONAL + !iv_language TYPE tadir-masterlang OPTIONAL + !iv_srcsystem TYPE tadir-srcsystem OPTIONAL + !iv_set_genflag TYPE abap_bool DEFAULT abap_false + !iv_set_edtflag TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception. + + METHODS delete_single + IMPORTING + !iv_pgmid TYPE csequence DEFAULT 'R3TR' + !iv_object TYPE csequence + !iv_obj_name TYPE csequence + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_oo_object_fnc. + + CONSTANTS: + BEGIN OF c_parts, + locals_def TYPE string VALUE 'locals_def', + locals_imp TYPE string VALUE 'locals_imp', + macros TYPE string VALUE 'macros', + testclasses TYPE string VALUE 'testclasses', + END OF c_parts. + + TYPES: BEGIN OF ty_includes, + programm TYPE syrepid, + END OF ty_includes, + ty_includes_tt TYPE STANDARD TABLE OF ty_includes WITH DEFAULT KEY. + + TYPES: + ty_seoclasstx_tt TYPE STANDARD TABLE OF seoclasstx WITH DEFAULT KEY . + TYPES: + ty_seocompotx_tt TYPE STANDARD TABLE OF seocompotx WITH DEFAULT KEY . + TYPES: + ty_seosubcotx_tt TYPE STANDARD TABLE OF seosubcotx WITH DEFAULT KEY . + + TYPES: + BEGIN OF ty_obj_attribute, + cmpname TYPE seocmpname, + attkeyfld TYPE seokeyfld, + attbusobj TYPE seobusobj, + exposure TYPE seoexpose, + END OF ty_obj_attribute . + TYPES: + ty_obj_attribute_tt TYPE STANDARD TABLE OF ty_obj_attribute WITH DEFAULT KEY + WITH NON-UNIQUE SORTED KEY cmpname COMPONENTS cmpname . + + METHODS: + create + IMPORTING + iv_check TYPE abap_bool + iv_package TYPE devclass + it_attributes TYPE ty_obj_attribute_tt OPTIONAL + CHANGING + cg_properties TYPE any + RAISING + zcx_abapgit_exception, + generate_locals + IMPORTING + is_key TYPE seoclskey + it_local_definitions TYPE seop_source_string OPTIONAL + it_local_implementations TYPE seop_source_string OPTIONAL + it_local_macros TYPE seop_source_string OPTIONAL + it_local_test_classes TYPE seop_source_string OPTIONAL + iv_package TYPE devclass + iv_version TYPE uccheck + RAISING + zcx_abapgit_exception, + deserialize_source + IMPORTING + is_key TYPE seoclskey + it_source TYPE zif_abapgit_definitions=>ty_string_tt + iv_package TYPE devclass + iv_version TYPE uccheck + RAISING + zcx_abapgit_exception + cx_sy_dyn_call_error, + insert_text_pool + IMPORTING + iv_class_name TYPE seoclsname + it_text_pool TYPE textpool_table + iv_language TYPE spras + iv_state TYPE c DEFAULT 'I' + RAISING + zcx_abapgit_exception, + update_descriptions_class + IMPORTING + is_key TYPE seoclskey + iv_language TYPE spras + it_descriptions TYPE ty_seoclasstx_tt, + update_descriptions_compo + IMPORTING + is_key TYPE seoclskey + it_descriptions TYPE ty_seocompotx_tt, + update_descriptions_subco + IMPORTING + is_key TYPE seoclskey + it_descriptions TYPE ty_seosubcotx_tt, + add_to_activation_list + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + RAISING + zcx_abapgit_exception, + create_sotr + IMPORTING + iv_object_name TYPE sobj_name + iv_package TYPE devclass + ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception, + create_documentation + IMPORTING + it_lines TYPE tlinetab + iv_id TYPE dokhl-id + iv_object_name TYPE dokhl-object + iv_language TYPE spras + iv_no_masterlang TYPE abap_bool OPTIONAL + RAISING + zcx_abapgit_exception, + delete_documentation + IMPORTING + iv_id TYPE dokhl-id + iv_object_name TYPE dokhl-object + iv_language TYPE spras + RAISING + zcx_abapgit_exception, + get_includes + IMPORTING + iv_object_name TYPE sobj_name + RETURNING + VALUE(rt_includes) TYPE ty_includes_tt + RAISING + zcx_abapgit_exception, + exists + IMPORTING + iv_object_name TYPE seoclsname + RETURNING + VALUE(rv_exists) TYPE abap_bool, + serialize_abap + IMPORTING + is_class_key TYPE seoclskey + iv_type TYPE seop_include_ext_app OPTIONAL + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt + RAISING + zcx_abapgit_exception + cx_sy_dyn_call_error, + get_skip_test_classes + RETURNING + VALUE(rv_skip) TYPE abap_bool, + get_class_properties + IMPORTING + is_class_key TYPE seoclskey + RETURNING + VALUE(rs_class_properties) TYPE vseoclass + RAISING + zcx_abapgit_exception, + get_interface_properties + IMPORTING + is_interface_key TYPE seoclskey + RETURNING + VALUE(rs_interface_properties) TYPE vseointerf + RAISING + zcx_abapgit_exception, + read_text_pool + IMPORTING + iv_class_name TYPE seoclsname + iv_language TYPE spras + RETURNING + VALUE(rt_text_pool) TYPE textpool_table, + read_documentation + IMPORTING + iv_id TYPE dokhl-id + iv_object_name TYPE dokhl-object + iv_language TYPE spras + RETURNING + VALUE(rt_lines) TYPE tlinetab, + read_sotr + IMPORTING + iv_object_name TYPE sobj_name + ii_xml TYPE REF TO zif_abapgit_xml_output + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params + RAISING + zcx_abapgit_exception, + read_descriptions_class + IMPORTING + iv_object_name TYPE seoclsname + iv_language TYPE spras OPTIONAL + RETURNING + VALUE(rt_descriptions) TYPE ty_seoclasstx_tt, + read_descriptions_compo + IMPORTING + iv_object_name TYPE seoclsname + iv_language TYPE spras OPTIONAL + RETURNING + VALUE(rt_descriptions) TYPE ty_seocompotx_tt, + read_descriptions_subco + IMPORTING + iv_object_name TYPE seoclsname + iv_language TYPE spras OPTIONAL + RETURNING + VALUE(rt_descriptions) TYPE ty_seosubcotx_tt, + delete + IMPORTING + is_deletion_key TYPE seoclskey + RAISING + zcx_abapgit_exception, + read_superclass + IMPORTING + iv_classname TYPE seoclsname + RETURNING + VALUE(rv_superclass) TYPE seoclsname, + read_attributes + IMPORTING + iv_object_name TYPE seoclsname + RETURNING + VALUE(rt_attributes) TYPE ty_obj_attribute_tt, + syntax_check + IMPORTING + iv_object_name TYPE seoclsname + RAISING + zcx_abapgit_exception. +ENDINTERFACE. + +INTERFACE zif_abapgit_sap_namespace . + + METHODS exists + IMPORTING + iv_namespace TYPE trnspace-namespace + RETURNING + VALUE(rv_yes) TYPE abap_bool. + + METHODS is_editable + IMPORTING + iv_namespace TYPE trnspace-namespace + RETURNING + VALUE(rv_yes) TYPE abap_bool. + + METHODS split_by_name + IMPORTING + iv_obj_with_namespace TYPE csequence + iv_allow_slash_in_name TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rs_obj_namespace) TYPE zif_abapgit_definitions=>ty_obj_namespace + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_sap_package . + TYPES: + ty_devclass_tt TYPE STANDARD TABLE OF devclass WITH DEFAULT KEY . + + TYPES: BEGIN OF ty_create, + devclass TYPE devclass, + dlvunit TYPE tdevc-dlvunit, + component TYPE c LENGTH 20, + ctext TYPE c LENGTH 60, + parentcl TYPE devclass, + pdevclass TYPE c LENGTH 4, + as4user TYPE usnam, + END OF ty_create. + + METHODS get + RETURNING + VALUE(rs_package) TYPE ty_create + RAISING + zcx_abapgit_exception . + METHODS validate_name + RAISING + zcx_abapgit_exception . + METHODS create + IMPORTING + !is_package TYPE ty_create + RAISING + zcx_abapgit_exception . + METHODS create_local + RAISING + zcx_abapgit_exception . + METHODS list_subpackages + RETURNING + VALUE(rt_list) TYPE ty_devclass_tt . + METHODS list_superpackages + RETURNING + VALUE(rt_list) TYPE ty_devclass_tt + RAISING + zcx_abapgit_exception . + METHODS read_parent + RETURNING + VALUE(rv_parentcl) TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS read_description + RETURNING + VALUE(rv_description) TYPE string. + METHODS read_responsible + RETURNING + VALUE(rv_responsible) TYPE usnam. + METHODS create_child + IMPORTING + !iv_child TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS exists + RETURNING + VALUE(rv_bool) TYPE abap_bool . + METHODS are_changes_recorded_in_tr_req + RETURNING + VALUE(rv_are_changes_rec_in_tr_req) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS get_transport_type + RETURNING + VALUE(rs_transport_type) TYPE zif_abapgit_definitions=>ty_transport_type + RAISING + zcx_abapgit_exception . + METHODS get_default_transport_layer + RETURNING + VALUE(rv_transport_layer) TYPE devlayer + RAISING + zcx_abapgit_exception. + METHODS check_object_type + IMPORTING + iv_obj_type TYPE tadir-object + RAISING + zcx_abapgit_exception. +ENDINTERFACE. + +INTERFACE zif_abapgit_sap_report. + + TYPES: + BEGIN OF ty_progdir, + name TYPE progdir-name, + state TYPE progdir-state, + sqlx TYPE progdir-sqlx, + edtx TYPE progdir-edtx, + varcl TYPE progdir-varcl, + dbapl TYPE progdir-dbapl, + dbna TYPE progdir-dbna, + clas TYPE progdir-clas, + type TYPE progdir-type, + occurs TYPE progdir-occurs, + subc TYPE progdir-subc, + appl TYPE progdir-appl, + secu TYPE progdir-secu, + cnam TYPE progdir-cnam, + cdat TYPE progdir-cdat, + unam TYPE progdir-unam, + udat TYPE progdir-udat, + vern TYPE progdir-vern, + levl TYPE progdir-levl, + rstat TYPE progdir-rstat, + rmand TYPE progdir-rmand, + rload TYPE progdir-rload, + fixpt TYPE progdir-fixpt, + sset TYPE progdir-sset, + sdate TYPE progdir-sdate, + stime TYPE progdir-stime, + idate TYPE progdir-idate, + itime TYPE progdir-itime, + ldbname TYPE progdir-ldbname, + uccheck TYPE progdir-uccheck, + END OF ty_progdir. + + METHODS read_report + IMPORTING + iv_name TYPE syrepid + iv_state TYPE r3state OPTIONAL + is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL + RETURNING + VALUE(rt_source) TYPE abaptxt255_tab + RAISING + zcx_abapgit_exception. + + METHODS insert_report + IMPORTING + iv_name TYPE syrepid + it_source TYPE STANDARD TABLE + iv_state TYPE r3state OPTIONAL + iv_program_type TYPE c OPTIONAL + iv_extension_type TYPE c OPTIONAL + iv_package TYPE devclass + iv_version TYPE uccheck + is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL + RAISING + zcx_abapgit_exception. + + METHODS update_report + IMPORTING + iv_name TYPE syrepid + it_source TYPE STANDARD TABLE + iv_state TYPE r3state OPTIONAL + iv_program_type TYPE c OPTIONAL + iv_extension_type TYPE c OPTIONAL + iv_package TYPE devclass + iv_version TYPE uccheck + is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL + RETURNING + VALUE(rv_updated) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS delete_report + IMPORTING + iv_name TYPE syrepid + iv_raise_error TYPE abap_bool DEFAULT abap_false + is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL + RAISING + zcx_abapgit_exception. + + METHODS read_progdir + IMPORTING + iv_name TYPE syrepid + iv_state TYPE r3state DEFAULT 'A' + RETURNING + VALUE(rs_progdir) TYPE ty_progdir + RAISING + zcx_abapgit_exception. + + METHODS update_progdir + IMPORTING + is_progdir TYPE ty_progdir + iv_package TYPE devclass + iv_state TYPE r3state DEFAULT 'I' + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_longtexts . + + TYPES: + BEGIN OF ty_longtext, + dokil TYPE dokil, + head TYPE thead, + lines TYPE tline_tab, + END OF ty_longtext . + TYPES: + ty_longtexts TYPE STANDARD TABLE OF ty_longtext WITH NON-UNIQUE DEFAULT KEY . + + METHODS changed_by + IMPORTING + !iv_object_name TYPE tadir-obj_name + !iv_longtext_id TYPE dokil-id + !it_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt OPTIONAL + RETURNING + VALUE(rv_user) TYPE syuname + RAISING + zcx_abapgit_exception . + METHODS serialize + IMPORTING + !iv_longtext_name TYPE string DEFAULT 'LONGTEXTS' + !iv_object_name TYPE clike + !iv_longtext_id TYPE dokil-id + !it_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt OPTIONAL + !ii_xml TYPE REF TO zif_abapgit_xml_output + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params + RETURNING + VALUE(rt_longtexts) TYPE ty_longtexts + RAISING + zcx_abapgit_exception . + METHODS deserialize + IMPORTING + !iv_longtext_name TYPE string DEFAULT 'LONGTEXTS' + !iv_object_name TYPE clike + !iv_longtext_id TYPE dokil-id + !ii_xml TYPE REF TO zif_abapgit_xml_input + !iv_main_language TYPE sy-langu + RAISING + zcx_abapgit_exception . + METHODS delete + IMPORTING + !iv_object_name TYPE tadir-obj_name + !iv_longtext_id TYPE dokil-id + RAISING + zcx_abapgit_exception . +ENDINTERFACE. + +INTERFACE zif_abapgit_object_tabl. + CONSTANTS: BEGIN OF c_s_dataname, + segment_definition TYPE string VALUE 'SEGMENT_DEFINITION', + tabl_extras TYPE string VALUE 'TABL_EXTRAS', + END OF c_s_dataname. + + TYPES: BEGIN OF ty_dd02_text, + ddlanguage TYPE dd02t-ddlanguage, + ddtext TYPE dd02t-ddtext, + END OF ty_dd02_text. + + TYPES ty_dd02_texts TYPE STANDARD TABLE OF ty_dd02_text WITH DEFAULT KEY. + + TYPES ty_dd03p_tt TYPE STANDARD TABLE OF dd03p WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_segment_definition, + segmentheader TYPE edisegmhd, + segmentdefinition TYPE edisegmdef, + segmentstructures TYPE STANDARD TABLE OF edisegstru WITH DEFAULT KEY, + END OF ty_segment_definition. + + TYPES: ty_segment_definitions TYPE STANDARD TABLE OF ty_segment_definition WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_tabl_extras, + tddat TYPE tddat, + abap_language_version TYPE uccheck, + END OF ty_tabl_extras. + + TYPES: BEGIN OF ty_internal, + dd02v TYPE dd02v, + dd09l TYPE dd09l, + dd03p TYPE ty_dd03p_tt, + dd05m TYPE STANDARD TABLE OF dd05m WITH DEFAULT KEY, + dd08v TYPE STANDARD TABLE OF dd08v WITH DEFAULT KEY, + dd12v TYPE STANDARD TABLE OF dd12v WITH DEFAULT KEY, + dd17v TYPE STANDARD TABLE OF dd17v WITH DEFAULT KEY, + dd35v TYPE STANDARD TABLE OF dd35v WITH DEFAULT KEY, + dd36m TYPE STANDARD TABLE OF dd36m WITH DEFAULT KEY, + dd02_texts TYPE ty_dd02_texts, + i18n_langs TYPE STANDARD TABLE OF langu WITH DEFAULT KEY, + longtexts TYPE zif_abapgit_longtexts=>ty_longtexts, + segment_definitions TYPE ty_segment_definitions, + extras TYPE ty_tabl_extras, + END OF ty_internal. + +ENDINTERFACE. + +INTERFACE zif_abapgit_objects. + + TYPES: + BEGIN OF ty_serialization, + files TYPE zif_abapgit_git_definitions=>ty_files_tt, + item TYPE zif_abapgit_definitions=>ty_item, + END OF ty_serialization . + TYPES: + BEGIN OF ty_deserialization, + obj TYPE REF TO zif_abapgit_object, + xml TYPE REF TO zif_abapgit_xml_input, + package TYPE devclass, + item TYPE zif_abapgit_definitions=>ty_item, + files TYPE REF TO zcl_abapgit_objects_files, + END OF ty_deserialization . + TYPES: + ty_deserialization_tt TYPE STANDARD TABLE OF ty_deserialization WITH DEFAULT KEY . + TYPES: + ty_types_tt TYPE SORTED TABLE OF tadir-object WITH UNIQUE KEY table_line. + TYPES: + ty_deserialization_step TYPE string. + TYPES: + ty_deserialization_step_tt TYPE STANDARD TABLE OF ty_deserialization_step WITH DEFAULT KEY. + TYPES: + BEGIN OF ty_step_data, + step_id TYPE ty_deserialization_step, + order TYPE i, + descr TYPE string, + syntax_check TYPE abap_bool, + objects TYPE ty_deserialization_tt, + END OF ty_step_data . + TYPES: + ty_step_data_tt TYPE STANDARD TABLE OF ty_step_data + WITH DEFAULT KEY . + + CONSTANTS: + BEGIN OF c_deserialize_action, + " also used to determine priority if object has multiple changes, so don't change order + no_support TYPE i VALUE -1, + none TYPE i VALUE 0, + add TYPE i VALUE 1, + update TYPE i VALUE 2, + overwrite TYPE i VALUE 3, + delete TYPE i VALUE 4, + delete_add TYPE i VALUE 5, + packmove TYPE i VALUE 6, + data_loss TYPE i VALUE 7, + END OF c_deserialize_action. + +ENDINTERFACE. + +INTERFACE zif_abapgit_object. + + CONSTANTS: + BEGIN OF gc_step_id, + early TYPE zif_abapgit_objects=>ty_deserialization_step VALUE 'EARLY', + abap TYPE zif_abapgit_objects=>ty_deserialization_step VALUE 'ABAP', + ddic TYPE zif_abapgit_objects=>ty_deserialization_step VALUE 'DDIC', + late TYPE zif_abapgit_objects=>ty_deserialization_step VALUE 'LATE', + lxe TYPE zif_abapgit_objects=>ty_deserialization_step VALUE 'LXE', + END OF gc_step_id. + + METHODS serialize + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + + METHODS deserialize + IMPORTING + !iv_package TYPE devclass + !io_xml TYPE REF TO zif_abapgit_xml_input + !iv_step TYPE zif_abapgit_objects=>ty_deserialization_step + !ii_log TYPE REF TO zif_abapgit_log + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + + METHODS delete + IMPORTING + !iv_package TYPE devclass + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + + METHODS exists + RETURNING + VALUE(rv_bool) TYPE abap_bool + RAISING + zcx_abapgit_exception . + + METHODS is_locked + RETURNING + VALUE(rv_is_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . + + METHODS is_active + RETURNING + VALUE(rv_active) TYPE abap_bool + RAISING + zcx_abapgit_exception . + + METHODS changed_by + IMPORTING + !iv_extra TYPE string OPTIONAL + RETURNING + VALUE(rv_user) TYPE syuname + RAISING + zcx_abapgit_exception . + + METHODS jump + IMPORTING + !iv_extra TYPE string OPTIONAL + RETURNING + VALUE(rv_exit) TYPE abap_bool + RAISING + zcx_abapgit_exception . + + METHODS get_metadata + RETURNING + VALUE(rs_metadata) TYPE zif_abapgit_definitions=>ty_metadata . + + METHODS get_comparator + RETURNING + VALUE(ri_comparator) TYPE REF TO zif_abapgit_comparator + RAISING + zcx_abapgit_exception . + + METHODS get_deserialize_steps + RETURNING + VALUE(rt_steps) TYPE zif_abapgit_objects=>ty_deserialization_step_tt. + + METHODS get_deserialize_order + IMPORTING + !it_all_objects TYPE zif_abapgit_definitions=>ty_items_tt + RETURNING + VALUE(rt_objects_before) TYPE zif_abapgit_definitions=>ty_items_tt. + + CLASS-METHODS map_filename_to_object + IMPORTING + !iv_item_part_of_filename TYPE string + !iv_path TYPE string OPTIONAL + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit OPTIONAL + !iv_package TYPE devclass OPTIONAL + CHANGING + cs_item TYPE zif_abapgit_definitions=>ty_item + RAISING + zcx_abapgit_exception. + + CLASS-METHODS map_object_to_filename + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_ext TYPE string + !iv_extra TYPE clike + CHANGING + !cv_item_part_of_filename TYPE string + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_object_filter . + + METHODS get_filter + RETURNING + VALUE(rt_filter) TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception. +ENDINTERFACE. + +INTERFACE zif_abapgit_merge . + + TYPES: + BEGIN OF ty_merge, + repo_online TYPE REF TO zif_abapgit_repo_online, + source TYPE zif_abapgit_git_definitions=>ty_git_branch, + target TYPE zif_abapgit_git_definitions=>ty_git_branch, + common TYPE zif_abapgit_definitions=>ty_ancestor, + stree TYPE zif_abapgit_git_definitions=>ty_expanded_tt, + ttree TYPE zif_abapgit_git_definitions=>ty_expanded_tt, + ctree TYPE zif_abapgit_git_definitions=>ty_expanded_tt, + result TYPE zif_abapgit_git_definitions=>ty_expanded_tt, + stage TYPE REF TO zcl_abapgit_stage, + conflict TYPE string, + END OF ty_merge . + TYPES: + BEGIN OF ty_merge_conflict, + path TYPE string, + filename TYPE string, + source_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + source_data TYPE xstring, + target_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + target_data TYPE xstring, + result_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + result_data TYPE xstring, + END OF ty_merge_conflict . + TYPES: + ty_merge_conflict_tt TYPE STANDARD TABLE OF ty_merge_conflict WITH DEFAULT KEY . + + METHODS get_conflicts + RETURNING + VALUE(rt_conflicts) TYPE ty_merge_conflict_tt . + METHODS get_result + RETURNING + VALUE(rs_merge) TYPE ty_merge . + METHODS get_source_branch + RETURNING + VALUE(rv_source_branch) TYPE string . + METHODS has_conflicts + RETURNING + VALUE(rv_conflicts_exists) TYPE abap_bool . + METHODS resolve_conflict + IMPORTING + !is_conflict TYPE ty_merge_conflict + RAISING + zcx_abapgit_exception . + METHODS run + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_stage_logic . + + METHODS get + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo + !ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL + RETURNING + VALUE(rs_files) TYPE zif_abapgit_definitions=>ty_stage_files + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_status_calc. + + METHODS calculate_status + IMPORTING + !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + !it_cur_state TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RETURNING + VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_dot_abapgit. + + TYPES: + BEGIN OF ty_requirement, + component TYPE tdevc-dlvunit, + min_release TYPE saprelease, + min_patch TYPE sappatchlv, + END OF ty_requirement . + TYPES: + ty_requirement_tt TYPE STANDARD TABLE OF ty_requirement WITH DEFAULT KEY . + + TYPES: + BEGIN OF ty_dot_abapgit, + name TYPE string, + master_language TYPE spras, + i18n_languages TYPE zif_abapgit_definitions=>ty_languages, + use_lxe TYPE abap_bool, + without_translation TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + starting_folder TYPE string, + folder_logic TYPE string, + ignore TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + requirements TYPE ty_requirement_tt, + version_constant TYPE string, + abap_language_version TYPE string, + original_system TYPE tadir-srcsystem, + END OF ty_dot_abapgit . + + CONSTANTS: + BEGIN OF c_folder_logic, + prefix TYPE string VALUE 'PREFIX', + full TYPE string VALUE 'FULL', + mixed TYPE string VALUE 'MIXED', + END OF c_folder_logic, + + BEGIN OF c_abap_language_version, + standard TYPE string VALUE 'standard', + key_user TYPE string VALUE 'keyUser', + cloud_development TYPE string VALUE 'cloudDevelopment', + ignore TYPE string VALUE 'ignore', + undefined TYPE string VALUE 'undefined', " any + END OF c_abap_language_version. + +ENDINTERFACE. + +INTERFACE zif_abapgit_persistence. + + TYPES: + ty_type TYPE c LENGTH 12 . + TYPES: + ty_value TYPE c LENGTH 12 . + TYPES: + BEGIN OF ty_content, + type TYPE ty_type, + value TYPE ty_value, + data_str TYPE string, + END OF ty_content . + TYPES: + ty_contents TYPE SORTED TABLE OF ty_content WITH UNIQUE KEY type value . + + TYPES: BEGIN OF ty_local_checksum, + item TYPE zif_abapgit_definitions=>ty_item_signature, + files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt, + END OF ty_local_checksum. + + TYPES: + BEGIN OF ty_local_settings, + display_name TYPE string, + ignore_subpackages TYPE abap_bool, + write_protected TYPE abap_bool, + only_local_objects TYPE abap_bool, + code_inspector_check_variant TYPE sci_chkv, + block_commit TYPE abap_bool, + main_language_only TYPE abap_bool, + suppress_lxe_po_comments TYPE abap_bool, + labels TYPE string, + transport_request TYPE trkorr, + customizing_request TYPE trkorr, + flow TYPE abap_bool, + exclude_remote_paths TYPE string_table, + END OF ty_local_settings. + + TYPES: ty_local_checksum_tt TYPE STANDARD TABLE OF ty_local_checksum WITH DEFAULT KEY. + TYPES: ty_local_checksum_by_item_tt TYPE SORTED TABLE OF ty_local_checksum + WITH NON-UNIQUE KEY item-obj_type item-obj_name. + + TYPES: BEGIN OF ty_repo_xml, + url TYPE string, + branch_name TYPE string, + selected_commit TYPE zif_abapgit_git_definitions=>ty_sha1, + package TYPE devclass, + created_by TYPE syuname, + created_at TYPE timestampl, + deserialized_by TYPE syuname, + deserialized_at TYPE timestampl, + offline TYPE abap_bool, + switched_origin TYPE string, + dot_abapgit TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit, + head_branch TYPE string, " HEAD symref of the repo, master branch + local_settings TYPE ty_local_settings, + END OF ty_repo_xml. + + TYPES: + BEGIN OF ty_repo_meta_mask, + url TYPE abap_bool, + branch_name TYPE abap_bool, + selected_commit TYPE abap_bool, + package TYPE abap_bool, + created_by TYPE abap_bool, + created_at TYPE abap_bool, + deserialized_by TYPE abap_bool, + deserialized_at TYPE abap_bool, + offline TYPE abap_bool, + switched_origin TYPE abap_bool, + dot_abapgit TYPE abap_bool, + head_branch TYPE abap_bool, + local_settings TYPE abap_bool, + END OF ty_repo_meta_mask. + + TYPES: BEGIN OF ty_repo, + key TYPE ty_value. + INCLUDE TYPE ty_repo_xml. + TYPES: END OF ty_repo. + TYPES: ty_repos TYPE STANDARD TABLE OF ty_repo WITH DEFAULT KEY. + TYPES: ty_repo_keys TYPE STANDARD TABLE OF ty_repo-key WITH DEFAULT KEY. + + TYPES: + BEGIN OF ty_remote_settings, + offline TYPE ty_repo-offline, + url TYPE ty_repo-url, + branch TYPE zif_abapgit_git_definitions=>ty_git_branch-name, + tag TYPE zif_abapgit_git_definitions=>ty_git_tag-name, + commit TYPE zif_abapgit_git_definitions=>ty_commit-sha1, + pull_request TYPE string, + head_type TYPE zif_abapgit_git_definitions=>ty_head_type, + switched_origin TYPE ty_repo-switched_origin, + END OF ty_remote_settings. + +ENDINTERFACE. + +INTERFACE zif_abapgit_exit. + + TYPES: + BEGIN OF ty_ci_repo, + name TYPE string, + clone_url TYPE string, + END OF ty_ci_repo. + + TYPES ty_ci_repos TYPE STANDARD TABLE OF ty_ci_repo WITH DEFAULT KEY. + + TYPES ty_object_types TYPE HASHED TABLE OF tadir-object WITH UNIQUE KEY table_line. + + TYPES: + BEGIN OF ty_class_key, + clsname TYPE abap_classname, + END OF ty_class_key. + + METHODS adjust_display_commit_url + IMPORTING + !iv_repo_url TYPE csequence + !iv_repo_name TYPE csequence + !iv_repo_key TYPE csequence + !iv_commit_hash TYPE zif_abapgit_git_definitions=>ty_sha1 + CHANGING + !cv_display_url TYPE csequence + RAISING + zcx_abapgit_exception. + + METHODS adjust_display_filename + IMPORTING + !is_repo_meta TYPE zif_abapgit_persistence=>ty_repo + !iv_filename TYPE string + RETURNING + VALUE(rv_filename) TYPE string. + + METHODS allow_sap_objects + RETURNING + VALUE(rv_allowed) TYPE abap_bool. + + METHODS change_local_host + CHANGING + !ct_hosts TYPE zif_abapgit_definitions=>ty_string_tt. + + METHODS change_max_parallel_processes + IMPORTING + !iv_package TYPE devclass + CHANGING + !cv_max_processes TYPE i. + + METHODS change_proxy_authentication + IMPORTING + !iv_repo_url TYPE csequence + CHANGING + !cv_proxy_authentication TYPE abap_bool. + + METHODS change_proxy_port + IMPORTING + !iv_repo_url TYPE csequence + CHANGING + !cv_proxy_port TYPE string. + + METHODS change_proxy_url + IMPORTING + !iv_repo_url TYPE csequence + CHANGING + !cv_proxy_url TYPE string. + + METHODS change_rfc_server_group + CHANGING + !cv_group TYPE rzlli_apcl. + + METHODS change_supported_data_objects + CHANGING + !ct_objects TYPE zif_abapgit_data_supporter=>ty_objects. + + METHODS change_supported_object_types + CHANGING + !ct_types TYPE ty_object_types. + + METHODS change_tadir + IMPORTING + !iv_package TYPE devclass + !ii_log TYPE REF TO zif_abapgit_log + !is_dot_abapgit TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit + !iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false + !iv_only_local_objects TYPE abap_bool DEFAULT abap_false + CHANGING + !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + + METHODS create_http_client + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(ri_client) TYPE REF TO if_http_client + RAISING + zcx_abapgit_exception. + + METHODS custom_serialize_abap_clif + IMPORTING + !is_class_key TYPE ty_class_key + !it_source TYPE zif_abapgit_definitions=>ty_string_tt OPTIONAL + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt + RAISING + zcx_abapgit_exception. + + METHODS deserialize_postprocess + IMPORTING + !is_step TYPE zif_abapgit_objects=>ty_step_data + !ii_log TYPE REF TO zif_abapgit_log. + + METHODS determine_transport_request + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !iv_transport_type TYPE zif_abapgit_definitions=>ty_transport_type + CHANGING + !cv_transport_request TYPE trkorr. + + METHODS enhance_any_toolbar + IMPORTING + !io_menu TYPE REF TO zcl_abapgit_html_toolbar. + + METHODS enhance_repo_toolbar + IMPORTING + !io_menu TYPE REF TO zcl_abapgit_html_toolbar + !iv_key TYPE zif_abapgit_persistence=>ty_value + !iv_act TYPE string. + + METHODS get_ci_tests + IMPORTING + !iv_object TYPE tadir-object + CHANGING + !ct_ci_repos TYPE ty_ci_repos. + + METHODS get_ssl_id + RETURNING + VALUE(rv_ssl_id) TYPE ssfapplssl. + + METHODS http_client + IMPORTING + !iv_url TYPE string + !ii_client TYPE REF TO if_http_client. + + METHODS on_event + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception. + + METHODS pre_calculate_repo_status + IMPORTING + !is_repo_meta TYPE zif_abapgit_persistence=>ty_repo + CHANGING + !ct_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !ct_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception. + + METHODS serialize_postprocess + IMPORTING + !iv_package TYPE devclass + !ii_log TYPE REF TO zif_abapgit_log + CHANGING + !ct_files TYPE zif_abapgit_definitions=>ty_files_item_tt. + + METHODS validate_before_push + IMPORTING + !is_comment TYPE zif_abapgit_git_definitions=>ty_comment + !io_stage TYPE REF TO zcl_abapgit_stage + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + RAISING + zcx_abapgit_exception. + + METHODS wall_message_list + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html. + + METHODS wall_message_repo + IMPORTING + !is_repo_meta TYPE zif_abapgit_persistence=>ty_repo + !ii_html TYPE REF TO zif_abapgit_html. + + METHODS change_committer_info + IMPORTING + iv_repo_url TYPE csequence + CHANGING + cv_name TYPE csequence + cv_email TYPE csequence. +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_jumper. + + TYPES: + ty_bdcdata_tt TYPE STANDARD TABLE OF bdcdata WITH DEFAULT KEY. + + METHODS jump + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !is_sub_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL + !iv_line_number TYPE i OPTIONAL + !iv_new_window TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rv_exit) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS jump_adt + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_sub_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name + !iv_line_number TYPE i + RETURNING + VALUE(rv_exit) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS jump_batch_input + IMPORTING + !iv_tcode TYPE sy-tcode + !it_bdcdata TYPE ty_bdcdata_tt + !iv_new_window TYPE abap_bool DEFAULT abap_true + RAISING + zcx_abapgit_exception. + + METHODS jump_abapgit + IMPORTING + !iv_language TYPE spras + !iv_key TYPE zif_abapgit_persistence=>ty_value + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_persist_background. + + TYPES: + BEGIN OF ty_xml, + method TYPE string, + username TYPE string, + password TYPE string, + settings TYPE zif_abapgit_background=>ty_settings_tt, + END OF ty_xml. + + TYPES: + BEGIN OF ty_background, + key TYPE zif_abapgit_persistence=>ty_value. + INCLUDE TYPE ty_xml. + TYPES: END OF ty_background. + + TYPES ty_background_keys TYPE STANDARD TABLE OF ty_background WITH DEFAULT KEY. + + METHODS list + RETURNING + VALUE(rt_list) TYPE ty_background_keys + RAISING + zcx_abapgit_exception. + + METHODS get_by_key + IMPORTING + !iv_key TYPE ty_background-key + RETURNING + VALUE(rs_data) TYPE ty_background + RAISING + zcx_abapgit_exception + zcx_abapgit_not_found. + + METHODS modify + IMPORTING + !is_data TYPE ty_background + RAISING + zcx_abapgit_exception. + + METHODS delete + IMPORTING + !iv_key TYPE ty_background-key + RAISING + zcx_abapgit_exception. + + METHODS exists + IMPORTING + !iv_key TYPE ty_background-key + RETURNING + VALUE(rv_yes) TYPE abap_bool + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_persist_repo . + METHODS add + IMPORTING + !iv_url TYPE string OPTIONAL + !iv_branch_name TYPE string OPTIONAL + !iv_branch TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL + !iv_display_name TYPE string OPTIONAL + !iv_package TYPE devclass + !iv_offline TYPE abap_bool DEFAULT abap_false + !is_dot_abapgit TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit + RETURNING + VALUE(rv_key) TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + METHODS delete + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + METHODS exists + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(rv_yes) TYPE abap_bool. + METHODS list + RETURNING + VALUE(rt_repos) TYPE zif_abapgit_persistence=>ty_repos + RAISING + zcx_abapgit_exception . + METHODS list_by_keys + IMPORTING + it_keys TYPE zif_abapgit_persistence=>ty_repo_keys + RETURNING + VALUE(rt_repos) TYPE zif_abapgit_persistence=>ty_repos + RAISING + zcx_abapgit_exception . + METHODS lock + IMPORTING + !iv_mode TYPE enqmode + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + METHODS read + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(rs_repo) TYPE zif_abapgit_persistence=>ty_repo + RAISING + zcx_abapgit_exception + zcx_abapgit_not_found . + METHODS update_metadata + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !is_meta TYPE zif_abapgit_persistence=>ty_repo_xml + !is_change_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask + RAISING + zcx_abapgit_exception . +ENDINTERFACE. + +INTERFACE zif_abapgit_persist_repo_cs . + + METHODS update + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !iv_cs_blob TYPE zif_abapgit_persistence=>ty_content-data_str + RAISING + zcx_abapgit_exception . + METHODS delete + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + METHODS read + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(rv_cs_blob) TYPE zif_abapgit_persistence=>ty_content-data_str + RAISING + zcx_abapgit_exception + zcx_abapgit_not_found . +ENDINTERFACE. + +INTERFACE zif_abapgit_persist_user . + + TYPES ty_favorites TYPE zif_abapgit_persistence=>ty_repo_keys . + + TYPES: + BEGIN OF ty_s_user_settings, + max_lines TYPE i, + adt_jump_enabled TYPE abap_bool, + show_default_repo TYPE abap_bool, + link_hints_enabled TYPE abap_bool, + link_hint_key TYPE c LENGTH 1, + parallel_proc_disabled TYPE abap_bool, + icon_scaling TYPE c LENGTH 1, + ui_theme TYPE string, + hide_sapgui_hint TYPE abap_bool, + activate_wo_popup TYPE abap_bool, + label_colors TYPE string, + default_git_uname TYPE string, + default_git_email TYPE string, + END OF ty_s_user_settings . + TYPES: + BEGIN OF ty_list_settings, + filter TYPE string, + only_favorites TYPE abap_bool, + show_details TYPE abap_bool, + order_by TYPE string, + order_descending TYPE abap_bool, + END OF ty_list_settings. + + TYPES: BEGIN OF ty_flow_settings, + only_my_transports TYPE abap_bool, + hide_full_matches TYPE abap_bool, + hide_matching_files TYPE abap_bool, + hide_conflicts TYPE abap_bool, + END OF ty_flow_settings. + + METHODS get_changes_only + RETURNING + VALUE(rv_changes_only) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS get_default_git_user_email + RETURNING + VALUE(rv_email) TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_default_git_user_name + RETURNING + VALUE(rv_username) TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_diff_unified + RETURNING + VALUE(rv_diff_unified) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS get_favorites + RETURNING + VALUE(rt_favorites) TYPE ty_favorites + RAISING + zcx_abapgit_exception . + METHODS get_hide_files + RETURNING + VALUE(rv_hide) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS get_show_folders + RETURNING + VALUE(rv_folders) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS get_repo_git_user_email + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + RETURNING + VALUE(rv_email) TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_repo_git_user_name + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + RETURNING + VALUE(rv_username) TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_repo_last_change_seen + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + RETURNING + VALUE(rv_version) TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_repo_login + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + RETURNING + VALUE(rv_login) TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_repo_show + RETURNING + VALUE(rv_key) TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + METHODS is_favorite_repo + IMPORTING + !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(rv_yes) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS set_default_git_user_email + IMPORTING + !iv_email TYPE string + RAISING + zcx_abapgit_exception . + METHODS set_default_git_user_name + IMPORTING + !iv_username TYPE string + RAISING + zcx_abapgit_exception . + METHODS set_repo_git_user_email + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + !iv_email TYPE string + RAISING + zcx_abapgit_exception . + METHODS set_repo_git_user_name + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + !iv_username TYPE string + RAISING + zcx_abapgit_exception . + METHODS set_repo_last_change_seen + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + !iv_version TYPE string + RAISING + zcx_abapgit_exception . + METHODS set_repo_login + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + !iv_login TYPE string + RAISING + zcx_abapgit_exception . + METHODS set_repo_show + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + METHODS toggle_changes_only + RETURNING + VALUE(rv_changes_only) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS get_order_by + RETURNING + VALUE(rv_order_by) TYPE string + RAISING + zcx_abapgit_exception. + METHODS set_order_by + IMPORTING + iv_order_by TYPE string + RETURNING + VALUE(rv_order_by) TYPE string + RAISING + zcx_abapgit_exception. + METHODS get_order_descending + RETURNING + VALUE(rv_order_descending) TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS set_order_descending + IMPORTING + iv_order_descending TYPE abap_bool + RETURNING + VALUE(rv_order_descending) TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS get_diff_first + RETURNING + VALUE(rv_diff_first) TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS set_diff_first + IMPORTING + iv_diff_first TYPE abap_bool + RETURNING + VALUE(rv_diff_first) TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS toggle_diff_unified + RETURNING + VALUE(rv_diff_unified) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS toggle_favorite + IMPORTING + !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + METHODS toggle_hide_files + RETURNING + VALUE(rv_hide) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS toggle_show_folders + RETURNING + VALUE(rv_folders) TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS get_settings + RETURNING + VALUE(rs_user_settings) TYPE ty_s_user_settings + RAISING + zcx_abapgit_exception. + METHODS set_settings + IMPORTING + is_user_settings TYPE ty_s_user_settings + RAISING + zcx_abapgit_exception. + METHODS get_list_settings + RETURNING + VALUE(rs_list_settings) TYPE ty_list_settings + RAISING + zcx_abapgit_exception. + METHODS set_list_settings + IMPORTING + is_list_settings TYPE ty_list_settings + RAISING + zcx_abapgit_exception. + METHODS get_flow_settings + RETURNING + VALUE(rs_flow_settings) TYPE ty_flow_settings + RAISING + zcx_abapgit_exception. + METHODS set_flow_settings + IMPORTING + is_flow_settings TYPE ty_flow_settings + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_repo . + + DATA ms_data TYPE zif_abapgit_persistence=>ty_repo READ-ONLY. + + METHODS get_key + RETURNING + VALUE(rv_key) TYPE zif_abapgit_persistence=>ty_value . + METHODS get_name + RETURNING + VALUE(rv_name) TYPE string. + METHODS is_offline + RETURNING + VALUE(rv_offline) TYPE abap_bool . + METHODS get_package + RETURNING + VALUE(rv_package) TYPE zif_abapgit_persistence=>ty_repo-package . + METHODS get_local_settings + RETURNING + VALUE(rs_settings) TYPE zif_abapgit_persistence=>ty_repo-local_settings . + + METHODS get_tadir_objects + RETURNING + VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + + METHODS get_files_local_filtered + IMPORTING + !ii_obj_filter TYPE REF TO zif_abapgit_object_filter + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + RETURNING + VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception . + + METHODS get_files_local + IMPORTING + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + RETURNING + VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception . + + METHODS get_files_remote + IMPORTING + !ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL + !iv_ignore_files TYPE abap_bool DEFAULT abap_false + PREFERRED PARAMETER ii_obj_filter + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + METHODS refresh + IMPORTING + !iv_drop_cache TYPE abap_bool DEFAULT abap_false + !iv_drop_log TYPE abap_bool DEFAULT abap_true + PREFERRED PARAMETER iv_drop_cache + RAISING + zcx_abapgit_exception . + METHODS get_dot_abapgit + RETURNING + VALUE(ro_dot_abapgit) TYPE REF TO zcl_abapgit_dot_abapgit . + METHODS set_dot_abapgit + IMPORTING + !io_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit + RAISING + zcx_abapgit_exception . + METHODS find_remote_dot_abapgit + RETURNING + VALUE(ro_dot) TYPE REF TO zcl_abapgit_dot_abapgit + RAISING + zcx_abapgit_exception . + METHODS deserialize + IMPORTING + !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks + !ii_log TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + METHODS deserialize_checks + RETURNING + VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks + RAISING + zcx_abapgit_exception . + + METHODS checksums + RETURNING + VALUE(ri_checksums) TYPE REF TO zif_abapgit_repo_checksums + RAISING + zcx_abapgit_exception . + + METHODS has_remote_source + RETURNING + VALUE(rv_yes) TYPE abap_bool . + METHODS get_log + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log . + METHODS create_new_log + IMPORTING + iv_title TYPE string OPTIONAL + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log . + METHODS get_dot_apack + RETURNING + VALUE(ro_dot_apack) TYPE REF TO zcl_abapgit_apack_reader + RAISING + zcx_abapgit_exception. + METHODS delete_checks + RETURNING + VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_delete_checks + RAISING + zcx_abapgit_exception . + METHODS set_files_remote + IMPORTING + it_files TYPE zif_abapgit_git_definitions=>ty_files_tt . + METHODS get_unsupported_objects_local + RETURNING + VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_items_tt + RAISING + zcx_abapgit_exception . + METHODS set_local_settings + IMPORTING + is_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings + RAISING + zcx_abapgit_exception . + METHODS switch_repo_type + IMPORTING + iv_offline TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS refresh_local_object + IMPORTING + iv_obj_type TYPE tadir-object + iv_obj_name TYPE tadir-obj_name + RAISING + zcx_abapgit_exception . + METHODS refresh_local_objects + RAISING + zcx_abapgit_exception . + METHODS get_data_config + RETURNING + VALUE(ri_config) TYPE REF TO zif_abapgit_data_config + RAISING + zcx_abapgit_exception . + METHODS bind_listener + IMPORTING + ii_listener TYPE REF TO zif_abapgit_repo_listener . + METHODS remove_ignored_files + CHANGING + ct_files TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + +ENDINTERFACE. + +INTERFACE zif_abapgit_repo_checksums. + + METHODS get + RETURNING + VALUE(rt_checksums) TYPE zif_abapgit_persistence=>ty_local_checksum_tt. + + METHODS get_checksums_per_file + RETURNING + VALUE(rt_checksums) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt . + + METHODS rebuild + RAISING + zcx_abapgit_exception. + + METHODS update + IMPORTING + !it_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_repo_listener . + + METHODS on_meta_change + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !is_meta TYPE zif_abapgit_persistence=>ty_repo_xml + !is_change_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask + RAISING + zcx_abapgit_exception . +ENDINTERFACE. + +INTERFACE zif_abapgit_repo_online. + + INTERFACES zif_abapgit_repo. + + METHODS get_url + RETURNING + VALUE(rv_url) TYPE zif_abapgit_persistence=>ty_repo-url . + METHODS get_selected_branch + RETURNING + VALUE(rv_name) TYPE zif_abapgit_persistence=>ty_repo-branch_name . + METHODS set_url + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + RAISING + zcx_abapgit_exception . + METHODS select_branch + IMPORTING + !iv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name + RAISING + zcx_abapgit_exception . + METHODS get_selected_commit + RETURNING + VALUE(rv_selected_commit) TYPE zif_abapgit_persistence=>ty_repo-selected_commit + RAISING + zcx_abapgit_exception . + METHODS get_current_remote + RETURNING + VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + METHODS select_commit + IMPORTING + !iv_selected_commit TYPE zif_abapgit_persistence=>ty_repo-selected_commit + RAISING + zcx_abapgit_exception . + METHODS switch_origin + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + !iv_branch TYPE zif_abapgit_persistence=>ty_repo-branch_name OPTIONAL + !iv_overwrite TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception . + METHODS get_switched_origin + RETURNING + VALUE(rv_switched_origin) TYPE zif_abapgit_persistence=>ty_repo-switched_origin. + METHODS push + IMPORTING + !is_comment TYPE zif_abapgit_git_definitions=>ty_comment + !io_stage TYPE REF TO zcl_abapgit_stage + RAISING + zcx_abapgit_exception . + METHODS create_branch + IMPORTING + !iv_name TYPE string + !iv_from TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS check_for_valid_branch + RAISING + zcx_abapgit_exception . + + METHODS get_remote_settings + RETURNING + VALUE(rs_settings) TYPE zif_abapgit_persistence=>ty_remote_settings + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_repo_srv . + TYPES: + ty_repo_list TYPE STANDARD TABLE OF REF TO zif_abapgit_repo WITH DEFAULT KEY, + + BEGIN OF ty_label, + label TYPE string, + END OF ty_label, + ty_labels TYPE STANDARD TABLE OF ty_label WITH NON-UNIQUE DEFAULT KEY + WITH NON-UNIQUE SORTED KEY key_label COMPONENTS label. + + METHODS init. + METHODS delete + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + METHODS get + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_value + RETURNING + VALUE(ri_repo) TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + METHODS is_repo_installed + IMPORTING + !iv_url TYPE string + !iv_target_package TYPE devclass OPTIONAL + RETURNING + VALUE(rv_installed) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS list + IMPORTING + !iv_offline TYPE abap_bool DEFAULT abap_undefined + RETURNING + VALUE(rt_list) TYPE ty_repo_list + RAISING + zcx_abapgit_exception . + METHODS list_favorites + IMPORTING + !iv_offline TYPE abap_bool DEFAULT abap_undefined + RETURNING + VALUE(rt_list) TYPE ty_repo_list + RAISING + zcx_abapgit_exception . + METHODS new_offline + IMPORTING + !iv_name TYPE string + !iv_package TYPE devclass + !iv_folder_logic TYPE string DEFAULT zif_abapgit_dot_abapgit=>c_folder_logic-full + !iv_labels TYPE string OPTIONAL + !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false + !iv_main_lang_only TYPE abap_bool DEFAULT abap_false + !iv_abap_lang_vers TYPE string OPTIONAL + RETURNING + VALUE(ri_repo) TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + METHODS new_online + IMPORTING + !iv_url TYPE string + !iv_branch_name TYPE string OPTIONAL + !iv_display_name TYPE string OPTIONAL + !iv_name TYPE string OPTIONAL + !iv_package TYPE devclass + !iv_folder_logic TYPE string DEFAULT zif_abapgit_dot_abapgit=>c_folder_logic-prefix + !iv_labels TYPE string OPTIONAL + !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false + !iv_main_lang_only TYPE abap_bool DEFAULT abap_false + !iv_abap_lang_vers TYPE string OPTIONAL + RETURNING + VALUE(ri_repo) TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + METHODS purge + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !is_checks TYPE zif_abapgit_definitions=>ty_delete_checks + !iv_keep_repo TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + METHODS validate_package + IMPORTING + !iv_package TYPE devclass + !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false + !iv_chk_exists TYPE abap_bool DEFAULT abap_true + RAISING + zcx_abapgit_exception . + METHODS validate_url + IMPORTING + !iv_url TYPE string + !iv_chk_exists TYPE abap_bool DEFAULT abap_true + RAISING + zcx_abapgit_exception . + METHODS get_repo_from_package + IMPORTING + !iv_package TYPE devclass + !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false + EXPORTING + VALUE(ei_repo) TYPE REF TO zif_abapgit_repo + !ev_reason TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_repo_from_url + IMPORTING + !iv_url TYPE string + EXPORTING + !ei_repo TYPE REF TO zif_abapgit_repo + !ev_reason TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_label_list + RETURNING + VALUE(rt_labels) TYPE ty_labels + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_flow_logic . + + TYPES: + BEGIN OF ty_path_name, + path TYPE string, + filename TYPE string, + remote_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + local_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + END OF ty_path_name. + TYPES: + ty_path_name_tt TYPE HASHED TABLE OF ty_path_name WITH UNIQUE KEY path filename. + + TYPES: BEGIN OF ty_branch, + display_name TYPE string, + sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + up_to_date TYPE abap_bool, + first_commit TYPE zif_abapgit_git_definitions=>ty_sha1, + END OF ty_branch. + + TYPES: BEGIN OF ty_feature, + BEGIN OF repo, + name TYPE string, + key TYPE zif_abapgit_persistence=>ty_repo-key, + package TYPE devclass, + END OF repo, + branch TYPE ty_branch, + BEGIN OF pr, + title TYPE string, + url TYPE string, + number TYPE i, + draft TYPE abap_bool, + END OF pr, + BEGIN OF transport, + trkorr TYPE trkorr, + title TYPE string, + END OF transport, + full_match TYPE abap_bool, + changed_files TYPE ty_path_name_tt, + changed_objects TYPE zif_abapgit_definitions=>ty_items_ts, + END OF ty_feature. + TYPES ty_features TYPE STANDARD TABLE OF ty_feature WITH DEFAULT KEY. + + TYPES: ty_transport_duplicates_tt TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_item_signature WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_information, + features TYPE ty_features, + errors TYPE string_table, + transport_duplicates TYPE ty_transport_duplicates_tt, + END OF ty_information. + + CONSTANTS c_main TYPE string VALUE 'main'. + +************************************** + + TYPES: BEGIN OF ty_consolidate, + errors TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + warnings TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + success TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + missing_remote TYPE ty_path_name_tt, + only_remote TYPE ty_path_name_tt, + END OF ty_consolidate. + +ENDINTERFACE. + +INTERFACE zif_abapgit_flow_exit . + + TYPES: BEGIN OF ty_settings, + allow_not_up_to_date TYPE abap_bool, + END OF ty_settings. + + METHODS get_settings + IMPORTING + !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(rs_settings) TYPE ty_settings + RAISING + zcx_abapgit_exception. + + METHODS toolbar_extras + IMPORTING + !io_toolbar TYPE REF TO zcl_abapgit_html_toolbar + !is_feature TYPE zif_abapgit_flow_logic=>ty_feature + !iv_index TYPE i + RAISING + zcx_abapgit_exception. + + METHODS info_extras + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_feature TYPE zif_abapgit_flow_logic=>ty_feature + RAISING + zcx_abapgit_exception. + + TYPES: BEGIN OF ty_event_result, + handled TYPE zif_abapgit_gui_event_handler=>ty_handling_result, + refresh TYPE abap_bool, + END OF ty_event_result. + + METHODS on_event + IMPORTING + ii_event TYPE REF TO zif_abapgit_gui_event + it_features TYPE zif_abapgit_flow_logic=>ty_features + RETURNING + VALUE(rs_result) TYPE ty_event_result + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_gui_diff_extra. +* only diff rendering, not page related stuff + + METHODS insert_nav + RETURNING + VALUE(rv_insert_nav) TYPE abap_bool . + +* this overrides the default + METHODS render_beacon_begin_of_row + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff . + +* this overrides the default + METHODS render_diff_head_after_state + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff . + +* extra rendering before the default + METHODS render_line_split_row + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !iv_filename TYPE string + !is_diff_line TYPE zif_abapgit_definitions=>ty_diff + !iv_index TYPE sy-tabix + !iv_fstate TYPE char1 + !iv_new TYPE string + !iv_old TYPE string + RAISING + zcx_abapgit_exception . + +* extra rendering after the default + METHODS render_table_head_non_unified + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff . + +ENDINTERFACE. + +INTERFACE zif_abapgit_services_git. + + TYPES: + BEGIN OF ty_commit_fields, + repo_key TYPE zif_abapgit_persistence=>ty_repo-key, + committer_name TYPE string, + committer_email TYPE string, + author_name TYPE string, + author_email TYPE string, + comment TYPE string, + body TYPE string, + END OF ty_commit_fields. + +ENDINTERFACE. + +INTERFACE zif_abapgit_popups . + TYPES ty_rows TYPE SORTED TABLE OF i WITH UNIQUE KEY table_line. + + TYPES: + BEGIN OF ty_alv_column, + name TYPE string, + text TYPE string, + length TYPE lvc_outlen, + show_icon TYPE abap_bool, + center TYPE abap_bool, + END OF ty_alv_column, + ty_alv_column_tt TYPE STANDARD TABLE OF ty_alv_column WITH DEFAULT KEY. + + TYPES: + BEGIN OF ty_popup_position, + start_column LIKE sy-cucol, + start_row LIKE sy-curow, + end_column LIKE sy-cucol, + end_row LIKE sy-curow, + END OF ty_popup_position. + + CONSTANTS c_new_branch_label TYPE string VALUE '+ create new ...' ##NO_TEXT. + + METHODS popup_search_help + IMPORTING + !iv_tab_field TYPE string + RETURNING + VALUE(rv_value) TYPE ddshretval-fieldval + RAISING + zcx_abapgit_exception . + METHODS popup_folder_logic + RETURNING + VALUE(rv_folder_logic) TYPE string + RAISING + zcx_abapgit_exception . + METHODS create_branch_popup + IMPORTING + !iv_source_branch_name TYPE string + EXPORTING + !ev_name TYPE string + !ev_cancel TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS branch_list_popup + IMPORTING + !iv_url TYPE string + !iv_default_branch TYPE string OPTIONAL + !iv_show_new_option TYPE abap_bool OPTIONAL + !iv_hide_branch TYPE zif_abapgit_persistence=>ty_repo-branch_name OPTIONAL + !iv_hide_head TYPE abap_bool OPTIONAL + RETURNING + VALUE(rs_branch) TYPE zif_abapgit_git_definitions=>ty_git_branch + RAISING + zcx_abapgit_exception . + METHODS tag_list_popup + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(rs_tag) TYPE zif_abapgit_git_definitions=>ty_git_tag + RAISING + zcx_abapgit_exception . + METHODS commit_list_popup + IMPORTING + !iv_repo_url TYPE string + !iv_branch_name TYPE string OPTIONAL + RETURNING + VALUE(rs_commit) TYPE zif_abapgit_git_definitions=>ty_commit + RAISING + zcx_abapgit_exception . + TYPES ty_char1 TYPE c LENGTH 1. + TYPES ty_icon TYPE c LENGTH 30. + METHODS popup_to_confirm + IMPORTING + !iv_titlebar TYPE clike + !iv_text_question TYPE clike + !iv_text_button_1 TYPE clike DEFAULT 'Yes' + !iv_icon_button_1 TYPE ty_icon DEFAULT space + !iv_text_button_2 TYPE clike DEFAULT 'No' + !iv_icon_button_2 TYPE ty_icon DEFAULT space + !iv_default_button TYPE ty_char1 DEFAULT '1' + !iv_display_cancel_button TYPE ty_char1 DEFAULT abap_true + !iv_popup_type TYPE clike DEFAULT 'ICON_MESSAGE_QUESTION' + RETURNING + VALUE(rv_answer) TYPE ty_char1 + RAISING + zcx_abapgit_exception . + METHODS popup_to_create_transp_branch + IMPORTING + !iv_trkorr TYPE trkorr + RETURNING + VALUE(rs_transport_branch) TYPE zif_abapgit_definitions=>ty_transport_to_branch + RAISING + zcx_abapgit_exception . + METHODS popup_to_select_transport + RETURNING + VALUE(rv_trkorr) TYPE trkorr . + METHODS popup_to_select_from_list + IMPORTING + !it_list TYPE STANDARD TABLE + !iv_title TYPE lvc_title DEFAULT space + !iv_header_text TYPE csequence DEFAULT space + !iv_start_column TYPE i DEFAULT 10 + !iv_end_column TYPE i DEFAULT 125 + !iv_start_line TYPE i DEFAULT 10 + !iv_end_line TYPE i DEFAULT 30 + !iv_striped_pattern TYPE abap_bool DEFAULT abap_false + !iv_optimize_col_width TYPE abap_bool DEFAULT abap_true + !iv_selection_mode TYPE salv_de_constant DEFAULT if_salv_c_selection_mode=>multiple + !iv_select_column_text TYPE csequence DEFAULT space + !it_columns_to_display TYPE ty_alv_column_tt + !it_preselected_rows TYPE ty_rows OPTIONAL + EXPORTING + VALUE(et_list) TYPE STANDARD TABLE + RAISING + zcx_abapgit_exception . + METHODS popup_transport_request + IMPORTING + !is_transport_type TYPE zif_abapgit_definitions=>ty_transport_type OPTIONAL + !iv_use_default_transport TYPE abap_bool DEFAULT abap_false + PREFERRED PARAMETER is_transport_type + RETURNING + VALUE(rv_transport) TYPE trkorr + RAISING + zcx_abapgit_exception . + METHODS popup_select_tr_requests + IMPORTING is_selection TYPE trwbo_selection + iv_title TYPE trwbo_title + iv_username_pattern TYPE any DEFAULT sy-uname + RETURNING VALUE(rt_r_trkorr) TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt + RAISING zcx_abapgit_exception. + METHODS popup_select_wb_tc_tr_and_tsk + RETURNING VALUE(rt_r_trkorr) TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt + RAISING zcx_abapgit_exception. + METHODS popup_to_select_labels + IMPORTING iv_labels TYPE string OPTIONAL + RETURNING VALUE(rv_labels) TYPE string + RAISING zcx_abapgit_exception. + METHODS choose_code_insp_check_variant + RETURNING VALUE(rv_check_variant) TYPE sci_chkv + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +INTERFACE zif_abapgit_log . + + CONSTANTS: + BEGIN OF c_status, + ok TYPE sy-msgty VALUE 'S', + error TYPE sy-msgty VALUE 'E', + warning TYPE sy-msgty VALUE 'W', + END OF c_status. + + CONSTANTS: + BEGIN OF c_log_level, + empty TYPE i VALUE 0, + info TYPE i VALUE 1, + warning TYPE i VALUE 2, + error TYPE i VALUE 3, + END OF c_log_level. + + TYPES: + BEGIN OF ty_log_out, + type TYPE sy-msgty, + id TYPE sy-msgid, + number TYPE sy-msgno, + text TYPE string, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + exception TYPE REF TO cx_root, + END OF ty_log_out . + TYPES: + ty_log_outs TYPE STANDARD TABLE OF ty_log_out + WITH NON-UNIQUE DEFAULT KEY . + TYPES: + BEGIN OF ty_msg, + text TYPE string, + type TYPE sy-msgty, + id TYPE sy-msgid, + number TYPE sy-msgno, + level TYPE i, + END OF ty_msg . + TYPES: + ty_msgs TYPE STANDARD TABLE OF ty_msg + WITH NON-UNIQUE DEFAULT KEY . + TYPES: + BEGIN OF ty_item_status_out, + item TYPE zif_abapgit_definitions=>ty_item, + status TYPE sy-msgty, + messages TYPE ty_msgs, + END OF ty_item_status_out . + TYPES: + ty_item_status_outs TYPE SORTED TABLE OF ty_item_status_out + WITH UNIQUE KEY item-obj_type item-obj_name . + + METHODS add + IMPORTING + !iv_msg TYPE csequence + !iv_type TYPE sy-msgty DEFAULT 'E' + !iv_class TYPE sy-msgid OPTIONAL + !iv_number TYPE sy-msgno OPTIONAL + !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL + !ix_exc TYPE REF TO cx_root OPTIONAL . + METHODS add_error + IMPORTING + !iv_msg TYPE csequence + !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . + METHODS add_info + IMPORTING + !iv_msg TYPE csequence + !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . + METHODS add_warning + IMPORTING + !iv_msg TYPE csequence + !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . + METHODS add_success + IMPORTING + !iv_msg TYPE csequence + !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . + METHODS add_exception + IMPORTING + !ix_exc TYPE REF TO cx_root + !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . + METHODS clear . + METHODS count + RETURNING + VALUE(rv_count) TYPE i . + METHODS get_messages + RETURNING + VALUE(rt_msg) TYPE ty_log_outs . + METHODS get_item_status + RETURNING + VALUE(rt_item_status) TYPE ty_item_status_outs . + METHODS get_status + RETURNING + VALUE(rv_status) TYPE sy-msgty . + METHODS get_log_level + RETURNING + VALUE(rv_level) TYPE i . + METHODS get_title + RETURNING + VALUE(rv_title) TYPE string . + METHODS set_title + IMPORTING + !iv_title TYPE csequence + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log. + METHODS merge_with + IMPORTING + ii_log TYPE REF TO zif_abapgit_log + iv_min_level TYPE i DEFAULT 0 + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log. + METHODS clone + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log. + +ENDINTERFACE. + +INTERFACE zif_abapgit_xml_input . + + METHODS read + IMPORTING + !iv_name TYPE clike + CHANGING + !cg_data TYPE any + RAISING + zcx_abapgit_exception . + METHODS get_raw + RETURNING + VALUE(ri_raw) TYPE REF TO if_ixml_document . + +* todo, add read_xml to match add_xml in lcl_xml_output + METHODS get_metadata + RETURNING + VALUE(rs_metadata) TYPE zif_abapgit_definitions=>ty_metadata . + +ENDINTERFACE. + +INTERFACE zif_abapgit_xml_output . + + METHODS add + IMPORTING + !iv_name TYPE clike + !ig_data TYPE any + RAISING + zcx_abapgit_exception . + METHODS set_raw + IMPORTING + !ii_raw TYPE REF TO if_ixml_element . + METHODS add_xml + IMPORTING + !iv_name TYPE clike + !ii_xml TYPE REF TO if_ixml_element . + METHODS render + IMPORTING + !iv_normalize TYPE abap_bool DEFAULT abap_true + !is_metadata TYPE zif_abapgit_definitions=>ty_metadata OPTIONAL + RETURNING + VALUE(rv_xml) TYPE string . + +ENDINTERFACE. + +INTERFACE zif_abapgit_version . + + CONSTANTS c_xml_version TYPE string VALUE 'v1.0.0' ##NO_TEXT. + CONSTANTS c_abap_version TYPE string VALUE '1.132.0' ##NO_TEXT. + +ENDINTERFACE. + +CLASS zcl_abapgit_apack_helper DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS are_dependencies_met + IMPORTING + !it_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies + RETURNING + VALUE(rv_status) TYPE zif_abapgit_definitions=>ty_yes_no + RAISING + zcx_abapgit_exception . + CLASS-METHODS dependencies_popup + IMPORTING + !it_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies + RAISING + zcx_abapgit_exception . + CLASS-METHODS to_file + IMPORTING + !iv_package TYPE devclass + RETURNING + VALUE(rs_file) TYPE zif_abapgit_git_definitions=>ty_file + RAISING + zcx_abapgit_exception . + + CLASS-METHODS get_manifest_implementations + RETURNING + VALUE(rt_manifest_implementations) TYPE zif_abapgit_apack_definitions=>ty_manifest_declarations. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_dependency_status, + met TYPE zif_abapgit_definitions=>ty_yes_no_partial. + INCLUDE TYPE zif_abapgit_apack_definitions=>ty_dependency. + TYPES: END OF ty_dependency_status . + TYPES: + ty_dependency_statuses TYPE STANDARD TABLE OF ty_dependency_status WITH NON-UNIQUE DEFAULT KEY . + TYPES: + BEGIN OF ty_color_line, + exception(1) TYPE c, + color TYPE lvc_t_scol. + INCLUDE TYPE ty_dependency_status. + TYPES: t_hyperlink TYPE salv_t_int4_column, + END OF ty_color_line. + + TYPES: ty_color_tab TYPE STANDARD TABLE OF ty_color_line WITH DEFAULT KEY. + + CLASS-METHODS get_dependencies_met_status + IMPORTING + !it_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies + RETURNING + VALUE(rt_status) TYPE ty_dependency_statuses + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_installed_packages + RETURNING + VALUE(rt_packages) TYPE zif_abapgit_apack_definitions=>ty_descriptors + RAISING + zcx_abapgit_exception . + CLASS-METHODS show_dependencies_popup + IMPORTING + !it_dependencies TYPE ty_dependency_statuses + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_color_table + IMPORTING + !io_alv TYPE REF TO cl_salv_table + !it_dependencies TYPE ty_dependency_statuses + CHANGING + !ct_color_table TYPE ty_color_tab + RAISING + cx_salv_existing. +ENDCLASS. +CLASS zcl_abapgit_apack_migration DEFINITION + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + CONSTANTS: c_apack_interface_version TYPE i VALUE 1. + CLASS-METHODS: run RAISING zcx_abapgit_exception. + METHODS: perform_migration RAISING zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS interface_exists + RETURNING + VALUE(rv_interface_exists) TYPE abap_bool . + METHODS interface_valid + RETURNING + VALUE(rv_interface_valid) TYPE abap_bool . + METHODS create_interface + RAISING + zcx_abapgit_exception . + METHODS add_interface_source_classic + IMPORTING + !is_clskey TYPE seoclskey + RAISING + zcx_abapgit_exception . + METHODS add_interface_source + IMPORTING + !is_clskey TYPE seoclskey + RAISING + zcx_abapgit_exception . + METHODS get_interface_source + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt . + METHODS add_intf_source_and_activate + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_apack_reader DEFINITION + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + TYPES ty_package_name TYPE devclass . + + CLASS-METHODS create_instance + IMPORTING + !iv_package_name TYPE ty_package_name + RETURNING + VALUE(ro_manifest_reader) TYPE REF TO zcl_abapgit_apack_reader . + CLASS-METHODS deserialize + IMPORTING + !iv_package_name TYPE ty_package_name + !iv_xstr TYPE xstring + RETURNING + VALUE(ro_manifest_reader) TYPE REF TO zcl_abapgit_apack_reader + RAISING + zcx_abapgit_exception. + METHODS get_manifest_descriptor + RETURNING + VALUE(rs_manifest_descriptor) TYPE zif_abapgit_apack_definitions=>ty_descriptor + RAISING + zcx_abapgit_exception. + METHODS set_manifest_descriptor + IMPORTING + !is_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor + RAISING + zcx_abapgit_exception. + METHODS copy_manifest_descriptor + IMPORTING + !io_manifest_provider TYPE REF TO object + RAISING + zcx_abapgit_exception. + METHODS has_manifest + RETURNING + VALUE(rv_has_manifest) TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS constructor + IMPORTING + !iv_package_name TYPE ty_package_name . + METHODS refresh. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_instance, + package TYPE ty_package_name, + instance TYPE REF TO zcl_abapgit_apack_reader, + END OF ty_instance, + ty_instances TYPE HASHED TABLE OF ty_instance WITH UNIQUE KEY package. + + CLASS-DATA gt_instances TYPE ty_instances. + + DATA mv_package_name TYPE ty_package_name . + DATA ms_cached_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor . + DATA mv_is_cached TYPE abap_bool . + + CLASS-METHODS from_xml + IMPORTING + iv_xml TYPE string + RETURNING + VALUE(rs_data) TYPE zif_abapgit_apack_definitions=>ty_descriptor. + + METHODS format_version + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_apack_writer DEFINITION + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + CLASS-METHODS create_instance + IMPORTING + !is_apack_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor + RETURNING + VALUE(ro_manifest_writer) TYPE REF TO zcl_abapgit_apack_writer . + METHODS serialize + RETURNING + VALUE(rv_xml) TYPE string + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !is_apack_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor . + PROTECTED SECTION. + PRIVATE SECTION. + + DATA ms_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor . +ENDCLASS. +CLASS zcl_abapgit_background DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: BEGIN OF ty_method, + class TYPE seoclsname, + description TYPE string, + END OF ty_method. + + TYPES: ty_methods TYPE SORTED TABLE OF ty_method WITH UNIQUE KEY class. + + CLASS-METHODS run + RAISING + zcx_abapgit_exception . + + CLASS-METHODS list_methods + RETURNING VALUE(rt_methods) TYPE ty_methods. + + CLASS-METHODS enqueue + RAISING + zcx_abapgit_exception. + + CLASS-METHODS dequeue. + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS c_enq_type TYPE c LENGTH 12 VALUE 'BACKGROUND'. + CONSTANTS c_interface TYPE seoclskey VALUE 'ZIF_ABAPGIT_BACKGROUND'. +ENDCLASS. +CLASS zcl_abapgit_background_pull DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_background . + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_background_push_au DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_background . + PROTECTED SECTION. + + DATA mi_log TYPE REF TO zif_abapgit_log . + + METHODS build_comment + IMPORTING + !is_files TYPE zif_abapgit_definitions=>ty_stage_files + RETURNING + VALUE(rv_comment) TYPE string . + METHODS push_auto + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + RAISING + zcx_abapgit_exception . + METHODS determine_user_details + IMPORTING + !iv_changed_by TYPE syuname + RETURNING + VALUE(rs_user) TYPE zif_abapgit_git_definitions=>ty_git_user . + METHODS push_deletions + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + !is_files TYPE zif_abapgit_definitions=>ty_stage_files + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_background_push_fi DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_background . + PROTECTED SECTION. + + CONSTANTS: + BEGIN OF c_settings, + name TYPE string VALUE 'NAME', + email TYPE string VALUE 'EMAIL', + END OF c_settings . + DATA mi_log TYPE REF TO zif_abapgit_log . + + METHODS build_comment + IMPORTING + !is_files TYPE zif_abapgit_definitions=>ty_stage_files + RETURNING + VALUE(rv_comment) TYPE string . + METHODS push_fixed + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + !iv_name TYPE string + !iv_email TYPE string + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. +ENDCLASS. +"! Change transport system API +CLASS zcl_abapgit_cts_api DEFINITION + FINAL + CREATE PRIVATE + FRIENDS ZCL_abapgit_factory. + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_cts_api. + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_confirm_transp_msgs_called TYPE abap_bool. + + "! Returns the transport request / task the object is currently locked in + "! @parameter iv_program_id | Program ID + "! @parameter iv_object_type | Object type + "! @parameter iv_object_name | Object name + "! @parameter rv_transport | Transport request / task + "! @raising zcx_abapgit_exception | Object is not locked in a transport + METHODS get_current_transport_for_obj + IMPORTING + !iv_program_id TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object_type TYPE trobjtype + !iv_object_name TYPE sobj_name + RETURNING + VALUE(rv_transport) TYPE trkorr + RAISING + zcx_abapgit_exception . + "! Returns the transport request / task that includes the object (even if not locked) + "! @parameter iv_program_id | Program ID + "! @parameter iv_object_type | Object type + "! @parameter iv_object_name | Object name + "! @parameter rv_transport | Transport request / task + "! @raising zcx_abapgit_exception | Object is not locked in a transport + METHODS get_current_transport_from_db + IMPORTING + !iv_program_id TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object_type TYPE trobjtype + !iv_object_name TYPE sobj_name + RETURNING + VALUE(rv_transport) TYPE trkorr + RAISING + zcx_abapgit_exception . + "! Check if the object is currently locked in a transport + "! @parameter iv_program_id | Program ID + "! @parameter iv_object_type | Object type + "! @parameter iv_object_name | Object name + "! @parameter rv_locked | Object is locked + "! @raising zcx_abapgit_exception | Object type is not lockable + METHODS is_object_locked_in_transport + IMPORTING + !iv_program_id TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object_type TYPE trobjtype + !iv_object_name TYPE sobj_name + RETURNING + VALUE(rv_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . + "! Check if the object type is lockable + "! @parameter iv_program_id | Program ID + "! @parameter iv_object_type | Object type + "! @parameter rv_lockable | Lockable + METHODS is_object_type_lockable + IMPORTING + !iv_program_id TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object_type TYPE trobjtype + RETURNING + VALUE(rv_lockable) TYPE abap_bool . + "! Check if the object type can be transported + "! @parameter iv_program_id | Program ID + "! @parameter iv_object_type | Object type + "! @parameter rv_transportable | Transportable + METHODS is_object_type_transportable + IMPORTING + !iv_program_id TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object_type TYPE trobjtype + RETURNING + VALUE(rv_transportable) TYPE abap_bool . +ENDCLASS. +CLASS zcl_abapgit_default_transport DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES zif_abapgit_default_transport. + + METHODS constructor. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA mv_is_set_by_abapgit TYPE abap_bool . + DATA ms_save TYPE e070use . + + METHODS store. + METHODS restore + RAISING + zcx_abapgit_exception . + METHODS set_internal + IMPORTING + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + METHODS clear + IMPORTING + !is_default_task TYPE e070use + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_transport DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. +* todo, add interfaces for this class, consider merging zcl_abapgit_transport_mass into this class? + CLASS-METHODS zip + IMPORTING + !iv_show_log_popup TYPE abap_bool DEFAULT abap_true + !iv_logic TYPE string OPTIONAL + !is_trkorr TYPE trwbo_request_header OPTIONAL + RETURNING + VALUE(rv_xstr) TYPE xstring + RAISING + zcx_abapgit_exception . + + CLASS-METHODS to_tadir + IMPORTING + !iv_trkorr TYPE trkorr + !iv_deleted_objects TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + + CLASS-METHODS add_all_objects_to_trans_req + IMPORTING + iv_key TYPE zif_abapgit_persistence=>ty_value + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + + TYPES ty_trkorr_tt TYPE STANDARD TABLE OF trkorr. + + CLASS-METHODS read_requests + IMPORTING + !it_trkorr TYPE ty_trkorr_tt + RETURNING + VALUE(rt_requests) TYPE trwbo_requests + RAISING + zcx_abapgit_exception . + CLASS-METHODS find_top_package + IMPORTING + !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RETURNING + VALUE(rv_package) TYPE devclass + RAISING + zcx_abapgit_exception . + CLASS-METHODS resolve + IMPORTING + !it_requests TYPE trwbo_requests + !iv_deleted_objects TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + CLASS-METHODS collect_all_objects + IMPORTING + iv_key TYPE zif_abapgit_persistence=>ty_value + RETURNING + VALUE(rt_objects) TYPE tr_objects + RAISING + zcx_abapgit_exception. + CLASS-METHODS show_log + IMPORTING + it_log TYPE sprot_u_tab + iv_title TYPE string. +ENDCLASS. +CLASS zcl_abapgit_transport_2_branch DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS create + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + !is_transport_to_branch TYPE zif_abapgit_definitions=>ty_transport_to_branch + !it_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + + METHODS generate_commit_message + IMPORTING + !is_transport_to_branch TYPE zif_abapgit_definitions=>ty_transport_to_branch + RETURNING + VALUE(rs_comment) TYPE zif_abapgit_git_definitions=>ty_comment . + METHODS stage_transport_objects + IMPORTING + !it_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt + !io_stage TYPE REF TO zcl_abapgit_stage + !is_stage_objects TYPE zif_abapgit_definitions=>ty_stage_files + !it_object_statuses TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_transport_mass DEFINITION + INHERITING FROM zcl_abapgit_transport + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS run . + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_transport_objects DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !it_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt . + METHODS to_stage + IMPORTING + !io_stage TYPE REF TO zcl_abapgit_stage + !is_stage_objects TYPE zif_abapgit_definitions=>ty_stage_files + !it_object_statuses TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mt_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt . +ENDCLASS. +CLASS zcl_abapgit_data_config DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_data_config . + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mt_config TYPE zif_abapgit_data_config=>ty_config_tt . + + METHODS dump + IMPORTING + !is_config TYPE zif_abapgit_data_config=>ty_config + RETURNING + VALUE(rv_json) TYPE xstring + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_data_deserializer DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_data_factory . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_data_deserializer . + + PROTECTED SECTION. + + PRIVATE SECTION. + + METHODS convert_json_to_itab + IMPORTING + !is_file TYPE zif_abapgit_git_definitions=>ty_file + !ir_data TYPE REF TO data + RAISING + zcx_abapgit_exception . + METHODS preview_database_changes + IMPORTING + !iv_name TYPE tadir-obj_name + !ir_lc_data TYPE REF TO data + !ir_db_data TYPE REF TO data + RETURNING + VALUE(rs_result) TYPE zif_abapgit_data_deserializer=>ty_result + RAISING + zcx_abapgit_exception. + METHODS write_database_table + IMPORTING + !iv_name TYPE tadir-obj_name + !ir_del TYPE REF TO data + !ir_ins TYPE REF TO data + !ir_upd TYPE REF TO data + RAISING + zcx_abapgit_exception . + METHODS read_database_table + IMPORTING + !iv_name TYPE tadir-obj_name + !it_where TYPE string_table + RETURNING + VALUE(rr_data) TYPE REF TO data + RAISING + zcx_abapgit_exception . + METHODS determine_transport_request + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + iv_transport_type TYPE zif_abapgit_definitions=>ty_transport_type + RETURNING + VALUE(rv_transport_request) TYPE trkorr. + + METHODS is_table_allowed_to_edit + IMPORTING + !is_result TYPE zif_abapgit_data_deserializer=>ty_result + RETURNING + VALUE(rv_allowed_to_edit) TYPE abap_bool. + + METHODS is_table_included_in_repo + IMPORTING + !iv_package TYPE devclass + !iv_tabname TYPE tabname + RETURNING + VALUE(rv_is_included) TYPE abap_bool + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_data_factory DEFINITION + CREATE PUBLIC + FRIENDS ZCL_abapgit_data_injector . + + PUBLIC SECTION. + + CLASS-METHODS get_supporter + RETURNING + VALUE(ri_supporter) TYPE REF TO zif_abapgit_data_supporter . + CLASS-METHODS get_serializer + RETURNING + VALUE(ri_serializer) TYPE REF TO zif_abapgit_data_serializer . + CLASS-METHODS get_deserializer + RETURNING + VALUE(ri_deserializer) TYPE REF TO zif_abapgit_data_deserializer . + CLASS-METHODS get_config + RETURNING + VALUE(ri_config) TYPE REF TO zif_abapgit_data_config . + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gi_supporter TYPE REF TO zif_abapgit_data_supporter . + CLASS-DATA gi_serializer TYPE REF TO zif_abapgit_data_serializer . + CLASS-DATA gi_deserializer TYPE REF TO zif_abapgit_data_deserializer . +ENDCLASS. +CLASS zcl_abapgit_data_injector DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS set_supporter + IMPORTING + !ii_supporter TYPE REF TO zif_abapgit_data_supporter . + METHODS set_serializer + IMPORTING + !ii_serializer TYPE REF TO zif_abapgit_data_serializer . + METHODS set_deserializer + IMPORTING + !ii_deserializer TYPE REF TO zif_abapgit_data_deserializer . + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_data_serializer DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_data_factory . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_data_serializer . + + PROTECTED SECTION. + + PRIVATE SECTION. + + CONSTANTS c_max_records TYPE i VALUE 20000 ##NO_TEXT. + + METHODS convert_itab_to_json + IMPORTING + !ir_data TYPE REF TO data + !iv_skip_initial TYPE abap_bool + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_abapgit_exception . + METHODS read_database_table + IMPORTING + !iv_name TYPE tadir-obj_name + !it_where TYPE string_table + RETURNING + VALUE(rr_data) TYPE REF TO data + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_data_supporter DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_data_factory . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_data_supporter. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mt_supported_objects TYPE zif_abapgit_data_supporter=>ty_objects. + + METHODS get_supported_objects. + +ENDCLASS. +CLASS zcl_abapgit_data_utils DEFINITION + CREATE PUBLIC. + + PUBLIC SECTION. + TYPES ty_names TYPE STANDARD TABLE OF abap_compname WITH DEFAULT KEY . + CLASS-METHODS build_table_itab + IMPORTING + !iv_name TYPE tadir-obj_name + RETURNING + VALUE(rr_data) TYPE REF TO data + RAISING + zcx_abapgit_exception. + CLASS-METHODS build_data_filename + IMPORTING + !is_config TYPE zif_abapgit_data_config=>ty_config + RETURNING + VALUE(rv_filename) TYPE string. + CLASS-METHODS build_config_filename + IMPORTING + !is_config TYPE zif_abapgit_data_config=>ty_config + RETURNING + VALUE(rv_filename) TYPE string. + CLASS-METHODS jump + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RAISING + zcx_abapgit_exception. + CLASS-METHODS does_table_exist + IMPORTING + !iv_name TYPE tadir-obj_name + RETURNING + VALUE(rv_exists) TYPE abap_bool. + CLASS-METHODS is_customizing_table + IMPORTING + !iv_name TYPE tadir-obj_name + RETURNING + VALUE(rv_customizing) TYPE abap_bool. + CLASS-METHODS is_application_table + IMPORTING + !iv_name TYPE tadir-obj_name + RETURNING + VALUE(rv_application) TYPE abap_bool. + CLASS-METHODS list_key_fields + IMPORTING + !iv_name TYPE tadir-obj_name + RETURNING + VALUE(rt_names) TYPE ty_names + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES ty_contflag TYPE c LENGTH 1. + + CLASS-METHODS get_table_contflag + IMPORTING + !iv_name TYPE csequence + RETURNING + VALUE(rv_contflag) TYPE ty_contflag. + +ENDCLASS. +CLASS zcl_abapgit_diff3 DEFINITION + FINAL + CREATE PUBLIC. + +************************************************************************ +* ABAP Diff3 +* +* https://github.com/Marc-Bernard-Tools/ABAP-Diff3 +* +* This is a port of JavaScript (https://github.com/bhousel/node-diff3, MIT license) +* https://github.com/bhousel/node-diff3/blob/main/index.mjs as of 2021-09-24 +* +* Copyright 2022 Marc Bernard +* SPDX-License-Identifier: MIT +************************************************************************ + + PUBLIC SECTION. + + CONSTANTS c_version TYPE string VALUE '1.1.0' ##NEEDED. + + INTERFACES zif_abapgit_diff3. + + CLASS-METHODS create + RETURNING + VALUE(ri_result) TYPE REF TO zif_abapgit_diff3. + + CLASS-METHODS convert_to_abap_indices + CHANGING + !ct_diff_indices TYPE zif_abapgit_diff3=>ty_diff_indices_result_t OPTIONAL. + + PROTECTED SECTION. + + TYPES: + ty_ab TYPE c LENGTH 1. + + TYPES: + BEGIN OF ty_hunk, + ab TYPE ty_ab, + o_start TYPE zif_abapgit_diff3=>ty_number, + o_length TYPE zif_abapgit_diff3=>ty_number, + ab_start TYPE zif_abapgit_diff3=>ty_number, + ab_length TYPE zif_abapgit_diff3=>ty_number, + END OF ty_hunk. + TYPES: + ty_hunks TYPE STANDARD TABLE OF ty_hunk WITH DEFAULT KEY. + + METHODS process_common + CHANGING + !ct_common TYPE string_table + !ct_result TYPE zif_abapgit_diff3=>ty_comm_result_t. + + METHODS chunk_description + IMPORTING + !it_buffer TYPE string_table + !iv_offset TYPE zif_abapgit_diff3=>ty_number + !iv_length TYPE zif_abapgit_diff3=>ty_number + RETURNING + VALUE(rs_result) TYPE zif_abapgit_diff3=>ty_chunk. + + METHODS add_hunk + IMPORTING + !it_buffer TYPE zif_abapgit_diff3=>ty_diff_indices_result_t + !iv_ab TYPE ty_ab + CHANGING + !ct_hunks TYPE ty_hunks. + + METHODS advance_to + IMPORTING + !iv_end_offset TYPE zif_abapgit_diff3=>ty_number + !it_o TYPE string_table + CHANGING + !cv_curr_offset TYPE zif_abapgit_diff3=>ty_number + !ct_results TYPE zif_abapgit_diff3=>ty_region_t. + + METHODS flush_ok + CHANGING + !ct_buffer TYPE string_table + !ct_result TYPE zif_abapgit_diff3=>ty_merge_region_t. + + METHODS get_labels + IMPORTING + !is_labels TYPE zif_abapgit_diff3=>ty_labels + RETURNING + VALUE(rs_labels) TYPE zif_abapgit_diff3=>ty_labels. + + PRIVATE SECTION. + + METHODS _reverse + IMPORTING + !it_data TYPE string_table + RETURNING + VALUE(rt_result) TYPE string_table. + + METHODS _slice + IMPORTING + !it_data TYPE string_table + !iv_start TYPE i + !iv_end TYPE i + RETURNING + VALUE(rt_result) TYPE string_table. + +ENDCLASS. +CLASS zcl_abapgit_diff DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_diff_factory . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_diff. + + PROTECTED SECTION. + + PRIVATE SECTION. + + CONSTANTS c_starting_beacon TYPE i VALUE 1. + + TYPES: + ty_regexset_tt TYPE STANDARD TABLE OF REF TO cl_abap_regex WITH KEY table_line. + + DATA mt_beacons TYPE zif_abapgit_definitions=>ty_string_tt. + DATA mt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt. + DATA ms_stats TYPE zif_abapgit_definitions=>ty_count. + + METHODS map_beacons. + METHODS shortlist. + METHODS create_regex_set + RETURNING + VALUE(rt_regex_set) TYPE ty_regexset_tt. + + METHODS calculate_stats. + +ENDCLASS. +CLASS zcl_abapgit_diff_diff3 DEFINITION. + PUBLIC SECTION. + CLASS-METHODS compute + IMPORTING + iv_new TYPE xstring + iv_old TYPE xstring + " todo + " iv_ignore_indentation TYPE abap_bool + " iv_ignore_comments TYPE abap_bool + " iv_ignore_case TYPE abap_bool + RETURNING + VALUE(rt_diff) TYPE zif_abapgit_definitions=>ty_diffs_tt + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_diff_factory DEFINITION. + PUBLIC SECTION. + CLASS-METHODS get + RETURNING + VALUE(ri_diff) TYPE REF TO zif_abapgit_diff. +ENDCLASS. +CLASS zcl_abapgit_diff_std DEFINITION. + PUBLIC SECTION. + CLASS-METHODS compute + IMPORTING + iv_new TYPE xstring + iv_old TYPE xstring + iv_ignore_indentation TYPE abap_bool + iv_ignore_comments TYPE abap_bool + iv_ignore_case TYPE abap_bool + RETURNING + VALUE(rt_diff) TYPE zif_abapgit_definitions=>ty_diffs_tt + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + CLASS-DATA gt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt. + CLASS-DATA gv_compare_mode TYPE c LENGTH 1. + CLASS-DATA gv_ignore_case TYPE abap_bool. + + CLASS-METHODS unpack + IMPORTING + !iv_new TYPE xstring + !iv_old TYPE xstring + EXPORTING + !et_new TYPE rswsourcet + !et_old TYPE rswsourcet + RAISING + zcx_abapgit_exception. + + CLASS-METHODS compute_diff + IMPORTING + !it_new TYPE rswsourcet + !it_old TYPE rswsourcet + RETURNING + VALUE(rt_diff) TYPE zif_abapgit_definitions=>ty_diffs_tt. + + CLASS-METHODS compute_diff_extra + IMPORTING + !it_new TYPE rswsourcet + !it_old TYPE rswsourcet + RETURNING + VALUE(rt_diff) TYPE zif_abapgit_definitions=>ty_diffs_tt. + + CLASS-METHODS adjust_diff. + + CLASS-METHODS has_line_diff + IMPORTING + iv_old TYPE string + iv_new TYPE string + RETURNING + VALUE(rv_has_diff) TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_abap_language_vers DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CONSTANTS: + c_any_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version VALUE '*', + c_no_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version VALUE '-', + c_feature_flag TYPE string VALUE 'ALAV'. + + METHODS constructor + IMPORTING + !io_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit. + + METHODS get_abap_language_vers_by_objt + IMPORTING + !iv_object_type TYPE trobjtype + !iv_package TYPE devclass + RETURNING + VALUE(rv_allowed_abap_langu_version) TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version. + + METHODS get_repo_abap_language_version + RETURNING + VALUE(rv_abap_language_version) TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version. + + METHODS is_import_allowed + IMPORTING + !iv_package TYPE devclass + RETURNING + VALUE(rv_allowed) TYPE abap_bool. + + CLASS-METHODS check_abap_language_version + IMPORTING + !iv_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version + !is_item TYPE zif_abapgit_definitions=>ty_item + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit. + + " Depends on experimental feature flag and repo setting + DATA mv_has_abap_language_vers TYPE abap_bool. + + METHODS get_default_abap_language_vers + IMPORTING + !iv_object_type TYPE trobjtype + RETURNING + VALUE(rv_abap_language_version) TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version. + + METHODS get_abap_language_vers_by_devc + IMPORTING + !iv_package TYPE devclass + RETURNING + VALUE(rv_abap_language_version) TYPE string. + + METHODS get_abap_language_vers_by_repo + RETURNING + VALUE(rv_abap_language_version) TYPE string. + + CLASS-METHODS get_description + IMPORTING + !iv_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version + RETURNING + VALUE(rv_description) TYPE string. + +ENDCLASS. +CLASS zcl_abapgit_env_factory DEFINITION FRIENDS ZCL_abapgit_env_injector. + PUBLIC SECTION. + CLASS-METHODS get_user_record + RETURNING + VALUE(ri_user_record) TYPE REF TO zif_abapgit_user_record. + + PRIVATE SECTION. + CLASS-DATA gi_user_record TYPE REF TO zif_abapgit_user_record. +ENDCLASS. +CLASS zcl_abapgit_env_injector DEFINITION. + PUBLIC SECTION. + CLASS-METHODS set_user_record + IMPORTING + !ii_user_record TYPE REF TO zif_abapgit_user_record. +ENDCLASS. +CLASS zcl_abapgit_environment DEFINITION + FINAL + CREATE PRIVATE + FRIENDS ZCL_abapgit_factory. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_environment. + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_cloud TYPE abap_bool VALUE abap_undefined ##NO_TEXT. + DATA mv_is_merged TYPE abap_bool VALUE abap_undefined ##NO_TEXT. + DATA mv_modifiable TYPE abap_bool VALUE abap_undefined ##NO_TEXT. + + METHODS is_system_changes_allowed + RETURNING + VALUE(rv_result) TYPE abap_bool. +ENDCLASS. +CLASS zcl_abapgit_feature DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + " For dependency injection/testing, use the following + " zcl_abapgit_persist_factory=>get_settings( )->read( )->set_experimental_features( ) + + CLASS-METHODS is_enabled + IMPORTING + !iv_feature TYPE string OPTIONAL + RETURNING + VALUE(rv_run) TYPE abap_bool. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_language DEFINITION + CREATE PUBLIC . + +*----------------------------------------------------------------------* +* This helper class is used to set and restore the current language. +* As some of the SAP functions used rely on SY-LANGU containing the +* main language, this class is used to temporarily change and then +* restore the value of SY-LANGU. +*----------------------------------------------------------------------* + PUBLIC SECTION. + + CLASS-METHODS class_constructor . + CLASS-METHODS restore_login_language . + CLASS-METHODS set_current_language + IMPORTING + !iv_language TYPE sy-langu . + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gv_login_language TYPE sy-langu . +ENDCLASS. +CLASS zcl_abapgit_settings DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CONSTANTS c_commitmsg_comment_length_dft TYPE i VALUE 50 ##NO_TEXT. + CONSTANTS c_commitmsg_body_size_dft TYPE i VALUE 72 ##NO_TEXT. + CONSTANTS: + BEGIN OF c_icon_scaling, + large TYPE c VALUE 'L', + small TYPE c VALUE 'S', + END OF c_icon_scaling . + CONSTANTS: + BEGIN OF c_ui_theme, + default TYPE string VALUE 'default', + dark TYPE string VALUE 'dark', + belize TYPE string VALUE 'belize', + synced_with_gui TYPE string VALUE 'synced_with_gui', + END OF c_ui_theme . + + METHODS set_proxy_url + IMPORTING + !iv_url TYPE string . + METHODS set_proxy_port + IMPORTING + !iv_port TYPE string . + METHODS set_proxy_authentication + IMPORTING + !iv_auth TYPE abap_bool . + METHODS set_proxy_bypass + IMPORTING + !it_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url OPTIONAL . + METHODS get_proxy_url + RETURNING + VALUE(rv_proxy_url) TYPE string . + METHODS get_proxy_port + RETURNING + VALUE(rv_port) TYPE string . + METHODS get_proxy_authentication + RETURNING + VALUE(rv_auth) TYPE abap_bool . + METHODS get_proxy_bypass + RETURNING + VALUE(rt_bypass) TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url . + METHODS set_run_critical_tests + IMPORTING + !iv_run TYPE abap_bool . + METHODS get_run_critical_tests + RETURNING + VALUE(rv_run) TYPE abap_bool . + METHODS set_experimental_features + IMPORTING + !iv_features TYPE string. + METHODS get_experimental_features + RETURNING + VALUE(rv_features) TYPE string. + METHODS set_max_lines + IMPORTING + !iv_lines TYPE i . + METHODS get_max_lines + RETURNING + VALUE(rv_lines) TYPE i . + METHODS set_adt_jump_enanbled + IMPORTING + !iv_adt_jump_enabled TYPE abap_bool . + METHODS get_adt_jump_enabled + RETURNING + VALUE(rv_adt_jump_enabled) TYPE abap_bool . + METHODS set_commitmsg_comment_length + IMPORTING + !iv_length TYPE i . + METHODS get_commitmsg_comment_length + RETURNING + VALUE(rv_length) TYPE i . + METHODS set_commitmsg_comment_default + IMPORTING + !iv_default TYPE string . + METHODS get_commitmsg_comment_default + RETURNING + VALUE(rv_default) TYPE string . + METHODS set_commitmsg_body_size + IMPORTING + !iv_length TYPE i . + METHODS get_commitmsg_body_size + RETURNING + VALUE(rv_length) TYPE i . + METHODS set_commitmsg_hide_author + IMPORTING + !iv_hide_author TYPE abap_bool. + METHODS get_commitmsg_hide_author + RETURNING + VALUE(rv_hide_author) TYPE abap_bool. + METHODS get_settings_xml + RETURNING + VALUE(rv_settings_xml) TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_user_settings + RETURNING + VALUE(rs_settings) TYPE zif_abapgit_persist_user=>ty_s_user_settings + RAISING + zcx_abapgit_exception . + METHODS set_xml_settings + IMPORTING + !iv_settings_xml TYPE string + RAISING + zcx_abapgit_exception . + METHODS set_defaults . + METHODS set_user_settings + IMPORTING + !is_user_settings TYPE zif_abapgit_persist_user=>ty_s_user_settings . + METHODS get_show_default_repo + RETURNING + VALUE(rv_show_default_repo) TYPE abap_bool . + METHODS set_show_default_repo + IMPORTING + !iv_show_default_repo TYPE abap_bool . + METHODS set_link_hints_enabled + IMPORTING + !iv_link_hints_enabled TYPE abap_bool . + METHODS get_link_hints_enabled + RETURNING + VALUE(rv_link_hints_enabled) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS set_link_hint_key + IMPORTING + !iv_link_hint_key TYPE string . + METHODS get_link_hint_key + RETURNING + VALUE(rv_link_hint_key) TYPE string . + METHODS set_parallel_proc_disabled + IMPORTING + !iv_disable_parallel_proc TYPE abap_bool . + METHODS get_parallel_proc_disabled + RETURNING + VALUE(rv_disable_parallel_proc) TYPE abap_bool . + METHODS get_icon_scaling + RETURNING + VALUE(rv_scaling) TYPE zif_abapgit_persist_user=>ty_s_user_settings-icon_scaling . + METHODS set_icon_scaling + IMPORTING + !iv_scaling TYPE zif_abapgit_persist_user=>ty_s_user_settings-icon_scaling . + METHODS get_ui_theme + IMPORTING + !iv_resolve_synced TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rv_ui_theme) TYPE zif_abapgit_persist_user=>ty_s_user_settings-ui_theme . + METHODS set_ui_theme + IMPORTING + !iv_ui_theme TYPE zif_abapgit_persist_user=>ty_s_user_settings-ui_theme . + METHODS get_activate_wo_popup + RETURNING + VALUE(rv_act_wo_popup) TYPE zif_abapgit_persist_user=>ty_s_user_settings-activate_wo_popup . + METHODS set_activate_wo_popup + IMPORTING + !iv_act_wo_popup TYPE zif_abapgit_persist_user=>ty_s_user_settings-activate_wo_popup . + METHODS set_default_git_uname + IMPORTING + !iv_default_git_uname TYPE string. + METHODS get_default_git_uname + RETURNING + VALUE(rv_default_git_uname) TYPE string. + METHODS set_default_git_email + IMPORTING + !iv_default_git_email TYPE string. + METHODS get_default_git_email + RETURNING + VALUE(rv_default_git_email) TYPE string. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_s_settings, + proxy_url TYPE string, + proxy_port TYPE string, + proxy_auth TYPE string, + proxy_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url, + run_critical_tests TYPE abap_bool, + experimental_features TYPE string, + commitmsg_comment_length TYPE i, + commitmsg_comment_deflt TYPE string, + commitmsg_body_size TYPE i, + commitmsg_hide_author TYPE abap_bool, + END OF ty_s_settings. + + DATA: ms_settings TYPE ty_s_settings, + ms_user_settings TYPE zif_abapgit_persist_user=>ty_s_user_settings. + + METHODS: + set_default_link_hint_key. + +ENDCLASS. +CLASS zcl_abapgit_user_record DEFINITION + FINAL + CREATE PRIVATE + FRIENDS ZCL_abapgit_env_factory. + + PUBLIC SECTION. + CLASS-METHODS reset. + + INTERFACES zif_abapgit_user_record. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_user, + user TYPE sy-uname, + name TYPE string, + email TYPE string, + END OF ty_user. + + CLASS-DATA gt_user TYPE HASHED TABLE OF ty_user WITH UNIQUE KEY user. + + CLASS-METHODS check_user_exists + IMPORTING + iv_user TYPE sy-uname + EXPORTING + ev_fullname TYPE string + ev_email TYPE string + RAISING + zcx_abapgit_exception. + + CLASS-METHODS get_user_dtls_from_other_clnt + IMPORTING + iv_user TYPE sy-uname + RETURNING + VALUE(rs_user) TYPE ty_user. + + CLASS-METHODS build_cache + IMPORTING + iv_user TYPE sy-uname + RETURNING + VALUE(rs_user) TYPE ty_user. + + CLASS-METHODS read_cache + IMPORTING + iv_user TYPE sy-uname + RETURNING + VALUE(rs_user) TYPE ty_user. +ENDCLASS. +CLASS zcl_abapgit_auth DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS is_allowed + IMPORTING + !iv_authorization TYPE zif_abapgit_auth=>ty_authorization + !iv_param TYPE string OPTIONAL + RETURNING + VALUE(rv_allowed) TYPE abap_bool . + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_exit DEFINITION + CREATE PUBLIC + . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_exit. + + CLASS-METHODS get_instance + RETURNING + VALUE(ri_exit) TYPE REF TO zif_abapgit_exit. + + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gi_global_exit TYPE REF TO zif_abapgit_exit. + CLASS-DATA gi_exit TYPE REF TO zif_abapgit_exit. + + CLASS-METHODS is_running_in_test_context + RETURNING + VALUE(rv_running_in_test_context) TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_gitv2_porcelain DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_git_factory . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gitv2_porcelain. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: + BEGIN OF c_service, + receive TYPE string VALUE 'receive', "#EC NOTEXT + upload TYPE string VALUE 'upload', "#EC NOTEXT + END OF c_service . + + CONSTANTS c_flush_pkt TYPE c LENGTH 4 VALUE '0000'. + CONSTANTS c_delim_pkt TYPE c LENGTH 4 VALUE '0001'. + + CLASS-METHODS get_request_uri + IMPORTING + iv_url TYPE string + iv_service TYPE string + RETURNING + VALUE(rv_uri) TYPE string + RAISING + zcx_abapgit_exception. + + CLASS-METHODS send_command + IMPORTING + iv_url TYPE string + iv_service TYPE string + iv_command TYPE string + it_arguments TYPE string_table OPTIONAL + RETURNING + VALUE(rv_response) TYPE xstring + RAISING + zcx_abapgit_exception. + + CLASS-METHODS decode_pack + IMPORTING + iv_xstring TYPE xstring + RETURNING + VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_git_add_patch DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + METHODS: + constructor + IMPORTING + it_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, + + get_patch + RETURNING + VALUE(rt_patch) TYPE string_table + RAISING + zcx_abapgit_exception, + + get_patch_binary + RETURNING + VALUE(rv_patch_binary) TYPE xstring + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + DATA: + mt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, + mt_patch TYPE string_table. + + METHODS: + calculate_patch + RETURNING + VALUE(rt_patch) TYPE string_table + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_git_branch_list DEFINITION + CREATE PUBLIC FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_git_branch_list. + + METHODS constructor + IMPORTING + !iv_data TYPE string + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt . + DATA mv_head_symref TYPE string . + + CLASS-METHODS skip_first_pkt + IMPORTING + !iv_data TYPE string + RETURNING + VALUE(rv_data) TYPE string + RAISING + zcx_abapgit_exception . + METHODS find_tag_by_name + IMPORTING + !iv_branch_name TYPE string + RETURNING + VALUE(rs_branch) TYPE zif_abapgit_git_definitions=>ty_git_branch + RAISING + zcx_abapgit_exception . + CLASS-METHODS parse_branch_list + IMPORTING + !iv_data TYPE string + EXPORTING + !et_list TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt + !ev_head_symref TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS parse_head_params + IMPORTING + !iv_data TYPE string + RETURNING + VALUE(rv_head_symref) TYPE string . +ENDCLASS. +CLASS zcl_abapgit_git_branch_utils DEFINITION. + PUBLIC SECTION. + + CLASS-METHODS get_display_name + IMPORTING + !iv_branch_name TYPE clike + RETURNING + VALUE(rv_display_name) TYPE string . + CLASS-METHODS get_type + IMPORTING + !iv_branch_name TYPE clike + !it_result TYPE string_table OPTIONAL + !iv_current_row_index TYPE sy-tabix OPTIONAL + RETURNING + VALUE(rv_type) TYPE zif_abapgit_git_definitions=>ty_git_branch_type . + CLASS-METHODS get_description + IMPORTING + !iv_branch_name TYPE clike + RETURNING + VALUE(rv_description) TYPE string. + CLASS-METHODS complete_heads_branch_name + IMPORTING + !iv_branch_name TYPE clike + RETURNING + VALUE(rv_name) TYPE string . + CLASS-METHODS normalize_branch_name + IMPORTING + !iv_branch_name TYPE clike + RETURNING + VALUE(rv_name) TYPE string . +ENDCLASS. +CLASS zcl_abapgit_git_commit DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + TYPES: + BEGIN OF ty_pull_result, + commits TYPE zif_abapgit_git_definitions=>ty_commit_tt, + commit TYPE zif_abapgit_git_definitions=>ty_sha1, + END OF ty_pull_result . + + CLASS-METHODS get_by_branch + IMPORTING + !iv_branch_name TYPE string + !iv_repo_url TYPE string + !iv_deepen_level TYPE i + !iv_sorted TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rs_pull_result) TYPE ty_pull_result + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_by_commit + IMPORTING + !iv_commit_hash TYPE zif_abapgit_git_definitions=>ty_sha1 + !iv_repo_url TYPE string + !iv_deepen_level TYPE i + RETURNING + VALUE(rt_commits) TYPE zif_abapgit_git_definitions=>ty_commit_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS parse_commits + IMPORTING + !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt + RETURNING + VALUE(rt_commits) TYPE zif_abapgit_git_definitions=>ty_commit_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS sort_commits + CHANGING + !ct_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS reverse_sort_order + CHANGING + !ct_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt . + CLASS-METHODS clear_missing_parents CHANGING ct_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt . + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: ty_sha1_range TYPE RANGE OF zif_abapgit_git_definitions=>ty_sha1 . + + CLASS-METHODS get_1st_child_commit + IMPORTING + it_commit_sha1s TYPE ty_sha1_range + EXPORTING + et_commit_sha1s TYPE ty_sha1_range + es_1st_commit TYPE zif_abapgit_git_definitions=>ty_commit + CHANGING + ct_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt . + + CLASS-METHODS is_missing + IMPORTING + it_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt + iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1 + RETURNING + VALUE(rv_result) TYPE abap_bool. + + CLASS-METHODS extract_author_data + IMPORTING + !iv_author TYPE string + EXPORTING + !ev_author TYPE zif_abapgit_git_definitions=>ty_commit-author + !ev_email TYPE zif_abapgit_git_definitions=>ty_commit-email + !ev_time TYPE zif_abapgit_git_definitions=>ty_commit-time + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS kHGwlatytwTSETnzZMKotffscEwAXR DEFINITION DEFERRED. +* renamed: zcl_abapgit_git_delta :: lcl_stream +CLASS kHGwlatytwTSETnzZMKotffscEwAXR DEFINITION FINAL. + PUBLIC SECTION. + TYPES: ty_hex TYPE x LENGTH 1. + + METHODS: + constructor + IMPORTING + iv_data TYPE xstring, + eat_byte + RETURNING VALUE(rv_x) TYPE ty_hex, + eat_bytes + IMPORTING + iv_length TYPE i + RETURNING + VALUE(rv_x) TYPE xstring. + + METHODS has_data + RETURNING + VALUE(rv_data) TYPE abap_bool. + + PRIVATE SECTION. + DATA mv_data TYPE xstring. + DATA mv_position TYPE i. + DATA mv_length TYPE i. +ENDCLASS. + +CLASS zcl_abapgit_git_delta DEFINITION. + PUBLIC SECTION. + + CLASS-METHODS decode_deltas + IMPORTING + iv_show_progress TYPE abap_bool DEFAULT abap_true + CHANGING + !ct_objects TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception . + + PRIVATE SECTION. + CLASS-METHODS delta + IMPORTING + !is_object TYPE zif_abapgit_definitions=>ty_object + CHANGING + !ct_objects TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception . + + CLASS-METHODS delta_header + IMPORTING + !io_stream TYPE REF TO kHGwlatytwTSETnzZMKotffscEwAXR. + +ENDCLASS. +CLASS zcl_abapgit_git_factory DEFINITION + FINAL + CREATE PRIVATE + . + + PUBLIC SECTION. + CLASS-METHODS: + get_v2_porcelain + RETURNING VALUE(ri_v2) TYPE REF TO zif_abapgit_gitv2_porcelain, + + get_git_transport + RETURNING + VALUE(ri_git_transport) TYPE REF TO zif_abapgit_git_transport. + + PROTECTED SECTION. + PRIVATE SECTION. + CLASS-DATA: + gi_git_transport TYPE REF TO zif_abapgit_git_transport. + CLASS-DATA: + gi_v2 TYPE REF TO zif_abapgit_gitv2_porcelain. + +ENDCLASS. +CLASS zcl_abapgit_git_pack DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + TYPES: + BEGIN OF ty_node, + chmod TYPE zif_abapgit_git_definitions=>ty_chmod, + name TYPE string, + sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + END OF ty_node . + TYPES: + ty_nodes_tt TYPE STANDARD TABLE OF ty_node WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_commit, + tree TYPE zif_abapgit_git_definitions=>ty_sha1, + parent TYPE zif_abapgit_git_definitions=>ty_sha1, + parent2 TYPE zif_abapgit_git_definitions=>ty_sha1, + author TYPE string, + committer TYPE string, + gpgsig TYPE string, + body TYPE string, + END OF ty_commit . + TYPES: + BEGIN OF ty_tag, + object TYPE string, + type TYPE string, + tag TYPE string, + tagger_name TYPE string, + tagger_email TYPE string, + message TYPE string, + body TYPE string, + END OF ty_tag . + + CLASS-METHODS decode + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS decode_tree + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rt_nodes) TYPE ty_nodes_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS decode_commit + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rs_commit) TYPE ty_commit + RAISING + zcx_abapgit_exception . + CLASS-METHODS decode_tag + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rs_tag) TYPE ty_tag + RAISING + zcx_abapgit_exception . + CLASS-METHODS encode + IMPORTING + !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS encode_tree + IMPORTING + !it_nodes TYPE ty_nodes_tt + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS encode_commit + IMPORTING + !is_commit TYPE ty_commit + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS encode_tag + IMPORTING + !is_tag TYPE ty_tag + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + c_pack_start TYPE x LENGTH 4 VALUE '5041434B' ##NO_TEXT. + CONSTANTS: + c_zlib TYPE x LENGTH 2 VALUE '789C' ##NO_TEXT. + CONSTANTS: + c_zlib_hmm TYPE x LENGTH 2 VALUE '7801' ##NO_TEXT. + CONSTANTS: " PACK + c_version TYPE x LENGTH 4 VALUE '00000002' ##NO_TEXT. + + CLASS-METHODS sort_tree + IMPORTING + !it_nodes TYPE ty_nodes_tt + RETURNING + VALUE(rt_nodes) TYPE ty_nodes_tt . + CLASS-METHODS get_type + IMPORTING + !iv_x TYPE x + RETURNING + VALUE(rv_type) TYPE zif_abapgit_git_definitions=>ty_type + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_length + EXPORTING + !ev_length TYPE i + CHANGING + !cv_data TYPE xstring . + CLASS-METHODS type_and_length + IMPORTING + !iv_type TYPE zif_abapgit_git_definitions=>ty_type + !iv_length TYPE i + RETURNING + VALUE(rv_xstring) TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS zlib_decompress + CHANGING + !cv_data TYPE xstring + !cv_decompressed TYPE xstring + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_git_porcelain DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_pull_result, + files TYPE zif_abapgit_git_definitions=>ty_files_tt, + objects TYPE zif_abapgit_definitions=>ty_objects_tt, + commit TYPE zif_abapgit_git_definitions=>ty_sha1, + END OF ty_pull_result . + TYPES: + BEGIN OF ty_push_result, + new_files TYPE zif_abapgit_git_definitions=>ty_files_tt, + branch TYPE zif_abapgit_git_definitions=>ty_sha1, + updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt, + new_objects TYPE zif_abapgit_definitions=>ty_objects_tt, + END OF ty_push_result . + + CLASS-METHODS pull_by_branch + IMPORTING + !iv_url TYPE string + !iv_branch_name TYPE string + !iv_deepen_level TYPE i DEFAULT 1 + RETURNING + VALUE(rs_result) TYPE ty_pull_result + RAISING + zcx_abapgit_exception . + CLASS-METHODS pull_by_commit + IMPORTING + !iv_url TYPE string + !iv_commit_hash TYPE zif_abapgit_git_definitions=>ty_sha1 + !iv_deepen_level TYPE i DEFAULT 1 + RETURNING + VALUE(rs_result) TYPE ty_pull_result + RAISING + zcx_abapgit_exception . + CLASS-METHODS push + IMPORTING + !is_comment TYPE zif_abapgit_git_definitions=>ty_comment + !io_stage TYPE REF TO zcl_abapgit_stage + !it_old_objects TYPE zif_abapgit_definitions=>ty_objects_tt + !iv_parent TYPE zif_abapgit_git_definitions=>ty_sha1 + !iv_url TYPE string + !iv_branch_name TYPE string + RETURNING + VALUE(rs_result) TYPE ty_push_result + RAISING + zcx_abapgit_exception . + CLASS-METHODS create_branch + IMPORTING + !iv_url TYPE string + !iv_name TYPE csequence + !iv_from TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + CLASS-METHODS create_tag + IMPORTING + !iv_url TYPE string + !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag + RAISING + zcx_abapgit_exception . + CLASS-METHODS delete_branch + IMPORTING + !iv_url TYPE string + !is_branch TYPE zif_abapgit_git_definitions=>ty_git_branch + RAISING + zcx_abapgit_exception . + CLASS-METHODS delete_tag + IMPORTING + !iv_url TYPE string + !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag + RAISING + zcx_abapgit_exception . + CLASS-METHODS full_tree + IMPORTING + !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt + !iv_parent TYPE zif_abapgit_git_definitions=>ty_sha1 + RETURNING + VALUE(rt_expanded) TYPE zif_abapgit_git_definitions=>ty_expanded_tt + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_tree, + path TYPE string, + data TYPE xstring, + sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + END OF ty_tree . + TYPES: + ty_trees_tt TYPE STANDARD TABLE OF ty_tree WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_folder, + path TYPE string, + count TYPE i, + sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + END OF ty_folder . + TYPES: + ty_folders_tt TYPE STANDARD TABLE OF ty_folder WITH DEFAULT KEY . + + CONSTANTS c_zero TYPE zif_abapgit_git_definitions=>ty_sha1 + VALUE '0000000000000000000000000000000000000000' ##NO_TEXT. + + CLASS-METHODS build_trees + IMPORTING + !it_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt + RETURNING + VALUE(rt_trees) TYPE ty_trees_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS find_folders + IMPORTING + !it_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt + RETURNING + VALUE(rt_folders) TYPE ty_folders_tt . + CLASS-METHODS pull + IMPORTING + !iv_commit TYPE zif_abapgit_git_definitions=>ty_sha1 + !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception. + CLASS-METHODS walk + IMPORTING + !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt + !iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1 + !iv_path TYPE string + CHANGING + !ct_files TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS walk_tree + IMPORTING + !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt + !iv_tree TYPE zif_abapgit_git_definitions=>ty_sha1 + !iv_base TYPE string + RETURNING + VALUE(rt_expanded) TYPE zif_abapgit_git_definitions=>ty_expanded_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS receive_pack_push + IMPORTING + !is_comment TYPE zif_abapgit_git_definitions=>ty_comment + !it_trees TYPE ty_trees_tt + !it_blobs TYPE zif_abapgit_git_definitions=>ty_files_tt + !iv_parent TYPE zif_abapgit_git_definitions=>ty_sha1 + !iv_parent2 TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL + !iv_url TYPE string + !iv_branch_name TYPE string + EXPORTING + !ev_new_commit TYPE zif_abapgit_git_definitions=>ty_sha1 + !et_new_objects TYPE zif_abapgit_definitions=>ty_objects_tt + !ev_new_tree TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + CLASS-METHODS create_annotated_tag + IMPORTING + !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag + !iv_url TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS create_lightweight_tag + IMPORTING + is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag + iv_url TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS delete_annotated_tag + IMPORTING + !iv_url TYPE string + !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag + RAISING + zcx_abapgit_exception . + CLASS-METHODS delete_lightweight_tag + IMPORTING + !iv_url TYPE string + !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag + RAISING + zcx_abapgit_exception . + CLASS-METHODS empty_packfile + RETURNING + VALUE(rv_pack) TYPE xstring + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_git_tag DEFINITION + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS add_tag_prefix + IMPORTING + !iv_text TYPE csequence + RETURNING + VALUE(rv_text) TYPE string. + + CLASS-METHODS remove_tag_prefix + IMPORTING + !iv_text TYPE string + RETURNING + VALUE(rv_text) TYPE string. + + CLASS-METHODS add_peel + IMPORTING + !iv_text TYPE string + RETURNING + VALUE(rv_text) TYPE string. + + CLASS-METHODS remove_peel + IMPORTING + !iv_text TYPE string + RETURNING + VALUE(rv_text) TYPE string. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_git_time DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + ty_unixtime TYPE c LENGTH 16 . + + CLASS-METHODS get_unix + RETURNING + VALUE(rv_time) TYPE ty_unixtime + RAISING + zcx_abapgit_exception . + + CLASS-METHODS get_one_year_ago + RETURNING + VALUE(rv_time) TYPE i + RAISING + zcx_abapgit_exception . + + CLASS-METHODS get_utc + IMPORTING + !iv_unix TYPE ty_unixtime + EXPORTING + !ev_date TYPE sy-datum + !ev_time TYPE sy-uzeit . + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_git_transport DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_git_transport. + +* remote to local + CLASS-METHODS upload_pack_by_branch + IMPORTING + !iv_url TYPE string + !iv_branch_name TYPE string + !iv_deepen_level TYPE i DEFAULT 1 + !it_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt OPTIONAL + EXPORTING + !et_objects TYPE zif_abapgit_definitions=>ty_objects_tt + !ev_branch TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + CLASS-METHODS upload_pack_by_commit + IMPORTING + !iv_url TYPE string + !iv_hash TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL + !iv_deepen_level TYPE i DEFAULT 0 + EXPORTING + !et_objects TYPE zif_abapgit_definitions=>ty_objects_tt + !ev_commit TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . +* local to remote + CLASS-METHODS receive_pack + IMPORTING + !iv_url TYPE string + !iv_old TYPE zif_abapgit_git_definitions=>ty_sha1 + !iv_new TYPE zif_abapgit_git_definitions=>ty_sha1 + !iv_branch_name TYPE string + !iv_pack TYPE xstring OPTIONAL + RAISING + zcx_abapgit_exception . + CLASS-METHODS branches + IMPORTING + iv_url TYPE string + RETURNING + VALUE(ri_branch_list) TYPE REF TO zif_abapgit_git_branch_list + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_service, + receive TYPE string VALUE 'receive', "#EC NOTEXT + upload TYPE string VALUE 'upload', "#EC NOTEXT + END OF c_service . + + CLASS-METHODS get_request_uri + IMPORTING + iv_url TYPE string + iv_service TYPE string + RETURNING + VALUE(rv_uri) TYPE string + RAISING + zcx_abapgit_exception. + + CLASS-METHODS check_report_status + IMPORTING + !iv_string TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS branch_list + IMPORTING + !iv_url TYPE string + !iv_service TYPE string + EXPORTING + !eo_client TYPE REF TO zcl_abapgit_http_client + !ei_branch_list TYPE REF TO zif_abapgit_git_branch_list + RAISING + zcx_abapgit_exception . + CLASS-METHODS find_branch + IMPORTING + !iv_url TYPE string + !iv_service TYPE string + !iv_branch_name TYPE string + EXPORTING + !eo_client TYPE REF TO zcl_abapgit_http_client + !ev_branch TYPE zif_abapgit_git_definitions=>ty_sha1 + !ei_branch_list TYPE REF TO zif_abapgit_git_branch_list + RAISING + zcx_abapgit_exception . + CLASS-METHODS parse + EXPORTING + !ev_pack TYPE xstring + CHANGING + !cv_data TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS upload_pack + IMPORTING + !io_client TYPE REF TO zcl_abapgit_http_client + !iv_url TYPE string + !iv_deepen_level TYPE i DEFAULT 0 + !it_hashes TYPE zif_abapgit_git_definitions=>ty_sha1_tt + RETURNING + VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_git_utils DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + ty_null TYPE c LENGTH 1 . + + CLASS-METHODS get_null + RETURNING + VALUE(rv_c) TYPE ty_null . + CLASS-METHODS pkt_string + IMPORTING + !iv_string TYPE string + RETURNING + VALUE(rv_pkt) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS length_utf8_hex + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rv_len) TYPE i + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_hash DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS adler32 + IMPORTING + !iv_xstring TYPE xstring + RETURNING + VALUE(rv_checksum) TYPE zif_abapgit_git_definitions=>ty_adler32 . + CLASS-METHODS sha1 + IMPORTING + !iv_type TYPE zif_abapgit_git_definitions=>ty_type + !iv_data TYPE xstring + RETURNING + VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + CLASS-METHODS sha1_commit + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + CLASS-METHODS sha1_tree + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + CLASS-METHODS sha1_tag + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + CLASS-METHODS sha1_blob + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + CLASS-METHODS sha1_raw + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + CLASS-METHODS sha1_string + IMPORTING + !iv_data TYPE string + RETURNING + VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_zlib DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_decompress, + raw TYPE xstring, + compressed_len TYPE i, + END OF ty_decompress . + + CLASS-METHODS decompress + IMPORTING + !iv_compressed TYPE xsequence + RETURNING + VALUE(rs_data) TYPE ty_decompress . + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: c_maxdcodes TYPE i VALUE 30. + + CLASS-DATA: gv_out TYPE xstring, + go_lencode TYPE REF TO zcl_abapgit_zlib_huffman, + go_distcode TYPE REF TO zcl_abapgit_zlib_huffman, + go_stream TYPE REF TO zcl_abapgit_zlib_stream. + + TYPES: BEGIN OF ty_pair, + length TYPE i, + distance TYPE i, + END OF ty_pair. + + CLASS-METHODS: + decode + IMPORTING io_huffman TYPE REF TO zcl_abapgit_zlib_huffman + RETURNING VALUE(rv_symbol) TYPE i, + map_length + IMPORTING iv_code TYPE i + RETURNING VALUE(rv_length) TYPE i, + map_distance + IMPORTING iv_code TYPE i + RETURNING VALUE(rv_distance) TYPE i, + dynamic, + fixed, + not_compressed, + decode_loop, + read_pair + IMPORTING iv_length TYPE i + RETURNING VALUE(rs_pair) TYPE ty_pair, + copy_out + IMPORTING is_pair TYPE ty_pair. + +ENDCLASS. +CLASS zcl_abapgit_zlib_convert DEFINITION FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS hex_to_bits + IMPORTING + !iv_hex TYPE xsequence + RETURNING + VALUE(rv_bits) TYPE string. + + CLASS-METHODS bits_to_int + IMPORTING + !iv_bits TYPE clike + RETURNING + VALUE(rv_int) TYPE i. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_zlib_huffman DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + ty_lengths TYPE STANDARD TABLE OF i WITH DEFAULT KEY . + + CONSTANTS c_maxbits TYPE i VALUE 15 ##NO_TEXT. + + METHODS constructor + IMPORTING + !it_lengths TYPE ty_lengths . + METHODS get_count + IMPORTING + !iv_index TYPE i + RETURNING + VALUE(rv_value) TYPE i . + METHODS get_symbol + IMPORTING + !iv_index TYPE i + RETURNING + VALUE(rv_value) TYPE i . + PROTECTED SECTION. + PRIVATE SECTION. + + DATA: mt_count TYPE STANDARD TABLE OF i WITH DEFAULT KEY, + mt_symbol TYPE STANDARD TABLE OF i WITH DEFAULT KEY. + +ENDCLASS. +CLASS zcl_abapgit_zlib_stream DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !iv_data TYPE xstring . + METHODS take_bits + IMPORTING + !iv_length TYPE i + RETURNING + VALUE(rv_bits) TYPE string . + METHODS take_int + IMPORTING + !iv_length TYPE i + RETURNING + VALUE(rv_int) TYPE i . + METHODS remaining + RETURNING + VALUE(rv_length) TYPE i . + "! Take bytes, there's an implicit realignment to start at the beginning of a byte + "! i.e. if next bit of current byte is not the first bit, then this byte is skipped + "! and the bytes are taken from the next one. + "! @parameter iv_length |

      + "! @parameter rv_bytes |

      + METHODS take_bytes + IMPORTING + !iv_length TYPE i + RETURNING + VALUE(rv_bytes) TYPE xstring . + METHODS clear_bits . + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_bits TYPE string . + DATA mv_compressed TYPE xstring . +ENDCLASS. +CLASS zcl_abapgit_git_url DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS get_commit_display_url + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + RETURNING + VALUE(rv_url) TYPE string + RAISING + zcx_abapgit_exception . + + METHODS validate_url + IMPORTING + !iv_url TYPE string + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + METHODS get_default_commit_display_url + IMPORTING + !iv_repo_url TYPE string + !iv_hash TYPE zif_abapgit_git_definitions=>ty_sha1 + RETURNING + VALUE(rv_commit_url) TYPE string + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_pr_enum_gitea DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_pr_enum_provider . + + METHODS constructor + IMPORTING + !iv_user_and_repo TYPE string + !ii_http_agent TYPE REF TO zif_abapgit_http_agent + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_info, + repo_json TYPE REF TO zif_abapgit_ajson, + pulls TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests, + END OF ty_info. + + DATA mi_http_agent TYPE REF TO zif_abapgit_http_agent. + DATA mv_repo_url TYPE string. + + METHODS fetch_repo_by_url + IMPORTING + iv_repo_url TYPE string + RETURNING + VALUE(rs_info) TYPE ty_info + RAISING + zcx_abapgit_exception. + + METHODS convert_list + IMPORTING + ii_json TYPE REF TO zif_abapgit_ajson + RETURNING + VALUE(rt_pulls) TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests. + + METHODS clean_url + IMPORTING + iv_url TYPE string + RETURNING + VALUE(rv_url) TYPE string. +ENDCLASS. +CLASS zcl_abapgit_pr_enum_github DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_pr_enum_provider . + + METHODS constructor + IMPORTING + !iv_user_and_repo TYPE string + !ii_http_agent TYPE REF TO zif_abapgit_http_agent + RAISING + zcx_abapgit_exception. + + METHODS create_pull_request + IMPORTING + iv_title TYPE clike + iv_body TYPE clike OPTIONAL + iv_head TYPE string + iv_base TYPE string + RAISING + zcx_abapgit_exception. + + METHODS merge_pull_request + IMPORTING + iv_pull_number TYPE i + RAISING + zcx_abapgit_exception. + + METHODS update_pull_request_branch + IMPORTING + iv_pull_number TYPE i + iv_expected_head_sha TYPE zif_abapgit_git_definitions=>ty_sha1 + RAISING + zcx_abapgit_exception. + + METHODS ready_for_review + IMPORTING + iv_pull_number TYPE i + RAISING + zcx_abapgit_exception. + + TYPES: BEGIN OF ty_status, + name TYPE string, + status TYPE string, + conclusion TYPE string, + title TYPE string, + END OF ty_status. + TYPES ty_status_tt TYPE STANDARD TABLE OF ty_status WITH DEFAULT KEY. + METHODS get_check_runs + IMPORTING + iv_ref TYPE string + RETURNING + VALUE(rt_status) TYPE ty_status_tt + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_info, + repo_json TYPE REF TO zif_abapgit_ajson, + pulls TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests, + END OF ty_info. + + DATA mi_http_agent TYPE REF TO zif_abapgit_http_agent. + DATA mv_repo_url TYPE string. + DATA mv_user_and_repo TYPE string. + + METHODS fetch_repo_by_url + IMPORTING + iv_repo_url TYPE string + RETURNING + VALUE(rs_info) TYPE ty_info + RAISING + zcx_abapgit_exception. + + METHODS convert_list + IMPORTING + ii_json TYPE REF TO zif_abapgit_ajson + RETURNING + VALUE(rt_pulls) TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests. + + METHODS clean_url + IMPORTING + iv_url TYPE string + RETURNING + VALUE(rv_url) TYPE string. +ENDCLASS. +CLASS zcl_abapgit_pr_enumerator DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + iv_url TYPE string + RAISING + zcx_abapgit_exception. + + METHODS get_pulls + RETURNING + VALUE(rt_pulls) TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests + RAISING + zcx_abapgit_exception. + + METHODS create_repository + IMPORTING + iv_description TYPE string OPTIONAL + iv_is_org TYPE abap_bool DEFAULT abap_true + iv_private TYPE abap_bool DEFAULT abap_true + iv_auto_init TYPE abap_bool DEFAULT abap_true + RAISING + zcx_abapgit_exception. + + METHODS create_initial_branch + IMPORTING + iv_readme TYPE string OPTIONAL + iv_branch_name TYPE string DEFAULT 'main' + RETURNING + VALUE(rv_branch_name) TYPE string + RAISING + zcx_abapgit_exception. + + CLASS-METHODS new + IMPORTING + iv_url TYPE string + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_pr_enumerator + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA mv_repo_url TYPE string. + DATA mi_enum_provider TYPE REF TO zif_abapgit_pr_enum_provider. + + CLASS-METHODS create_provider + IMPORTING + iv_repo_url TYPE string + RETURNING + VALUE(ri_provider) TYPE REF TO zif_abapgit_pr_enum_provider + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_http DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CONSTANTS: + BEGIN OF c_scheme, + digest TYPE string VALUE 'Digest', + END OF c_scheme . + + CLASS-METHODS get_agent + RETURNING + VALUE(rv_agent) TYPE string . + + TYPES: BEGIN OF ty_key_value, + key TYPE string, + value TYPE string, + END OF ty_key_value. + TYPES ty_headers TYPE STANDARD TABLE OF ty_key_value WITH DEFAULT KEY. + + CLASS-METHODS create_by_url + IMPORTING + !iv_url TYPE string + it_headers TYPE ty_headers OPTIONAL + RETURNING + VALUE(ro_client) TYPE REF TO zcl_abapgit_http_client + RAISING + zcx_abapgit_exception . + + CLASS-METHODS check_connection + IMPORTING + !iv_url TYPE string + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + + CLASS-METHODS check_auth_requested + IMPORTING + !ii_client TYPE REF TO if_http_client + RETURNING + VALUE(rv_auth_requested) TYPE abap_bool + RAISING + zcx_abapgit_exception . + CLASS-METHODS is_local_system + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(rv_bool) TYPE abap_bool . + CLASS-METHODS acquire_login_details + IMPORTING + !ii_client TYPE REF TO if_http_client + !io_client TYPE REF TO zcl_abapgit_http_client + !iv_url TYPE string + RETURNING + VALUE(rv_scheme) TYPE string + RAISING + zcx_abapgit_exception . + + CLASS-METHODS get_http_client + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(ri_client) TYPE REF TO if_http_client + RAISING + zcx_abapgit_exception. + + CLASS-METHODS get_connection_longtext + IMPORTING + !iv_host TYPE string + !iv_ssl_id TYPE ssfapplssl + !iv_proxy_host TYPE string + !iv_proxy_service TYPE string + RETURNING + VALUE(rv_longtext) TYPE string. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_http_agent DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES zif_abapgit_http_agent . + + CLASS-METHODS create + RETURNING + VALUE(ri_instance) TYPE REF TO zif_abapgit_http_agent . + + METHODS constructor. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mo_global_headers TYPE REF TO zcl_abapgit_string_map. + + CLASS-METHODS attach_payload + IMPORTING + ii_request TYPE REF TO if_http_request + iv_payload TYPE any + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_http_client DEFINITION CREATE PUBLIC. + + PUBLIC SECTION. + + METHODS: + constructor + IMPORTING ii_client TYPE REF TO if_http_client, + close, + set_digest + IMPORTING io_digest TYPE REF TO zcl_abapgit_http_digest, + send_receive_close + IMPORTING iv_data TYPE xstring + RETURNING VALUE(rv_data) TYPE xstring + RAISING zcx_abapgit_exception, + get_cdata + RETURNING VALUE(rv_value) TYPE string, + check_http_200 + RAISING zcx_abapgit_exception, + check_smart_response + IMPORTING iv_expected_content_type TYPE string + iv_content_regex TYPE string + RAISING zcx_abapgit_exception, + send_receive + RAISING zcx_abapgit_exception, + set_headers + IMPORTING iv_url TYPE string + iv_service TYPE string + RAISING zcx_abapgit_exception. + + METHODS set_header + IMPORTING + iv_key TYPE string + iv_value TYPE string + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mi_client TYPE REF TO if_http_client, + mo_digest TYPE REF TO zcl_abapgit_http_digest. + +ENDCLASS. +CLASS zcl_abapgit_http_digest DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !ii_client TYPE REF TO if_http_client + !iv_username TYPE string + !iv_password TYPE string + RAISING + zcx_abapgit_exception. + METHODS run + IMPORTING + !ii_client TYPE REF TO if_http_client + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mv_ha1 TYPE string, + mv_username TYPE string, + mv_realm TYPE string, + mv_qop TYPE string, + mv_nonce TYPE string. + + CLASS-DATA: gv_nc TYPE n LENGTH 8. + + CLASS-METHODS: + md5 + IMPORTING + iv_data TYPE string + RETURNING + VALUE(rv_hash) TYPE string + RAISING zcx_abapgit_exception. + + METHODS: + hash + IMPORTING + iv_qop TYPE string + iv_nonce TYPE string + iv_uri TYPE string + iv_method TYPE string + iv_cnonse TYPE string + RETURNING + VALUE(rv_response) TYPE string + RAISING zcx_abapgit_exception, + parse + IMPORTING + ii_client TYPE REF TO if_http_client. + +ENDCLASS. +CLASS zcl_abapgit_login_manager DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS load + IMPORTING + !iv_uri TYPE string + RETURNING + VALUE(rv_authorization) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS save + IMPORTING + !iv_uri TYPE string + !iv_authorization TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS clear . + CLASS-METHODS set_basic + IMPORTING + !iv_uri TYPE string + !iv_username TYPE string + !iv_password TYPE string + RETURNING + VALUE(rv_auth) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS set_bearer + IMPORTING + !iv_uri TYPE string + !iv_token TYPE string + RETURNING + VALUE(rv_auth) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS get + IMPORTING + !iv_uri TYPE string + RETURNING + VALUE(rv_auth) TYPE string + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_auth, + uri TYPE string, + authorization TYPE string, + END OF ty_auth . + + CLASS-DATA: + gt_auth TYPE TABLE OF ty_auth WITH DEFAULT KEY . + + CLASS-METHODS append + IMPORTING + !iv_uri TYPE string + !iv_auth TYPE string + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_proxy_auth DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + CLASS-METHODS: + run + IMPORTING ii_client TYPE REF TO if_http_client + RAISING zcx_abapgit_exception. + + PRIVATE SECTION. + CLASS-DATA: gv_username TYPE string, + gv_password TYPE string. + + CLASS-METHODS: enter RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_proxy_config DEFINITION FINAL CREATE PUBLIC. + + PUBLIC SECTION. + METHODS: + constructor, + + get_proxy_url + IMPORTING + iv_repo_url TYPE csequence OPTIONAL + RETURNING + VALUE(rv_proxy_url) TYPE string, + + get_proxy_port + IMPORTING + iv_repo_url TYPE csequence OPTIONAL + RETURNING + VALUE(rv_port) TYPE string, + + get_proxy_authentication + IMPORTING + iv_repo_url TYPE csequence OPTIONAL + RETURNING + VALUE(rv_auth) TYPE abap_bool. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mo_settings TYPE REF TO zcl_abapgit_settings, + mi_exit TYPE REF TO zif_abapgit_exit. + + METHODS: + bypass_proxy + IMPORTING + iv_repo_url TYPE csequence OPTIONAL + RETURNING + VALUE(rv_bypass_proxy) TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_url DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS validate + IMPORTING + !iv_url TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS host + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(rv_host) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS name + IMPORTING + !iv_url TYPE string + !iv_validate TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rv_name) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS path_name + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(rv_path_name) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS is_abapgit_repo + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(rv_abapgit) TYPE abap_bool . + CLASS-METHODS url_address + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(rv_adress) TYPE string + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-METHODS regex + IMPORTING + !iv_url TYPE string + EXPORTING + !ev_host TYPE string + !ev_path TYPE string + !ev_name TYPE string + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_code_inspector DEFINITION + CREATE PROTECTED. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_code_inspector . + + METHODS constructor + IMPORTING + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception . + + CLASS-METHODS get_code_inspector + IMPORTING + !iv_package TYPE devclass + RETURNING + VALUE(ri_code_inspector) TYPE REF TO zif_abapgit_code_inspector + RAISING + zcx_abapgit_exception. + + CLASS-METHODS set_code_inspector + IMPORTING + !iv_package TYPE devclass + !ii_code_inspector TYPE REF TO zif_abapgit_code_inspector. + + PROTECTED SECTION. + DATA mv_package TYPE devclass . + + METHODS create_variant + IMPORTING + !iv_variant TYPE sci_chkv + RETURNING + VALUE(ro_variant) TYPE REF TO cl_ci_checkvariant + RAISING + zcx_abapgit_exception . + METHODS cleanup + IMPORTING + !io_set TYPE REF TO cl_ci_objectset + RAISING + zcx_abapgit_exception . + METHODS skip_object + IMPORTING + !is_obj TYPE scir_objs + RETURNING + VALUE(rv_skip) TYPE abap_bool. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_code_inspector_pack, + package TYPE devclass, + instance TYPE REF TO zif_abapgit_code_inspector, + END OF ty_code_inspector_pack, + ty_code_inspector_packs TYPE HASHED TABLE OF ty_code_inspector_pack WITH UNIQUE KEY package. + + CLASS-DATA gt_code_inspector TYPE ty_code_inspector_packs. + + DATA mv_success TYPE abap_bool . + DATA mv_summary TYPE string. + + TYPES: ty_run_mode TYPE c LENGTH 1. + + CONSTANTS: + BEGIN OF co_run_mode, + run_with_popup TYPE ty_run_mode VALUE 'P', + run_after_popup TYPE ty_run_mode VALUE 'A', + run_via_rfc TYPE ty_run_mode VALUE 'R', + run_in_batch TYPE ty_run_mode VALUE 'B', + run_loc_parallel TYPE ty_run_mode VALUE 'L', + run_direct TYPE ty_run_mode VALUE 'L', + END OF co_run_mode . + DATA mo_inspection TYPE REF TO cl_ci_inspection . + DATA mv_name TYPE sci_objs . + DATA mv_run_mode TYPE c LENGTH 1 . + + METHODS create_objectset + RETURNING + VALUE(ro_set) TYPE REF TO cl_ci_objectset . + METHODS run_inspection + IMPORTING + !io_inspection TYPE REF TO cl_ci_inspection + RETURNING + VALUE(rt_list) TYPE scit_alvlist + RAISING + zcx_abapgit_exception . + METHODS create_inspection + IMPORTING + !io_set TYPE REF TO cl_ci_objectset + !io_variant TYPE REF TO cl_ci_checkvariant + RETURNING + VALUE(ro_inspection) TYPE REF TO cl_ci_inspection + RAISING + zcx_abapgit_exception . + METHODS decide_run_mode + RETURNING + VALUE(rv_run_mode) TYPE ty_run_mode . + METHODS filter_inspection + CHANGING + !ct_list TYPE scit_alvlist . +ENDCLASS. +CLASS zcl_abapgit_where_used_tools DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES ty_devc_range TYPE RANGE OF tadir-devclass. + TYPES: + BEGIN OF ty_dependency, + root_package TYPE devclass, + package TYPE devclass, + obj_type TYPE tadir-object, + obj_prog_type TYPE trdir-subc, + obj_name TYPE tadir-obj_name, + obj_cls TYPE string, + dep_package TYPE devclass, + dep_obj_type TYPE tadir-object, + dep_obj_name TYPE tadir-obj_name, + dep_used_cls TYPE string, + dep_used_obj TYPE string, + END OF ty_dependency. + TYPES: + ty_dependency_tt TYPE STANDARD TABLE OF ty_dependency WITH DEFAULT KEY. + + CLASS-METHODS new + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_where_used_tools. + + " the initial version of this utility is also available as a standalone tool + " here: https://github.com/sbcgua/crossdeps + METHODS select_external_usages + IMPORTING + iv_package TYPE tadir-devclass + iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false + ir_package_scope TYPE ty_devc_range OPTIONAL + RETURNING + VALUE(rt_objs) TYPE ty_dependency_tt + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_obj_signature, + package TYPE devclass, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + END OF ty_obj_signature. + + TYPES ty_where_used_tt TYPE STANDARD TABLE OF rsfindlst WITH DEFAULT KEY. + TYPES ty_seu_obj TYPE STANDARD TABLE OF seu_obj WITH DEFAULT KEY. + TYPES: + BEGIN OF ty_dev_object, + type TYPE seu_stype, + tadir TYPE trobjtype, + END OF ty_dev_object. + + DATA mt_object_packages TYPE HASHED TABLE OF ty_obj_signature WITH UNIQUE KEY obj_type obj_name. + DATA mt_dev_obj_cache TYPE HASHED TABLE OF ty_dev_object WITH UNIQUE KEY type. + + METHODS get_where_used + IMPORTING + iv_obj_type TYPE euobj-id + iv_obj_name TYPE tadir-obj_name + it_scope TYPE ty_seu_obj OPTIONAL + ir_package_scope TYPE ty_devc_range OPTIONAL + RETURNING + VALUE(rt_findings) TYPE ty_where_used_tt + RAISING + zcx_abapgit_exception. + + METHODS get_obj_package + IMPORTING + iv_obj_type TYPE tadir-object + iv_obj_name TYPE tadir-obj_name + RETURNING + VALUE(rv_package) TYPE tadir-devclass. + + METHODS get_func_package + IMPORTING + iv_func_name TYPE tadir-obj_name + RETURNING + VALUE(rv_package) TYPE tadir-devclass. + + METHODS get_incl_package + IMPORTING + iv_prog_name TYPE tadir-obj_name + RETURNING + VALUE(rv_package) TYPE tadir-devclass. + + METHODS build_package_scope + IMPORTING + it_tadir TYPE STANDARD TABLE + ir_package_scope TYPE ty_devc_range + RETURNING + VALUE(rt_package_scope) TYPE ty_devc_range. + + METHODS collect_where_used + IMPORTING + it_tadir TYPE STANDARD TABLE + ir_package_scope TYPE ty_devc_range + RETURNING + VALUE(rt_objs) TYPE ty_dependency_tt + RAISING + zcx_abapgit_exception. + + METHODS convert_list + IMPORTING + iv_package TYPE ty_dependency-dep_package + iv_obj_type TYPE ty_dependency-dep_obj_type + iv_obj_name TYPE ty_dependency-dep_obj_name + it_where_used TYPE ty_where_used_tt + RETURNING + VALUE(rt_objs) TYPE ty_dependency_tt. + + METHODS decode_obj_type + IMPORTING + iv_type TYPE rsfindlst-object_cls + RETURNING + VALUE(rv_type) TYPE ty_dev_object-tadir. + + METHODS find_root_packages + CHANGING + ct_objs TYPE ty_dependency_tt + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_ajson DEFINITION + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_ajson. + + ALIASES: + is_empty FOR zif_abapgit_ajson~is_empty, + exists FOR zif_abapgit_ajson~exists, + members FOR zif_abapgit_ajson~members, + get FOR zif_abapgit_ajson~get, + get_boolean FOR zif_abapgit_ajson~get_boolean, + get_integer FOR zif_abapgit_ajson~get_integer, + get_number FOR zif_abapgit_ajson~get_number, + get_date FOR zif_abapgit_ajson~get_date, + get_timestamp FOR zif_abapgit_ajson~get_timestamp, + get_string FOR zif_abapgit_ajson~get_string, + slice FOR zif_abapgit_ajson~slice, + to_abap FOR zif_abapgit_ajson~to_abap, + array_to_string_table FOR zif_abapgit_ajson~array_to_string_table. + + ALIASES: + clear FOR zif_abapgit_ajson~clear, + set FOR zif_abapgit_ajson~set, + setx FOR zif_abapgit_ajson~setx, + set_boolean FOR zif_abapgit_ajson~set_boolean, + set_string FOR zif_abapgit_ajson~set_string, + set_integer FOR zif_abapgit_ajson~set_integer, + set_date FOR zif_abapgit_ajson~set_date, + set_timestamp FOR zif_abapgit_ajson~set_timestamp, + set_null FOR zif_abapgit_ajson~set_null, + delete FOR zif_abapgit_ajson~delete, + touch_array FOR zif_abapgit_ajson~touch_array, + push FOR zif_abapgit_ajson~push, + stringify FOR zif_abapgit_ajson~stringify. + + ALIASES: + clone FOR zif_abapgit_ajson~clone, + filter FOR zif_abapgit_ajson~filter, + map FOR zif_abapgit_ajson~map. + + ALIASES: + mt_json_tree FOR zif_abapgit_ajson~mt_json_tree, + keep_item_order FOR zif_abapgit_ajson~keep_item_order, + format_datetime FOR zif_abapgit_ajson~format_datetime, + to_abap_corresponding_only FOR zif_abapgit_ajson~to_abap_corresponding_only, + freeze FOR zif_abapgit_ajson~freeze. + + CLASS-METHODS parse + IMPORTING + !iv_json TYPE any + !iv_freeze TYPE abap_bool DEFAULT abap_false + !ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + !iv_keep_item_order TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + CLASS-METHODS create_empty " Might be deprecated, prefer using new( ) or create object + IMPORTING + !ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + iv_keep_item_order TYPE abap_bool DEFAULT abap_false + iv_format_datetime TYPE abap_bool DEFAULT abap_true + iv_to_abap_corresponding_only TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson. + + " Experimental ! May change + CLASS-METHODS create_from " TODO, rename to 'from' ? + IMPORTING + !ii_source_json TYPE REF TO zif_abapgit_ajson + !ii_filter TYPE REF TO zif_abapgit_ajson_filter OPTIONAL " Might be deprecated, use filter() instead + !ii_mapper TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL " Might be deprecated, use map() instead + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + + METHODS constructor + IMPORTING + iv_keep_item_order TYPE abap_bool DEFAULT abap_false + iv_format_datetime TYPE abap_bool DEFAULT abap_true + iv_to_abap_corresponding_only TYPE abap_bool DEFAULT abap_false. + + CLASS-METHODS new + IMPORTING + iv_keep_item_order TYPE abap_bool DEFAULT abap_false + iv_format_datetime TYPE abap_bool DEFAULT abap_true + iv_to_abap_corresponding_only TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson. + + CLASS-METHODS normalize_path + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_path) TYPE string. + + PROTECTED SECTION. + + PRIVATE SECTION. + + CLASS-DATA go_float_regex TYPE REF TO cl_abap_regex. + + DATA ms_opts TYPE zif_abapgit_ajson=>ty_opts. + DATA mi_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping. " DEPRECATED, will be removed + + METHODS get_item + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_item) TYPE REF TO zif_abapgit_ajson_types=>ty_node. + METHODS prove_path_exists + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rr_end_node) TYPE REF TO zif_abapgit_ajson_types=>ty_node + RAISING + zcx_abapgit_ajson_error. + METHODS delete_subtree + IMPORTING + iv_path TYPE string + iv_name TYPE string + ir_parent TYPE REF TO zif_abapgit_ajson_types=>ty_node OPTIONAL + RETURNING + VALUE(rs_top_node) TYPE zif_abapgit_ajson_types=>ty_node. + METHODS read_only_watchdog + RAISING + zcx_abapgit_ajson_error. +ENDCLASS. +CLASS zcl_abapgit_ajson_filter_lib DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS create_empty_filter + RETURNING + VALUE(ri_filter) TYPE REF TO zif_abapgit_ajson_filter + RAISING + zcx_abapgit_ajson_error . + CLASS-METHODS create_path_filter + IMPORTING + !it_skip_paths TYPE string_table OPTIONAL + !iv_skip_paths TYPE string OPTIONAL + !iv_pattern_search TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_filter) TYPE REF TO zif_abapgit_ajson_filter + RAISING + zcx_abapgit_ajson_error . + CLASS-METHODS create_and_filter + IMPORTING + !it_filters TYPE zif_abapgit_ajson_filter=>ty_filter_tab + RETURNING + VALUE(ri_filter) TYPE REF TO zif_abapgit_ajson_filter + RAISING + zcx_abapgit_ajson_error . + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS kHGwlpuwVGRXmbkWZJMoWRsLzEdjUi DEFINITION DEFERRED. +CLASS kHGwlpuwVGRXmbkWZJMorCLylKulMM DEFINITION DEFERRED. +CLASS kHGwlpuwVGRXmbkWZJMooAlevhaDMg DEFINITION DEFERRED. +CLASS kHGwlpuwVGRXmbkWZJMoYWDnXPYsQA DEFINITION DEFERRED. +CLASS kHGwlpuwVGRXmbkWZJMoIaLFAtEmIg DEFINITION DEFERRED. +CLASS kHGwlpuwVGRXmbkWZJMoayhtkOTSGN DEFINITION DEFERRED. +CLASS kHGwlpuwVGRXmbkWZJMocwrelrEIET DEFINITION DEFERRED. +CLASS kHGwlpuwVGRXmbkWZJMoTFhfUGDgXz DEFINITION DEFERRED. +* renamed: zcl_abapgit_ajson_mapping :: lcl_mapping_fields +CLASS kHGwlpuwVGRXmbkWZJMoTFhfUGDgXz DEFINITION. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + + METHODS constructor + IMPORTING + it_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields OPTIONAL. + + PROTECTED SECTION. + + PRIVATE SECTION. + DATA mt_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields. + +ENDCLASS. + +* renamed: zcl_abapgit_ajson_mapping :: lcl_rename +CLASS kHGwlpuwVGRXmbkWZJMocwrelrEIET DEFINITION. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + + METHODS constructor + IMPORTING + it_rename_map TYPE zif_abapgit_ajson_mapping~tty_rename_map + iv_rename_by TYPE i. + + PROTECTED SECTION. + + PRIVATE SECTION. + DATA mt_rename_map TYPE zif_abapgit_ajson_mapping~tty_rename_map. + DATA mv_rename_by TYPE i. + +ENDCLASS. + +* renamed: zcl_abapgit_ajson_mapping :: lcl_mapping_to_upper +CLASS kHGwlpuwVGRXmbkWZJMoayhtkOTSGN DEFINITION. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + + METHODS constructor + IMPORTING + it_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields OPTIONAL. + + PROTECTED SECTION. + + PRIVATE SECTION. + DATA mi_mapping_fields TYPE REF TO zif_abapgit_ajson_mapping. + +ENDCLASS. +* renamed: zcl_abapgit_ajson_mapping :: lcl_mapping_to_lower +CLASS kHGwlpuwVGRXmbkWZJMoIaLFAtEmIg DEFINITION. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + + METHODS constructor + IMPORTING + it_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields OPTIONAL. + + PROTECTED SECTION. + + PRIVATE SECTION. + DATA mi_mapping_fields TYPE REF TO zif_abapgit_ajson_mapping. + +ENDCLASS. +* renamed: zcl_abapgit_ajson_mapping :: lcl_mapping_camel +CLASS kHGwlpuwVGRXmbkWZJMoYWDnXPYsQA DEFINITION. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + + METHODS constructor + IMPORTING + it_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields OPTIONAL + iv_first_json_upper TYPE abap_bool DEFAULT abap_true. + + PROTECTED SECTION. + + PRIVATE SECTION. + DATA mv_first_json_upper TYPE abap_bool. + DATA mi_mapping_fields TYPE REF TO zif_abapgit_ajson_mapping. + +ENDCLASS. + +* renamed: zcl_abapgit_ajson_mapping :: lcl_compound_mapper +CLASS kHGwlpuwVGRXmbkWZJMooAlevhaDMg DEFINITION. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + + METHODS constructor + IMPORTING + it_queue TYPE zif_abapgit_ajson_mapping=>ty_table_of. + + PROTECTED SECTION. + + PRIVATE SECTION. + DATA mt_queue TYPE zif_abapgit_ajson_mapping=>ty_table_of. + +ENDCLASS. + +* renamed: zcl_abapgit_ajson_mapping :: lcl_to_snake +CLASS kHGwlpuwVGRXmbkWZJMorCLylKulMM DEFINITION. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. +ENDCLASS. + +* renamed: zcl_abapgit_ajson_mapping :: lcl_to_camel +CLASS kHGwlpuwVGRXmbkWZJMoWRsLzEdjUi DEFINITION. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + METHODS constructor + IMPORTING + iv_first_json_upper TYPE abap_bool. + PRIVATE SECTION. + DATA mv_first_json_upper TYPE abap_bool. +ENDCLASS. + +CLASS zcl_abapgit_ajson_mapping DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CONSTANTS: + BEGIN OF rename_by, + attr_name TYPE i VALUE 0, + full_path TYPE i VALUE 1, + pattern TYPE i VALUE 2, + " regex type i value 3, " TODO add if needed in future + END OF rename_by. + + CLASS-METHODS create_camel_case " DEPRECATED + IMPORTING + it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL + iv_first_json_upper TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_upper_case + IMPORTING + it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_lower_case + IMPORTING + it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_field_mapping " DEPRECATED + IMPORTING + it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_rename + IMPORTING + it_rename_map TYPE zif_abapgit_ajson_mapping=>tty_rename_map + iv_rename_by TYPE i DEFAULT rename_by-attr_name + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_compound_mapper + IMPORTING + ii_mapper1 TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + ii_mapper2 TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + ii_mapper3 TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + it_more TYPE zif_abapgit_ajson_mapping=>ty_table_of OPTIONAL + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_to_snake_case + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_to_camel_case + IMPORTING + iv_first_json_upper TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + PROTECTED SECTION. + + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_ajson_ref_init_lib DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS create_path_refs_init + IMPORTING + !it_data_refs TYPE zif_abapgit_ajson_ref_init=>tty_data_refs + RETURNING + VALUE(ri_refs_init) TYPE REF TO zif_abapgit_ajson_ref_init + RAISING + zcx_abapgit_ajson_error. + +ENDCLASS. +CLASS zcl_abapgit_ajson_utilities DEFINITION + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS new + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson_utilities. + METHODS diff + IMPORTING + !iv_json_a TYPE string OPTIONAL + !iv_json_b TYPE string OPTIONAL + !io_json_a TYPE REF TO zif_abapgit_ajson OPTIONAL + !io_json_b TYPE REF TO zif_abapgit_ajson OPTIONAL + !iv_keep_empty_arrays TYPE abap_bool DEFAULT abap_false + EXPORTING + !eo_insert TYPE REF TO zif_abapgit_ajson + !eo_delete TYPE REF TO zif_abapgit_ajson + !eo_change TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + METHODS merge + IMPORTING + !iv_json_a TYPE string OPTIONAL + !iv_json_b TYPE string OPTIONAL + !io_json_a TYPE REF TO zif_abapgit_ajson OPTIONAL + !io_json_b TYPE REF TO zif_abapgit_ajson OPTIONAL + !iv_keep_empty_arrays TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + METHODS sort + IMPORTING + !iv_json TYPE string OPTIONAL + !io_json TYPE REF TO zif_abapgit_ajson OPTIONAL + RETURNING + VALUE(rv_sorted) TYPE string + RAISING + zcx_abapgit_ajson_error. + METHODS is_equal + IMPORTING + !iv_json_a TYPE string OPTIONAL + !iv_json_b TYPE string OPTIONAL + !ii_json_a TYPE REF TO zif_abapgit_ajson OPTIONAL + !ii_json_b TYPE REF TO zif_abapgit_ajson OPTIONAL + RETURNING + VALUE(rv_yes) TYPE abap_bool + RAISING + zcx_abapgit_ajson_error. + CLASS-METHODS iterate_array + IMPORTING + ii_json TYPE REF TO zif_abapgit_ajson + iv_path TYPE string + RETURNING + VALUE(ri_iterator) TYPE REF TO zif_abapgit_ajson_iterator + RAISING + zcx_abapgit_ajson_error. + CLASS-METHODS iterate_object + IMPORTING + ii_json TYPE REF TO zif_abapgit_ajson + iv_path TYPE string + RETURNING + VALUE(ri_iterator) TYPE REF TO zif_abapgit_ajson_iterator + RAISING + zcx_abapgit_ajson_error. + + PROTECTED SECTION. + + PRIVATE SECTION. + + DATA mo_json_a TYPE REF TO zif_abapgit_ajson. + DATA mo_json_b TYPE REF TO zif_abapgit_ajson. + DATA mo_insert TYPE REF TO zif_abapgit_ajson. + DATA mo_delete TYPE REF TO zif_abapgit_ajson. + DATA mo_change TYPE REF TO zif_abapgit_ajson. + + METHODS normalize_input + IMPORTING + !iv_json TYPE string OPTIONAL + !io_json TYPE REF TO zif_abapgit_ajson OPTIONAL + RETURNING + VALUE(ro_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + METHODS diff_a_b + IMPORTING + !iv_path TYPE string + RAISING + zcx_abapgit_ajson_error. + METHODS diff_b_a + IMPORTING + !iv_path TYPE string + !iv_array TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_ajson_error. + METHODS delete_empty_nodes + IMPORTING + !io_json TYPE REF TO zif_abapgit_ajson + !iv_keep_empty_arrays TYPE abap_bool + RAISING + zcx_abapgit_ajson_error. + +ENDCLASS. +CLASS zcl_abapgit_aff_factory DEFINITION + . + PUBLIC SECTION. + CLASS-METHODS get_registry + RETURNING + VALUE(ri_registry) TYPE REF TO zif_abapgit_aff_registry. + PRIVATE SECTION. + CLASS-DATA gi_registry TYPE REF TO zif_abapgit_aff_registry. +ENDCLASS. +CLASS zcl_abapgit_aff_registry DEFINITION + FINAL + CREATE PRIVATE + FRIENDS ZCL_abapgit_aff_factory . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_aff_registry. + + CONSTANTS c_aff_feature TYPE string VALUE 'AFF'. + + METHODS constructor. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_registry_entry, + obj_type TYPE tadir-object, + experimental TYPE abap_bool, + END OF ty_registry_entry. + + CLASS-DATA: + gt_registry TYPE HASHED TABLE OF ty_registry_entry WITH UNIQUE KEY obj_type. + + DATA mv_aff_enabled TYPE abap_bool. + + CLASS-METHODS initialize_registry_table. + + CLASS-METHODS: + register + IMPORTING + iv_obj_type TYPE tadir-object + iv_experimental TYPE abap_bool DEFAULT abap_false. + +ENDCLASS. +CLASS zcl_abapgit_json_handler DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_json_abap_mapping, + json TYPE string, + abap TYPE string, + END OF ty_json_abap_mapping . + TYPES: + ty_json_abap_mappings TYPE STANDARD TABLE OF ty_json_abap_mapping WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_enum_mapping, + path TYPE string, + mappings TYPE ty_json_abap_mappings, + END OF ty_enum_mapping . + TYPES: + ty_enum_mappings TYPE STANDARD TABLE OF ty_enum_mapping WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_path_value_pair, + path TYPE string, + value TYPE string, + END OF ty_path_value_pair . + TYPES: + ty_skip_paths TYPE STANDARD TABLE OF ty_path_value_pair WITH KEY path . + + "! Serializes data to xstring. Type of data is specified in the + "! implementing class. + "! + "! @parameter iv_data | data to be serialized + "! @parameter iv_enum_mappings | ABAP/JSON value mappings + "! @parameter iv_skip_paths | path/value pairs to be skipped during serialization + "! @parameter rv_result | serialized data + METHODS serialize + IMPORTING + !iv_data TYPE data + !iv_enum_mappings TYPE ty_enum_mappings OPTIONAL + !iv_skip_paths TYPE ty_skip_paths OPTIONAL + RETURNING + VALUE(rv_result) TYPE xstring + RAISING + cx_static_check . + "! Deserializes xstring into data. The type of data is specified in + "! the implementing class + "! + "! @parameter iv_content | xstring to be deserialized + "! @parameter iv_defaults | path-value pairs that apply if value is initial + "! @parameter ev_data | data of the xstring + METHODS deserialize + IMPORTING + !iv_content TYPE string + !iv_defaults TYPE ty_skip_paths OPTIONAL + !iv_enum_mappings TYPE ty_enum_mappings OPTIONAL + EXPORTING + !ev_data TYPE data + RAISING + cx_static_check . + PROTECTED SECTION. + + PRIVATE SECTION. + + METHODS: + map2json_original_language + CHANGING co_ajson TYPE REF TO zif_abapgit_ajson + RAISING zcx_abapgit_ajson_error, + map2json_custom_enum + IMPORTING it_enum_mappings TYPE ty_enum_mappings + CHANGING co_ajson TYPE REF TO zif_abapgit_ajson + RAISING zcx_abapgit_ajson_error, + map2json_abap_language_version + CHANGING co_ajson TYPE REF TO zif_abapgit_ajson + RAISING zcx_abapgit_ajson_error, + "! Get the enum mapping from object handler, as other enums as well + map2abap_abap_language_version + CHANGING co_ajson TYPE REF TO zif_abapgit_ajson + RAISING zcx_abapgit_ajson_error, + "! For deserialization + map2abap_original_language + CHANGING co_ajson TYPE REF TO zif_abapgit_ajson + RAISING zcx_abapgit_ajson_error, + "! For deserialization + set_defaults + IMPORTING it_defaults TYPE ty_skip_paths + CHANGING co_ajson TYPE REF TO zif_abapgit_ajson + RAISING zcx_abapgit_ajson_error, + map2abap_custom_enum + IMPORTING it_enum_mappings TYPE ty_enum_mappings + CHANGING co_ajson TYPE REF TO zif_abapgit_ajson + RAISING zcx_abapgit_ajson_error. + +ENDCLASS. +CLASS zcl_abapgit_json_path DEFINITION CREATE PUBLIC. + PUBLIC SECTION. + METHODS: serialize + IMPORTING iv_json TYPE string + RETURNING VALUE(rt_result) TYPE string_table + RAISING zcx_abapgit_exception. + METHODS: deserialize + IMPORTING it_json_path TYPE string_table + RETURNING VALUE(rv_result) TYPE string + RAISING zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_dependencies DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS resolve + CHANGING + !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_dependency, + depname TYPE dd02l-tabname, + deptyp TYPE c LENGTH 4, + deplocal TYPE dd02l-as4local, + refname TYPE dd02l-tabname, + reftyp TYPE c LENGTH 4, + kind TYPE c LENGTH 1, + END OF ty_dependency . + TYPES: + ty_dedenpencies TYPE STANDARD TABLE OF ty_dependency + WITH NON-UNIQUE DEFAULT KEY . + TYPES: + BEGIN OF ty_item, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + devclass TYPE devclass, + END OF ty_item . + + CLASS-METHODS resolve_ddic + CHANGING + !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_ddls_dependencies + IMPORTING + iv_ddls_name TYPE tadir-obj_name + RETURNING + VALUE(rt_dependency) TYPE ty_dedenpencies. + CLASS-METHODS resolve_packages + CHANGING + ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. +ENDCLASS. +CLASS zcl_abapgit_file_deserialize DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS get_results + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + RETURNING + VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + + PRIVATE SECTION. + + CLASS-METHODS filter_files_to_deserialize + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + RETURNING + VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt . + CLASS-METHODS prioritize_deser + IMPORTING + !ii_log TYPE REF TO zif_abapgit_log + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RETURNING + VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt . + CLASS-METHODS map_results_to_items + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RETURNING + VALUE(rt_items) TYPE zif_abapgit_definitions=>ty_items_tt . +ENDCLASS. +CLASS zcl_abapgit_filename_logic DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CONSTANTS: + BEGIN OF c_package_file, + obj_name TYPE c LENGTH 7 VALUE 'package', + sep1 TYPE c LENGTH 1 VALUE '.', + obj_type TYPE c LENGTH 4 VALUE 'devc', + sep2 TYPE c LENGTH 1 VALUE '.', + extension TYPE c LENGTH 3 VALUE 'xml', + END OF c_package_file. + + CONSTANTS: + BEGIN OF c_json_file, + extension TYPE c LENGTH 4 VALUE 'json', + END OF c_json_file. + + CLASS-METHODS detect_obj_definition + IMPORTING + !iv_type TYPE string + !iv_ext TYPE string + EXPORTING + !ev_is_xml TYPE abap_bool + !ev_is_json TYPE abap_bool. + + CLASS-METHODS is_obj_definition_file + IMPORTING + !iv_filename TYPE string + RETURNING + VALUE(rv_yes) TYPE abap_bool. + + CLASS-METHODS file_to_object + IMPORTING + !iv_filename TYPE string + !iv_path TYPE string + !iv_devclass TYPE devclass OPTIONAL + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + EXPORTING + !es_item TYPE zif_abapgit_definitions=>ty_item + !ev_is_xml TYPE abap_bool + !ev_is_json TYPE abap_bool + RAISING + zcx_abapgit_exception . + + CLASS-METHODS i18n_file_to_object + IMPORTING + !iv_filename TYPE string + !iv_path TYPE string + EXPORTING + !es_item TYPE zif_abapgit_definitions=>ty_item + !ev_lang TYPE laiso + !ev_ext TYPE string + RAISING + zcx_abapgit_exception . + + CLASS-METHODS object_to_file + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_ext TYPE string + !iv_extra TYPE clike OPTIONAL + RETURNING + VALUE(rv_filename) TYPE string . + + CLASS-METHODS object_to_i18n_file + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_lang_suffix TYPE string + !iv_ext TYPE string + RETURNING + VALUE(rv_filename) TYPE string. + + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-METHODS name_escape + IMPORTING + !iv_name TYPE csequence + RETURNING + VALUE(rv_name) TYPE string. + + CLASS-METHODS name_unescape + IMPORTING + !iv_name TYPE csequence + RETURNING + VALUE(rv_name) TYPE string. + + CLASS-METHODS map_filename_to_object + IMPORTING + !iv_item_part_of_filename TYPE string + !iv_path TYPE string + !iv_package TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + CHANGING + cs_item TYPE zif_abapgit_definitions=>ty_item + RAISING + zcx_abapgit_exception. + + CLASS-METHODS map_object_to_filename + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_ext TYPE string + !iv_extra TYPE clike + CHANGING + cv_item_part_of_filename TYPE string + RAISING + zcx_abapgit_exception. + + CLASS-METHODS get_lang_and_ext + IMPORTING + iv_filename TYPE string + EXPORTING + ev_lang TYPE laiso + ev_ext TYPE string + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_folder_logic DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS package_to_path + IMPORTING + !iv_top TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !iv_package TYPE devclass + RETURNING + VALUE(rv_path) TYPE string + RAISING + zcx_abapgit_exception . + METHODS path_to_package + IMPORTING + !iv_top TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !iv_path TYPE string + !iv_create_if_not_exists TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rv_package) TYPE devclass + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_instance + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_folder_logic . + PROTECTED SECTION. + + METHODS get_parent + IMPORTING + !iv_top TYPE devclass + !iv_package TYPE devclass + RETURNING + VALUE(rv_parent) TYPE devclass + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + TYPES: + BEGIN OF ty_devclass_info, + devclass TYPE devclass, + namespace TYPE namespace, + parentcl TYPE parentcl, + END OF ty_devclass_info . + TYPES: + ty_devclass_info_tt TYPE SORTED TABLE OF ty_devclass_info + WITH UNIQUE KEY devclass . + DATA mt_top_subpackages TYPE ty_devclass_info_tt . + DATA mt_parent TYPE ty_devclass_info_tt . +ENDCLASS. +CLASS zcl_abapgit_item_graph DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !it_items TYPE zif_abapgit_definitions=>ty_items_tt . + METHODS add_edge + IMPORTING + !is_from TYPE zif_abapgit_definitions=>ty_item + !is_to TYPE zif_abapgit_definitions=>ty_item . + METHODS has_vertices + RETURNING + VALUE(rv_bool) TYPE abap_bool . + METHODS get_next + IMPORTING + !ii_log TYPE REF TO zif_abapgit_log + RETURNING + VALUE(rs_item) TYPE zif_abapgit_definitions=>ty_item . + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_edge, + from TYPE zif_abapgit_definitions=>ty_item, + to TYPE zif_abapgit_definitions=>ty_item, + END OF ty_edge. + + DATA mt_vertices TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_item WITH DEFAULT KEY. + DATA mt_edges TYPE STANDARD TABLE OF ty_edge WITH DEFAULT KEY + WITH NON-UNIQUE SORTED KEY sec_to COMPONENTS to + WITH NON-UNIQUE SORTED KEY sec_from COMPONENTS from. + DATA mv_warning TYPE abap_bool. + + METHODS remove_vertex IMPORTING iv_index TYPE i. +ENDCLASS. +CLASS zcl_abapgit_objects_activation DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS add + IMPORTING + !iv_type TYPE trobjtype + !iv_name TYPE clike + !iv_delete TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception . + CLASS-METHODS add_item + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RAISING + zcx_abapgit_exception . + CLASS-METHODS activate + IMPORTING + !iv_ddic TYPE abap_bool DEFAULT abap_false + !ii_log TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + CLASS-METHODS clear . + CLASS-METHODS is_ddic_type + IMPORTING + !iv_obj_type TYPE trobjtype + RETURNING + VALUE(rv_result) TYPE abap_bool . + CLASS-METHODS is_active + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RETURNING + VALUE(rv_active) TYPE abap_bool + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_classes, + object TYPE trobjtype, + clsname TYPE seoclsname, + END OF ty_classes. + + CONSTANTS: + c_domain TYPE c LENGTH 9 VALUE 'DOMA DOMD', + c_types TYPE c LENGTH 55 VALUE 'DTEL DTED TABL TABD SQLT SQLD TTYP TTYD VIEW VIED DRTY', + c_technset TYPE c LENGTH 24 VALUE 'TABT VIET SQTT INDX XINX', + c_f4_objects TYPE c LENGTH 35 VALUE 'SHLP SHLD MCOB MCOD MACO MACD MCID', + c_enqueue TYPE c LENGTH 9 VALUE 'ENQU ENQD', + c_sqsc TYPE c LENGTH 4 VALUE 'SQSC', + c_stob TYPE c LENGTH 4 VALUE 'STOB', + c_ntab TYPE c LENGTH 14 VALUE 'NTTT NTTB NTDT', + c_ddls TYPE c LENGTH 24 VALUE 'DDLS DRUL DTDC DTEB', + c_switches TYPE c LENGTH 24 VALUE 'SF01 SF02 SFSW SFBS SFBF', + c_para TYPE c LENGTH 4 VALUE 'PARA', " can be referenced by DTEL + c_enhd TYPE c LENGTH 4 VALUE 'ENHD', + c_scalarfunc TYPE c LENGTH 9 VALUE 'DSFD DSFI', + c_aspect TYPE c LENGTH 4 VALUE 'DRAS'. + + CLASS-DATA: + gt_classes TYPE STANDARD TABLE OF ty_classes WITH DEFAULT KEY . + CLASS-DATA: + gt_objects TYPE TABLE OF dwinactiv . + + CLASS-METHODS update_where_used + IMPORTING + !ii_log TYPE REF TO zif_abapgit_log. + CLASS-METHODS use_new_activation_logic + RETURNING + VALUE(rv_use_new_activation_logic) TYPE abap_bool . + CLASS-METHODS activate_new + IMPORTING + !iv_ddic TYPE abap_bool DEFAULT abap_false + !ii_log TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + CLASS-METHODS activate_old + IMPORTING + !iv_ddic TYPE abap_bool DEFAULT abap_false + !ii_log TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + CLASS-METHODS activate_ddic + IMPORTING + !ii_log TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + CLASS-METHODS add_errors_and_warnings_to_log + IMPORTING + !iv_logname TYPE ddmass-logname + !ii_log TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + CLASS-METHODS add_activation_errors_to_log + IMPORTING + !io_checklist TYPE REF TO cl_wb_checklist + !ii_log TYPE REF TO zif_abapgit_log + RETURNING + VALUE(rv_try_again) TYPE abap_bool + RAISING + zcx_abapgit_exception . + CLASS-METHODS is_non_ddic_active + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RETURNING + VALUE(rv_active) TYPE abap_bool + RAISING + zcx_abapgit_exception . + CLASS-METHODS is_ddic_active + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RETURNING + VALUE(rv_active) TYPE abap_bool + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_ddic_type + IMPORTING + !iv_obj_type TYPE clike + !iv_obj_name TYPE clike + EXPORTING + !ev_type TYPE ddobjtyp + !ev_name TYPE ddobjname + !ev_id TYPE ddobjectid + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_objects_check DEFINITION + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS class_constructor. + + CLASS-METHODS deserialize_checks + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks + RAISING + zcx_abapgit_exception. + + CLASS-METHODS checks_adjust + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks + CHANGING + !ct_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gi_exit TYPE REF TO zif_abapgit_exit. + + CLASS-METHODS adjust_result + IMPORTING + !iv_txt TYPE string + !it_overwrite_old TYPE zif_abapgit_definitions=>ty_overwrite_tt + !it_overwrite_new TYPE zif_abapgit_definitions=>ty_overwrite_tt + CHANGING + !ct_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS warning_overwrite_adjust + IMPORTING + !it_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt + CHANGING + !ct_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS warning_overwrite_find + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RETURNING + VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt. + + CLASS-METHODS warning_package_adjust + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !it_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt + CHANGING + !ct_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS warning_package_find + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS warning_data_loss_adjust + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !it_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt + CHANGING + !ct_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS warning_data_loss_find + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RETURNING + VALUE(rt_overwrite) TYPE zif_abapgit_definitions=>ty_overwrite_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS determine_transport_request + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + iv_transport_type TYPE zif_abapgit_definitions=>ty_transport_type + RETURNING + VALUE(rv_transport_request) TYPE trkorr. + + CLASS-METHODS check_multiple_files + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_objects_compare DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS get_comparator + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + RETURNING + VALUE(ri_comparator) TYPE REF TO zif_abapgit_comparator. + + CLASS-METHODS get_result + IMPORTING + ii_comparator TYPE REF TO zif_abapgit_comparator + iv_filename TYPE string + it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + RETURNING + VALUE(rv_result) TYPE string + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_objects_files DEFINITION + CREATE PRIVATE. + + PUBLIC SECTION. + + CLASS-METHODS new + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_path TYPE string OPTIONAL + RETURNING + VALUE(ro_files) TYPE REF TO zcl_abapgit_objects_files. + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_path TYPE string OPTIONAL . + METHODS add_string + IMPORTING + !iv_extra TYPE clike OPTIONAL + !iv_ext TYPE string + !iv_string TYPE string + RAISING + zcx_abapgit_exception . + METHODS read_string + IMPORTING + !iv_extra TYPE clike OPTIONAL + !iv_ext TYPE string + RETURNING + VALUE(rv_string) TYPE string + RAISING + zcx_abapgit_exception . + METHODS add_xml + IMPORTING + !iv_extra TYPE clike OPTIONAL + !ii_xml TYPE REF TO zif_abapgit_xml_output + !iv_normalize TYPE abap_bool DEFAULT abap_true + !is_metadata TYPE zif_abapgit_definitions=>ty_metadata OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS read_xml + IMPORTING + !iv_extra TYPE clike OPTIONAL + RETURNING + VALUE(ri_xml) TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS read_abap + IMPORTING + !iv_extra TYPE clike OPTIONAL + !iv_error TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rt_abap) TYPE abaptxt255_tab + RAISING + zcx_abapgit_exception . + METHODS add_abap + IMPORTING + !iv_extra TYPE clike OPTIONAL + !it_abap TYPE STANDARD TABLE + RAISING + zcx_abapgit_exception . + METHODS add + IMPORTING + !is_file TYPE zif_abapgit_git_definitions=>ty_file . + METHODS add_raw + IMPORTING + !iv_extra TYPE clike OPTIONAL + !iv_ext TYPE string + !iv_data TYPE xstring. + METHODS read_raw + IMPORTING + !iv_extra TYPE clike OPTIONAL + !iv_ext TYPE string + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_abapgit_exception . + METHODS get_files + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt . + METHODS set_files + IMPORTING + !it_files TYPE zif_abapgit_git_definitions=>ty_files_tt . + METHODS get_accessed_files + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt . + METHODS contains_file + IMPORTING + !iv_extra TYPE clike OPTIONAL + !iv_ext TYPE string + RETURNING + VALUE(rv_present) TYPE abap_bool . + METHODS get_file_pattern + RETURNING + VALUE(rv_pattern) TYPE string . + METHODS is_json_metadata + RETURNING + VALUE(rv_result) TYPE abap_bool. + METHODS add_i18n_file + IMPORTING + !ii_i18n_file TYPE REF TO zif_abapgit_i18n_file + RAISING + zcx_abapgit_exception . + METHODS read_i18n_files + RETURNING + VALUE(rt_i18n_files) TYPE zif_abapgit_i18n_file=>ty_table_of + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + + METHODS read_file + IMPORTING + !iv_filename TYPE string + !iv_error TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + + DATA ms_item TYPE zif_abapgit_definitions=>ty_item . + DATA mt_accessed_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt . + DATA mt_files TYPE zif_abapgit_git_definitions=>ty_files_tt . + DATA mv_path TYPE string . + + METHODS mark_accessed + IMPORTING + !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path + !iv_file TYPE zif_abapgit_git_definitions=>ty_file-filename + !iv_sha1 TYPE zif_abapgit_git_definitions=>ty_file-sha1. + +ENDCLASS. +CLASS zcl_abapgit_serialize DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !io_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit OPTIONAL + !is_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS on_end_of_task + IMPORTING + !p_task TYPE clike ##NEEDED. + METHODS serialize + IMPORTING + !iv_package TYPE devclass OPTIONAL + !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + !iv_force_sequential TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception . + METHODS files_local + IMPORTING + !iv_package TYPE devclass + !ii_log TYPE REF TO zif_abapgit_log + !it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt OPTIONAL + !ii_data_config TYPE REF TO zif_abapgit_data_config OPTIONAL + RETURNING + VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + + TYPES: + BEGIN OF ty_unsupported_count, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + count TYPE i, + END OF ty_unsupported_count . + TYPES: + ty_unsupported_count_tt TYPE HASHED TABLE OF ty_unsupported_count WITH UNIQUE KEY obj_type . + TYPES: + ty_char32 TYPE c LENGTH 32 . + + CLASS-DATA gv_max_processes TYPE i . + DATA mt_files TYPE zif_abapgit_definitions=>ty_files_item_tt . + DATA mv_free TYPE i . + DATA mi_log TYPE REF TO zif_abapgit_log . + DATA mv_group TYPE rzlli_apcl . + DATA mo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit. + DATA ms_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings. + DATA ms_i18n_params TYPE zif_abapgit_definitions=>ty_i18n_params. + DATA mo_abap_language_version TYPE REF TO zcl_abapgit_abap_language_vers. + DATA mt_wo_translation_patterns TYPE string_table. + + METHODS add_apack + IMPORTING + !iv_package TYPE devclass + CHANGING + !ct_files TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception . + METHODS add_data + IMPORTING + !ii_data_config TYPE REF TO zif_abapgit_data_config + CHANGING + !ct_files TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception . + METHODS add_dot_abapgit + CHANGING + !ct_files TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception . + METHODS add_to_return + IMPORTING + !iv_path TYPE string + !is_file_item TYPE zif_abapgit_objects=>ty_serialization . + METHODS run_parallel + IMPORTING + !is_tadir TYPE zif_abapgit_definitions=>ty_tadir + !iv_task TYPE ty_char32 + RAISING + zcx_abapgit_exception . + METHODS run_sequential + IMPORTING + !is_tadir TYPE zif_abapgit_definitions=>ty_tadir + RAISING + zcx_abapgit_exception . + METHODS add_objects + IMPORTING + !iv_package TYPE devclass + !ii_log TYPE REF TO zif_abapgit_log + !it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt OPTIONAL + CHANGING + VALUE(ct_files) TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception . + METHODS determine_rfc_server_group + RETURNING + VALUE(rv_group) TYPE rzlli_apcl + RAISING + zcx_abapgit_exception. + METHODS determine_max_processes + IMPORTING + !iv_force_sequential TYPE abap_bool DEFAULT abap_false + iv_package TYPE devclass + RETURNING + VALUE(rv_processes) TYPE i + RAISING + zcx_abapgit_exception . + METHODS filter_unsupported_objects + CHANGING + !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt . + METHODS filter_ignored_objects + IMPORTING + !iv_package TYPE devclass + CHANGING + !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + + METHODS is_parallelization_possible + RETURNING + VALUE(rv_result) TYPE abap_bool. + + METHODS is_no_parallel + IMPORTING + !iv_object_type TYPE tadir-object + RETURNING + VALUE(rv_result) TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_tadir DEFINITION + FINAL + CREATE PRIVATE + FRIENDS ZCL_abapgit_factory . + + PUBLIC SECTION. + INTERFACES zif_abapgit_tadir . + + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS check_exists + IMPORTING + !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RETURNING + VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + METHODS build + IMPORTING + !iv_package TYPE tadir-devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false + !iv_only_local_objects TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + METHODS select_objects + IMPORTING + !iv_package TYPE tadir-devclass + !iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false + !iv_only_local_objects TYPE abap_bool + EXPORTING + !et_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt + !et_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + METHODS add_local_packages + IMPORTING + !it_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt + CHANGING + !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + METHODS add_namespaces + IMPORTING + !iv_package TYPE devclass + CHANGING + !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + METHODS add_namespace + IMPORTING + !iv_package TYPE devclass + !iv_object TYPE csequence + CHANGING + !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + !ct_tadir_nspc TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + METHODS determine_path + IMPORTING + !iv_package TYPE tadir-devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + CHANGING + !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_ecatt_config_downl DEFINITION + INHERITING FROM cl_apl_ecatt_config_download + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_download. + + METHODS: + download REDEFINITION. + + PROTECTED SECTION. + METHODS: + download_data REDEFINITION. + + PRIVATE SECTION. + DATA: + mv_xml_stream TYPE xstring. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_config_upl DEFINITION + INHERITING FROM cl_apl_ecatt_config_upload + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_upload. + + PROTECTED SECTION. + METHODS: + upload_data_from_stream REDEFINITION. + + PRIVATE SECTION. + DATA: mv_external_xml TYPE xstring. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_data_downl DEFINITION + INHERITING FROM cl_apl_ecatt_data_download + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_download. + + METHODS: + download + REDEFINITION. + + PROTECTED SECTION. + METHODS: + download_data REDEFINITION. + + PRIVATE SECTION. + DATA: + mv_xml_stream TYPE xstring. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_data_upload DEFINITION + INHERITING FROM cl_apl_ecatt_data_upload + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_upload. + + METHODS upload REDEFINITION. + + PROTECTED SECTION. + METHODS: + upload_data_from_stream REDEFINITION. + + PRIVATE SECTION. + DATA: mv_external_xml TYPE xstring, + BEGIN OF ms_current_object, + s_obj_type TYPE etobj_type, + d_obj_name TYPE etobjdname, + d_obj_ver TYPE etobjdver, + END OF ms_current_object, + mx_ecatt_apl TYPE REF TO cx_ecatt_apl. + METHODS on_ev_object_saved FOR EVENT ev_object_saved OF cl_apl_ecatt_object IMPORTING ex_ecatt_object. +ENDCLASS. +CLASS zcl_abapgit_ecatt_helper DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + CLASS-METHODS: + build_xml_of_object + IMPORTING + iv_object_name TYPE etobj_name + iv_object_version TYPE etobj_ver + iv_object_type TYPE etobj_type + io_download TYPE REF TO cl_apl_ecatt_download + RETURNING + VALUE(rv_xml_stream) TYPE xstring + RAISING + zcx_abapgit_exception, + + download_data + IMPORTING + ii_template_over_all TYPE REF TO if_ixml_document + RETURNING + VALUE(rv_xml_stream) TYPE xstring, + + upload_data_from_stream + IMPORTING + iv_xml_stream TYPE xstring + RETURNING + VALUE(ri_template_over_all) TYPE REF TO if_ixml_document + RAISING + cx_ecatt_apl. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: + c_xml TYPE i VALUE 1. " downport of if_apl_ecatt_xml=>co_xml + +ENDCLASS. +CLASS zcl_abapgit_ecatt_script_downl DEFINITION + INHERITING FROM cl_apl_ecatt_script_download + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_download. + + METHODS: + download REDEFINITION. + + PROTECTED SECTION. + METHODS: + download_data REDEFINITION. + + PRIVATE SECTION. + DATA: + mv_xml_stream TYPE xstring, + mi_script_node TYPE REF TO if_ixml_element. + + METHODS: + set_script_to_template + RAISING + cx_ecatt_apl, + + set_control_data_for_tcd + IMPORTING + is_param TYPE etpar_gui + io_params TYPE REF TO cl_apl_ecatt_params + RAISING + cx_ecatt_apl, + + escape_control_data + IMPORTING + ii_element TYPE REF TO if_ixml_element + iv_tabname TYPE string + iv_node TYPE string + RAISING + cx_ecatt_apl, + + set_blob_to_template + RAISING + cx_ecatt_apl, + + set_artmp_to_template + RAISING + cx_ecatt_apl. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_script_upl DEFINITION + INHERITING FROM cl_apl_ecatt_script_upload + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_upload. + + PROTECTED SECTION. + METHODS: + upload_data_from_stream REDEFINITION. + + PRIVATE SECTION. + DATA: mv_external_xml TYPE xstring. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_sp_download DEFINITION + INHERITING FROM cl_apl_ecatt_download + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_download. + + METHODS: + download REDEFINITION. + + PROTECTED SECTION. + METHODS: + download_data REDEFINITION. + + PRIVATE SECTION. + DATA: + mv_xml_stream TYPE xstring. + + METHODS: + set_sp_data_to_template. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_sp_upload DEFINITION + INHERITING FROM cl_apl_ecatt_upload + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_upload. + + METHODS: + upload + REDEFINITION. + + PROTECTED SECTION. + METHODS: + upload_data_from_stream REDEFINITION, + + get_ecatt_sp + RAISING + cx_ecatt_apl . + + PRIVATE SECTION. + DATA: mv_external_xml TYPE xstring. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_system_downl DEFINITION + INHERITING FROM cl_apl_ecatt_systems_download + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_download. + + METHODS: + download REDEFINITION. + + PROTECTED SECTION. + METHODS: + download_data REDEFINITION. + + PRIVATE SECTION. + DATA: + mv_xml_stream TYPE xstring. + + METHODS: + set_systems_data_to_template. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_system_upl DEFINITION + INHERITING FROM cl_apl_ecatt_systems_upload + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_upload. + + PROTECTED SECTION. + METHODS: + upload_data_from_stream REDEFINITION. + + PRIVATE SECTION. + DATA: mv_external_xml TYPE xstring. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_val_obj_down DEFINITION + INHERITING FROM cl_apl_ecatt_download + CREATE PUBLIC. + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_download. + + METHODS: + download REDEFINITION. + + PROTECTED SECTION. + DATA: + mi_objects_node TYPE REF TO if_ixml_element. + + METHODS: + download_data REDEFINITION. + + PRIVATE SECTION. + DATA: + mv_xml_stream TYPE xstring. + + METHODS: + set_ecatt_impl_detail, + set_ecatt_flags, + set_business_msgs. + +ENDCLASS. +CLASS zcl_abapgit_ecatt_val_obj_upl DEFINITION + INHERITING FROM cl_apl_ecatt_upload + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_ecatt_upload. + + METHODS: + upload REDEFINITION. + + PROTECTED SECTION. + METHODS: + upload_data_from_stream REDEFINITION, + + get_business_msgs_from_dom + RAISING + cx_ecatt_apl, + + get_impl_detail_from_dom + RAISING + cx_ecatt_apl, + + get_vo_flags_from_dom + RAISING + cx_ecatt_apl. + + PRIVATE SECTION. + DATA: + mv_external_xml TYPE xstring. + +ENDCLASS. +CLASS zcl_abapgit_object_enho_badi DEFINITION. + + PUBLIC SECTION. + METHODS: constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item. + INTERFACES: zif_abapgit_object_enho. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. + +ENDCLASS. +CLASS zcl_abapgit_object_enho_class DEFINITION + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object_enho. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !io_files TYPE REF TO zcl_abapgit_objects_files. + PROTECTED SECTION. + PRIVATE SECTION. + CLASS-METHODS adjust_generated_comments + CHANGING + ct_source TYPE rswsourcet. + METHODS: + serialize_includes + IMPORTING + io_class TYPE REF TO cl_enh_tool_class + RAISING + zcx_abapgit_exception, + deserialize_includes + IMPORTING + ii_xml TYPE REF TO zif_abapgit_xml_input + io_class TYPE REF TO cl_enh_tool_class + RAISING + zcx_abapgit_exception. + + DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. + DATA: mo_files TYPE REF TO zcl_abapgit_objects_files. + +ENDCLASS. +CLASS zcl_abapgit_object_enho_clif DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS deserialize + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + !io_clif TYPE REF TO cl_enh_tool_clif + RAISING + zcx_abapgit_exception + cx_enh_root . + CLASS-METHODS serialize + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + !io_clif TYPE REF TO cl_enh_tool_clif + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_object_enho_fugr DEFINITION. + + PUBLIC SECTION. + METHODS: constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + io_files TYPE REF TO zcl_abapgit_objects_files. + INTERFACES: zif_abapgit_object_enho. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: ms_item TYPE zif_abapgit_definitions=>ty_item, + mo_files TYPE REF TO zcl_abapgit_objects_files. + +ENDCLASS. +CLASS zcl_abapgit_object_enho_hook DEFINITION. + PUBLIC SECTION. + METHODS: constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + io_files TYPE REF TO zcl_abapgit_objects_files. + + INTERFACES: zif_abapgit_object_enho. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_spaces, + full_name TYPE string, + spaces TYPE STANDARD TABLE OF i WITH DEFAULT KEY, + END OF ty_spaces. + + TYPES: ty_spaces_tt TYPE STANDARD TABLE OF ty_spaces WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_file, + name TYPE string, + file TYPE string, + END OF ty_file. + + TYPES: ty_files TYPE HASHED TABLE OF ty_file WITH UNIQUE KEY name. + + CONSTANTS c_enhancement TYPE string VALUE 'ENHANCEMENT 0 *.' ##NO_TEXT. + CONSTANTS c_endenhancement TYPE string VALUE 'ENDENHANCEMENT.' ##NO_TEXT. + + DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. + DATA: mo_files TYPE REF TO zcl_abapgit_objects_files. + + METHODS add_sources + CHANGING + !ct_enhancements TYPE enh_hook_impl_it + !ct_files TYPE ty_files + RAISING + zcx_abapgit_exception . + METHODS read_sources + CHANGING + !ct_enhancements TYPE enh_hook_impl_it + !ct_files TYPE ty_files + RAISING + zcx_abapgit_exception . + METHODS hook_impl_deserialize + IMPORTING + !it_spaces TYPE ty_spaces_tt + CHANGING + !ct_impl TYPE enh_hook_impl_it + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_enho_intf DEFINITION. + + PUBLIC SECTION. + METHODS: + constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + io_files TYPE REF TO zcl_abapgit_objects_files. + INTERFACES: zif_abapgit_object_enho. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: ms_item TYPE zif_abapgit_definitions=>ty_item, + mo_files TYPE REF TO zcl_abapgit_objects_files. + +ENDCLASS. +CLASS zcl_abapgit_object_enho_wdyc DEFINITION. + + PUBLIC SECTION. + METHODS: constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item. + INTERFACES: zif_abapgit_object_enho. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. + +ENDCLASS. +CLASS zcl_abapgit_object_enho_wdyn DEFINITION. + + PUBLIC SECTION. + METHODS: constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item. + INTERFACES: zif_abapgit_object_enho. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. + +ENDCLASS. +CLASS zcl_abapgit_object_enhs_badi_d DEFINITION. + + PUBLIC SECTION. + INTERFACES: zif_abapgit_object_enhs. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_enhs_hook_d DEFINITION. + + PUBLIC SECTION. + INTERFACES: zif_abapgit_object_enhs. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_hook_defifnition, + pgmid TYPE tadir-pgmid, + obj_name TYPE trobj_name, + obj_type TYPE trobjtype, + main_type TYPE trobjtype, + main_name TYPE eu_aname, + program TYPE progname, + def_hooks TYPE enh_hook_def_ext_it, + END OF ty_hook_defifnition. + +ENDCLASS. +CLASS zcl_abapgit_adt_link DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS jump + IMPORTING + !iv_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name + !iv_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type + !iv_sub_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name OPTIONAL + !iv_line_number TYPE i OPTIONAL + RAISING + zcx_abapgit_exception. + + CLASS-METHODS link_transport + IMPORTING + iv_transport TYPE trkorr + RETURNING + VALUE(rv_link) TYPE string. + + PROTECTED SECTION. + + CLASS-METHODS generate + IMPORTING + !iv_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name + !iv_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type + !iv_sub_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name OPTIONAL + !iv_line_number TYPE i OPTIONAL + RETURNING + VALUE(rv_result) TYPE string + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + + CLASS-METHODS get_adt_objects_and_names + IMPORTING + iv_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name + iv_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type + EXPORTING + eo_adt_uri_mapper TYPE REF TO object + eo_adt_objectref TYPE REF TO object + ev_program TYPE progname + ev_include TYPE progname + RAISING + zcx_abapgit_exception. + + CLASS-METHODS is_adt_jump_possible + IMPORTING + io_object TYPE REF TO cl_wb_object + io_adt TYPE REF TO object + RETURNING + VALUE(rv_is_adt_jump_possible) TYPE abap_bool + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_jumper DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_jumper. + + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS jump_tr + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RETURNING + VALUE(rv_exit) TYPE abap_bool. + + METHODS jump_wb + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_new_window TYPE abap_bool + RETURNING + VALUE(rv_exit) TYPE abap_bool. + + METHODS jump_wb_line + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_sub_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name + !iv_sub_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type + !iv_line_number TYPE i + !iv_new_window TYPE abap_bool + RETURNING + VALUE(rv_exit) TYPE abap_bool. + + METHODS jump_bw + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_new_window TYPE abap_bool + RETURNING + VALUE(rv_exit) TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_oo_base DEFINITION + ABSTRACT + CREATE PROTECTED. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_oo_object_fnc . + CONSTANTS c_cp_program_type TYPE c LENGTH 1 VALUE 'K'. + CONSTANTS c_include_program_type TYPE c LENGTH 1 VALUE 'I'. + CONSTANTS c_ip_program_type TYPE c LENGTH 1 VALUE 'J'. + PROTECTED SECTION. + CLASS-METHODS: + convert_attrib_to_vseoattrib + IMPORTING iv_clsname TYPE seoclsname + it_attributes TYPE zif_abapgit_oo_object_fnc=>ty_obj_attribute_tt + RETURNING VALUE(rt_vseoattrib) TYPE seoo_attributes_r. + + PRIVATE SECTION. + CONSTANTS c_docu_state_active TYPE dokstate VALUE 'A'. " See include SDOC_CONSTANTS + + DATA mv_skip_test_classes TYPE abap_bool . + +ENDCLASS. +CLASS zcl_abapgit_oo_class DEFINITION + INHERITING FROM zcl_abapgit_oo_base + CREATE PUBLIC + FRIENDS ZCL_abapgit_oo_factory. + + PUBLIC SECTION. + + METHODS zif_abapgit_oo_object_fnc~create + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~create_sotr + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~delete + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~deserialize_source + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~generate_locals + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~get_class_properties + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~get_includes + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~insert_text_pool + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~read_sotr + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~read_text_pool + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~exists + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~syntax_check + REDEFINITION . + PROTECTED SECTION. + + TYPES: + ty_char1 TYPE c LENGTH 1 . + TYPES: + ty_char2 TYPE c LENGTH 2 . + PRIVATE SECTION. + + CLASS-METHODS update_source_index + IMPORTING + !iv_clsname TYPE csequence + !io_scanner TYPE REF TO cl_oo_source_scanner_class . + CLASS-METHODS update_report + IMPORTING + !iv_program TYPE syrepid + !it_source TYPE string_table + !iv_package TYPE devclass + !iv_version TYPE uccheck + RETURNING + VALUE(rv_updated) TYPE abap_bool + RAISING + zcx_abapgit_exception . + CLASS-METHODS generate_classpool + IMPORTING + !iv_name TYPE seoclsname + RAISING + zcx_abapgit_exception . + CLASS-METHODS update_meta + IMPORTING + !iv_name TYPE seoclsname + !iv_exposure TYPE seoexpose + !it_source TYPE rswsourcet + RAISING + zcx_abapgit_exception . + CLASS-METHODS determine_method_include + IMPORTING + !iv_name TYPE seoclsname + !iv_method TYPE seocpdname + RETURNING + VALUE(rv_program) TYPE syrepid + RAISING + zcx_abapgit_exception . + CLASS-METHODS init_scanner + IMPORTING + !it_source TYPE zif_abapgit_definitions=>ty_string_tt + !iv_name TYPE seoclsname + RETURNING + VALUE(ro_scanner) TYPE REF TO cl_oo_source_scanner_class + RAISING + zcx_abapgit_exception . + CLASS-METHODS update_full_class_include + IMPORTING + !iv_classname TYPE seoclsname + !it_source TYPE string_table + !it_methods TYPE cl_oo_source_scanner_class=>type_method_implementations + !iv_package TYPE devclass + !iv_version TYPE uccheck + RAISING + zcx_abapgit_exception. + CLASS-METHODS create_report + IMPORTING + !iv_program TYPE syrepid + !it_source TYPE string_table + !iv_extension TYPE ty_char2 + !iv_program_type TYPE ty_char1 + !iv_state TYPE r3state + !iv_package TYPE devclass + !iv_version TYPE uccheck + RAISING + zcx_abapgit_exception. + CLASS-METHODS update_cs_number_of_methods + IMPORTING + !iv_classname TYPE seoclsname + !iv_number_of_impl_methods TYPE i . + CLASS-METHODS delete_report + IMPORTING + !iv_program TYPE syrepid + RAISING + zcx_abapgit_exception. + CLASS-METHODS get_method_includes + IMPORTING + !iv_classname TYPE seoclsname + RETURNING + VALUE(rt_includes) TYPE seop_methods_w_include. + CLASS-METHODS repair_classpool + IMPORTING + !is_key TYPE seoclskey + RAISING + zcx_abapgit_exception . + CLASS-METHODS repair_redefinitions + IMPORTING + !is_key TYPE seoclskey + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_oo_factory DEFINITION. + + PUBLIC SECTION. + CLASS-METHODS: + get_by_type + IMPORTING + iv_object_type TYPE tadir-object + RETURNING + VALUE(ri_object_oriented_object) TYPE REF TO zif_abapgit_oo_object_fnc, + + get_by_name + IMPORTING + iv_object_name TYPE seoclsname + RETURNING + VALUE(ri_object_oriented_object) TYPE REF TO zif_abapgit_oo_object_fnc + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_oo_interface DEFINITION + INHERITING FROM zcl_abapgit_oo_base + CREATE PUBLIC + FRIENDS ZCL_abapgit_oo_factory. + + PUBLIC SECTION. + + METHODS zif_abapgit_oo_object_fnc~create + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~delete + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~get_includes + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~get_interface_properties + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~deserialize_source + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~exists + REDEFINITION . + METHODS zif_abapgit_oo_object_fnc~syntax_check + REDEFINITION . + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-METHODS update_report + IMPORTING + !iv_program TYPE syrepid + !it_source TYPE string_table + !iv_package TYPE devclass + !iv_version TYPE uccheck + RETURNING + VALUE(rv_updated) TYPE abap_bool + RAISING + zcx_abapgit_exception . + CLASS-METHODS update_meta + IMPORTING + !iv_name TYPE seoclsname + !it_source TYPE rswsourcet + RAISING + zcx_abapgit_exception . + CLASS-METHODS init_scanner + IMPORTING + !it_source TYPE zif_abapgit_definitions=>ty_string_tt + !iv_name TYPE seoclsname + RETURNING + VALUE(ro_scanner) TYPE REF TO cl_oo_source_scanner_interface + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_oo_serializer DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS serialize_abap_clif_source + IMPORTING + !is_class_key TYPE seoclskey + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt + RAISING + zcx_abapgit_exception + cx_sy_dyn_call_error . + METHODS are_test_classes_skipped + RETURNING + VALUE(rv_return) TYPE abap_bool . + METHODS serialize_locals_imp + IMPORTING + !is_clskey TYPE seoclskey + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt + RAISING + zcx_abapgit_exception . + METHODS serialize_locals_def + IMPORTING + !is_clskey TYPE seoclskey + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt + RAISING + zcx_abapgit_exception . + METHODS serialize_testclasses + IMPORTING + !is_clskey TYPE seoclskey + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt + RAISING + zcx_abapgit_exception . + METHODS serialize_macros + IMPORTING + !is_clskey TYPE seoclskey + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_skip_testclass TYPE abap_bool . + + METHODS calculate_skip_testclass + IMPORTING + !it_source TYPE zif_abapgit_definitions=>ty_string_tt + RETURNING + VALUE(rv_skip_testclass) TYPE abap_bool . + METHODS serialize_abap_old + IMPORTING + !is_clskey TYPE seoclskey + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt + RAISING + zcx_abapgit_exception . + METHODS serialize_abap_new + IMPORTING + !is_clskey TYPE seoclskey + RETURNING + VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt + RAISING + zcx_abapgit_exception + cx_sy_dyn_call_error . + METHODS remove_signatures + CHANGING + !ct_source TYPE zif_abapgit_definitions=>ty_string_tt . + METHODS read_include + IMPORTING + !is_clskey TYPE seoclskey + !iv_type TYPE seop_include_ext_app + RETURNING + VALUE(rt_source) TYPE seop_source_string + RAISING + zcx_abapgit_exception. + METHODS reduce + CHANGING + !ct_source TYPE zif_abapgit_definitions=>ty_string_tt . +ENDCLASS. +CLASS zcl_abapgit_field_rules DEFINITION + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_field_rules. + + CLASS-METHODS create + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_item, + tabname TYPE tabname, + fieldname TYPE fieldname, + fill_rule TYPE zif_abapgit_field_rules=>ty_fill_rule, + END OF ty_item, + ty_items TYPE SORTED TABLE OF ty_item WITH UNIQUE KEY tabname fieldname. + + DATA mt_item TYPE ty_items. + + METHODS fill_value + IMPORTING + iv_rule TYPE zif_abapgit_field_rules=>ty_fill_rule + iv_package TYPE devclass + iv_abap_language_version TYPE uccheck OPTIONAL + CHANGING + cv_value TYPE any. + +ENDCLASS. +CLASS zcl_abapgit_function_module DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_function_module. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_sap_namespace DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES zif_abapgit_sap_namespace. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_sap_package DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_factory . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_sap_package . + + METHODS constructor + IMPORTING + !iv_package TYPE devclass . + PROTECTED SECTION. + PRIVATE SECTION. + DATA mv_package TYPE devclass. +ENDCLASS. +CLASS zcl_abapgit_sap_report DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_sap_report. + + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS authorization_check + IMPORTING + iv_mode TYPE csequence + is_item TYPE zif_abapgit_definitions=>ty_item + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_tabl_compar DEFINITION + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_comparator. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item. + + PROTECTED SECTION. + + TYPES: + ty_founds TYPE STANDARD TABLE OF rsfindlst + WITH NON-UNIQUE DEFAULT KEY. + TYPES: + ty_seu_obj TYPE STANDARD TABLE OF seu_obj + WITH NON-UNIQUE DEFAULT KEY. + + DATA ms_item TYPE zif_abapgit_definitions=>ty_item. + + METHODS get_where_used_recursive + IMPORTING + !iv_object_name TYPE csequence + !iv_depth TYPE i + !iv_object_type TYPE euobj-id + !it_scope TYPE ty_seu_obj + RETURNING + VALUE(rt_founds_all) TYPE ty_founds + RAISING + zcx_abapgit_exception. + + METHODS is_structure_used_in_db_table + IMPORTING + !iv_object_name TYPE dd02v-tabname + RETURNING + VALUE(rv_is_structure_used_in_db_tab) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS validate + IMPORTING + !ii_remote_version TYPE REF TO zif_abapgit_xml_input + !ii_local_version TYPE REF TO zif_abapgit_xml_input + !ii_log TYPE REF TO zif_abapgit_log + RETURNING + VALUE(rv_message) TYPE string + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_tabl_ddl DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS read_data + IMPORTING + !iv_name TYPE tadir-obj_name + RETURNING + VALUE(rs_data) TYPE zif_abapgit_object_tabl=>ty_internal . + METHODS serialize + IMPORTING + !is_data TYPE zif_abapgit_object_tabl=>ty_internal + RETURNING + VALUE(rv_ddl) TYPE string . + METHODS deserialize + IMPORTING + !iv_ddl TYPE string + RETURNING + VALUE(rs_data) TYPE zif_abapgit_object_tabl=>ty_internal . + METHODS serialize_adt + IMPORTING + !iv_name TYPE tadir-obj_name + RETURNING + VALUE(rv_ddl) TYPE string + RAISING + cx_static_check . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS parse_top_annotations + CHANGING + !cs_data TYPE zif_abapgit_object_tabl=>ty_internal + !cv_ddl TYPE string . + METHODS parse_field_annotations + EXPORTING + !es_dd08v TYPE dd08v + CHANGING + !cv_ddl TYPE string . + METHODS parse_field + IMPORTING + !iv_field TYPE string + CHANGING + !cs_data TYPE zif_abapgit_object_tabl=>ty_internal . + METHODS serialize_top + IMPORTING + !is_data TYPE zif_abapgit_object_tabl=>ty_internal + RETURNING + VALUE(rv_ddl) TYPE string . + METHODS serialize_extend + IMPORTING + !is_dd03p TYPE dd03p + !is_data TYPE zif_abapgit_object_tabl=>ty_internal + RETURNING + VALUE(rv_ddl) TYPE string . + METHODS serialize_field_annotations + IMPORTING + !iv_fieldname TYPE clike + !is_data TYPE zif_abapgit_object_tabl=>ty_internal + RETURNING + VALUE(rv_ddl) TYPE string . + METHODS serialize_fkey_annotations + IMPORTING + !iv_fieldname TYPE clike + !is_data TYPE zif_abapgit_object_tabl=>ty_internal + RETURNING + VALUE(rv_ddl) TYPE string . + METHODS serialize_field_foreign_key + IMPORTING + !iv_fieldname TYPE clike + !is_data TYPE zif_abapgit_object_tabl=>ty_internal + RETURNING + VALUE(rv_ddl) TYPE string . + METHODS serialize_value_help + IMPORTING + !iv_fieldname TYPE clike + !is_data TYPE zif_abapgit_object_tabl=>ty_internal + RETURNING + VALUE(rv_ddl) TYPE string . + METHODS escape_string + IMPORTING + !iv_string TYPE clike + RETURNING + VALUE(rv_string) TYPE string . + METHODS unescape_string + IMPORTING + !iv_string TYPE clike + RETURNING + VALUE(rv_string) TYPE string . + METHODS serialize_type + IMPORTING + !is_dd03p TYPE dd03p + RETURNING + VALUE(rv_type) TYPE string . + METHODS parse_type + IMPORTING + !iv_token TYPE string + CHANGING + !cs_dd03p TYPE dd03p . +ENDCLASS. +CLASS zcl_abapgit_i18n_params DEFINITION + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + DATA ms_params TYPE zif_abapgit_definitions=>ty_i18n_params READ-ONLY . + + CLASS-METHODS new + IMPORTING + !iv_main_language TYPE spras DEFAULT zif_abapgit_definitions=>c_english + !iv_main_language_only TYPE abap_bool DEFAULT abap_false + !it_translation_langs TYPE zif_abapgit_definitions=>ty_languages OPTIONAL + !iv_use_lxe TYPE abap_bool DEFAULT abap_false + !is_params TYPE zif_abapgit_definitions=>ty_i18n_params OPTIONAL + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_i18n_params. + METHODS constructor + IMPORTING + !iv_main_language TYPE spras DEFAULT zif_abapgit_definitions=>c_english + !iv_main_language_only TYPE abap_bool DEFAULT abap_false + !it_translation_langs TYPE zif_abapgit_definitions=>ty_languages OPTIONAL + !iv_use_lxe TYPE abap_bool DEFAULT abap_false + !is_params TYPE zif_abapgit_definitions=>ty_i18n_params OPTIONAL. + + METHODS is_lxe_applicable + RETURNING + VALUE(rv_yes) TYPE abap_bool . + METHODS build_language_filter + RETURNING + VALUE(rt_language_filter) TYPE zif_abapgit_environment=>ty_system_language_filter . + METHODS trim_saplang_list + CHANGING + ct_sap_langs TYPE zif_abapgit_definitions=>ty_sap_langu_tab + RAISING + zcx_abapgit_exception. + METHODS trim_saplang_keyed_table + IMPORTING + iv_lang_field_name TYPE abap_compname + iv_keep_master_lang TYPE abap_bool DEFAULT abap_false "sy-langu OPTIONAL + CHANGING + ct_tab TYPE STANDARD TABLE + RAISING + zcx_abapgit_exception. + + CLASS-METHODS normalize_obj_patterns + IMPORTING + it_wo_translation_patterns TYPE string_table + RETURNING + VALUE(rt_wo_translation_clean) TYPE string_table + RAISING + zcx_abapgit_exception. + + CLASS-METHODS match_obj_patterns + IMPORTING + it_wo_translation_patterns TYPE string_table + is_tadir TYPE zif_abapgit_definitions=>ty_tadir + RETURNING + VALUE(rv_yes) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA mt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + CLASS-METHODS iso_langs_to_lang_filter + IMPORTING + it_iso_filter TYPE zif_abapgit_definitions=>ty_languages + RETURNING + VALUE(rt_language_filter) TYPE zif_abapgit_environment=>ty_system_language_filter. + +ENDCLASS. +CLASS zcl_abapgit_longtexts DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_factory. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_longtexts. + + PROTECTED SECTION. + + METHODS read + IMPORTING + !iv_object_name TYPE clike + !iv_longtext_id TYPE dokil-id + !it_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt + !iv_main_lang_only TYPE abap_bool DEFAULT abap_false + !iv_clear_fields TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rt_longtexts) TYPE zif_abapgit_longtexts=>ty_longtexts + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + + CONSTANTS c_docu_state_active TYPE dokstate VALUE 'A' ##NO_TEXT. + + METHODS escape_name + IMPORTING + !iv_longtext_id TYPE dokil-id + !iv_object_name TYPE clike + RETURNING + VALUE(rv_object) TYPE dokil-object. +ENDCLASS. +CLASS zcl_abapgit_lxe_texts DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_lxe_texts . + + CLASS-METHODS get_translation_languages + IMPORTING + !iv_main_language TYPE spras + !it_i18n_languages TYPE zif_abapgit_definitions=>ty_languages + RETURNING + VALUE(rt_languages) TYPE zif_abapgit_definitions=>ty_languages + RAISING + zcx_abapgit_exception. + CLASS-METHODS get_installed_languages + RETURNING + VALUE(rt_languages) TYPE zif_abapgit_definitions=>ty_languages + RAISING + zcx_abapgit_exception. + CLASS-METHODS convert_lang_string_to_table + IMPORTING + !iv_langs TYPE string + !iv_skip_main_language TYPE spras OPTIONAL + RETURNING + VALUE(rt_languages) TYPE zif_abapgit_definitions=>ty_languages + RAISING + zcx_abapgit_exception . + CLASS-METHODS convert_table_to_lang_string + IMPORTING + !it_languages TYPE zif_abapgit_definitions=>ty_languages + RETURNING + VALUE(rv_langs) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS detect_unsupported_languages + IMPORTING + !it_languages TYPE zif_abapgit_definitions=>ty_languages + RETURNING + VALUE(rt_unsupported_languages) TYPE zif_abapgit_definitions=>ty_languages + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_custmnr TYPE lxecustmnr VALUE '999999' ##NEEDED. + " The value for ABAP system translation is always 999999 (from lxecustmnr docs) + + TYPES: + BEGIN OF ty_lxe_lang_map, " extract from LXE_T002X + language TYPE lxeisolang, + r3_lang TYPE spras, + langshort TYPE c LENGTH 2, + END OF ty_lxe_lang_map. + + CLASS-DATA gt_lxe_lang_cache TYPE SORTED TABLE OF ty_lxe_lang_map WITH UNIQUE KEY language + WITH NON-UNIQUE SORTED KEY iso2 COMPONENTS langshort. + " Controversial: we need uniq, but maybe it's better to keep it debuggable + " TODO, add r3 key if needed in future + + TYPES: + BEGIN OF ty_lxe_translation, + source_lang TYPE lxeisolang, + target_lang TYPE lxeisolang, + custmnr TYPE lxecustmnr, + objtype TYPE trobjtype, + objname TYPE lxeobjname, + text_pairs TYPE zif_abapgit_lxe_texts=>ty_text_pairs, + END OF ty_lxe_translation. + TYPES: + ty_lxe_translations TYPE STANDARD TABLE OF ty_lxe_translation WITH DEFAULT KEY . + + CLASS-DATA gt_installed_languages_cache TYPE zif_abapgit_definitions=>ty_languages. + + DATA mo_i18n_params TYPE REF TO zcl_abapgit_i18n_params. + DATA mi_xml_out TYPE REF TO zif_abapgit_xml_output. + DATA mi_xml_in TYPE REF TO zif_abapgit_xml_input. + DATA mo_files TYPE REF TO zcl_abapgit_objects_files. + + METHODS serialize_xml + IMPORTING + !iv_lxe_text_name TYPE string DEFAULT 'LXE_TEXTS' + !iv_object_type TYPE tadir-object + !iv_object_name TYPE tadir-obj_name + RAISING + zcx_abapgit_exception . + + METHODS serialize_as_po + IMPORTING + !iv_object_type TYPE tadir-object + !iv_object_name TYPE tadir-obj_name + RAISING + zcx_abapgit_exception . + + " Implementation of deserialize_xml is not complete (but kept as future option) + METHODS deserialize_xml + IMPORTING + !iv_lxe_text_name TYPE string DEFAULT 'LXE_TEXTS' + !iv_object_type TYPE tadir-object OPTIONAL + !iv_object_name TYPE tadir-obj_name OPTIONAL + RAISING + zcx_abapgit_exception ##NEEDED. + + METHODS deserialize_from_po + IMPORTING + !iv_object_type TYPE tadir-object + !iv_object_name TYPE tadir-obj_name + RETURNING + VALUE(rv_changed) TYPE abap_bool + RAISING + zcx_abapgit_exception . + + METHODS get_lang_iso4 + IMPORTING + iv_src TYPE laiso + RETURNING + VALUE(rv_iso4) TYPE lxeisolang + RAISING + zcx_abapgit_exception. + METHODS get_lxe_object_list + IMPORTING + iv_object_type TYPE trobjtype + iv_object_name TYPE sobj_name + RETURNING + VALUE(rt_obj_list) TYPE lxe_tt_colob . + METHODS remove_irrelevant + IMPORTING + iv_objtype TYPE trobjtype + CHANGING + ct_text_pairs_tmp TYPE ty_lxe_translation-text_pairs. + METHODS read_lxe_object_text_pair + IMPORTING + iv_s_lang TYPE lxeisolang + iv_t_lang TYPE lxeisolang + iv_custmnr TYPE lxecustmnr + iv_objtype TYPE trobjtype + iv_objname TYPE lxeobjname + iv_read_only TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rt_text_pairs_tmp) TYPE ty_lxe_translation-text_pairs + RAISING + zcx_abapgit_exception. + METHODS write_lxe_object_text_pair + IMPORTING + iv_s_lang TYPE lxeisolang + iv_t_lang TYPE lxeisolang + iv_custmnr TYPE lxecustmnr + iv_objtype TYPE trobjtype + iv_objname TYPE lxeobjname + it_pcx_s1 TYPE ty_lxe_translation-text_pairs + RAISING + zcx_abapgit_exception. + METHODS read_text_items + IMPORTING + iv_object_type TYPE tadir-object + iv_object_name TYPE tadir-obj_name + RETURNING + VALUE(rt_text_items) TYPE ty_lxe_translations + RAISING + zcx_abapgit_exception. + + CLASS-METHODS langu_to_laiso_safe + IMPORTING + iv_langu TYPE sy-langu + RETURNING + VALUE(rv_laiso) TYPE laiso + RAISING + zcx_abapgit_exception. + CLASS-METHODS iso4_to_iso2 + IMPORTING + iv_lxe_lang TYPE lxeisolang + RETURNING + VALUE(rv_laiso) TYPE laiso + RAISING + zcx_abapgit_exception. + + CLASS-METHODS check_langs_versus_installed + IMPORTING + it_languages TYPE zif_abapgit_definitions=>ty_languages + it_installed TYPE zif_abapgit_definitions=>ty_languages + EXPORTING + et_intersection TYPE zif_abapgit_definitions=>ty_languages + et_missfits TYPE zif_abapgit_definitions=>ty_languages. +ENDCLASS. +CLASS zcl_abapgit_po_file DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES zif_abapgit_i18n_file. + + METHODS constructor + IMPORTING + iv_lang TYPE laiso + iv_suppress_comments TYPE abap_bool DEFAULT abap_false. + + METHODS parse + IMPORTING + iv_xdata TYPE xstring + RAISING + zcx_abapgit_exception. + + METHODS push_text_pairs + IMPORTING + iv_objtype TYPE trobjtype + iv_objname TYPE lxeobjname + it_text_pairs TYPE zif_abapgit_lxe_texts=>ty_text_pairs + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_comment, + translator TYPE i VALUE 1, + extracted TYPE i VALUE 2, + reference TYPE i VALUE 3, + flag TYPE i VALUE 4, + previous TYPE i VALUE 5, + END OF c_comment. + TYPES: + BEGIN OF ty_comment, + kind TYPE i, + text TYPE string, + END OF ty_comment. + TYPES: + BEGIN OF ty_msg_pair, + source TYPE string, + target TYPE string, + comments TYPE STANDARD TABLE OF ty_comment WITH KEY kind text, + END OF ty_msg_pair. + + DATA mv_lang TYPE laiso. + DATA mv_suppress_comments TYPE abap_bool. + DATA mt_pairs TYPE SORTED TABLE OF ty_msg_pair WITH UNIQUE KEY source. + + METHODS build_po_body + RETURNING + VALUE(ro_buf) TYPE REF TO zcl_abapgit_string_buffer. + METHODS build_po_head + RETURNING + VALUE(ro_buf) TYPE REF TO zcl_abapgit_string_buffer. + METHODS parse_po + IMPORTING + iv_data TYPE string + RAISING + zcx_abapgit_exception. + + CLASS-METHODS get_comment_marker + IMPORTING + iv_comment_kind TYPE i + RETURNING + VALUE(rv_marker) TYPE string. + + CLASS-METHODS quote + IMPORTING + iv_text TYPE string + RETURNING + VALUE(rv_text) TYPE string. + CLASS-METHODS unquote + IMPORTING + iv_text TYPE string + RETURNING + VALUE(rv_text) TYPE string + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_properties_file DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES zif_abapgit_i18n_file. + + METHODS constructor + IMPORTING + iv_lang TYPE laiso. + + METHODS parse + IMPORTING + iv_xdata TYPE xstring + RAISING + zcx_abapgit_exception. + + METHODS push_text_pairs + IMPORTING it_translation TYPE string_table. + + METHODS get_translations + EXPORTING + ev_data TYPE data + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_lang TYPE laiso. + DATA mt_translation TYPE string_table. + +ENDCLASS. +CLASS zcl_abapgit_sotr_handler DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_sotr, + header TYPE sotr_head, + entries TYPE sotr_text_tt, + END OF ty_sotr. + TYPES: + ty_sotr_tt TYPE STANDARD TABLE OF ty_sotr WITH DEFAULT KEY. + TYPES: + ty_sotr_use_tt TYPE STANDARD TABLE OF sotr_use WITH DEFAULT KEY. + + CLASS-METHODS read_sotr + IMPORTING + !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object TYPE trobjtype + !iv_obj_name TYPE csequence + !io_xml TYPE REF TO zif_abapgit_xml_output OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params + EXPORTING + !et_sotr TYPE ty_sotr_tt + !et_sotr_use TYPE ty_sotr_use_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS create_sotr + IMPORTING + !iv_package TYPE devclass + !io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception. + + CLASS-METHODS create_sotr_from_data + IMPORTING + !iv_package TYPE devclass + !it_sotr TYPE ty_sotr_tt + !it_sotr_use TYPE ty_sotr_use_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS delete_sotr + IMPORTING + !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object TYPE trobjtype + !iv_obj_name TYPE csequence + RAISING + zcx_abapgit_exception. + + CLASS-METHODS delete_sotr_package + IMPORTING + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception. + + CLASS-METHODS change_sotr_package + IMPORTING + !iv_old_package TYPE devclass + !iv_new_package TYPE devclass + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + CLASS-METHODS get_sotr_usage + IMPORTING + !iv_pgmid TYPE tadir-pgmid + !iv_object TYPE trobjtype + !iv_obj_name TYPE csequence + RETURNING + VALUE(rt_sotr_use) TYPE ty_sotr_use_tt. + + CLASS-METHODS get_sotr_4_concept + IMPORTING + !iv_concept TYPE sotr_conc + RETURNING + VALUE(rs_sotr) TYPE ty_sotr. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_sots_handler DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_sots, + header TYPE sotr_headu, + entries TYPE sotr_textl_tt, + END OF ty_sots. + TYPES: + ty_sots_tt TYPE STANDARD TABLE OF ty_sots WITH DEFAULT KEY. + TYPES: + ty_sots_use_tt TYPE STANDARD TABLE OF sotr_useu WITH DEFAULT KEY. + + CLASS-METHODS read_sots + IMPORTING + !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object TYPE trobjtype + !iv_obj_name TYPE csequence + !io_xml TYPE REF TO zif_abapgit_xml_output OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params + EXPORTING + !et_sots TYPE ty_sots_tt + !et_sots_use TYPE ty_sots_use_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS create_sots + IMPORTING + !iv_package TYPE devclass + !io_xml TYPE REF TO zif_abapgit_xml_input OPTIONAL + RAISING + zcx_abapgit_exception. + + CLASS-METHODS create_sots_from_data + IMPORTING + !iv_package TYPE devclass + !it_sots TYPE ty_sots_tt OPTIONAL + !it_sots_use TYPE ty_sots_use_tt OPTIONAL + RAISING + zcx_abapgit_exception. + + CLASS-METHODS delete_sots + IMPORTING + !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' + !iv_object TYPE trobjtype + !iv_obj_name TYPE csequence + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + CLASS-METHODS get_sots_usage + IMPORTING + !iv_pgmid TYPE tadir-pgmid + !iv_object TYPE trobjtype + !iv_obj_name TYPE csequence + RETURNING + VALUE(rt_sots_use) TYPE ty_sots_use_tt. + + CLASS-METHODS get_sots_4_concept + IMPORTING + !iv_concept TYPE sotr_conc + RETURNING + VALUE(rs_sots) TYPE ty_sots. + + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_objects DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS serialize + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params + RETURNING + VALUE(rs_files_and_item) TYPE zif_abapgit_objects=>ty_serialization + RAISING + zcx_abapgit_exception . + CLASS-METHODS deserialize + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks + !ii_log TYPE REF TO zif_abapgit_log + RETURNING + VALUE(rt_accessed_files) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS deserialize_checks + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks + RAISING + zcx_abapgit_exception . + CLASS-METHODS delete + IMPORTING + !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + !is_checks TYPE zif_abapgit_definitions=>ty_delete_checks OPTIONAL + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + RAISING + zcx_abapgit_exception . + CLASS-METHODS jump + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !is_sub_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL + !iv_filename TYPE string OPTIONAL + !iv_line_number TYPE i OPTIONAL + !iv_new_window TYPE abap_bool DEFAULT abap_true + RAISING + zcx_abapgit_exception . + CLASS-METHODS changed_by + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_filename TYPE string OPTIONAL + RETURNING + VALUE(rv_user) TYPE syuname . + CLASS-METHODS is_supported + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_native_only TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rv_bool) TYPE abap_bool . + CLASS-METHODS is_type_supported + IMPORTING + !iv_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type + RETURNING + VALUE(rv_bool) TYPE abap_bool . + CLASS-METHODS exists + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RETURNING + VALUE(rv_bool) TYPE abap_bool . + CLASS-METHODS supported_list + RETURNING + VALUE(rt_types) TYPE zif_abapgit_objects=>ty_types_tt. + CLASS-METHODS is_active + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RETURNING + VALUE(rv_active) TYPE abap_bool + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_supported_types, + obj_type TYPE tadir-object, + supported TYPE abap_bool, + END OF ty_supported_types. + + TYPES: ty_supported_types_tt TYPE SORTED TABLE OF ty_supported_types WITH UNIQUE KEY obj_type. + + TYPES: + BEGIN OF ty_obj_serializer_item, + item TYPE zif_abapgit_definitions=>ty_item, + metadata TYPE zif_abapgit_definitions=>ty_metadata, + END OF ty_obj_serializer_item . + TYPES: + ty_obj_serializer_map TYPE SORTED TABLE OF ty_obj_serializer_item WITH UNIQUE KEY item . + + CLASS-DATA gt_obj_serializer_map TYPE ty_obj_serializer_map . + CLASS-DATA gt_supported_obj_types TYPE ty_supported_types_tt . + CLASS-DATA gv_supported_obj_types_loaded TYPE abap_bool . + + CLASS-METHODS check_duplicates + IMPORTING + !it_files TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS class_name + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + RETURNING + VALUE(rv_class_name) TYPE string . + CLASS-METHODS update_package_tree + IMPORTING + !iv_package TYPE devclass . + CLASS-METHODS delete_object + IMPORTING + !iv_package TYPE devclass + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + CLASS-METHODS deserialize_steps + IMPORTING + !it_steps TYPE zif_abapgit_objects=>ty_step_data_tt + !ii_log TYPE REF TO zif_abapgit_log + !iv_transport TYPE trkorr + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params + CHANGING + !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS deserialize_step + IMPORTING + !is_step TYPE zif_abapgit_objects=>ty_step_data + !ii_log TYPE REF TO zif_abapgit_log + !iv_transport TYPE trkorr + CHANGING + !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS deserialize_lxe + IMPORTING + !is_step TYPE zif_abapgit_objects=>ty_step_data + !ii_log TYPE REF TO zif_abapgit_log + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params + CHANGING + !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS check_original_system + IMPORTING + !it_items TYPE zif_abapgit_definitions=>ty_items_tt + !ii_log TYPE REF TO zif_abapgit_log + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + RAISING + zcx_abapgit_exception . + CLASS-METHODS update_original_system + IMPORTING + !it_items TYPE zif_abapgit_definitions=>ty_items_tt + !ii_log TYPE REF TO zif_abapgit_log + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + CLASS-METHODS check_objects_locked + IMPORTING + !it_items TYPE zif_abapgit_definitions=>ty_items_tt + RAISING + zcx_abapgit_exception . + + CLASS-METHODS create_object + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + !is_metadata TYPE zif_abapgit_definitions=>ty_metadata OPTIONAL + !iv_native_only TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_obj) TYPE REF TO zif_abapgit_object + RAISING + zcx_abapgit_type_not_supported . + + CLASS-METHODS map_tadir_to_items + IMPORTING + !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RETURNING + VALUE(rt_items) TYPE zif_abapgit_definitions=>ty_items_tt . + CLASS-METHODS map_results_to_items + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RETURNING + VALUE(rt_items) TYPE zif_abapgit_definitions=>ty_items_tt . + CLASS-METHODS get_deserialize_steps + RETURNING + VALUE(rt_steps) TYPE zif_abapgit_objects=>ty_step_data_tt . + CLASS-METHODS change_package_assignments + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !ii_log TYPE REF TO zif_abapgit_log . + CLASS-METHODS get_extra_from_filename + IMPORTING + !iv_filename TYPE string + RETURNING + VALUE(rv_extra) TYPE string. + + CLASS-METHODS is_type_supported_exit + IMPORTING + !iv_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type + RETURNING + VALUE(rv_bool) TYPE abap_bool. +ENDCLASS. +CLASS zcl_abapgit_objects_factory DEFINITION + CREATE PRIVATE + . + + PUBLIC SECTION. + CLASS-METHODS get_gui_jumper + RETURNING + VALUE(ri_gui_jumper) TYPE REF TO zif_abapgit_gui_jumper . + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gi_gui_jumper TYPE REF TO zif_abapgit_gui_jumper . +ENDCLASS. +CLASS zcl_abapgit_objects_generic DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras DEFAULT sy-langu + io_field_rules TYPE REF TO zif_abapgit_field_rules OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS delete + IMPORTING + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS deserialize + IMPORTING + !iv_package TYPE devclass + !io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS exists + RETURNING + VALUE(rv_bool) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS serialize + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + + TYPES: + BEGIN OF ty_s_objkey, + num TYPE n LENGTH 3, + value TYPE c LENGTH 128, + END OF ty_s_objkey . + TYPES: + ty_t_objkey TYPE SORTED TABLE OF ty_s_objkey WITH UNIQUE KEY num . + + DATA ms_object_header TYPE objh . + DATA: + mt_object_table TYPE STANDARD TABLE OF objsl WITH DEFAULT KEY . + DATA: + mt_object_method TYPE STANDARD TABLE OF objm WITH DEFAULT KEY . + DATA ms_item TYPE zif_abapgit_definitions=>ty_item . + DATA mv_language TYPE spras . + + METHODS after_import . + METHODS before_export . + METHODS corr_insert + IMPORTING + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS deserialize_data + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS distribute_name_to_components + IMPORTING + !it_key_component TYPE ddfields + CHANGING + !ct_objkey TYPE ty_t_objkey + !cs_objkey TYPE ty_s_objkey + !cv_non_value_pos TYPE numc3 . + METHODS get_key_fields + IMPORTING + !iv_table TYPE objsl-tobj_name + RETURNING + VALUE(rt_keys) TYPE ddfields + RAISING + zcx_abapgit_exception . + METHODS get_primary_table + RETURNING + VALUE(rv_table) TYPE objsl-tobj_name + RAISING + zcx_abapgit_exception . + METHODS get_where_clause + IMPORTING + !iv_tobj_name TYPE objsl-tobj_name + RETURNING + VALUE(rv_where) TYPE string + RAISING + zcx_abapgit_exception . + METHODS serialize_data + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS split_value_to_keys + IMPORTING + !it_key_component TYPE ddfields + CHANGING + !ct_objkey TYPE ty_t_objkey + !cs_objkey TYPE ty_s_objkey + !cv_non_value_pos TYPE numc3 . + METHODS validate + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + + DATA mo_field_rules TYPE REF TO zif_abapgit_field_rules . + + METHODS apply_clear_logic + IMPORTING + !iv_table TYPE objsl-tobj_name + CHANGING + !ct_data TYPE STANDARD TABLE . + METHODS apply_fill_logic + IMPORTING + !iv_table TYPE objsl-tobj_name + !iv_package TYPE devclass + CHANGING + !ct_data TYPE STANDARD TABLE . +ENDCLASS. +CLASS zcl_abapgit_objects_super DEFINITION + ABSTRACT + CREATE PUBLIC. + + PUBLIC SECTION. + + CONSTANTS c_user_unknown TYPE syuname VALUE 'UNKNOWN'. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL. + + METHODS get_accessed_files + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt. + PROTECTED SECTION. + + DATA: + ms_item TYPE zif_abapgit_definitions=>ty_item, + mv_language TYPE spras, + mo_files TYPE REF TO zcl_abapgit_objects_files, + mo_i18n_params TYPE REF TO zcl_abapgit_i18n_params. + + METHODS get_metadata + RETURNING + VALUE(rs_metadata) TYPE zif_abapgit_definitions=>ty_metadata . + METHODS corr_insert + IMPORTING + !iv_package TYPE devclass + !ig_object_class TYPE any OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS tadir_insert + IMPORTING + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS tadir_delete + RAISING + zcx_abapgit_exception . + METHODS exists_a_lock_entry_for + IMPORTING + !iv_lock_object TYPE string + !iv_argument TYPE csequence OPTIONAL + !iv_prefix TYPE csequence OPTIONAL + RETURNING + VALUE(rv_exists_a_lock_entry) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS set_default_package + IMPORTING + !iv_package TYPE devclass . + METHODS set_default_transport + IMPORTING + !iv_transport TYPE trkorr. + METHODS serialize_longtexts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + !iv_longtext_id TYPE dokil-id OPTIONAL + !it_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt OPTIONAL + !iv_longtext_name TYPE string DEFAULT 'LONGTEXTS' + RAISING + zcx_abapgit_exception . + METHODS deserialize_longtexts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + !iv_longtext_id TYPE dokil-id OPTIONAL + !iv_longtext_name TYPE string DEFAULT 'LONGTEXTS' + RAISING + zcx_abapgit_exception . + METHODS delete_longtexts + IMPORTING + !iv_longtext_id TYPE dokil-id + RAISING + zcx_abapgit_exception . + METHODS is_active + RETURNING + VALUE(rv_active) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS delete_ddic + IMPORTING + !iv_objtype TYPE string + !iv_no_ask TYPE abap_bool DEFAULT abap_true + !iv_no_ask_delete_append TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception . + METHODS get_abap_language_version + RETURNING + VALUE(rv_abap_language_version) TYPE uccheck + RAISING + zcx_abapgit_exception . + METHODS set_abap_language_version + CHANGING + !cv_abap_language_version TYPE uccheck + RAISING + zcx_abapgit_exception . + METHODS clear_abap_language_version + CHANGING + !cv_abap_language_version TYPE uccheck + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. +ENDCLASS. +"! Provides common functionality for the abapGit integration of objects based on ABAP File Formats (AFF). +"! It inherits from {@link ZCL_ABAPGIT_OBJECTS_SUPER} and implements the interface {@link ZIF_ABAPGIT_OBJECT}. +"!

      +"! Each subclass must implement at least the abstract method ZIF_ABAPGIT_OBJECT~CHANGED_BY. +"! In case you deal with a DDIC object, the methods GET_METADATA and ZIF_ABAPGIT_OBJECT~GET_DESERIALIZE_STEPS +"! have to be redefined in the subclass. +"!

      +"! In case the object has an additional file to the json file, the subclass needs +"! to redefine the method GET_ADDITIONAL_EXTENSIONS. +"!

      +"! This common class fully relies on the implementation of the object-specific AFF handler +"! (it inherits from {@link CL_AFF_OBJECT_HANDLER}). +"! Precisely, for the existence check-, serialization-, deserialization- or deletion-functionality, the corresponding +"! AFF object handler method is called. +CLASS zcl_abapgit_object_common_aff DEFINITION + INHERITING FROM zcl_abapgit_objects_super + ABSTRACT + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object + ABSTRACT METHODS changed_by . + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + TYPES: BEGIN OF ty_extension_mapper_pair, + "! file extension + extension TYPE string, + "! instance of {@link CL_AFF_FILE_NAME_MAPPER} providing file names for file extensions + file_name_mapper TYPE REF TO object, + END OF ty_extension_mapper_pair, + ty_extension_mapper_pairs TYPE STANDARD TABLE OF ty_extension_mapper_pair WITH DEFAULT KEY. + + "! Delivers other file extensions than json to be considered at serialize or deserialize of an object + METHODS get_additional_extensions + RETURNING VALUE(rv_additional_extensions) TYPE ty_extension_mapper_pairs ##NEEDED. + + "! Delivers an instance of AFF object handler ({@link IF_AFF_OBJECT_HANDLER}) + METHODS get_object_handler + RETURNING + VALUE(ro_object_handler) TYPE REF TO object + RAISING + zcx_abapgit_exception. + METHODS create_aff_setting_deserialize FINAL + RETURNING + VALUE(ro_settings_deserialize) TYPE REF TO object + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + METHODS is_file_empty + IMPORTING + io_object_json_file TYPE REF TO object + RETURNING + VALUE(rv_is_empty) TYPE abap_bool. + + CLASS-METHODS remove_abap_language_version + IMPORTING + iv_json_as_xstring TYPE xstring + RETURNING + VALUE(rv_json_as_xstring_wo_alv) TYPE xstring + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_aplo DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS zif_abapgit_object~changed_by + REDEFINITION . + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_object_bgqc DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + + PRIVATE SECTION. + CONSTANTS c_bgqc_name TYPE string VALUE 'BGQCNAME'. + CONSTANTS c_bgqc_wbi_p TYPE string VALUE 'CL_BGQC_WBI_P'. + CONSTANTS c_select_changed_by TYPE string VALUE 'IF_BGQC_WBI_P~SELECT_CHANGED_BY'. + +ENDCLASS. +CLASS zcl_abapgit_object_cdbo DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + METHODS zif_abapgit_object~changed_by REDEFINITION. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_table_name TYPE tabname VALUE 'CDB_OBJH' ##NO_TEXT. + +ENDCLASS. +CLASS zcl_abapgit_object_chkc DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_object_chko DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_object_chkv DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_object_cota DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + METHODS zif_abapgit_object~delete REDEFINITION. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_dras DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + METHODS zif_abapgit_object~get_deserialize_steps REDEFINITION. + PROTECTED SECTION. + METHODS get_additional_extensions REDEFINITION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_drty DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + METHODS zif_abapgit_object~get_deserialize_steps REDEFINITION. + PROTECTED SECTION. + METHODS get_additional_extensions REDEFINITION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_dsfd DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + METHODS zif_abapgit_object~get_deserialize_steps REDEFINITION. + PROTECTED SECTION. + METHODS get_additional_extensions REDEFINITION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_dsfi DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + METHODS zif_abapgit_object~get_deserialize_steps REDEFINITION. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_dteb DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION . + METHODS zif_abapgit_object~get_deserialize_steps REDEFINITION. + PROTECTED SECTION. + + METHODS get_additional_extensions + REDEFINITION . + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_object_eeec DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS: + zif_abapgit_object~changed_by REDEFINITION . + + PROTECTED SECTION. + METHODS: get_object_handler REDEFINITION. +ENDCLASS. +CLASS zcl_abapgit_object_evtb DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + CREATE PUBLIC. + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION . + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: + c_table_name TYPE tabname VALUE 'EVTB_HEADER'. +ENDCLASS. +CLASS zcl_abapgit_object_gsmp DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_nont DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + CREATE PUBLIC. + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS c_table_name TYPE tabname VALUE 'NONT_HEADER'. +ENDCLASS. +CLASS zcl_abapgit_object_ront DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + CREATE PUBLIC. + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS c_table_name TYPE tabname VALUE 'RONT_HEADER'. +ENDCLASS. +CLASS zcl_abapgit_object_sajc DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS zif_abapgit_object~changed_by + REDEFINITION . + METHODS zif_abapgit_object~get_deserialize_steps REDEFINITION. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_sajt DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS zif_abapgit_object~changed_by + REDEFINITION . + METHODS zif_abapgit_object~get_deserialize_steps REDEFINITION. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_smbc DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + METHODS zif_abapgit_object~changed_by REDEFINITION. + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_swcr DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS: zif_abapgit_object~changed_by REDEFINITION. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_uiad DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS zif_abapgit_object~changed_by + REDEFINITION . + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_uipg DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS zif_abapgit_object~changed_by + REDEFINITION . + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_uist DEFINITION + INHERITING FROM zcl_abapgit_object_common_aff + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS zif_abapgit_object~changed_by + REDEFINITION . + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_tabl DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + "! get additional data like table authorization group + "! @parameter iv_tabname | name of the table + METHODS read_extras IMPORTING iv_tabname TYPE ddobjname + RETURNING VALUE(rs_tabl_extras) TYPE zif_abapgit_object_tabl=>ty_tabl_extras + RAISING zcx_abapgit_exception. + + "! Update additional data + "! @parameter iv_tabname | name of the table + "! @parameter is_tabl_extras | additional table data + METHODS update_extras IMPORTING iv_tabname TYPE ddobjname + is_tabl_extras TYPE zif_abapgit_object_tabl=>ty_tabl_extras + RAISING zcx_abapgit_exception. + + "! Delete additional data + "! @parameter iv_tabname | name of the table + METHODS delete_extras IMPORTING iv_tabname TYPE ddobjname. + + "! Serialize IDoc Segment type/definition if exits + "! @raising zcx_abapgit_exception | Exceptions + METHODS serialize_idoc_segment CHANGING cs_internal TYPE zif_abapgit_object_tabl=>ty_internal + RAISING zcx_abapgit_exception. + + "! Deserialize IDoc Segment type/definition if exits + "! @parameter iv_package | Target package + "! @parameter rv_deserialized | It's a segment and was deserialized + "! @raising zcx_abapgit_exception | Exceptions + METHODS deserialize_idoc_segment IMPORTING is_internal TYPE zif_abapgit_object_tabl=>ty_internal + iv_transport TYPE trkorr + iv_package TYPE devclass + RETURNING VALUE(rv_deserialized) TYPE abap_bool + RAISING zcx_abapgit_exception. + "! Delete the IDoc Segment type if exists + "! @parameter rv_deleted | It's a segment and was deleted + "! @raising zcx_abapgit_exception | Exceptions + METHODS delete_idoc_segment RETURNING VALUE(rv_deleted) TYPE abap_bool + RAISING zcx_abapgit_exception. + PRIVATE SECTION. + CONSTANTS c_longtext_id_tabl TYPE dokil-id VALUE 'TB' ##NO_TEXT. + + METHODS deserialize_indexes + IMPORTING + !is_internal TYPE zif_abapgit_object_tabl=>ty_internal + RAISING + zcx_abapgit_exception . + METHODS clear_dd03p_fields + CHANGING + !ct_dd03p TYPE zif_abapgit_object_tabl=>ty_dd03p_tt . + "! Check if structure is an IDoc segment + "! @parameter rv_is_idoc_segment | It's an IDoc segment or not + METHODS is_idoc_segment + RETURNING + VALUE(rv_is_idoc_segment) TYPE abap_bool . + METHODS clear_dd03p_fields_common + CHANGING + !cs_dd03p TYPE dd03p . + METHODS clear_dd03p_fields_dataelement + CHANGING + !cs_dd03p TYPE dd03p . + METHODS serialize_texts + CHANGING + !cs_internal TYPE zif_abapgit_object_tabl=>ty_internal + RAISING + zcx_abapgit_exception . + METHODS deserialize_texts + CHANGING + !cs_internal TYPE zif_abapgit_object_tabl=>ty_internal + RAISING + zcx_abapgit_exception . + METHODS is_db_table_category + IMPORTING + !iv_tabclass TYPE dd02l-tabclass + RETURNING + VALUE(rv_is_db_table_type) TYPE dd02l-tabclass . +ENDCLASS. +CLASS zcl_abapgit_object_acid DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: create_object + RETURNING VALUE(ro_aab) TYPE REF TO cl_aab_id + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_aifc DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + TYPES: + BEGIN OF ty_aif_key_s, + ns TYPE c LENGTH 6, + ifname TYPE c LENGTH 10, + ifver TYPE c LENGTH 5, + END OF ty_aif_key_s. + TYPES: + BEGIN OF ty_icd_data_key_s, + depl_scenario TYPE c LENGTH 20, + ns TYPE c LENGTH 6, + ifname TYPE c LENGTH 10, + ifver2 TYPE c LENGTH 4, + END OF ty_icd_data_key_s. + TYPES: + BEGIN OF ty_icd_data_key, + depl_scenario TYPE c LENGTH 20, + ns TYPE c LENGTH 6, + ifname TYPE c LENGTH 10, + ifver2 TYPE c LENGTH 4, + ifver TYPE c LENGTH 5, + END OF ty_icd_data_key. + TYPES: + BEGIN OF ty_table_data_s, + tabname TYPE tabname, + table_data TYPE REF TO data, + END OF ty_table_data_s. + TYPES: + ty_table_data_t TYPE SORTED TABLE OF + ty_table_data_s WITH UNIQUE KEY tabname. + + DATA ms_icd_data_key TYPE ty_icd_data_key_s. + + METHODS handle_table_data + IMPORTING + !iv_tabname TYPE tabname + !it_data TYPE STANDARD TABLE + RAISING + zcx_abapgit_exception. + METHODS clear_client + CHANGING + !ct_data TYPE STANDARD TABLE + RAISING + zcx_abapgit_exception. + METHODS authorization_check + RETURNING + VALUE(rv_success) TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS get_content_compress + IMPORTING + !io_log TYPE REF TO zif_abapgit_log + !is_ifkeys TYPE ty_aif_key_s + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception. + METHODS validate_interface + IMPORTING + !is_ifkeys TYPE ty_aif_key_s + RETURNING + VALUE(rv_success) TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS compress_interface + IMPORTING + !is_ifkeys TYPE ty_aif_key_s + RETURNING + VALUE(rv_success) TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS execute_checks + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + RETURNING + VALUE(rv_success) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + TYPES: + BEGIN OF ty_content_s, + tabname TYPE tabname, + END OF ty_content_s. + TYPES: + ty_content_t TYPE STANDARD TABLE OF ty_content_s WITH NON-UNIQUE DEFAULT KEY. + + DATA mo_abapgit_util TYPE REF TO object. +ENDCLASS. +CLASS zcl_abapgit_object_amsd DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: + clear_fields + CHANGING + cs_logical_db_schema TYPE any, + + clear_field + IMPORTING + iv_fieldname TYPE csequence + CHANGING + cs_logical_db_schema TYPE any, + + fill_metadata_from_db + CHANGING + cs_logical_db_schema TYPE any + RAISING + zcx_abapgit_exception, + + get_wb_object_operator + RETURNING + VALUE(ri_wb_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception. + + DATA: + mr_logical_db_schema TYPE REF TO data, + mv_logical_db_schema_key TYPE seu_objkey, + mi_persistence TYPE REF TO if_wb_object_persist, + mi_wb_object_operator TYPE REF TO object. +ENDCLASS. +CLASS zcl_abapgit_object_apis DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS c_model TYPE string VALUE 'ARS_S_API_ABAPGIT'. + DATA mo_handler TYPE REF TO object. + METHODS initialize. +ENDCLASS. +CLASS zcl_abapgit_object_aqbg DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_aqqu DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_aqsg DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_area DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_object_asfc DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_auth DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mv_fieldname TYPE authx-fieldname. + +ENDCLASS. +CLASS zcl_abapgit_object_avar DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: create_object + RETURNING VALUE(ro_aab_var) TYPE REF TO cl_aab_variant + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_avas DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + TYPES: + BEGIN OF ty_header, + guid TYPE guid_32, + attribute TYPE cls_attribute_name, + object TYPE pak_object_key, + END OF ty_header . + TYPES: + BEGIN OF ty_avas, + header TYPE ty_header, + values TYPE cls_value_assignments, + links TYPE cls_linked_objects, + END OF ty_avas . + + METHODS insert_assignments + IMPORTING + !is_avas TYPE ty_avas + RAISING + zcx_abapgit_exception . + METHODS instantiate + RETURNING + VALUE(ro_avas) TYPE REF TO cl_cls_attr_value_assignment + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_bdef DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mi_persistence TYPE REF TO if_wb_object_persist . + DATA mi_wb_object_operator TYPE REF TO object . + DATA mv_behaviour_definition_key TYPE seu_objkey . + DATA mr_behaviour_definition TYPE REF TO data . + + METHODS clear_fields + CHANGING + !cs_metadata TYPE any . + METHODS clear_field + IMPORTING + !iv_fieldname TYPE csequence + CHANGING + !cs_metadata TYPE any . + METHODS get_wb_object_operator + RETURNING + VALUE(ri_wb_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception . + METHODS merge_object_data + IMPORTING + !io_object_data TYPE REF TO object + RETURNING + VALUE(ro_object_data_merged) TYPE REF TO if_wb_object_data_model + RAISING + zcx_abapgit_exception . + METHODS get_object_data + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + RETURNING + VALUE(ro_object_data) TYPE REF TO if_wb_object_data_model + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_char DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_char, + cls_attribute TYPE cls_attribute, + cls_attributet TYPE STANDARD TABLE OF cls_attributet WITH DEFAULT KEY, + cls_attr_value TYPE STANDARD TABLE OF cls_attr_value WITH DEFAULT KEY, + cls_attr_valuet TYPE STANDARD TABLE OF cls_attr_valuet WITH DEFAULT KEY, + END OF ty_char . + + CONSTANTS c_longtext_id_char TYPE dokil-id VALUE 'CH'. + + METHODS instantiate_char_and_lock + IMPORTING + !iv_type_group TYPE cls_object_type_group + !iv_activation_state TYPE pak_activation_state + RETURNING + VALUE(ro_char) TYPE REF TO cl_cls_attribute + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_chdo DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + METHODS after_import + RAISING + zcx_abapgit_exception . + METHODS delete_tadir_cdnames + IMPORTING + !is_cdnames TYPE cdnames + RAISING + zcx_abapgit_exception . + METHODS delete_tadir_tabl + IMPORTING + !is_tcdrs TYPE tcdrs + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + TYPES: BEGIN OF ty_change_document, + reports_generated TYPE SORTED TABLE OF tcdrps WITH UNIQUE KEY object reportname, + objects TYPE SORTED TABLE OF tcdobs WITH UNIQUE KEY object tabname, + objects_text TYPE SORTED TABLE OF tcdobts WITH UNIQUE KEY spras object, + END OF ty_change_document. + + DATA: mv_object TYPE cdobjectcl. + +ENDCLASS. +CLASS zcl_abapgit_object_cmod DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_object_cmpt DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mo_cmp_db TYPE REF TO object, + mv_name TYPE c LENGTH 30. + +ENDCLASS. +CLASS zcl_abapgit_object_cus0 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: ty_img_activity_texts TYPE STANDARD TABLE OF cus_imgact + WITH NON-UNIQUE DEFAULT KEY, + BEGIN OF ty_img_activity, + header TYPE cus_imgach, + texts TYPE ty_img_activity_texts, + END OF ty_img_activity. + DATA: mv_img_activity TYPE cus_img_ac. + +ENDCLASS. +CLASS zcl_abapgit_object_cus1 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: ty_activity_titles TYPE STANDARD TABLE OF cus_actt + WITH NON-UNIQUE DEFAULT KEY, + + ty_objects TYPE STANDARD TABLE OF cus_actobj + WITH NON-UNIQUE DEFAULT KEY, + + ty_objects_title TYPE STANDARD TABLE OF cus_actobt + WITH NON-UNIQUE DEFAULT KEY, + + BEGIN OF ty_customzing_activity, + activity_header TYPE cus_acth, + activity_customer_exit TYPE cus_actext, + activity_title TYPE ty_activity_titles, + objects TYPE ty_objects, + objects_title TYPE ty_objects_title, + END OF ty_customzing_activity. + + DATA: mv_customizing_activity TYPE cus_img_ac. + +ENDCLASS. +CLASS zcl_abapgit_object_cus2 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: ty_attribute_titles TYPE STANDARD TABLE OF cus_atrt + WITH NON-UNIQUE DEFAULT KEY, + ty_attribute_countries TYPE STANDARD TABLE OF cus_atrcou + WITH NON-UNIQUE DEFAULT KEY, + ty_attribute_components TYPE STANDARD TABLE OF tfm18 + WITH NON-UNIQUE DEFAULT KEY, + ty_attribute_comp_variants TYPE STANDARD TABLE OF cus_atrvco + WITH NON-UNIQUE DEFAULT KEY. + + TYPES: BEGIN OF ty_customizing_attribute, + header TYPE cus_atrh, + titles TYPE ty_attribute_titles, + countries TYPE ty_attribute_countries, + components TYPE ty_attribute_components, + components_variants TYPE ty_attribute_comp_variants, + END OF ty_customizing_attribute. + + DATA: mv_img_attribute TYPE cus_atr. + +ENDCLASS. +CLASS zcl_abapgit_object_dcls DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mo_dcl_handler TYPE REF TO object. " CL_ACM_DCL_HANDLER + METHODS clear_fields + CHANGING + !cg_data TYPE any + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_ddls DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + METHODS open_adt_stob + IMPORTING + iv_ddls_name TYPE tadir-obj_name + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + DATA mo_ddl_handler TYPE REF TO object. " CL_DD_DDL_HANDLER + METHODS is_baseinfo_supported + RETURNING + VALUE(rv_supported) TYPE abap_bool . + METHODS read_baseinfo + RETURNING + VALUE(rv_baseinfo_string) TYPE string. + METHODS format_source_before_serialize + CHANGING + cv_string TYPE string. + METHODS clear_fields + CHANGING + !cg_data TYPE any + RAISING + zcx_abapgit_exception . + +ENDCLASS. +CLASS zcl_abapgit_object_ddlx DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. + DATA mi_persistence TYPE REF TO if_wb_object_persist. + DATA mi_data_model TYPE REF TO if_wb_object_data_model. + DATA mv_object_key TYPE seu_objkey. + METHODS clear_fields + CHANGING + !cg_data TYPE any + RAISING + zcx_abapgit_exception . + +ENDCLASS. +CLASS zcl_abapgit_object_devc DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL. + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_local_devclass TYPE devclass . + + METHODS get_package + RETURNING + VALUE(ri_package) TYPE REF TO if_package + RAISING + zcx_abapgit_exception . + METHODS update_pinf_usages + IMPORTING + !ii_package TYPE REF TO if_package + !it_usage_data TYPE scomppdata + RAISING + zcx_abapgit_exception . + METHODS set_lock + IMPORTING + !ii_package TYPE REF TO if_package + !iv_lock TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS unlock_and_raise_error + IMPORTING + !ii_package TYPE REF TO if_package + RAISING + zcx_abapgit_exception . + METHODS is_empty + IMPORTING + !iv_package_name TYPE devclass + RETURNING + VALUE(rv_is_empty) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS load_package + IMPORTING + !iv_package_name TYPE devclass + RETURNING + VALUE(ri_package) TYPE REF TO if_package + RAISING + zcx_abapgit_exception . + METHODS is_local + IMPORTING + !iv_package_name TYPE devclass + RETURNING + VALUE(rv_is_local) TYPE abap_bool . + METHODS remove_obsolete_tadir + IMPORTING + !iv_package_name TYPE devclass + RAISING + zcx_abapgit_exception. + METHODS adjust_sw_component + CHANGING + cv_dlvunit TYPE dlvunit. +ENDCLASS. +CLASS zcl_abapgit_object_dial DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_dialog_module, + tdct TYPE tdct, + dia_pars TYPE STANDARD TABLE OF diapar + WITH NON-UNIQUE DEFAULT KEY, + END OF ty_dialog_module. + + METHODS: + _read_tdct + RETURNING + VALUE(rs_tdct) TYPE tdct. + +ENDCLASS. +CLASS zcl_abapgit_object_doct DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_id TYPE dokhl-id VALUE 'TX' ##NO_TEXT. + CONSTANTS c_name TYPE string VALUE 'DOC' ##NO_TEXT. + DATA mi_longtexts TYPE REF TO zif_abapgit_longtexts . +ENDCLASS. +CLASS zcl_abapgit_object_docv DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_data, + doctitle TYPE dsyst-doktitle, + head TYPE thead, + lines TYPE tline_tab, + END OF ty_data. + + CONSTANTS c_typ TYPE dokhl-typ VALUE 'E' ##NO_TEXT. + CONSTANTS c_version TYPE dokhl-dokversion VALUE '0001' ##NO_TEXT. + CONSTANTS c_name TYPE string VALUE 'DOC' ##NO_TEXT. + + DATA mv_id TYPE dokhl-id. + DATA mv_doc_object TYPE dokhl-object. + + METHODS read + RETURNING + VALUE(rs_data) TYPE ty_data. +ENDCLASS. +CLASS zcl_abapgit_object_doma DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_dd01_text, + ddlanguage TYPE dd01v-ddlanguage, + ddtext TYPE dd01v-ddtext, + END OF ty_dd01_text . + TYPES: + BEGIN OF ty_dd07_text, + valpos TYPE dd07v-valpos, + ddlanguage TYPE dd07v-ddlanguage, + domvalue_l TYPE dd07v-domvalue_l, + domvalue_h TYPE dd07v-domvalue_h, + ddtext TYPE dd07v-ddtext, + domval_ld TYPE dd07v-domval_ld, + domval_hd TYPE dd07v-domval_hd, + END OF ty_dd07_text . + TYPES: + ty_dd01_texts TYPE STANDARD TABLE OF ty_dd01_text . + TYPES: + ty_dd07_texts TYPE STANDARD TABLE OF ty_dd07_text . + + " Fields that are not part of dd01v + TYPES: + BEGIN OF ty_extra, + abap_language_version TYPE c LENGTH 1, + END OF ty_extra. + + CONSTANTS c_longtext_id_doma TYPE dokil-id VALUE 'DO' ##NO_TEXT. + + METHODS serialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + !it_dd07v TYPE dd07v_tab + RAISING + zcx_abapgit_exception . + METHODS deserialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + !is_dd01v TYPE dd01v + !it_dd07v TYPE dd07v_tab + RAISING + zcx_abapgit_exception . + + METHODS handle_dependencies + IMPORTING + !iv_step TYPE zif_abapgit_objects=>ty_deserialization_step + CHANGING + !cv_exit TYPE dd01v-convexit + !cv_done TYPE abap_bool. + + METHODS adjust_exit + CHANGING + !cv_exit TYPE dd01v-convexit. + + METHODS check_exit + IMPORTING + !iv_exit TYPE dd01v-convexit + RETURNING + VALUE(rv_done) TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_object_drul DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: + clear_fields + CHANGING + cs_dependency_rule TYPE any, + + clear_field + IMPORTING + iv_fieldname TYPE csequence + CHANGING + cs_dependency_rule TYPE any, + + fill_metadata_from_db + CHANGING + cs_dependency_rule TYPE any + RAISING + zcx_abapgit_exception, + + get_wb_object_operator + RETURNING + VALUE(ri_wb_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception. + + DATA: + mr_dependency_rule TYPE REF TO data, + mv_dependency_rule_key TYPE seu_objkey, + mi_persistence TYPE REF TO if_wb_object_persist, + mi_wb_object_operator TYPE REF TO object. +ENDCLASS. +CLASS zcl_abapgit_object_dsys DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + PRIVATE SECTION. + + CONSTANTS: c_typ TYPE dokhl-typ VALUE 'E', + c_id TYPE dokhl-id VALUE 'HY'. + + DATA: mv_doc_object TYPE sobj_name. + + TYPES: BEGIN OF ty_data, + doctitle TYPE dsyst-doktitle, + head TYPE thead, + lines TYPE tline_tab, + END OF ty_data. + + METHODS deserialize_dsys + IMPORTING + ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception. + + METHODS get_main_lang + RETURNING + VALUE(rv_language) TYPE spras. + +ENDCLASS. +CLASS zcl_abapgit_object_dtdc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: + clear_fields + CHANGING + cs_dynamic_cache TYPE any, + + clear_field + IMPORTING + iv_fieldname TYPE csequence + CHANGING + cs_dynamic_cache TYPE any, + + fill_metadata_from_db + CHANGING + cs_dynamic_cache TYPE any + RAISING + zcx_abapgit_exception, + + get_wb_object_operator + RETURNING + VALUE(ri_wb_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception, + + has_own_wb_data_class + RETURNING + VALUE(rv_supported) TYPE abap_bool. + + DATA: + mr_dynamic_cache TYPE REF TO data, + mv_dynamic_cache_key TYPE seu_objkey, + mv_has_own_wb_data_class TYPE abap_bool, + mi_persistence TYPE REF TO if_wb_object_persist, + mi_wb_object_operator TYPE REF TO object. +ENDCLASS. +CLASS zcl_abapgit_object_dtel DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_dd04_text, + ddlanguage TYPE dd04t-ddlanguage, + ddtext TYPE dd04t-ddtext, + reptext TYPE dd04t-reptext, + scrtext_s TYPE dd04t-scrtext_s, + scrtext_m TYPE dd04t-scrtext_m, + scrtext_l TYPE dd04t-scrtext_l, + END OF ty_dd04_text . + TYPES: + ty_dd04_texts TYPE STANDARD TABLE OF ty_dd04_text . + + " Fields that are not part of dd04v + TYPES: + BEGIN OF ty_extra, + abap_language_version TYPE uccheck, + END OF ty_extra. + + CONSTANTS c_longtext_id_dtel TYPE dokil-id VALUE 'DE' ##NO_TEXT. + CONSTANTS c_longtext_id_dtel_suppl TYPE dokil-id VALUE 'DZ' ##NO_TEXT. + + METHODS serialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + !is_dd04v TYPE dd04v + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_ecatt_super DEFINITION + INHERITING FROM zcl_abapgit_objects_super + ABSTRACT + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + METHODS: + get_object_type ABSTRACT + RETURNING VALUE(rv_object_type) TYPE etobj_type, + + get_upload ABSTRACT + RETURNING + VALUE(ro_upload) TYPE REF TO cl_apl_ecatt_upload, + + get_download ABSTRACT + RETURNING + VALUE(ro_download) TYPE REF TO cl_apl_ecatt_download, + + get_lock_object ABSTRACT + RETURNING + VALUE(rv_lock_object) TYPE eqeobj. + + PRIVATE SECTION. + TYPES: + BEGIN OF ty_last_changed, + luser TYPE syuname, + ldate TYPE d, + ltime TYPE t, + END OF ty_last_changed. + + CONSTANTS: + BEGIN OF c_name, + version TYPE string VALUE 'VERSION' ##NO_TEXT, + versions TYPE string VALUE 'VERSIONS' ##NO_TEXT, + END OF c_name, + c_default_version TYPE etobj_ver VALUE '1' ##NO_TEXT. + + CLASS-METHODS: + is_change_more_recent_than + IMPORTING + is_currently_changed TYPE ty_last_changed + is_last_changed TYPE ty_last_changed + RETURNING + VALUE(rv_is_change_more_recent) TYPE abap_bool. + + DATA: + mv_object_name TYPE etobj_name. + + METHODS: + get_changed_date + IMPORTING + ii_document TYPE REF TO if_ixml_document + RETURNING + VALUE(rv_changed_date) TYPE d, + + get_changed_time + IMPORTING + ii_document TYPE REF TO if_ixml_document + RETURNING + VALUE(rv_changed_time) TYPE t, + + get_changed_by_user + IMPORTING + ii_document TYPE REF TO if_ixml_document + RETURNING + VALUE(rv_changed_by_user) TYPE syuname, + + get_change_information + IMPORTING + is_version_info TYPE etversinfo + RETURNING + VALUE(rs_change_information) TYPE ty_last_changed + RAISING + cx_ecatt_apl + zcx_abapgit_exception, + + clear_attributes + CHANGING + ci_document TYPE REF TO if_ixml_document, + + clear_elements + CHANGING + ci_document TYPE REF TO if_ixml_document, + + get_version_from_node + IMPORTING + ii_node TYPE REF TO if_ixml_node + RETURNING + VALUE(rv_version) TYPE string, + + deserialize_version + IMPORTING + ii_version_node TYPE REF TO if_ixml_node + iv_package TYPE devclass + RAISING + zcx_abapgit_exception, + + serialize_version + IMPORTING + iv_version TYPE etversinfo-version + CHANGING + ci_node TYPE REF TO if_ixml_element + RAISING + cx_ecatt + zcx_abapgit_exception, + + clear_element + IMPORTING + iv_name TYPE csequence + CHANGING + ci_document TYPE REF TO if_ixml_document, + + clear_element_collection + IMPORTING + iv_name TYPE csequence + CHANGING + ci_document TYPE REF TO if_ixml_document, + + serialize_versions + IMPORTING + it_version_info TYPE etversinfo_tabtype + CHANGING + ci_document TYPE REF TO if_ixml_document + RAISING + cx_ecatt + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_object_ecat DEFINITION + INHERITING FROM zcl_abapgit_object_ecatt_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + PROTECTED SECTION. + METHODS: + get_object_type REDEFINITION, + get_upload REDEFINITION, + get_download REDEFINITION, + get_lock_object REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_ecsd DEFINITION + INHERITING FROM zcl_abapgit_object_ecatt_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + PROTECTED SECTION. + METHODS: + get_object_type REDEFINITION, + get_upload REDEFINITION, + get_download REDEFINITION, + get_lock_object REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_ecsp DEFINITION + INHERITING FROM zcl_abapgit_object_ecatt_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + PROTECTED SECTION. + METHODS: + get_object_type REDEFINITION, + get_upload REDEFINITION, + get_download REDEFINITION, + get_lock_object REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_ectc DEFINITION + INHERITING FROM zcl_abapgit_object_ecatt_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + PROTECTED SECTION. + METHODS: + get_object_type REDEFINITION, + get_upload REDEFINITION, + get_download REDEFINITION, + get_lock_object REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_ectd DEFINITION + INHERITING FROM zcl_abapgit_object_ecatt_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + PROTECTED SECTION. + METHODS: + get_object_type REDEFINITION, + get_upload REDEFINITION, + get_download REDEFINITION, + get_lock_object REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_ecvo DEFINITION + INHERITING FROM zcl_abapgit_object_ecatt_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + PROTECTED SECTION. + METHODS: + get_object_type REDEFINITION, + get_upload REDEFINITION, + get_download REDEFINITION, + get_lock_object REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_enhc DEFINITION + INHERITING FROM zcl_abapgit_objects_super. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: + mv_composite_id TYPE enhcompositename. + +ENDCLASS. +CLASS zcl_abapgit_object_enho DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS: + factory + IMPORTING + iv_tool TYPE enhtooltype + RETURNING + VALUE(ri_enho) TYPE REF TO zif_abapgit_object_enho + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_enhs DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: + factory + IMPORTING + iv_tool TYPE enhtooltype + RETURNING + VALUE(ri_enho) TYPE REF TO zif_abapgit_object_enhs + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_enqu DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: ty_dd27p TYPE STANDARD TABLE OF dd27p WITH DEFAULT KEY. + + " Fields that are not part of dd25v + TYPES: + BEGIN OF ty_extra, + abap_language_version TYPE uccheck, + END OF ty_extra. + + METHODS _clear_dd27p_fields CHANGING ct_dd27p TYPE ty_dd27p. + +ENDCLASS. +CLASS zcl_abapgit_object_ensc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_fdt0 DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + PRIVATE SECTION. + + METHODS check_is_local + RETURNING + VALUE(rv_is_local) TYPE abap_bool . + METHODS get_application_id + RETURNING + VALUE(rv_application_id) TYPE fdt_admn_0000s-application_id . + METHODS before_xml_deserialize + IMPORTING + !iv_package TYPE devclass + EXPORTING + !ev_create TYPE abap_bool + !ev_is_local TYPE abap_bool + CHANGING + !co_dom_tree TYPE REF TO if_ixml_document + RAISING + zcx_abapgit_exception . + METHODS filter_xml_serialize + CHANGING + !co_ixml_element TYPE REF TO if_ixml_element + RAISING + zcx_abapgit_exception . + METHODS set_field + IMPORTING + !iv_name TYPE string + !iv_value TYPE string DEFAULT '' + CHANGING + !co_ixml_element TYPE REF TO if_ixml_element + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_form DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: c_objectname_form TYPE thead-tdobject VALUE 'FORM' ##NO_TEXT. + CONSTANTS: c_objectname_tdlines TYPE thead-tdobject VALUE 'TDLINES' ##NO_TEXT. + CONSTANTS: c_extension_xml TYPE string VALUE 'xml' ##NO_TEXT. + DATA: mv_form_name TYPE itcta-tdform. + + TYPES: BEGIN OF ty_s_form_data, + form_header TYPE itcta, + text_header TYPE thead, + orig_language TYPE sy-langu, + pages TYPE STANDARD TABLE OF itctg WITH DEFAULT KEY, + page_windows TYPE STANDARD TABLE OF itcth WITH DEFAULT KEY, + paragraphs TYPE STANDARD TABLE OF itcdp WITH DEFAULT KEY, + strings TYPE STANDARD TABLE OF itcds WITH DEFAULT KEY, + tabs TYPE STANDARD TABLE OF itcdq WITH DEFAULT KEY, + windows TYPE STANDARD TABLE OF itctw WITH DEFAULT KEY, + END OF ty_s_form_data, + ty_t_form_data TYPE STANDARD TABLE OF ty_s_form_data WITH DEFAULT KEY, + ty_t_form_header TYPE STANDARD TABLE OF itcta WITH DEFAULT KEY, + ty_s_form_header TYPE LINE OF ty_t_form_header, + ty_t_text_header TYPE STANDARD TABLE OF thead WITH DEFAULT KEY, + ty_s_text_header TYPE LINE OF ty_t_text_header, + ty_t_lines TYPE tline_tab. + + METHODS get_last_changes + IMPORTING + iv_form_name TYPE zif_abapgit_definitions=>ty_item-obj_name + RETURNING + VALUE(rs_last_changed) TYPE ty_s_form_header. + + METHODS build_extra_from_header + IMPORTING + is_header TYPE ty_s_form_header + RETURNING + VALUE(rv_result) TYPE string. + + METHODS build_extra_from_header_old + IMPORTING + is_header TYPE ty_s_form_header + RETURNING + VALUE(rv_result) TYPE string. + + METHODS _save_form + IMPORTING + it_lines TYPE ty_t_lines + CHANGING + cs_form_data TYPE ty_s_form_data. + + METHODS extract_tdlines + IMPORTING + is_form_data TYPE ty_s_form_data + RETURNING + VALUE(rt_lines) TYPE ty_t_lines + RAISING + zcx_abapgit_exception. + + METHODS _clear_changed_fields + CHANGING + cs_form_data TYPE ty_s_form_data. + + METHODS compress_lines + IMPORTING + is_form_data TYPE ty_s_form_data + it_lines TYPE ty_t_lines + RAISING + zcx_abapgit_exception. + + METHODS find_form + IMPORTING + iv_object_name TYPE zif_abapgit_definitions=>ty_item-obj_name + RETURNING + VALUE(rt_text_header) TYPE ty_t_text_header. + + METHODS _read_form + IMPORTING + is_text_header TYPE ty_s_text_header + EXPORTING + ev_form_found TYPE abap_bool + es_form_data TYPE ty_s_form_data + et_lines TYPE ty_t_lines. + + METHODS _sort_tdlines_by_windows + CHANGING + ct_form_windows TYPE ty_s_form_data-windows + ct_lines TYPE ty_t_lines. + + METHODS order_check_and_insert + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_object_ftgl DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: + mv_toggle_id TYPE c LENGTH 40, "sftgl_ft_id + mr_toggle TYPE REF TO data. + + METHODS: + clear_field + IMPORTING + iv_fieldname TYPE string + CHANGING + cg_header TYPE any. + +ENDCLASS. +CLASS zcl_abapgit_object_g4ba DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_g4bs DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_http DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object. + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: BEGIN OF ty_uconservhttphandler, + id TYPE c LENGTH 30, + version TYPE c LENGTH 1, + serviceorder TYPE n LENGTH 2, + servicehandler TYPE c LENGTH 30, + END OF ty_uconservhttphandler. + TYPES: BEGIN OF ty_uconhttpservtext, + id TYPE c LENGTH 30, + version TYPE c LENGTH 1, + lang TYPE c LENGTH 1, + shorttext TYPE c LENGTH 255, + END OF ty_uconhttpservtext. + TYPES: BEGIN OF ty_handler, + id TYPE c LENGTH 30, + version TYPE c LENGTH 1, + serviceorder TYPE n LENGTH 2, + servicehandler TYPE c LENGTH 30, + END OF ty_handler. + TYPES: BEGIN OF ty_gs_object_version, + id TYPE c LENGTH 1, + object_state TYPE c LENGTH 1, + END OF ty_gs_object_version. + + TYPES: BEGIN OF ty_icf_node, + icfname TYPE c LENGTH 15, + icfparguid TYPE c LENGTH 25, + END OF ty_icf_node. + +ENDCLASS. +CLASS zcl_abapgit_object_iamu DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_internet_appl_comp_binary, + attributes TYPE w3mimeattr, + source TYPE w3mimetabtype, + length TYPE i, + extension TYPE string, + END OF ty_internet_appl_comp_binary. + + DATA: mi_mime_api TYPE REF TO if_w3_api_mime. + + METHODS: + get_extension + IMPORTING + iv_name TYPE csequence + iv_data TYPE xstring + RETURNING + VALUE(rv_extension) TYPE string, + + load_mime_api + RAISING + zcx_abapgit_exception, + + read + RETURNING + VALUE(rs_internet_appl_comp_binary) TYPE ty_internet_appl_comp_binary + RAISING + zcx_abapgit_exception, + + save + IMPORTING + is_internet_appl_comp_binary TYPE ty_internet_appl_comp_binary + RAISING + zcx_abapgit_exception, + + lock + IMPORTING + iv_changable TYPE abap_bool + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_iarp DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: + ms_name TYPE w3resokey. + + METHODS: + read + EXPORTING es_attributes TYPE w3resoattr + et_parameters TYPE w3resopara_tabletype + RAISING zcx_abapgit_exception, + + save + IMPORTING is_attributes TYPE w3resoattr + it_parameters TYPE w3resopara_tabletype + RAISING zcx_abapgit_exception, + + w3_api_load + RETURNING VALUE(ri_resource) TYPE REF TO if_w3_api_resource + RAISING zcx_abapgit_exception, + + w3_api_get_attributes + IMPORTING ii_resource TYPE REF TO if_w3_api_resource + RETURNING VALUE(rs_attributes) TYPE w3resoattr + RAISING zcx_abapgit_exception, + + w3_api_get_parameters + IMPORTING ii_resource TYPE REF TO if_w3_api_resource + RETURNING VALUE(rt_parameters) TYPE w3resopara_tabletype + RAISING zcx_abapgit_exception, + + w3_api_create_new + IMPORTING is_attributes TYPE w3resoattr + RETURNING VALUE(ri_resource) TYPE REF TO if_w3_api_resource + RAISING zcx_abapgit_exception, + + w3_api_set_attributes + IMPORTING ii_resource TYPE REF TO if_w3_api_resource + is_attributes TYPE w3resoattr + RAISING zcx_abapgit_exception, + + w3_api_set_parameters + IMPORTING ii_resource TYPE REF TO if_w3_api_resource + it_parameters TYPE w3resopara_tabletype + RAISING zcx_abapgit_exception, + + w3_api_save + IMPORTING ii_resource TYPE REF TO if_w3_api_resource + RAISING zcx_abapgit_exception, + + w3_api_set_changeable + IMPORTING ii_resource TYPE REF TO if_w3_api_resource + iv_changeable TYPE abap_bool DEFAULT abap_true + RAISING zcx_abapgit_exception, + + w3_api_delete + IMPORTING ii_resource TYPE REF TO if_w3_api_resource + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_iasp DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: + mv_name TYPE itsappl. + + METHODS: + read + EXPORTING es_attr TYPE w3servattr + et_parameters TYPE w3servpara_tabletype + RAISING zcx_abapgit_exception, + + save + IMPORTING is_attr TYPE w3servattr + it_parameters TYPE w3servpara_tabletype + RAISING zcx_abapgit_exception, + + w3_api_load + RETURNING VALUE(ri_service) TYPE REF TO if_w3_api_service + RAISING zcx_abapgit_exception, + + w3_api_get_attributes + IMPORTING ii_service TYPE REF TO if_w3_api_service + RETURNING VALUE(rs_attributes) TYPE w3servattr, + + w3_api_get_parameters + IMPORTING ii_service TYPE REF TO if_w3_api_service + RETURNING VALUE(rt_parameters) TYPE w3servpara_tabletype, + + w3_api_create_new + IMPORTING is_attributes TYPE w3servattr + RETURNING VALUE(ri_service) TYPE REF TO if_w3_api_service + RAISING zcx_abapgit_exception, + + w3_api_set_attributes + IMPORTING ii_service TYPE REF TO if_w3_api_service + is_attributes TYPE w3servattr + RAISING zcx_abapgit_exception, + + w3_api_set_parameters + IMPORTING ii_service TYPE REF TO if_w3_api_service + it_parameters TYPE w3servpara_tabletype + RAISING zcx_abapgit_exception, + + w3_api_save + IMPORTING ii_service TYPE REF TO if_w3_api_service + RAISING zcx_abapgit_exception, + + w3_api_set_changeable + IMPORTING ii_service TYPE REF TO if_w3_api_service + iv_changeable TYPE abap_bool DEFAULT abap_true + RAISING zcx_abapgit_exception, + + w3_api_delete + IMPORTING ii_service TYPE REF TO if_w3_api_service + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_iatu DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: + read + EXPORTING es_attr TYPE w3tempattr + ev_source TYPE string + RAISING zcx_abapgit_exception, + save + IMPORTING + is_attr TYPE w3tempattr + iv_source TYPE string + RAISING zcx_abapgit_exception, + w3_api_load + IMPORTING is_name TYPE iacikeyt + RETURNING VALUE(ri_template) TYPE REF TO if_w3_api_template + RAISING zcx_abapgit_exception, + w3_api_set_changeable + IMPORTING iv_changeable TYPE abap_bool + ii_template TYPE REF TO if_w3_api_template + RAISING zcx_abapgit_exception, + w3_api_delete + IMPORTING ii_template TYPE REF TO if_w3_api_template + RAISING zcx_abapgit_exception, + w3_api_save + IMPORTING ii_template TYPE REF TO if_w3_api_template + RAISING zcx_abapgit_exception, + w3_api_get_attributes + IMPORTING ii_template TYPE REF TO if_w3_api_template + RETURNING VALUE(rs_attributes) TYPE w3tempattr + RAISING zcx_abapgit_exception, + w3_api_get_source + IMPORTING ii_template TYPE REF TO if_w3_api_template + RETURNING VALUE(rt_source) TYPE w3htmltabtype + RAISING zcx_abapgit_exception, + w3_api_create_new + IMPORTING is_template_data TYPE w3tempattr + RETURNING VALUE(ri_template) TYPE REF TO if_w3_api_template + RAISING zcx_abapgit_exception, + w3_api_set_attributes + IMPORTING ii_template TYPE REF TO if_w3_api_template + is_attr TYPE w3tempattr + RAISING zcx_abapgit_exception, + w3_api_set_source + IMPORTING ii_template TYPE REF TO if_w3_api_template + it_source TYPE w3htmltabtype + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_iaxu DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mv_source_style_2006 TYPE w3style VALUE 'XML', + mv_generator_class TYPE w3styleclass VALUE 'CL_ITS_GENERATE_XML3'. + + METHODS: + read + RETURNING VALUE(rs_attr) TYPE w3tempattr + RAISING zcx_abapgit_exception, + save + IMPORTING is_attr TYPE w3tempattr + RAISING zcx_abapgit_exception, + w3_api_load + IMPORTING is_name TYPE iacikeyt + EXPORTING eo_xml_api TYPE REF TO object + es_attr TYPE w3tempattr + RAISING zcx_abapgit_exception, + w3_api_set_changeable + IMPORTING io_xml_api TYPE REF TO object + iv_changeable TYPE abap_bool + RAISING zcx_abapgit_exception, + w3_api_delete + IMPORTING io_xml_api TYPE REF TO object + RAISING zcx_abapgit_exception, + w3_api_save + IMPORTING io_xml_api TYPE REF TO object + RAISING zcx_abapgit_exception, + w3_api_create_new + IMPORTING is_attr TYPE w3tempattr + RETURNING VALUE(ro_xml_api) TYPE REF TO object + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_idoc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + CLASS-METHODS clear_idoc_segement_fields CHANGING cg_structure TYPE any. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_idoc, + attributes TYPE edi_iapi01, + t_syntax TYPE STANDARD TABLE OF edi_iapi02 WITH NON-UNIQUE DEFAULT KEY, + END OF ty_idoc. + + DATA: mv_idoctyp TYPE edi_iapi00-idoctyp. + + CLASS-METHODS clear_idoc_segement_field + IMPORTING iv_fieldname TYPE csequence + CHANGING cg_structure TYPE any. + + METHODS is_closed + RETURNING + VALUE(rv_closed) TYPE abap_bool. +ENDCLASS. +CLASS zcl_abapgit_object_iext DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_extention, + attributes TYPE edi_iapi01, + t_syntax TYPE STANDARD TABLE OF edi_iapi03 WITH NON-UNIQUE DEFAULT KEY, + END OF ty_extention. + + CONSTANTS c_dataname_iext TYPE string VALUE 'IEXT' ##NO_TEXT. + DATA: mv_extension TYPE edi_cimtyp. + +ENDCLASS. +CLASS zcl_abapgit_object_iobj DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: + clear_field + IMPORTING + iv_fieldname TYPE string + CHANGING + cg_metadata TYPE any. + +ENDCLASS. +CLASS zcl_abapgit_object_iwmo DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_iwom DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_iwpr DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_iwsg DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_iwsv DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_iwvb DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_jobd DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: ty_jd_name TYPE c LENGTH 32. + +ENDCLASS. +CLASS zcl_abapgit_object_msag DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_t100_text, + sprsl TYPE t100-sprsl, + msgnr TYPE t100-msgnr, + text TYPE t100-text, + END OF ty_t100_text . + TYPES: + ty_t100_texts TYPE STANDARD TABLE OF ty_t100_text . + TYPES: + ty_t100s TYPE STANDARD TABLE OF t100 + WITH NON-UNIQUE DEFAULT KEY . + + CONSTANTS c_longtext_id_msag TYPE dokil-id VALUE 'NA'. + + METHODS serialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS serialize_longtexts_msag + IMPORTING + !it_t100 TYPE ty_t100s + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS delete_msgid + IMPORTING + !iv_message_id TYPE arbgb + RAISING + zcx_abapgit_exception. + METHODS free_access_permission + IMPORTING + !iv_message_id TYPE arbgb . + METHODS delete_documentation + IMPORTING + !iv_message_id TYPE arbgb + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_object_nrob DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: + delete_intervals IMPORTING iv_object TYPE inri-object + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_nspc DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_nspc, + namespace TYPE trnspacet-namespace, + replicense TYPE trnspacet-replicense, + sscrflag TYPE trnspacet-sscrflag, + sapflag TYPE trnspacet-sapflag, + gen_only TYPE trnspacet-gen_only, + END OF ty_nspc . + TYPES: + BEGIN OF ty_nspc_text, + spras TYPE trnspacett-spras, + descriptn TYPE trnspacett-descriptn, + owner TYPE trnspacett-owner, + END OF ty_nspc_text . + TYPES: + ty_nspc_texts TYPE STANDARD TABLE OF ty_nspc_text . + + DATA mv_component TYPE cvers-component. + + METHODS serialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + !iv_namespace TYPE namespace + RAISING + zcx_abapgit_exception . + METHODS add_to_transport + IMPORTING + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS serialize_sw_component + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_sw_component + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_oa2p DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mv_profile TYPE c LENGTH 30. + +ENDCLASS. +CLASS zcl_abapgit_object_odso DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS: + clear_field + IMPORTING + iv_fieldname TYPE string + CHANGING + cg_metadata TYPE any. +ENDCLASS. +CLASS zcl_abapgit_object_otgr DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_otgr, + cls_type_group TYPE cls_type_group, + texts TYPE STANDARD TABLE OF cls_type_groupt WITH DEFAULT KEY, + elements TYPE STANDARD TABLE OF cls_tygr_element WITH DEFAULT KEY, + END OF ty_otgr . + + METHODS instantiate_and_lock_otgr + RETURNING + VALUE(ro_otgr) TYPE REF TO cl_cls_object_type_group + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_para DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS unlock + IMPORTING + !iv_paramid TYPE memoryid . + +ENDCLASS. +CLASS zcl_abapgit_object_pdxx_super DEFINITION + INHERITING FROM zcl_abapgit_objects_super + ABSTRACT. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + DATA ms_objkey TYPE hrsobject. + + METHODS check_subrc_for IMPORTING iv_call TYPE clike OPTIONAL + RAISING zcx_abapgit_exception. + + PRIVATE SECTION. + +ENDCLASS. +INTERFACE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa DEFERRED. +* renamed: zcl_abapgit_object_pdts :: lif_task_definition +INTERFACE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa. + + TYPES: BEGIN OF ty_task_data, + short_text TYPE hr_mcshort, + plvar TYPE plvar, + wi_text TYPE witext, + method TYPE hrs1201, + method_binding TYPE hrsmtbind, + starting_events TYPE hrsevtab, + starting_events_binding TYPE hrsevbind, + terminating_events TYPE hrsetmtab, + terminating_events_binding TYPE hrsevbind, + descriptions TYPE wstexts, + END OF ty_task_data. + + METHODS clear_origin_data. + METHODS get_definition RETURNING VALUE(rs_result) TYPE ty_task_data. + METHODS get_container RETURNING VALUE(ri_result) TYPE REF TO if_swf_cnt_container. + METHODS get_user_container RETURNING VALUE(ri_result) TYPE REF TO if_swf_cnt_container. + METHODS import_container IMPORTING iv_xml_string TYPE xstring + RAISING zcx_abapgit_exception. + METHODS create_task RAISING zcx_abapgit_exception. + METHODS save IMPORTING iv_package TYPE devclass OPTIONAL + RAISING zcx_abapgit_exception. + METHODS change_wi_text RAISING zcx_abapgit_exception. + METHODS change_method RAISING zcx_abapgit_exception. + METHODS change_start_events RAISING zcx_abapgit_exception. + METHODS change_terminating_events RAISING zcx_abapgit_exception. + METHODS change_text RAISING zcx_abapgit_exception. + +ENDINTERFACE. + +CLASS zcl_abapgit_object_pdts DEFINITION + INHERITING FROM zcl_abapgit_object_pdxx_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + METHODS zif_abapgit_object~serialize REDEFINITION. + METHODS zif_abapgit_object~deserialize REDEFINITION. + + PROTECTED SECTION. + + PRIVATE SECTION. + + DATA mv_objid TYPE hrobjid. + + METHODS get_container_xml IMPORTING ii_task TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa + RETURNING VALUE(ri_first_element) TYPE REF TO if_ixml_element + RAISING zcx_abapgit_exception. + + METHODS extract_container IMPORTING io_xml TYPE REF TO zif_abapgit_xml_input + RETURNING VALUE(rv_result) TYPE xstring. + +ENDCLASS. +CLASS zcl_abapgit_object_pers DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_personalization_object, + pers_reg TYPE spers_reg, + pers_reg_text TYPE spers_regt, + END OF ty_personalization_object. + + DATA: + mv_pers_key TYPE spers_key. + + METHODS: + get_personalization_object + IMPORTING + iv_create TYPE abap_bool OPTIONAL + iv_view_only TYPE abap_bool OPTIONAL + RETURNING + VALUE(ro_personalization_object) TYPE REF TO cl_pers_reg + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS kHGwlqJyKbsVHldwKaGddDbbHeNaet DEFINITION DEFERRED. +INTERFACE iUFTsqJyKbsVHldwKaGdXoRoiJNIwT DEFERRED. +* renamed: zcl_abapgit_object_pinf :: lif_package_interface_facade +INTERFACE iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. + TYPES ty_tpak_package_interf_elem_tt TYPE STANDARD TABLE OF tpak_package_interf_elem_ref WITH DEFAULT KEY. + + METHODS: + get_elements + RETURNING + VALUE(rt_elements) TYPE ty_tpak_package_interf_elem_tt + RAISING + zcx_abapgit_exception, + + set_elements_changeable + IMPORTING + iv_changeable TYPE abap_bool + RAISING + zcx_abapgit_exception, + + save_elements + RAISING + zcx_abapgit_exception, + + get_all_attributes + RETURNING + VALUE(rs_package_interface_data) TYPE scompidtln + RAISING + zcx_abapgit_exception, + + set_changeable + IMPORTING + iv_changeable TYPE abap_bool + RAISING + zcx_abapgit_exception, + + delete + RAISING + zcx_abapgit_exception, + + save + RAISING + zcx_abapgit_exception, + + remove_elements + IMPORTING + it_elements TYPE tpak_package_interf_elem_list + RAISING + zcx_abapgit_exception, + + add_elements + IMPORTING + it_elements_data TYPE scomeldata + RAISING + zcx_abapgit_exception, + + set_all_attributes + IMPORTING + is_package_interface_data TYPE scompidtln + is_data_sign TYPE scompisign + RAISING + zcx_abapgit_exception, + + get_changeable + RETURNING + VALUE(rv_changeable) TYPE abap_bool + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +* renamed: zcl_abapgit_object_pinf :: lcl_package_interface_facade +CLASS kHGwlqJyKbsVHldwKaGddDbbHeNaet DEFINITION. + + PUBLIC SECTION. + INTERFACES: + iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. + + METHODS: + constructor + IMPORTING + ii_interface TYPE REF TO if_package_interface. + + PRIVATE SECTION. + DATA: mi_interface TYPE REF TO if_package_interface. + +ENDCLASS. + +CLASS zcl_abapgit_object_pinf DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_pinf, + attributes TYPE scompidtln, + elements TYPE STANDARD TABLE OF scomeldtln WITH DEFAULT KEY, + END OF ty_pinf . + TYPES: + ty_elements TYPE STANDARD TABLE OF tpak_package_interf_elem_ref WITH DEFAULT KEY . + + METHODS create_or_load + IMPORTING + !is_pinf TYPE ty_pinf + !iv_package TYPE devclass + RETURNING + VALUE(ri_interface) TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT + RAISING + zcx_abapgit_exception . + METHODS delete_elements + IMPORTING + !ii_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT + RAISING + zcx_abapgit_exception . + METHODS update_attributes + IMPORTING + !iv_package TYPE devclass + !is_pinf TYPE ty_pinf + !ii_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT + RAISING + zcx_abapgit_exception . + METHODS update_elements + IMPORTING + !iv_package TYPE devclass + !is_pinf TYPE ty_pinf + !ii_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT + RAISING + zcx_abapgit_exception . + METHODS load + IMPORTING + iv_name TYPE scomifnam + RETURNING + VALUE(ri_interface) TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. + METHODS create_facade + IMPORTING + ii_interface TYPE REF TO if_package_interface + RETURNING + VALUE(ri_facade) TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. + +ENDCLASS. +CLASS zcl_abapgit_object_prag DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_pragma, + pragma TYPE c LENGTH 40, + extension TYPE c LENGTH 1, + signature TYPE c LENGTH 10, + description TYPE c LENGTH 255, + END OF ty_pragma. + +ENDCLASS. +CLASS zcl_abapgit_object_saxx_super DEFINITION + INHERITING FROM zcl_abapgit_objects_super + ABSTRACT + CREATE PUBLIC . + +* common class for SAPC and SAMC objects + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL. + + PROTECTED SECTION. + + METHODS get_persistence_class_name ABSTRACT + RETURNING + VALUE(rv_persistence_class_name) TYPE seoclsname . + METHODS get_data_class_name ABSTRACT + RETURNING + VALUE(rv_data_class_name) TYPE seoclsname . + METHODS get_data_structure_name ABSTRACT + RETURNING + VALUE(rv_data_structure_name) TYPE string . + METHODS get_lock_object ABSTRACT + RETURNING + VALUE(rv_lock_object) TYPE string. + METHODS create_channel_objects + RAISING + zcx_abapgit_type_not_supported . + + PRIVATE SECTION. + + DATA mi_persistence TYPE REF TO if_wb_object_persist . + DATA mi_appl_obj_data TYPE REF TO if_wb_object_data_model . + DATA mv_data_structure_name TYPE string . + DATA mv_appl_obj_cls_name TYPE seoclsname . + DATA mv_persistence_cls_name TYPE seoclsname . + DATA mv_object_key TYPE seu_objkey . + + METHODS get_data + EXPORTING + !eg_data TYPE any + RAISING + zcx_abapgit_exception . + METHODS lock + RAISING + zcx_abapgit_exception . + METHODS unlock + RAISING + zcx_abapgit_exception . + METHODS get_names . + +ENDCLASS. +CLASS zcl_abapgit_object_samc DEFINITION + INHERITING FROM zcl_abapgit_object_saxx_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + + METHODS get_data_class_name + REDEFINITION . + METHODS get_data_structure_name + REDEFINITION . + METHODS get_persistence_class_name + REDEFINITION . + METHODS get_lock_object + REDEFINITION . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_sapc DEFINITION + INHERITING FROM zcl_abapgit_object_saxx_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + + METHODS get_data_class_name + REDEFINITION . + METHODS get_data_structure_name + REDEFINITION . + METHODS get_persistence_class_name + REDEFINITION . + METHODS get_lock_object + REDEFINITION . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_scp1 DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + TYPES: + BEGIN OF ty_scp1, + scprattr TYPE scprattr, + scprtext TYPE STANDARD TABLE OF scprtext WITH DEFAULT KEY, + scprvals TYPE STANDARD TABLE OF scprvals WITH DEFAULT KEY, + scprvall TYPE STANDARD TABLE OF scprvall WITH DEFAULT KEY, + scprreca TYPE STANDARD TABLE OF scprreca WITH DEFAULT KEY, + scprfldv TYPE STANDARD TABLE OF scprfldv WITH DEFAULT KEY, + subprofs TYPE STANDARD TABLE OF scprpprl WITH DEFAULT KEY, + END OF ty_scp1 . + + METHODS dequeue . + METHODS enqueue + RAISING + zcx_abapgit_exception . + METHODS save + IMPORTING + !is_scp1 TYPE ty_scp1 + RAISING + zcx_abapgit_exception . + METHODS save_hier + IMPORTING + !is_scp1 TYPE ty_scp1 + RAISING + zcx_abapgit_exception . + METHODS adjust_inbound + CHANGING + !cs_scp1 TYPE ty_scp1 . + METHODS adjust_outbound + CHANGING + !cs_scp1 TYPE ty_scp1 . + METHODS load + CHANGING + !cs_scp1 TYPE ty_scp1 . + METHODS load_hier + CHANGING + !cs_scp1 TYPE ty_scp1 . + METHODS call_delete_fms + IMPORTING + !iv_profile_id TYPE scpr_id + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_scvi DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_screen_variant, + shdsvci TYPE shdsvci, + shdsvtxci TYPE STANDARD TABLE OF shdsvtxci WITH DEFAULT KEY, + shdsvfvci TYPE STANDARD TABLE OF shdsvfvci WITH DEFAULT KEY, + shdguixt TYPE STANDARD TABLE OF shdguixt WITH DEFAULT KEY, + shdgxtcode TYPE STANDARD TABLE OF shdgxtcode WITH DEFAULT KEY, + END OF ty_screen_variant . +ENDCLASS. +CLASS zcl_abapgit_object_sfbf DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_longtext_id_sfbf TYPE dokil-id VALUE 'BF'. + + DATA mv_bf TYPE sfw_bfunction. + + METHODS: + unlock, + activate + RAISING zcx_abapgit_exception, + create + RETURNING VALUE(ro_bf) TYPE REF TO cl_sfw_bf + RAISING zcx_abapgit_exception, + get + RETURNING VALUE(ro_bf) TYPE REF TO cl_sfw_bf + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_sfbs DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_longtext_id_sfbs TYPE dokil-id VALUE 'BS'. + + DATA mv_bfset TYPE sfw_bset. + + METHODS: + unlock, + activate + RAISING zcx_abapgit_exception, + create + RETURNING VALUE(ro_bfs) TYPE REF TO cl_sfw_bfs + RAISING zcx_abapgit_exception, + get + RETURNING VALUE(ro_bfs) TYPE REF TO cl_sfw_bfs + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_sfpf DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + CLASS-METHODS fix_oref + IMPORTING + !ii_document TYPE REF TO if_ixml_document + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_layout_file_ext TYPE string VALUE 'xdp'. + + METHODS: + load + RETURNING VALUE(ri_wb_form) TYPE REF TO if_fp_wb_form + RAISING zcx_abapgit_exception, + form_to_xstring + RETURNING VALUE(rv_xstr) TYPE xstring + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_sfpi DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: + load + RETURNING VALUE(ri_wb_interface) TYPE REF TO if_fp_wb_interface + RAISING zcx_abapgit_exception, + interface_to_xstring + RETURNING VALUE(rv_xstr) TYPE xstring + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_sfsw DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_longtext_id_sfsw TYPE dokil-id VALUE 'SW'. + + DATA mv_switch TYPE sfw_switch_id. + + METHODS: + unlock, + activate + RAISING zcx_abapgit_exception, + create + RETURNING VALUE(ro_switch) TYPE REF TO cl_sfw_sw + RAISING zcx_abapgit_exception, + get + RETURNING VALUE(ro_switch) TYPE REF TO cl_sfw_sw + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_shi3 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + METHODS has_authorization + IMPORTING + !iv_devclass TYPE devclass + !iv_structure_id TYPE hier_guid + !iv_activity TYPE activ_auth + RAISING + zcx_abapgit_exception . + METHODS is_used + IMPORTING + !iv_structure_id TYPE hier_guid + RAISING + zcx_abapgit_exception . + METHODS delete_tree_structure + IMPORTING + !iv_structure_id TYPE hier_guid . + PRIVATE SECTION. + + DATA mv_tree_id TYPE ttree-id. + + METHODS insert_transport + IMPORTING + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception. + METHODS jump_se43 + RAISING + zcx_abapgit_exception. + METHODS jump_sbach04 + RAISING + zcx_abapgit_exception. + METHODS clear_fields + CHANGING + !cs_head TYPE ttree + !ct_nodes TYPE hier_iface_t. +ENDCLASS. +CLASS zcl_abapgit_object_shi5 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: ty_ttree_extt TYPE STANDARD TABLE OF ttree_extt + WITH NON-UNIQUE DEFAULT KEY, + BEGIN OF ty_extension, + header TYPE ttree_ext, + texts TYPE ty_ttree_extt, + sequences TYPE STANDARD TABLE OF ttrees WITH NON-UNIQUE DEFAULT KEY, + END OF ty_extension. + + DATA: mv_extension TYPE hier_names. + +ENDCLASS. +CLASS zcl_abapgit_object_shi8 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mv_assignment_id TYPE hier_sfw_id. + +ENDCLASS. +CLASS zcl_abapgit_object_shlp DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS handle_dependencies + IMPORTING + !iv_step TYPE zif_abapgit_objects=>ty_deserialization_step + CHANGING + !cv_exit TYPE dd30v-selmexit + !cv_done TYPE abap_bool. + + METHODS adjust_exit + CHANGING + !cv_exit TYPE dd30v-selmexit. + + METHODS check_exit + IMPORTING + !iv_exit TYPE dd30v-selmexit + RETURNING + VALUE(rv_done) TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_object_shma DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_sicf DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES ty_hash TYPE c LENGTH 25. + + TYPES: + ty_icfhandler_tt TYPE STANDARD TABLE OF icfhandler WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_sicf_key, + icf_name TYPE icfservice-icf_name, + icfparguid TYPE icfservice-icfparguid, + END OF ty_sicf_key . + + METHODS serialize_otr + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_otr + IMPORTING + !iv_package TYPE devclass + !io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS read + IMPORTING + !iv_clear TYPE abap_bool DEFAULT abap_true + EXPORTING + !es_icfservice TYPE icfservice + !es_icfdocu TYPE icfdocu + !et_icfhandler TYPE ty_icfhandler_tt + !ev_url TYPE string + RAISING + zcx_abapgit_exception . + METHODS insert_sicf + IMPORTING + !is_icfservice TYPE icfservice + !is_icfdocu TYPE icfdocu + !it_icfhandler TYPE ty_icfhandler_tt + !iv_package TYPE devclass + !iv_url TYPE string + RAISING + zcx_abapgit_exception . + METHODS change_sicf + IMPORTING + !is_icfservice TYPE icfservice + !is_icfdocu TYPE icfdocu + !it_icfhandler TYPE ty_icfhandler_tt + !iv_package TYPE devclass + !iv_parent TYPE icfparguid + RAISING + zcx_abapgit_exception . + METHODS to_icfhndlist + IMPORTING + !it_list TYPE ty_icfhandler_tt + RETURNING + VALUE(rt_list) TYPE icfhndlist . + METHODS find_parent + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(rv_parent) TYPE icfparguid + RAISING + zcx_abapgit_exception . + + CLASS-METHODS get_hash_from_object + IMPORTING + !iv_obj_name TYPE tadir-obj_name + RETURNING + VALUE(rv_hash) TYPE ty_hash + RAISING + zcx_abapgit_exception. + + CLASS-METHODS get_icfaltname + IMPORTING + !is_icfservice TYPE icfservice + RETURNING + VALUE(rv_icfaltnme) TYPE icfservice-icfaltnme. +ENDCLASS. +CLASS zcl_abapgit_object_sktd DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mr_data TYPE REF TO data . + DATA mv_object_key TYPE seu_objkey . + DATA mi_persistence TYPE REF TO if_wb_object_persist . + DATA mi_wb_object_operator TYPE REF TO object . + + METHODS clear_fields + CHANGING + !cs_data TYPE any . + METHODS clear_field + IMPORTING + !iv_fieldname TYPE csequence + CHANGING + !cs_data TYPE any . + METHODS get_wb_object_operator + RETURNING + VALUE(ri_wb_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_smim DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + METHODS get_filename + IMPORTING iv_url TYPE string + RETURNING VALUE(rv_filename) TYPE string. + + METHODS find_content + IMPORTING iv_url TYPE string + RETURNING VALUE(rv_content) TYPE xstring + RAISING zcx_abapgit_exception. + + METHODS build_filename + IMPORTING iv_filename TYPE string + RETURNING VALUE(rv_filename) TYPE string. + + METHODS get_url_for_io + EXPORTING ev_url TYPE string + ev_is_folder TYPE abap_bool + RAISING zcx_abapgit_not_found + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_smtg DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: + mv_template_id TYPE c LENGTH 30, + mo_structdescr TYPE REF TO cl_abap_structdescr. + + METHODS: + clear_field + IMPORTING + iv_fieldname TYPE string + CHANGING + cg_header TYPE any, + + get_structure + RETURNING + VALUE(ro_structdescr) TYPE REF TO cl_abap_structdescr + RAISING + zcx_abapgit_exception, + + add_component + IMPORTING + iv_fielname TYPE string + iv_structure_name TYPE string + CHANGING + ct_components TYPE abap_component_tab + RAISING + zcx_abapgit_exception, + + get_template + EXPORTING + es_template TYPE any + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_sobj DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + METHODS get_field_rules + RETURNING + VALUE(ri_rules) TYPE REF TO zif_abapgit_field_rules. + METHODS is_locked RETURNING VALUE(rv_is_locked) TYPE abap_bool. + METHODS is_objtype_locked RETURNING VALUE(rv_is_locked) TYPE abap_bool. + METHODS is_program_locked RETURNING VALUE(rv_is_locked) TYPE abap_bool. + METHODS get_program RETURNING VALUE(rv_program) TYPE tojtb-progname. +ENDCLASS. +CLASS zcl_abapgit_object_sod1 DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: c_xml_transformation_name TYPE string VALUE 'SOD1', + c_data_model_class_name TYPE string VALUE 'CL_APS_ODA_WBI_SOD1_DATA_MODEL'. + + METHODS create_wb_object_operator + IMPORTING + !is_object_type TYPE wbobjtype + !iv_object_key TYPE seu_objkey + !iv_transport_request TYPE trkorr OPTIONAL + !iv_do_commits TYPE abap_bool DEFAULT abap_true + !iv_run_in_test_mode TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_wb_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception. + + METHODS get_wb_object_operator + IMPORTING + !is_object_type TYPE wbobjtype + !iv_object_key TYPE seu_objkey + !iv_transport_request TYPE trkorr OPTIONAL + RETURNING + VALUE(ro_wb_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception. + + METHODS clear_metadata_fields + CHANGING + !cs_data TYPE any. + + METHODS clear_content_fields + CHANGING + !cs_data TYPE any. + + METHODS clear_field + IMPORTING + !iv_fieldname TYPE csequence + CHANGING + !cs_metadata TYPE any. + +ENDCLASS. +CLASS zcl_abapgit_object_sod2 DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: c_xml_transformation_name TYPE string VALUE 'SOD2', + c_data_model_class_name TYPE string VALUE 'CL_APS_ODA_WBI_SOD2_DATA_MODEL'. + + METHODS create_wb_object_operator + IMPORTING + !is_object_type TYPE wbobjtype + !iv_object_key TYPE seu_objkey + !iv_transport_request TYPE trkorr OPTIONAL + !iv_do_commits TYPE abap_bool DEFAULT abap_true + !iv_run_in_test_mode TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_wb_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception. + + METHODS get_wb_object_operator + IMPORTING + !is_object_type TYPE wbobjtype + !iv_object_key TYPE seu_objkey + !iv_transport_request TYPE trkorr OPTIONAL + RETURNING + VALUE(ro_wb_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception. + + METHODS clear_metadata_fields + CHANGING + !cs_data TYPE any. + + METHODS clear_content_fields + CHANGING + !cs_data TYPE any. + + METHODS clear_field + IMPORTING + !iv_fieldname TYPE csequence + CHANGING + !cs_metadata TYPE any. + +ENDCLASS. +CLASS zcl_abapgit_object_sots DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_sots, + header TYPE sotr_headu, + entries TYPE sotr_textl_tt, + END OF ty_sots, + ty_sots_tt TYPE STANDARD TABLE OF ty_sots + WITH NON-UNIQUE DEFAULT KEY. + + METHODS: + read_sots + RETURNING + VALUE(rt_sots) TYPE ty_sots_tt, + + create_sots + IMPORTING + is_sots TYPE ty_sots + iv_package TYPE devclass + iv_object TYPE trobjtype + RAISING + zcx_abapgit_exception, + + get_raw_text_filename + IMPORTING + is_entry TYPE sotr_textl + RETURNING + VALUE(rv_filename) TYPE string. + +ENDCLASS. +CLASS zcl_abapgit_object_splo DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_sppf DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_sprx DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_proxy, + data TYPE string VALUE 'PROXY_DATA' ##NO_TEXT, + header TYPE string VALUE 'PROXY_HEADER' ##NO_TEXT, + END OF c_proxy . + DATA mv_object TYPE sproxhdr-object . + DATA mv_obj_name TYPE sproxhdr-obj_name . + + METHODS load_db + RETURNING + VALUE(rs_data) TYPE sprx_db_data . + METHODS get_object_and_name + EXPORTING + !ev_object TYPE sproxhdr-object + !ev_obj_name TYPE sproxhdr-obj_name . + METHODS delta_handling + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + EXPORTING + !et_sproxhdr_new TYPE sprx_hdr_t + !et_sproxdat_new TYPE sprx_dat_t + RAISING + zcx_abapgit_exception . + METHODS check_sprx_tadir + RAISING + zcx_abapgit_exception . + METHODS save + IMPORTING + !it_sproxhdr_new TYPE sprx_hdr_t + !it_sproxdat_new TYPE sprx_dat_t . +ENDCLASS. +CLASS zcl_abapgit_object_sqsc DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + " Downport original structures from + " - IF_DBPROC_PROXY_UI + " - IF_DBPROC_PROXY_BASIC_TYPES + + TYPES: + ty_db_name TYPE c LENGTH 256, + ty_abap_name TYPE c LENGTH 30, + ty_param_direction TYPE c LENGTH 10, + ty_param_kind TYPE c LENGTH 10, + ty_ddic_name TYPE ddobjname, + + BEGIN OF ty_db_simple_type_s, + name TYPE ty_db_name, + length TYPE i, + decs TYPE i, + END OF ty_db_simple_type_s, + + BEGIN OF ty_abap_simple_type_s, + name TYPE ty_abap_name, + length TYPE i, + decs TYPE i, + END OF ty_abap_simple_type_s, + + BEGIN OF ty_abap_simple_type_ui_s, + typ TYPE ty_abap_simple_type_s, + text TYPE string, + END OF ty_abap_simple_type_ui_s, + + BEGIN OF ty_header_ui_s, + db_repository_package TYPE ty_db_name, + db_repository_proc_name TYPE ty_db_name, + db_catalog_schema TYPE ty_db_name, + db_catalog_proc_name TYPE ty_db_name, + read_only TYPE abap_bool, + interface_pool TYPE ty_abap_name, + END OF ty_header_ui_s, + + BEGIN OF ty_param_ui_s, + position TYPE i, + db_name TYPE ty_db_name, + direction TYPE ty_param_direction, + kind TYPE ty_param_kind, + db_table_type_schema TYPE ty_db_name, + db_table_type_name TYPE ty_db_name, + db_table_type_is_ddic TYPE abap_bool, + transfer_table_schema TYPE ty_db_name, + transfer_table_name TYPE ty_db_name, + abap_name TYPE ty_abap_name, + abap_name_is_ro TYPE abap_bool, + ddic_table TYPE ty_ddic_name, + ddic_table_is_ro TYPE abap_bool, + END OF ty_param_ui_s, + ty_param_ui_t TYPE STANDARD TABLE OF ty_param_ui_s WITH KEY position, + + ty_abap_simple_type_ui_t TYPE STANDARD TABLE OF ty_abap_simple_type_ui_s WITH DEFAULT KEY, + + BEGIN OF ty_param_type_ui_s, + param_position TYPE i, + comp_index TYPE i, + db_comp_name TYPE ty_db_name, + abap_comp_name TYPE ty_abap_name, + abap_comp_name_is_ro TYPE abap_bool, + db_type TYPE ty_db_simple_type_s, + db_type_text TYPE string, + abap_type TYPE ty_abap_simple_type_ui_s, + abap_type_is_ro TYPE abap_bool, + abap_type_selection TYPE ty_abap_simple_type_ui_t, + ddic_type TYPE ty_ddic_name, + ddic_type_is_ro TYPE abap_bool, + END OF ty_param_type_ui_s , + ty_param_type_ui_t TYPE STANDARD TABLE OF ty_param_type_ui_s WITH KEY param_position comp_index, + + BEGIN OF ty_proxy, + description TYPE ddtext, + header TYPE ty_header_ui_s, + parameters TYPE ty_param_ui_t, + parameter_types TYPE ty_param_type_ui_t, + END OF ty_proxy. + + DATA: + mo_proxy TYPE REF TO object. + + METHODS: + delete_interface_if_it_exists + IMPORTING + iv_package TYPE devclass + iv_transport TYPE trkorr + iv_interface TYPE ty_abap_name + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_object_srfc DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_srvb DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + PRIVATE SECTION. + METHODS: + clear_fields + CHANGING + cs_service_binding TYPE any, + + clear_field + IMPORTING + iv_fieldname TYPE csequence + CHANGING + cs_service_binding TYPE any. + METHODS get_wb_object_operator + RETURNING + VALUE(ro_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception . + METHODS merge_object_data + IMPORTING + !io_object_data TYPE REF TO object + RETURNING + VALUE(ro_object_data_merged) TYPE REF TO if_wb_object_data_model + RAISING + zcx_abapgit_exception . + METHODS get_object_data + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + RETURNING + VALUE(ro_object_data) TYPE REF TO if_wb_object_data_model + RAISING + zcx_abapgit_exception . + METHODS is_ai_supported + RETURNING VALUE(rv_ai_supported) TYPE abap_bool. + + DATA: + mi_persistence TYPE REF TO if_wb_object_persist, + mv_is_inactive_supported TYPE abap_bool, + mv_service_binding_key TYPE seu_objkey, + mr_service_binding TYPE REF TO data, + mr_srvb_svrs_config TYPE REF TO object, + mo_object_operator TYPE REF TO object. +ENDCLASS. +CLASS zcl_abapgit_object_srvd DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + + PROTECTED SECTION. + + PRIVATE SECTION. + + DATA mv_service_definition_key TYPE seu_objkey . + DATA mr_service_definition TYPE REF TO data . + CONSTANTS c_source_file TYPE string VALUE 'srvdsrv' ##NO_TEXT. + CONSTANTS c_xml_parent_name TYPE string VALUE 'SRVD' ##NO_TEXT. + DATA mo_object_operator TYPE REF TO object . + + METHODS clear_fields + CHANGING + !cs_metadata TYPE any . + METHODS clear_field + IMPORTING + !iv_fieldname TYPE csequence + CHANGING + !cs_metadata TYPE any . + METHODS get_object_data + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + RETURNING + VALUE(ro_object_data) TYPE REF TO if_wb_object_data_model + RAISING + zcx_abapgit_exception . + METHODS get_wb_object_operator + RETURNING + VALUE(ro_object_operator) TYPE REF TO object + RAISING + zcx_abapgit_exception . + METHODS merge_object_data + IMPORTING + !io_object_data TYPE REF TO object + RETURNING + VALUE(ro_object_data_merged) TYPE REF TO if_wb_object_data_model + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_ssfo DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + ty_string_range TYPE RANGE OF string . + + CLASS-DATA gt_range_node_codes TYPE ty_string_range . + CONSTANTS c_prefix TYPE string VALUE 'File:'. + + METHODS fix_ids + IMPORTING + !ii_xml_doc TYPE REF TO if_ixml_document . + CLASS-METHODS sort_texts + IMPORTING + !ii_xml_doc TYPE REF TO if_ixml_document + RAISING + zcx_abapgit_exception . + METHODS get_range_node_codes + RETURNING + VALUE(rt_range_node_codes) TYPE ty_string_range . + METHODS deserialize_sources + IMPORTING + !ii_node TYPE REF TO if_ixml_node + RAISING + zcx_abapgit_exception. + METHODS serialize_sources + IMPORTING + !ii_node TYPE REF TO if_ixml_node + RAISING + zcx_abapgit_exception. + METHODS get_hash_for_path + IMPORTING + !ii_node TYPE REF TO if_ixml_node + RETURNING + VALUE(rv_hash) TYPE string + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_object_ssst DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + CONSTANTS: c_style_active TYPE tdactivate VALUE 'A'. + PROTECTED SECTION. + PRIVATE SECTION. + METHODS validate_font + IMPORTING iv_tdfamily TYPE tdfamily + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_stvi DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_transaction_variant, + shdtvciu TYPE shdtvciu, + shdttciu TYPE STANDARD TABLE OF shdttciu WITH DEFAULT KEY, + shdfvguicu TYPE STANDARD TABLE OF shdfvguicu WITH DEFAULT KEY, + shdtvsvciu TYPE STANDARD TABLE OF shdtvsvciu WITH DEFAULT KEY, + END OF ty_transaction_variant. +ENDCLASS. +CLASS zcl_abapgit_object_styl DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_style, + header TYPE itcda, + paragraphs TYPE STANDARD TABLE OF itcdp WITH DEFAULT KEY, + strings TYPE STANDARD TABLE OF itcds WITH DEFAULT KEY, + tabs TYPE STANDARD TABLE OF itcdq WITH DEFAULT KEY, + END OF ty_style. + +ENDCLASS. +CLASS zcl_abapgit_object_sucu DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_susc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + + CONSTANTS c_transobjecttype_class TYPE c LENGTH 1 VALUE 'C' ##NO_TEXT. + + METHODS has_authorization + IMPORTING + !iv_class TYPE tobc-oclss + !iv_activity TYPE activ_auth + RAISING + zcx_abapgit_exception . + METHODS is_used + IMPORTING + !iv_auth_object_class TYPE tobc-oclss + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + + METHODS delete_class + IMPORTING + !iv_auth_object_class TYPE tobc-oclss . + METHODS put_delete_to_transport + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_sush DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + PRIVATE SECTION. + METHODS clear_metadata + CHANGING + cs_data_head TYPE any + ct_usobx TYPE STANDARD TABLE + ct_usobt TYPE STANDARD TABLE + ct_usobx_ext TYPE STANDARD TABLE + ct_usobt_ext TYPE STANDARD TABLE. + +ENDCLASS. +CLASS zcl_abapgit_object_suso DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS c_longtext_id_suso TYPE dokil-id VALUE 'UO'. + + DATA: + mv_objectname TYPE tobj-objct. + + METHODS: + delete_documentation + RAISING + zcx_abapgit_exception, + + pre_check + RAISING + zcx_abapgit_exception, + + regenerate_sap_all. + +ENDCLASS. +CLASS zcl_abapgit_object_sxci DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_classic_badi_implementation, + implementation_data TYPE impl_data, + function_codes TYPE seex_fcode_table, + control_composites TYPE seex_coco_table, + customer_includes TYPE seex_table_table, + screens TYPE seex_screen_table, + filters TYPE seex_filter_table, + END OF ty_classic_badi_implementation. +ENDCLASS. +CLASS zcl_abapgit_object_sxsd DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA ms_badi_attr TYPE sxc_attr. +ENDCLASS. +CLASS zcl_abapgit_object_tobj DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_tobj, + tddat TYPE tddat, + tvdir TYPE tvdir, + tvimf TYPE STANDARD TABLE OF tvimf WITH DEFAULT KEY, + END OF ty_tobj. + + METHODS: + read_extra IMPORTING iv_tabname TYPE vim_name + RETURNING VALUE(rs_tobj) TYPE ty_tobj, + update_extra IMPORTING is_tobj TYPE ty_tobj, + delete_extra IMPORTING iv_tabname TYPE vim_name. + +ENDCLASS. +CLASS zcl_abapgit_object_tran DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + + PRIVATE SECTION. + TYPES: + ty_param_values TYPE STANDARD TABLE OF rsparam + WITH NON-UNIQUE DEFAULT KEY , + ty_tstca TYPE STANDARD TABLE OF tstca + WITH DEFAULT KEY. + + CONSTANTS: + c_oo_program TYPE c LENGTH 9 VALUE '\PROGRAM=' ##NO_TEXT, + c_oo_class TYPE c LENGTH 7 VALUE '\CLASS=' ##NO_TEXT, + c_oo_method TYPE c LENGTH 8 VALUE '\METHOD=' ##NO_TEXT, + c_oo_tcode TYPE tcode VALUE 'OS_APPLICATION' ##NO_TEXT, + c_oo_frclass TYPE c LENGTH 30 VALUE 'CLASS' ##NO_TEXT, + c_oo_frmethod TYPE c LENGTH 30 VALUE 'METHOD' ##NO_TEXT, + c_oo_frupdtask TYPE c LENGTH 30 VALUE 'UPDATE_MODE' ##NO_TEXT, + c_oo_synchron TYPE c VALUE 'S' ##NO_TEXT, + c_oo_asynchron TYPE c VALUE 'U' ##NO_TEXT, + c_true TYPE c VALUE 'X' ##NO_TEXT, + c_false TYPE c VALUE space ##NO_TEXT, + BEGIN OF c_variant_type, + dialog TYPE rglif-docutype VALUE 'D' ##NO_TEXT, + report TYPE rglif-docutype VALUE 'R' ##NO_TEXT, + variant TYPE rglif-docutype VALUE 'V' ##NO_TEXT, + parameters TYPE rglif-docutype VALUE 'P' ##NO_TEXT, + object TYPE rglif-docutype VALUE 'O' ##NO_TEXT, + END OF c_variant_type. + + DATA: + mt_bcdata TYPE STANDARD TABLE OF bdcdata . + + METHODS transaction_read + IMPORTING + iv_transaction TYPE tcode + EXPORTING + es_transaction TYPE tstc + es_gui_attr TYPE tstcc + RAISING + zcx_abapgit_exception. + METHODS shift_param + CHANGING + !ct_rsparam TYPE s_param + !cs_tstcp TYPE tstcp . + METHODS add_data + IMPORTING + !iv_fnam TYPE bdcdata-fnam + !iv_fval TYPE clike . + METHODS call_se93 + RAISING + zcx_abapgit_exception . + METHODS set_oo_parameters + IMPORTING + !it_rsparam TYPE s_param + CHANGING + !cs_rsstcd TYPE rsstcd . + METHODS split_parameters + CHANGING + !ct_rsparam TYPE s_param + !cs_rsstcd TYPE rsstcd + !cs_tstcp TYPE tstcp + !cs_tstc TYPE tstc . + METHODS split_parameters_comp + IMPORTING + !ig_type TYPE any + !ig_param TYPE any + CHANGING + !cg_value TYPE any . + METHODS serialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS deserialize_oo_transaction + IMPORTING + !iv_package TYPE devclass + !is_tstc TYPE tstc + !is_tstcc TYPE tstcc + !is_tstct TYPE tstct + !is_rsstcd TYPE rsstcd + RAISING + zcx_abapgit_exception . + METHODS save_authorizations + IMPORTING + iv_transaction TYPE tstc-tcode + it_authorizations TYPE ty_tstca + RAISING + zcx_abapgit_exception. + METHODS clear_functiongroup_globals. + METHODS is_variant_transaction IMPORTING is_tstcp TYPE tstcp + RETURNING VALUE(rv_variant_transaction) TYPE abap_bool. +ENDCLASS. +CLASS zcl_abapgit_object_ttyp DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + + " Fields that are not part of dd40v + TYPES: + BEGIN OF ty_extra, + abap_language_version TYPE uccheck, + END OF ty_extra. + + CONSTANTS c_longtext_id_ttyp TYPE dokil-id VALUE 'TT'. +ENDCLASS. +CLASS zcl_abapgit_object_type DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: c_prefix TYPE c LENGTH 3 VALUE '%_C'. + + METHODS read + EXPORTING ev_ddtext TYPE ddtypet-ddtext + et_source TYPE abaptxt255_tab + RAISING zcx_abapgit_exception. + + METHODS create + IMPORTING iv_ddtext TYPE ddtypet-ddtext + it_source TYPE abaptxt255_tab + iv_devclass TYPE devclass + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_ucsa DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: + BEGIN OF c_version, + active TYPE r3state VALUE 'A', + inactive TYPE r3state VALUE 'I', + END OF c_version . + + TYPES: + ty_id TYPE c LENGTH 30. + + METHODS: + get_persistence + IMPORTING + iv_id TYPE ty_id + RETURNING + VALUE(ro_persistence) TYPE REF TO object, + + clear_dynamic_fields + CHANGING + cg_complete_comm_assembly TYPE any, + + clear_field + IMPORTING + iv_fieldname TYPE csequence + CHANGING + cg_header TYPE any. + +ENDCLASS. +CLASS zcl_abapgit_object_udmo DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + METHODS corr_insert + REDEFINITION . + PRIVATE SECTION. + + TYPES: + " You are reminded that the text serialisation / de-serialisation methods depend upon a common type. + " To make the dependency explicit, there is one common definition. + BEGIN OF ty_udmo_text_type. + TYPES sprache TYPE dm40t-sprache. + TYPES dmoid TYPE dm40t-dmoid. + TYPES langbez TYPE dm40t-langbez. + TYPES as4local TYPE dm40t-as4local. + TYPES END OF ty_udmo_text_type . + + DATA mv_data_model TYPE uddmodl . + DATA mv_text_object TYPE doku_obj . + DATA mv_lxe_text_name TYPE lxeobjname . + DATA mv_activation_state TYPE as4local . + DATA ms_object_type TYPE rsdeo . + CONSTANTS c_transport_object_class TYPE trobjtype VALUE 'SUDM' ##NO_TEXT. + CONSTANTS c_lxe_text_type TYPE lxeobjtype VALUE 'IM' ##NO_TEXT. + CONSTANTS c_correction_object_type TYPE rsdeo-objtype VALUE 'UDMO' ##NO_TEXT. + CONSTANTS c_active_state TYPE as4local VALUE 'A' ##NO_TEXT. + + METHODS is_name_permitted + RAISING + zcx_abapgit_exception . + METHODS update_tree . + METHODS serialize_short_texts + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_short_texts + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS serialize_long_texts + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_long_texts + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS serialize_entities + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_entities + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS access_modify + RETURNING + VALUE(rv_result) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS access_free + RETURNING + VALUE(rv_result) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS deserialize_model + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS serialize_model + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_ueno DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + PRIVATE SECTION. + + TYPES BEGIN OF ty_docu. + TYPES language TYPE dm40t-sprache. + TYPES header TYPE thead. + TYPES content TYPE xstring. + TYPES itf TYPE tsftext. + TYPES END OF ty_docu. + + TYPES ty_docu_lines TYPE STANDARD TABLE OF ty_docu WITH DEFAULT KEY. + + DATA mv_entity_id TYPE udentity. + + CONSTANTS c_text_object_type TYPE lxeobjtype VALUE 'IM' ##NO_TEXT. + CONSTANTS c_active_state TYPE as4local VALUE 'A' ##NO_TEXT. + METHODS build_text_name + IMPORTING iv_id TYPE tdid + RETURNING VALUE(rv_result) TYPE doku_obj. + + METHODS is_name_permitted + RAISING + zcx_abapgit_exception. + + METHODS delete_docu_uen + RAISING zcx_abapgit_exception. + + METHODS delete_docu_url + RAISING zcx_abapgit_exception. + + METHODS delete_docu_usp + RAISING zcx_abapgit_exception. + + METHODS deserialize_docu_uen + IMPORTING + io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception. + + METHODS deserialize_docu_url + IMPORTING + io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception. + + METHODS deserialize_docu_usp + IMPORTING + io_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception. + + METHODS serialize_docu_uen + IMPORTING + io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception. + + METHODS serialize_docu_url + IMPORTING + io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception. + + METHODS serialize_docu_xxxx + IMPORTING iv_id TYPE tdid + RETURNING VALUE(rt_result) TYPE ty_docu_lines. + + METHODS serialize_docu_usp + IMPORTING + io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception. + + METHODS deserialize_docu_xxxx + IMPORTING + it_docu TYPE ty_docu_lines + RAISING + zcx_abapgit_exception. + METHODS get_generic + RETURNING + VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic + RAISING + zcx_abapgit_exception . + METHODS get_field_rules + RETURNING + VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. +ENDCLASS. +CLASS zcl_abapgit_object_vcls DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. + +* See include MTOBJCON: + CONSTANTS c_cluster_type TYPE c VALUE 'C' ##NO_TEXT. + CONSTANTS c_mode_insert TYPE obj_para-maint_mode VALUE 'I' ##NO_TEXT. + + METHODS is_locked + IMPORTING + !iv_tabname TYPE tabname + !iv_argument TYPE seqg3-garg + RETURNING + VALUE(rv_is_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_view DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + "! get additional data like table authorization group + "! @parameter iv_name | name of the view + METHODS read_extras + IMPORTING + iv_name TYPE ddobjname + RETURNING + VALUE(rs_tabl_extras) TYPE zif_abapgit_object_tabl=>ty_tabl_extras + RAISING + zcx_abapgit_exception. + + "! Update additional data + "! @parameter iv_name | name of the table + "! @parameter iv_transport | transport request + "! @parameter is_tabl_extras | additional view data + METHODS update_extras + IMPORTING + iv_name TYPE ddobjname + iv_transport TYPE trkorr + is_tabl_extras TYPE zif_abapgit_object_tabl=>ty_tabl_extras + RAISING + zcx_abapgit_exception. + + "! Delete additional data + "! @parameter iv_name | name of the view + "! @parameter iv_transport | transport request + METHODS delete_extras + IMPORTING + iv_name TYPE ddobjname + iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception. + + METHODS insert_transport + IMPORTING + iv_name TYPE ddobjname + iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + TYPES: ty_dd26v TYPE STANDARD TABLE OF dd26v + WITH NON-UNIQUE DEFAULT KEY, + ty_dd27p TYPE STANDARD TABLE OF dd27p + WITH NON-UNIQUE DEFAULT KEY, + ty_dd28j TYPE STANDARD TABLE OF dd28j + WITH NON-UNIQUE DEFAULT KEY, + ty_dd28v TYPE STANDARD TABLE OF dd28v + WITH NON-UNIQUE DEFAULT KEY, + BEGIN OF ty_dd25_text, + ddlanguage TYPE dd25t-ddlanguage, + ddtext TYPE dd25t-ddtext, + END OF ty_dd25_text , + ty_dd25_texts TYPE STANDARD TABLE OF ty_dd25_text. + CONSTANTS c_longtext_id_view TYPE dokil-id VALUE 'VW'. + + METHODS: + read_view + IMPORTING + iv_language TYPE sy-langu + EXPORTING + ev_state TYPE ddgotstate + es_dd25v TYPE dd25v + es_dd09l TYPE dd09l + et_dd26v TYPE ty_dd26v + et_dd27p TYPE ty_dd27p + et_dd28j TYPE ty_dd28j + et_dd28v TYPE ty_dd28v + es_extras TYPE zif_abapgit_object_tabl=>ty_tabl_extras + RAISING + zcx_abapgit_exception, + + serialize_texts + IMPORTING + ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception, + + deserialize_texts + IMPORTING + ii_xml TYPE REF TO zif_abapgit_xml_input + is_dd25v TYPE dd25v + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_w3xx_super DEFINITION + INHERITING FROM zcl_abapgit_objects_super + ABSTRACT + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + TYPES: + ty_wwwparams_tt TYPE STANDARD TABLE OF wwwparams WITH DEFAULT KEY . + + CONSTANTS: + BEGIN OF c_param_names, + version TYPE w3_name VALUE 'version', + fileext TYPE w3_name VALUE 'fileextension', + filesize TYPE w3_name VALUE 'filesize', + filename TYPE w3_name VALUE 'filename', + mimetype TYPE w3_name VALUE 'mimetype', + END OF c_param_names . + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + TYPES ty_bdcdata TYPE STANDARD TABLE OF bdcdata + WITH NON-UNIQUE DEFAULT KEY. + + METHODS change_bdc_jump_data ABSTRACT + CHANGING + ct_bdcdata TYPE ty_bdcdata. + + PRIVATE SECTION. + + DATA ms_key TYPE wwwdatatab. + + METHODS get_ext + IMPORTING it_params TYPE ty_wwwparams_tt + RETURNING VALUE(rv_ext) TYPE string + RAISING zcx_abapgit_exception. + + METHODS normalize_params + IMPORTING iv_size TYPE i + CHANGING ct_params TYPE ty_wwwparams_tt " Param table to patch + RAISING zcx_abapgit_exception. + + METHODS strip_params + CHANGING ct_params TYPE ty_wwwparams_tt + RAISING zcx_abapgit_exception. + + METHODS find_param + IMPORTING it_params TYPE ty_wwwparams_tt + iv_name TYPE w3_name + RETURNING VALUE(rv_value) TYPE string + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_w3ht DEFINITION INHERITING FROM zcl_abapgit_object_w3xx_super FINAL. + + PROTECTED SECTION. + METHODS: change_bdc_jump_data REDEFINITION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_w3mi DEFINITION INHERITING FROM zcl_abapgit_object_w3xx_super FINAL. + + PROTECTED SECTION. + METHODS: change_bdc_jump_data REDEFINITION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_wapa DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_page, + attributes TYPE o2pagattr, + event_handlers TYPE o2pagevh_tabletype, + parameters TYPE o2pagpar_tabletype, + types TYPE rswsourcet, + END OF ty_page. + + TYPES: ty_pages_tt TYPE STANDARD TABLE OF ty_page WITH DEFAULT KEY. + + CONSTANTS: c_active TYPE so2_version VALUE 'A'. + + METHODS: + get_page_content + IMPORTING io_page TYPE REF TO cl_o2_api_pages + RETURNING VALUE(rv_content) TYPE xstring + RAISING zcx_abapgit_exception, + to_page_content + IMPORTING iv_content TYPE xstring + RETURNING VALUE(rt_content) TYPE o2pageline_table + RAISING zcx_abapgit_exception, + read_page + IMPORTING is_page TYPE o2pagattr + iv_no_files_add TYPE abap_bool OPTIONAL + RETURNING VALUE(rs_page) TYPE ty_page + RAISING zcx_abapgit_exception, + create_new_application + IMPORTING is_attributes TYPE o2applattr + it_nodes TYPE o2applnode_table + it_navgraph TYPE o2applgrap_table + RETURNING VALUE(ro_bsp) TYPE REF TO cl_o2_api_application + RAISING zcx_abapgit_exception, + create_new_page + IMPORTING + is_page_attributes TYPE o2pagattr + RETURNING + VALUE(ro_page) TYPE REF TO cl_o2_api_pages + RAISING + zcx_abapgit_exception, + delete_superfluous_pages + IMPORTING + it_local_pages TYPE o2pagelist + it_remote_pages TYPE ty_pages_tt + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_wdca DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS read + EXPORTING + !es_outline TYPE wdy_cfg_outline_data + !et_data TYPE wdy_cfg_persist_data_appl_tab + RAISING + zcx_abapgit_exception . + METHODS save + IMPORTING + !is_outline TYPE wdy_cfg_outline_data + !it_data TYPE wdy_cfg_persist_data_appl_tab + !iv_package TYPE devclass + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + METHODS delete + IMPORTING + !iv_package TYPE devclass + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + METHODS check + IMPORTING + !it_messages TYPE cts_messages + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_wdcc DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item + iv_language TYPE spras + io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_type_not_supported. + PROTECTED SECTION. + METHODS after_import + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_object_wdya DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS c_longtext_id_wdya TYPE dokil-id VALUE 'WA'. + + METHODS read + EXPORTING es_app TYPE wdy_application + et_properties TYPE wdy_app_property_table + RAISING zcx_abapgit_exception. + + METHODS save + IMPORTING is_app TYPE wdy_application + it_properties TYPE wdy_app_property_table + iv_package TYPE devclass + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_wdyn DEFINITION + INHERITING FROM zcl_abapgit_objects_super + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_longtext_id_wc TYPE dokil-id VALUE 'WC' ##NO_TEXT. + CONSTANTS c_longtext_id_wd TYPE dokil-id VALUE 'WD' ##NO_TEXT. + CONSTANTS c_longtext_name_wc TYPE string VALUE 'LONGTEXTS_WC' ##NO_TEXT. + + DATA: + mt_components TYPE TABLE OF wdy_ctlr_compo_vrs, + mt_sources TYPE TABLE OF wdy_ctlr_compo_source_vrs. + + METHODS: + get_limu_objects + RETURNING VALUE(rt_objects) TYPE wdy_md_transport_keys, + read + RETURNING VALUE(rs_component) TYPE wdy_component_metadata + RAISING zcx_abapgit_exception, + read_controller + IMPORTING is_key TYPE wdy_md_controller_key + RETURNING VALUE(rs_controller) TYPE wdy_md_controller_meta_data + RAISING zcx_abapgit_exception, + read_definition + IMPORTING is_key TYPE wdy_md_component_key + RETURNING VALUE(rs_definition) TYPE wdy_md_component_meta_data + RAISING zcx_abapgit_exception, + read_view + IMPORTING is_key TYPE wdy_md_view_key + RETURNING VALUE(rs_view) TYPE wdy_md_view_meta_data + RAISING zcx_abapgit_exception, + recover_controller + IMPORTING is_controller TYPE wdy_md_controller_meta_data + RAISING zcx_abapgit_exception, + recover_definition + IMPORTING is_definition TYPE wdy_md_component_meta_data + iv_package TYPE devclass + RAISING zcx_abapgit_exception, + recover_view + IMPORTING is_view TYPE wdy_md_view_meta_data + RAISING zcx_abapgit_exception, + unlock_definition + IMPORTING is_component_key TYPE wdy_md_component_key, + unlock_controller + IMPORTING is_controller_key TYPE wdy_md_controller_key, + unlock_view + IMPORTING is_view_key TYPE wdy_md_view_key, + delta_controller + IMPORTING is_controller TYPE wdy_md_controller_meta_data + RETURNING VALUE(rs_delta) TYPE svrs2_xversionable_object + RAISING zcx_abapgit_exception, + delta_definition + IMPORTING is_definition TYPE wdy_md_component_meta_data + VALUE(iv_package) TYPE devclass + RETURNING VALUE(rs_delta) TYPE svrs2_xversionable_object + RAISING zcx_abapgit_exception, + delta_view + IMPORTING is_view TYPE wdy_md_view_meta_data + RETURNING VALUE(rs_delta) TYPE svrs2_xversionable_object + RAISING zcx_abapgit_exception, + deserialize_sources + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING zcx_abapgit_exception, + serialize_sources + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING zcx_abapgit_exception, + add_fm_param_exporting + IMPORTING iv_name TYPE string + ig_value TYPE any + CHANGING ct_param TYPE abap_func_parmbind_tab, + add_fm_param_tables + IMPORTING iv_name TYPE string + CHANGING ct_value TYPE ANY TABLE + ct_param TYPE abap_func_parmbind_tab, + add_fm_exception + IMPORTING iv_name TYPE string + iv_value TYPE i + CHANGING ct_exception TYPE abap_func_excpbind_tab, + add_with_inactive_parts + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_object_webi DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: BEGIN OF ty_webi, + veptext TYPE veptext, + pvepheader TYPE STANDARD TABLE OF vepheader WITH DEFAULT KEY, + pvepfunction TYPE STANDARD TABLE OF vepfunction WITH DEFAULT KEY, + pvepfault TYPE STANDARD TABLE OF vepfault WITH DEFAULT KEY, + pvepparameter TYPE STANDARD TABLE OF vepparameter WITH DEFAULT KEY, + pveptype TYPE STANDARD TABLE OF veptype WITH DEFAULT KEY, + pvepelemtype TYPE STANDARD TABLE OF vepelemtype WITH DEFAULT KEY, + pveptabletype TYPE STANDARD TABLE OF veptabletype WITH DEFAULT KEY, + pvepstrutype TYPE STANDARD TABLE OF vepstrutype WITH DEFAULT KEY, + pveptypesoapext TYPE STANDARD TABLE OF veptypesoapext WITH DEFAULT KEY, + pvepeletypsoap TYPE STANDARD TABLE OF vepeletypsoap WITH DEFAULT KEY, + pveptabtypsoap TYPE STANDARD TABLE OF veptabtypsoap WITH DEFAULT KEY, + pvepfuncsoapext TYPE STANDARD TABLE OF vepfuncsoapext WITH DEFAULT KEY, + pvepfieldref TYPE STANDARD TABLE OF vepfieldref WITH DEFAULT KEY, + pvependpoint TYPE STANDARD TABLE OF vependpoint WITH DEFAULT KEY, + pvepvisoapext TYPE STANDARD TABLE OF vepvisoapext WITH DEFAULT KEY, + pvepparasoapext TYPE STANDARD TABLE OF vepparasoapext WITH DEFAULT KEY, + pwsheader TYPE STANDARD TABLE OF wsheader WITH DEFAULT KEY, + pwssoapprop TYPE STANDARD TABLE OF wssoapprop WITH DEFAULT KEY, + END OF ty_webi. + + DATA: mi_vi TYPE REF TO if_ws_md_vif. + + METHODS: + handle_endpoint + IMPORTING is_webi TYPE ty_webi + RAISING zcx_abapgit_exception + cx_ws_md_exception, + handle_types + IMPORTING is_webi TYPE ty_webi + RAISING zcx_abapgit_exception + cx_ws_md_exception, + handle_soap + IMPORTING is_webi TYPE ty_webi + RAISING zcx_abapgit_exception + cx_ws_md_exception, + handle_function + IMPORTING is_webi TYPE ty_webi + RAISING zcx_abapgit_exception + cx_ws_md_exception. + METHODS handle_single_parameter + IMPORTING + iv_parameter_type TYPE vepparamtype + iv_name TYPE vepparameter-vepparam + ii_function TYPE REF TO if_ws_md_vif_func + RETURNING + VALUE(ri_parameter) TYPE REF TO if_ws_md_vif_param + RAISING + zcx_abapgit_exception + cx_ws_md_exception. + METHODS sort + CHANGING + cs_webi TYPE ty_webi. + +ENDCLASS. +CLASS zcl_abapgit_object_xinx DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_extension_index, + dd12v TYPE dd12v, + t_dd17v TYPE STANDARD TABLE OF dd17v + WITH NON-UNIQUE DEFAULT KEY, + END OF ty_extension_index. + + CONSTANTS: + c_objtype_extension_index TYPE trobjtype VALUE 'XINX'. + + CONSTANTS c_longtext_id_xinx TYPE dokil-id VALUE 'XI'. + + DATA: + mv_name TYPE ddobjname, + mv_id TYPE ddobjectid. + + METHODS: + xinx_delete_docu + IMPORTING + iv_objname TYPE ddobjname + iv_id TYPE ddobjectid. + +ENDCLASS. +CLASS zcl_abapgit_object_xslt DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_extra, + abap_language_version TYPE uccheck, + END OF ty_extra. + + METHODS: + get + RETURNING VALUE(ro_xslt) TYPE REF TO cl_o2_api_xsltdesc + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_objects_bridge DEFINITION FINAL CREATE PUBLIC INHERITING FROM zcl_abapgit_objects_super. + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + cx_sy_create_object_error. + + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + DATA mo_plugin TYPE REF TO object. + + CLASS-METHODS initialize. + + " Metadata flags (late_deser, delete_tadir, and ddic) are not required by abapGit anymore + " We keep them to stay compatible with old bridge implementation + TYPES: + BEGIN OF ty_metadata, + class TYPE string, + version TYPE string, + late_deser TYPE abap_bool, + delete_tadir TYPE abap_bool, + ddic TYPE abap_bool, + END OF ty_metadata . + + TYPES: BEGIN OF ty_s_objtype_map, + obj_typ TYPE tadir-object, + plugin_class TYPE seoclsname, + END OF ty_s_objtype_map, + ty_t_objtype_map TYPE SORTED TABLE OF ty_s_objtype_map WITH UNIQUE KEY obj_typ. + + CLASS-DATA gv_init TYPE abap_bool. + CLASS-DATA gt_objtype_map TYPE ty_t_objtype_map. + +ENDCLASS. +CLASS zcl_abapgit_objects_program DEFINITION + INHERITING FROM zcl_abapgit_objects_super + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_cua, + adm TYPE rsmpe_adm, + sta TYPE STANDARD TABLE OF rsmpe_stat WITH DEFAULT KEY, + fun TYPE STANDARD TABLE OF rsmpe_funt WITH DEFAULT KEY, + men TYPE STANDARD TABLE OF rsmpe_men WITH DEFAULT KEY, + mtx TYPE STANDARD TABLE OF rsmpe_mnlt WITH DEFAULT KEY, + act TYPE STANDARD TABLE OF rsmpe_act WITH DEFAULT KEY, + but TYPE STANDARD TABLE OF rsmpe_but WITH DEFAULT KEY, + pfk TYPE STANDARD TABLE OF rsmpe_pfk WITH DEFAULT KEY, + set TYPE STANDARD TABLE OF rsmpe_staf WITH DEFAULT KEY, + doc TYPE STANDARD TABLE OF rsmpe_atrt WITH DEFAULT KEY, + tit TYPE STANDARD TABLE OF rsmpe_titt WITH DEFAULT KEY, + biv TYPE STANDARD TABLE OF rsmpe_buts WITH DEFAULT KEY, + END OF ty_cua. + + METHODS serialize_program + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output OPTIONAL + !is_item TYPE zif_abapgit_definitions=>ty_item + !io_files TYPE REF TO zcl_abapgit_objects_files + !iv_program TYPE syrepid OPTIONAL + !iv_extra TYPE clike OPTIONAL + RAISING + zcx_abapgit_exception. + METHODS deserialize_program + IMPORTING + !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir + !it_source TYPE abaptxt255_tab + !it_tpool TYPE textpool_table + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + + TYPES: + ty_spaces_tt TYPE STANDARD TABLE OF i WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_dynpro, + header TYPE rpy_dyhead, + containers TYPE dycatt_tab, + fields TYPE dyfatc_tab, + flow_logic TYPE swydyflow, + spaces TYPE ty_spaces_tt, + nat_header TYPE d020s, + nat_fields TYPE STANDARD TABLE OF d021s WITH DEFAULT KEY, + nat_texts TYPE STANDARD TABLE OF d021t WITH DEFAULT KEY, + END OF ty_dynpro . + TYPES: + ty_dynpro_tt TYPE STANDARD TABLE OF ty_dynpro WITH DEFAULT KEY . + + METHODS strip_generation_comments + CHANGING + ct_source TYPE STANDARD TABLE. " tab of string or charX + METHODS serialize_dynpros + IMPORTING + !iv_program_name TYPE syrepid + RETURNING + VALUE(rt_dynpro) TYPE ty_dynpro_tt + RAISING + zcx_abapgit_exception . + METHODS serialize_cua + IMPORTING + !iv_program_name TYPE syrepid + RETURNING + VALUE(rs_cua) TYPE ty_cua + RAISING + zcx_abapgit_exception . + METHODS deserialize_dynpros + IMPORTING + !it_dynpros TYPE ty_dynpro_tt + RAISING + zcx_abapgit_exception . + METHODS deserialize_textpool + IMPORTING + !iv_program TYPE syrepid + !it_tpool TYPE textpool_table + !iv_language TYPE sy-langu OPTIONAL + !iv_is_include TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception . + METHODS deserialize_cua + IMPORTING + !iv_program_name TYPE syrepid + !is_cua TYPE ty_cua + RAISING + zcx_abapgit_exception . + METHODS is_any_dynpro_locked + IMPORTING + !iv_program TYPE syrepid + RETURNING + VALUE(rv_is_any_dynpro_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS is_cua_locked + IMPORTING + !iv_program TYPE syrepid + RETURNING + VALUE(rv_is_cua_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS is_text_locked + IMPORTING + !iv_program TYPE syrepid + RETURNING + VALUE(rv_is_text_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . + CLASS-METHODS add_tpool + IMPORTING + !it_tpool TYPE textpool_table + RETURNING + VALUE(rt_tpool) TYPE zif_abapgit_lang_definitions=>ty_tpool_tt. + CLASS-METHODS read_tpool + IMPORTING + !it_tpool TYPE zif_abapgit_lang_definitions=>ty_tpool_tt + RETURNING + VALUE(rt_tpool) TYPE textpool_table. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_state, + active TYPE r3state VALUE 'A', + inactive TYPE r3state VALUE 'I', + END OF c_state. + + CONSTANTS c_native_dynpro TYPE c LENGTH 2 VALUE 'IN'. + + METHODS: + uncondense_flow + IMPORTING it_flow TYPE swydyflow + it_spaces TYPE ty_spaces_tt + RETURNING VALUE(rt_flow) TYPE swydyflow. + + CLASS-METHODS auto_correct_cua_adm + IMPORTING + is_cua TYPE ty_cua + CHANGING + cs_adm TYPE rsmpe_adm. + + METHODS get_program_title + IMPORTING + !it_tpool TYPE textpool_table + RETURNING + VALUE(rv_title) TYPE repti . + METHODS insert_program + IMPORTING + !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir + !it_source TYPE abaptxt255_tab + !iv_title TYPE repti + !iv_package TYPE devclass + !iv_state TYPE progdir-state DEFAULT c_state-inactive + RAISING + zcx_abapgit_exception . + METHODS update_program + IMPORTING + !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir + !it_source TYPE abaptxt255_tab + !iv_title TYPE repti + !iv_state TYPE progdir-state DEFAULT c_state-inactive + RAISING + zcx_abapgit_exception . + METHODS is_exit_include + IMPORTING + !iv_program TYPE syrepid + RETURNING + VALUE(rv_is_exit_include) TYPE abap_bool. + METHODS deserialize_exit_include + IMPORTING + !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir + !it_source TYPE abaptxt255_tab + !it_tpool TYPE textpool_table + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_object_clas DEFINITION + INHERITING FROM zcl_abapgit_objects_program + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + DATA: mi_object_oriented_object_fct TYPE REF TO zif_abapgit_oo_object_fnc, + mv_skip_testclass TYPE abap_bool, + mv_classpool_name TYPE progname. + METHODS: + deserialize_abap + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + iv_package TYPE devclass + RAISING zcx_abapgit_exception, + deserialize_descr + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING zcx_abapgit_exception, + deserialize_docu + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING zcx_abapgit_exception, + deserialize_tpool + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING zcx_abapgit_exception, + deserialize_tpool_i18n + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING zcx_abapgit_exception, + deserialize_sotr + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + iv_package TYPE devclass + RAISING zcx_abapgit_exception, + deserialize_exceptions + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING zcx_abapgit_exception, + serialize_xml + IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING zcx_abapgit_exception, + serialize_attr + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + !iv_clsname TYPE seoclsname + RAISING + zcx_abapgit_exception, + serialize_descr_class + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + !iv_clsname TYPE seoclsname + RAISING + zcx_abapgit_exception, + serialize_descr_compo + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + !iv_clsname TYPE seoclsname + RAISING + zcx_abapgit_exception, + serialize_descr_subco + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + !iv_clsname TYPE seoclsname + RAISING + zcx_abapgit_exception, + serialize_docu + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + !it_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus OPTIONAL + !iv_clsname TYPE seoclsname + RAISING + zcx_abapgit_exception, + serialize_tpool + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + !iv_clsname TYPE seoclsname + RETURNING + VALUE(rt_tpool) TYPE textpool_table + RAISING + zcx_abapgit_exception, + serialize_tpool_i18n + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + !it_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus OPTIONAL + !iv_clsname TYPE seoclsname + !it_tpool_main TYPE textpool_table + RAISING + zcx_abapgit_exception, + serialize_sotr + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception, + source_apack_replacement + CHANGING + !ct_source TYPE seop_source_string + RAISING + zcx_abapgit_exception, + repo_apack_replacement + CHANGING + !ct_source TYPE seop_source_string + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_longtext_name, + attributes TYPE string VALUE 'LONGTEXTS_CA', + methods TYPE string VALUE 'LONGTEXTS_CO', + events TYPE string VALUE 'LONGTEXTS_CE', + types TYPE string VALUE 'LONGTEXTS_CT', + END OF c_longtext_name. + CONSTANTS: + BEGIN OF c_longtext_id, + class TYPE dokil-id VALUE 'CL', + attributes TYPE dokil-id VALUE 'CA', + methods TYPE dokil-id VALUE 'CO', + events TYPE dokil-id VALUE 'CE', + types TYPE dokil-id VALUE 'CT', + END OF c_longtext_id. + + METHODS deserialize_pre_ddic + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception. + + METHODS is_class_locked + RETURNING + VALUE(rv_is_class_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS interface_replacement + IMPORTING + !iv_from_interface TYPE seoclsname + !iv_to_interface TYPE seoclsname + CHANGING + !ct_source TYPE seop_source_string. + +ENDCLASS. +CLASS zcl_abapgit_object_fugr DEFINITION + INHERITING FROM zcl_abapgit_objects_program + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_object . + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + c_longtext_id_prog TYPE dokil-id VALUE 'RE', + c_longtext_id_func TYPE dokil-id VALUE 'FU', + c_longtext_id_func_exc TYPE dokil-id VALUE 'FX'. + + TYPES: + ty_rs38l_incl_tt TYPE STANDARD TABLE OF rs38l_incl WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_function, + funcname TYPE rs38l_fnam, + global_flag TYPE rs38l-global, + remote_call TYPE rs38l-remote, + update_task TYPE rs38l-utask, + short_text TYPE tftit-stext, + remote_basxml TYPE rs38l-basxml_enabled, + import TYPE STANDARD TABLE OF rsimp WITH DEFAULT KEY, + changing TYPE STANDARD TABLE OF rscha WITH DEFAULT KEY, + export TYPE STANDARD TABLE OF rsexp WITH DEFAULT KEY, + tables TYPE STANDARD TABLE OF rstbl WITH DEFAULT KEY, + exception TYPE STANDARD TABLE OF rsexc WITH DEFAULT KEY, + documentation TYPE STANDARD TABLE OF rsfdo WITH DEFAULT KEY, + exception_classes TYPE abap_bool, + END OF ty_function . + TYPES: + ty_function_tt TYPE STANDARD TABLE OF ty_function WITH DEFAULT KEY . + TYPES: + ty_sobj_name_tt TYPE STANDARD TABLE OF sobj_name WITH DEFAULT KEY . + + DATA mt_includes_cache TYPE ty_sobj_name_tt . + DATA mt_includes_all TYPE ty_sobj_name_tt . + + METHODS check_rfc_parameters + IMPORTING + !is_function TYPE ty_function + RAISING + zcx_abapgit_exception . + METHODS update_where_used + IMPORTING + !it_includes TYPE ty_sobj_name_tt . + METHODS main_name + RETURNING + VALUE(rv_program) TYPE program + RAISING + zcx_abapgit_exception . + METHODS functions + RETURNING + VALUE(rt_functab) TYPE ty_rs38l_incl_tt + RAISING + zcx_abapgit_exception . + METHODS includes + RETURNING + VALUE(rt_includes) TYPE ty_sobj_name_tt + RAISING + zcx_abapgit_exception . + METHODS serialize_functions + RETURNING + VALUE(rt_functions) TYPE ty_function_tt + RAISING + zcx_abapgit_exception . + METHODS deserialize_functions + IMPORTING + !it_functions TYPE ty_function_tt + !ii_log TYPE REF TO zif_abapgit_log + !iv_version TYPE uccheck + !iv_package TYPE devclass + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + METHODS serialize_function_docs + IMPORTING + !iv_prog_name TYPE syrepid + !it_functions TYPE ty_function_tt + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_function_docs + IMPORTING + !iv_prog_name TYPE syrepid + !it_functions TYPE ty_function_tt + !ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS serialize_xml + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_xml + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + !iv_version TYPE uccheck + !iv_package TYPE devclass + !iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + METHODS serialize_includes + RAISING + zcx_abapgit_exception . + METHODS deserialize_includes + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + !iv_package TYPE devclass + !ii_log TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + METHODS is_function_group_locked + RETURNING + VALUE(rv_is_functions_group_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS is_any_include_locked + RETURNING + VALUE(rv_is_any_include_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS is_any_function_module_locked + RETURNING + VALUE(rv_any_function_module_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS get_abap_version + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + RETURNING + VALUE(rv_abap_version) TYPE progdir-uccheck + RAISING + zcx_abapgit_exception . + METHODS update_func_group_short_text + IMPORTING + !iv_group TYPE rs38l-area + !iv_short_text TYPE tftit-stext . + METHODS serialize_texts + IMPORTING + !iv_prog_name TYPE syrepid + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_texts + IMPORTING + !iv_prog_name TYPE syrepid + !ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS is_part_of_other_fugr + IMPORTING + !iv_include TYPE sobj_name + RETURNING + VALUE(rv_belongs_to_other_fugr) TYPE abap_bool. +ENDCLASS. +CLASS zcl_abapgit_object_fugs DEFINITION + INHERITING FROM zcl_abapgit_object_fugr + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_object_intf DEFINITION FINAL INHERITING FROM zcl_abapgit_objects_program. + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + + TYPES: + BEGIN OF ty_docu, + lines TYPE tlinetab, + i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_lines, + END OF ty_docu. + + TYPES: + BEGIN OF ty_intf, + vseointerf TYPE vseointerf, + docu TYPE ty_docu, + description_int TYPE zif_abapgit_oo_object_fnc=>ty_seoclasstx_tt, + description TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, + description_sub TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt, + END OF ty_intf. + + METHODS constructor + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !iv_language TYPE spras + !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL + !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + METHODS deserialize_proxy + IMPORTING + iv_transport TYPE trkorr + RAISING + zcx_abapgit_exception . + METHODS deserialize_docu + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + !is_docu TYPE ty_docu + RAISING + zcx_abapgit_exception . + METHODS serialize_docu + IMPORTING + !it_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus OPTIONAL + !iv_clsname TYPE seoclsname + RETURNING VALUE(rs_docu) TYPE ty_docu + RAISING + zcx_abapgit_exception. + METHODS serialize_descr_class + IMPORTING + !iv_clsname TYPE seoclsname + RETURNING + VALUE(rs_description) TYPE ty_intf-description_int + RAISING + zcx_abapgit_exception. + METHODS serialize_descr_compo + IMPORTING + !iv_clsname TYPE seoclsname + RETURNING + VALUE(rs_description) TYPE ty_intf-description + RAISING + zcx_abapgit_exception. + METHODS serialize_descr_subco + IMPORTING + !iv_clsname TYPE seoclsname + RETURNING + VALUE(rs_description) TYPE ty_intf-description_sub + RAISING + zcx_abapgit_exception. + METHODS serialize_xml + IMPORTING + !io_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_longtext_name, + attributes TYPE string VALUE 'LONGTEXTS_IA', + methods TYPE string VALUE 'LONGTEXTS_IO', + events TYPE string VALUE 'LONGTEXTS_IE', + END OF c_longtext_name. + + CONSTANTS: + BEGIN OF c_longtext_id, + interface TYPE dokil-id VALUE 'IF', + attributes TYPE dokil-id VALUE 'IA', + methods TYPE dokil-id VALUE 'IO', + events TYPE dokil-id VALUE 'IE', + END OF c_longtext_id. + + DATA mv_aff_enabled TYPE abap_bool. + DATA mi_object_oriented_object_fct TYPE REF TO zif_abapgit_oo_object_fnc . + + METHODS deserialize_pre_ddic + IMPORTING + ii_xml TYPE REF TO zif_abapgit_xml_input + iv_package TYPE devclass + RAISING + zcx_abapgit_exception. + + METHODS deserialize_descr_class + IMPORTING + it_description TYPE zif_abapgit_oo_object_fnc=>ty_seoclasstx_tt OPTIONAL. + METHODS deserialize_descr_compo + IMPORTING + it_description TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt OPTIONAL. + METHODS deserialize_descr_subco + IMPORTING + it_description TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt OPTIONAL. + METHODS read_xml + IMPORTING + ii_xml TYPE REF TO zif_abapgit_xml_input + RETURNING VALUE(rs_intf) TYPE ty_intf + RAISING + zcx_abapgit_exception. + METHODS read_json + RETURNING VALUE(rs_intf) TYPE ty_intf + RAISING + zcx_abapgit_exception. + METHODS extract_languages_for_transl + IMPORTING is_intf TYPE ty_intf + RETURNING VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_languages. +ENDCLASS. +CLASS zcl_abapgit_object_prog DEFINITION INHERITING FROM zcl_abapgit_objects_program FINAL. + + PUBLIC SECTION. + INTERFACES zif_abapgit_object. + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_longtext_id_prog TYPE dokil-id VALUE 'RE' ##NO_TEXT. + + METHODS deserialize_with_ext + IMPORTING + !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir + !it_source TYPE abaptxt255_tab + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS serialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_output + RAISING + zcx_abapgit_exception . + METHODS deserialize_texts + IMPORTING + !ii_xml TYPE REF TO zif_abapgit_xml_input + RAISING + zcx_abapgit_exception . + METHODS is_program_locked + RETURNING + VALUE(rv_is_program_locked) TYPE abap_bool + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_migrations DEFINITION FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + CLASS-METHODS run + RAISING + zcx_abapgit_exception + zcx_abapgit_not_found. + + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-METHODS migrate_offline_repos. +ENDCLASS. +CLASS zcl_abapgit_persist_background DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_persist_factory. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_persist_background. + + METHODS constructor. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mo_db TYPE REF TO zcl_abapgit_persistence_db . + + METHODS from_xml + IMPORTING + !iv_string TYPE string + RETURNING + VALUE(rs_xml) TYPE zif_abapgit_persist_background=>ty_xml + RAISING + zcx_abapgit_exception . + + METHODS to_xml + IMPORTING + !is_background TYPE zif_abapgit_persist_background=>ty_background + RETURNING + VALUE(rv_string) TYPE string . +ENDCLASS. +CLASS zcl_abapgit_persist_factory DEFINITION + CREATE PRIVATE + . + + PUBLIC SECTION. + + CLASS-METHODS get_repo + RETURNING + VALUE(ri_repo) TYPE REF TO zif_abapgit_persist_repo . + CLASS-METHODS get_repo_cs + RETURNING + VALUE(ri_repo_cs) TYPE REF TO zif_abapgit_persist_repo_cs . + CLASS-METHODS get_settings + RETURNING + VALUE(ri_settings) TYPE REF TO zif_abapgit_persist_settings . + CLASS-METHODS get_background + RETURNING + VALUE(ri_background) TYPE REF TO zif_abapgit_persist_background. + CLASS-METHODS get_packages + RETURNING + VALUE(ri_packages) TYPE REF TO zif_abapgit_persist_packages. + CLASS-METHODS get_user + IMPORTING + !iv_user TYPE sy-uname DEFAULT sy-uname + RETURNING + VALUE(ri_user) TYPE REF TO zif_abapgit_persist_user. + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gi_repo TYPE REF TO zif_abapgit_persist_repo . + CLASS-DATA gi_repo_cs TYPE REF TO zif_abapgit_persist_repo_cs . + CLASS-DATA gi_settings TYPE REF TO zif_abapgit_persist_settings . + CLASS-DATA gi_background TYPE REF TO zif_abapgit_persist_background. + CLASS-DATA gi_packages TYPE REF TO zif_abapgit_persist_packages. + CLASS-DATA gi_current_user TYPE REF TO zif_abapgit_persist_user. +ENDCLASS. +CLASS zcl_abapgit_persist_migrate DEFINITION CREATE PUBLIC. + + PUBLIC SECTION. + CLASS-METHODS: run RAISING zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS c_text TYPE string VALUE 'Generated by abapGit' ##NO_TEXT. + + CLASS-METHODS table_create + RAISING + zcx_abapgit_exception. + CLASS-METHODS table_exists + RETURNING + VALUE(rv_exists) TYPE abap_bool. + CLASS-METHODS lock_create + RAISING + zcx_abapgit_exception. + CLASS-METHODS lock_exists + RETURNING + VALUE(rv_exists) TYPE abap_bool. + CLASS-METHODS gui_status_create + RAISING + zcx_abapgit_exception. + CLASS-METHODS gui_status_exists + RETURNING + VALUE(rv_exists) TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_persist_packages DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_persist_factory. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_persist_packages. + + METHODS init. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mt_packages TYPE zif_abapgit_persist_packages=>ty_packages. + + METHODS from_xml + IMPORTING + iv_xml TYPE string + RETURNING + VALUE(rt_packages) TYPE zif_abapgit_persist_packages=>ty_packages + RAISING + zcx_abapgit_exception. + METHODS to_xml + IMPORTING + it_packages TYPE zif_abapgit_persist_packages=>ty_packages + RETURNING + VALUE(rv_xml) TYPE string + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_persist_settings DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_persist_factory . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_persist_settings . + PROTECTED SECTION. + PRIVATE SECTION. + DATA mo_settings TYPE REF TO zcl_abapgit_settings . + +ENDCLASS. +CLASS zcl_abapgit_persistence_db DEFINITION + CREATE PRIVATE . + + PUBLIC SECTION. + CONSTANTS c_tabname TYPE c LENGTH 30 VALUE 'ZABAPGIT' ##NO_TEXT. + CONSTANTS c_lock TYPE c LENGTH 30 VALUE 'EZABAPGIT' ##NO_TEXT. + + CONSTANTS: + c_type_settings TYPE zif_abapgit_persistence=>ty_type VALUE 'SETTINGS' ##NO_TEXT, + c_type_repo TYPE zif_abapgit_persistence=>ty_type VALUE 'REPO' ##NO_TEXT, + c_type_repo_csum TYPE zif_abapgit_persistence=>ty_type VALUE 'REPO_CS' ##NO_TEXT, + c_type_background TYPE zif_abapgit_persistence=>ty_type VALUE 'BACKGROUND' ##NO_TEXT, + c_type_packages TYPE zif_abapgit_persistence=>ty_type VALUE 'PACKAGES' ##NO_TEXT, + c_type_user TYPE zif_abapgit_persistence=>ty_type VALUE 'USER' ##NO_TEXT. + + CLASS-METHODS get_instance + RETURNING + VALUE(ro_db) TYPE REF TO zcl_abapgit_persistence_db . + METHODS add + IMPORTING + !iv_type TYPE zif_abapgit_persistence=>ty_type + !iv_value TYPE zif_abapgit_persistence=>ty_content-value + !iv_data TYPE zif_abapgit_persistence=>ty_content-data_str + RAISING + zcx_abapgit_exception . + METHODS delete + IMPORTING + !iv_type TYPE zif_abapgit_persistence=>ty_type + !iv_value TYPE zif_abapgit_persistence=>ty_content-value + RAISING + zcx_abapgit_exception . + METHODS list + RETURNING + VALUE(rt_content) TYPE zif_abapgit_persistence=>ty_contents . + METHODS list_by_type + IMPORTING + !iv_type TYPE zif_abapgit_persistence=>ty_type + RETURNING + VALUE(rt_content) TYPE zif_abapgit_persistence=>ty_contents . + METHODS list_by_keys + IMPORTING it_keys TYPE zif_abapgit_persistence=>ty_repo_keys + iv_type TYPE zif_abapgit_persistence=>ty_type + RETURNING VALUE(rt_contents) TYPE zif_abapgit_persistence=>ty_contents. + METHODS lock + IMPORTING + !iv_mode TYPE enqmode DEFAULT 'E' + !iv_type TYPE zif_abapgit_persistence=>ty_type + !iv_value TYPE zif_abapgit_persistence=>ty_content-value + RAISING + zcx_abapgit_exception . + METHODS modify + IMPORTING + !iv_type TYPE zif_abapgit_persistence=>ty_type + !iv_value TYPE zif_abapgit_persistence=>ty_content-value + !iv_data TYPE zif_abapgit_persistence=>ty_content-data_str + RAISING + zcx_abapgit_exception . + METHODS read + IMPORTING + !iv_type TYPE zif_abapgit_persistence=>ty_type + !iv_value TYPE zif_abapgit_persistence=>ty_content-value + RETURNING + VALUE(rv_data) TYPE zif_abapgit_persistence=>ty_content-data_str + RAISING + zcx_abapgit_not_found . + METHODS update + IMPORTING + !iv_type TYPE zif_abapgit_persistence=>ty_type + !iv_value TYPE zif_abapgit_persistence=>ty_content-value + !iv_data TYPE zif_abapgit_persistence=>ty_content-data_str + RAISING + zcx_abapgit_exception . + CLASS-METHODS validate_entry_type + IMPORTING + !iv_type TYPE zif_abapgit_persistence=>ty_type + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA go_db TYPE REF TO zcl_abapgit_persistence_db . + DATA mv_update_function TYPE funcname . + + METHODS get_update_function + RETURNING + VALUE(rv_funcname) TYPE funcname . + METHODS validate_and_unprettify_xml + IMPORTING + !iv_xml TYPE string + RETURNING + VALUE(rv_xml) TYPE string + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_persistence_repo DEFINITION + CREATE PROTECTED + FRIENDS ZCL_abapgit_persist_factory . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_persist_repo . + INTERFACES zif_abapgit_persist_repo_cs . + + METHODS constructor . + METHODS rewrite_repo_meta + IMPORTING + !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception + zcx_abapgit_not_found. + PROTECTED SECTION. + + PRIVATE SECTION. + + DATA mt_meta_fields TYPE STANDARD TABLE OF abap_compname. + DATA mo_db TYPE REF TO zcl_abapgit_persistence_db . + + METHODS from_xml + IMPORTING + !iv_repo_xml_string TYPE string + RETURNING + VALUE(rs_repo) TYPE zif_abapgit_persistence=>ty_repo_xml + RAISING + zcx_abapgit_exception . + METHODS to_xml + IMPORTING + !is_repo TYPE zif_abapgit_persistence=>ty_repo + RETURNING + VALUE(rv_repo_xml_string) TYPE string . + METHODS get_next_id + RETURNING + VALUE(rv_next_repo_id) TYPE zif_abapgit_persistence=>ty_content-value + RAISING + zcx_abapgit_exception . + METHODS get_repo_from_content + IMPORTING + is_content TYPE zif_abapgit_persistence=>ty_content + RETURNING + VALUE(rs_result) TYPE zif_abapgit_persistence=>ty_repo + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_persistence_user DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_persist_factory. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_persist_user . + + METHODS constructor + IMPORTING + !iv_user TYPE sy-uname DEFAULT sy-uname. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_repo_config, + url TYPE zif_abapgit_persistence=>ty_repo-url, + login TYPE string, + git_user TYPE zif_abapgit_git_definitions=>ty_git_user, + last_change_seen TYPE string, + END OF ty_repo_config . + TYPES: + ty_repo_configs TYPE STANDARD TABLE OF ty_repo_config WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_user, + repo_show TYPE zif_abapgit_persistence=>ty_repo-key, + hide_files TYPE abap_bool, + changes_only TYPE abap_bool, + order_by TYPE string, + order_descending TYPE abap_bool, + diff_first TYPE abap_bool, + diff_unified TYPE abap_bool, + favorites TYPE zif_abapgit_persist_user=>ty_favorites, + repo_config TYPE ty_repo_configs, + settings TYPE zif_abapgit_persist_user=>ty_s_user_settings, + show_folders TYPE abap_bool, + list_settings TYPE zif_abapgit_persist_user=>ty_list_settings, + flow_settings TYPE zif_abapgit_persist_user=>ty_flow_settings, + END OF ty_user . + + DATA mv_user TYPE sy-uname . + DATA ms_user TYPE ty_user. + + METHODS from_xml + IMPORTING + !iv_xml TYPE string + RETURNING + VALUE(rs_user) TYPE ty_user. + METHODS read. + METHODS read_repo_config + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + RETURNING + VALUE(rs_repo_config) TYPE ty_repo_config + RAISING + zcx_abapgit_exception . + METHODS to_xml + IMPORTING + !is_user TYPE ty_user + RETURNING + VALUE(rv_xml) TYPE string . + METHODS update + RAISING + zcx_abapgit_exception . + METHODS update_repo_config + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url + !is_repo_config TYPE ty_repo_config + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_object_filter_obj DEFINITION. + PUBLIC SECTION. + INTERFACES zif_abapgit_object_filter. + + METHODS constructor + IMPORTING + it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + + PRIVATE SECTION. + DATA mt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. +ENDCLASS. +CLASS zcl_abapgit_object_filter_tran DEFINITION + CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES zif_abapgit_object_filter. + + METHODS set_filter_values + IMPORTING + iv_package TYPE tadir-devclass + it_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt + RAISING + zcx_abapgit_exception . + + METHODS get_filter_values + EXPORTING + ev_package TYPE tadir-devclass + et_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt. + + PROTECTED SECTION. + TYPES: BEGIN OF ty_e071_filter, + pgmid TYPE tadir-pgmid, + object TYPE tadir-object, + obj_name TYPE trobj_name, + END OF ty_e071_filter, + ty_e071_filter_tt TYPE STANDARD TABLE OF ty_e071_filter. + + METHODS adjust_local_filter + IMPORTING + it_e071_filter TYPE ty_e071_filter_tt + iv_package TYPE tadir-devclass + RETURNING VALUE(rt_filter) TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + + DATA mt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt . + DATA mt_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt . + DATA mv_package TYPE tadir-devclass. + + METHODS generate_local_filter + IMPORTING + iv_package TYPE tadir-devclass + it_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt + RETURNING + VALUE(rt_filter) TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception . + + METHODS init . + + METHODS get_all_sub_packages + IMPORTING + iv_package TYPE tadir-devclass + RETURNING + VALUE(rt_filter) TYPE zif_abapgit_definitions=>ty_tadir_tt. +ENDCLASS. +CLASS zcl_abapgit_repo_filter DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS apply + IMPORTING + it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt + CHANGING + ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt . + + METHODS apply_object_filter + IMPORTING + it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt + io_dot TYPE REF TO zcl_abapgit_dot_abapgit OPTIONAL + iv_devclass TYPE devclass OPTIONAL + CHANGING + ct_files TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_merge DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES zif_abapgit_merge. + + METHODS constructor + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + !iv_source_branch TYPE string + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + ty_ancestor_tt TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_ancestor WITH DEFAULT KEY . + TYPES: + ty_visit_tt TYPE STANDARD TABLE OF zif_abapgit_git_definitions=>ty_sha1 WITH DEFAULT KEY . + + DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online . + DATA ms_merge TYPE zif_abapgit_merge=>ty_merge . + DATA mt_conflicts TYPE zif_abapgit_merge=>ty_merge_conflict_tt . + DATA mt_objects TYPE zif_abapgit_definitions=>ty_objects_tt . + DATA mv_source_branch TYPE string . + + METHODS visit + IMPORTING + !iv_parent TYPE zif_abapgit_git_definitions=>ty_sha1 + CHANGING + !ct_visit TYPE ty_visit_tt . + METHODS all_files + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_expanded_tt . + METHODS calculate_result + RAISING + zcx_abapgit_exception . + METHODS fetch_git + RETURNING + VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception . + METHODS find_ancestors + IMPORTING + !iv_commit TYPE zif_abapgit_git_definitions=>ty_sha1 + RETURNING + VALUE(rt_ancestors) TYPE ty_ancestor_tt + RAISING + zcx_abapgit_exception . + METHODS find_first_common + IMPORTING + !it_list1 TYPE ty_ancestor_tt + !it_list2 TYPE ty_ancestor_tt + RETURNING + VALUE(rs_common) TYPE zif_abapgit_definitions=>ty_ancestor + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_stage DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS method_description + IMPORTING + !iv_method TYPE zif_abapgit_definitions=>ty_method + RETURNING + VALUE(rv_description) TYPE string + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !iv_merge_source TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL . + METHODS add + IMPORTING + !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path + !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename + !iv_data TYPE xstring + !is_status TYPE zif_abapgit_definitions=>ty_result OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS reset + IMPORTING + !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path + !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename + RAISING + zcx_abapgit_exception . + METHODS rm + IMPORTING + !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path + !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename + !is_status TYPE zif_abapgit_definitions=>ty_result OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS ignore + IMPORTING + !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path + !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename + RAISING + zcx_abapgit_exception . + METHODS get_merge_source + RETURNING + VALUE(rv_source) TYPE zif_abapgit_git_definitions=>ty_sha1 . + METHODS count + RETURNING + VALUE(rv_count) TYPE i . + METHODS get_all + RETURNING + VALUE(rt_stage) TYPE zif_abapgit_definitions=>ty_stage_tt . + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mt_stage TYPE zif_abapgit_definitions=>ty_stage_tt . + DATA mv_merge_source TYPE zif_abapgit_git_definitions=>ty_sha1 . + + METHODS append + IMPORTING + !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path + !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename + !iv_method TYPE zif_abapgit_definitions=>ty_method + !is_status TYPE zif_abapgit_definitions=>ty_result OPTIONAL + !iv_data TYPE xstring OPTIONAL + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_stage_logic DEFINITION + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_stage_logic. + + CLASS-METHODS get_stage_logic + RETURNING + VALUE(ri_logic) TYPE REF TO zif_abapgit_stage_logic. + + CLASS-METHODS set_stage_logic + IMPORTING + ii_logic TYPE REF TO zif_abapgit_stage_logic. + + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gi_stage_logic TYPE REF TO zif_abapgit_stage_logic. + + CLASS-METHODS: + remove_ignored + IMPORTING ii_repo TYPE REF TO zif_abapgit_repo + CHANGING cs_files TYPE zif_abapgit_definitions=>ty_stage_files, + remove_identical + CHANGING cs_files TYPE zif_abapgit_definitions=>ty_stage_files. + +ENDCLASS. +CLASS zcl_abapgit_status_calc DEFINITION + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_status_calc. + + CLASS-METHODS get_instance + IMPORTING + !iv_root_package TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + RETURNING + VALUE(ri_instance) TYPE REF TO zif_abapgit_status_calc. + + METHODS constructor + IMPORTING + !iv_root_package TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_root_package TYPE devclass. + DATA mo_dot TYPE REF TO zcl_abapgit_dot_abapgit. + + METHODS process_local + IMPORTING + !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !it_state_idx TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts + CHANGING + !ct_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + !ct_items TYPE zif_abapgit_definitions=>ty_items_tt + !ct_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + + METHODS process_items + IMPORTING + !it_unprocessed_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + CHANGING + !ct_items TYPE zif_abapgit_definitions=>ty_items_tt + RAISING + zcx_abapgit_exception. + + METHODS process_remote + IMPORTING + !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !it_unprocessed_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + !it_state_idx TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts + !it_items_idx TYPE zif_abapgit_definitions=>ty_items_ts + CHANGING + !ct_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS build_existing + IMPORTING + !is_local TYPE zif_abapgit_definitions=>ty_file_item + !is_remote TYPE zif_abapgit_git_definitions=>ty_file + !it_state TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts + RETURNING + VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_result. + + CLASS-METHODS build_new_local + IMPORTING + !is_local TYPE zif_abapgit_definitions=>ty_file_item + RETURNING + VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_result. + + METHODS build_new_remote + IMPORTING + !is_remote TYPE zif_abapgit_git_definitions=>ty_file + !it_items_idx TYPE zif_abapgit_definitions=>ty_items_ts + !it_state_idx TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts + RETURNING + VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_result + RAISING + zcx_abapgit_exception. + + CLASS-METHODS get_object_package + IMPORTING + !iv_object TYPE tadir-object + !iv_obj_name TYPE tadir-obj_name + RETURNING + VALUE(rv_devclass) TYPE devclass + RAISING + zcx_abapgit_exception. + + CLASS-METHODS check_local_remote_consistency + IMPORTING + !is_local TYPE zif_abapgit_definitions=>ty_file_item + !is_remote TYPE zif_abapgit_git_definitions=>ty_file + RAISING + zcx_abapgit_exception. + + CLASS-METHODS ensure_state + IMPORTING + !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !it_cur_state TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RETURNING + VALUE(rt_state) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt. + +ENDCLASS. +CLASS zcl_abapgit_repo_item_state DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + METHODS local + RETURNING + VALUE(rv_state) TYPE zif_abapgit_git_definitions=>ty_item_state. + METHODS remote + RETURNING + VALUE(rv_state) TYPE zif_abapgit_git_definitions=>ty_item_state. + METHODS is_reassigned + RETURNING + VALUE(rv_is_reassigned) TYPE abap_bool. + METHODS is_unchanged + RETURNING + VALUE(rv_is_unchanged) TYPE abap_bool. + METHODS sum_with_repo_item + IMPORTING + !is_repo_item TYPE zif_abapgit_definitions=>ty_repo_item. + METHODS sum_with_status_item + IMPORTING + !is_status_item TYPE zif_abapgit_definitions=>ty_result. + PROTECTED SECTION. + PRIVATE SECTION. + DATA mv_lstate TYPE zif_abapgit_git_definitions=>ty_item_state. + DATA mv_rstate TYPE zif_abapgit_git_definitions=>ty_item_state. + DATA mv_is_reassigned TYPE abap_bool. + + CLASS-METHODS reduce + IMPORTING + iv_prev TYPE zif_abapgit_git_definitions=>ty_item_state + iv_cur TYPE zif_abapgit_git_definitions=>ty_item_state + RETURNING + VALUE(rv_new) TYPE zif_abapgit_git_definitions=>ty_item_state. +ENDCLASS. +CLASS zcl_abapgit_repo_labels DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_label_color, + label TYPE string, + color TYPE string, + END OF ty_label_color, + ty_label_colors TYPE STANDARD TABLE OF ty_label_color WITH KEY label. + + TYPES: + BEGIN OF ty_color, + cls TYPE string, + fg TYPE string, + bg TYPE string, + border TYPE string, + END OF ty_color. + + CONSTANTS c_allowed_chars TYPE string VALUE `-_. a-zA-Z0-9` ##NO_TEXT. + + " it is easier to allow chars, though potentially other chars can be added later if needed + CLASS-METHODS class_constructor. + CLASS-METHODS validate + IMPORTING + !iv_labels TYPE string + RAISING + zcx_abapgit_exception. + CLASS-METHODS split + IMPORTING + !iv_labels TYPE string + RETURNING + VALUE(rt_labels) TYPE string_table. + CLASS-METHODS normalize + IMPORTING + !iv_labels TYPE string + RETURNING + VALUE(rv_labels) TYPE string. + + CLASS-METHODS validate_colors + IMPORTING + !iv_config TYPE string + RAISING + zcx_abapgit_exception. + CLASS-METHODS split_colors + IMPORTING + !iv_config TYPE string + RETURNING + VALUE(rt_label_colors) TYPE ty_label_colors. + CLASS-METHODS split_colors_into_map + IMPORTING + !iv_config TYPE string + RETURNING + VALUE(ro_map) TYPE REF TO zcl_abapgit_string_map. + CLASS-METHODS normalize_colors + IMPORTING + !iv_config TYPE string + RETURNING + VALUE(rv_config) TYPE string. + + CLASS-METHODS parse_color + IMPORTING + iv_color TYPE string + RETURNING + VALUE(rs_parsed) TYPE ty_color. + + PROTECTED SECTION. + PRIVATE SECTION. + CLASS-DATA gv_regex TYPE string. + + CLASS-METHODS validate_one_label_color + IMPORTING + !is_lc TYPE ty_label_color + !iv_index TYPE i DEFAULT 0 + RAISING + zcx_abapgit_exception. + + CLASS-METHODS validate_rgb_color + IMPORTING + !iv_color TYPE string + !iv_index TYPE i DEFAULT 0 + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_repo_news DEFINITION + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_log, + version TYPE string, + pos_to_cur TYPE i, + is_header TYPE abap_bool, + is_important TYPE abap_bool, + text TYPE string, + END OF ty_log. + TYPES: + ty_logs TYPE STANDARD TABLE OF ty_log WITH DEFAULT KEY. + + CONSTANTS c_tail_length TYPE i VALUE 5 ##NO_TEXT. " Number of versions to display if no updates + + CLASS-METHODS create " TODO REFACTOR + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_repo_news + RAISING + zcx_abapgit_exception. + METHODS get_log + RETURNING + VALUE(rt_log) TYPE ty_logs. + METHODS has_news + RETURNING + VALUE(rv_boolean) TYPE abap_bool. + METHODS has_important + RETURNING + VALUE(rv_boolean) TYPE abap_bool. + METHODS has_updates + RETURNING + VALUE(rv_boolean) TYPE abap_bool. + METHODS has_unseen + RETURNING + VALUE(rv_boolean) TYPE abap_bool. + METHODS constructor + IMPORTING + !iv_rawdata TYPE xstring + !iv_lastseen_version TYPE string + !iv_current_version TYPE string + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mt_log TYPE ty_logs . + DATA mv_current_version TYPE string . + DATA mv_lastseen_version TYPE string . + DATA mv_latest_version TYPE string . + + METHODS latest_version + RETURNING + VALUE(rv_version) TYPE string . + CLASS-METHODS parse_line + IMPORTING + !iv_line TYPE string + !iv_current_version TYPE string + RETURNING + VALUE(rs_log) TYPE ty_log . + CLASS-METHODS parse + IMPORTING + !it_lines TYPE string_table + !iv_current_version TYPE string + RETURNING + VALUE(rt_log) TYPE ty_logs . +ENDCLASS. +CLASS zcl_abapgit_repo_requirements DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + TYPES ty_cvers TYPE STANDARD TABLE OF cvers WITH DEFAULT KEY. + + CLASS-METHODS requirements_popup + IMPORTING + !it_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt + RAISING + zcx_abapgit_exception. + CLASS-METHODS is_requirements_met + IMPORTING + !it_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt + RETURNING + VALUE(rv_status) TYPE zif_abapgit_definitions=>ty_yes_no + RAISING + zcx_abapgit_exception. + + CLASS-METHODS inject_cvers + IMPORTING + !it_cvers TYPE ty_cvers. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_requirement_status, + met TYPE abap_bool, + component TYPE tdevc-dlvunit, + description TYPE string, + installed_release TYPE saprelease, + installed_patch TYPE sappatchlv, + required_release TYPE saprelease, + required_patch TYPE sappatchlv, + END OF ty_requirement_status . + TYPES: + ty_requirement_status_tt TYPE STANDARD TABLE OF ty_requirement_status WITH DEFAULT KEY . + + CLASS-DATA gt_cvers TYPE ty_cvers. + + CLASS-METHODS get_cvers + RETURNING + VALUE(rt_cvers) TYPE ty_cvers + RAISING + zcx_abapgit_exception. + + CLASS-METHODS show_requirement_popup + IMPORTING + !it_requirements TYPE ty_requirement_status_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_requirement_met_status + IMPORTING + !it_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt + RETURNING + VALUE(rt_status) TYPE ty_requirement_status_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS is_version_greater_or_equal + IMPORTING + !is_status TYPE ty_requirement_status + RETURNING + VALUE(rv_true) TYPE abap_bool . +ENDCLASS. +CLASS zcl_abapgit_version DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS normalize + IMPORTING + !iv_version TYPE string + RETURNING + VALUE(rv_version) TYPE string . + CLASS-METHODS conv_str_to_version + IMPORTING + !iv_version TYPE csequence + RETURNING + VALUE(rs_version) TYPE zif_abapgit_definitions=>ty_version + RAISING + zcx_abapgit_exception . + CLASS-METHODS check_dependant_version + IMPORTING + !is_current TYPE zif_abapgit_definitions=>ty_version + !is_dependant TYPE zif_abapgit_definitions=>ty_version + RAISING + zcx_abapgit_exception . + CLASS-METHODS compare + IMPORTING + !iv_a TYPE string OPTIONAL + !iv_b TYPE string OPTIONAL + !is_a TYPE zif_abapgit_definitions=>ty_version OPTIONAL + !is_b TYPE zif_abapgit_definitions=>ty_version OPTIONAL + RETURNING + VALUE(rv_result) TYPE i . + CLASS-METHODS get_version_constant_value + IMPORTING + iv_version_constant TYPE string + RETURNING + VALUE(rv_version) TYPE string + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-METHODS version_to_numeric + IMPORTING + !iv_version TYPE string + RETURNING + VALUE(rv_version) TYPE i. +ENDCLASS. +CLASS zcl_abapgit_zip DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS encode_files + IMPORTING + !it_files TYPE zif_abapgit_definitions=>ty_files_item_tt + RETURNING + VALUE(rv_xstr) TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS export + IMPORTING + !is_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings + !iv_package TYPE devclass + !io_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit + !iv_show_log TYPE abap_bool DEFAULT abap_true + !it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt OPTIONAL + RETURNING + VALUE(rv_xstr) TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS export_object + IMPORTING + !iv_object_type TYPE trobjtype + !iv_object_name TYPE sobj_name + !iv_main_language_only TYPE abap_bool DEFAULT abap_false + !it_translation_langs TYPE zif_abapgit_definitions=>ty_languages OPTIONAL + !iv_use_lxe TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception . + CLASS-METHODS export_package + IMPORTING + !iv_package TYPE devclass + !iv_folder_logic TYPE string + !iv_main_lang_only TYPE abap_bool + !iv_ign_subpkg TYPE abap_bool OPTIONAL + RAISING + zcx_abapgit_exception . + CLASS-METHODS load + IMPORTING + !iv_xstr TYPE xstring + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS save_binstring_to_localfile + IMPORTING + !iv_filename TYPE string + !iv_binstring TYPE xstring + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-METHODS filename + IMPORTING + !iv_str TYPE string + EXPORTING + !ev_path TYPE string + !ev_filename TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS normalize_path + CHANGING + !ct_files TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS unzip_file + IMPORTING + !iv_xstr TYPE xstring + RETURNING + VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_dot_abapgit DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS build_default + RETURNING + VALUE(ro_dot_abapgit) TYPE REF TO zcl_abapgit_dot_abapgit . + CLASS-METHODS deserialize + IMPORTING + !iv_xstr TYPE xstring + RETURNING + VALUE(ro_dot_abapgit) TYPE REF TO zcl_abapgit_dot_abapgit + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !is_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit . + METHODS serialize + RETURNING + VALUE(rv_xstr) TYPE xstring + RAISING + zcx_abapgit_exception . + METHODS to_file + RETURNING + VALUE(rs_file) TYPE zif_abapgit_git_definitions=>ty_file + RAISING + zcx_abapgit_exception . + METHODS get_data + RETURNING + VALUE(rs_data) TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit . + METHODS add_ignore + IMPORTING + !iv_path TYPE string + !iv_filename TYPE string . + METHODS is_ignored + IMPORTING + !iv_path TYPE string + !iv_filename TYPE string + RETURNING + VALUE(rv_ignored) TYPE abap_bool . + METHODS remove_ignore + IMPORTING + !iv_path TYPE string + !iv_filename TYPE string . + METHODS get_starting_folder + RETURNING + VALUE(rv_path) TYPE string . + METHODS get_folder_logic + RETURNING + VALUE(rv_logic) TYPE string . + METHODS set_folder_logic + IMPORTING + !iv_logic TYPE string . + METHODS set_starting_folder + IMPORTING + !iv_path TYPE string . + METHODS get_main_language + RETURNING + VALUE(rv_language) TYPE spras . + METHODS get_i18n_languages + RETURNING + VALUE(rt_languages) TYPE zif_abapgit_definitions=>ty_languages + RAISING + zcx_abapgit_exception . + METHODS set_i18n_languages + IMPORTING + it_languages TYPE zif_abapgit_definitions=>ty_languages + RAISING + zcx_abapgit_exception . + METHODS determine_i18n_parameters + IMPORTING + !iv_main_language_only TYPE abap_bool + RETURNING + VALUE(rs_i18n_params) TYPE zif_abapgit_definitions=>ty_i18n_params + RAISING + zcx_abapgit_exception. + METHODS get_signature + RETURNING + VALUE(rs_signature) TYPE zif_abapgit_git_definitions=>ty_file_signature + RAISING + zcx_abapgit_exception . + METHODS use_lxe + IMPORTING + !iv_yes TYPE abap_bool DEFAULT abap_undefined + RETURNING + VALUE(rv_yes) TYPE abap_bool . + METHODS get_requirements + RETURNING + VALUE(rt_requirements) TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt . + METHODS set_requirements + IMPORTING + !it_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt . + METHODS get_name + RETURNING + VALUE(rv_name) TYPE string. + METHODS set_name + IMPORTING + !iv_name TYPE csequence. + METHODS get_version_constant + RETURNING + VALUE(rv_version_constant) TYPE string . + METHODS set_version_constant + IMPORTING + !iv_version_constant TYPE csequence . + METHODS get_abap_language_version + RETURNING + VALUE(rv_abap_language_version) TYPE string . + METHODS set_abap_language_version + IMPORTING + !iv_abap_language_version TYPE string . + METHODS get_original_system + RETURNING + VALUE(rv_original_system) TYPE string . + METHODS set_original_system + IMPORTING + !iv_original_system TYPE csequence . + METHODS get_objs_without_translation + RETURNING + VALUE(rt_list) TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit-without_translation. + METHODS set_objs_without_translation + IMPORTING + !it_list TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit-without_translation. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA ms_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit . + + CLASS-METHODS to_xml + IMPORTING + !is_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit + RETURNING + VALUE(rv_xml) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS from_xml + IMPORTING + !iv_xml TYPE string + RETURNING + VALUE(rs_data) TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit . +ENDCLASS. +CLASS zcl_abapgit_repo DEFINITION + ABSTRACT + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_repo . + + ALIASES ms_data + FOR zif_abapgit_repo~ms_data . + + ALIASES get_key FOR zif_abapgit_repo~get_key. + ALIASES get_name FOR zif_abapgit_repo~get_name. + ALIASES is_offline FOR zif_abapgit_repo~is_offline. + ALIASES get_package FOR zif_abapgit_repo~get_package. + ALIASES get_local_settings FOR zif_abapgit_repo~get_local_settings. + ALIASES get_tadir_objects FOR zif_abapgit_repo~get_tadir_objects. + ALIASES get_files_local_filtered FOR zif_abapgit_repo~get_files_local_filtered. + ALIASES get_files_local FOR zif_abapgit_repo~get_files_local. + ALIASES get_files_remote FOR zif_abapgit_repo~get_files_remote. + ALIASES refresh FOR zif_abapgit_repo~refresh. + ALIASES get_dot_abapgit FOR zif_abapgit_repo~get_dot_abapgit. + ALIASES set_dot_abapgit FOR zif_abapgit_repo~set_dot_abapgit. + ALIASES find_remote_dot_abapgit FOR zif_abapgit_repo~find_remote_dot_abapgit. + ALIASES deserialize FOR zif_abapgit_repo~deserialize. + ALIASES deserialize_checks FOR zif_abapgit_repo~deserialize_checks. + ALIASES checksums FOR zif_abapgit_repo~checksums. + ALIASES has_remote_source FOR zif_abapgit_repo~has_remote_source. + ALIASES get_log FOR zif_abapgit_repo~get_log. + ALIASES create_new_log FOR zif_abapgit_repo~create_new_log. + ALIASES get_dot_apack FOR zif_abapgit_repo~get_dot_apack. + ALIASES delete_checks FOR zif_abapgit_repo~delete_checks. + ALIASES set_files_remote FOR zif_abapgit_repo~set_files_remote. + ALIASES get_unsupported_objects_local FOR zif_abapgit_repo~get_unsupported_objects_local. + ALIASES set_local_settings FOR zif_abapgit_repo~set_local_settings. + ALIASES switch_repo_type FOR zif_abapgit_repo~switch_repo_type. + ALIASES refresh_local_object FOR zif_abapgit_repo~refresh_local_object. + ALIASES refresh_local_objects FOR zif_abapgit_repo~refresh_local_objects. + ALIASES get_data_config FOR zif_abapgit_repo~get_data_config. + ALIASES bind_listener FOR zif_abapgit_repo~bind_listener. + ALIASES remove_ignored_files FOR zif_abapgit_repo~remove_ignored_files. + + METHODS constructor + IMPORTING + !is_data TYPE zif_abapgit_persistence=>ty_repo . + + PROTECTED SECTION. + + DATA mt_local TYPE zif_abapgit_definitions=>ty_files_item_tt . + DATA mt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt . + DATA mv_request_local_refresh TYPE abap_bool . + DATA mv_request_remote_refresh TYPE abap_bool . + DATA mi_log TYPE REF TO zif_abapgit_log . + DATA mi_listener TYPE REF TO zif_abapgit_repo_listener . + DATA mo_apack_reader TYPE REF TO zcl_abapgit_apack_reader . + DATA mi_data_config TYPE REF TO zif_abapgit_data_config . + + METHODS find_remote_dot_apack + RETURNING + VALUE(ro_dot) TYPE REF TO zcl_abapgit_apack_reader + RAISING + zcx_abapgit_exception . + METHODS reset_remote . + METHODS set + IMPORTING + !iv_url TYPE zif_abapgit_persistence=>ty_repo-url OPTIONAL + !iv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name OPTIONAL + !iv_selected_commit TYPE zif_abapgit_persistence=>ty_repo-selected_commit OPTIONAL + !iv_head_branch TYPE zif_abapgit_persistence=>ty_repo-head_branch OPTIONAL + !iv_offline TYPE zif_abapgit_persistence=>ty_repo-offline OPTIONAL + !is_dot_abapgit TYPE zif_abapgit_persistence=>ty_repo-dot_abapgit OPTIONAL + !is_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings OPTIONAL + !iv_deserialized_at TYPE zif_abapgit_persistence=>ty_repo-deserialized_at OPTIONAL + !iv_deserialized_by TYPE zif_abapgit_persistence=>ty_repo-deserialized_by OPTIONAL + !iv_switched_origin TYPE zif_abapgit_persistence=>ty_repo-switched_origin OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS set_dot_apack + IMPORTING + !io_dot_apack TYPE REF TO zcl_abapgit_apack_reader + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + METHODS check_language + RAISING + zcx_abapgit_exception . + METHODS check_write_protect + RAISING + zcx_abapgit_exception . + METHODS deserialize_data + IMPORTING + !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks + CHANGING + !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RAISING + zcx_abapgit_exception . + METHODS deserialize_dot_abapgit + CHANGING + !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RAISING + zcx_abapgit_exception . + METHODS deserialize_objects + IMPORTING + !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks + !ii_log TYPE REF TO zif_abapgit_log + CHANGING + !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RAISING + zcx_abapgit_exception . + METHODS normalize_local_settings + CHANGING + !cs_local_settings TYPE zif_abapgit_persistence=>ty_local_settings . + METHODS notify_listener + IMPORTING + !is_change_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask + RAISING + zcx_abapgit_exception . + METHODS update_last_deserialize + RAISING + zcx_abapgit_exception . + METHODS check_abap_language_version + RAISING + zcx_abapgit_exception . + METHODS remove_locally_excluded_files + CHANGING + !ct_rem_files TYPE zif_abapgit_git_definitions=>ty_files_tt OPTIONAL + !ct_loc_files TYPE zif_abapgit_definitions=>ty_files_item_tt OPTIONAL + RAISING + zcx_abapgit_exception . + +ENDCLASS. +CLASS zcl_abapgit_repo_checksums DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_repo_checksums. + + METHODS constructor + IMPORTING + !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception. + + METHODS force_write + IMPORTING + it_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + ty_local_files_by_item_tt TYPE SORTED TABLE OF zif_abapgit_definitions=>ty_file_item WITH NON-UNIQUE KEY item. + + DATA mv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key. + DATA mi_repo TYPE REF TO zif_abapgit_repo. + + METHODS remove_non_code_related_files + CHANGING + !ct_local_files TYPE ty_local_files_by_item_tt. + + METHODS build_checksums_from_files + IMPORTING + it_local TYPE ty_local_files_by_item_tt + RETURNING + VALUE(rt_checksums) TYPE zif_abapgit_persistence=>ty_local_checksum_tt. + + METHODS save_checksums + IMPORTING + it_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt + RAISING + zcx_abapgit_exception. + + METHODS add_meta + CHANGING + cv_cs_blob TYPE string + RAISING + zcx_abapgit_exception. + + METHODS extract_meta + CHANGING +* co_string_map - return string map with meta when it is needed + cv_cs_blob TYPE string. + + METHODS get_latest_local_files + IMPORTING + it_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + RETURNING + VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_repo_content_list DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS constructor + IMPORTING ii_repo TYPE REF TO zif_abapgit_repo. + + METHODS list + IMPORTING iv_path TYPE string + iv_by_folders TYPE abap_bool OPTIONAL + iv_changes_only TYPE abap_bool OPTIONAL + iv_transports TYPE abap_bool OPTIONAL + RETURNING VALUE(rt_repo_items) TYPE zif_abapgit_definitions=>ty_repo_item_tt + RAISING zcx_abapgit_exception. + + METHODS get_log + RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log. + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: BEGIN OF c_sortkey, + default TYPE i VALUE 9999, + parent_dir TYPE i VALUE 0, + dir TYPE i VALUE 1, + orphan TYPE i VALUE 2, + changed TYPE i VALUE 3, + inactive TYPE i VALUE 4, + END OF c_sortkey. + + DATA: mi_repo TYPE REF TO zif_abapgit_repo, + mi_log TYPE REF TO zif_abapgit_log. + + METHODS build_repo_items + RETURNING VALUE(rt_repo_items) TYPE zif_abapgit_definitions=>ty_repo_item_tt + RAISING zcx_abapgit_exception. + + METHODS build_folders + IMPORTING iv_cur_dir TYPE string + CHANGING ct_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt + RAISING zcx_abapgit_exception. + + METHODS determine_transports + CHANGING ct_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt. + + METHODS filter_changes + CHANGING ct_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt. + + METHODS check_repo_size + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_repo_cs_migration DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + CLASS-METHODS run + RAISING + zcx_abapgit_exception + zcx_abapgit_not_found. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + ty_repo_ids TYPE SORTED TABLE OF zif_abapgit_persistence=>ty_repo-key WITH UNIQUE KEY table_line. + + CLASS-METHODS get_unconverted_repo_ids + RETURNING + VALUE(rt_repo_ids) TYPE ty_repo_ids. + CLASS-METHODS clear_repo_metadata + IMPORTING + iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception + zcx_abapgit_not_found. + CLASS-METHODS convert_checksums + IMPORTING + iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception + zcx_abapgit_not_found. + +ENDCLASS. +CLASS zcl_abapgit_repo_offline DEFINITION + INHERITING FROM zcl_abapgit_repo + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + PROTECTED SECTION. + + METHODS reset_remote + REDEFINITION . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_repo_online DEFINITION + INHERITING FROM zcl_abapgit_repo + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_repo_online . + + ALIASES get_url FOR zif_abapgit_repo_online~get_url. + ALIASES get_selected_branch FOR zif_abapgit_repo_online~get_selected_branch. + ALIASES set_url FOR zif_abapgit_repo_online~set_url. + ALIASES select_branch FOR zif_abapgit_repo_online~select_branch. + ALIASES get_selected_commit FOR zif_abapgit_repo_online~get_selected_commit. + ALIASES get_current_remote FOR zif_abapgit_repo_online~get_current_remote. + ALIASES select_commit FOR zif_abapgit_repo_online~select_commit. + ALIASES switch_origin FOR zif_abapgit_repo_online~switch_origin. + ALIASES get_switched_origin FOR zif_abapgit_repo_online~get_switched_origin. + ALIASES push FOR zif_abapgit_repo_online~push. + ALIASES create_branch FOR zif_abapgit_repo_online~create_branch. + ALIASES check_for_valid_branch FOR zif_abapgit_repo_online~check_for_valid_branch. + ALIASES get_remote_settings FOR zif_abapgit_repo_online~get_remote_settings. + + METHODS zif_abapgit_repo~get_files_remote + REDEFINITION . + METHODS zif_abapgit_repo~get_name + REDEFINITION . + METHODS zif_abapgit_repo~has_remote_source + REDEFINITION . + METHODS constructor + IMPORTING + is_data TYPE zif_abapgit_persistence=>ty_repo. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mt_objects TYPE zif_abapgit_definitions=>ty_objects_tt . + DATA mv_current_commit TYPE zif_abapgit_git_definitions=>ty_sha1 . + + METHODS handle_stage_ignore + IMPORTING + !io_stage TYPE REF TO zcl_abapgit_stage + RAISING + zcx_abapgit_exception . + METHODS set_objects + IMPORTING + !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception . + METHODS fetch_remote + RAISING + zcx_abapgit_exception . + METHODS get_objects + RETURNING + VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt + RAISING + zcx_abapgit_exception . + METHODS raise_error_if_branch_exists + IMPORTING + iv_name TYPE string + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_repo_srv DEFINITION + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_repo_srv . + INTERFACES zif_abapgit_repo_listener . + + CLASS-METHODS get_instance + RETURNING + VALUE(ri_srv) TYPE REF TO zif_abapgit_repo_srv . + CLASS-METHODS inject_instance + IMPORTING + ii_srv TYPE REF TO zif_abapgit_repo_srv OPTIONAL. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_main_branch TYPE string VALUE 'main'. + + CLASS-DATA gi_ref TYPE REF TO zif_abapgit_repo_srv . + DATA mv_init TYPE abap_bool. + DATA mv_only_favorites TYPE abap_bool. + DATA mt_list TYPE zif_abapgit_repo_srv=>ty_repo_list . + + METHODS create_initial_branch + IMPORTING + !iv_url TYPE string + !iv_readme TYPE string OPTIONAL + !iv_branch_name TYPE string DEFAULT c_main_branch + RETURNING + VALUE(rv_name) TYPE string + RAISING + zcx_abapgit_exception. + + METHODS determine_branch_name + IMPORTING + !iv_name TYPE string + !iv_url TYPE string + RETURNING + VALUE(rv_name) TYPE string + RAISING + zcx_abapgit_exception . + METHODS refresh_all + RAISING + zcx_abapgit_exception . + METHODS refresh_favorites + RAISING + zcx_abapgit_exception . + METHODS instantiate_and_add + IMPORTING + !is_repo_meta TYPE zif_abapgit_persistence=>ty_repo + RETURNING + VALUE(ri_repo) TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + METHODS add + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + METHODS reinstantiate_repo + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !is_meta TYPE zif_abapgit_persistence=>ty_repo_xml + RAISING + zcx_abapgit_exception . + + METHODS validate_sub_super_packages + IMPORTING + !iv_package TYPE devclass + !it_repos TYPE zif_abapgit_persistence=>ty_repos + !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false + EXPORTING + VALUE(ei_repo) TYPE REF TO zif_abapgit_repo + !ev_reason TYPE string + RAISING + zcx_abapgit_exception . + + METHODS validate_package_korrflag + IMPORTING + !iv_package TYPE devclass + !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_repo_status DEFINITION + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + CLASS-METHODS calculate + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !ii_log TYPE REF TO zif_abapgit_log OPTIONAL + !ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL + RETURNING + VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_syntax_factory DEFINITION + ABSTRACT + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS create + IMPORTING + !iv_filename TYPE string + !iv_hidden_chars TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_syntax_highlighter . + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_syntax_highlighter DEFINITION + ABSTRACT + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS process_line + IMPORTING + !iv_line TYPE string + RETURNING + VALUE(rv_line) TYPE string . + METHODS set_hidden_chars + IMPORTING + !iv_hidden_chars TYPE abap_bool . + PROTECTED SECTION. + + TYPES: + BEGIN OF ty_match, + token TYPE c LENGTH 1, " Type of matches + offset TYPE i, " Beginning position of the string that should be formatted + length TYPE i, " Length of the string that should be formatted + text_tag TYPE string, " Type of text tag + END OF ty_match . + TYPES: + ty_match_tt TYPE STANDARD TABLE OF ty_match WITH DEFAULT KEY . + TYPES: + BEGIN OF ty_rule, + regex TYPE REF TO cl_abap_regex, + token TYPE c LENGTH 1, + style TYPE string, + relevant_submatch TYPE i, + END OF ty_rule . + + CONSTANTS c_token_none TYPE c VALUE '.' ##NO_TEXT. + DATA: + mt_rules TYPE STANDARD TABLE OF ty_rule . + DATA mv_hidden_chars TYPE abap_bool . + + METHODS add_rule + IMPORTING + !iv_regex TYPE string + !iv_token TYPE c + !iv_style TYPE string + !iv_submatch TYPE i OPTIONAL . + METHODS parse_line + IMPORTING + !iv_line TYPE string + RETURNING + VALUE(rt_matches) TYPE ty_match_tt . + METHODS order_matches + IMPORTING + !iv_line TYPE string + CHANGING + !ct_matches TYPE ty_match_tt . + METHODS extend_matches + IMPORTING + !iv_line TYPE string + CHANGING + !ct_matches TYPE ty_match_tt . + METHODS format_line + IMPORTING + !iv_line TYPE string + !it_matches TYPE ty_match_tt + RETURNING + VALUE(rv_line) TYPE string . + METHODS apply_style + IMPORTING + !iv_line TYPE string + !iv_class TYPE string + RETURNING + VALUE(rv_line) TYPE string . + METHODS is_whitespace + IMPORTING + !iv_string TYPE string + RETURNING + VALUE(rv_result) TYPE abap_bool . + METHODS show_hidden_chars + IMPORTING + !iv_line TYPE string + RETURNING + VALUE(rv_line) TYPE string . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_syntax_abap DEFINITION + INHERITING FROM zcl_abapgit_syntax_highlighter + CREATE PUBLIC . + + PUBLIC SECTION. + CLASS-METHODS class_constructor. + METHODS constructor. + + CONSTANTS: + BEGIN OF c_css, + keyword TYPE string VALUE 'keyword', + text TYPE string VALUE 'text', + comment TYPE string VALUE 'comment', + END OF c_css, + + BEGIN OF c_token, + keyword TYPE c VALUE 'K', + text TYPE c VALUE 'T', + comment TYPE c VALUE 'C', + END OF c_token, + + BEGIN OF c_regex, + comment TYPE string VALUE '##|"|^\*', + text TYPE string VALUE '`|''|\||\{|\}', + keyword TYPE string VALUE '&&|\b[-_a-z0-9]+\b', + END OF c_regex. + + PROTECTED SECTION. + + CLASS-DATA gt_keywords TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line. + + CLASS-METHODS init_keywords. + CLASS-METHODS is_keyword + IMPORTING iv_chunk TYPE string + RETURNING VALUE(rv_yes) TYPE abap_bool. + + METHODS order_matches REDEFINITION. + METHODS parse_line REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_syntax_css DEFINITION + INHERITING FROM zcl_abapgit_syntax_highlighter + CREATE PUBLIC . + + PUBLIC SECTION. + + " CSS Standard https://www.w3.org/TR/css-2018/ + " CSS Reference https://www.w3schools.com/cssref/default.asp + + " We used a mixture of above as reference for the keyword list + " 1) CSS Properties https://www.w3schools.com/cssref/default.asp + " 2) CSS Values & Units https://www.w3schools.com/cssref/css_units.asp + " 3) CSS Selectors https://www.w3.org/TR/css-2018/#selectors + " 4) CSS Functions https://www.w3schools.com/cssref/css_functions.asp + " 5) CSS Colors https://www.w3schools.com/colors/colors_names.asp + " 6) CSS Extensions + " 7) CSS At-Rules https://www.w3.org/TR/css-2018/#at-rules + " 8) HTML Tags + + CONSTANTS: + BEGIN OF c_css, + keyword TYPE string VALUE 'keyword', + text TYPE string VALUE 'text', + comment TYPE string VALUE 'comment', + selectors TYPE string VALUE 'selectors', + units TYPE string VALUE 'units', + properties TYPE string VALUE 'properties', + values TYPE string VALUE 'values', + functions TYPE string VALUE 'functions', + colors TYPE string VALUE 'colors', + extensions TYPE string VALUE 'extensions', + at_rules TYPE string VALUE 'at_rules', + html TYPE string VALUE 'html', + END OF c_css . + CONSTANTS: + BEGIN OF c_token, + keyword TYPE c VALUE 'K', + text TYPE c VALUE 'T', + comment TYPE c VALUE 'C', + selectors TYPE c VALUE 'S', + units TYPE c VALUE 'U', + properties TYPE c VALUE 'P', + values TYPE c VALUE 'V', + functions TYPE c VALUE 'F', + colors TYPE c VALUE 'Z', + extensions TYPE c VALUE 'E', + at_rules TYPE c VALUE 'A', + html TYPE c VALUE 'H', + END OF c_token . + CONSTANTS: + BEGIN OF c_regex, + " comments /* ... */ + comment TYPE string VALUE '\/\*.*\*\/|\/\*|\*\/', + " single or double quoted strings + text TYPE string VALUE '("[^"]*")|(''[^'']*'')|(`[^`]*`)', + " in general keywords don't contain numbers (except -ms-scrollbar-3dlight-color) + keyword TYPE string VALUE '\b[a-z3@\-]+\b', + " selectors begin with : + selectors TYPE string VALUE ':[:a-z]+\b', + " units + units TYPE string + VALUE '\b[0-9\. ]+(ch|cm|em|ex|in|mm|pc|pt|px|vh|vmax|vmin|vw)\b|\b[0-9\. ]+%', + END OF c_regex . + + CLASS-METHODS class_constructor . + METHODS constructor . + PROTECTED SECTION. + TYPES: ty_token TYPE c LENGTH 1. + + TYPES: BEGIN OF ty_keyword, + keyword TYPE string, + token TYPE ty_token, + END OF ty_keyword. + + CLASS-DATA gt_keywords TYPE HASHED TABLE OF ty_keyword WITH UNIQUE KEY keyword. + CLASS-DATA gv_comment TYPE abap_bool. + + CLASS-METHODS init_keywords. + CLASS-METHODS insert_keywords + IMPORTING + iv_keywords TYPE string + iv_token TYPE ty_token. + CLASS-METHODS is_keyword + IMPORTING iv_chunk TYPE string + RETURNING VALUE(rv_yes) TYPE abap_bool. + + METHODS order_matches REDEFINITION. + METHODS parse_line REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_syntax_js DEFINITION + INHERITING FROM zcl_abapgit_syntax_highlighter + CREATE PUBLIC . + + PUBLIC SECTION. + + CONSTANTS: + " JavaScript + " 1) General keywords + " 2) Variable types + " 3) HTML Tags + BEGIN OF c_css, + keyword TYPE string VALUE 'keyword', + text TYPE string VALUE 'text', + comment TYPE string VALUE 'comment', + variables TYPE string VALUE 'variables', + END OF c_css . + CONSTANTS: + BEGIN OF c_token, + keyword TYPE c VALUE 'K', + text TYPE c VALUE 'T', + comment TYPE c VALUE 'C', + variables TYPE c VALUE 'V', + END OF c_token . + CONSTANTS: + BEGIN OF c_regex, + " comments /* ... */ or // + comment TYPE string VALUE '\/\*.*\*\/|\/\*|\*\/|\/\/', + " single or double quoted strings + text TYPE string VALUE '"|''|`', + " in general keywords don't contain numbers (except -ms-scrollbar-3dlight-color) + keyword TYPE string VALUE '\b[a-z-]+\b', + END OF c_regex . + + CLASS-METHODS class_constructor . + METHODS constructor . + PROTECTED SECTION. + TYPES: ty_token TYPE c LENGTH 1. + + TYPES: BEGIN OF ty_keyword, + keyword TYPE string, + token TYPE ty_token, + END OF ty_keyword. + + CLASS-DATA gt_keywords TYPE HASHED TABLE OF ty_keyword WITH UNIQUE KEY keyword. + CLASS-DATA gv_comment TYPE abap_bool. + + CLASS-METHODS init_keywords. + CLASS-METHODS insert_keywords + IMPORTING + iv_keywords TYPE string + iv_token TYPE ty_token. + CLASS-METHODS is_keyword + IMPORTING iv_chunk TYPE string + RETURNING VALUE(rv_yes) TYPE abap_bool. + + METHODS order_matches REDEFINITION. + METHODS parse_line REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_syntax_json DEFINITION + INHERITING FROM zcl_abapgit_syntax_highlighter + CREATE PUBLIC. + + PUBLIC SECTION. + + CONSTANTS: + " JSON... This was easy :-) + " JSONC... With comments + BEGIN OF c_css, + keyword TYPE string VALUE 'selectors', "#EC NOTEXT + text TYPE string VALUE 'text', "#EC NOTEXT + values TYPE string VALUE 'properties', "#EC NOTEXT + comment TYPE string VALUE 'comment', "#EC NOTEXT + END OF c_css. + CONSTANTS: + BEGIN OF c_token, + keyword TYPE c VALUE 'K', "#EC NOTEXT + text TYPE c VALUE 'T', "#EC NOTEXT + values TYPE c VALUE 'V', "#EC NOTEXT + comment TYPE c VALUE 'C', "#EC NOTEXT + END OF c_token. + CONSTANTS: + BEGIN OF c_regex, + " comments /* ... */ or // + comment TYPE string VALUE '\/\*.*\*\/|\/\*|\*\/|\/\/', "#EC NOTEXT + " not much here + keyword TYPE string VALUE 'true|false|null', "#EC NOTEXT + " double quoted strings + text TYPE string VALUE '"', "#EC NOTEXT + END OF c_regex. + + METHODS constructor. + PROTECTED SECTION. + + METHODS order_matches REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_syntax_po DEFINITION + INHERITING FROM zcl_abapgit_syntax_highlighter + CREATE PUBLIC. + + PUBLIC SECTION. + + METHODS constructor. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_style, + msgid TYPE string VALUE 'keyword', + msgstr TYPE string VALUE 'xml_tag', + comment TYPE string VALUE 'comment', + END OF c_style. + CONSTANTS: + BEGIN OF c_token, + msgid TYPE c VALUE 'I', + msgstr TYPE c VALUE 'S', + comment TYPE c VALUE 'C', + END OF c_token. + CONSTANTS: + BEGIN OF c_regex, + msgid TYPE string VALUE '^msgid\b', + msgstr TYPE string VALUE '^msgstr\b', + comment TYPE string VALUE '^#.*', + END OF c_regex. + +ENDCLASS. +CLASS zcl_abapgit_syntax_txt DEFINITION + INHERITING FROM zcl_abapgit_syntax_highlighter + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor . + + METHODS process_line + REDEFINITION . + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_syntax_xml DEFINITION + INHERITING FROM zcl_abapgit_syntax_highlighter + CREATE PUBLIC . + + PUBLIC SECTION. + + CONSTANTS: + BEGIN OF c_css, + xml_tag TYPE string VALUE 'xml_tag', + attr TYPE string VALUE 'attr', + attr_val TYPE string VALUE 'attr_val', + comment TYPE string VALUE 'comment', + END OF c_css . + CONSTANTS: + BEGIN OF c_token, + xml_tag TYPE c VALUE 'X', + attr TYPE c VALUE 'A', + attr_val TYPE c VALUE 'V', + comment TYPE c VALUE 'C', + END OF c_token . + CONSTANTS: + BEGIN OF c_regex, + "for XML tags, we will use a submatch + " main pattern includes quoted strings so we can ignore < and > in attr values + xml_tag TYPE string VALUE '(?:"[^"]*")|(?:''[^'']*'')|(?:`[^`]*`)|([<>])', + attr TYPE string VALUE '(?:^|\s)[-a-z:_0-9]+\s*(?==\s*["|''|`])', + attr_val TYPE string VALUE '("[^"]*")|(''[^'']*'')|(`[^`]*`)', + " comments + comment TYPE string VALUE '[\<]!--.*--[\>]|[\<]!--|--[\>]', + END OF c_regex . + + METHODS constructor . + PROTECTED SECTION. + CLASS-DATA gv_comment TYPE abap_bool. + + METHODS order_matches REDEFINITION. + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_gui DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_services . + + CONSTANTS: + BEGIN OF c_event_state, + not_handled TYPE i VALUE 0, + re_render TYPE i VALUE 1, + new_page TYPE i VALUE 2, + go_back TYPE i VALUE 3, + no_more_act TYPE i VALUE 4, + new_page_w_bookmark TYPE i VALUE 5, + go_back_to_bookmark TYPE i VALUE 6, + new_page_replacing TYPE i VALUE 7, + END OF c_event_state . + + METHODS go_home + IMPORTING + iv_action TYPE string + RAISING + zcx_abapgit_exception . + METHODS back + IMPORTING + !iv_to_bookmark TYPE abap_bool DEFAULT abap_false + !iv_graceful TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rv_exit) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS back_graceful + RETURNING + VALUE(rv_handled) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS on_event + FOR EVENT sapevent OF zif_abapgit_html_viewer + IMPORTING + !action + !frame + !getdata + !postdata + !query_table . + METHODS constructor + IMPORTING + !io_component TYPE REF TO object OPTIONAL + !ii_asset_man TYPE REF TO zif_abapgit_gui_asset_manager OPTIONAL + !ii_hotkey_ctl TYPE REF TO zif_abapgit_gui_hotkey_ctl OPTIONAL + !ii_html_processor TYPE REF TO zif_abapgit_gui_html_processor OPTIONAL + !iv_rollback_on_error TYPE abap_bool DEFAULT abap_true + RAISING + zcx_abapgit_exception . + METHODS free . + METHODS set_focus + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_page_stack, + page TYPE REF TO zif_abapgit_gui_renderable, + bookmark TYPE abap_bool, + END OF ty_page_stack . + + DATA mv_rollback_on_error TYPE abap_bool . + DATA mi_cur_page TYPE REF TO zif_abapgit_gui_renderable . + DATA mt_stack TYPE STANDARD TABLE OF ty_page_stack . + DATA mt_event_handlers TYPE STANDARD TABLE OF REF TO zif_abapgit_gui_event_handler . + DATA mi_router TYPE REF TO zif_abapgit_gui_event_handler . + DATA mi_asset_man TYPE REF TO zif_abapgit_gui_asset_manager . + DATA mi_hotkey_ctl TYPE REF TO zif_abapgit_gui_hotkey_ctl . + DATA mi_html_processor TYPE REF TO zif_abapgit_gui_html_processor . + DATA mi_html_viewer TYPE REF TO zif_abapgit_html_viewer . + DATA mo_html_parts TYPE REF TO zcl_abapgit_html_parts . + DATA mi_common_log TYPE REF TO zif_abapgit_log . + METHODS cache_html + IMPORTING + !iv_text TYPE string + RETURNING + VALUE(rv_url) TYPE string + RAISING + zcx_abapgit_exception . + METHODS startup + RAISING + zcx_abapgit_exception . + METHODS render + RAISING + zcx_abapgit_exception . + METHODS call_page + IMPORTING + !ii_page TYPE REF TO zif_abapgit_gui_renderable + !iv_with_bookmark TYPE abap_bool DEFAULT abap_false + !iv_replacing TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception . + METHODS handle_action + IMPORTING + !iv_action TYPE c + !iv_getdata TYPE c OPTIONAL + !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data OPTIONAL . + METHODS handle_error + IMPORTING + !iv_state TYPE i + !ix_exception TYPE REF TO zcx_abapgit_exception . + METHODS is_page_modal + IMPORTING + !ii_page TYPE REF TO zif_abapgit_gui_renderable + RETURNING + VALUE(rv_yes) TYPE abap_bool . + METHODS is_new_page + IMPORTING + !iv_state TYPE i + RETURNING + VALUE(rv_new_page) TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_gui_asset_manager DEFINITION FINAL CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_asset_manager. + + CLASS-METHODS create + RETURNING + VALUE(ri_asset_manager) TYPE REF TO zif_abapgit_gui_asset_manager. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_asset_entry. + INCLUDE TYPE zif_abapgit_gui_asset_manager~ty_web_asset. + TYPES: mime_name TYPE wwwdatatab-objid, + END OF ty_asset_entry. + TYPES: + ty_asset_register TYPE STANDARD TABLE OF ty_asset_entry WITH KEY url. + + DATA mt_asset_register TYPE ty_asset_register. + + METHODS get_mime_asset + IMPORTING + iv_mime_name TYPE c + RETURNING + VALUE(rv_xdata) TYPE xstring + RAISING + zcx_abapgit_exception. + + METHODS load_asset + IMPORTING + is_asset_entry TYPE ty_asset_entry + RETURNING + VALUE(rs_asset) TYPE zif_abapgit_gui_asset_manager~ty_web_asset + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_css_processor DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + METHODS: + constructor + IMPORTING + ii_asset_manager TYPE REF TO zif_abapgit_gui_asset_manager, + add_file + IMPORTING + iv_url TYPE string, + process + RETURNING + VALUE(rv_result) TYPE string + RAISING zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_css_var, + name TYPE string, + value TYPE string, + END OF ty_css_var, + ty_css_vars TYPE SORTED TABLE OF ty_css_var WITH UNIQUE KEY name. + + METHODS: + get_css_vars_in_string + IMPORTING + iv_string TYPE string + RETURNING + VALUE(rt_variables) TYPE ty_css_vars, + resolve_var_recursively + IMPORTING + iv_variable_name TYPE string + CHANGING + ct_variables TYPE ty_css_vars + RAISING + zcx_abapgit_exception. + DATA: + mi_asset_manager TYPE REF TO zif_abapgit_gui_asset_manager, + mt_files TYPE string_table. +ENDCLASS. +CLASS zcl_abapgit_gui_event DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event . + + CLASS-METHODS class_constructor . + + CLASS-METHODS new + IMPORTING + !ii_gui_services TYPE REF TO zif_abapgit_gui_services OPTIONAL + !iv_action TYPE clike + !iv_getdata TYPE clike OPTIONAL + !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data OPTIONAL + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_gui_event. + METHODS constructor + IMPORTING + !ii_gui_services TYPE REF TO zif_abapgit_gui_services OPTIONAL + !iv_action TYPE clike + !iv_getdata TYPE clike OPTIONAL + !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data OPTIONAL . + PROTECTED SECTION. + PRIVATE SECTION. + DATA mo_query TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + + CLASS-DATA gv_non_breaking_space TYPE string . + + TYPES: BEGIN OF ty_name_value, + name TYPE string, + value TYPE string, + END OF ty_name_value. + TYPES ty_name_value_tt TYPE STANDARD TABLE OF ty_name_value WITH DEFAULT KEY. + + METHODS fields_to_map + IMPORTING + it_fields TYPE ty_name_value_tt + RETURNING + VALUE(ro_string_map) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + + CLASS-METHODS parse_post_form_data + IMPORTING + !it_post_data TYPE zif_abapgit_html_viewer=>ty_post_data + !iv_upper_cased TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_fields) TYPE ty_name_value_tt . + CLASS-METHODS parse_fields + IMPORTING + !iv_string TYPE clike + !iv_upper_cased TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_fields) TYPE ty_name_value_tt . + + CLASS-METHODS parse_fields_upper_case_name + IMPORTING + !iv_string TYPE clike + RETURNING + VALUE(rt_fields) TYPE ty_name_value_tt . + + CLASS-METHODS translate_postdata + IMPORTING + !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data + RETURNING + VALUE(rv_string) TYPE string . + + CLASS-METHODS field_keys_to_upper + CHANGING + !ct_fields TYPE ty_name_value_tt . + CLASS-METHODS unescape + IMPORTING + !iv_string TYPE string + RETURNING + VALUE(rv_string) TYPE string . + +ENDCLASS. +CLASS zcl_abapgit_gui_html_processor DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CONSTANTS c_css_build_name TYPE string VALUE 'css/bundle.css'. + CONSTANTS c_preprocess_marker TYPE string VALUE ``. + CONSTANTS c_comment_start TYPE string VALUE ``. + + INTERFACES zif_abapgit_gui_html_processor . + + METHODS constructor + IMPORTING + ii_asset_man TYPE REF TO zif_abapgit_gui_asset_manager. + + METHODS preserve_css + IMPORTING + !iv_css_url TYPE string . + + PROTECTED SECTION. + PRIVATE SECTION. + DATA mt_preserve_css TYPE string_table. + DATA mi_asset_man TYPE REF TO zif_abapgit_gui_asset_manager. + + METHODS patch_html + IMPORTING + iv_html TYPE string + EXPORTING + ev_html TYPE string + et_css_urls TYPE string_table + RAISING + zcx_abapgit_exception. + + METHODS is_preserved + IMPORTING + !iv_css_url TYPE string + RETURNING + VALUE(rv_yes) TYPE abap_bool. + + METHODS find_head_offset + IMPORTING + iv_html TYPE string + RETURNING + VALUE(rv_head_end) TYPE i + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_utils DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS is_renderable + IMPORTING + !io_obj TYPE REF TO object + RETURNING + VALUE(rv_yes) TYPE abap_bool . + CLASS-METHODS is_event_handler + IMPORTING + !io_obj TYPE REF TO object + RETURNING + VALUE(rv_yes) TYPE abap_bool . + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_html DEFINITION + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_html. + + CONSTANTS c_indent_size TYPE i VALUE 2 ##NO_TEXT. + + CLASS-METHODS class_constructor. + + CLASS-METHODS create + IMPORTING + !iv_initial_chunk TYPE any OPTIONAL + RETURNING + VALUE(ri_instance) TYPE REF TO zif_abapgit_html. + + CLASS-METHODS icon + IMPORTING + !iv_name TYPE string + !iv_hint TYPE string OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_onclick TYPE string OPTIONAL + RETURNING + VALUE(rv_str) TYPE string. + + CLASS-METHODS checkbox + IMPORTING + iv_id TYPE string OPTIONAL + iv_checked TYPE abap_bool OPTIONAL + RETURNING + VALUE(rv_html) TYPE string. + + CLASS-METHODS parse_data_attr + IMPORTING + iv_str TYPE string OPTIONAL + RETURNING + VALUE(rs_data_attr) TYPE zif_abapgit_html=>ty_data_attr. + + CLASS-METHODS set_debug_mode + IMPORTING + iv_mode TYPE abap_bool. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_max_indent TYPE i VALUE 200. + + TYPES: + BEGIN OF ty_indent_context, + no_indent_jscss TYPE abap_bool, + within_style TYPE abap_bool, + within_js TYPE abap_bool, + within_textarea TYPE abap_bool, + within_pre TYPE abap_bool, + indent TYPE i, + indent_str TYPE string, + END OF ty_indent_context. + + TYPES: + BEGIN OF ty_study_result, + style_open TYPE abap_bool, + style_close TYPE abap_bool, + script_open TYPE abap_bool, + script_close TYPE abap_bool, + textarea_open TYPE abap_bool, + textarea_close TYPE abap_bool, + pre_open TYPE abap_bool, + pre_close TYPE abap_bool, + tag_close TYPE abap_bool, + curly_close TYPE abap_bool, + openings TYPE i, + closings TYPE i, + singles TYPE i, + END OF ty_study_result. + + CLASS-DATA go_single_tags_re TYPE REF TO cl_abap_regex. + CLASS-DATA gv_spaces TYPE string. + CLASS-DATA gv_debug_mode TYPE abap_bool. + DATA mt_buffer TYPE string_table. + + METHODS indent_line + CHANGING + !cs_context TYPE ty_indent_context + !cv_line TYPE string. + + METHODS study_line + IMPORTING + !iv_line TYPE string + !is_context TYPE ty_indent_context + RETURNING + VALUE(rs_result) TYPE ty_study_result. + +ENDCLASS. +CLASS zcl_abapgit_html_parts DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS add_part + IMPORTING + !iv_collection TYPE string + !ii_part TYPE REF TO zif_abapgit_html . + METHODS get_parts + IMPORTING + !iv_collection TYPE string + RETURNING + VALUE(rt_parts) TYPE zif_abapgit_html=>ty_table_of . + METHODS get_collection_names + RETURNING + VALUE(rt_list) TYPE string_table . + METHODS get_collection_size + IMPORTING + !iv_collection TYPE string + RETURNING + VALUE(rv_size) TYPE i . + METHODS clear. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_named_collection, + name TYPE string, + pile TYPE zif_abapgit_html=>ty_table_of, + END OF ty_named_collection. + TYPES: + ty_named_collections TYPE STANDARD TABLE OF ty_named_collection WITH KEY name. + + DATA mt_part_collections TYPE ty_named_collections. + + METHODS get_collection + IMPORTING + !iv_collection TYPE string + !iv_create_if_missing TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rr_collection) TYPE REF TO ty_named_collection . + +ENDCLASS. +CLASS zcl_abapgit_html_viewer_gui DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_html_viewer . + + METHODS constructor + IMPORTING + !io_container TYPE REF TO cl_gui_container DEFAULT cl_gui_container=>screen0 + !iv_disable_query_table TYPE abap_bool DEFAULT abap_true . + PROTECTED SECTION. + + DATA mo_html_viewer TYPE REF TO cl_gui_html_viewer . + + METHODS on_event + FOR EVENT sapevent OF cl_gui_html_viewer + IMPORTING + !action + !frame + !getdata + !postdata + !query_table . + + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_ui_core_factory DEFINITION + CREATE PRIVATE + . + + PUBLIC SECTION. + + CLASS-METHODS get_html_viewer + IMPORTING + !io_container TYPE REF TO cl_gui_container DEFAULT cl_gui_container=>screen0 + !iv_disable_query_table TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ri_viewer) TYPE REF TO zif_abapgit_html_viewer . + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gi_html_viewer TYPE REF TO zif_abapgit_html_viewer . +ENDCLASS. +CLASS zcl_abapgit_flow_exit DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_flow_exit . + + CLASS-METHODS get_instance + RETURNING + VALUE(ri_exit) TYPE REF TO zif_abapgit_flow_exit. + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gi_global_exit TYPE REF TO zif_abapgit_flow_exit. + CLASS-DATA gi_exit TYPE REF TO zif_abapgit_flow_exit. +ENDCLASS. +CLASS zcl_abapgit_flow_git DEFINITION. + PUBLIC SECTION. +* various git related methods + + CLASS-METHODS find_changes_in_git + IMPORTING + iv_url TYPE string + io_dot TYPE REF TO zcl_abapgit_dot_abapgit + iv_package TYPE devclass + it_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt + EXPORTING + et_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt + CHANGING + ct_features TYPE zif_abapgit_flow_logic=>ty_features + RAISING + zcx_abapgit_exception. + + CLASS-METHODS find_up_to_date + IMPORTING + it_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt + it_objects TYPE zif_abapgit_definitions=>ty_objects_tt + CHANGING + ct_features TYPE zif_abapgit_flow_logic=>ty_features + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + + CLASS-METHODS map_files_to_objects + IMPORTING + it_files TYPE zif_abapgit_flow_logic=>ty_path_name_tt + io_dot TYPE REF TO zcl_abapgit_dot_abapgit + iv_package TYPE devclass + RETURNING + VALUE(rt_changed_objects) TYPE zif_abapgit_definitions=>ty_items_ts + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_flow_logic DEFINITION. + PUBLIC SECTION. + CLASS-METHODS get + RETURNING + VALUE(rs_information) TYPE zif_abapgit_flow_logic=>ty_information + RAISING + zcx_abapgit_exception. + + CLASS-METHODS consolidate + IMPORTING + ii_online TYPE REF TO zif_abapgit_repo_online + RETURNING + VALUE(rs_consolidate) TYPE zif_abapgit_flow_logic=>ty_consolidate + RAISING + zcx_abapgit_exception. + + TYPES ty_repos_tt TYPE STANDARD TABLE OF REF TO zif_abapgit_repo_online WITH DEFAULT KEY. + + CLASS-METHODS list_repos + IMPORTING + iv_favorites_only TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(rt_repos) TYPE ty_repos_tt + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: BEGIN OF ty_transport, + trkorr TYPE trkorr, + title TYPE string, + object TYPE e071-object, + obj_name TYPE e071-obj_name, + devclass TYPE tadir-devclass, + END OF ty_transport. + + TYPES ty_transports_tt TYPE STANDARD TABLE OF ty_transport WITH DEFAULT KEY. + + TYPES ty_trkorr_tt TYPE STANDARD TABLE OF trkorr WITH DEFAULT KEY. + + CLASS-METHODS consolidate_files + IMPORTING + ii_online TYPE REF TO zif_abapgit_repo_online + CHANGING + cs_information TYPE zif_abapgit_flow_logic=>ty_consolidate + RAISING + zcx_abapgit_exception. + + CLASS-METHODS check_files + IMPORTING + it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + it_features TYPE zif_abapgit_flow_logic=>ty_features + CHANGING + ct_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt + ct_missing_remote TYPE zif_abapgit_flow_logic=>ty_consolidate-missing_remote + RAISING + zcx_abapgit_exception. + + CLASS-METHODS build_repo_data + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(rs_data) TYPE zif_abapgit_flow_logic=>ty_feature-repo. + + CLASS-METHODS try_matching_transports + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + it_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt + it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + CHANGING + ct_features TYPE zif_abapgit_flow_logic=>ty_features + ct_transports TYPE ty_transports_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS errors_from_transports + IMPORTING + it_all_transports TYPE ty_transports_tt + CHANGING + cs_information TYPE zif_abapgit_flow_logic=>ty_information. + + CLASS-METHODS add_objects_and_files_from_tr + IMPORTING + iv_trkorr TYPE trkorr + it_transports TYPE ty_transports_tt + it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + it_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt + CHANGING + cs_feature TYPE zif_abapgit_flow_logic=>ty_feature + RAISING + zcx_abapgit_exception. + + CLASS-METHODS find_prs + IMPORTING + iv_url TYPE string + CHANGING + ct_features TYPE zif_abapgit_flow_logic=>ty_features + RAISING + zcx_abapgit_exception. + + CLASS-METHODS add_local_status + IMPORTING + it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + CHANGING + ct_features TYPE zif_abapgit_flow_logic=>ty_features + RAISING + zcx_abapgit_exception. + + CLASS-METHODS relevant_transports_via_devc + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + it_transports TYPE ty_transports_tt + RETURNING + VALUE(rt_transports) TYPE ty_trkorr_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS find_open_transports + RETURNING + VALUE(rt_transports) TYPE ty_transports_tt + RAISING + zcx_abapgit_exception. + + CLASS-METHODS serialize_filtered + IMPORTING + it_relevant_transports TYPE ty_trkorr_tt + ii_repo TYPE REF TO zif_abapgit_repo + it_all_transports TYPE ty_transports_tt + it_features TYPE zif_abapgit_flow_logic=>ty_features + RETURNING + VALUE(rt_local) TYPE zif_abapgit_definitions=>ty_files_item_tt + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_flow_page_utils DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS render_table + IMPORTING + !it_files TYPE zif_abapgit_flow_logic=>ty_path_name_tt + !it_transport_duplicates TYPE zif_abapgit_flow_logic=>ty_transport_duplicates_tt OPTIONAL + !is_user_settings TYPE zif_abapgit_persist_user=>ty_flow_settings OPTIONAL + !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS call_diff + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_exception_viewer DEFINITION + CREATE PUBLIC. + PUBLIC SECTION. + METHODS: + constructor + IMPORTING + ix_error TYPE REF TO zcx_abapgit_exception, + + goto_source + RAISING + zcx_abapgit_exception, + + goto_message + RAISING + zcx_abapgit_exception, + + show_callstack + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA: + mx_error TYPE REF TO zcx_abapgit_exception, + mt_callstack TYPE abap_callstack. + + METHODS: + build_top_of_list + IMPORTING + is_top_of_stack TYPE abap_callstack_line + RETURNING + VALUE(ro_form) TYPE REF TO cl_salv_form_element, + + add_row + IMPORTING + io_grid TYPE REF TO cl_salv_form_layout_grid + iv_col_1 TYPE csequence + iv_col_2 TYPE csequence, + + on_double_click FOR EVENT double_click OF cl_salv_events_table + IMPORTING + row column, + + set_text + IMPORTING + io_columns TYPE REF TO cl_salv_columns_table + iv_column TYPE lvc_fname + iv_text TYPE string + RAISING + cx_static_check, + + goto_source_code + IMPORTING + is_callstack TYPE abap_callstack_line + RAISING + zcx_abapgit_exception, + + extract_classname + IMPORTING + iv_mainprogram TYPE abap_callstack_line-mainprogram + RETURNING + VALUE(rv_classname) TYPE tadir-obj_name, + + get_top_of_callstack + RETURNING + VALUE(rs_top_of_callstack) TYPE abap_callstack_line + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_buttons DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS new_online + RETURNING VALUE(rv_html_string) TYPE string. + + CLASS-METHODS flow + RETURNING VALUE(rv_html_string) TYPE string. + + CLASS-METHODS new_offline + RETURNING VALUE(rv_html_string) TYPE string. + + CLASS-METHODS advanced + RETURNING VALUE(rv_html_string) TYPE string. + + CLASS-METHODS help + RETURNING VALUE(rv_html_string) TYPE string. + + CLASS-METHODS repo_list + RETURNING VALUE(rv_html_string) TYPE string. + + CLASS-METHODS settings + RETURNING VALUE(rv_html_string) TYPE string. + + CLASS-METHODS experimental + RETURNING VALUE(rv_html_string) TYPE string. + + CLASS-METHODS refresh + RETURNING VALUE(rv_html_string) TYPE string. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_gui_chunk_lib DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_event_signature, + method TYPE string, + name TYPE string, + END OF ty_event_signature . + + TYPES: + BEGIN OF ty_col_spec, + tech_name TYPE string, + display_name TYPE string, + css_class TYPE string, + add_tz TYPE abap_bool, + title TYPE string, + allow_order_by TYPE abap_bool, + END OF ty_col_spec, + ty_col_spec_tt TYPE STANDARD TABLE OF ty_col_spec WITH NON-UNIQUE KEY tech_name. + + CLASS-METHODS class_constructor . + CLASS-METHODS render_error + IMPORTING + !ix_error TYPE REF TO zcx_abapgit_exception OPTIONAL + !iv_error TYPE string OPTIONAL + !iv_extra_style TYPE string OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS render_success + IMPORTING + iv_message TYPE string + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS render_repo_top + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !iv_show_package TYPE abap_bool DEFAULT abap_true + !iv_show_branch TYPE abap_bool DEFAULT abap_true + !iv_show_commit TYPE abap_bool DEFAULT abap_true + !iv_show_edit TYPE abap_bool DEFAULT abap_false + !iv_interactive_branch TYPE abap_bool DEFAULT abap_false + !iv_interactive_favorite TYPE abap_bool DEFAULT abap_true + !io_news TYPE REF TO zcl_abapgit_repo_news OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_item_state + IMPORTING + !iv_lstate TYPE char1 + !iv_rstate TYPE char1 + RETURNING + VALUE(rv_html) TYPE string . + CLASS-METHODS render_js_error_banner + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_news + IMPORTING + !io_news TYPE REF TO zcl_abapgit_repo_news + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_error_message_box + IMPORTING + !ix_error TYPE REF TO zcx_abapgit_exception + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS render_table_header + IMPORTING + !it_col_spec TYPE ty_col_spec_tt + !iv_order_by TYPE string + !iv_order_descending TYPE abap_bool + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS render_table_footer + IMPORTING + !iv_message TYPE string + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS render_warning_banner + IMPORTING + !iv_text TYPE string + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS render_infopanel + IMPORTING + !iv_div_id TYPE string + !iv_title TYPE string + !iv_hide TYPE abap_bool DEFAULT abap_true + !iv_hint TYPE string OPTIONAL + !iv_scrollable TYPE abap_bool DEFAULT abap_true + !io_content TYPE REF TO zif_abapgit_html + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_event_as_form + IMPORTING + !is_event TYPE ty_event_signature + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS render_repo_palette + IMPORTING + iv_action TYPE string + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_branch_name + IMPORTING + !iv_branch TYPE string OPTIONAL + !iv_repo_key TYPE zif_abapgit_persistence=>ty_value OPTIONAL + !ii_repo_online TYPE REF TO zif_abapgit_repo_online OPTIONAL + !iv_interactive TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_repo_url + IMPORTING + iv_url TYPE zif_abapgit_persistence=>ty_repo-url + iv_render_remote_edit_for_key TYPE zif_abapgit_persistence=>ty_repo-key OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_package_name + IMPORTING + !iv_package TYPE devclass + !iv_interactive TYPE abap_bool DEFAULT abap_true + !iv_suppress_title TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_user_name + IMPORTING + !iv_username TYPE syuname + !iv_interactive TYPE abap_bool DEFAULT abap_true + !iv_icon_only TYPE abap_bool DEFAULT abap_false + !iv_suppress_title TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_transport + IMPORTING + !iv_transport TYPE trkorr + !iv_obj_type TYPE zif_abapgit_definitions=>ty_repo_item-obj_type OPTIONAL + !iv_obj_name TYPE zif_abapgit_definitions=>ty_repo_item-obj_name OPTIONAL + !iv_interactive TYPE abap_bool DEFAULT abap_true + !iv_icon_only TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + CLASS-METHODS render_sci_result + IMPORTING + ii_html TYPE REF TO zif_abapgit_html + iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result. + + CLASS-METHODS render_path + IMPORTING + !iv_path TYPE string + !iv_interactive TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + + CLASS-METHODS render_timestamp + IMPORTING + iv_timestamp TYPE timestampl + RETURNING + VALUE(rv_rendered) TYPE string. + + CLASS-METHODS render_text_input + IMPORTING + iv_name TYPE string + iv_label TYPE string + iv_value TYPE string OPTIONAL + iv_max_length TYPE string OPTIONAL + iv_autofocus TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html. + + CLASS-METHODS render_label_list + IMPORTING + it_labels TYPE string_table + io_label_colors TYPE REF TO zcl_abapgit_string_map + iv_clickable_action TYPE string OPTIONAL + iv_unlisted TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rv_html) TYPE string. + + CLASS-METHODS render_help_hint + IMPORTING + iv_text_to_wrap TYPE string + iv_add_class TYPE string OPTIONAL + RETURNING + VALUE(rv_html) TYPE string. + + CLASS-METHODS get_item_icon + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + RETURNING + VALUE(rv_html) TYPE string. + + CLASS-METHODS get_item_link + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item OPTIONAL + !iv_obj_type TYPE zif_abapgit_definitions=>ty_repo_item-obj_type OPTIONAL + !iv_obj_name TYPE zif_abapgit_definitions=>ty_repo_item-obj_name OPTIONAL + PREFERRED PARAMETER is_item + RETURNING + VALUE(rv_html) TYPE string. + + PROTECTED SECTION. + + CLASS-METHODS render_repo_top_commit_hash + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + + CLASS-DATA gv_time_zone TYPE timezone . + + CLASS-METHODS get_t100_text + IMPORTING + !iv_msgid TYPE scx_t100key-msgid + !iv_msgno TYPE scx_t100key-msgno + RETURNING + VALUE(rv_text) TYPE string . + CLASS-METHODS normalize_program_name + IMPORTING + !iv_program_name TYPE sy-repid + RETURNING + VALUE(rv_normalized_program_name) TYPE string . + + CLASS-METHODS shorten_repo_url + IMPORTING + iv_full_url TYPE string + iv_max_length TYPE i DEFAULT 60 + RETURNING + VALUE(rv_shortened) TYPE string. + +ENDCLASS. +CLASS zcl_abapgit_gui_component DEFINITION + ABSTRACT + CREATE PUBLIC . + + PUBLIC SECTION. + + CONSTANTS: + BEGIN OF c_html_parts, + scripts TYPE string VALUE 'scripts', + hidden_forms TYPE string VALUE 'hidden_forms', + END OF c_html_parts. + + PROTECTED SECTION. + + METHODS register_deferred_script + IMPORTING + ii_part TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + METHODS gui_services + RETURNING + VALUE(ri_gui_services) TYPE REF TO zif_abapgit_gui_services + RAISING + zcx_abapgit_exception. + METHODS register_handlers + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + DATA mi_gui_services TYPE REF TO zif_abapgit_gui_services. + + METHODS register_event_handler + IMPORTING + ii_event_handler TYPE REF TO zif_abapgit_gui_event_handler OPTIONAL + RAISING + zcx_abapgit_exception. + METHODS register_hotkeys + IMPORTING + ii_hotkey_provider TYPE REF TO zif_abapgit_gui_hotkeys OPTIONAL + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_template DEFINITION + FINAL + INHERITING FROM zcl_abapgit_gui_component + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_page_title, + zif_abapgit_gui_event_handler, + zif_abapgit_gui_hotkeys, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable, + " TODO: remove table interface if not used on the page + zif_abapgit_html_table. + + CLASS-METHODS create + " TODO: page parameters, e.g. ref to repo +* IMPORTING +* ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor +* IMPORTING +* ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_action, + " TODO: List of in-page actions + refresh TYPE string VALUE 'refresh', + END OF c_action. + + CONSTANTS c_title TYPE string VALUE 'Page Template'. " TODO: define page title + +ENDCLASS. +CLASS zcl_abapgit_gui_page_flow DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + INTERFACES zif_abapgit_gui_menu_provider . + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS constructor + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_action, + refresh TYPE string VALUE 'refresh', + consolidate TYPE string VALUE 'consolidate', + pull TYPE string VALUE 'pull', + stage_and_commit TYPE string VALUE 'stage_and_commit', + only_my_transports TYPE string VALUE 'only_my_transports', + hide_full_matches TYPE string VALUE 'hide_full_matches', + hide_matching_files TYPE string VALUE 'hide_matching_files', + hide_conflicts TYPE string VALUE 'hide_conflicts', + END OF c_action . + DATA ms_information TYPE zif_abapgit_flow_logic=>ty_information . + DATA ms_user_settings TYPE zif_abapgit_persist_user=>ty_flow_settings. + + METHODS refresh + RAISING + zcx_abapgit_exception . + METHODS set_branch + IMPORTING + !iv_branch TYPE string + !iv_key TYPE zif_abapgit_persistence=>ty_value + RAISING + zcx_abapgit_exception . + + METHODS render_toolbar + IMPORTING + !iv_index TYPE i + !is_feature TYPE zif_abapgit_flow_logic=>ty_feature + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + + METHODS render_info + IMPORTING + !is_feature TYPE zif_abapgit_flow_logic=>ty_feature + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + + METHODS call_stage_commit + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception. + + METHODS call_pull + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception. + + METHODS call_consolidate + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception. + + METHODS render_user_settings + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + + METHODS skip_show + IMPORTING + is_feature TYPE zif_abapgit_flow_logic=>ty_feature + RETURNING + VALUE(rv_skip) TYPE abap_bool + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_gui_page_flowcons DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + INTERFACES zif_abapgit_gui_menu_provider . + + CLASS-METHODS create + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo_online + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + + METHODS constructor + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo_online + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_action, + refresh TYPE string VALUE 'refresh', + stage_missing_remote TYPE string VALUE 'stage_missing_remote', + stage_only_remote TYPE string VALUE 'stage_only_remote', + END OF c_action . + + DATA mo_repo TYPE REF TO zif_abapgit_repo_online. + DATA ms_consolidate TYPE zif_abapgit_flow_logic=>ty_consolidate. + + METHODS stage_missing_remote + RAISING zcx_abapgit_exception. + + METHODS stage_only_remote + RAISING zcx_abapgit_exception. + + METHODS push + IMPORTING + io_stage TYPE REF TO zcl_abapgit_stage + iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1 + iv_branch_name TYPE string + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_gui_in_page_modal DEFINITION + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + !ii_child TYPE REF TO zif_abapgit_gui_renderable + !iv_width TYPE i OPTIONAL + !iv_height TYPE i OPTIONAL + RETURNING + VALUE(ro_wrap) TYPE REF TO zcl_abapgit_gui_in_page_modal + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !ii_child TYPE REF TO zif_abapgit_gui_renderable + !iv_width TYPE i OPTIONAL + !iv_height TYPE i OPTIONAL. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mi_child TYPE REF TO zif_abapgit_gui_renderable. + + DATA: + BEGIN OF ms_attrs, + width TYPE i, + height TYPE i, + END OF ms_attrs. + +ENDCLASS. +CLASS zcl_abapgit_gui_menus DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS advanced + RETURNING + VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. + + CLASS-METHODS help + RETURNING + VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. + + CLASS-METHODS back + RETURNING + VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. + + CLASS-METHODS settings + IMPORTING + !iv_act TYPE string + RETURNING + VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. + + CLASS-METHODS repo_settings + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !iv_act TYPE string + RETURNING + VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. + + CLASS-METHODS experimental + IMPORTING + io_menu TYPE REF TO zcl_abapgit_html_toolbar. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_gui_page DEFINITION ABSTRACT + INHERITING FROM zcl_abapgit_gui_component + CREATE PUBLIC. + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_gui_modal, + zif_abapgit_gui_renderable, + zif_abapgit_gui_event_handler, + zif_abapgit_gui_error_handler. + + TYPES: + BEGIN OF ty_control, + page_layout TYPE string, + page_title TYPE string, + page_menu TYPE REF TO zcl_abapgit_html_toolbar, + page_menu_provider TYPE REF TO zif_abapgit_gui_menu_provider, + page_title_provider TYPE REF TO zif_abapgit_gui_page_title, + extra_css_url TYPE string, + extra_js_url TYPE string, + show_as_modal TYPE abap_bool, + END OF ty_control . + + METHODS constructor RAISING zcx_abapgit_exception. + + CONSTANTS: + BEGIN OF c_page_layout, + centered TYPE string VALUE `centered`, + full_width TYPE string VALUE `full_width`, + END OF c_page_layout. + + PROTECTED SECTION. + + DATA ms_control TYPE ty_control . + + METHODS render_content " TODO refactor, render child directly + ABSTRACT + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + PRIVATE SECTION. + + DATA mo_settings TYPE REF TO zcl_abapgit_settings . + DATA mx_error TYPE REF TO zcx_abapgit_exception . + DATA mo_exception_viewer TYPE REF TO zcl_abapgit_exception_viewer . + + METHODS render_deferred_parts + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !iv_part_category TYPE string + RAISING + zcx_abapgit_exception . + METHODS html_head + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS header_stylesheet_links + IMPORTING + ii_html TYPE REF TO zif_abapgit_html . + METHODS header_script_links + IMPORTING + ii_html TYPE REF TO zif_abapgit_html . + METHODS title + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS footer + IMPORTING + !iv_time TYPE string + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_link_hints + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_browser_control_warning + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_command_palettes + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_hotkey_overview + RETURNING + VALUE(ro_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_error_message_box + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS scripts + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS get_version_details + RETURNING + VALUE(rv_version) TYPE string. + METHODS is_edge_control_warning_needed + RETURNING + VALUE(rv_result) TYPE abap_bool. +ENDCLASS. +CLASS zcl_abapgit_gui_page_hoc DEFINITION + INHERITING FROM zcl_abapgit_gui_page + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + CLASS-METHODS create + IMPORTING + !ii_child_component TYPE REF TO zif_abapgit_gui_renderable + !iv_page_title TYPE string OPTIONAL + !iv_page_layout TYPE string DEFAULT zcl_abapgit_gui_page=>c_page_layout-centered + !io_page_menu TYPE REF TO zcl_abapgit_html_toolbar OPTIONAL + !ii_page_menu_provider TYPE REF TO zif_abapgit_gui_menu_provider OPTIONAL + !ii_page_title_provider TYPE REF TO zif_abapgit_gui_page_title OPTIONAL + !iv_extra_css_url TYPE string OPTIONAL + !iv_extra_js_url TYPE string OPTIONAL + !iv_show_as_modal TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_page_wrap) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + METHODS get_child + RETURNING + VALUE(ri_child) TYPE REF TO zif_abapgit_gui_renderable. + METHODS constructor + IMPORTING + !ii_child_component TYPE REF TO zif_abapgit_gui_renderable + !is_control TYPE zcl_abapgit_gui_page=>ty_control + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + + METHODS render_content + REDEFINITION. + PRIVATE SECTION. + + DATA mi_child TYPE REF TO zif_abapgit_gui_renderable . + + METHODS detect_modal + RETURNING + VALUE(rv_is_modal) TYPE abap_bool. + + METHODS detect_menu_provider + RETURNING + VALUE(ri_ref) TYPE REF TO zif_abapgit_gui_menu_provider. + + METHODS detect_title_provider + RETURNING + VALUE(ri_ref) TYPE REF TO zif_abapgit_gui_page_title. + +ENDCLASS. +CLASS zcl_abapgit_gui_picklist DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + INTERFACES zif_abapgit_gui_page_title. + + METHODS constructor + IMPORTING + !it_list TYPE STANDARD TABLE + !iv_id TYPE string OPTIONAL + !iv_in_page TYPE abap_bool DEFAULT abap_false + !iv_title TYPE string DEFAULT 'Choose from list' + !iv_attr_name TYPE abap_compname OPTIONAL + !ii_item_renderer TYPE REF TO zif_abapgit_gui_render_item OPTIONAL + RAISING + zcx_abapgit_exception. + METHODS get_result_idx + RETURNING + VALUE(rv_index) TYPE i. + METHODS get_result_item + CHANGING + !cs_selected TYPE any. + METHODS was_cancelled + RETURNING + VALUE(rv_yes) TYPE abap_bool. + METHODS is_fulfilled + RETURNING + VALUE(rv_yes) TYPE abap_bool. + METHODS id + RETURNING + VALUE(rv_id) TYPE string. + METHODS is_in_page + RETURNING + VALUE(rv_yes) TYPE abap_bool. + METHODS set_id + IMPORTING + iv_id TYPE string + RETURNING + VALUE(ro_me) TYPE REF TO zcl_abapgit_gui_picklist. + METHODS set_in_page + IMPORTING + iv_in_page TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ro_me) TYPE REF TO zcl_abapgit_gui_picklist. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_event, + back TYPE string VALUE 'back', + choose TYPE string VALUE 'choose', + END OF c_event. + + CONSTANTS c_radio_name TYPE string VALUE 'radio'. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + DATA mr_list TYPE REF TO data. + DATA mv_selected TYPE i. + DATA mv_cancelled TYPE abap_bool. + DATA mv_fulfilled TYPE abap_bool. + DATA mv_attr_name TYPE abap_compname. + DATA mi_item_renderer TYPE REF TO zif_abapgit_gui_render_item. + DATA mv_in_page TYPE abap_bool. + DATA mv_id TYPE string. + DATA mv_title TYPE string. + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form + RAISING + zcx_abapgit_exception. + METHODS return_state + RETURNING + VALUE(rv_state) TYPE zif_abapgit_gui_event_handler=>ty_handling_result-state. + +ENDCLASS. +CLASS zcl_abapgit_html_action_utils DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS jump_encode + IMPORTING + !iv_obj_type TYPE tadir-object + !iv_obj_name TYPE tadir-obj_name + !iv_filename TYPE string OPTIONAL + RETURNING + VALUE(rv_string) TYPE string . + CLASS-METHODS dir_encode + IMPORTING + !iv_path TYPE string + RETURNING + VALUE(rv_string) TYPE string . + CLASS-METHODS file_encode + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !ig_file TYPE any + !iv_extra TYPE clike OPTIONAL + RETURNING + VALUE(rv_string) TYPE string . + CLASS-METHODS obj_encode + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !ig_object TYPE any + RETURNING + VALUE(rv_string) TYPE string . + CLASS-METHODS dbkey_encode + IMPORTING + !is_key TYPE zif_abapgit_persistence=>ty_content + RETURNING + VALUE(rv_string) TYPE string . + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: BEGIN OF ty_name_value, + name TYPE string, + value TYPE string, + END OF ty_name_value. + TYPES ty_name_value_tt TYPE STANDARD TABLE OF ty_name_value WITH DEFAULT KEY. + + CLASS-METHODS add_field + IMPORTING + !iv_name TYPE string + !ig_field TYPE any + CHANGING + !ct_field TYPE ty_name_value_tt . + + CLASS-METHODS fields_to_string + IMPORTING + !it_fields TYPE ty_name_value_tt + RETURNING + VALUE(rv_string) TYPE string. +ENDCLASS. +CLASS zcl_abapgit_html_form DEFINITION + FINAL + INHERITING FROM zcl_abapgit_gui_component + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_html_form . + INTERFACES zif_abapgit_gui_hotkeys . + + CLASS-METHODS create + IMPORTING + !iv_form_id TYPE csequence OPTIONAL + !iv_help_page TYPE csequence OPTIONAL + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form . + METHODS render + IMPORTING + !iv_form_class TYPE csequence DEFAULT 'dialog-form' + !io_values TYPE REF TO zcl_abapgit_string_map + !io_validation_log TYPE REF TO zcl_abapgit_string_map OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS command + IMPORTING + !iv_label TYPE csequence + !iv_action TYPE csequence + !iv_cmd_type TYPE i DEFAULT zif_abapgit_html_form=>c_cmd_type-input + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS text + IMPORTING + !iv_label TYPE csequence + !iv_name TYPE csequence + !iv_hint TYPE csequence OPTIONAL + !iv_required TYPE abap_bool DEFAULT abap_false + !iv_upper_case TYPE abap_bool DEFAULT abap_false + !iv_readonly TYPE abap_bool DEFAULT abap_false + !iv_password TYPE abap_bool DEFAULT abap_false + !iv_condense TYPE abap_bool OPTIONAL + !iv_placeholder TYPE csequence OPTIONAL + !iv_side_action TYPE csequence OPTIONAL + !iv_min TYPE i DEFAULT cl_abap_math=>min_int4 + !iv_max TYPE i DEFAULT cl_abap_math=>max_int4 + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS textarea + IMPORTING + !iv_label TYPE csequence + !iv_name TYPE csequence + !iv_hint TYPE csequence OPTIONAL + !iv_required TYPE abap_bool DEFAULT abap_false + !iv_readonly TYPE abap_bool DEFAULT abap_false + !iv_placeholder TYPE csequence OPTIONAL + !iv_rows TYPE i OPTIONAL + !iv_cols TYPE i OPTIONAL + !iv_upper_case TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS number + IMPORTING + !iv_label TYPE csequence + !iv_name TYPE csequence + !iv_hint TYPE csequence OPTIONAL + !iv_required TYPE abap_bool DEFAULT abap_false + !iv_readonly TYPE abap_bool DEFAULT abap_false + !iv_min TYPE i DEFAULT cl_abap_math=>min_int4 + !iv_max TYPE i DEFAULT cl_abap_math=>max_int4 + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS checkbox + IMPORTING + !iv_label TYPE csequence + !iv_name TYPE csequence + !iv_hint TYPE csequence OPTIONAL + !iv_readonly TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS radio + IMPORTING + !iv_label TYPE csequence + !iv_name TYPE csequence + !iv_default_value TYPE csequence OPTIONAL + !iv_hint TYPE csequence OPTIONAL + !iv_condense TYPE abap_bool DEFAULT abap_false + !iv_action TYPE csequence OPTIONAL + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS option + IMPORTING + !iv_label TYPE csequence + !iv_value TYPE csequence + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS table + IMPORTING + !iv_label TYPE csequence + !iv_name TYPE csequence + !iv_hint TYPE csequence OPTIONAL + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS column + IMPORTING + !iv_label TYPE csequence + !iv_width TYPE csequence OPTIONAL + !iv_readonly TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS start_group + IMPORTING + !iv_label TYPE csequence + !iv_name TYPE csequence + !iv_hint TYPE csequence OPTIONAL + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS hidden + IMPORTING + !iv_name TYPE csequence + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . + METHODS get_fields + RETURNING + VALUE(rt_fields) TYPE zif_abapgit_html_form=>ty_fields . + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_attr, + value TYPE string, + error TYPE string, + hint TYPE string, + readonly TYPE string, + placeholder TYPE string, + required TYPE string, + autofocus TYPE string, + END OF ty_attr . + + DATA mv_webgui TYPE abap_bool. + DATA mt_fields TYPE zif_abapgit_html_form=>ty_fields . + DATA: + mt_commands TYPE STANDARD TABLE OF zif_abapgit_html_form=>ty_command . + DATA mv_form_id TYPE string . + DATA mv_help_page TYPE string . + + METHODS render_field + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !io_values TYPE REF TO zcl_abapgit_string_map + !io_validation_log TYPE REF TO zcl_abapgit_string_map + !is_field TYPE zif_abapgit_html_form=>ty_field + !iv_autofocus TYPE abap_bool . + METHODS render_field_text + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_field TYPE zif_abapgit_html_form=>ty_field + !is_attr TYPE ty_attr . + METHODS render_field_textarea + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_field TYPE zif_abapgit_html_form=>ty_field + !is_attr TYPE ty_attr . + METHODS render_field_checkbox + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_field TYPE zif_abapgit_html_form=>ty_field + !is_attr TYPE ty_attr . + METHODS render_field_radio + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_field TYPE zif_abapgit_html_form=>ty_field + !is_attr TYPE ty_attr . + METHODS render_field_table + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_field TYPE zif_abapgit_html_form=>ty_field + !is_attr TYPE ty_attr + !io_values TYPE REF TO zcl_abapgit_string_map . + METHODS render_command + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_cmd TYPE zif_abapgit_html_form=>ty_command . + METHODS render_command_link + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_cmd TYPE zif_abapgit_html_form=>ty_command . + METHODS render_field_hidden + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_field TYPE zif_abapgit_html_form=>ty_field + !is_attr TYPE ty_attr . +ENDCLASS. +CLASS zcl_abapgit_html_form_utils DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS create + IMPORTING + !io_form TYPE REF TO zcl_abapgit_html_form + RETURNING + VALUE(ro_form_util) TYPE REF TO zcl_abapgit_html_form_utils . + CLASS-METHODS is_dirty + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + !io_compare_with TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(rv_dirty) TYPE abap_bool . + + METHODS constructor + IMPORTING + !io_form TYPE REF TO zcl_abapgit_html_form . + METHODS normalize + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + METHODS validate + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + METHODS is_empty + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(rv_empty) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS set_data + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map . + METHODS exit + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + !io_compare_with TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(rv_state) TYPE i + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form . + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . + +ENDCLASS. +CLASS zcl_abapgit_html_table DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS create + IMPORTING + !ii_renderer TYPE REF TO zif_abapgit_html_table OPTIONAL " Can be passed to renderer + !is_initial_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state OPTIONAL + PREFERRED PARAMETER ii_renderer + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_html_table . + " maybe also th css_class + METHODS define_column + IMPORTING + !iv_column_id TYPE string + !iv_column_title TYPE string OPTIONAL + !iv_from_field TYPE abap_compname OPTIONAL + !iv_sortable TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_table . + METHODS define_column_group + IMPORTING + !iv_group_id TYPE string OPTIONAL " not mandatory, but can be used for CSS (TODO data-gid) + !iv_group_title TYPE string OPTIONAL " can be empty ! + PREFERRED PARAMETER iv_group_title + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_table + RAISING + zcx_abapgit_exception . + " Maybe also data_provider + " TODO record Limiter + METHODS render + IMPORTING + !ii_renderer TYPE REF TO zif_abapgit_html_table OPTIONAL + !it_data TYPE ANY TABLE + !iv_id TYPE csequence OPTIONAL + !iv_css_class TYPE csequence OPTIONAL + !iv_with_cids TYPE abap_bool DEFAULT abap_false + !is_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state OPTIONAL + !iv_wrap_in_div TYPE string OPTIONAL " div class name + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + + " Sorting utils + CLASS-METHODS detect_sorting_request + IMPORTING + iv_event TYPE string + RETURNING + VALUE(rs_sorting_request) TYPE zif_abapgit_html_table=>ty_sorting_state. + METHODS process_sorting_request + IMPORTING + iv_event TYPE string + RETURNING + VALUE(rv_processed) TYPE abap_bool. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_sort_by_event_prefix TYPE string VALUE `sort_by:`. + CONSTANTS c_sort_by_event_regex TYPE string VALUE `^sort_by:\w+:(asc|dsc)$`. + + TYPES: + BEGIN OF ty_column, + column_id TYPE string, + column_title TYPE string, + from_field TYPE abap_compname, + sortable TYPE abap_bool, + is_group TYPE abap_bool, + group_span TYPE i, + END OF ty_column, + ty_columns TYPE STANDARD TABLE OF ty_column WITH KEY column_id. + + DATA mi_renderer TYPE REF TO zif_abapgit_html_table. + DATA mt_columns TYPE ty_columns. + DATA mi_html TYPE REF TO zif_abapgit_html. + DATA mv_with_cids TYPE abap_bool. + DATA mv_table_id TYPE string. + DATA ms_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state. + DATA mr_last_grp TYPE REF TO ty_column. + + " potentially receive from outside + DATA mv_sort_span_class TYPE string VALUE `sort-arrow`. + DATA mv_sort_active_class TYPE string VALUE `sort-active`. + + METHODS render_thead + RAISING + zcx_abapgit_exception . + + METHODS render_tbody + IMPORTING + it_data TYPE ANY TABLE + RAISING + zcx_abapgit_exception . + + METHODS render_row + IMPORTING + iv_row_index TYPE i + is_row TYPE any + RAISING + zcx_abapgit_exception . + + METHODS render_column_title + IMPORTING + is_col TYPE ty_column + RETURNING + VALUE(rv_text) TYPE string + RAISING + zcx_abapgit_exception . + + CLASS-METHODS cid_attr + IMPORTING + iv_column_id TYPE string + RETURNING + VALUE(rs_data_attr) TYPE zif_abapgit_html=>ty_data_attr. + + CLASS-METHODS gid_attr + IMPORTING + iv_column_id TYPE string + RETURNING + VALUE(rs_data_attr) TYPE zif_abapgit_html=>ty_data_attr. + + METHODS apply_sorting + CHANGING + ct_data TYPE STANDARD TABLE. + +ENDCLASS. +CLASS zcl_abapgit_html_toolbar DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS create + IMPORTING + !iv_id TYPE string OPTIONAL + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_html_toolbar. + METHODS constructor + IMPORTING + !iv_id TYPE string OPTIONAL . + METHODS add + IMPORTING + !iv_txt TYPE string + !io_sub TYPE REF TO zcl_abapgit_html_toolbar OPTIONAL + !iv_typ TYPE c DEFAULT zif_abapgit_html=>c_action_type-sapevent + !iv_act TYPE string OPTIONAL + !iv_ico TYPE string OPTIONAL + !iv_cur TYPE abap_bool OPTIONAL + !iv_opt TYPE c OPTIONAL + !iv_chk TYPE abap_bool DEFAULT abap_undefined + !iv_aux TYPE string OPTIONAL + !iv_id TYPE string OPTIONAL + !iv_title TYPE string OPTIONAL + !iv_class TYPE string OPTIONAL + !iv_hotkey TYPE string OPTIONAL + !iv_li_class TYPE string OPTIONAL + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_toolbar . + METHODS count_items + RETURNING + VALUE(rv_count) TYPE i . + METHODS render + IMPORTING + !iv_right TYPE abap_bool OPTIONAL + !iv_sort TYPE abap_bool OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_as_droplist + IMPORTING + !iv_label TYPE string + !iv_right TYPE abap_bool OPTIONAL + !iv_sort TYPE abap_bool OPTIONAL + !iv_corner TYPE abap_bool OPTIONAL + !iv_action TYPE string OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS get_hotkeys + IMPORTING + iv_component_name TYPE string OPTIONAL + RETURNING + VALUE(rt_hotkeys) TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_item, + txt TYPE string, + act TYPE string, + ico TYPE string, + sub TYPE REF TO zcl_abapgit_html_toolbar, + opt TYPE c LENGTH 1, + typ TYPE c LENGTH 1, + cur TYPE abap_bool, + chk TYPE abap_bool, + aux TYPE string, + id TYPE string, + title TYPE string, + class TYPE string, + li_class TYPE string, + hotkey TYPE string, + END OF ty_item . + TYPES: + ty_items TYPE STANDARD TABLE OF ty_item . + + DATA mt_items TYPE ty_items . + DATA mv_id TYPE string . + + METHODS render_items + IMPORTING + !iv_sort TYPE abap_bool OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . +ENDCLASS. +CLASS zcl_abapgit_log_viewer DEFINITION + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + CLASS-METHODS show_log + IMPORTING + !ii_log TYPE REF TO zif_abapgit_log . + CLASS-METHODS to_html + IMPORTING + !ii_log TYPE REF TO zif_abapgit_log + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS write_log + IMPORTING + !ii_log TYPE REF TO zif_abapgit_log . + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_log_out, + type TYPE icon_d, + msg TYPE string, + obj_type TYPE trobjtype, + obj_name TYPE sobj_name, + exception TYPE REF TO cx_root, + longtext TYPE icon_d, + t100 TYPE icon_d, + source TYPE icon_d, + callstack TYPE icon_d, + cell_type TYPE salv_t_int4_column, + id TYPE sy-msgid, + number TYPE sy-msgno, + END OF ty_log_out. + TYPES: + ty_log_outs TYPE STANDARD TABLE OF ty_log_out + WITH NON-UNIQUE DEFAULT KEY. + + CLASS-METHODS: + prepare_log_for_display + IMPORTING + ii_log TYPE REF TO zif_abapgit_log + RETURNING + VALUE(rt_log_out) TYPE ty_log_outs, + + show_longtext + IMPORTING + is_log TYPE ty_log_out + RAISING + zcx_abapgit_exception, + + goto_source + IMPORTING + is_log TYPE ty_log_out + RAISING + zcx_abapgit_exception, + + goto_callstack + IMPORTING + is_log TYPE ty_log_out + RAISING + zcx_abapgit_exception, + + goto_t100_message + IMPORTING + is_log TYPE ty_log_out + RAISING + zcx_abapgit_exception, + + on_link_click FOR EVENT link_click OF cl_salv_events_table + IMPORTING row column, + + dispatch + IMPORTING + is_log TYPE ty_log_out + iv_column TYPE salv_de_column + RAISING + zcx_abapgit_exception, + + calculate_cell_type, + + get_exception_viewer + IMPORTING + is_log TYPE ty_log_out + RETURNING + VALUE(ro_exception_viewer) TYPE REF TO zcl_abapgit_exception_viewer. + + CLASS-DATA: + gt_log TYPE ty_log_outs. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_codi_base DEFINITION + INHERITING FROM zcl_abapgit_gui_component. + + PUBLIC SECTION. + INTERFACES zif_abapgit_html_table. + + PROTECTED SECTION. + + CONSTANTS: + BEGIN OF c_actions, + rerun TYPE string VALUE 'rerun', + stage TYPE string VALUE 'stage', + commit TYPE string VALUE 'commit', + filter_kind TYPE string VALUE 'filter_kind', + apply_filter TYPE string VALUE 'apply_filter', + END OF c_actions . + + DATA mi_repo TYPE REF TO zif_abapgit_repo. + DATA mt_result TYPE zif_abapgit_code_inspector=>ty_results. + DATA mv_summary TYPE string. + + METHODS on_event + IMPORTING + ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception. + + METHODS render_ci_report + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !iv_variant TYPE sci_chkv + !iv_success_msg TYPE string + RAISING + zcx_abapgit_exception. + METHODS render_head + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !iv_variant TYPE sci_chkv + !iv_summary TYPE string. + METHODS render_detail + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !it_result TYPE zif_abapgit_code_inspector=>ty_results + RAISING + zcx_abapgit_exception. + METHODS render_stats + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !it_result TYPE zif_abapgit_code_inspector=>ty_results + RAISING + zcx_abapgit_exception. + METHODS build_base_menu + RETURNING + VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. + + PRIVATE SECTION. + + CONSTANTS c_object_separator TYPE c LENGTH 1 VALUE '|'. + CONSTANTS c_ci_sig TYPE string VALUE 'cinav:'. + CONSTANTS c_limit TYPE i VALUE 500. + DATA mv_filter_kind TYPE string. + DATA ms_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state. + + TYPES: + BEGIN OF ty_result_view, + kind TYPE zif_abapgit_code_inspector=>ty_result-kind, + obj_type TYPE zif_abapgit_code_inspector=>ty_result-objtype, + location TYPE string, + text TYPE string, + nav TYPE string, + author TYPE c LENGTH 12, + END OF ty_result_view, + ty_view_tab TYPE STANDARD TABLE OF ty_result_view WITH DEFAULT KEY. + + METHODS convert_result_to_view + IMPORTING + it_result TYPE zif_abapgit_code_inspector=>ty_results + RETURNING + VALUE(rt_view) TYPE ty_view_tab. + METHODS explain_include + IMPORTING + !is_result TYPE zif_abapgit_code_inspector=>ty_result + RETURNING + VALUE(rv_txt) TYPE string. + METHODS render_limit_warning + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html. + METHODS build_nav_link + IMPORTING + !is_result TYPE zif_abapgit_code_inspector=>ty_result + RETURNING + VALUE(rv_link) TYPE string. + METHODS jump + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_item + !is_sub_item TYPE zif_abapgit_definitions=>ty_item + !iv_line_number TYPE i + RAISING + zcx_abapgit_exception. + METHODS apply_sorting + CHANGING + ct_view TYPE ty_view_tab. + METHODS apply_filter_kind + CHANGING + ct_view TYPE ty_view_tab. + METHODS handle_navigation + IMPORTING + iv_link TYPE string + RAISING + zcx_abapgit_exception. + METHODS render_stat + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !iv_count TYPE i + !iv_type TYPE string + !iv_title TYPE string + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_code_insp DEFINITION + INHERITING FROM zcl_abapgit_gui_page_codi_base + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_page_title, + zif_abapgit_gui_event_handler, + zif_abapgit_gui_hotkeys, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + io_stage TYPE REF TO zcl_abapgit_stage OPTIONAL + iv_check_variant TYPE sci_chkv OPTIONAL + iv_raise_when_no_results TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + io_stage TYPE REF TO zcl_abapgit_stage OPTIONAL + iv_check_variant TYPE sci_chkv OPTIONAL + iv_raise_when_no_results TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mo_stage TYPE REF TO zcl_abapgit_stage. + DATA mv_check_variant TYPE sci_chkv. + + METHODS: + run_code_inspector + RAISING + zcx_abapgit_exception, + + has_inspection_errors + RETURNING + VALUE(rv_has_inspection_errors) TYPE abap_bool, + + is_stage_allowed + RETURNING + VALUE(rv_is_stage_allowed) TYPE abap_bool, + + ask_user_for_check_variant + RETURNING + VALUE(rv_check_variant) TYPE sci_chkv + RAISING + zcx_abapgit_exception, + + determine_check_variant + RAISING + zcx_abapgit_exception. + + METHODS status + RETURNING + VALUE(rv_status) TYPE zif_abapgit_definitions=>ty_sci_result. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_runit DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + INTERFACES zif_abapgit_gui_menu_provider. + + CLASS-METHODS create + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_actions, + rerun TYPE string VALUE 'rerun' ##NO_TEXT, + END OF c_actions . + + TYPES: + BEGIN OF ty_key, + obj_name TYPE tadir-obj_name, + obj_type TYPE tadir-object, + END OF ty_key, + ty_keys_tt TYPE STANDARD TABLE OF ty_key WITH DEFAULT KEY. + + DATA mi_repo TYPE REF TO zif_abapgit_repo. + DATA mv_summary TYPE string. + + METHODS build_tadir + RETURNING + VALUE(rt_tadir) TYPE ty_keys_tt + RAISING + zcx_abapgit_exception. + + METHODS run + RETURNING + VALUE(ro_result) TYPE REF TO object + RAISING + zcx_abapgit_exception. + + METHODS get_text_for_method + IMPORTING + !is_method TYPE any + !it_indices TYPE ANY TABLE + !iv_program_ndx TYPE sy-tabix + !iv_class_ndx TYPE sy-tabix + !iv_method_ndx TYPE sy-tabix + RETURNING + VALUE(rv_text) TYPE string. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_syntax DEFINITION + INHERITING FROM zcl_abapgit_gui_page_codi_base + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_page_title, + zif_abapgit_gui_event_handler, + zif_abapgit_gui_hotkeys, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + CONSTANTS c_variant TYPE c LENGTH 30 VALUE 'SYNTAX_CHECK'. + + PRIVATE SECTION. + + METHODS run_syntax_check + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_whereused DEFINITION + FINAL + INHERITING FROM zcl_abapgit_gui_component + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_gui_page_title, + zif_abapgit_gui_event_handler, + zif_abapgit_gui_hotkeys, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable, + zif_abapgit_html_table. + + CLASS-METHODS create + IMPORTING + iv_package TYPE devclass OPTIONAL + ii_repo TYPE REF TO zif_abapgit_repo OPTIONAL + PREFERRED PARAMETER iv_package + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + iv_package TYPE devclass OPTIONAL + ii_repo TYPE REF TO zif_abapgit_repo OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: + BEGIN OF c_action, + refresh TYPE string VALUE 'refresh', + show_used_obj TYPE string VALUE 'show_used_obj', + show_root_pkg TYPE string VALUE 'show_root_pkg', + END OF c_action. + + CONSTANTS c_title TYPE string VALUE 'Where Used'. + DATA mv_package TYPE devclass. + DATA mv_ignore_subpackages TYPE abap_bool. + DATA mi_table TYPE REF TO zcl_abapgit_html_table. + DATA mv_show_used_obj TYPE abap_bool. + DATA mv_show_root_pkg TYPE abap_bool. + DATA mt_where_used TYPE zcl_abapgit_where_used_tools=>ty_dependency_tt. + + METHODS init_table_component + RAISING + zcx_abapgit_exception. + + METHODS render_filter_help_hint + RETURNING + VALUE(rv_html) TYPE string. + METHODS render_header + IMPORTING + ii_html TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + METHODS run_where_used + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_db DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + INTERFACES zif_abapgit_gui_menu_provider. + INTERFACES zif_abapgit_html_table. + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_action, + delete TYPE string VALUE 'delete', + backup TYPE string VALUE 'backup', + restore TYPE string VALUE 'restore', + END OF c_action. + + CONSTANTS c_css_url TYPE string VALUE 'css/page_db.css'. + CONSTANTS c_toc_filename TYPE string VALUE '#_Table_of_Content_#.txt'. + + TYPES: + BEGIN OF ty_explanation, + value TYPE string, + extra TYPE string, + END OF ty_explanation. + + DATA mt_methods TYPE zcl_abapgit_background=>ty_methods. + + METHODS register_stylesheet + RAISING + zcx_abapgit_exception. + + METHODS render_stats + IMPORTING + it_db_entries TYPE zif_abapgit_persistence=>ty_contents + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + + METHODS render_table + IMPORTING + it_db_entries TYPE zif_abapgit_persistence=>ty_contents + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + + METHODS do_backup_db + RAISING + zcx_abapgit_exception. + CLASS-METHODS do_delete_entry + IMPORTING + !is_key TYPE zif_abapgit_persistence=>ty_content + RAISING + zcx_abapgit_exception. + CLASS-METHODS do_restore_db + RAISING + zcx_abapgit_exception. + + METHODS explain_content + IMPORTING + !is_data TYPE zif_abapgit_persistence=>ty_content + RETURNING + VALUE(rv_text) TYPE string + RAISING + zcx_abapgit_exception. + METHODS explain_content_repo + IMPORTING + !is_data TYPE zif_abapgit_persistence=>ty_content + RETURNING + VALUE(rs_expl) TYPE ty_explanation + RAISING + zcx_abapgit_exception. + METHODS explain_content_repo_cs + IMPORTING + !is_data TYPE zif_abapgit_persistence=>ty_content + RETURNING + VALUE(rs_expl) TYPE ty_explanation + RAISING + zcx_abapgit_exception. + METHODS explain_content_background + IMPORTING + !is_data TYPE zif_abapgit_persistence=>ty_content + RETURNING + VALUE(rs_expl) TYPE ty_explanation + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_gui_page_db_entry DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + INTERFACES zif_abapgit_gui_page_title . + + CLASS-METHODS create + IMPORTING + !is_key TYPE zif_abapgit_persistence=>ty_content + !iv_edit_mode TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + + METHODS constructor + IMPORTING + !is_key TYPE zif_abapgit_persistence=>ty_content + !iv_edit_mode TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + + PRIVATE SECTION. + CONSTANTS: + BEGIN OF c_action, + update TYPE string VALUE 'update', + switch_mode TYPE string VALUE 'switch_mode', + END OF c_action . + + CONSTANTS c_edit_form_id TYPE string VALUE `db_form`. + CONSTANTS c_css_url TYPE string VALUE 'css/page_db_entry.css'. + + DATA ms_key TYPE zif_abapgit_persistence=>ty_content. + DATA mv_edit_mode TYPE abap_bool. + + METHODS register_stylesheet + RAISING + zcx_abapgit_exception. + + METHODS render_view + IMPORTING + iv_raw_db_value TYPE zif_abapgit_persistence=>ty_content-data_str + ii_html TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + + METHODS render_edit + IMPORTING + iv_raw_db_value TYPE zif_abapgit_persistence=>ty_content-data_str + ii_html TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + + METHODS render_header + IMPORTING + ii_html TYPE REF TO zif_abapgit_html + io_toolbar TYPE REF TO zcl_abapgit_html_toolbar. + + METHODS build_toolbar + RETURNING + VALUE(ro_toolbar) TYPE REF TO zcl_abapgit_html_toolbar. + + CLASS-METHODS render_entry_tag + IMPORTING + is_key TYPE zif_abapgit_persistence=>ty_content + RETURNING + VALUE(rv_html) TYPE string. + + CLASS-METHODS dbcontent_decode + IMPORTING + io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(rs_content) TYPE zif_abapgit_persistence=>ty_content + RAISING + zcx_abapgit_exception . + + CLASS-METHODS do_update + IMPORTING + is_content TYPE zif_abapgit_persistence=>ty_content + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_gui_page_diff_base DEFINITION + INHERITING FROM zcl_abapgit_gui_component + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_hotkeys. + INTERFACES zif_abapgit_gui_menu_provider. + INTERFACES zif_abapgit_gui_renderable. + + CONSTANTS: + BEGIN OF c_fstate, + local TYPE c LENGTH 1 VALUE 'L', + remote TYPE c LENGTH 1 VALUE 'R', + both TYPE c LENGTH 1 VALUE 'B', + END OF c_fstate. + + METHODS constructor + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key OPTIONAL + !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL + !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL + !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + DATA mi_extra TYPE REF TO zif_abapgit_gui_diff_extra. + + CONSTANTS: + BEGIN OF c_actions, + toggle_unified TYPE string VALUE 'toggle_unified', + toggle_hide_diffs TYPE string VALUE 'toggle_hide_diffs', + toggle_hidden_chars TYPE string VALUE 'toggle_hidden_chars', + toggle_ignore_indent TYPE string VALUE 'toggle_ignore_indent', + toggle_ignore_comments TYPE string VALUE 'toggle_ignore_comments', + toggle_ignore_case TYPE string VALUE 'toggle_ignore_case', + refresh_prefix TYPE string VALUE 'refresh', + refresh_all TYPE string VALUE 'refresh_all', + refresh_local TYPE string VALUE 'refresh_local', + refresh_local_object TYPE string VALUE 'refresh_local_object', + END OF c_actions , + BEGIN OF c_action_texts, + refresh_all TYPE string VALUE `Refresh All`, + refresh_local TYPE string VALUE `Refresh Local`, + END OF c_action_texts, + BEGIN OF c_action_titles, + refresh_local TYPE string VALUE `Refresh all local objects, without refreshing the remote`, + refresh_all TYPE string VALUE `Complete refresh of all objects, local and remote`, + END OF c_action_titles. + + DATA mv_unified TYPE abap_bool VALUE abap_true ##NO_TEXT. + DATA mi_repo TYPE REF TO zif_abapgit_repo . + DATA mt_diff_files TYPE zif_abapgit_gui_diff=>ty_file_diffs . + + CLASS-METHODS get_page_layout + RETURNING + VALUE(rv_page_layout) TYPE string. + + CLASS-METHODS get_normalized_fname_with_path + IMPORTING + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff + RETURNING + VALUE(rv_filename) TYPE string . + CLASS-METHODS normalize_path + IMPORTING + !iv_path TYPE string + RETURNING + VALUE(rv_normalized) TYPE string . + CLASS-METHODS normalize_filename + IMPORTING + !iv_filename TYPE string + RETURNING + VALUE(rv_normalized) TYPE string . + METHODS add_menu_end + IMPORTING + !io_menu TYPE REF TO zcl_abapgit_html_toolbar . + METHODS calculate_diff + IMPORTING + !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL + !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL + !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL + RAISING + zcx_abapgit_exception . + METHODS get_files_and_status + IMPORTING + !is_file TYPE zif_abapgit_git_definitions=>ty_file + !is_object TYPE zif_abapgit_definitions=>ty_item + EXPORTING + et_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + et_local TYPE zif_abapgit_definitions=>ty_files_item_tt + et_status TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception. + METHODS add_menu_begin + IMPORTING + !io_menu TYPE REF TO zcl_abapgit_html_toolbar . + METHODS refresh + IMPORTING + iv_action TYPE clike + RAISING + zcx_abapgit_exception . + METHODS refresh_full + RAISING + zcx_abapgit_exception . + METHODS refresh_local + RAISING + zcx_abapgit_exception . + METHODS refresh_local_object + IMPORTING + iv_action TYPE clike + RAISING + zcx_abapgit_exception . + METHODS is_refresh + IMPORTING + iv_action TYPE string + RETURNING + VALUE(rv_is_refrseh) TYPE abap_bool. + METHODS modify_files_before_diff_calc + IMPORTING + it_diff_files_old TYPE zif_abapgit_gui_diff=>ty_file_diffs + RETURNING + VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_stage_tt. + METHODS add_view_sub_menu + IMPORTING + io_menu TYPE REF TO zcl_abapgit_html_toolbar . + METHODS append_diff + IMPORTING + !it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !is_status TYPE zif_abapgit_definitions=>ty_result + RAISING + zcx_abapgit_exception . + + PRIVATE SECTION. + TYPES: + BEGIN OF ty_view, + hide_diffs TYPE abap_bool, + hidden_chars TYPE abap_bool, + ignore_indent TYPE abap_bool, + ignore_comments TYPE abap_bool, + ignore_case TYPE abap_bool, + END OF ty_view. + DATA mt_delayed_lines TYPE zif_abapgit_definitions=>ty_diffs_tt . + DATA mv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key . + DATA mv_seed TYPE string . " Unique page id to bind JS sessionStorage + DATA ms_view TYPE ty_view. + METHODS render_table_head_non_unified + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html . + METHODS render_line_split_row + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !iv_fstate TYPE char1 + !iv_new TYPE string + !iv_old TYPE string + RAISING + zcx_abapgit_exception . + METHODS render_diff_head_after_state + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff . + METHODS render_beacon_begin_of_row + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html. + METHODS render_diff + IMPORTING + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_diff_head + IMPORTING + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_table_head + IMPORTING + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_beacon + IMPORTING + !is_diff_line TYPE zif_abapgit_definitions=>ty_diff + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_line_no_diffs + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_line_split + IMPORTING + !is_diff_line TYPE zif_abapgit_definitions=>ty_diff + !iv_filename TYPE string + !iv_fstate TYPE char1 + !iv_index TYPE sy-tabix + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_line_unified + IMPORTING + !is_diff_line TYPE zif_abapgit_definitions=>ty_diff OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS is_binary + IMPORTING + !iv_d1 TYPE xstring + !iv_d2 TYPE xstring + RETURNING + VALUE(rv_yes) TYPE abap_bool . + METHODS add_jump_sub_menu + IMPORTING + !io_menu TYPE REF TO zcl_abapgit_html_toolbar . + METHODS add_filter_sub_menu + IMPORTING + !io_menu TYPE REF TO zcl_abapgit_html_toolbar . + METHODS render_lines + IMPORTING + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_table_head_unified + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html . + METHODS render_scripts + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS is_file_requested + IMPORTING + it_files TYPE zif_abapgit_definitions=>ty_stage_tt + is_status TYPE zif_abapgit_definitions=>ty_result + RETURNING + VALUE(rv_is_file_requested) TYPE abap_bool. + METHODS has_diffs + IMPORTING + !it_diffs TYPE zif_abapgit_definitions=>ty_diffs_tt + RETURNING + VALUE(rv_has_diffs) TYPE abap_bool. +ENDCLASS. +CLASS zcl_abapgit_gui_page_diff DEFINITION + INHERITING FROM zcl_abapgit_gui_page_diff_base + CREATE PRIVATE. + + PUBLIC SECTION. + + CLASS-METHODS create + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL + !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL + !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_gui_page_diff_file DEFINITION + INHERITING FROM zcl_abapgit_gui_page_diff_base + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS create + IMPORTING + iv_obj_type TYPE tadir-object + iv_obj_name TYPE tadir-obj_name + !is_local TYPE zif_abapgit_git_definitions=>ty_file + !is_remote TYPE zif_abapgit_git_definitions=>ty_file + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + METHODS do_diff + IMPORTING + iv_obj_type TYPE tadir-object + iv_obj_name TYPE tadir-obj_name + !is_local TYPE zif_abapgit_git_definitions=>ty_file + !is_remote TYPE zif_abapgit_git_definitions=>ty_file + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_patch DEFINITION + INHERITING FROM zcl_abapgit_gui_page_diff_base + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_diff_extra. + + CLASS-METHODS create + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL + !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL + !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL + !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL + !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL + RAISING + zcx_abapgit_exception. + + CLASS-METHODS get_patch_data + IMPORTING + !iv_patch TYPE string + EXPORTING + !ev_filename TYPE string + !ev_line_index TYPE string + RAISING + zcx_abapgit_exception. + + METHODS: + zif_abapgit_gui_event_handler~on_event REDEFINITION, + zif_abapgit_gui_hotkeys~get_hotkey_actions REDEFINITION, + zif_abapgit_gui_renderable~render REDEFINITION. + + PROTECTED SECTION. + + METHODS: + add_menu_begin REDEFINITION, + add_menu_end REDEFINITION, + refresh REDEFINITION. + + PRIVATE SECTION. + + TYPES ty_patch_action TYPE string . + + CONSTANTS: + BEGIN OF c_patch_actions, + stage TYPE string VALUE 'patch_stage', + END OF c_patch_actions . + CONSTANTS: + BEGIN OF c_patch_action, + add TYPE ty_patch_action VALUE 'add', + remove TYPE ty_patch_action VALUE 'remove', + END OF c_patch_action . + DATA mo_stage TYPE REF TO zcl_abapgit_stage . + DATA mv_section_count TYPE i . + DATA mv_pushed TYPE abap_bool . + DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online . + + METHODS render_patch + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !iv_filename TYPE string + !is_diff_line TYPE zif_abapgit_definitions=>ty_diff + !iv_index TYPE sy-tabix + RAISING + zcx_abapgit_exception . + METHODS render_patch_head + IMPORTING + !ii_html TYPE REF TO zif_abapgit_html + !is_diff TYPE zif_abapgit_gui_diff=>ty_file_diff . + METHODS start_staging + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RAISING + zcx_abapgit_exception . + METHODS apply_patch_from_form_fields + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RAISING + zcx_abapgit_exception . + METHODS restore_patch_flags + IMPORTING + !it_diff_files_old TYPE zif_abapgit_gui_diff=>ty_file_diffs + RAISING + zcx_abapgit_exception . + METHODS add_to_stage + RAISING + zcx_abapgit_exception . + METHODS apply_patch_all + IMPORTING + !iv_patch TYPE string + !iv_patch_flag TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS are_all_lines_patched + IMPORTING + !it_diff TYPE zif_abapgit_definitions=>ty_diffs_tt + RETURNING + VALUE(rv_are_all_lines_patched) TYPE abap_bool . + METHODS apply_patch_for + IMPORTING + !iv_filename TYPE string + !iv_line_index TYPE string + !iv_patch_flag TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS get_diff_object + IMPORTING + !iv_filename TYPE string + RETURNING + VALUE(ro_diff) TYPE REF TO zif_abapgit_diff + RAISING + zcx_abapgit_exception . + METHODS get_diff_line + IMPORTING + !io_diff TYPE REF TO zif_abapgit_diff + !iv_line_index TYPE string + RETURNING + VALUE(rs_diff) TYPE zif_abapgit_definitions=>ty_diff + RAISING + zcx_abapgit_exception . + CLASS-METHODS is_patch_line_possible + IMPORTING + !is_diff_line TYPE zif_abapgit_definitions=>ty_diff + RETURNING + VALUE(rv_is_patch_line_possible) TYPE abap_bool . + METHODS render_scripts + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_gui_page_addofflin DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + name TYPE string VALUE 'name', + package TYPE string VALUE 'package', + folder_logic TYPE string VALUE 'folder_logic', + labels TYPE string VALUE 'labels', + ignore_subpackages TYPE string VALUE 'ignore_subpackages', + main_lang_only TYPE string VALUE 'main_lang_only', + abap_lang_vers TYPE string VALUE 'abap_lang_vers', + END OF c_id . + + CONSTANTS: + BEGIN OF c_event, + choose_package TYPE string VALUE 'choose-package', + choose_labels TYPE string VALUE 'choose-labels', + create_package TYPE string VALUE 'create-package', + add_offline_repo TYPE string VALUE 'add-repo-offline', + END OF c_event . + + DATA mo_form TYPE REF TO zcl_abapgit_html_form . + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . + + METHODS validate_form + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form . + + METHODS choose_labels + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_addonline DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + url TYPE string VALUE 'url', + package TYPE string VALUE 'package', + branch_name TYPE string VALUE 'branch_name', + display_name TYPE string VALUE 'display_name', + labels TYPE string VALUE 'labels', + folder_logic TYPE string VALUE 'folder_logic', + ignore_subpackages TYPE string VALUE 'ignore_subpackages', + main_lang_only TYPE string VALUE 'main_lang_only', + abap_lang_vers TYPE string VALUE 'abap_lang_vers', + END OF c_id. + + CONSTANTS: + BEGIN OF c_event, + choose_package TYPE string VALUE 'choose-package', + create_package TYPE string VALUE 'create-package', + choose_branch TYPE string VALUE 'choose-branch', + choose_labels TYPE string VALUE 'choose-labels', + add_online_repo TYPE string VALUE 'add-repo-online', + create_repo TYPE string VALUE 'create-repository', + END OF c_event. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form . + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . + + METHODS validate_form + IMPORTING + io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + + METHODS choose_labels + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_cr_repo DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + !iv_url TYPE string + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + !iv_url TYPE string + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + PRIVATE SECTION. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + DATA mv_url TYPE string. + + CONSTANTS: + BEGIN OF c_id, + repo_type TYPE string VALUE 'repo_type', + user_or_org TYPE string VALUE 'user_or_org', + name TYPE string VALUE 'name', + description TYPE string VALUE 'description', + private TYPE string VALUE 'private', + END OF c_id. + + CONSTANTS: + BEGIN OF c_event, + create TYPE string VALUE 'create', + END OF c_event. + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + + METHODS set_defaults + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_sett_bckg DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + + CLASS-METHODS create + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + mode_selection TYPE string VALUE 'mode_selection', + method TYPE string VALUE 'method', + authentication TYPE string VALUE 'authentication', + username TYPE string VALUE 'username', + password TYPE string VALUE 'password', + mode_settings TYPE string VALUE 'mode_settings', + settings TYPE string VALUE 'settings', + END OF c_id . + CONSTANTS: + BEGIN OF c_event, + run_now TYPE string VALUE 'run_now', + save TYPE string VALUE 'save', + END OF c_event . + DATA mo_form TYPE REF TO zcl_abapgit_html_form . + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . + DATA mi_repo TYPE REF TO zif_abapgit_repo . + DATA mv_settings_count TYPE i . + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form + RAISING + zcx_abapgit_exception . + METHODS read_settings + RETURNING + VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + METHODS read_persist + RETURNING + VALUE(rs_persist) TYPE zif_abapgit_persist_background=>ty_background + RAISING + zcx_abapgit_exception . + METHODS save_settings + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_gui_page_sett_glob DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + METHODS constructor + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + proxy_settings TYPE string VALUE 'proxy_settings', + proxy_url TYPE string VALUE 'proxy_url', + proxy_port TYPE string VALUE 'proxy_port', + proxy_auth TYPE string VALUE 'proxy_auth', + proxy_bypass TYPE string VALUE 'proxy_bypass', + commit_settings TYPE string VALUE 'commit_settings', + commitmsg_comment_length TYPE string VALUE 'commitmsg_comment_length', + commitmsg_comment_deflt TYPE string VALUE 'commitmsg_comment_deflt', + commitmsg_body_size TYPE string VALUE 'commitmsg_body_size', + commitmsg_hide_author TYPE string VALUE 'commitmsg_hide_author', + devint_settings TYPE string VALUE 'devint_settings', + run_critical_tests TYPE string VALUE 'run_critical_tests', + experimental_features TYPE string VALUE 'experimental_features', + activate_wo_popup TYPE string VALUE 'activate_wo_popup', + END OF c_id. + CONSTANTS: + BEGIN OF c_event, + proxy_bypass TYPE string VALUE 'proxy_bypass', + save TYPE string VALUE 'save', + END OF c_event. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + + DATA mo_settings TYPE REF TO zcl_abapgit_settings. + + METHODS validate_form + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + METHODS read_settings + RETURNING + VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + METHODS save_settings + RAISING + zcx_abapgit_exception. + CLASS-METHODS read_proxy_bypass + IMPORTING + io_form_data TYPE REF TO zcl_abapgit_string_map + io_settings TYPE REF TO zcl_abapgit_settings + RAISING + zcx_abapgit_exception. + METHODS save_proxy_bypass + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_gui_page_sett_info DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + + CLASS-METHODS create + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_stats, + measure TYPE string, + local TYPE i, + remote TYPE i, + END OF ty_stats . + TYPES: + BEGIN OF ty_infos, + size TYPE p LENGTH 16 DECIMALS 0, + line TYPE p LENGTH 16 DECIMALS 0, + sloc TYPE p LENGTH 16 DECIMALS 0, + END OF ty_infos . + + CONSTANTS: + BEGIN OF c_id, + info TYPE string VALUE 'info', + created_by TYPE string VALUE 'created_by', + created_at TYPE string VALUE 'created_at', + deserialized_by TYPE string VALUE 'deserialized_by', + deserialized_at TYPE string VALUE 'deserialized_at', + stats TYPE string VALUE 'stats', + stats_table TYPE string VALUE 'stats_table', + END OF c_id . + + DATA mo_form TYPE REF TO zcl_abapgit_html_form . + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . + DATA mi_repo TYPE REF TO zif_abapgit_repo . + DATA: + mt_stats TYPE STANDARD TABLE OF ty_stats WITH KEY measure . + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form + RAISING + zcx_abapgit_exception . + METHODS read_settings + RAISING + zcx_abapgit_exception . + METHODS read_stats + RAISING + zcx_abapgit_exception . + METHODS read_stats_files + EXPORTING + !et_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !et_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + METHODS read_stats_state + RAISING + zcx_abapgit_exception . + METHODS read_stats_size_lines_sloc + IMPORTING + !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + !it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + EXPORTING + !et_local_items TYPE zif_abapgit_definitions=>ty_items_tt + !et_remote_items TYPE zif_abapgit_definitions=>ty_items_tt + RAISING + zcx_abapgit_exception . + METHODS read_stats_file + IMPORTING + !is_file TYPE zif_abapgit_git_definitions=>ty_file + RETURNING + VALUE(rs_info) TYPE ty_infos . + METHODS read_stats_objects + CHANGING + !ct_local_items TYPE zif_abapgit_definitions=>ty_items_tt + !ct_remote_items TYPE zif_abapgit_definitions=>ty_items_tt + RAISING + zcx_abapgit_exception . + METHODS format_user + IMPORTING + !iv_username TYPE syuname + RETURNING + VALUE(rv_user) TYPE string . + METHODS format_timestamp + IMPORTING + !iv_timestamp TYPE timestampl + RETURNING + VALUE(rv_timestamp) TYPE string . + METHODS format_size + IMPORTING + !iv_size TYPE i + RETURNING + VALUE(rv_size) TYPE string . +ENDCLASS. +CLASS zcl_abapgit_gui_page_sett_locl DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + + CLASS-METHODS create + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mo_popup_picklist TYPE REF TO zcl_abapgit_gui_picklist. + + CONSTANTS: + BEGIN OF c_id, + local TYPE string VALUE 'local', + display_name TYPE string VALUE 'display_name', + transport_request TYPE string VALUE 'transport_request', + customizing_request TYPE string VALUE 'customizing_request', + labels TYPE string VALUE 'labels', + ignore_subpackages TYPE string VALUE 'ignore_subpackages', + write_protected TYPE string VALUE 'write_protected', + only_local_objects TYPE string VALUE 'only_local_objects', + main_language_only TYPE string VALUE 'main_language_only', + suppress_lxe_po_comments TYPE string VALUE 'suppress_lxe_po_comments', + checks TYPE string VALUE 'checks', + code_inspector_check_variant TYPE string VALUE 'code_inspector_check_variant', + block_commit TYPE string VALUE 'block_commit', + flow TYPE string VALUE 'flow', + exclude_remote_paths TYPE string VALUE 'exclude_remote_paths', + END OF c_id . + CONSTANTS: + BEGIN OF c_event, + save TYPE string VALUE 'save', + choose_transport_request TYPE string VALUE 'choose_transport_request', + choose_customizing_request TYPE string VALUE 'choose_customizing_request', + choose_labels TYPE string VALUE 'choose-labels', + choose_check_variant TYPE string VALUE 'choose_check_variant', + END OF c_event . + DATA mo_form TYPE REF TO zcl_abapgit_html_form . + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . + DATA mi_repo TYPE REF TO zif_abapgit_repo . + DATA ms_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings . + + METHODS validate_form + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form + RAISING + zcx_abapgit_exception . + METHODS read_settings + RETURNING + VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + METHODS save_settings + RAISING + zcx_abapgit_exception . + METHODS choose_labels + RAISING + zcx_abapgit_exception . + METHODS choose_check_variant + IMPORTING + iv_is_return TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception . + METHODS choose_transport_request + RAISING + zcx_abapgit_exception . + METHODS choose_customizing_request + RAISING + zcx_abapgit_exception . + METHODS is_customizing_included + RETURNING + VALUE(rv_result) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS handle_picklist_state + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_gui_page_sett_pers DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + METHODS constructor + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + startup TYPE string VALUE 'startup', + show_default_repo TYPE string VALUE 'show_default_repo', + ui TYPE string VALUE 'ui', + ui_theme TYPE string VALUE 'ui_theme', + icon_scaling TYPE string VALUE 'icon_scaling', + max_lines TYPE string VALUE 'max_lines', + interaction TYPE string VALUE 'interaction', + adt_jump_enabled TYPE string VALUE 'adt_jump_enabled', + link_hints_enabled TYPE string VALUE 'link_hints_enabled', + link_hint_key TYPE string VALUE 'link_hint_key', + hotkeys TYPE string VALUE 'hotkeys', + resources TYPE string VALUE 'resources', + parallel_proc_disabled TYPE string VALUE 'parallel_proc_disabled', + hide_sapgui_hint TYPE string VALUE 'hide_sapgui_hint', + activate_wo_popup TYPE string VALUE 'activate_wo_popup', + label_colors TYPE string VALUE 'label_colors', + git_default_values TYPE string VALUE 'git_default_values', + default_git_uname TYPE string VALUE 'default_git_uname', + default_git_email TYPE string VALUE 'default_git_email', + END OF c_id. + CONSTANTS: + BEGIN OF c_event, + save TYPE string VALUE 'save', + END OF c_event. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + + DATA mo_settings TYPE REF TO zcl_abapgit_settings. + DATA ms_settings TYPE zif_abapgit_persist_user=>ty_s_user_settings. + + METHODS validate_form + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + METHODS read_settings + RETURNING + VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + METHODS save_settings + RAISING + zcx_abapgit_exception. + METHODS render_repo_labels_help_hint + RETURNING + VALUE(rv_html) TYPE string. +ENDCLASS. +CLASS zcl_abapgit_gui_page_sett_remo DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + INTERFACES zif_abapgit_gui_hotkeys. + + CLASS-METHODS create + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES ty_remote_settings TYPE zif_abapgit_persistence=>ty_remote_settings. + + CONSTANTS: + BEGIN OF c_repo_type, + online TYPE string VALUE 'Online Repository', + offline TYPE string VALUE 'Offline Repository', + END OF c_repo_type. + CONSTANTS: + BEGIN OF c_id, + general TYPE string VALUE 'general', + repo_type TYPE string VALUE 'repo_type', + offline TYPE string VALUE 'offline', + url TYPE string VALUE 'url', + head_group TYPE string VALUE 'head_group', + branch TYPE string VALUE 'branch', + tag TYPE string VALUE 'tag', + commit TYPE string VALUE 'commit', + pull_request TYPE string VALUE 'pull_request', + head_type TYPE string VALUE 'head_type', + END OF c_id. + CONSTANTS: + BEGIN OF c_event, + save TYPE string VALUE 'save', + switch TYPE string VALUE 'switch', + choose_url TYPE string VALUE 'choose_url', + choose_branch TYPE string VALUE 'choose_branch', + choose_tag TYPE string VALUE 'choose_tag', + choose_commit TYPE string VALUE 'choose_commit', + choose_pull_request TYPE string VALUE 'choose_pull_request', + change_head_type TYPE string VALUE 'change_head_type', + END OF c_event . + + DATA mi_repo TYPE REF TO zif_abapgit_repo . + DATA ms_settings_snapshot TYPE ty_remote_settings. + DATA mo_form TYPE REF TO zcl_abapgit_html_form . + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . + DATA mv_refresh_on_back TYPE abap_bool. + DATA mv_offline_switch_saved_url TYPE string. + + DATA mo_popup_picklist TYPE REF TO zcl_abapgit_gui_picklist. + + METHODS get_remote_settings_from_repo + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(rs_settings) TYPE ty_remote_settings + RAISING + zcx_abapgit_exception. + + METHODS get_remote_settings_from_form + IMPORTING + io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(rs_settings) TYPE ty_remote_settings + RAISING + zcx_abapgit_exception. + + METHODS get_form_schema + IMPORTING + io_existing_form_data TYPE REF TO zcl_abapgit_string_map OPTIONAL + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form + RAISING + zcx_abapgit_exception. + + METHODS initialize_form_data + RETURNING + VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + + METHODS prepare_for_compare + IMPORTING + io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + + METHODS check_protection + RAISING + zcx_abapgit_exception. + + METHODS validate_form + IMPORTING + io_form_data TYPE REF TO zcl_abapgit_string_map + iv_connection_check TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + + METHODS save_settings + RAISING + zcx_abapgit_exception. + + METHODS choose_url + RETURNING + VALUE(rv_url) TYPE string + RAISING + zcx_abapgit_exception. + METHODS choose_branch + IMPORTING + iv_is_return TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception. + METHODS choose_tag + IMPORTING + iv_is_return TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception. + METHODS choose_pr + IMPORTING + iv_is_return TYPE abap_bool DEFAULT abap_false + RAISING + zcx_abapgit_exception. + METHODS choose_commit + RETURNING + VALUE(rv_commit) TYPE ty_remote_settings-commit + RAISING + zcx_abapgit_exception. + + METHODS switch_online_offline + RAISING + zcx_abapgit_exception. + METHODS switch_to_branch_tag + IMPORTING + !iv_name TYPE string OPTIONAL + RAISING + zcx_abapgit_exception. + METHODS switch_to_commit + IMPORTING + !iv_revert TYPE abap_bool DEFAULT abap_false + !iv_commit TYPE ty_remote_settings-commit OPTIONAL + RAISING + zcx_abapgit_exception. + METHODS switch_to_pull_req + IMPORTING + !iv_revert TYPE abap_bool DEFAULT abap_false + !iv_pull TYPE string OPTIONAL + RAISING + zcx_abapgit_exception. + + METHODS handle_picklist_state + RAISING + zcx_abapgit_exception. + + METHODS render_content + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_sett_repo DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + + CLASS-METHODS create + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS constructor + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + dot TYPE string VALUE 'dot', + file_system TYPE string VALUE 'file_system', + abap_system TYPE string VALUE 'abap_system', + name TYPE string VALUE 'name', + i18n TYPE string VALUE 'i18n', + main_language TYPE string VALUE 'main_language', + i18n_langs TYPE string VALUE 'i18n_langs', + use_lxe TYPE string VALUE 'use_lxe', + wo_transaltion TYPE string VALUE 'wo_translation', + starting_folder TYPE string VALUE 'starting_folder', + folder_logic TYPE string VALUE 'folder_logic', + ignore TYPE string VALUE 'ignore', + requirements TYPE string VALUE 'requirements', + version_constant TYPE string VALUE 'version_constant', + version_value TYPE string VALUE 'version_value', + abap_langu_vers TYPE string VALUE 'abap_langu_vers', + original_system TYPE string VALUE 'original_system', + END OF c_id. + CONSTANTS: + BEGIN OF c_event, + save TYPE string VALUE 'save', + END OF c_event . + CONSTANTS c_empty_rows TYPE i VALUE 2 ##NO_TEXT. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form . + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . + + DATA mi_repo TYPE REF TO zif_abapgit_repo . + DATA mv_requirements_count TYPE i . + + METHODS validate_form + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + METHODS validate_version_constant + IMPORTING + !iv_version_constant TYPE string + RAISING + zcx_abapgit_exception . + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form + RAISING + zcx_abapgit_exception . + METHODS read_settings + RETURNING + VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + METHODS save_settings + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_gui_page_chg_pckg DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + old_package TYPE string VALUE 'old-package', + new_package TYPE string VALUE 'new-package', + remove_old TYPE string VALUE 'remove-old', + END OF c_id. + + CONSTANTS: + BEGIN OF c_event, + change_package TYPE string VALUE 'change-package', + choose_package_old TYPE string VALUE 'choose-package-old', + choose_package_new TYPE string VALUE 'choose-package-new', + END OF c_event. + + TYPES: + BEGIN OF ty_map, + old_package TYPE devclass, + new_package TYPE devclass, + END OF ty_map, + ty_mapping TYPE STANDARD TABLE OF ty_map WITH KEY old_package. + + DATA mi_repo TYPE REF TO zif_abapgit_repo. + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + + METHODS init_form + RAISING + zcx_abapgit_exception. + + METHODS validate_form + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + + METHODS change_package + IMPORTING + !iv_old_package TYPE devclass + !iv_new_package TYPE devclass + !iv_remove_old TYPE abap_bool + RAISING + zcx_abapgit_exception. + + METHODS get_package_mapping + IMPORTING + !iv_old_package TYPE devclass + !iv_new_package TYPE devclass + RETURNING + VALUE(rt_mapping) TYPE ty_mapping + RAISING + zcx_abapgit_exception. + + METHODS create_package_hierarchy + IMPORTING + !it_mapping TYPE ty_mapping + RAISING + zcx_abapgit_exception. + + METHODS delete_packages + IMPORTING + !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception. + + METHODS change_package_assignment + IMPORTING + !it_mapping TYPE ty_mapping + !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt + RAISING + zcx_abapgit_exception. + + METHODS update_sotr_package_assignment + IMPORTING + !it_mapping TYPE ty_mapping + RAISING + zcx_abapgit_exception. + + METHODS update_repo_persistence + IMPORTING + !iv_old_package TYPE devclass + !iv_new_package TYPE devclass + RAISING + zcx_abapgit_exception. + + METHODS update_repo_checksums + IMPORTING + !it_mapping TYPE ty_mapping + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_gui_page_commit DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + !io_stage TYPE REF TO zcl_abapgit_stage + !iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result DEFAULT zif_abapgit_definitions=>c_sci_result-no_run + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + METHODS constructor + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + !io_stage TYPE REF TO zcl_abapgit_stage + !iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + committer TYPE string VALUE 'committer', + committer_name TYPE string VALUE 'committer_name', + committer_email TYPE string VALUE 'committer_email', + message TYPE string VALUE 'message', + comment TYPE string VALUE 'comment', + body TYPE string VALUE 'body', + author TYPE string VALUE 'author', + author_name TYPE string VALUE 'author_name', + author_email TYPE string VALUE 'author_email', + new_branch_name TYPE string VALUE 'new_branch_name', + END OF c_id. + + CONSTANTS: + BEGIN OF c_event, + commit TYPE string VALUE 'commit', + END OF c_event. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + DATA mo_settings TYPE REF TO zcl_abapgit_settings. + DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online. + DATA mo_stage TYPE REF TO zcl_abapgit_stage. + DATA mt_stage TYPE zif_abapgit_definitions=>ty_stage_tt. + DATA ms_commit TYPE zif_abapgit_services_git=>ty_commit_fields. + DATA mv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result. + + METHODS render_stage_summary + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + METHODS render_stage_details + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + METHODS validate_form + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + METHODS get_defaults + RAISING + zcx_abapgit_exception. + METHODS get_committer_name + RETURNING + VALUE(rv_user) TYPE string + RAISING + zcx_abapgit_exception. + METHODS get_committer_email + RETURNING + VALUE(rv_email) TYPE string + RAISING + zcx_abapgit_exception. + METHODS get_comment_default + RETURNING + VALUE(rv_text) TYPE string. + METHODS get_comment_object + IMPORTING + !it_stage TYPE zif_abapgit_definitions=>ty_stage_tt + RETURNING + VALUE(rv_text) TYPE string. + METHODS get_comment_file + IMPORTING + !it_stage TYPE zif_abapgit_definitions=>ty_stage_tt + RETURNING + VALUE(rv_text) TYPE string. + METHODS branch_name_to_internal + IMPORTING + iv_branch_name TYPE string + RETURNING + VALUE(rv_new_branch_name) TYPE string. +ENDCLASS. +CLASS zcl_abapgit_gui_page_cpackage DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_event_handler, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + iv_name TYPE devclass + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + PRIVATE SECTION. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + DATA mv_default_name TYPE devclass. + + CONSTANTS: + BEGIN OF c_id, + package TYPE string VALUE 'package', + description TYPE string VALUE 'description', + software_component TYPE string VALUE 'software_component', + transport_layer TYPE string VALUE 'transport_layer', + super_package TYPE string VALUE 'super_package', + END OF c_id. + + CONSTANTS: + BEGIN OF c_event, + create TYPE string VALUE 'create', + END OF c_event. + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + + METHODS get_defaults + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_data DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_event_handler, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + CONSTANTS: + BEGIN OF c_event, + add TYPE string VALUE 'add', + update TYPE string VALUE 'update', + remove TYPE string VALUE 'remove', + add_via_transport TYPE string VALUE 'add_via_transport', + END OF c_event. + CONSTANTS: + BEGIN OF c_id, + table TYPE string VALUE 'table', + where TYPE string VALUE 'where', + skip_initial TYPE string VALUE 'skip_initial', + END OF c_id. + DATA mi_config TYPE REF TO zif_abapgit_data_config. + + PRIVATE SECTION. + + DATA mi_repo TYPE REF TO zif_abapgit_repo. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + + CLASS-METHODS concatenated_key_to_where + IMPORTING + !iv_table TYPE tabname + !iv_tabkey TYPE clike + RETURNING + VALUE(rv_where) TYPE string + RAISING + zcx_abapgit_exception. + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + METHODS add_via_transport + RAISING + zcx_abapgit_exception . + METHODS build_where + IMPORTING + !io_map TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(rt_where) TYPE string_table . + METHODS render_existing + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS event_add + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RAISING + zcx_abapgit_exception . + METHODS event_remove + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RAISING + zcx_abapgit_exception . + METHODS event_update + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RAISING + zcx_abapgit_exception . + METHODS validate_table_name + IMPORTING + iv_table_name TYPE string + CHANGING + co_validation_log TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_gui_page_debuginfo DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS c_exit_standalone TYPE syrepid VALUE 'ZABAPGIT_USER_EXIT' ##NO_TEXT. + CONSTANTS c_exit_class TYPE c LENGTH 30 VALUE 'ZCL_ABAPGIT_USER_EXIT' ##NO_TEXT. + CONSTANTS c_exit_interface TYPE c LENGTH 30 VALUE 'ZIF_ABAPGIT_EXIT' ##NO_TEXT. + CONSTANTS: + BEGIN OF c_action, + save TYPE string VALUE 'save', + END OF c_action. + DATA mv_html TYPE string . + + CLASS-METHODS build_toolbar + RETURNING + VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. + METHODS render_debug_info + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_exit_info + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_exit_info_methods + IMPORTING + !it_source TYPE string_table + !iv_clsname TYPE seoclsname OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_supported_object_types + RETURNING + VALUE(rv_html) TYPE string . + METHODS render_scripts + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS get_jump_object + IMPORTING + !iv_obj_type TYPE csequence DEFAULT 'CLAS' + !iv_obj_name TYPE csequence + RETURNING + VALUE(rv_html) TYPE string . + METHODS resolve_exit_include + CHANGING + !cv_clsname TYPE seoclsname + !ct_source TYPE string_table. +ENDCLASS. +CLASS zcl_abapgit_gui_page_ex_object DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + METHODS constructor + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: + BEGIN OF c_id, + object_type TYPE string VALUE 'object_type', + object_name TYPE string VALUE 'object_name', + only_main TYPE string VALUE 'only_main', + i18n_langs TYPE string VALUE 'i18n_langs', + use_lxe TYPE string VALUE 'use_lxe', + END OF c_id. + + CONSTANTS: + BEGIN OF c_event, + export TYPE string VALUE 'export', + choose_object_type TYPE string VALUE 'choose-object-type', + END OF c_event. + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + + METHODS export_object + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_gui_page_ex_pckage DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + METHODS constructor + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: + BEGIN OF c_id, + package TYPE string VALUE 'package', + folder_logic TYPE string VALUE 'folder_logic', + ignore_subpackages TYPE string VALUE 'ignore_subpackages', + main_lang_only TYPE string VALUE 'main_lang_only', + END OF c_id. + + CONSTANTS: + BEGIN OF c_event, + export_package TYPE string VALUE 'export-package', + choose_package TYPE string VALUE 'choose-object-type', + END OF c_event. + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. + + METHODS export_package + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_gui_page_merge DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_event_handler, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + ii_repo_online TYPE REF TO zif_abapgit_repo_online + iv_source TYPE string + iv_target TYPE string + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + ii_repo_online TYPE REF TO zif_abapgit_repo_online + iv_source TYPE string + iv_target TYPE string + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online. + DATA mi_merge TYPE REF TO zif_abapgit_merge. + + CONSTANTS: + BEGIN OF c_actions, + merge TYPE string VALUE 'merge', + res_conflicts TYPE string VALUE 'res_conflicts', + END OF c_actions. + + METHODS show_file + IMPORTING + !it_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt + !ii_html TYPE REF TO zif_abapgit_html + !is_file TYPE zif_abapgit_git_definitions=>ty_expanded + !is_result TYPE zif_abapgit_git_definitions=>ty_expanded. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_merge_res DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_event_handler, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + ii_repo_online TYPE REF TO zif_abapgit_repo_online + io_merge_page TYPE REF TO zcl_abapgit_gui_page_merge + io_merge TYPE REF TO zif_abapgit_merge + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + ii_repo_online TYPE REF TO zif_abapgit_repo_online + io_merge_page TYPE REF TO zcl_abapgit_gui_page_merge + io_merge TYPE REF TO zif_abapgit_merge + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_file_diff, + path TYPE string, + filename TYPE string, + lstate TYPE char1, + rstate TYPE char1, + fstate TYPE char1, " FILE state - Abstraction for shorter ifs + o_diff TYPE REF TO zif_abapgit_diff, + changed_by TYPE syuname, + type TYPE string, + END OF ty_file_diff . + + CONSTANTS: + BEGIN OF c_actions, + toggle_mode TYPE string VALUE 'toggle_mode' ##NO_TEXT, + apply_merge TYPE string VALUE 'apply_merge' ##NO_TEXT, + apply_source TYPE string VALUE 'apply_source' ##NO_TEXT, + apply_target TYPE string VALUE 'apply_target' ##NO_TEXT, + cancel TYPE string VALUE 'cancel' ##NO_TEXT, + END OF c_actions . + CONSTANTS: + BEGIN OF c_merge_mode, + selection TYPE string VALUE 'selection' ##NO_TEXT, + merge TYPE string VALUE 'merge' ##NO_TEXT, + END OF c_merge_mode . + DATA mo_merge TYPE REF TO zif_abapgit_merge . + DATA mo_merge_page TYPE REF TO zcl_abapgit_gui_page_merge . + DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online . + DATA ms_diff_file TYPE ty_file_diff . + DATA mv_current_conflict_index TYPE sy-tabix . + DATA mv_merge_mode TYPE string . + DATA mt_conflicts TYPE zif_abapgit_merge=>ty_merge_conflict_tt . + + METHODS apply_merged_content + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RAISING + zcx_abapgit_exception . + METHODS is_binary + IMPORTING + !iv_d1 TYPE xstring + !iv_d2 TYPE xstring + RETURNING + VALUE(rv_yes) TYPE abap_bool . + METHODS render_beacon + IMPORTING + !is_diff_line TYPE zif_abapgit_definitions=>ty_diff + !is_diff TYPE ty_file_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_diff + IMPORTING + !is_diff TYPE ty_file_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_diff_head + IMPORTING + !is_diff TYPE ty_file_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_lines + IMPORTING + !is_diff TYPE ty_file_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_line_split + IMPORTING + !is_diff_line TYPE zif_abapgit_definitions=>ty_diff + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_table_head + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS resolve_diff + RAISING + zcx_abapgit_exception . + METHODS toggle_merge_mode . +ENDCLASS. +CLASS zcl_abapgit_gui_page_merge_sel DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + branches TYPE string VALUE 'branches', + source TYPE string VALUE 'source', + target TYPE string VALUE 'target', + END OF c_id. + + CONSTANTS: + BEGIN OF c_event, + merge TYPE string VALUE 'merge', + END OF c_event. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. + DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online. + DATA mt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. + + METHODS read_branches + RAISING + zcx_abapgit_exception. + + METHODS get_form_schema + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_gui_page_pull DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_menu_provider. + INTERFACES zif_abapgit_gui_renderable. + + CONSTANTS: + BEGIN OF c_id, + transport_request TYPE string VALUE 'transport_request', + END OF c_id . + + CONSTANTS: BEGIN OF c_action, + pull TYPE string VALUE 'pull', + refresh TYPE string VALUE 'refresh', + choose_tr TYPE string VALUE 'choose_tr', + END OF c_action. + + CLASS-METHODS create + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + iv_trkorr TYPE trkorr OPTIONAL + ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + ii_repo TYPE REF TO zif_abapgit_repo + iv_trkorr TYPE trkorr + ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + PRIVATE SECTION. + + DATA mi_repo TYPE REF TO zif_abapgit_repo . + DATA mi_obj_filter TYPE REF TO zif_abapgit_object_filter . + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . + DATA ms_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks . + + METHODS pull + RAISING + zcx_abapgit_exception . + METHODS form + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form + RAISING + zcx_abapgit_exception . + METHODS choose_transport_request + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_gui_page_repo_over DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_event_handler, + zif_abapgit_gui_hotkeys, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + !iv_only_favorites TYPE abap_bool OPTIONAL + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + !iv_only_favorites TYPE abap_bool OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_overview, + favorite TYPE string, + offline TYPE abap_bool, + key TYPE zif_abapgit_persistence=>ty_value, + name TYPE string, + labels TYPE string_table, + url TYPE string, + package TYPE devclass, + branch TYPE string, + created_by TYPE syuname, + created_at TYPE string, + created_at_raw TYPE timestampl, + deserialized_by TYPE syuname, + deserialized_at TYPE string, + deserialized_at_raw TYPE timestampl, + write_protected TYPE abap_bool, + flow TYPE abap_bool, + END OF ty_overview, + ty_overviews TYPE STANDARD TABLE OF ty_overview + WITH NON-UNIQUE DEFAULT KEY. + CONSTANTS: + BEGIN OF c_action, + select TYPE string VALUE 'select', + apply_filter TYPE string VALUE 'apply_filter', + label_filter TYPE string VALUE 'label_filter', + clear_filter TYPE string VALUE 'clear_filter', + refresh_list TYPE string VALUE 'refresh_list', + END OF c_action, + c_label_filter_prefix TYPE string VALUE `label:`, + c_raw_field_suffix TYPE string VALUE `_RAW` ##NO_TEXT. + + DATA: mt_all_labels TYPE string_table, + mo_label_colors TYPE REF TO zcl_abapgit_string_map. + DATA ms_list_settings TYPE zif_abapgit_persist_user=>ty_list_settings. + + METHODS set_order_by + IMPORTING + !iv_order_by TYPE string + RAISING + zcx_abapgit_exception. + METHODS set_order_direction + IMPORTING + !iv_order_descending TYPE abap_bool + RAISING + zcx_abapgit_exception. + METHODS set_filter + IMPORTING + it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data + RAISING + zcx_abapgit_exception. + + METHODS: + apply_filter + CHANGING + ct_overview TYPE ty_overviews, + + map_repo_list_to_overview + IMPORTING + it_repo_obj_list TYPE zif_abapgit_repo_srv=>ty_repo_list + RETURNING + VALUE(rt_overview) TYPE ty_overviews + RAISING + zcx_abapgit_exception, + + render_repo_list + IMPORTING + ii_html TYPE REF TO zif_abapgit_html + it_overview TYPE ty_overviews + RAISING + zcx_abapgit_exception, + + render_table_header + IMPORTING + ii_html TYPE REF TO zif_abapgit_html, + + render_table_footer + IMPORTING + ii_html TYPE REF TO zif_abapgit_html, + + render_table_body + IMPORTING + ii_html TYPE REF TO zif_abapgit_html + it_repo_list TYPE ty_overviews + RAISING + zcx_abapgit_exception, + + render_table_item + IMPORTING + ii_html TYPE REF TO zif_abapgit_html + is_repo TYPE ty_overview + RAISING + zcx_abapgit_exception, + + render_header_bar + IMPORTING + ii_html TYPE REF TO zif_abapgit_html, + + render_header_label_list + IMPORTING + ii_html TYPE REF TO zif_abapgit_html, + + apply_order_by + CHANGING ct_overview TYPE ty_overviews. + + METHODS prepare_overviews + RETURNING + VALUE(rt_overviews) TYPE ty_overviews + RAISING + zcx_abapgit_exception. + + METHODS render_scripts + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + + METHODS render_action_toolbar + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html. + + METHODS render_filter_bar + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html. + + METHODS build_table_scheme + RETURNING + VALUE(rt_tab_scheme) TYPE zcl_abapgit_gui_chunk_lib=>ty_col_spec_tt. + + METHODS collect_all_labels + IMPORTING + it_overview TYPE ty_overviews + RETURNING + VALUE(rt_list) TYPE string_table. + + METHODS render_filter_help_hint + RETURNING + VALUE(rv_html) TYPE string. + + METHODS save_settings + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_gui_page_repo_view DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_event_handler, + zif_abapgit_gui_hotkeys, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable. + + CONSTANTS: + BEGIN OF c_actions, + change_dir TYPE string VALUE 'change_dir' ##NO_TEXT, + toggle_hide_files TYPE string VALUE 'toggle_hide_files' ##NO_TEXT, + toggle_folders TYPE string VALUE 'toggle_folders' ##NO_TEXT, + toggle_changes TYPE string VALUE 'toggle_changes' ##NO_TEXT, + toggle_diff_first TYPE string VALUE 'toggle_diff_first ' ##NO_TEXT, + display_more TYPE string VALUE 'display_more' ##NO_TEXT, + go_data TYPE string VALUE 'go_data', + go_unit TYPE string VALUE 'go_unit', + END OF c_actions . + + CLASS-METHODS create + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mi_repo TYPE REF TO zif_abapgit_repo . + DATA mo_repo_aggregated_state TYPE REF TO zcl_abapgit_repo_item_state. + DATA mv_connection_error TYPE abap_bool. + DATA mv_cur_dir TYPE string . + DATA mv_hide_files TYPE abap_bool . + DATA mv_max_lines TYPE i . + DATA mv_max_setting TYPE i . + DATA mv_show_folders TYPE abap_bool . + DATA mv_changes_only TYPE abap_bool . + DATA mv_order_by TYPE string . + DATA mv_order_descending TYPE abap_bool . + DATA mv_diff_first TYPE abap_bool . + DATA mv_key TYPE zif_abapgit_persistence=>ty_value . + DATA mv_are_changes_recorded_in_tr TYPE abap_bool . + + METHODS render_head_line + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS build_view_dropdown + RETURNING + VALUE(ro_toolbar) TYPE REF TO zcl_abapgit_html_toolbar + RAISING + zcx_abapgit_exception . + METHODS render_item + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + !iv_render_transports TYPE abap_bool + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_item_files + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_item_command + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_file_command + IMPORTING + !is_file TYPE zif_abapgit_definitions=>ty_repo_file + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS get_item_class + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + iv_is_object_row TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rv_html) TYPE string . + METHODS render_item_transport + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_parent_dir + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS build_dir_jump_link + IMPORTING + !iv_path TYPE string + RETURNING + VALUE(rv_html) TYPE string . + METHODS build_inactive_object_code + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + RETURNING + VALUE(rv_inactive_html_code) TYPE string . + METHODS build_srcsystem_code + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + RETURNING + VALUE(rv_srcsystem_html_code) TYPE string . + METHODS build_origlang_code + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + RETURNING + VALUE(rv_html_code) TYPE string . + METHODS open_in_main_language + RAISING + zcx_abapgit_exception . + METHODS render_table_header + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_table_footer + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS apply_order_by + CHANGING + !ct_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt + RAISING + zcx_abapgit_exception . + METHODS build_branch_dropdown + RETURNING + VALUE(ro_branch_dropdown) TYPE REF TO zcl_abapgit_html_toolbar + RAISING + zcx_abapgit_exception . + METHODS build_tag_dropdown + RETURNING + VALUE(ro_tag_dropdown) TYPE REF TO zcl_abapgit_html_toolbar + RAISING + zcx_abapgit_exception . + METHODS build_advanced_dropdown + RETURNING + VALUE(ro_advanced_dropdown) TYPE REF TO zcl_abapgit_html_toolbar + RAISING + zcx_abapgit_exception . + METHODS build_main_toolbar + RETURNING + VALUE(ro_toolbar) TYPE REF TO zcl_abapgit_html_toolbar + RAISING + zcx_abapgit_exception . + METHODS render_scripts + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS is_repo_lang_logon_lang + RETURNING + VALUE(rv_repo_lang_is_logon_lang) TYPE abap_bool . + + METHODS render_item_changed_by + IMPORTING + !is_item TYPE zif_abapgit_definitions=>ty_repo_item + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + + METHODS order_files + CHANGING + ct_files TYPE zif_abapgit_definitions=>ty_repo_file_tt. + + METHODS get_crossout + IMPORTING + !iv_authorization TYPE zif_abapgit_auth=>ty_authorization OPTIONAL + !iv_protected TYPE abap_bool DEFAULT abap_false + !iv_strong TYPE abap_bool DEFAULT abap_false + PREFERRED PARAMETER iv_authorization + RETURNING + VALUE(rv_crossout) LIKE zif_abapgit_html=>c_html_opt-crossout. + + METHODS check_branch + RAISING + zcx_abapgit_exception. + + METHODS check_connection + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_run_bckg DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler . + INTERFACES zif_abapgit_gui_renderable . + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS constructor + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + DATA: mt_text TYPE TABLE OF string. + + METHODS run. +ENDCLASS. +CLASS zcl_abapgit_gui_page_stage DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES: + zif_abapgit_gui_event_handler, + zif_abapgit_gui_hotkeys, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable. + + CONSTANTS: BEGIN OF c_action, + stage_refresh TYPE string VALUE 'stage_refresh', + stage_all TYPE string VALUE 'stage_all', + stage_commit TYPE string VALUE 'stage_commit', + stage_filter TYPE string VALUE 'stage_filter', + END OF c_action. + + CLASS-METHODS create + IMPORTING + ii_repo_online TYPE REF TO zif_abapgit_repo_online + iv_seed TYPE string OPTIONAL + iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result DEFAULT zif_abapgit_definitions=>c_sci_result-no_run + ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL + ii_force_refresh TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + ii_repo_online TYPE REF TO zif_abapgit_repo_online + iv_seed TYPE string OPTIONAL + iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result DEFAULT zif_abapgit_definitions=>c_sci_result-no_run + ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL + ii_force_refresh TYPE abap_bool DEFAULT abap_true + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_changed_by, + item TYPE zif_abapgit_definitions=>ty_item, + filename TYPE string, + name TYPE syuname, + END OF ty_changed_by . + TYPES: + ty_changed_by_tt TYPE SORTED TABLE OF ty_changed_by WITH UNIQUE KEY item filename. + + DATA mi_repo TYPE REF TO zif_abapgit_repo. + DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online. + DATA ms_files TYPE zif_abapgit_definitions=>ty_stage_files . + DATA mv_seed TYPE string . " Unique page id to bind JS sessionStorage + DATA mv_filter_value TYPE string . + DATA mv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result. + DATA mi_obj_filter TYPE REF TO zif_abapgit_object_filter. + + METHODS find_changed_by + IMPORTING + !it_files TYPE zif_abapgit_definitions=>ty_stage_files + !it_transports TYPE zif_abapgit_cts_api=>ty_transport_list + RETURNING + VALUE(rt_changed_by) TYPE ty_changed_by_tt . + METHODS find_transports + IMPORTING + !it_files TYPE zif_abapgit_definitions=>ty_stage_files + RETURNING + VALUE(rt_transports) TYPE zif_abapgit_cts_api=>ty_transport_list . + METHODS render_list + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_file + IMPORTING + !iv_context TYPE string + !is_file TYPE zif_abapgit_git_definitions=>ty_file + !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL + !is_status TYPE zif_abapgit_definitions=>ty_result + !iv_changed_by TYPE syuname OPTIONAL + !iv_transport TYPE trkorr OPTIONAL + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS render_actions + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS stage_selected + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(ro_stage) TYPE REF TO zcl_abapgit_stage + RAISING + zcx_abapgit_exception . + METHODS stage_all + RETURNING + VALUE(ro_stage) TYPE REF TO zcl_abapgit_stage + RAISING + zcx_abapgit_exception . + METHODS get_page_patch + IMPORTING + !io_stage TYPE REF TO zcl_abapgit_stage + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS render_main_language_warning + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS count_default_files_to_commit + RETURNING + VALUE(rv_count) TYPE i . + METHODS render_deferred_hidden_events + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS render_scripts + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception . + METHODS init_files + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_gui_page_tags DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + CONSTANTS: + BEGIN OF c_id, + tag_group TYPE string VALUE 'tag_group', + tag_type TYPE string VALUE 'tag_type', + tags TYPE string VALUE 'tags', + type TYPE string VALUE 'type', + name TYPE string VALUE 'name', + sha1 TYPE string VALUE 'sha1', + anno_group TYPE string VALUE 'anno_group', + tagger TYPE string VALUE 'tagger', + tagger_name TYPE string VALUE 'tagger_name', + tagger_email TYPE string VALUE 'tagger_email', + message TYPE string VALUE 'message', + body TYPE string VALUE 'body', + END OF c_id. + + CONSTANTS: + BEGIN OF c_event, + create TYPE string VALUE 'create', + choose_commit TYPE string VALUE 'choose_commit', + change_type TYPE string VALUE 'change_type', + END OF c_event. + + DATA mo_form TYPE REF TO zcl_abapgit_html_form. + DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. + DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online. + DATA mo_settings TYPE REF TO zcl_abapgit_settings. + DATA ms_tag TYPE zif_abapgit_git_definitions=>ty_git_tag. + + METHODS get_form_schema + IMPORTING + io_form_data TYPE REF TO zcl_abapgit_string_map OPTIONAL + RETURNING + VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form + RAISING + zcx_abapgit_exception. + + METHODS initialize_form_data + RAISING + zcx_abapgit_exception. + + METHODS get_tagger_name + RETURNING + VALUE(rv_user) TYPE string + RAISING + zcx_abapgit_exception. + + METHODS get_tagger_email + RETURNING + VALUE(rv_email) TYPE string + RAISING + zcx_abapgit_exception. + + METHODS validate_form + IMPORTING + !io_form_data TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + + METHODS choose_commit + RETURNING + VALUE(rv_commit) TYPE zif_abapgit_git_definitions=>ty_commit-sha1 + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_gui_page_tutorial DEFINITION + FINAL + INHERITING FROM zcl_abapgit_gui_component + CREATE PUBLIC. + + PUBLIC SECTION. + INTERFACES zif_abapgit_gui_renderable. + + CLASS-METHODS create + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + + PRIVATE SECTION. + + CLASS-METHODS build_main_menu + RETURNING + VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. + +ENDCLASS. +CLASS zcl_abapgit_popup_branch_list DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_render_item. + INTERFACES zif_abapgit_html_popup. + + CLASS-METHODS create + IMPORTING + !iv_url TYPE string + !iv_default_branch TYPE string OPTIONAL + !iv_show_new_option TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_popup) TYPE REF TO zif_abapgit_html_popup. + + METHODS constructor + IMPORTING + !iv_url TYPE string + !iv_default_branch TYPE string OPTIONAL + !iv_show_new_option TYPE abap_bool DEFAULT abap_false. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_repo_url TYPE string. + DATA mv_default_branch TYPE string. + DATA mv_show_new_option TYPE abap_bool. + + METHODS fetch_branch_list + RETURNING + VALUE(rt_branches) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_popup_code_insp DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_render_item . + INTERFACES zif_abapgit_html_popup . + + CLASS-METHODS create + RETURNING + VALUE(ri_popup) TYPE REF TO zif_abapgit_html_popup . + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS fetch_list + RETURNING + VALUE(rt_list) TYPE zif_abapgit_code_inspector=>ty_variants + RAISING + zcx_abapgit_exception. + +ENDCLASS. +CLASS zcl_abapgit_popup_pull_request DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_render_item. + INTERFACES zif_abapgit_html_popup. + + CLASS-METHODS create + IMPORTING + iv_url TYPE string + RETURNING + VALUE(ri_popup) TYPE REF TO zif_abapgit_html_popup. + + METHODS constructor + IMPORTING + iv_url TYPE string. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_repo_url TYPE string. + + METHODS fetch_pull_request_list + RETURNING + VALUE(rt_pulls) TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_popup_tag_list DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_render_item. + INTERFACES zif_abapgit_html_popup. + + CLASS-METHODS create + IMPORTING + iv_url TYPE string + RETURNING + VALUE(ri_popup) TYPE REF TO zif_abapgit_html_popup. + + METHODS constructor + IMPORTING + iv_url TYPE string. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_repo_url TYPE string. + + METHODS fetch_tag_list + RETURNING + VALUE(rt_tags) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_progress DEFINITION + FINAL + CREATE PROTECTED . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_progress . + + CLASS-METHODS set_instance + IMPORTING + !ii_progress TYPE REF TO zif_abapgit_progress . + CLASS-METHODS get_instance + IMPORTING + !iv_total TYPE i + RETURNING + VALUE(ri_progress) TYPE REF TO zif_abapgit_progress . + PROTECTED SECTION. + + DATA mv_total TYPE i . + CLASS-DATA gi_progress TYPE REF TO zif_abapgit_progress . + + METHODS calc_pct + IMPORTING + !iv_current TYPE i + RETURNING + VALUE(rv_pct) TYPE i . + PRIVATE SECTION. + + DATA mv_cv_time_next TYPE sy-uzeit . + DATA mv_cv_datum_next TYPE sy-datum . +ENDCLASS. +CLASS zcl_abapgit_gui_router DEFINITION + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_event_handler. + + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS general_page_routing + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception . + METHODS abapgit_services_actions + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception . + METHODS db_actions + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception . + CLASS-METHODS file_download + IMPORTING + !iv_package TYPE devclass + !iv_xstr TYPE xstring + RAISING + zcx_abapgit_exception . + METHODS git_services + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception . + METHODS sap_gui_actions + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception . + METHODS other_utilities + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception . + METHODS zip_services + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception . + METHODS zip_export_transport + IMPORTING + iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception. + METHODS go_stage_transport + IMPORTING + iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(ro_filter) TYPE REF TO zcl_abapgit_object_filter_tran + RAISING + zcx_abapgit_exception. + METHODS repository_services + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result + RAISING + zcx_abapgit_exception . + METHODS get_page_diff + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS get_page_patch + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + METHODS get_page_stage + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception . + CLASS-METHODS jump_object + IMPORTING + !iv_obj_type TYPE string + !iv_obj_name TYPE string + !iv_filename TYPE string + !iv_sub_type TYPE string OPTIONAL + !iv_sub_name TYPE string OPTIONAL + !iv_line TYPE string OPTIONAL + !iv_new_window TYPE string DEFAULT 'X' + RAISING + zcx_abapgit_exception . + CLASS-METHODS jump_display_transport + IMPORTING + !iv_transport TYPE trkorr + iv_obj_type TYPE tadir-object OPTIONAL + iv_obj_name TYPE tadir-obj_name OPTIONAL + RAISING + zcx_abapgit_exception . + CLASS-METHODS jump_display_user + IMPORTING + !iv_username TYPE syuname + RAISING + zcx_abapgit_exception . + METHODS call_browser + IMPORTING + !iv_url TYPE csequence + RAISING + zcx_abapgit_exception . + METHODS call_transaction + IMPORTING + !iv_tcode TYPE csequence + RAISING + zcx_abapgit_exception . + METHODS get_state_settings + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rv_state) TYPE i . + METHODS get_state_diff + IMPORTING + !ii_event TYPE REF TO zif_abapgit_gui_event + RETURNING + VALUE(rv_state) TYPE i . + METHODS main_page + RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_services_abapgit DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CONSTANTS c_abapgit_repo TYPE string VALUE 'https://github.com/abapGit/abapGit' ##NO_TEXT. + CONSTANTS c_abapgit_homepage TYPE string VALUE 'https://www.abapgit.org' ##NO_TEXT. + CONSTANTS c_abapgit_wikipage TYPE string VALUE 'https://docs.abapgit.org' ##NO_TEXT. + CONSTANTS c_dotabap_homepage TYPE string VALUE 'https://dotabap.org' ##NO_TEXT. + CONSTANTS c_changelog_path TYPE string VALUE '/blob/main/changelog.txt' ##NO_TEXT. + + CLASS-METHODS open_abapgit_homepage + IMPORTING + iv_page TYPE string OPTIONAL + RAISING + zcx_abapgit_exception . + CLASS-METHODS open_abapgit_wikipage + IMPORTING + iv_page TYPE string OPTIONAL + RAISING + zcx_abapgit_exception . + CLASS-METHODS open_dotabap_homepage + RAISING + zcx_abapgit_exception . + CLASS-METHODS open_abapgit_changelog + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_abapgit_tcode + RETURNING + VALUE(rv_tcode) TYPE tcode . + PROTECTED SECTION. + PRIVATE SECTION. + CLASS-METHODS open_url_in_browser + IMPORTING + !iv_url TYPE string + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_services_git DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + CLASS-METHODS pull + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception. + CLASS-METHODS create_branch + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception. + CLASS-METHODS switch_branch + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception. + CLASS-METHODS delete_branch + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception. + CLASS-METHODS delete_tag + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception. + CLASS-METHODS switch_tag + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception. + CLASS-METHODS commit + IMPORTING + !ii_repo_online TYPE REF TO zif_abapgit_repo_online + !is_commit TYPE zif_abapgit_services_git=>ty_commit_fields + !io_stage TYPE REF TO zcl_abapgit_stage + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. +CLASS zcl_abapgit_services_repo DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS new_online + IMPORTING + !is_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params + RETURNING + VALUE(ri_repo_online) TYPE REF TO zif_abapgit_repo_online + RAISING + zcx_abapgit_exception . + CLASS-METHODS refresh + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + CLASS-METHODS remove + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + CLASS-METHODS purge + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + !iv_keep_repo TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + CLASS-METHODS new_offline + IMPORTING + !is_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params + RETURNING + VALUE(ri_repo) TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + CLASS-METHODS refresh_local_checksums + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + CLASS-METHODS toggle_favorite + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RAISING + zcx_abapgit_exception . + CLASS-METHODS transport_to_branch + IMPORTING + !iv_repository_key TYPE zif_abapgit_persistence=>ty_value + RAISING + zcx_abapgit_exception . + CLASS-METHODS gui_deserialize + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + RAISING + zcx_abapgit_exception . + CLASS-METHODS real_deserialize + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks + RAISING + zcx_abapgit_exception . + CLASS-METHODS activate_objects + IMPORTING + !iv_key TYPE zif_abapgit_persistence=>ty_repo-key + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + CLASS-METHODS delete_unnecessary_objects + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + !ii_log TYPE REF TO zif_abapgit_log + !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-METHODS check_package_exists + IMPORTING + !iv_package TYPE devclass + !it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS popup_decisions + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo + CHANGING + !cs_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks + RAISING + zcx_abapgit_cancel + zcx_abapgit_exception . + CLASS-METHODS popup_objects_overwrite + CHANGING + !ct_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS popup_data_loss_overwrite + IMPORTING + !it_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt + CHANGING + !ct_data_loss TYPE zif_abapgit_definitions=>ty_overwrite_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS popup_package_overwrite + CHANGING + !ct_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt + RAISING + zcx_abapgit_exception . + CLASS-METHODS check_package + IMPORTING + !is_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params + RAISING + zcx_abapgit_exception . + CLASS-METHODS check_for_restart + IMPORTING + !ii_repo TYPE REF TO zif_abapgit_repo . +ENDCLASS. +CLASS zcl_abapgit_frontend_no_gui DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_ui_factory. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_frontend_services. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_frontend_services DEFINITION + CREATE PRIVATE + FRIENDS ZCL_abapgit_ui_factory. + PUBLIC SECTION. + + INTERFACES zif_abapgit_frontend_services. + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gv_initial_folder TYPE string. + + METHODS get_path_from_fullname + IMPORTING + iv_fullname TYPE string + RETURNING + VALUE(rv_path) TYPE string. + +ENDCLASS. +CLASS zcl_abapgit_gui_hotkey_ctl DEFINITION + INHERITING FROM zcl_abapgit_gui_component + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + INTERFACES zif_abapgit_gui_hotkeys. + INTERFACES zif_abapgit_gui_hotkey_ctl. + INTERFACES zif_abapgit_gui_renderable. + + CONSTANTS c_showhotkeys_action TYPE string VALUE `showHotkeys` ##NO_TEXT. + + CLASS-METHODS should_show_hint + RETURNING + VALUE(rv_yes) TYPE abap_bool. + METHODS constructor + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + + DATA: + mt_hotkeys TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr, + ms_user_settings TYPE zif_abapgit_persist_user=>ty_s_user_settings, + mv_visible TYPE abap_bool. + CLASS-DATA gv_hint_was_shown TYPE abap_bool . + + METHODS render_scripts + IMPORTING + !it_hotkeys TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . +ENDCLASS. +CLASS zcl_abapgit_password_dialog DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS popup + IMPORTING + !iv_repo_url TYPE string + CHANGING + !cv_user TYPE string + !cv_pass TYPE string + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_popups DEFINITION + FINAL + CREATE PRIVATE + FRIENDS ZCL_abapgit_ui_factory . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_popups . + + CLASS-METHODS center + IMPORTING + !iv_width TYPE i + !iv_height TYPE i + RETURNING + VALUE(rs_position) TYPE zif_abapgit_popups=>ty_popup_position. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + ty_lt_fields TYPE STANDARD TABLE OF sval WITH DEFAULT KEY . + + TYPES: + BEGIN OF ty_commit_value_tab, + commit TYPE zif_abapgit_git_definitions=>ty_sha1, + message TYPE c LENGTH 100, + datetime TYPE c LENGTH 20, + END OF ty_commit_value_tab. + TYPES: + ty_commit_value_tab_tt TYPE STANDARD TABLE OF ty_commit_value_tab WITH DEFAULT KEY. + + CONSTANTS c_answer_cancel TYPE c LENGTH 1 VALUE 'A' ##NO_TEXT. + + DATA ms_position TYPE zif_abapgit_popups=>ty_popup_position. + TYPES ty_sval_tt TYPE STANDARD TABLE OF sval WITH DEFAULT KEY. + + METHODS add_field + IMPORTING + !iv_tabname TYPE sval-tabname + !iv_fieldname TYPE sval-fieldname + !iv_fieldtext TYPE sval-fieldtext + !iv_value TYPE clike DEFAULT '' + !iv_field_attr TYPE sval-field_attr DEFAULT '' + !iv_obligatory TYPE spo_obl OPTIONAL + CHANGING + !ct_fields TYPE ty_sval_tt . + METHODS _popup_3_get_values + IMPORTING + !iv_popup_title TYPE string + !iv_no_value_check TYPE abap_bool DEFAULT abap_false + EXPORTING + !ev_value_1 TYPE spo_value + !ev_value_2 TYPE spo_value + !ev_value_3 TYPE spo_value + CHANGING + !ct_fields TYPE ty_lt_fields + RAISING + zcx_abapgit_exception . + METHODS commit_list_build + IMPORTING + !iv_repo_url TYPE string + !iv_branch_name TYPE string + EXPORTING + !et_value_tab TYPE ty_commit_value_tab_tt + !et_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_ui_factory DEFINITION + CREATE PRIVATE + . + + PUBLIC SECTION. + + CLASS-METHODS get_asset_manager + RETURNING + VALUE(ri_asset_man) TYPE REF TO zif_abapgit_gui_asset_manager + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_popups + RETURNING + VALUE(ri_popups) TYPE REF TO zif_abapgit_popups . + CLASS-METHODS get_gui + RETURNING + VALUE(ro_gui) TYPE REF TO zcl_abapgit_gui + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_gui_services + RETURNING + VALUE(ri_gui_services) TYPE REF TO zif_abapgit_gui_services + RAISING + zcx_abapgit_exception . + CLASS-METHODS get_frontend_services + IMPORTING + !iv_disable_gui TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_fe_serv) TYPE REF TO zif_abapgit_frontend_services . + + PROTECTED SECTION. + PRIVATE SECTION. + + CLASS-DATA gi_popups TYPE REF TO zif_abapgit_popups . + CLASS-DATA go_gui TYPE REF TO zcl_abapgit_gui . + CLASS-DATA gi_fe_services TYPE REF TO zif_abapgit_frontend_services . + CLASS-DATA gi_gui_services TYPE REF TO zif_abapgit_gui_services . +ENDCLASS. +CLASS zcl_abapgit_convert DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS bitbyte_to_int + IMPORTING + !iv_bits TYPE clike + RETURNING + VALUE(rv_int) TYPE i . + CLASS-METHODS x_to_bitbyte + IMPORTING + !iv_x TYPE x + RETURNING + VALUE(rv_bitbyte) TYPE zif_abapgit_git_definitions=>ty_bitbyte . + CLASS-METHODS string_to_xstring_utf8 + IMPORTING + !iv_string TYPE string + RETURNING + VALUE(rv_xstring) TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS xstring_to_string_utf8 + IMPORTING + !iv_data TYPE xsequence + !iv_length TYPE i OPTIONAL + RETURNING + VALUE(rv_string) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS string_to_xstring_utf8_bom + IMPORTING + !iv_string TYPE string + RETURNING + VALUE(rv_xstring) TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS xstring_to_string_utf8_bom + IMPORTING + !iv_xstring TYPE xstring + RETURNING + VALUE(rv_string) TYPE string + RAISING + zcx_abapgit_exception . + CLASS-METHODS xstring_to_int + IMPORTING + !iv_xstring TYPE xstring + RETURNING + VALUE(rv_i) TYPE i + RAISING + zcx_abapgit_exception . + CLASS-METHODS int_to_xstring4 + IMPORTING + !iv_i TYPE i + RETURNING + VALUE(rv_xstring) TYPE xstring . + CLASS-METHODS split_string + IMPORTING + !iv_string TYPE string + RETURNING + VALUE(rt_lines) TYPE string_table . + CLASS-METHODS conversion_exit_isola_output + IMPORTING + !iv_spras TYPE spras + RETURNING + VALUE(rv_spras) TYPE laiso . + CLASS-METHODS string_to_xstring + IMPORTING + !iv_str TYPE string + RETURNING + VALUE(rv_xstr) TYPE xstring + RAISING + zcx_abapgit_exception . + CLASS-METHODS string_to_tab + IMPORTING + !iv_str TYPE string + EXPORTING + !ev_size TYPE i + !et_tab TYPE STANDARD TABLE . + CLASS-METHODS base64_to_xstring + IMPORTING + !iv_base64 TYPE string + RETURNING + VALUE(rv_xstr) TYPE xstring . + CLASS-METHODS xstring_to_bintab + IMPORTING + !iv_xstr TYPE xsequence + EXPORTING + !ev_size TYPE i + !et_bintab TYPE STANDARD TABLE . + + CLASS-METHODS language_sap1_to_sap2 + IMPORTING + im_lang_sap1 TYPE sy-langu + RETURNING + VALUE(re_lang_sap2) TYPE string + EXCEPTIONS + no_assignment. + + CLASS-METHODS language_sap1_to_text + IMPORTING + im_lang_sap1 TYPE sy-langu + RETURNING + VALUE(re_text) TYPE string. + + CLASS-METHODS language_sap2_to_sap1 + IMPORTING + im_lang_sap2 TYPE laiso + RETURNING + VALUE(re_lang_sap1) TYPE sy-langu + EXCEPTIONS + no_assignment. + + CLASS-METHODS language_sap1_to_bcp47 + IMPORTING + im_lang_sap1 TYPE sy-langu + RETURNING + VALUE(re_lang_bcp47) TYPE string + EXCEPTIONS + no_assignment. + + CLASS-METHODS language_bcp47_to_sap1 + IMPORTING + im_lang_bcp47 TYPE string + RETURNING + VALUE(re_lang_sap1) TYPE sy-langu + EXCEPTIONS + no_assignment. + + TYPES ty_char02 TYPE c LENGTH 2. + CLASS-METHODS uccp + IMPORTING + iv_uccp TYPE string + RETURNING + VALUE(rv_char) TYPE ty_char02 + EXCEPTIONS + no_assignment. + + PROTECTED SECTION. + PRIVATE SECTION. + CLASS-METHODS xstring_remove_bom + IMPORTING + iv_xstr TYPE xsequence + RETURNING + VALUE(rv_xstr) TYPE xstring. +ENDCLASS. +CLASS zcl_abapgit_log DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_log . + + METHODS constructor + IMPORTING + iv_title TYPE string OPTIONAL. + + CLASS-METHODS from_exception + IMPORTING + io_x TYPE REF TO cx_root + RETURNING + VALUE(ro_log) TYPE REF TO zcl_abapgit_log. + + PROTECTED SECTION. + + TYPES: + BEGIN OF ty_log, "in order of occurrence + msg TYPE zif_abapgit_log=>ty_msg, + item TYPE zif_abapgit_definitions=>ty_item, + exception TYPE REF TO cx_root, + END OF ty_log . + + DATA: + mt_log TYPE STANDARD TABLE OF ty_log WITH DEFAULT KEY . + DATA mv_title TYPE string . + + METHODS get_messages_status + IMPORTING + !it_msg TYPE zif_abapgit_log=>ty_msgs + RETURNING + VALUE(rv_status) TYPE sy-msgty . + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_path DEFINITION FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CLASS-METHODS split_file_location + IMPORTING iv_fullpath TYPE string + EXPORTING ev_path TYPE string + ev_filename TYPE string. + + CLASS-METHODS is_root + IMPORTING iv_path TYPE string + RETURNING VALUE(rv_yes) TYPE abap_bool. + + CLASS-METHODS is_subdir + IMPORTING iv_path TYPE string + iv_parent TYPE string + RETURNING VALUE(rv_yes) TYPE abap_bool. + + CLASS-METHODS change_dir + IMPORTING iv_cur_dir TYPE string + iv_cd TYPE string + RETURNING VALUE(rv_path) TYPE string. + + CLASS-METHODS get_filename_from_syspath + IMPORTING iv_path TYPE string + RETURNING VALUE(rv_filename) TYPE string. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_string_buffer DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS new + RETURNING + VALUE(ro_me) TYPE REF TO zcl_abapgit_string_buffer. + METHODS add + IMPORTING + !iv_str TYPE string + RETURNING + VALUE(ro_me) TYPE REF TO zcl_abapgit_string_buffer. + METHODS join_and_flush + RETURNING + VALUE(rv_str) TYPE string. + METHODS join_w_newline_and_flush + RETURNING + VALUE(rv_str) TYPE string. + METHODS join_w_space_and_flush + RETURNING + VALUE(rv_str) TYPE string. + + PROTECTED SECTION. + PRIVATE SECTION. + DATA mt_buffer TYPE string_table. +ENDCLASS. +CLASS zcl_abapgit_string_map DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_entry, + k TYPE string, + v TYPE string, + END OF ty_entry . + TYPES: + ty_entries TYPE SORTED TABLE OF ty_entry WITH UNIQUE KEY k . + + DATA mt_entries TYPE ty_entries READ-ONLY . + + CLASS-METHODS create + IMPORTING + !iv_case_insensitive TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_string_map . + METHODS constructor + IMPORTING + !iv_case_insensitive TYPE abap_bool DEFAULT abap_false . + METHODS get + IMPORTING + !iv_key TYPE string + RETURNING + VALUE(rv_val) TYPE string . + METHODS has + IMPORTING + !iv_key TYPE string + RETURNING + VALUE(rv_has) TYPE abap_bool . + METHODS set + IMPORTING + !iv_key TYPE string + !iv_val TYPE csequence OPTIONAL + RETURNING + VALUE(ro_map) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + METHODS size + RETURNING + VALUE(rv_size) TYPE i . + METHODS is_empty + RETURNING + VALUE(rv_yes) TYPE abap_bool . + METHODS delete + IMPORTING + !iv_key TYPE string + RAISING + zcx_abapgit_exception . + METHODS clear + RAISING + zcx_abapgit_exception . + METHODS to_abap + CHANGING + !cs_container TYPE any + RAISING + zcx_abapgit_exception . + METHODS strict + IMPORTING + !iv_strict TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_string_map . + METHODS freeze . + METHODS merge + IMPORTING + !io_string_map TYPE REF TO zcl_abapgit_string_map + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + DATA mv_read_only TYPE abap_bool. + DATA mv_is_strict TYPE abap_bool. + DATA mv_case_insensitive TYPE abap_bool. + +ENDCLASS. +CLASS zcl_abapgit_timer DEFINITION + FINAL + CREATE PRIVATE. + + PUBLIC SECTION. + + CLASS-METHODS create + IMPORTING + !iv_text TYPE string OPTIONAL + !iv_count TYPE i OPTIONAL + PREFERRED PARAMETER iv_text + RETURNING + VALUE(ro_timer) TYPE REF TO zcl_abapgit_timer. + + METHODS constructor + IMPORTING + !iv_text TYPE string OPTIONAL + !iv_count TYPE i OPTIONAL. + + METHODS start + RETURNING + VALUE(ro_timer) TYPE REF TO zcl_abapgit_timer. + + METHODS end + IMPORTING + !iv_output_as_status_message TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rv_result) TYPE string. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mv_text TYPE string. + DATA mv_count TYPE i. + DATA mv_timer TYPE timestampl. + +ENDCLASS. +CLASS zcl_abapgit_utils DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS is_binary + IMPORTING + !iv_data TYPE xstring + RETURNING + VALUE(rv_is_binary) TYPE abap_bool. + CLASS-METHODS is_valid_email + IMPORTING + iv_email TYPE string + RETURNING + VALUE(rv_valid) TYPE abap_bool. + CLASS-METHODS check_eol + IMPORTING + !iv_data TYPE string + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_abapgit_xml DEFINITION + ABSTRACT + CREATE PUBLIC . + + PUBLIC SECTION. + METHODS: + constructor + IMPORTING iv_filename TYPE string OPTIONAL. + PROTECTED SECTION. + DATA: mi_ixml TYPE REF TO if_ixml, + mi_xml_doc TYPE REF TO if_ixml_document, + ms_metadata TYPE zif_abapgit_definitions=>ty_metadata, + mv_filename TYPE string. + + CONSTANTS: c_abapgit_tag TYPE string VALUE 'abapGit' ##NO_TEXT, + c_attr_version TYPE string VALUE 'version' ##NO_TEXT, + c_attr_serializer TYPE string VALUE 'serializer' ##NO_TEXT, + c_attr_serializer_version TYPE string VALUE 'serializer_version' ##NO_TEXT. + + METHODS to_xml + IMPORTING iv_normalize TYPE abap_bool DEFAULT abap_true + RETURNING VALUE(rv_xml) TYPE string. + + METHODS parse + IMPORTING iv_xml TYPE string + RAISING zcx_abapgit_exception. + PRIVATE SECTION. + + METHODS error + IMPORTING + !ii_parser TYPE REF TO if_ixml_parser + RAISING + zcx_abapgit_exception . + METHODS raise_version_mismatch + IMPORTING + !iv_vers TYPE string + RAISING + zcx_abapgit_exception . + METHODS raise_exception_for + IMPORTING + !ii_error TYPE REF TO if_ixml_parse_error + RAISING + zcx_abapgit_exception . +ENDCLASS. +CLASS zcl_abapgit_xml_input DEFINITION + INHERITING FROM zcl_abapgit_xml + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_xml_input. + + METHODS constructor + IMPORTING + !iv_xml TYPE clike + !iv_filename TYPE string OPTIONAL + RAISING + zcx_abapgit_exception . + + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS fix_xml. + +ENDCLASS. +CLASS zcl_abapgit_xml_output DEFINITION + INHERITING FROM zcl_abapgit_xml + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES zif_abapgit_xml_output. + + PROTECTED SECTION. + PRIVATE SECTION. + + DATA mi_raw TYPE REF TO if_ixml_element . + + METHODS build_asx_node + RETURNING + VALUE(ri_element) TYPE REF TO if_ixml_element . +ENDCLASS. +CLASS zcl_abapgit_xml_pretty DEFINITION + CREATE PUBLIC . + + PUBLIC SECTION. + + CLASS-METHODS print + IMPORTING + !iv_xml TYPE string + !iv_ignore_errors TYPE abap_bool DEFAULT abap_true + !iv_unpretty TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rv_xml) TYPE string + RAISING + zcx_abapgit_exception . + PROTECTED SECTION. + PRIVATE SECTION. + CLASS-METHODS raise_error + IMPORTING + ii_parser TYPE REF TO if_ixml_parser + RAISING + zcx_abapgit_exception. +ENDCLASS. +CLASS zcl_abapgit_factory DEFINITION + CREATE PRIVATE + . + + PUBLIC SECTION. + + CLASS-METHODS get_tadir + RETURNING + VALUE(ri_tadir) TYPE REF TO zif_abapgit_tadir . + CLASS-METHODS get_sap_package + IMPORTING + !iv_package TYPE devclass + RETURNING + VALUE(ri_sap_package) TYPE REF TO zif_abapgit_sap_package . + CLASS-METHODS get_cts_api + RETURNING + VALUE(ri_cts_api) TYPE REF TO zif_abapgit_cts_api . + CLASS-METHODS get_default_transport + RETURNING + VALUE(ri_default_transport) TYPE REF TO zif_abapgit_default_transport. + CLASS-METHODS get_environment + RETURNING + VALUE(ri_environment) TYPE REF TO zif_abapgit_environment . + CLASS-METHODS get_longtexts + RETURNING + VALUE(ri_longtexts) TYPE REF TO zif_abapgit_longtexts . + CLASS-METHODS get_lxe_texts + RETURNING + VALUE(ri_lxe_texts) TYPE REF TO zif_abapgit_lxe_texts . + CLASS-METHODS get_sap_namespace + RETURNING + VALUE(ri_namespace) TYPE REF TO zif_abapgit_sap_namespace . + CLASS-METHODS get_sap_report + RETURNING + VALUE(ri_report) TYPE REF TO zif_abapgit_sap_report. + CLASS-METHODS get_function_module + RETURNING + VALUE(ri_function_module) TYPE REF TO zif_abapgit_function_module. + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_sap_package, + package TYPE devclass, + instance TYPE REF TO zif_abapgit_sap_package, + END OF ty_sap_package . + TYPES: + ty_sap_packages TYPE HASHED TABLE OF ty_sap_package + WITH UNIQUE KEY package . + + CLASS-DATA gi_tadir TYPE REF TO zif_abapgit_tadir . + CLASS-DATA gt_sap_package TYPE ty_sap_packages . + CLASS-DATA gi_cts_api TYPE REF TO zif_abapgit_cts_api . + CLASS-DATA gi_environment TYPE REF TO zif_abapgit_environment . + CLASS-DATA gi_longtext TYPE REF TO zif_abapgit_longtexts . + CLASS-DATA gi_lxe_texts TYPE REF TO zif_abapgit_lxe_texts . + CLASS-DATA gi_sap_namespace TYPE REF TO zif_abapgit_sap_namespace . + CLASS-DATA gi_sap_report TYPE REF TO zif_abapgit_sap_report. + CLASS-DATA gi_function_module TYPE REF TO zif_abapgit_function_module. + CLASS-DATA gi_default_transport TYPE REF TO zif_abapgit_default_transport . +ENDCLASS. +CLASS zcl_abapgit_factory IMPLEMENTATION. + METHOD get_cts_api. + IF gi_cts_api IS NOT BOUND. + CREATE OBJECT gi_cts_api TYPE zcl_abapgit_cts_api. + ENDIF. + + ri_cts_api = gi_cts_api. + ENDMETHOD. + METHOD get_default_transport. + + IF gi_default_transport IS NOT BOUND. + CREATE OBJECT gi_default_transport TYPE zcl_abapgit_default_transport. + ENDIF. + + ri_default_transport = gi_default_transport. + + ENDMETHOD. + METHOD get_environment. + IF gi_environment IS NOT BOUND. + CREATE OBJECT gi_environment TYPE zcl_abapgit_environment. + ENDIF. + ri_environment = gi_environment. + ENDMETHOD. + METHOD get_function_module. + + IF gi_function_module IS INITIAL. + CREATE OBJECT gi_function_module TYPE zcl_abapgit_function_module. + ENDIF. + + ri_function_module = gi_function_module. + + ENDMETHOD. + METHOD get_longtexts. + + IF gi_longtext IS NOT BOUND. + CREATE OBJECT gi_longtext TYPE zcl_abapgit_longtexts. + ENDIF. + ri_longtexts = gi_longtext. + + ENDMETHOD. + METHOD get_lxe_texts. + + IF gi_lxe_texts IS NOT BOUND. + CREATE OBJECT gi_lxe_texts TYPE zcl_abapgit_lxe_texts. + ENDIF. + ri_lxe_texts = gi_lxe_texts. + + ENDMETHOD. + METHOD get_sap_namespace. + + IF gi_sap_namespace IS NOT BOUND. + CREATE OBJECT gi_sap_namespace TYPE zcl_abapgit_sap_namespace. + ENDIF. + + ri_namespace = gi_sap_namespace. + + ENDMETHOD. + METHOD get_sap_package. + + DATA ls_sap_package TYPE ty_sap_package. + FIELD-SYMBOLS TYPE ty_sap_package. + + ASSERT iv_package IS NOT INITIAL. + + READ TABLE gt_sap_package ASSIGNING + WITH TABLE KEY package = iv_package. + IF sy-subrc <> 0. + + ls_sap_package-package = iv_package. + CREATE OBJECT ls_sap_package-instance TYPE zcl_abapgit_sap_package + EXPORTING + iv_package = iv_package. + + INSERT ls_sap_package + INTO TABLE gt_sap_package + ASSIGNING . + + ENDIF. + + ri_sap_package = -instance. + + ENDMETHOD. + METHOD get_sap_report. + + IF gi_sap_report IS NOT BOUND. + CREATE OBJECT gi_sap_report TYPE zcl_abapgit_sap_report. + ENDIF. + + ri_report = gi_sap_report. + + ENDMETHOD. + METHOD get_tadir. + + IF gi_tadir IS INITIAL. + CREATE OBJECT gi_tadir TYPE zcl_abapgit_tadir. + ENDIF. + + ri_tadir = gi_tadir. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_xml_pretty IMPLEMENTATION. + METHOD print. + + DATA: li_ixml TYPE REF TO if_ixml, + li_xml_doc TYPE REF TO if_ixml_document, + li_stream_factory TYPE REF TO if_ixml_stream_factory, + li_istream TYPE REF TO if_ixml_istream, + li_parser TYPE REF TO if_ixml_parser, + lv_xstring TYPE xstring, + li_encoding TYPE REF TO if_ixml_encoding, + li_ostream TYPE REF TO if_ixml_ostream, + li_renderer TYPE REF TO if_ixml_renderer. + ASSERT NOT iv_xml IS INITIAL. + + li_ixml = cl_ixml=>create( ). + li_xml_doc = li_ixml->create_document( ). + + li_stream_factory = li_ixml->create_stream_factory( ). + li_istream = li_stream_factory->create_istream_xstring( + zcl_abapgit_convert=>string_to_xstring_utf8( iv_xml ) ). + li_parser = li_ixml->create_parser( stream_factory = li_stream_factory + istream = li_istream + document = li_xml_doc ). + li_parser->set_normalizing( abap_true ). + IF li_parser->parse( ) <> 0. + IF iv_ignore_errors = abap_true. + rv_xml = iv_xml. + RETURN. + ELSE. + raise_error( li_parser ). + ENDIF. + ENDIF. + li_ostream = li_stream_factory->create_ostream_xstring( lv_xstring ). + + li_encoding = li_ixml->create_encoding( + character_set = 'utf-8' + byte_order = if_ixml_encoding=>co_big_endian ). + + li_xml_doc->set_encoding( li_encoding ). + li_renderer = li_ixml->create_renderer( ostream = li_ostream + document = li_xml_doc ). + + li_renderer->set_normalizing( boolc( iv_unpretty = abap_false ) ). + + li_renderer->render( ). + + rv_xml = zcl_abapgit_convert=>xstring_to_string_utf8_bom( lv_xstring ). + REPLACE FIRST OCCURRENCE OF 'utf-8' IN rv_xml WITH 'utf-16'. + + ENDMETHOD. + METHOD raise_error. + + DATA: + lv_num_errors TYPE i, + li_error TYPE REF TO if_ixml_parse_error, + lv_reason TYPE string. + + lv_num_errors = ii_parser->num_errors( ). + + DO lv_num_errors TIMES. + + li_error = ii_parser->get_error( + index = sy-index + min_severity = if_ixml_parse_error=>co_info ). + + IF li_error IS BOUND. + lv_reason = li_error->get_reason( ). + ENDIF. + + IF lv_reason IS NOT INITIAL. + EXIT. + ENDIF. + + ENDDO. + + IF lv_reason IS NOT INITIAL. + zcx_abapgit_exception=>raise( lv_reason ). + ELSE. + zcx_abapgit_exception=>raise( 'error parsing xml' ). + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +CLASS ZCL_ABAPGIT_XML_OUTPUT IMPLEMENTATION. + METHOD build_asx_node. + + DATA: li_attr TYPE REF TO if_ixml_attribute. + ri_element = mi_xml_doc->create_element_ns( + name = 'abap' + prefix = 'asx' ). + + li_attr = mi_xml_doc->create_attribute_ns( 'version' ). + li_attr->if_ixml_node~set_value( '1.0' ). + ri_element->set_attribute_node_ns( li_attr ). + + li_attr = mi_xml_doc->create_attribute_ns( + name = 'asx' + prefix = 'xmlns' ). + li_attr->if_ixml_node~set_value( 'http://www.sap.com/abapxml' ). + ri_element->set_attribute_node_ns( li_attr ). + + ENDMETHOD. + METHOD zif_abapgit_xml_output~add. + + DATA: li_node TYPE REF TO if_ixml_node, + li_doc TYPE REF TO if_ixml_document, + lt_stab TYPE abap_trans_srcbind_tab. + + FIELD-SYMBOLS: LIKE LINE OF lt_stab. + ASSERT NOT iv_name IS INITIAL. + + IF ig_data IS INITIAL. + RETURN. + ENDIF. + + APPEND INITIAL LINE TO lt_stab ASSIGNING . + -name = iv_name. + GET REFERENCE OF ig_data INTO -value. + + li_doc = cl_ixml=>create( )->create_document( ). + + CALL TRANSFORMATION id + OPTIONS initial_components = 'suppress' + SOURCE (lt_stab) + RESULT XML li_doc. + + li_node = mi_xml_doc->get_root( )->get_first_child( ). + IF li_node IS BOUND. + mi_xml_doc->get_root( )->get_first_child( )->get_first_child( )->append_child( + li_doc->get_root( )->get_first_child( )->get_first_child( )->get_first_child( ) ). + ELSE. + mi_xml_doc->get_root( )->append_child( li_doc->get_root( )->get_first_child( ) ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_xml_output~add_xml. + + DATA: li_element TYPE REF TO if_ixml_element. + + li_element = mi_xml_doc->create_element( iv_name ). + li_element->append_child( ii_xml ). + + mi_xml_doc->get_root( )->get_first_child( )->get_first_child( )->append_child( li_element ). + + ENDMETHOD. + METHOD zif_abapgit_xml_output~render. + + DATA: li_git TYPE REF TO if_ixml_element, + li_abap TYPE REF TO if_ixml_element. + IF mi_raw IS INITIAL. + li_abap ?= mi_xml_doc->get_root( )->get_first_child( ). + mi_xml_doc->get_root( )->remove_child( li_abap ). + IF li_abap IS INITIAL. + li_abap = build_asx_node( ). + ENDIF. + ELSE. + li_abap = mi_raw. + ENDIF. + + li_git = mi_xml_doc->create_element( c_abapgit_tag ). + li_git->set_attribute( name = c_attr_version + value = zif_abapgit_version=>c_xml_version ). + IF NOT is_metadata IS INITIAL. + li_git->set_attribute( name = c_attr_serializer + value = is_metadata-class ). + li_git->set_attribute( name = c_attr_serializer_version + value = is_metadata-version ). + ENDIF. + li_git->append_child( li_abap ). + mi_xml_doc->get_root( )->append_child( li_git ). + + rv_xml = to_xml( iv_normalize ). + + ENDMETHOD. + METHOD zif_abapgit_xml_output~set_raw. + mi_raw = ii_raw. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_XML_INPUT IMPLEMENTATION. + METHOD constructor. + + super->constructor( iv_filename ). + parse( iv_xml ). + fix_xml( ). + + ENDMETHOD. + METHOD fix_xml. + + DATA: li_git TYPE REF TO if_ixml_element, + li_abap TYPE REF TO if_ixml_node. + li_git ?= mi_xml_doc->find_from_name_ns( depth = 0 + name = c_abapgit_tag ). + li_abap = li_git->get_first_child( ). + + mi_xml_doc->get_root( )->remove_child( li_git ). + mi_xml_doc->get_root( )->append_child( li_abap ). + + ENDMETHOD. + METHOD zif_abapgit_xml_input~get_metadata. + rs_metadata = ms_metadata. + ENDMETHOD. + METHOD zif_abapgit_xml_input~get_raw. + ri_raw = mi_xml_doc. + ENDMETHOD. + METHOD zif_abapgit_xml_input~read. + + DATA: lx_error TYPE REF TO cx_transformation_error, + lt_rtab TYPE abap_trans_resbind_tab. + + FIELD-SYMBOLS: LIKE LINE OF lt_rtab. + + ASSERT NOT iv_name IS INITIAL. + + CLEAR cg_data. "Initialize result to avoid problems with empty values + + APPEND INITIAL LINE TO lt_rtab ASSIGNING . + -name = iv_name. + GET REFERENCE OF cg_data INTO -value. + + TRY. + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML mi_xml_doc + RESULT (lt_rtab). + CATCH cx_transformation_error INTO lx_error. + IF mv_filename IS INITIAL. + zcx_abapgit_exception=>raise( lx_error->if_message~get_text( ) ). + ELSE. + zcx_abapgit_exception=>raise( |File { mv_filename }: { lx_error->if_message~get_text( ) }| ). + ENDIF. + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_xml IMPLEMENTATION. + METHOD constructor. + mi_ixml = cl_ixml=>create( ). + mi_xml_doc = mi_ixml->create_document( ). + mv_filename = iv_filename. + ENDMETHOD. + METHOD error. + + IF ii_parser->num_errors( ) <> 0. + raise_exception_for( ii_parser->get_error( 0 ) ). + ENDIF. + + IF mv_filename IS INITIAL. + zcx_abapgit_exception=>raise( |Error while parsing XML| ). + ELSE. + zcx_abapgit_exception=>raise( |Error while parsing XML file { mv_filename }| ). + ENDIF. + + ENDMETHOD. + METHOD parse. + + DATA: li_stream_factory TYPE REF TO if_ixml_stream_factory, + li_istream TYPE REF TO if_ixml_istream, + li_element TYPE REF TO if_ixml_element, + li_version TYPE REF TO if_ixml_node, + li_parser TYPE REF TO if_ixml_parser. + ASSERT NOT iv_xml IS INITIAL. + + li_stream_factory = mi_ixml->create_stream_factory( ). + li_istream = li_stream_factory->create_istream_string( iv_xml ). + li_parser = mi_ixml->create_parser( stream_factory = li_stream_factory + istream = li_istream + document = mi_xml_doc ). + li_parser->add_strip_space_element( ). + IF li_parser->parse( ) <> 0. + error( li_parser ). + ENDIF. + + li_istream->close( ). + li_element = mi_xml_doc->find_from_name_ns( depth = 0 + name = c_abapgit_tag ). + li_version = li_element->if_ixml_node~get_attributes( + )->get_named_item_ns( c_attr_version ). + IF li_version->get_value( ) <> zif_abapgit_version=>c_xml_version. + raise_version_mismatch( li_version->get_value( ) ). + ENDIF. + +* buffer serializer metadata. Git node will be removed lateron + ms_metadata-class = li_element->get_attribute_ns( c_attr_serializer ). + ms_metadata-version = li_element->get_attribute_ns( c_attr_serializer_version ). + + ENDMETHOD. + METHOD raise_exception_for. + DATA lv_message TYPE string. + + lv_message = |XML parser error: { ii_error->get_reason( ) }, | && + |Line { ii_error->get_line( ) } | && + |Col. { ii_error->get_column( ) }|. + + IF mv_filename IS NOT INITIAL. + lv_message = lv_message && | File { mv_filename }|. + ENDIF. + + zcx_abapgit_exception=>raise( lv_message ). + + ENDMETHOD. + METHOD raise_version_mismatch. + + DATA lv_text TYPE string. + + lv_text = |The XML versions do not match, expected: { zif_abapgit_version=>c_xml_version }, actual: { iv_vers }|. + + IF mv_filename IS NOT INITIAL. + lv_text = lv_text && |, file: { mv_filename }|. + ENDIF. + + lv_text = lv_text && | (see https://docs.abapgit.org/other-xml-mismatch.html)|. + + zcx_abapgit_exception=>raise( lv_text ). + + ENDMETHOD. + METHOD to_xml. +* will render to codepage UTF-16 + + DATA: li_ostream TYPE REF TO if_ixml_ostream, + li_renderer TYPE REF TO if_ixml_renderer, + li_streamfactory TYPE REF TO if_ixml_stream_factory. + + li_streamfactory = mi_ixml->create_stream_factory( ). + + li_ostream = li_streamfactory->create_ostream_cstring( rv_xml ). + + li_renderer = mi_ixml->create_renderer( ostream = li_ostream + document = mi_xml_doc ). + li_renderer->set_normalizing( iv_normalize ). + + li_renderer->render( ). + + " handling of BOM moved to zcl_abapgit_convert=>string_to_xstring_utf8_bom + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_utils IMPLEMENTATION. + METHOD check_eol. + + " Check if data is using CRLF as EOL separator. If only LF is used, data was likely + " edited by external tools + IF iv_data IS NOT INITIAL AND + iv_data CS cl_abap_char_utilities=>newline AND + iv_data NS cl_abap_char_utilities=>cr_lf. + zcx_abapgit_exception=>raise( 'Incorrect source format: Requires CRLF instead of LF' ). + ENDIF. + + ENDMETHOD. + METHOD is_binary. + + " Previously we did a simple char range test described here + " stackoverflow.com/questions/277521/how-to-identify-the-file-content-as-ascii-or-binary + " but this is insufficient if the data contains German umlauts and other special characters. + " Therefore we adopted another algorithm, which is similarly used by AL11 + " RSWATCH0 / GUESS_FILE_TYPE + " We count non-printable characters if there are more than XX% it's binary. + + CONSTANTS: + lc_binary_threshold TYPE i VALUE 10, + lc_bytes_to_check TYPE i VALUE 1000. + + DATA: lv_string_data TYPE string, + lv_printable_chars_count TYPE i, + lv_percentage TYPE i, + lv_data TYPE xstring, + lv_xlen TYPE i. + + lv_xlen = xstrlen( iv_data ). + IF lv_xlen = 0. + RETURN. + ENDIF. + + lv_xlen = nmin( + val1 = lv_xlen + val2 = lc_bytes_to_check ). + + lv_data = iv_data(lv_xlen). + + TRY. + lv_string_data = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). + CATCH zcx_abapgit_exception. + " Contains data that does not convert to UTF-8 so consider it binary + rv_is_binary = abap_true. + RETURN. + ENDTRY. + + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN lv_string_data WITH space. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_string_data WITH space. + + FIND ALL OCCURRENCES OF REGEX '[^[:print:]]' IN lv_string_data MATCH COUNT lv_printable_chars_count. + lv_percentage = lv_printable_chars_count * 100 / strlen( lv_string_data ). + rv_is_binary = boolc( lv_percentage > lc_binary_threshold ). + + ENDMETHOD. + METHOD is_valid_email. + + " Email address validation (RFC 5322) + " https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s01.html + CONSTANTS lc_email_regex TYPE string VALUE + '[\w!#$%&*+/=?`{|}~^-]+(?:\.[\w!#$%&*+/=?`{|}~^-]+)*@(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,6}'. + + IF iv_email IS INITIAL. + rv_valid = abap_true. + ELSE. + FIND REGEX lc_email_regex IN iv_email. + rv_valid = boolc( sy-subrc = 0 ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_timer IMPLEMENTATION. + METHOD constructor. + mv_text = iv_text. + mv_count = iv_count. + ENDMETHOD. + METHOD create. + CREATE OBJECT ro_timer + EXPORTING + iv_text = iv_text + iv_count = iv_count. + ENDMETHOD. + METHOD end. + + DATA: + lv_timestamp TYPE timestampl, + lv_runtime TYPE timestampl, + lv_sec TYPE p LENGTH 11 DECIMALS 2. + + IF mv_timer IS INITIAL. + rv_result = 'Runtime measurement has not been started'. + ELSE. + GET TIME STAMP FIELD lv_timestamp. + + TRY. + lv_runtime = cl_abap_tstmp=>subtract( + tstmp1 = lv_timestamp + tstmp2 = mv_timer ). + + lv_sec = lv_runtime. " round to 2 decimal places + + IF mv_count = 1. + rv_result = |1 object, |. + ELSEIF mv_count > 1. + rv_result = |{ mv_count } objects, |. + ENDIF. + + rv_result = rv_result && |{ lv_sec } seconds|. + + CATCH cx_parameter_invalid. + rv_result = 'Error getting runtime measurement'. + ENDTRY. + ENDIF. + + IF iv_output_as_status_message = abap_true. + MESSAGE s000(oo) WITH mv_text rv_result. + ENDIF. + + IF mv_text IS NOT INITIAL. + rv_result = |{ mv_text } { rv_result }|. + ENDIF. + + ENDMETHOD. + METHOD start. + GET TIME STAMP FIELD mv_timer. + ro_timer = me. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_STRING_MAP IMPLEMENTATION. + METHOD clear. + IF mv_read_only = abap_true. + zcx_abapgit_exception=>raise( 'Cannot clear. This string map is immutable' ). + ENDIF. + CLEAR mt_entries. + ENDMETHOD. + METHOD constructor. + mv_is_strict = abap_true. + mv_case_insensitive = iv_case_insensitive. + ENDMETHOD. + METHOD create. + CREATE OBJECT ro_instance + EXPORTING + iv_case_insensitive = iv_case_insensitive. + ENDMETHOD. + METHOD delete. + + IF mv_read_only = abap_true. + zcx_abapgit_exception=>raise( 'Cannot delete. This string map is immutable' ). + ENDIF. + + DELETE mt_entries WHERE k = iv_key. + + ENDMETHOD. + METHOD freeze. + mv_read_only = abap_true. + ENDMETHOD. + METHOD get. + + DATA lv_key LIKE iv_key. + FIELD-SYMBOLS LIKE LINE OF mt_entries. + + IF mv_case_insensitive = abap_true. + lv_key = to_upper( iv_key ). + ELSE. + lv_key = iv_key. + ENDIF. + + READ TABLE mt_entries ASSIGNING WITH KEY k = lv_key. + IF sy-subrc IS INITIAL. + rv_val = -v. + ENDIF. + + ENDMETHOD. + METHOD has. + + READ TABLE mt_entries TRANSPORTING NO FIELDS WITH KEY k = iv_key. + rv_has = boolc( sy-subrc IS INITIAL ). + + ENDMETHOD. + METHOD is_empty. + rv_yes = boolc( lines( mt_entries ) = 0 ). + ENDMETHOD. + METHOD merge. + + FIELD-SYMBOLS LIKE LINE OF mt_entries. + + LOOP AT io_string_map->mt_entries ASSIGNING . + set( + iv_key = -k + iv_val = -v ). + ENDLOOP. + + ro_instance = me. + + ENDMETHOD. + METHOD set. + + DATA lv_key LIKE iv_key. + DATA ls_entry LIKE LINE OF mt_entries. + FIELD-SYMBOLS LIKE LINE OF mt_entries. + + IF mv_read_only = abap_true. + zcx_abapgit_exception=>raise( 'Cannot set. This string map is immutable' ). + ENDIF. + + IF mv_case_insensitive = abap_true. + lv_key = to_upper( iv_key ). + ELSE. + lv_key = iv_key. + ENDIF. + + READ TABLE mt_entries ASSIGNING WITH KEY k = lv_key. + IF sy-subrc IS INITIAL. + -v = iv_val. + ELSE. + ls_entry-k = lv_key. + ls_entry-v = iv_val. + INSERT ls_entry INTO TABLE mt_entries. + ENDIF. + + ro_map = me. + + ENDMETHOD. + METHOD size. + + rv_size = lines( mt_entries ). + + ENDMETHOD. + METHOD strict. + mv_is_strict = iv_strict. + ro_instance = me. + ENDMETHOD. + METHOD to_abap. + + DATA lo_type TYPE REF TO cl_abap_typedescr. + DATA lv_field TYPE string. + FIELD-SYMBOLS LIKE LINE OF mt_entries. + FIELD-SYMBOLS TYPE any. + + lo_type = cl_abap_typedescr=>describe_by_data( cs_container ). + IF lo_type->type_kind <> cl_abap_typedescr=>typekind_struct1 + AND lo_type->type_kind <> cl_abap_typedescr=>typekind_struct2. + zcx_abapgit_exception=>raise( 'Only structures supported' ). + ENDIF. + + LOOP AT mt_entries ASSIGNING . + lv_field = to_upper( -k ). + ASSIGN COMPONENT lv_field OF STRUCTURE cs_container TO . + IF sy-subrc = 0. + " TODO check target type ? + = -v. + ELSEIF mv_is_strict = abap_false. + CONTINUE. + ELSE. + zcx_abapgit_exception=>raise( |Component { lv_field } not found in target| ). + ENDIF. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_STRING_BUFFER IMPLEMENTATION. + METHOD add. + APPEND iv_str TO mt_buffer. + ro_me = me. + ENDMETHOD. + METHOD join_and_flush. + rv_str = concat_lines_of( mt_buffer ). + CLEAR mt_buffer. + ENDMETHOD. + METHOD join_w_newline_and_flush. + rv_str = concat_lines_of( + table = mt_buffer + sep = cl_abap_char_utilities=>newline ). + CLEAR mt_buffer. + ENDMETHOD. + METHOD join_w_space_and_flush. + rv_str = concat_lines_of( + table = mt_buffer + sep = ` ` ). + CLEAR mt_buffer. + ENDMETHOD. + METHOD new. + CREATE OBJECT ro_me. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_PATH IMPLEMENTATION. + METHOD change_dir. + + DATA: lv_last TYPE i, + lv_temp TYPE string. + + lv_last = strlen( iv_cur_dir ) - 1. + + IF iv_cd = '' OR iv_cd = '.'. " No change + rv_path = iv_cur_dir. + ELSEIF iv_cd+0(1) = '/'. " Absolute path + rv_path = iv_cd. + ELSEIF iv_cd = '..'. " CD back + IF iv_cur_dir = '/' OR iv_cur_dir = ''. " Back from root = root + rv_path = iv_cur_dir. + ELSE. + lv_temp = reverse( iv_cur_dir ). + IF lv_temp+0(1) = '/'. + SHIFT lv_temp BY 1 PLACES LEFT. + ENDIF. + SHIFT lv_temp UP TO '/' LEFT. + rv_path = reverse( lv_temp ). + ENDIF. + ELSEIF iv_cur_dir+lv_last(1) = '/'. " Append cd to cur_dir separated by / + rv_path = iv_cur_dir && iv_cd. + ELSE. + rv_path = iv_cur_dir && '/' && iv_cd. + ENDIF. + + " TODO: improve logic and cases + + ENDMETHOD. + METHOD get_filename_from_syspath. + + DATA: lv_split TYPE c LENGTH 1, + lv_index TYPE i, + lt_split TYPE TABLE OF string. + + " filename | c:\filename | /dir/filename | \\server\filename + IF iv_path CA '/'. + lv_split = '/'. + ELSE. + lv_split = '\'. + ENDIF. + + SPLIT iv_path AT lv_split INTO TABLE lt_split. + + lv_index = lines( lt_split ). + + READ TABLE lt_split INDEX lv_index INTO rv_filename. + + ENDMETHOD. + METHOD is_root. + rv_yes = boolc( iv_path = '/' ). + ENDMETHOD. + METHOD is_subdir. + + DATA lv_len TYPE i. + DATA lv_last TYPE i. + + lv_len = strlen( iv_parent ). + lv_last = lv_len - 1. + rv_yes = boolc( strlen( iv_path ) > lv_len + AND iv_path+0(lv_len) = iv_parent + AND ( iv_parent+lv_last(1) = '/' OR iv_path+lv_len(1) = '/' ) ). + + ENDMETHOD. + METHOD split_file_location. + + DATA: lv_cnt TYPE i, + lv_len TYPE i. + + FIND FIRST OCCURRENCE OF REGEX '^/(.*/)?' IN iv_fullpath + MATCH COUNT lv_cnt + MATCH LENGTH lv_len. + + IF lv_cnt > 0. + ev_path = iv_fullpath+0(lv_len). + ev_filename = iv_fullpath+lv_len. + ELSE. + CLEAR ev_path. + ev_filename = iv_fullpath. + ENDIF. + + ev_filename = cl_http_utility=>unescape_url( escaped = ev_filename ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_log IMPLEMENTATION. + METHOD constructor. + + zif_abapgit_log~set_title( iv_title ). + + ENDMETHOD. + METHOD from_exception. + + CREATE OBJECT ro_log. + + IF io_x IS BOUND. + ro_log->zif_abapgit_log~add_exception( io_x ). + ENDIF. + + ENDMETHOD. + METHOD get_messages_status. + + DATA lr_msg TYPE REF TO zif_abapgit_log=>ty_msg. + rv_status = 'S'. + LOOP AT it_msg REFERENCE INTO lr_msg. + CASE lr_msg->type. + WHEN 'E' OR 'A' OR 'X'. + rv_status = 'E'. "not okay + EXIT. + WHEN 'W'. + rv_status = 'W'. "maybe + CONTINUE. + WHEN 'S' OR 'I'. + IF rv_status <> 'W'. + rv_status = 'S'. "okay + ENDIF. + CONTINUE. + WHEN OTHERS. "unknown + CONTINUE. + ENDCASE. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_log~add. + + FIELD-SYMBOLS: LIKE LINE OF mt_log. + + APPEND INITIAL LINE TO mt_log ASSIGNING . + -msg-text = iv_msg. + -msg-type = iv_type. + -msg-id = iv_class. + -msg-number = iv_number. + -item = is_item. + -exception = ix_exc. + + CASE iv_type. + WHEN 'E' OR 'A' OR 'X'. + -msg-level = zif_abapgit_log=>c_log_level-error. + WHEN 'W'. + -msg-level = zif_abapgit_log=>c_log_level-warning. + WHEN 'S' OR 'I'. + -msg-level = zif_abapgit_log=>c_log_level-info. + WHEN OTHERS. "unknown + ASSERT 0 = 1. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_log~add_error. + + zif_abapgit_log~add( + iv_msg = iv_msg + iv_type = 'E' + is_item = is_item ). + + ENDMETHOD. + METHOD zif_abapgit_log~add_exception. + + DATA lx_exc TYPE REF TO cx_root. + DATA lv_msg TYPE string. + lx_exc = ix_exc. + DO. + lv_msg = lx_exc->get_text( ). + zif_abapgit_log~add( iv_msg = lv_msg + iv_type = 'E' + is_item = is_item + ix_exc = lx_exc ). + IF lx_exc->previous IS BOUND. + lx_exc = lx_exc->previous. + ELSE. + EXIT. + ENDIF. + ENDDO. + + ENDMETHOD. + METHOD zif_abapgit_log~add_info. + + zif_abapgit_log~add( + iv_msg = iv_msg + iv_type = 'I' + is_item = is_item ). + + ENDMETHOD. + METHOD zif_abapgit_log~add_success. + + zif_abapgit_log~add( + iv_msg = iv_msg + iv_type = 'S' + is_item = is_item ). + + ENDMETHOD. + METHOD zif_abapgit_log~add_warning. + + zif_abapgit_log~add( + iv_msg = iv_msg + iv_type = 'W' + is_item = is_item ). + + ENDMETHOD. + METHOD zif_abapgit_log~clear. + CLEAR mt_log. + ENDMETHOD. + METHOD zif_abapgit_log~clone. + + DATA lo_log TYPE REF TO zcl_abapgit_log. + + CREATE OBJECT lo_log EXPORTING iv_title = mv_title. + lo_log->mt_log = mt_log. + ri_log = lo_log. + + ENDMETHOD. + METHOD zif_abapgit_log~count. + rv_count = lines( mt_log ). + ENDMETHOD. + METHOD zif_abapgit_log~get_item_status. + + DATA lr_log TYPE REF TO ty_log. + DATA ls_msg TYPE zif_abapgit_log=>ty_msg. + DATA ls_item_status TYPE zif_abapgit_log=>ty_item_status_out. + DATA lr_item_status TYPE REF TO zif_abapgit_log=>ty_item_status_out. + + "collect all message for all objects + LOOP AT mt_log REFERENCE INTO lr_log. + CLEAR ls_item_status. + ls_item_status-item = lr_log->item. + READ TABLE rt_item_status REFERENCE INTO lr_item_status + WITH KEY item-obj_type = ls_item_status-item-obj_type + item-obj_name = ls_item_status-item-obj_name. + IF sy-subrc <> 0. + INSERT ls_item_status INTO TABLE rt_item_status. + GET REFERENCE OF ls_item_status INTO lr_item_status. + ENDIF. + CLEAR ls_msg. + ls_msg-type = lr_log->msg-type. + ls_msg-text = lr_log->msg-text. + INSERT ls_msg INTO TABLE lr_item_status->messages. + ENDLOOP. + + "determine object status from object messages + LOOP AT rt_item_status REFERENCE INTO lr_item_status. + lr_item_status->status = get_messages_status( lr_item_status->messages ). + IF lr_item_status->messages IS INITIAL. + CLEAR ls_msg. + ls_msg-type = 'I'. + ls_msg-text = 'No message'. + INSERT ls_msg INTO TABLE lr_item_status->messages. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_log~get_log_level. + + FIELD-SYMBOLS LIKE LINE OF mt_log. + + rv_level = zif_abapgit_log=>c_log_level-empty. + + LOOP AT mt_log ASSIGNING . + IF -msg-level = zif_abapgit_log=>c_log_level-error. + rv_level = zif_abapgit_log=>c_log_level-error. + EXIT. + ELSEIF -msg-level > rv_level. + rv_level = -msg-level. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_log~get_messages. + DATA ls_msg TYPE zif_abapgit_log~ty_log_out. + FIELD-SYMBOLS TYPE ty_log. + LOOP AT mt_log ASSIGNING . + ls_msg-type = -msg-type. + ls_msg-id = -msg-id. + ls_msg-number = -msg-number. + ls_msg-text = -msg-text. + ls_msg-obj_type = -item-obj_type. + ls_msg-obj_name = -item-obj_name. + ls_msg-exception = -exception. + APPEND ls_msg TO rt_msg. + ENDLOOP. + DELETE ADJACENT DUPLICATES FROM rt_msg. + ENDMETHOD. + METHOD zif_abapgit_log~get_status. + + DATA lr_log TYPE REF TO ty_log. + rv_status = zif_abapgit_log=>c_status-ok. + LOOP AT mt_log REFERENCE INTO lr_log. + CASE lr_log->msg-type. + WHEN 'E' OR 'A' OR 'X'. + rv_status = zif_abapgit_log=>c_status-error. + EXIT. + WHEN 'W'. + rv_status = zif_abapgit_log=>c_status-warning. + CONTINUE. + WHEN 'S' OR 'I'. + IF rv_status <> zif_abapgit_log=>c_status-warning. + rv_status = zif_abapgit_log=>c_status-ok. + ENDIF. + CONTINUE. + WHEN OTHERS. "unknown + ASSERT 0 = 1. + ENDCASE. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_log~get_title. + rv_title = mv_title. + IF rv_title IS INITIAL. + rv_title = 'Log'. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_log~merge_with. + + DATA lo_log TYPE REF TO zcl_abapgit_log. + DATA lt_log_temp LIKE lo_log->mt_log. + + IF ii_log IS BOUND. + lo_log ?= ii_log. + IF iv_min_level > 0. + lt_log_temp = lo_log->mt_log. + DELETE lt_log_temp WHERE msg-level < iv_min_level. + APPEND LINES OF lt_log_temp TO mt_log. + ELSE. + APPEND LINES OF lo_log->mt_log TO mt_log. + ENDIF. + ENDIF. + + ri_log = me. + + ENDMETHOD. + METHOD zif_abapgit_log~set_title. + mv_title = iv_title. + ri_log = me. + ENDMETHOD. +ENDCLASS. + +CLASS kHGwldKtJfHZXmphMQgfeIQhGnfrcH DEFINITION DEFERRED. +CLASS kHGwldKtJfHZXmphMQgfcZaQwkuAox DEFINITION DEFERRED. +CLASS kHGwldKtJfHZXmphMQgfQYNhjRNkGw DEFINITION DEFERRED. +* renamed: zcl_abapgit_convert :: lcl_in +CLASS kHGwldKtJfHZXmphMQgfQYNhjRNkGw DEFINITION. + PUBLIC SECTION. + CLASS-METHODS convert + IMPORTING + !iv_data TYPE xsequence + !iv_length TYPE i OPTIONAL + RETURNING + VALUE(rv_string) TYPE string + RAISING + zcx_abapgit_exception. + PRIVATE SECTION. + CLASS-DATA go_conv_new TYPE REF TO object. + CLASS-DATA go_conv_old TYPE REF TO object. +ENDCLASS. + +CLASS kHGwldKtJfHZXmphMQgfQYNhjRNkGw IMPLEMENTATION. + METHOD convert. + + DATA lv_class TYPE string. + DATA lx_error TYPE REF TO cx_root. + + IF go_conv_new IS INITIAL AND go_conv_old IS INITIAL. + TRY. + CALL METHOD ('CL_ABAP_CONV_CODEPAGE')=>create_in + RECEIVING + instance = go_conv_new. + CATCH cx_sy_dyn_call_illegal_class. + lv_class = 'CL_ABAP_CONV_IN_CE'. + CALL METHOD (lv_class)=>create + EXPORTING + encoding = 'UTF-8' + RECEIVING + conv = go_conv_old. + ENDTRY. + ENDIF. + + TRY. + IF go_conv_new IS NOT INITIAL. + CALL METHOD go_conv_new->('IF_ABAP_CONV_IN~CONVERT') + EXPORTING + source = iv_data + RECEIVING + result = rv_string. + ELSE. + CALL METHOD go_conv_old->('CONVERT') + EXPORTING + input = iv_data + n = iv_length + IMPORTING + data = rv_string. + ENDIF. + CATCH cx_parameter_invalid_range + cx_sy_codepage_converter_init + cx_sy_conversion_codepage + cx_parameter_invalid_type INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +* renamed: zcl_abapgit_convert :: lcl_out +CLASS kHGwldKtJfHZXmphMQgfcZaQwkuAox DEFINITION. + PUBLIC SECTION. + CLASS-METHODS convert + IMPORTING + !iv_string TYPE string + RETURNING + VALUE(rv_xstring) TYPE xstring + RAISING + zcx_abapgit_exception. + PRIVATE SECTION. + CLASS-DATA go_conv_new TYPE REF TO object. + CLASS-DATA go_conv_old TYPE REF TO object. +ENDCLASS. + +CLASS kHGwldKtJfHZXmphMQgfcZaQwkuAox IMPLEMENTATION. + METHOD convert. + DATA lx_error TYPE REF TO cx_root. + DATA lv_class TYPE string. + + IF go_conv_new IS INITIAL AND go_conv_old IS INITIAL. + TRY. + CALL METHOD ('CL_ABAP_CONV_CODEPAGE')=>create_out + RECEIVING + instance = go_conv_new. + CATCH cx_sy_dyn_call_illegal_class. + lv_class = 'CL_ABAP_CONV_OUT_CE'. + CALL METHOD (lv_class)=>create + EXPORTING + encoding = 'UTF-8' + RECEIVING + conv = go_conv_old. + ENDTRY. + ENDIF. + + TRY. + IF go_conv_new IS NOT INITIAL. + CALL METHOD go_conv_new->('IF_ABAP_CONV_OUT~CONVERT') + EXPORTING + source = iv_string + RECEIVING + result = rv_xstring. + ELSE. + CALL METHOD go_conv_old->('CONVERT') + EXPORTING + data = iv_string + IMPORTING + buffer = rv_xstring. + ENDIF. + CATCH cx_parameter_invalid_range + cx_sy_codepage_converter_init + cx_sy_conversion_codepage + cx_parameter_invalid_type INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. +ENDCLASS. + +* renamed: zcl_abapgit_convert :: lcl_bcp47_language_table +CLASS kHGwldKtJfHZXmphMQgfeIQhGnfrcH DEFINITION CREATE PRIVATE. + + PUBLIC SECTION. + TYPES: BEGIN OF ty_language_mapping, + sap1_code TYPE sy-langu, + sap2_code TYPE laiso, + bcp47_code TYPE string, + text TYPE string, + END OF ty_language_mapping, + ty_language_mappings TYPE STANDARD TABLE OF ty_language_mapping WITH DEFAULT KEY. + CLASS-DATA gt_language_mappings TYPE ty_language_mappings. + CLASS-METHODS: + sap1_to_text + IMPORTING + im_sap1 TYPE sy-langu + RETURNING + VALUE(re_text) TYPE string, + sap1_to_sap2 + IMPORTING + im_sap1 TYPE sy-langu + RETURNING + VALUE(re_sap2) TYPE laiso + RAISING + zcx_abapgit_exception, + sap2_to_sap1 + IMPORTING + im_sap2 TYPE laiso + RETURNING + VALUE(re_sap1) TYPE sy-langu + RAISING + zcx_abapgit_exception, + sap1_to_bcp47 + IMPORTING + im_sap1 TYPE sy-langu + RETURNING + VALUE(re_bcp47) TYPE string + RAISING + zcx_abapgit_exception, + bcp47_to_sap1 + IMPORTING + im_bcp47 TYPE string + RETURNING + VALUE(re_sap1) TYPE sy-langu + RAISING + zcx_abapgit_exception. + PROTECTED SECTION. + PRIVATE SECTION. + CLASS-METHODS fill_language_mappings. + CLASS-METHODS + fill_language_mapping + IMPORTING + im_sap1 TYPE string + im_sap2 TYPE string + im_bcp47 TYPE string + iv_text TYPE string OPTIONAL. + +ENDCLASS. + +CLASS kHGwldKtJfHZXmphMQgfeIQhGnfrcH IMPLEMENTATION. + + METHOD sap1_to_bcp47. + DATA lv_language_mapping TYPE ty_language_mapping. + + IF gt_language_mappings IS INITIAL OR lines( gt_language_mappings ) = 0. + fill_language_mappings( ). + ENDIF. + + LOOP AT gt_language_mappings INTO lv_language_mapping WHERE sap1_code = im_sap1. + IF re_bcp47 IS INITIAL OR strlen( re_bcp47 ) > strlen( lv_language_mapping-bcp47_code ). + re_bcp47 = lv_language_mapping-bcp47_code. + ENDIF. + ENDLOOP. + + IF re_bcp47 IS INITIAL. + zcx_abapgit_exception=>raise( |Could not map SAP1 language code { im_sap1 } to BCP47 language code.| ). + ENDIF. + ENDMETHOD. + + METHOD bcp47_to_sap1. + DATA lv_language_mapping TYPE ty_language_mapping. + + IF gt_language_mappings IS INITIAL OR lines( gt_language_mappings ) = 0. + fill_language_mappings( ). + ENDIF. + + LOOP AT gt_language_mappings INTO lv_language_mapping. + IF to_lower( lv_language_mapping-bcp47_code ) = to_lower( im_bcp47 ) AND re_sap1 IS INITIAL. + re_sap1 = lv_language_mapping-sap1_code. + ENDIF. + ENDLOOP. + + IF re_sap1 IS INITIAL. + zcx_abapgit_exception=>raise( |Could not map BCP47 language code { im_bcp47 } to SAP1 language code.| ). + ENDIF. + ENDMETHOD. + + METHOD sap1_to_text. + DATA lv_language_mapping TYPE ty_language_mapping. + + IF gt_language_mappings IS INITIAL. + fill_language_mappings( ). + ENDIF. + + READ TABLE gt_language_mappings WITH KEY sap1_code = im_sap1 INTO lv_language_mapping. + IF sy-subrc = 0. + re_text = lv_language_mapping-text. + ELSE. + re_text = 'Unknonw language'. + ENDIF. + ENDMETHOD. + + METHOD sap1_to_sap2. + DATA lv_language_mapping TYPE ty_language_mapping. + + IF gt_language_mappings IS INITIAL. + fill_language_mappings( ). + ENDIF. + + READ TABLE gt_language_mappings WITH KEY sap1_code = im_sap1 INTO lv_language_mapping. + re_sap2 = lv_language_mapping-sap2_code. + + IF re_sap2 IS INITIAL. + zcx_abapgit_exception=>raise( |Could not map SAP1 language code { im_sap1 } to SAP2 language code.| ). + ENDIF. + ENDMETHOD. + + METHOD sap2_to_sap1. + DATA lv_language_mapping TYPE ty_language_mapping. + + IF gt_language_mappings IS INITIAL. + fill_language_mappings( ). + ENDIF. + + READ TABLE gt_language_mappings WITH KEY sap2_code = im_sap2 INTO lv_language_mapping. + re_sap1 = lv_language_mapping-sap1_code. + + IF re_sap1 IS INITIAL. + zcx_abapgit_exception=>raise( |Could not map SAP2 language code { im_sap2 } to SAP1 language code.| ). + ENDIF. + ENDMETHOD. + + METHOD fill_language_mapping. + DATA lv_line TYPE ty_language_mapping. + DATA lv_sap1 TYPE sy-langu. + + IF strlen( im_sap1 ) = 4. + TRY. + lv_sap1 = zcl_abapgit_convert=>uccp( im_sap1 ). + CATCH cx_root. + " Language is not supported in this system -> ignore it + " Should someone try to use the language in a repo, it will result in an error (see above) + RETURN. + ENDTRY. + ELSEIF strlen( im_sap1 ) = 1. + lv_sap1 = im_sap1. + ENDIF. + + lv_line-bcp47_code = im_bcp47. + lv_line-sap2_code = im_sap2. + lv_line-sap1_code = lv_sap1. + lv_line-text = iv_text. + + APPEND lv_line TO gt_language_mappings. + CLEAR lv_line. + ENDMETHOD. + + METHOD fill_language_mappings. + fill_language_mapping( im_sap1 = 'a' + im_sap2 = 'AF' + im_bcp47 = 'af' + iv_text = 'Afrikaans' ). + + fill_language_mapping( im_sap1 = 'BF51' + im_sap2 = 'SQ' + im_bcp47 = 'sq' + iv_text = 'Albanian' ). + + fill_language_mapping( im_sap1 = 'A' + im_sap2 = 'AR' + im_bcp47 = 'ar-SA' + iv_text = 'Arabic' ). + + fill_language_mapping( im_sap1 = 'BA15' + im_sap2 = 'EU' + im_bcp47 = 'eu' + iv_text = 'Basque' ). + + fill_language_mapping( im_sap1 = 'B8F3' + im_sap2 = 'BS' + im_bcp47 = 'bs' + iv_text = 'Bosnian' ). + + fill_language_mapping( im_sap1 = 'W' + im_sap2 = 'BG' + im_bcp47 = 'bg' + iv_text = 'Bulgarian' ). + + fill_language_mapping( im_sap1 = 'c' + im_sap2 = 'CA' + im_bcp47 = 'ca' + iv_text = 'Catalan' ). + + fill_language_mapping( im_sap1 = '1' + im_sap2 = 'ZH' + im_bcp47 = 'zh' + iv_text = 'Chinese' ). + + fill_language_mapping( im_sap1 = '1' + im_sap2 = 'ZH' + im_bcp47 = 'zh-Hans' + iv_text = 'Chinese (Simplified)' ). + + fill_language_mapping( im_sap1 = 'B343' + im_sap2 = '3C' + im_bcp47 = 'zh-SG' + iv_text = 'Chinese (Singapore)' ). + + fill_language_mapping( im_sap1 = 'M' + im_sap2 = 'ZF' + im_bcp47 = 'zh-Hant' + iv_text = 'Chinese (Traditional)' ). + + fill_language_mapping( im_sap1 = '6' + im_sap2 = 'HR' + im_bcp47 = 'hr' + iv_text = 'Croatian' ). + + fill_language_mapping( im_sap1 = 'C' + im_sap2 = 'CS' + im_bcp47 = 'cs' + iv_text = 'Czech' ). + + fill_language_mapping( im_sap1 = 'K' + im_sap2 = 'DA' + im_bcp47 = 'da' + iv_text = 'Danish' ). + + fill_language_mapping( im_sap1 = 'N' + im_sap2 = 'NL' + im_bcp47 = 'nl' + iv_text = 'Dutch' ). + + fill_language_mapping( im_sap1 = 'N' + im_sap2 = 'NL' + im_bcp47 = 'nl-NL' + iv_text = 'Dutch' ). + + fill_language_mapping( im_sap1 = 'B284' + im_sap2 = '1D' + im_bcp47 = 'nl-BE' + iv_text = 'Dutch (Belgium)' ). + + fill_language_mapping( im_sap1 = 'E' + im_sap2 = 'EN' + im_bcp47 = 'en' + iv_text = 'English' ). + + fill_language_mapping( im_sap1 = 'E' + im_sap2 = 'EN' + im_bcp47 = 'en-US' + iv_text = 'English (American)' ). + + fill_language_mapping( im_sap1 = 'B46E' + im_sap2 = '6N' + im_bcp47 = 'en-GB' + iv_text = 'English (British)' ). + + fill_language_mapping( im_sap1 = 'B285' + im_sap2 = '1E' + im_bcp47 = 'en-AU' + iv_text = 'English (Australia)' ). + + fill_language_mapping( im_sap1 = 'B2E5' + im_sap2 = '2E' + im_bcp47 = 'en-BZ' + iv_text = 'English (Belize)' ). + + fill_language_mapping( im_sap1 = 'B345' + im_sap2 = '3E' + im_bcp47 = 'en-CA' + iv_text = 'English (Canada)' ). + + fill_language_mapping( im_sap1 = 'B405' + im_sap2 = '5E' + im_bcp47 = 'en-HK' + iv_text = 'English (Hong Kong SAR China)' ). + + fill_language_mapping( im_sap1 = 'B465' + im_sap2 = '6E' + im_bcp47 = 'en-IN' + iv_text = 'English (India)' ). + + fill_language_mapping( im_sap1 = 'B4C5' + im_sap2 = '7E' + im_bcp47 = 'en-ID' + iv_text = 'English' ). + + fill_language_mapping( im_sap1 = 'B525' + im_sap2 = '8E' + im_bcp47 = 'en-IE' + iv_text = 'English (Ireland)' ). + + fill_language_mapping( im_sap1 = 'B585' + im_sap2 = '9E' + im_bcp47 = 'en-JM' + iv_text = 'English (Jamaica)' ). + + fill_language_mapping( im_sap1 = 'B225' + im_sap2 = '0E' + im_bcp47 = 'en-MY' + iv_text = 'English (Malaysia)' ). + + fill_language_mapping( im_sap1 = 'B28E' + im_sap2 = '1N' + im_bcp47 = 'en-NZ' + iv_text = 'English (New Zealand)' ). + + fill_language_mapping( im_sap1 = 'B2EE' + im_sap2 = '2N' + im_bcp47 = 'en-PH' + iv_text = 'English (Philippines)' ). + + fill_language_mapping( im_sap1 = 'B34E' + im_sap2 = '3N' + im_bcp47 = 'en-SG' + iv_text = 'English (Singapore)' ). + + fill_language_mapping( im_sap1 = 'B3AE' + im_sap2 = '4N' + im_bcp47 = 'en-ZA' + iv_text = 'English (South Africa)' ). + + fill_language_mapping( im_sap1 = 'B40E' + im_sap2 = '5N' + im_bcp47 = 'en-TT' + iv_text = 'English (Trinidad & Tobago)' ). + + fill_language_mapping( im_sap1 = 'B4CE' + im_sap2 = '7N' + im_bcp47 = 'en-ZW' + iv_text = 'English (Zimbabwe)' ). + + fill_language_mapping( im_sap1 = '9' + im_sap2 = 'ET' + im_bcp47 = 'et' + iv_text = 'Estonian' ). + + fill_language_mapping( im_sap1 = 'U' + im_sap2 = 'FI' + im_bcp47 = 'fi' + iv_text = 'Finnish' ). + + fill_language_mapping( im_sap1 = 'F' + im_sap2 = 'FR' + im_bcp47 = 'fr' + iv_text = 'French' ). + + fill_language_mapping( im_sap1 = 'F' + im_sap2 = 'FR' + im_bcp47 = 'fr-FR' + iv_text = 'French' ). + + fill_language_mapping( im_sap1 = 'B286' + im_sap2 = '1F' + im_bcp47 = 'fr-BE' + iv_text = 'French (Belgium)' ). + + fill_language_mapping( im_sap1 = 'B2E6' + im_sap2 = '2F' + im_bcp47 = 'fr-CM' + iv_text = 'French (Cameroon)' ). + + fill_language_mapping( im_sap1 = 'B346' + im_sap2 = '3F' + im_bcp47 = 'fr-CA' + iv_text = 'French (Canada)' ). + + fill_language_mapping( im_sap1 = 'B3A6' + im_sap2 = '4F' + im_bcp47 = 'fr-CG' + iv_text = 'French (Congo-Brazzaville)' ). + + fill_language_mapping( im_sap1 = 'B406' + im_sap2 = '5F' + im_bcp47 = 'fr-CI' + iv_text = 'French (Cote d''Ivoire)' ). + + fill_language_mapping( im_sap1 = 'B466' + im_sap2 = '6F' + im_bcp47 = 'fr-HT' + iv_text = 'French (Haiti)' ). + + fill_language_mapping( im_sap1 = 'B4C6' + im_sap2 = '7F' + im_bcp47 = 'fr-LU' + iv_text = 'French (Luxembourg)' ). + + fill_language_mapping( im_sap1 = 'B526' + im_sap2 = '8F' + im_bcp47 = 'fr-ML' + iv_text = 'French (Mali)' ). + + fill_language_mapping( im_sap1 = 'B586' + im_sap2 = '9F' + im_bcp47 = 'fr-MC' + iv_text = 'French (Monaco)' ). + + fill_language_mapping( im_sap1 = 'B288' + im_sap2 = '1H' + im_bcp47 = 'fr-MA' + iv_text = 'French (Morocco)' ). + + fill_language_mapping( im_sap1 = 'B2E8' + im_sap2 = '2H' + im_bcp47 = 'fr-RE' + iv_text = 'French (Reunion)' ). + + fill_language_mapping( im_sap1 = 'B348' + im_sap2 = '3H' + im_bcp47 = 'fr-SN' + iv_text = 'French (Senegal)' ). + + fill_language_mapping( im_sap1 = 'B3A8' + im_sap2 = '4H' + im_bcp47 = 'fr-CH' + iv_text = 'French (Switzerland)' ). + + fill_language_mapping( im_sap1 = 'BAC4' + im_sap2 = 'GD' + im_bcp47 = 'gd' + iv_text = 'Scottish Gaelic' ). + + fill_language_mapping( im_sap1 = 'BACC' + im_sap2 = 'GL' + im_bcp47 = 'gl' + iv_text = 'Galician' ). + + fill_language_mapping( im_sap1 = 'D' + im_sap2 = 'DE' + im_bcp47 = 'de' + iv_text = 'German' ). + + fill_language_mapping( im_sap1 = 'D' + im_sap2 = 'DE' + im_bcp47 = 'de-DE' + iv_text = 'German' ). + + fill_language_mapping( im_sap1 = 'B287' + im_sap2 = '1G' + im_bcp47 = 'de-AT' + iv_text = 'German (Austria)' ). + + fill_language_mapping( im_sap1 = 'B2E7' + im_sap2 = '2G' + im_bcp47 = 'de-LI' + iv_text = 'German (Liechtenstein)' ). + + fill_language_mapping( im_sap1 = 'B347' + im_sap2 = '3G' + im_bcp47 = 'de-LU' + iv_text = 'German (Luxembourg)' ). + + fill_language_mapping( im_sap1 = 'B3A7' + im_sap2 = '4G' + im_bcp47 = 'de-CH' + iv_text = 'German (Switzerland)' ). + + fill_language_mapping( im_sap1 = 'G' + im_sap2 = 'EL' + im_bcp47 = 'el' + iv_text = 'Greek' ). + + fill_language_mapping( im_sap1 = 'B' + im_sap2 = 'HE' + im_bcp47 = 'he' + iv_text = 'Hebrew' ). + + fill_language_mapping( im_sap1 = 'BB29' + im_sap2 = 'HI' + im_bcp47 = 'hi' + iv_text = 'Hindi' ). + + fill_language_mapping( im_sap1 = 'H' + im_sap2 = 'HU' + im_bcp47 = 'hu' + iv_text = 'Hungarian' ). + + fill_language_mapping( im_sap1 = 'b' + im_sap2 = 'IS' + im_bcp47 = 'is' + iv_text = 'Icelandic' ). + + fill_language_mapping( im_sap1 = 'i' + im_sap2 = 'ID' + im_bcp47 = 'id' + iv_text = 'Indonesian' ). + + fill_language_mapping( im_sap1 = 'BAC1' + im_sap2 = 'GA' + im_bcp47 = 'ga' + iv_text = 'Irish' ). + + fill_language_mapping( im_sap1 = 'I' + im_sap2 = 'IT' + im_bcp47 = 'it' + iv_text = 'Italian' ). + + fill_language_mapping( im_sap1 = 'I' + im_sap2 = 'IT' + im_bcp47 = 'it-IT' + iv_text = 'Italian' ). + + fill_language_mapping( im_sap1 = 'B289' + im_sap2 = '1I' + im_bcp47 = 'it-CH' + iv_text = 'Italian (Swiss)' ). + + fill_language_mapping( im_sap1 = 'J' + im_sap2 = 'JA' + im_bcp47 = 'ja' + iv_text = 'Japanese' ). + + fill_language_mapping( im_sap1 = '3' + im_sap2 = 'KO' + im_bcp47 = 'ko' + iv_text = 'Korean' ). + + fill_language_mapping( im_sap1 = '3' + im_sap2 = 'KO' + im_bcp47 = 'ko-KR' + iv_text = 'Korean' ). + + fill_language_mapping( im_sap1 = 'Y' + im_sap2 = 'LV' + im_bcp47 = 'lv' + iv_text = 'Latvian' ). + + fill_language_mapping( im_sap1 = 'X' + im_sap2 = 'LT' + im_bcp47 = 'lt' + iv_text = 'Lithuanian' ). + + fill_language_mapping( im_sap1 = '7' + im_sap2 = 'MS' + im_bcp47 = 'ms' + iv_text = 'Malay' ). + + fill_language_mapping( im_sap1 = '7' + im_sap2 = 'MS' + im_bcp47 = 'ms-MY' + iv_text = 'Malay' ). + + fill_language_mapping( im_sap1 = 'B28D' + im_sap2 = '1M' + im_bcp47 = 'ms-BN' + iv_text = 'Malay (Brunei)' ). + + fill_language_mapping( im_sap1 = 'O' + im_sap2 = 'NO' + im_bcp47 = 'no' + iv_text = 'Norwegian' ). + + fill_language_mapping( im_sap1 = 'L' + im_sap2 = 'PL' + im_bcp47 = 'pl' + iv_text = 'Polish' ). + + fill_language_mapping( im_sap1 = 'P' + im_sap2 = 'PT' + im_bcp47 = 'pt' + iv_text = 'Portuguese' ). + + fill_language_mapping( im_sap1 = 'P' + im_sap2 = 'PT' + im_bcp47 = 'pt-BR' + iv_text = 'Portuguese' ). + + fill_language_mapping( im_sap1 = 'BEED' + im_sap2 = 'RM' + im_bcp47 = 'rm' + iv_text = 'Romansh' ). + + fill_language_mapping( im_sap1 = '4' + im_sap2 = 'RO' + im_bcp47 = 'ro' + iv_text = 'Romanian' ). + + fill_language_mapping( im_sap1 = '4' + im_sap2 = 'RO' + im_bcp47 = 'ro-RO' + iv_text = 'Romanian' ). + + fill_language_mapping( im_sap1 = 'R' + im_sap2 = 'RU' + im_bcp47 = 'ru-RU' + iv_text = 'Russian' ). + + fill_language_mapping( im_sap1 = '0' + im_sap2 = 'SR' + im_bcp47 = 'sr' + iv_text = 'Serbian' ). + + fill_language_mapping( im_sap1 = '0' + im_sap2 = 'SR' + im_bcp47 = 'sr-Cyrl' + iv_text = 'Serbian' ). + + fill_language_mapping( im_sap1 = 'd' + im_sap2 = 'SH' + im_bcp47 = 'sr-Latn' + iv_text = 'Serbian (Latin)' ). + + fill_language_mapping( im_sap1 = 'Q' + im_sap2 = 'SK' + im_bcp47 = 'sk' + iv_text = 'Slovak' ). + + fill_language_mapping( im_sap1 = '5' + im_sap2 = 'SL' + im_bcp47 = 'sl' + iv_text = 'Slovenian' ). + + fill_language_mapping( im_sap1 = 'BF42' + im_sap2 = 'SB' + im_bcp47 = 'wen' + iv_text = '' ). + + fill_language_mapping( im_sap1 = 'B9B3' + im_sap2 = 'DS' + im_bcp47 = 'dsb' + iv_text = '' ). + + fill_language_mapping( im_sap1 = 'BB33' + im_sap2 = 'HS' + im_bcp47 = 'hsb' + iv_text = '' ). + + fill_language_mapping( im_sap1 = 'S' + im_sap2 = 'ES' + im_bcp47 = 'es' + iv_text = 'Spanish' ). + + fill_language_mapping( im_sap1 = 'S' + im_sap2 = 'ES' + im_bcp47 = 'es-ES' + iv_text = 'Spanish' ). + + fill_language_mapping( im_sap1 = 'B293' + im_sap2 = '1S' + im_bcp47 = 'es-AR' + iv_text = 'Spanish (Argentina)' ). + + fill_language_mapping( im_sap1 = 'B2F3' + im_sap2 = '2S' + im_bcp47 = 'es-BO' + iv_text = 'Spanish (Bolivia)' ). + + fill_language_mapping( im_sap1 = 'B353' + im_sap2 = '3S' + im_bcp47 = 'es-CL' + iv_text = 'Spanish (Chile)' ). + + fill_language_mapping( im_sap1 = 'B233' + im_sap2 = '0S' + im_bcp47 = 'es-CO' + iv_text = 'Spanish (Colombia)' ). + + fill_language_mapping( im_sap1 = 'B3B3' + im_sap2 = '4S' + im_bcp47 = 'es-CR' + iv_text = 'Spanish (Costa Rica)' ). + + fill_language_mapping( im_sap1 = 'B413' + im_sap2 = '5S' + im_bcp47 = 'es-DO' + iv_text = 'Spanish (Dominican Republic)' ). + + fill_language_mapping( im_sap1 = 'B473' + im_sap2 = '6S' + im_bcp47 = 'es-EC' + iv_text = 'Spanish (Ecuador)' ). + + fill_language_mapping( im_sap1 = 'B4D3' + im_sap2 = '7S' + im_bcp47 = 'es-SV' + iv_text = 'Spanish (El Salvador)' ). + + fill_language_mapping( im_sap1 = 'B533' + im_sap2 = '8S' + im_bcp47 = 'es-GT' + iv_text = 'Spanish (Guatemala)' ). + + fill_language_mapping( im_sap1 = 'B593' + im_sap2 = '9S' + im_bcp47 = 'es-HN' + iv_text = 'Spanish (Honduras)' ). + + fill_language_mapping( im_sap1 = 'B298' + im_sap2 = '1X' + im_bcp47 = 'es-MX' + iv_text = 'Spanish (Mexico)' ). + + fill_language_mapping( im_sap1 = 'B2F8' + im_sap2 = '2X' + im_bcp47 = 'es-NI' + iv_text = 'Spanish (Nicaragua)' ). + + fill_language_mapping( im_sap1 = 'B358' + im_sap2 = '3X' + im_bcp47 = 'es-PA' + iv_text = 'Spanish (Panama)' ). + + fill_language_mapping( im_sap1 = 'B3B8' + im_sap2 = '4X' + im_bcp47 = 'es-PY' + iv_text = 'Spanish (Paraguay)' ). + + fill_language_mapping( im_sap1 = 'B418' + im_sap2 = '5X' + im_bcp47 = 'es-PE' + iv_text = 'Spanish (Peru)' ). + + fill_language_mapping( im_sap1 = 'B478' + im_sap2 = '6X' + im_bcp47 = 'es-PR' + iv_text = 'Spanish (Puerto Rico)' ). + + fill_language_mapping( im_sap1 = 'B4D8' + im_sap2 = '7X' + im_bcp47 = 'es-UY' + iv_text = 'Spanish (Uruguay)' ). + + fill_language_mapping( im_sap1 = 'B538' + im_sap2 = '8X' + im_bcp47 = 'es-VE' + iv_text = 'Spanish (Venezuela)' ). + + fill_language_mapping( im_sap1 = 'BF57' + im_sap2 = 'SW' + im_bcp47 = 'sw' + iv_text = 'Swahili' ). + + fill_language_mapping( im_sap1 = 'V' + im_sap2 = 'SV' + im_bcp47 = 'sv' + iv_text = 'Swedish' ). + + fill_language_mapping( im_sap1 = 'BFAC' + im_sap2 = 'TL' + im_bcp47 = 'tl' + iv_text = 'Tagalog' ). + + fill_language_mapping( im_sap1 = '2' + im_sap2 = 'TH' + im_bcp47 = 'th' + iv_text = 'Thai' ). + + fill_language_mapping( im_sap1 = 'T' + im_sap2 = 'TR' + im_bcp47 = 'tr' + iv_text = 'Turkish' ). + + fill_language_mapping( im_sap1 = '8' + im_sap2 = 'UK' + im_bcp47 = 'uk' + iv_text = 'Ukrainian' ). + + fill_language_mapping( im_sap1 = 'C069' + im_sap2 = 'VI' + im_bcp47 = 'vi' + iv_text = 'Vietnamese' ). + + fill_language_mapping( im_sap1 = 'C0C1' + im_sap2 = 'WA' + im_bcp47 = 'wa' + iv_text = 'Wa' ). + + fill_language_mapping( im_sap1 = 'Z' + im_sap2 = 'Z1' + im_bcp47 = 'z1' + iv_text = 'Customer reserve' ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_convert IMPLEMENTATION. + METHOD base64_to_xstring. + + rv_xstr = cl_http_utility=>decode_x_base64( iv_base64 ). + + ENDMETHOD. + METHOD bitbyte_to_int. + + DATA: lv_bitbyte TYPE string, + lv_len TYPE i, + lv_offset TYPE i. + + lv_bitbyte = iv_bits. + SHIFT lv_bitbyte LEFT DELETING LEADING '0 '. + lv_len = strlen( lv_bitbyte ). + lv_offset = lv_len - 1. + + rv_int = 0. + DO lv_len TIMES. + + IF sy-index = 1. + "Initialize + IF lv_bitbyte+lv_offset(1) = '1'. + rv_int = 1. + ENDIF. + ELSEIF lv_bitbyte+lv_offset(1) = '1'. + rv_int = rv_int + ( 2 ** ( sy-index - 1 ) ). + ENDIF. + + lv_offset = lv_offset - 1. "Move Cursor + + ENDDO. + + ENDMETHOD. + METHOD conversion_exit_isola_output. + + language_sap1_to_sap2( + EXPORTING + im_lang_sap1 = iv_spras + RECEIVING + re_lang_sap2 = rv_spras + EXCEPTIONS + no_assignment = 1 + OTHERS = 2 ). "#EC CI_SUBRC + + TRANSLATE rv_spras TO UPPER CASE. + + ENDMETHOD. + METHOD int_to_xstring4. +* returns xstring of length 4 containing the integer value iv_i + + DATA lv_x TYPE x LENGTH 4. + + lv_x = iv_i. + rv_xstring = lv_x. + + ENDMETHOD. + METHOD language_bcp47_to_sap1. + DATA lv_converter_instance TYPE REF TO object. + DATA lv_converter_class_name TYPE string VALUE `CL_AFF_LANGUAGE_CONVERTER`. + DATA lv_regex TYPE REF TO cl_abap_regex. + DATA lv_abap_matcher TYPE REF TO cl_abap_matcher. + + DATA lv_sap2_lang_code TYPE laiso. + + TRY. + CALL METHOD (lv_converter_class_name)=>create_instance + RECEIVING + result = lv_converter_instance. + + TRY. + CALL METHOD lv_converter_instance->(`IF_AFF_LANGUAGE_CONVERTER~BCP47_TO_SAP1`) + EXPORTING + language = im_lang_bcp47 + RECEIVING + result = re_lang_sap1. + + CATCH cx_static_check. + RAISE no_assignment. + ENDTRY. + + CATCH cx_sy_dyn_call_error. + TRY. + re_lang_sap1 = kHGwldKtJfHZXmphMQgfeIQhGnfrcH=>bcp47_to_sap1( im_lang_bcp47 ). + CATCH zcx_abapgit_exception. + + CREATE OBJECT lv_regex EXPORTING pattern = `[A-Z0-9]{2}`. + lv_abap_matcher = lv_regex->create_matcher( text = im_lang_bcp47 ). + + IF abap_true = lv_abap_matcher->match( ). + "Fallback try to convert from SAP language + lv_sap2_lang_code = im_lang_bcp47. + + language_sap2_to_sap1( + EXPORTING + im_lang_sap2 = lv_sap2_lang_code + RECEIVING + re_lang_sap1 = re_lang_sap1 + EXCEPTIONS + no_assignment = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + RAISE no_assignment. + ENDIF. + + ELSE. + RAISE no_assignment. + ENDIF. + ENDTRY. + ENDTRY. + ENDMETHOD. + METHOD language_sap1_to_bcp47. + DATA lv_converter_instance TYPE REF TO object. + DATA lv_converter_class_name TYPE string VALUE `CL_AFF_LANGUAGE_CONVERTER`. + + TRY. + CALL METHOD (lv_converter_class_name)=>create_instance + RECEIVING + result = lv_converter_instance. + + TRY. + CALL METHOD lv_converter_instance->(`IF_AFF_LANGUAGE_CONVERTER~SAP1_TO_BCP47`) + EXPORTING + language = im_lang_sap1 + RECEIVING + result = re_lang_bcp47. + CATCH cx_static_check. + RAISE no_assignment. + ENDTRY. + CATCH cx_sy_dyn_call_error. + TRY. + re_lang_bcp47 = kHGwldKtJfHZXmphMQgfeIQhGnfrcH=>sap1_to_bcp47( im_lang_sap1 ). + CATCH zcx_abapgit_exception. + RAISE no_assignment. + ENDTRY. + ENDTRY. + ENDMETHOD. + METHOD language_sap1_to_sap2. + + TRY. + re_lang_sap2 = kHGwldKtJfHZXmphMQgfeIQhGnfrcH=>sap1_to_sap2( im_lang_sap1 ). + CATCH zcx_abapgit_exception. + RAISE no_assignment. + ENDTRY. + + ENDMETHOD. + METHOD language_sap1_to_text. + re_text = kHGwldKtJfHZXmphMQgfeIQhGnfrcH=>sap1_to_text( im_lang_sap1 ). + ENDMETHOD. + METHOD language_sap2_to_sap1. + + TRY. + re_lang_sap1 = kHGwldKtJfHZXmphMQgfeIQhGnfrcH=>sap2_to_sap1( im_lang_sap2 ). + CATCH zcx_abapgit_exception. + RAISE no_assignment. + ENDTRY. + + ENDMETHOD. + METHOD split_string. + + FIND FIRST OCCURRENCE OF cl_abap_char_utilities=>cr_lf IN iv_string. + + " Convert string into table depending on separator type CR_LF vs. LF + IF sy-subrc = 0. + SPLIT iv_string AT cl_abap_char_utilities=>cr_lf INTO TABLE rt_lines. + ELSE. + SPLIT iv_string AT cl_abap_char_utilities=>newline INTO TABLE rt_lines. + ENDIF. + + ENDMETHOD. + METHOD string_to_tab. + + DATA lv_length TYPE i. + DATA lv_iterations TYPE i. + DATA lv_offset TYPE i. + + FIELD-SYMBOLS TYPE any. + CLEAR et_tab. + ev_size = strlen( iv_str ). + + APPEND INITIAL LINE TO et_tab ASSIGNING . + = iv_str. + lv_length = cl_abap_typedescr=>describe_by_data( )->length / cl_abap_char_utilities=>charsize. + lv_iterations = ev_size DIV lv_length. + + DO lv_iterations TIMES. + lv_offset = sy-index * lv_length. + APPEND INITIAL LINE TO et_tab ASSIGNING . + = iv_str+lv_offset. + ENDDO. + + ENDMETHOD. + METHOD string_to_xstring. + + rv_xstr = string_to_xstring_utf8( iv_str ). + + ENDMETHOD. + METHOD string_to_xstring_utf8. + + rv_xstring = kHGwldKtJfHZXmphMQgfcZaQwkuAox=>convert( iv_string ). + + ENDMETHOD. + METHOD string_to_xstring_utf8_bom. + + IF iv_string IS INITIAL. + RETURN. + ENDIF. + + rv_xstring = string_to_xstring_utf8( iv_string ). + + " Add UTF-8 BOM + IF xstrlen( rv_xstring ) < 3 OR rv_xstring(3) <> cl_abap_char_utilities=>byte_order_mark_utf8. + rv_xstring = cl_abap_char_utilities=>byte_order_mark_utf8 && rv_xstring. + ENDIF. + + ENDMETHOD. + METHOD uccp. + + DATA lv_class TYPE string. + DATA lv_xstr TYPE xstring. + DATA lo_instance TYPE REF TO object. + + lv_class = 'CL_ABAP_CONV_IN_CE'. + + TRY. + CALL METHOD (lv_class)=>uccp + EXPORTING + uccp = iv_uccp + RECEIVING + char = rv_char. + CATCH cx_sy_dyn_call_illegal_class. + lv_xstr = iv_uccp. + + CALL METHOD ('CL_ABAP_CONV_CODEPAGE')=>create_in + EXPORTING + codepage = 'UTF-16' + RECEIVING + instance = lo_instance. + +* convert endianness + CONCATENATE lv_xstr+1(1) lv_xstr(1) INTO lv_xstr IN BYTE MODE. + + CALL METHOD lo_instance->('IF_ABAP_CONV_IN~CONVERT') + EXPORTING + source = lv_xstr + RECEIVING + result = rv_char. + ENDTRY. + + ENDMETHOD. + METHOD xstring_remove_bom. + + rv_xstr = iv_xstr. + + " cl_abap_conv_in_ce does not handle BOM in non-Unicode systems, so we remove it + IF cl_abap_char_utilities=>charsize = 1 AND xstrlen( rv_xstr ) > 3 + AND rv_xstr(3) = cl_abap_char_utilities=>byte_order_mark_utf8. + + rv_xstr = rv_xstr+3. + + ENDIF. + + ENDMETHOD. + METHOD xstring_to_bintab. + + DATA lv_length TYPE i. + DATA lv_iterations TYPE i. + DATA lv_offset TYPE i. + DATA lv_struct TYPE abap_bool. + + FIELD-SYMBOLS TYPE any. + + CLEAR et_bintab. + ev_size = xstrlen( iv_xstr ). + + IF iv_xstr IS INITIAL. + RETURN. + ENDIF. + + APPEND INITIAL LINE TO et_bintab ASSIGNING . + lv_struct = boolc( + cl_abap_typedescr=>describe_by_data( )->type_kind = cl_abap_typedescr=>typekind_struct1 ). + IF lv_struct = abap_true. + ASSIGN COMPONENT 1 OF STRUCTURE TO . + ENDIF. + = iv_xstr. + + lv_length = cl_abap_typedescr=>describe_by_data( )->length. + ASSERT lv_length > 0. + + lv_iterations = ( ev_size - 1 ) DIV lv_length. + + DO lv_iterations TIMES. + lv_offset = sy-index * lv_length. + APPEND INITIAL LINE TO et_bintab ASSIGNING . + IF lv_struct = abap_true. + ASSIGN COMPONENT 1 OF STRUCTURE TO . + ENDIF. + = iv_xstr+lv_offset. + ENDDO. + + ENDMETHOD. + METHOD xstring_to_int. + +* use the built-in type conversion + rv_i = iv_xstring. + + ENDMETHOD. + METHOD xstring_to_string_utf8. + + DATA lv_data TYPE xstring. + DATA lv_length TYPE i. + + " Remove BOM for non-Unicode systems + lv_data = xstring_remove_bom( iv_data ). + + lv_length = iv_length. + IF lv_length <= 0. + lv_length = xstrlen( lv_data ). + ENDIF. + + rv_string = kHGwldKtJfHZXmphMQgfQYNhjRNkGw=>convert( + iv_data = lv_data + iv_length = lv_length ). + + ENDMETHOD. + METHOD xstring_to_string_utf8_bom. + + DATA lv_xstring TYPE xstring. + + IF iv_xstring IS INITIAL. + RETURN. + ENDIF. + + lv_xstring = iv_xstring. + " Add UTF-8 BOM + IF xstrlen( lv_xstring ) < 3 OR lv_xstring(3) <> cl_abap_char_utilities=>byte_order_mark_utf8. + lv_xstring = cl_abap_char_utilities=>byte_order_mark_utf8 && lv_xstring. + ENDIF. + + rv_string = xstring_to_string_utf8( lv_xstring ). + + ENDMETHOD. + METHOD x_to_bitbyte. + + CLEAR rv_bitbyte. + + GET BIT 1 OF iv_x INTO rv_bitbyte+0(1). + GET BIT 2 OF iv_x INTO rv_bitbyte+1(1). + GET BIT 3 OF iv_x INTO rv_bitbyte+2(1). + GET BIT 4 OF iv_x INTO rv_bitbyte+3(1). + GET BIT 5 OF iv_x INTO rv_bitbyte+4(1). + GET BIT 6 OF iv_x INTO rv_bitbyte+5(1). + GET BIT 7 OF iv_x INTO rv_bitbyte+6(1). + GET BIT 8 OF iv_x INTO rv_bitbyte+7(1). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_ui_factory IMPLEMENTATION. + METHOD get_asset_manager. + + DATA lo_buf TYPE REF TO zcl_abapgit_string_buffer. + DATA li_asset_man TYPE REF TO zif_abapgit_gui_asset_manager. + + CREATE OBJECT lo_buf. + + li_asset_man = zcl_abapgit_gui_asset_manager=>create( ). + +**************************************************** +* abapmerge Pragma [include] - ZABAPGIT_CSS_COMMON.W3MI.DATA.CSS +**************************************************** + lo_buf->add( '/*' ). + lo_buf->add( ' * ABAPGIT COMMON CSS' ). + lo_buf->add( ' */' ). + lo_buf->add( '' ). + lo_buf->add( '/* GLOBALS */' ). + lo_buf->add( '' ). + lo_buf->add( 'body {' ). + lo_buf->add( ' overflow-x: hidden;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'body.centered {' ). + lo_buf->add( ' max-width: 1280px;' ). + lo_buf->add( ' margin: 0 auto;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'body.full_width {' ). + lo_buf->add( ' width:100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'a, a:visited {' ). + lo_buf->add( ' text-decoration: none;' ). + lo_buf->add( '}' ). + lo_buf->add( 'a:hover, a:active {' ). + lo_buf->add( ' cursor: pointer;' ). + lo_buf->add( ' text-decoration: underline;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'img {' ). + lo_buf->add( ' border-width: 0px;' ). + lo_buf->add( ' vertical-align: middle;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table { border-collapse: collapse; }' ). + lo_buf->add( 'pre { display: inline; }' ). + lo_buf->add( 'sup {' ). + lo_buf->add( ' vertical-align: top;' ). + lo_buf->add( ' position: relative;' ). + lo_buf->add( ' top: -0.5em;' ). + lo_buf->add( ' font-size: 75%;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'input, textarea, select {' ). + lo_buf->add( ' padding: 3px 0.5em;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( 'input:focus, textarea:focus {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.cursor-pointer {' ). + lo_buf->add( ' cursor: pointer;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'span.separator {' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( ' padding-right: 0.5em;' ). + lo_buf->add( ' opacity: 0.25;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* MODIFIERS */' ). + lo_buf->add( '' ). + lo_buf->add( '.emphasis { font-weight: bold !important; }' ). + lo_buf->add( '.crossout { text-decoration: line-through !important; }' ). + lo_buf->add( '.right { text-align:right; }' ). + lo_buf->add( '.center { text-align:center; }' ). + lo_buf->add( '.paddings { padding: 0.5em 0.5em; }' ). + lo_buf->add( '.pad-sides { padding-left: 0.3em; padding-right: 0.3em; }' ). + lo_buf->add( '.pad-1em { padding: 1em 1em; }' ). + lo_buf->add( '.margin-v5 { margin-top: 0.5em; margin-bottom: 0.5em; }' ). + lo_buf->add( '.margin-v1 { margin-top: 1em; margin-bottom: 1em; }' ). + lo_buf->add( '.indent5em { padding-left: 0.5em; }' ). + lo_buf->add( '.pad4px { padding: 4px; }' ). + lo_buf->add( '.w100 { width: 100%; }' ). + lo_buf->add( '.wmin { width: 1%; }' ). + lo_buf->add( '.w40 { width: 40%; }' ). + lo_buf->add( '.float-right { float: right; }' ). + lo_buf->add( '.pad-right { padding-right: 6px; }' ). + lo_buf->add( '.no-pad { padding: 0px !important; }' ). + lo_buf->add( '.inline { display: inline; }' ). + lo_buf->add( '.hidden { visibility: hidden; }' ). + lo_buf->add( '.nodisplay { display: none }' ). + lo_buf->add( '.m-em5-sides { margin-left: 0.5em; margin-right: 0.5em }' ). + lo_buf->add( '.w600px { width: 600px }' ). + lo_buf->add( '.w800px { width: 800px }' ). + lo_buf->add( '.w1000px { width: 1000px }' ). + lo_buf->add( '.wmax600px { max-width: 600px }' ). + lo_buf->add( '.auto-center { /* use with max-width */' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( ' margin-left: auto;' ). + lo_buf->add( ' margin-right: auto;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'span.boxed {' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' padding: 4px 7px;' ). + lo_buf->add( ' margin-left: 0.2em;' ). + lo_buf->add( ' margin-right: 0.2em;' ). + lo_buf->add( ' font-size: smaller;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.boxed i.icon {' ). + lo_buf->add( ' padding-right: 5px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.red-filled-set {' ). + lo_buf->add( ' border-width: 0px;' ). + lo_buf->add( ' color: hsl(0, 78%, 93%);' ). + lo_buf->add( ' background-color: hsl(0, 78%, 65%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.green-filled-set {' ). + lo_buf->add( ' border-width: 0px;' ). + lo_buf->add( ' color: hsl(120, 45%, 90%);' ). + lo_buf->add( ' background-color: hsl(120, 27%, 60%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.yellow-filled-set {' ). + lo_buf->add( ' border-width: 0px;' ). + lo_buf->add( ' color: hsl(45, 99%, 90%);' ). + lo_buf->add( ' background-color: hsl(45, 100%, 46%);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* PANELS */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.panel {' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' padding: 0.5em 0.5em;' ). + lo_buf->add( ' margin: 0.5em 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.dummydiv {' ). + lo_buf->add( ' padding: 0.5em 1em;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'a.close-btn {' ). + lo_buf->add( ' text-decoration: none;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* STRUCTURE DIVS, HEADER & FOOTER */' ). + lo_buf->add( '' ). + lo_buf->add( 'div#header {' ). + lo_buf->add( ' padding: 0.5em 0.5em;' ). + lo_buf->add( ' border-bottom: 3px double;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div#header > div { display: inline-block }' ). + lo_buf->add( '' ). + lo_buf->add( '.logo .icon { display: inline-block }' ). + lo_buf->add( '.logo .icon:before { width: auto }' ). + lo_buf->add( '' ). + lo_buf->add( '/* official logo colors, not vars, redefine in themes directly*/' ). + lo_buf->add( '.logo .icon.icon-git-alt { color: #f03c2e }' ). + lo_buf->add( '.logo .icon.icon-abapgit {' ). + lo_buf->add( ' color: #362701;' ). + lo_buf->add( ' vertical-align: bottom;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div#header .logo { font-size: x-large }' ). + lo_buf->add( 'div#header .page-title { font-size: x-large }' ). + lo_buf->add( 'div#header span.spacer {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' padding-right: 0.25em;' ). + lo_buf->add( ' padding-left: 0.25em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div#footer .sponsor a { font-size: smaller; }' ). + lo_buf->add( 'div#footer .logo { font-size: large }' ). + lo_buf->add( 'div#footer {' ). + lo_buf->add( ' padding: 0.5em 0.5em;' ). + lo_buf->add( ' border-top: 3px double;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div#footer .version {' ). + lo_buf->add( ' margin-top: 0.5em;' ). + lo_buf->add( ' font-size: small;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '#debug-output {' ). + lo_buf->add( ' text-align: right;' ). + lo_buf->add( ' padding-right: 0.5em;' ). + lo_buf->add( ' font-size: smaller;' ). + lo_buf->add( '}' ). + lo_buf->add( '#debug-output p {' ). + lo_buf->add( ' margin-top: 0em;' ). + lo_buf->add( ' margin-bottom: 0em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* ERROR LOG */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.log {' ). + lo_buf->add( ' padding: 6px;' ). + lo_buf->add( ' margin: 4px;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-radius: 4px;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.log > span { display:block; }' ). + lo_buf->add( 'div.log .icon { padding-right: 6px; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* REPOSITORY */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.repo {' ). + lo_buf->add( ' padding: 0.5em 1em 0.5em 1em;' ). + lo_buf->add( ' position: relative;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_name span.name {' ). + lo_buf->add( ' font-weight: bold;' ). + lo_buf->add( ' font-size: 14pt;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_name a.url {' ). + lo_buf->add( ' font-size: 12pt;' ). + lo_buf->add( ' margin-left: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_name span.url {' ). + lo_buf->add( ' font-size: 12pt;' ). + lo_buf->add( ' margin-left: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_name .icon {' ). + lo_buf->add( ' padding-right: 4px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_attr {' ). + lo_buf->add( ' font-size: 12pt;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_attr span {' ). + lo_buf->add( ' margin-left: 0.2em;' ). + lo_buf->add( ' margin-right: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_attr span.bg_marker {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' font-size: 8pt;' ). + lo_buf->add( ' padding: 4px 2px 3px 2px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* ABAPGIT OBJECTS */' ). + lo_buf->add( '' ). + lo_buf->add( 'span.branch,' ). + lo_buf->add( 'span.user-box,' ). + lo_buf->add( 'span.package-box,' ). + lo_buf->add( 'span.path-box,' ). + lo_buf->add( 'span.transport-box {' ). + lo_buf->add( ' padding: 2px 4px;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-radius: 4px;' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'span.package-box i.icon {' ). + lo_buf->add( ' margin-right: 0.15em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* MISC AND REFACTOR */' ). + lo_buf->add( '' ). + lo_buf->add( '.hidden-submit {' ). + lo_buf->add( ' border: 0 none;' ). + lo_buf->add( ' height: 0;' ). + lo_buf->add( ' width: 0;' ). + lo_buf->add( ' padding: 0;' ). + lo_buf->add( ' margin: 0;' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' overflow: hidden;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* STATE BLOCK COMMON*/' ). + lo_buf->add( '' ). + lo_buf->add( 'span.state-block {' ). + lo_buf->add( ' margin-left: 1em;' ). + lo_buf->add( ' font-family: Consolas, "Lucida Console", Courier, monospace;' ). + lo_buf->add( ' font-size: x-small;' ). + lo_buf->add( ' vertical-align: 13%;' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( ' white-space: nowrap;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.state-block span {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' padding: 0px 3px;' ). + lo_buf->add( ' border-width: 1px;' ). + lo_buf->add( ' border-style: solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* REPOSITORY TABLE*/' ). + lo_buf->add( '' ). + lo_buf->add( 'div.repo_container {' ). + lo_buf->add( ' position: relative;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.repo_banner {' ). + lo_buf->add( ' margin: 0em 1em 1em;' ). + lo_buf->add( ' padding: 0.5em 0.5em;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( ' font-size: 85%;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.repo_tab {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( ' line-height: 1.2;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_tab th {' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( ' padding: 0.5em;' ). + lo_buf->add( ' border-bottom: 1px solid;' ). + lo_buf->add( ' font-weight: normal;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_tab td {' ). + lo_buf->add( ' vertical-align: middle;' ). + lo_buf->add( ' padding-top: 2px;' ). + lo_buf->add( ' padding-bottom: 2px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab td.icon {' ). + lo_buf->add( ' width: 1px;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( ' padding-left: 8px;' ). + lo_buf->add( ' padding-right: 4px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab td.transport {' ). + lo_buf->add( ' width: 140px;' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_tab td.type {' ). + lo_buf->add( ' width: 4em;' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab td.filename{' ). + lo_buf->add( ' padding-left: 1em;' ). + lo_buf->add( ' word-break: break-all;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab td.object {' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab td.files {' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( ' line-height: 1.5;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab tr.object_row{' ). + lo_buf->add( ' border-top: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab td.cmd, .repo_tab th.cmd {' ). + lo_buf->add( ' text-align: right;' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( ' padding-right: 0.7em;' ). + lo_buf->add( ' min-width: 70px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab th.cmd .icon{' ). + lo_buf->add( ' padding-right: 8px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_tab tr:first-child td { border-top: 0px; }' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab tr:hover td {' ). + lo_buf->add( ' background-image: linear-gradient(rgba(0, 0, 0, 0.075), rgba(0, 0, 0, 0.075));' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* STAGE */' ). + lo_buf->add( '' ). + lo_buf->add( 'th.stage-status { width: 30px; }' ). + lo_buf->add( 'th.stage-objtype { width: 30px; }' ). + lo_buf->add( 'input.stage-filter { width: 18em; }' ). + lo_buf->add( '' ). + lo_buf->add( '.stage_tab {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' margin-top: 0.2em;' ). + lo_buf->add( ' line-height: 1.5;' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td {' ). + lo_buf->add( ' border-top: 1px solid;' ). + lo_buf->add( ' vertical-align: middle;' ). + lo_buf->add( ' padding: 2px 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab th {' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( ' font-weight: normal;' ). + lo_buf->add( ' padding: 4px 0.5em;' ). + lo_buf->add( ' border-bottom: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td.status {' ). + lo_buf->add( ' width: 2em;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td.highlight {' ). + lo_buf->add( ' font-weight: bold;' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td.name {' ). + lo_buf->add( ' word-break: break-all;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.stage_tab tr:first-child td { border-top: 0px; }' ). + lo_buf->add( '' ). + lo_buf->add( '.stage_tab tr:hover td {' ). + lo_buf->add( ' background-image: linear-gradient(rgba(0, 0, 0, 0.075), rgba(0, 0, 0, 0.075));' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.stage_tab td.cmd { cursor: pointer; }' ). + lo_buf->add( '.stage_tab td.cmd a { padding: 0px 4px; }' ). + lo_buf->add( '.stage_tab th.cmd a { padding: 0px 4px; }' ). + lo_buf->add( '.stage_tab tbody tr:first-child td { padding-top: 0.5em; }' ). + lo_buf->add( '.stage_tab tbody tr:last-child td { padding-bottom: 0.5em; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* COMMIT */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.form-container {' ). + lo_buf->add( ' padding: 1em 1em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'form.aligned-form {' ). + lo_buf->add( ' display: table;' ). + lo_buf->add( ' border-spacing: 2px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'form.aligned-form label {' ). + lo_buf->add( ' padding-right: 1em;' ). + lo_buf->add( ' vertical-align: middle;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'form.aligned-form select {' ). + lo_buf->add( ' padding-right: 1em;' ). + lo_buf->add( ' vertical-align: middle;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'form.aligned-form span.sub-title {' ). + lo_buf->add( ' font-size: smaller;' ). + lo_buf->add( ' padding-top: 8px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'form.aligned-form div.row { display: table-row; }' ). + lo_buf->add( 'form.aligned-form label { display: table-cell; }' ). + lo_buf->add( 'form.aligned-form input { display: table-cell; }' ). + lo_buf->add( 'form.aligned-form input[type="text"] { width: 25em; }' ). + lo_buf->add( 'form.aligned-form span.cell { display: table-cell; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* SETTINGS STYLES */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.settings_container {' ). + lo_buf->add( ' padding: 0.5em 0.5em 1em;' ). + lo_buf->add( ' font-size: 10pt;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.settings_section {' ). + lo_buf->add( ' margin-left:50px' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.settings td:first-child {' ). + lo_buf->add( ' padding-left: 1em;' ). + lo_buf->add( ' padding-right: 1em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* DIFF */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.diff {' ). + lo_buf->add( ' padding: 0.7em' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.diff_head {' ). + lo_buf->add( ' padding-bottom: 0.7em;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.diff_name {' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.diff_changed_by {' ). + lo_buf->add( ' float: right;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.diff_banner {' ). + lo_buf->add( ' border-style: solid;' ). + lo_buf->add( ' border-width: 1px;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' padding-left: 0.3em;' ). + lo_buf->add( ' padding-right: 0.3em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.diff_content {' ). + lo_buf->add( ' border-top: 1px solid;' ). + lo_buf->add( ' border-bottom: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.diff_content tbody tr td{' ). + lo_buf->add( ' width: 50%;' ). + lo_buf->add( ' vertical-align: top' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.diff_head span.state-block {' ). + lo_buf->add( ' margin-left: 0.5em;' ). + lo_buf->add( ' font-size: inherit;' ). + lo_buf->add( ' vertical-align: initial;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.diff_head span.state-block span {' ). + lo_buf->add( ' padding: 0px 4px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* DIFF TABLE */' ). + lo_buf->add( '' ). + lo_buf->add( 'table.diff_tab {' ). + lo_buf->add( ' font-family: Consolas, Courier, monospace;' ). + lo_buf->add( ' font-size: 10pt;' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab td,' ). + lo_buf->add( 'table.diff_tab th {' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( ' padding-right: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab th {' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( ' font-weight: normal;' ). + lo_buf->add( ' padding-top: 3px;' ). + lo_buf->add( ' padding-bottom: 3px;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab thead.header th {' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( ' font-weight: bold;' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( ' font-size: 9pt;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab td.num, th.num {' ). + lo_buf->add( ' width: 1%;' ). + lo_buf->add( ' min-width: 2em;' ). + lo_buf->add( ' padding-right: 8px;' ). + lo_buf->add( ' padding-left: 8px;' ). + lo_buf->add( ' text-align: right !important;' ). + lo_buf->add( ' border-left: 1px solid;' ). + lo_buf->add( ' border-right: 1px solid;' ). + lo_buf->add( ' -ms-user-select: none;' ). + lo_buf->add( ' user-select: none;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab td.patch, th.patch {' ). + lo_buf->add( ' width: 1%;' ). + lo_buf->add( ' min-width: 1.5em;' ). + lo_buf->add( ' padding-right: 8px;' ). + lo_buf->add( ' padding-left: 8px;' ). + lo_buf->add( ' text-align: right !important;' ). + lo_buf->add( ' border-left: 1px solid;' ). + lo_buf->add( ' border-right: 1px solid;' ). + lo_buf->add( ' -ms-user-select: none;' ). + lo_buf->add( ' user-select: none;' ). + lo_buf->add( ' cursor: pointer;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.diff_tab tr.diff_line:hover td {' ). + lo_buf->add( ' background-image: linear-gradient(rgba(0, 0, 0, 0.075), rgba(0, 0, 0, 0.075));' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.diff_tab td.num::before {' ). + lo_buf->add( ' content: attr(line-num);' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab code {' ). + lo_buf->add( ' font-family: inherit;' ). + lo_buf->add( ' white-space: pre;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab td.code {' ). + lo_buf->add( ' word-wrap: break-word;' ). + lo_buf->add( ' white-space: pre-wrap;' ). + lo_buf->add( ' overflow: visible;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.diff_tab tbody tr:first-child td { padding-top: 0.5em; }' ). + lo_buf->add( 'table.diff_tab tbody tr:last-child td { padding-bottom: 0.5em; }' ). + lo_buf->add( '' ). + lo_buf->add( 'table.diff_tab td.mark, th.mark {' ). + lo_buf->add( ' width: 0.1%;' ). + lo_buf->add( ' -ms-user-select: none;' ). + lo_buf->add( ' user-select: none;' ). + lo_buf->add( ' cursor: default;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.diff_select_left td.diff_right,' ). + lo_buf->add( '.diff_select_left td.diff_right *,' ). + lo_buf->add( '.diff_select_left th.diff_right,' ). + lo_buf->add( '.diff_select_left th.diff_right *,' ). + lo_buf->add( '.diff_select_right td.diff_left,' ). + lo_buf->add( '.diff_select_right td.diff_left *,' ). + lo_buf->add( '.diff_select_right th.diff_left,' ). + lo_buf->add( '.diff_select_right th.diff_left * {' ). + lo_buf->add( ' -ms-user-select: none;' ). + lo_buf->add( ' user-select: none;' ). + lo_buf->add( ' cursor: text;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.diff_select_left td.diff_left,' ). + lo_buf->add( '.diff_select_left td.diff_left *,' ). + lo_buf->add( '.diff_select_left th.diff_left,' ). + lo_buf->add( '.diff_select_left th.diff_left *,' ). + lo_buf->add( '.diff_select_right td.diff_right,' ). + lo_buf->add( '.diff_select_right td.diff_right *,' ). + lo_buf->add( '.diff_select_right th.diff_right,' ). + lo_buf->add( '.diff_select_right th.diff_right * {' ). + lo_buf->add( ' -ms-user-select: text;' ). + lo_buf->add( ' user-select: text;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'td.diff_others::selection,' ). + lo_buf->add( 'td.diff_others *::selection,' ). + lo_buf->add( 'th.diff_others::selection,' ). + lo_buf->add( 'th.diff_others *::selection {' ). + lo_buf->add( ' background-color: transparent;' ). + lo_buf->add( ' cursor: default;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.diff_select_left td.diff_right::selection,' ). + lo_buf->add( '.diff_select_left td.diff_right *::selection,' ). + lo_buf->add( '.diff_select_left th.diff_right::selection,' ). + lo_buf->add( '.diff_select_left th.diff_right *::selection,' ). + lo_buf->add( '.diff_select_right td.diff_left::selection,' ). + lo_buf->add( '.diff_select_right td.diff_left *::selection,' ). + lo_buf->add( '.diff_select_right th.diff_left::selection,' ). + lo_buf->add( '.diff_select_right th.diff_left *::selection {' ). + lo_buf->add( ' background-color: transparent;' ). + lo_buf->add( ' cursor: text;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* DEBUG INFO STYLES */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.debug_container {' ). + lo_buf->add( ' padding: 0.5em;' ). + lo_buf->add( ' font-size: 10pt;' ). + lo_buf->add( ' font-family: Consolas, Courier, monospace;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.debug_container p {' ). + lo_buf->add( ' margin: 0px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* *** */' ). + lo_buf->add( '' ). + lo_buf->add( 'li.action_link.enabled{' ). + lo_buf->add( ' visibility: visible;' ). + lo_buf->add( ' position: relative;' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'li.action_link:not(enabled){' ). + lo_buf->add( ' visibility: hidden;' ). + lo_buf->add( ' position: fixed; /* so it does not take up space when hidden */' ). + lo_buf->add( ' display: none;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* TUTORIAL */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.tutorial {' ). + lo_buf->add( ' margin-top: 3px;' ). + lo_buf->add( ' padding: 0.5em 1em 0.5em 1em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.tutorial li { margin: 2px 0px }' ). + lo_buf->add( 'div.tutorial h1 { font-size: 18pt; }' ). + lo_buf->add( 'div.tutorial h2 { font-size: 14pt;}' ). + lo_buf->add( '' ). + lo_buf->add( '/* MENU */' ). + lo_buf->add( '' ). + lo_buf->add( '/* Special credits to example at https://codepen.io/philhoyt/pen/ujHzd */' ). + lo_buf->add( '/* container div, aligned left, but with .float-right modifier aligns right */' ). + lo_buf->add( '' ). + lo_buf->add( '.nav-container ul {' ). + lo_buf->add( ' list-style: none;' ). + lo_buf->add( ' position: relative;' ). + lo_buf->add( ' float: left;' ). + lo_buf->add( ' margin: 0;' ). + lo_buf->add( ' padding: 0;' ). + lo_buf->add( ' white-space: nowrap;' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( '}' ). + lo_buf->add( '.nav-container.float-right ul { float: right; }' ). + lo_buf->add( '' ). + lo_buf->add( '.nav-container ul a {' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( ' text-decoration: none;' ). + lo_buf->add( ' line-height: 30px;' ). + lo_buf->add( ' padding: 0 12px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* clearfix https://css-tricks.com/snippets/css/clear-fix/ */' ). + lo_buf->add( '.nav-container:after {' ). + lo_buf->add( ' clear: both;' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( ' content: "";' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* submenues align to left or right border of the active item' ). + lo_buf->add( ' depending on .float-right modifier */' ). + lo_buf->add( '.nav-container ul li {' ). + lo_buf->add( ' position: relative;' ). + lo_buf->add( ' float: left;' ). + lo_buf->add( ' margin: 0;' ). + lo_buf->add( ' padding: 0;' ). + lo_buf->add( '}' ). + lo_buf->add( '.nav-container.float-right ul ul { left: auto; right: 0; }' ). + lo_buf->add( '.nav-container ul li.current-menu-item { font-weight: 700; }' ). + lo_buf->add( '.nav-container ul li.force-nav-hover ul { display: block; }' ). + lo_buf->add( '.nav-container ul li:hover > ul { display: block; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* special selection style for 1st level items (see also .corner below) */' ). + lo_buf->add( '' ). + lo_buf->add( '.nav-container ul ul {' ). + lo_buf->add( ' display: none;' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' top: 100%;' ). + lo_buf->add( ' left: 0;' ). + lo_buf->add( ' z-index: 1;' ). + lo_buf->add( ' padding: 0;' ). + lo_buf->add( ' box-shadow: 1px 1px 3px 0px #bbb;' ). + lo_buf->add( ' max-height: 700px;' ). + lo_buf->add( ' overflow: auto;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.nav-container ul ul li {' ). + lo_buf->add( ' float: none;' ). + lo_buf->add( ' min-width: 160px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.nav-container ul ul a {' ). + lo_buf->add( ' line-height: 120%;' ). + lo_buf->add( ' padding: 8px 15px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.nav-container ul ul ul {' ). + lo_buf->add( ' top: 0;' ). + lo_buf->add( ' left: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.nav-container.float-right ul ul ul {' ). + lo_buf->add( ' left: auto;' ). + lo_buf->add( ' right: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Minizone to extent hover area,' ). + lo_buf->add( ' aligned to the left or to the right of the selected item' ). + lo_buf->add( ' depending on .float-right modifier */' ). + lo_buf->add( '.nav-container > ul > li > div.minizone {' ). + lo_buf->add( ' display: none;' ). + lo_buf->add( ' z-index: 1;' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' padding: 0px;' ). + lo_buf->add( ' width: 16px;' ). + lo_buf->add( ' height: 100%;' ). + lo_buf->add( ' bottom: 0px;' ). + lo_buf->add( ' left: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '.nav-container > ul > li:hover div.minizone { display: block; }' ). + lo_buf->add( '.nav-container.float-right > ul > li > div.minizone {' ). + lo_buf->add( ' left: auto;' ). + lo_buf->add( ' right: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* icons - text-align strictly left - otherwise look ugly' ). + lo_buf->add( ' + bite a bit of left padding for nicer look' ). + lo_buf->add( ' + forbids item text wrapping (maybe can be done differently) */' ). + lo_buf->add( '.nav-container ul ul li a .icon {' ). + lo_buf->add( ' padding-right: 10px;' ). + lo_buf->add( ' margin-left: -3px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.nav-container ul.with-icons li {' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( ' white-space: nowrap;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Special .corner modifier - hangs menu at the top right corner' ). + lo_buf->add( ' and cancels 1st level background coloring */' ). + lo_buf->add( '.nav-container.corner {' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' right: 0px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Toolbar separator style */' ). + lo_buf->add( '.nav-container ul ul li.separator {' ). + lo_buf->add( ' font-size: x-small;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( ' padding: 4px 0;' ). + lo_buf->add( ' text-transform: uppercase;' ). + lo_buf->add( ' border-bottom: 1px solid;' ). + lo_buf->add( ' border-top: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '.nav-container ul ul li.separator:first-child { border-top: none; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* NEWS ANNOUNCEMENT */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel {' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' z-index: 99;' ). + lo_buf->add( ' top: 36px;' ). + lo_buf->add( ' left: 50%;' ). + lo_buf->add( ' width: 40em;' ). + lo_buf->add( ' margin-left: -20em;' ). + lo_buf->add( ' box-shadow: 1px 1px 3px 2px #dcdcdc;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel-fixed {' ). + lo_buf->add( ' position: fixed;' ). + lo_buf->add( ' top: 15%;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel div.info-hint {' ). + lo_buf->add( ' text-transform: uppercase;' ). + lo_buf->add( ' font-size: small;' ). + lo_buf->add( ' padding: 8px 6px 0px;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel div.info-title {' ). + lo_buf->add( ' text-transform: uppercase;' ). + lo_buf->add( ' font-size: small;' ). + lo_buf->add( ' padding: 6px;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel div.info-title a.close-btn {' ). + lo_buf->add( ' padding-left: 12px;' ). + lo_buf->add( ' padding-right: 2px;' ). + lo_buf->add( ' position: relative;' ). + lo_buf->add( ' bottom: 1px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel div.info-list {' ). + lo_buf->add( ' padding: 0.8em 0.7em 1em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel ul {' ). + lo_buf->add( ' padding-left: 10px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel li {' ). + lo_buf->add( ' padding-left: 0px;' ). + lo_buf->add( ' list-style-type: none;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel h1:first-child { margin: auto; }' ). + lo_buf->add( 'div.info-panel h1 {' ). + lo_buf->add( ' font-size: inherit;' ). + lo_buf->add( ' padding: 6px 4px;' ). + lo_buf->add( ' margin: 4px auto auto;' ). + lo_buf->add( ' text-decoration: underline;' ). + lo_buf->add( ' font-weight: normal;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel .version-marker {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' margin-left: 20px;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' padding: 0px 6px;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel .update { border: 1px solid; }' ). + lo_buf->add( 'div.info-panel div.info-list td { padding-right: 1em }' ). + lo_buf->add( '' ). + lo_buf->add( '/* ERROR MESSAGE PANEL */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.message-panel {' ). + lo_buf->add( ' z-index: 99;' ). + lo_buf->add( ' box-shadow: 2px 2px 4px 0px hsla(0, 0%, 0%, .1);' ). + lo_buf->add( ' padding: 0.5em 1em;' ). + lo_buf->add( ' position: fixed;' ). + lo_buf->add( ' bottom: 12px;' ). + lo_buf->add( ' width: 95%;' ). + lo_buf->add( ' margin: 0 auto;' ). + lo_buf->add( ' max-width: 1248px;' ). + lo_buf->add( '' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-radius: 5px;' ). + lo_buf->add( ' border-color: hsl(0, 42%, 64%);' ). + lo_buf->add( ' background-color: hsla(0, 42%, 90%, 1);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.message-panel-bar {' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' bottom: 10px;' ). + lo_buf->add( ' right: 10px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.message-panel-commands {' ). + lo_buf->add( ' display: none;' ). + lo_buf->add( ' margin-right: 2em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.message-panel-commands a {' ). + lo_buf->add( ' padding: 0em 0.5em;' ). + lo_buf->add( ' border-left: 1px solid;' ). + lo_buf->add( ' border-left-color: #ccc;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.message-panel-commands a:first-child {' ). + lo_buf->add( ' padding-left: 0;' ). + lo_buf->add( ' border-left: none;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.message-panel:hover .message-panel-commands {' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* TOOLTIP TEXT */' ). + lo_buf->add( '' ). + lo_buf->add( '.link-hint {' ). + lo_buf->add( ' line-height: 1em;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( ' padding: 5px 15px;' ). + lo_buf->add( ' border-radius: 4px;' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' z-index: 1;' ). + lo_buf->add( ' margin-top: -30px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.link-hint-a {' ). + lo_buf->add( ' margin-left: -60px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.link-hint-input {' ). + lo_buf->add( ' margin-left: -30px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.link-hint-i {' ). + lo_buf->add( ' margin-left: -30px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.link-hint .pending { color: hsla(0, 0%, 0%, 0.2); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* Tooltip arrow */' ). + lo_buf->add( '.link-hint::after {' ). + lo_buf->add( ' content: "";' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' top: 100%;' ). + lo_buf->add( ' left: 50%;' ). + lo_buf->add( ' margin-left: -5px;' ). + lo_buf->add( ' border-width: 5px;' ). + lo_buf->add( ' border-style: solid;' ). + lo_buf->add( ' border-color: transparent;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* HOTKEYS */' ). + lo_buf->add( '' ). + lo_buf->add( 'ul.hotkeys {' ). + lo_buf->add( ' list-style-type: none;' ). + lo_buf->add( ' padding: 0;' ). + lo_buf->add( ' margin: 0;' ). + lo_buf->add( ' font-size: smaller;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'ul.hotkeys span.key-id {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' padding: 1px 7px;' ). + lo_buf->add( ' width: 3em;' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( ' margin-top: 0.2em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'ul.hotkeys span.key-descr {' ). + lo_buf->add( ' margin-left: 1.2em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.corner-hint {' ). + lo_buf->add( ' position: fixed;' ). + lo_buf->add( ' bottom: 10px;' ). + lo_buf->add( ' right: 10px;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' padding: 4px;' ). + lo_buf->add( ' font-size: smaller;' ). + lo_buf->add( ' opacity: 0.5;' ). + lo_buf->add( ' z-index: 99;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Commit popup */' ). + lo_buf->add( 'table.commit tr .title {' ). + lo_buf->add( ' font-weight: bold;' ). + lo_buf->add( ' vertical-align: top;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Repo overview */' ). + lo_buf->add( '.repo-overview {' ). + lo_buf->add( ' padding: 0.5em 0.7em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview table {' ). + lo_buf->add( ' font-size: 90%;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview-toolbar {' ). + lo_buf->add( ' padding: 1em 1em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview-toolbar label {' ). + lo_buf->add( ' margin-right: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview th {' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( ' font-weight: normal;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview table {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview thead tr {' ). + lo_buf->add( ' border-bottom: 1px solid;' ). + lo_buf->add( ' line-height: 1.5;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview tfoot tr {' ). + lo_buf->add( ' border-top: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview tr.favorite .icon-star {' ). + lo_buf->add( ' color: #5e8dc9 !important;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview td,' ). + lo_buf->add( '.repo-overview th {' ). + lo_buf->add( ' padding: 6px 6px; /* maybe use height ? */' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview .ro-detail { display: none; }' ). + lo_buf->add( '.repo-overview .ro-go a {' ). + lo_buf->add( ' padding: 0px 0.15em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview .ro-go a:hover {' ). + lo_buf->add( ' color: #ff721e;' ). + lo_buf->add( ' text-decoration: none;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview td.labels {' ). + lo_buf->add( ' max-width: 18ch;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* REPO LABELS */' ). + lo_buf->add( '' ). + lo_buf->add( '.repo-label-catalog {' ). + lo_buf->add( ' padding: 1em 1em;' ). + lo_buf->add( ' margin-top: -1em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-label-catalog label {' ). + lo_buf->add( ' margin-right: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( 'ul.repo-labels {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' list-style-type: none;' ). + lo_buf->add( ' padding-inline-start: 0px;' ). + lo_buf->add( ' padding-left: 0px;' ). + lo_buf->add( ' margin-block-start: 0px;' ). + lo_buf->add( ' margin-block-end: 0px;' ). + lo_buf->add( ' margin-top: 0px;' ). + lo_buf->add( ' margin-bottom: 0px;' ). + lo_buf->add( '}' ). + lo_buf->add( 'ul.repo-labels li {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' padding: 3px 5px;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' border-style: solid;' ). + lo_buf->add( ' border-width: 1px;' ). + lo_buf->add( ' margin-bottom: 2px;' ). + lo_buf->add( '}' ). + lo_buf->add( 'ul.repo-labels li a {' ). + lo_buf->add( ' color: inherit;' ). + lo_buf->add( '}' ). + lo_buf->add( 'ul.repo-labels li:not(:last-child) { margin-right: 0.3em; }' ). + lo_buf->add( 'table ul.repo-labels li {' ). + lo_buf->add( ' font-size: 90%;' ). + lo_buf->add( ' padding: 2px 4px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* LABEL COLORS */' ). + lo_buf->add( '' ). + lo_buf->add( '.rl-white {' ). + lo_buf->add( ' color: hsl(0, 0%, 30%);' ). + lo_buf->add( ' background-color: hsl(0, 0%, 100%);' ). + lo_buf->add( ' border-color: hsl(0, 0%, 80%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-white-b {' ). + lo_buf->add( ' color: hsl(214, 100%, 60%);' ). + lo_buf->add( ' background-color: hsl(0, 0%, 100%);' ). + lo_buf->add( ' border-color: hsl(214, 89%, 86%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-white-r {' ). + lo_buf->add( ' color: hsl(0, 100%, 41%);' ). + lo_buf->add( ' background-color: hsl(0, 0%, 100%);' ). + lo_buf->add( ' border-color: hsl(0, 100%, 85%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-grey {' ). + lo_buf->add( ' color: hsl(0, 0%, 100%);' ). + lo_buf->add( ' background-color: hsl(0, 0%, 70%);' ). + lo_buf->add( ' border-color: hsl(0, 0%, 60%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-dark-w {' ). + lo_buf->add( ' color: hsl(0, 0%, 100%);' ). + lo_buf->add( ' background-color: hsl(0, 0%, 25%);' ). + lo_buf->add( ' border-color: hsl(0, 0%, 25%);;' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-dark-y {' ). + lo_buf->add( ' color: hsl(43, 95%, 75%);' ). + lo_buf->add( ' background-color: hsl(0, 0%, 25%);' ). + lo_buf->add( ' border-color: hsl(0, 0%, 25%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-dark-r {' ). + lo_buf->add( ' color: hsl(0, 100%, 74%);' ). + lo_buf->add( ' background-color: hsl(0, 0%, 25%);' ). + lo_buf->add( ' border-color: hsl(0, 0%, 25%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-dark-b {' ). + lo_buf->add( ' color: hsl(227, 92%, 80%);' ). + lo_buf->add( ' background-color: hsl(0, 0%, 25%);' ). + lo_buf->add( ' border-color: hsl(0, 0%, 25%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-lightblue {' ). + lo_buf->add( ' color: hsl(217, 80%, 25%);' ). + lo_buf->add( ' background-color: hsl(216, 76%, 84%);' ). + lo_buf->add( ' border-color: hsl(216, 76%, 73%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-darkblue {' ). + lo_buf->add( ' color: hsl(218, 77%, 88%);' ). + lo_buf->add( ' background-color: hsl(217, 66%, 32%);' ). + lo_buf->add( ' border-color: hsl(217, 66%, 20%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-lightgreen {' ). + lo_buf->add( ' color: hsl(153, 76%, 18%);' ). + lo_buf->add( ' background-color: hsl(152, 65%, 82%);' ). + lo_buf->add( ' border-color: hsl(152, 65%, 65%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-darkgreen {' ). + lo_buf->add( ' color: hsl(0, 0%, 100%);' ). + lo_buf->add( ' background-color: hsl(153, 77%, 37%);' ). + lo_buf->add( ' border-color: hsl(153, 77%, 30%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-lightred {' ). + lo_buf->add( ' color: hsl(8, 86%, 29%);' ). + lo_buf->add( ' background-color: hsl(8, 74%, 80%);' ). + lo_buf->add( ' border-color: hsl(8, 74%, 70%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-darkred {' ). + lo_buf->add( ' color: hsl(7, 76%, 85%);' ). + lo_buf->add( ' background-color: hsl(8, 77%, 29%);' ). + lo_buf->add( ' border-color: hsl(8, 77%, 20%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-yellow {' ). + lo_buf->add( ' color: hsl(44, 87%, 22%);' ). + lo_buf->add( ' background-color: hsl(44, 94%, 87%);' ). + lo_buf->add( ' border-color: hsl(44, 94%, 70%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-darkyellow {' ). + lo_buf->add( ' color: hsl(49, 100%, 24%);' ). + lo_buf->add( ' background-color: hsl(49, 100%, 64%);' ). + lo_buf->add( ' border-color: hsl(49, 100%, 49%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-orange {' ). + lo_buf->add( ' color: hsl(0, 0%, 100%);' ). + lo_buf->add( ' background-color: hsl(19, 100%, 61%);' ). + lo_buf->add( ' border-color: hsl(19, 100%, 50%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-brown {' ). + lo_buf->add( ' color: hsl(33, 100%, 89%);' ). + lo_buf->add( ' background-color: hsl(33, 66%, 39%);' ). + lo_buf->add( ' border-color: hsl(33, 66%, 30%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-pink {' ). + lo_buf->add( ' color: hsl(340, 35%, 45%);' ). + lo_buf->add( ' background-color: hsl(340, 85%, 77%);' ). + lo_buf->add( ' border-color: hsl(340, 85%, 65%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-teal {' ). + lo_buf->add( ' color: hsl(0, 0%, 100%);' ). + lo_buf->add( ' background-color: hsl(191, 61%, 45%);' ). + lo_buf->add( ' border-color: hsl(191, 61%, 37%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.rl-darkviolet {' ). + lo_buf->add( ' color: hsl(0, 0%, 100%);' ). + lo_buf->add( ' background-color: hsl(258, 100%, 80%);' ). + lo_buf->add( ' border-color: hsl(258, 100%, 72%);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* FORM FIELD HELP TOOLTIP */' ). + lo_buf->add( '' ). + lo_buf->add( '.form-field-help-tooltip {' ). + lo_buf->add( ' position: relative;' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( '}' ). + lo_buf->add( '.form-field-help-tooltip .form-field-help-tooltip-text {' ). + lo_buf->add( ' visibility: hidden;' ). + lo_buf->add( ' width: 40ch;' ). + lo_buf->add( ' border-radius: 5px;' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' z-index: 1;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' padding: 0.4em 0.6em;' ). + lo_buf->add( ' text-align: justify;' ). + lo_buf->add( '}' ). + lo_buf->add( '.form-field-help-tooltip .form-field-help-tooltip-text p {' ). + lo_buf->add( ' margin: 0px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.form-field-help-tooltip .form-field-help-tooltip-text {' ). + lo_buf->add( ' background-color: white;' ). + lo_buf->add( ' border-color: #888;' ). + lo_buf->add( '}' ). + lo_buf->add( '.form-field-help-tooltip:hover .form-field-help-tooltip-text {' ). + lo_buf->add( ' visibility: visible;' ). + lo_buf->add( '}' ). + lo_buf->add( '.form-field-help-tooltip code {' ). + lo_buf->add( ' border-radius: 5px;' ). + lo_buf->add( ' font-size: 90%;' ). + lo_buf->add( ' padding: 0.1em 0.4em;' ). + lo_buf->add( ' background-color: #e2e2e2;' ). + lo_buf->add( ' word-wrap: break-word;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* TABLE COMPONENT DEFAULT STYLE */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.default-table-container {' ). + lo_buf->add( ' padding: 6px 0.5em;' ). + lo_buf->add( ' background-color: white;' ). + lo_buf->add( ' border-radius: 6px;' ). + lo_buf->add( ' overflow-x: hidden;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.default-table {' ). + lo_buf->add( ' line-height: 1.5;' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.default-table thead tr:last-child {' ). + lo_buf->add( ' border-bottom: #efefef solid 1px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.default-table td,' ). + lo_buf->add( 'table.default-table th {' ). + lo_buf->add( ' padding: 6px 8px;' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.default-table th {' ). + lo_buf->add( ' white-space: nowrap;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.default-table th span.sort-arrow {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' color: hsla(0, 0%, 0%, 0.15);' ). + lo_buf->add( ' width: 1em; /*for constant width*/' ). + lo_buf->add( ' text-align: right;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.default-table th span.sort-active {' ). + lo_buf->add( ' color: #4078c0;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.default-table th {' ). + lo_buf->add( ' padding-bottom: 10px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* CODE INSPECTOR */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci {' ). + lo_buf->add( ' margin-top: 1px;' ). + lo_buf->add( ' margin-bottom: 1px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-msg {' ). + lo_buf->add( ' padding: 0.7em 1em 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.ci-msg span.ci-variant {' ). + lo_buf->add( ' font-weight: bold;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-stats {' ). + lo_buf->add( ' padding: 0.5em 1em;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.ci-stats span.count {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' padding: 2px 6px;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-detail {' ). + lo_buf->add( ' padding: 6px 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-detail table td,' ). + lo_buf->add( 'div.ci-detail table th {' ). + lo_buf->add( ' vertical-align: text-top;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-detail table th[data-cid="kind"],' ). + lo_buf->add( 'div.ci-detail table th[data-cid="obj_type"] {' ). + lo_buf->add( ' white-space: nowrap' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-detail table td[data-cid="kind"] span {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' width: 1em;' ). + lo_buf->add( ' height: 1em;' ). + lo_buf->add( ' vertical-align: inherit;' ). + lo_buf->add( ' color: transparent;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-detail table td[data-cid="text"] {' ). + lo_buf->add( ' font-size: smaller;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* FLOATING BUTTONS */' ). + lo_buf->add( '' ). + lo_buf->add( '.floating-button {' ). + lo_buf->add( ' position: fixed;' ). + lo_buf->add( ' top: 8em;' ). + lo_buf->add( ' right: 2.8em;' ). + lo_buf->add( ' padding: 1em 1.8em;' ). + lo_buf->add( ' border-radius: 4px;' ). + lo_buf->add( ' border-width: 1px;' ). + lo_buf->add( ' border-style: solid;' ). + lo_buf->add( ' box-shadow: 2px 2px 6px 0px #ccc;' ). + lo_buf->add( ' cursor: pointer;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* COMMAND PALETTE */' ). + lo_buf->add( '' ). + lo_buf->add( '.cmd-palette {' ). + lo_buf->add( ' position: absolute;' ). + lo_buf->add( ' z-index: 99;' ). + lo_buf->add( ' top: 36px;' ). + lo_buf->add( ' left: 50%;' ). + lo_buf->add( ' width: 40em;' ). + lo_buf->add( ' margin-left: -20em;' ). + lo_buf->add( ' box-shadow: 1px 1px 3px 2px #dcdcdc;' ). + lo_buf->add( ' background-color: white;' ). + lo_buf->add( ' border: solid 2px;' ). + lo_buf->add( ' padding: 0px 1px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.cmd-palette input {' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( ' box-sizing: border-box;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.cmd-palette ul {' ). + lo_buf->add( ' max-height: 10em;' ). + lo_buf->add( ' overflow-y: scroll;' ). + lo_buf->add( ' margin: 4px 0;' ). + lo_buf->add( ' padding: 2px 4px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.cmd-palette li {' ). + lo_buf->add( ' list-style-type: none;' ). + lo_buf->add( ' cursor: default;' ). + lo_buf->add( ' padding: 4px 6px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.cmd-palette li .icon {' ). + lo_buf->add( ' margin-right: 10px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.cmd-palette li .icon:before {' ). + lo_buf->add( ' width: 1.1em;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* SETTINGS */' ). + lo_buf->add( '' ). + lo_buf->add( 'table.settings_tab {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' max-width: 600px;' ). + lo_buf->add( ' line-height: 1.5;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.settings_tab th {' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( ' padding: 0.5em;' ). + lo_buf->add( ' border-bottom: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.settings_tab td {' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( ' padding: 0.3em 0.5em;' ). + lo_buf->add( ' border-top: 1px solid;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.settings_tab input {' ). + lo_buf->add( ' border: none;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( '}' ). + lo_buf->add( 'settings_tab tr:first-child td { border-top: 0px; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* UNIT TESTS */' ). + lo_buf->add( '' ). + lo_buf->add( 'table.unit_tests {' ). + lo_buf->add( ' line-height: 1.5;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* DIALOGS */' ). + lo_buf->add( '' ). + lo_buf->add( '.dialog {' ). + lo_buf->add( ' margin: 0 auto;' ). + lo_buf->add( ' margin-top: 1em;' ). + lo_buf->add( ' margin-bottom: 1em;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' padding: 1em 1em;' ). + lo_buf->add( ' border-radius: 6px;' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog-form {' ). + lo_buf->add( ' width: 600px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog-form-center {' ). + lo_buf->add( ' margin: 1em auto 1em;' ). + lo_buf->add( ' max-width: 600px;' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog ul {' ). + lo_buf->add( ' padding: 0;' ). + lo_buf->add( ' margin: 0;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li {' ). + lo_buf->add( ' padding: 5px 10px;' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( ' list-style: none;' ). + lo_buf->add( ' position: relative;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.dialog-commands {' ). + lo_buf->add( ' text-align: right;' ). + lo_buf->add( ' margin-top: 12px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.dialog-commands a {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' cursor: pointer;' ). + lo_buf->add( ' text-decoration: none;' ). + lo_buf->add( ' padding: 6px 12px;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.dialog-commands input[type="button"],' ). + lo_buf->add( '.dialog li.dialog-commands input[type="submit"] {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' padding: 6px 12px;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' cursor: pointer;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.dialog-commands a.main,' ). + lo_buf->add( '.dialog li.dialog-commands input[type="submit"].main {' ). + lo_buf->add( ' border: 1px solid transparent;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog label {' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( ' font-size: 90%;' ). + lo_buf->add( ' margin-top: 6px;' ). + lo_buf->add( ' margin-bottom: 6px;' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.error small {' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( ' font-size: 75%;' ). + lo_buf->add( ' margin: 4px 0px;' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.hidden {' ). + lo_buf->add( ' padding: 0px 0px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .radio-container {' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' padding: 4px;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog input[type="checkbox"] + label {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog input[type="password"],' ). + lo_buf->add( '.dialog input[type="text"] {' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( ' box-sizing: border-box;' ). + lo_buf->add( ' height: 2.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog input[type="number"] {' ). + lo_buf->add( ' width: 25%;' ). + lo_buf->add( ' box-sizing: border-box;' ). + lo_buf->add( ' height: 2.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog textarea {' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( ' box-sizing: border-box;' ). + lo_buf->add( ' padding: 10px;' ). + lo_buf->add( ' font-family: Arial,Helvetica,sans-serif;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .radio-container input[type="radio"] {' ). + lo_buf->add( ' visibility: hidden;' ). + lo_buf->add( ' display: none;' ). + lo_buf->add( ' height: 0px;' ). + lo_buf->add( ' width: 0px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .radio-container input[type="radio"] + label {' ). + lo_buf->add( ' border: 1px solid transparent;' ). + lo_buf->add( ' cursor: pointer;' ). + lo_buf->add( ' width: auto;' ). + lo_buf->add( ' margin: 0px;' ). + lo_buf->add( ' padding: 3px 8px;' ). + lo_buf->add( ' border-radius: 2px;' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .radio-container input[type="radio"]:checked + label {' ). + lo_buf->add( ' border: 1px solid transparent;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog table {' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog table thead td {' ). + lo_buf->add( ' font-size: 14px;' ). + lo_buf->add( ' height: 2.5em;' ). + lo_buf->add( ' background-color: #ddd;' ). + lo_buf->add( ' border: 1px solid #ccc;' ). + lo_buf->add( ' padding: 0px 10px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog table tbody td {' ). + lo_buf->add( ' border: 1px solid #ccc;' ). + lo_buf->add( ' background-color: white;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog table td input {' ). + lo_buf->add( ' border: 0px;' ). + lo_buf->add( ' background: none;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.with-command div.input-container {' ). + lo_buf->add( ' display: table-cell;' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.with-command div.command-container {' ). + lo_buf->add( ' display: table-cell;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.with-command input[type="button"],' ). + lo_buf->add( '.dialog li.with-command input[type="submit"] {' ). + lo_buf->add( ' height: 2.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog fieldset {' ). + lo_buf->add( ' margin-top: 1em;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-right: none;' ). + lo_buf->add( ' border-left: none;' ). + lo_buf->add( ' border-bottom: none;' ). + lo_buf->add( ' border-radius: 6px; /* does not work in IE ? */' ). + lo_buf->add( ' padding-bottom: 1em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog fieldset:first-child {' ). + lo_buf->add( ' margin-top: 0;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog fieldset legend {' ). + lo_buf->add( ' font-size: large;' ). + lo_buf->add( ' font-weight: bold;' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( ' padding-right: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .dialog-help {' ). + lo_buf->add( ' float: left;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* STICKY HEADERS */' ). + lo_buf->add( '' ). + lo_buf->add( '/* https://www.w3schools.com/howto/howto_js_navbar_sticky.asp */' ). + lo_buf->add( '/* Note: We have to use JS since IE does not support CSS position:sticky */' ). + lo_buf->add( '' ). + lo_buf->add( '/* The sticky class is added to the navbar with JS when it reaches its scroll position */' ). + lo_buf->add( '.sticky {' ). + lo_buf->add( ' position: fixed;' ). + lo_buf->add( ' top: 0;' ). + lo_buf->add( ' z-index: 10;' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( ' padding: 0.5em;' ). + lo_buf->add( ' margin-bottom: 3px;' ). + lo_buf->add( ' max-height: 47px;' ). + lo_buf->add( ' max-width: 1265px; /* if set to 1280px, then actual width will be 1296px (strange) */' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.sticky_full_width {' ). + lo_buf->add( ' position: fixed;' ). + lo_buf->add( ' top: 0;' ). + lo_buf->add( ' z-index: 10;' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( ' padding: 0.5em 0.5em;' ). + lo_buf->add( ' margin-bottom: 3px;' ). + lo_buf->add( ' max-height: 47px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.sticky_full_width .nav-container {' ). + lo_buf->add( ' margin-right: 18px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Add some top padding to the page content to prevent sudden quick movement' ). + lo_buf->add( ' as the navigation bar gets a new position at the top of the page */' ). + lo_buf->add( '.sticky + .not_sticky {' ). + lo_buf->add( ' padding-top: 50px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Give more padding if browser control warning is present */' ). + lo_buf->add( '.sticky:has(.browser-control-warning) + .not_sticky,' ). + lo_buf->add( '.sticky_full_width:has(.browser-control-warning) + .not_sticky {' ). + lo_buf->add( ' padding-top: 75px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.sticky_full_width + .not_sticky {' ). + lo_buf->add( ' padding-top: 50px;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Light toolbar or blocks with separators */' ). + lo_buf->add( '.toolbar-light a {' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( ' padding-right: 0.5em;' ). + lo_buf->add( ' border-left: 1px solid;' ). + lo_buf->add( ' border-left-color: #ccc;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.toolbar-light a:first-child {' ). + lo_buf->add( ' padding-left: 0;' ). + lo_buf->add( ' border-left: none;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Warning if wrong browser control is used */' ). + lo_buf->add( '.browser-control-warning {' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* MODAL POPUP */' ). + lo_buf->add( '/* https://css-tricks.com/considerations-styling-modal/ */' ). + lo_buf->add( '' ). + lo_buf->add( '.modal {' ). + lo_buf->add( ' /* center on screen */' ). + lo_buf->add( ' position: fixed;' ). + lo_buf->add( ' top: 50%;' ). + lo_buf->add( ' left: 50%;' ). + lo_buf->add( ' transform: translate(-50%, -50%);' ). + lo_buf->add( ' /* size */' ). + lo_buf->add( ' max-width: 100%;' ). + lo_buf->add( ' max-height: 100%;' ). + lo_buf->add( ' /* infront of overlay */' ). + lo_buf->add( ' z-index: 1010;' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.modal-guts {' ). + lo_buf->add( ' padding: 6px 6px;' ). + lo_buf->add( ' /* let it scroll */' ). + lo_buf->add( ' overflow: auto;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.modal-guts .dialog {' ). + lo_buf->add( ' box-shadow: 2px 2px 4px 1px rgba(0,0,0,0.3);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.modal-overlay {' ). + lo_buf->add( ' /* darken and prevent interactions with background */' ). + lo_buf->add( ' z-index: 1000;' ). + lo_buf->add( ' position: fixed;' ). + lo_buf->add( ' top: 0;' ). + lo_buf->add( ' left: 0;' ). + lo_buf->add( ' width: 100%;' ). + lo_buf->add( ' height: 100%;' ). + lo_buf->add( ' background: rgba(0, 0, 0, 0.3);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.modal .radio-container label {' ). + lo_buf->add( ' /* hacky, improve later, get rid of !important, hook it to a named style instead */' ). + lo_buf->add( ' border-radius: 3px !important;' ). + lo_buf->add( ' border: 1px solid rgba(0, 0, 0, 0.3) !important;' ). + lo_buf->add( ' margin-bottom: 2px !important;' ). + lo_buf->add( '}' ). + lo_buf->add( '.modal .radio-container label:hover {' ). + lo_buf->add( ' background-color: rgba(0, 0, 0, 0.1);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* WHERE USED PAGE */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.wu-header {' ). + lo_buf->add( ' padding: 8px 0.5em;' ). + lo_buf->add( ' margin: 0px 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.wu {' ). + lo_buf->add( ' padding: 8px 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.wu table thead tr:first-child {' ). + lo_buf->add( ' /* TODO: maybe move this to default table style */' ). + lo_buf->add( ' color: hsl(0, 0%, 80%);' ). + lo_buf->add( ' text-transform: uppercase;' ). + lo_buf->add( ' font-size: 90%;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.wu table tbody {' ). + lo_buf->add( ' font-size: 90%;' ). + lo_buf->add( ' vertical-align: baseline; /* for second lines, used type */' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.wu table td[data-cid="dep_obj_name"] span.used-obj {' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( ' color: hsl(0, 0%, 70%);' ). + lo_buf->add( ' font-size: smaller;' ). + lo_buf->add( ' text-transform: lowercase;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.wu table td[data-gid="where"],' ). + lo_buf->add( 'div.wu table th[data-gid="where"] {' ). + lo_buf->add( ' background-color: hsl(0, 0%, 97%);' ). + lo_buf->add( '}' ). + li_asset_man->register_asset( + iv_url = 'css/common.css' + iv_type = 'text/css' + iv_mime_name = 'ZABAPGIT_CSS_COMMON' + iv_inline = lo_buf->join_w_newline_and_flush( ) ). + +**************************************************** +* abapmerge Pragma [include] - ZABAPGIT_CSS_THEME_DEFAULT.W3MI.DATA.CSS +**************************************************** + lo_buf->add( '/*' ). + lo_buf->add( ' * ABAPGIT COLOR THEME CSS - DEFAULT' ). + lo_buf->add( ' */' ). + lo_buf->add( '' ). + lo_buf->add( ':root {' ). + lo_buf->add( ' --theme-background-color: #E8E8E8;' ). + lo_buf->add( ' --theme-container-background-color: #f2f2f2;' ). + lo_buf->add( ' --theme-container-border-color: lightgrey;' ). + lo_buf->add( ' --theme-table-background-color: white;' ). + lo_buf->add( ' --theme-table-head-background-color: #edf2f9;' ). + lo_buf->add( ' --theme-table-border-color: #ddd;' ). + lo_buf->add( ' --theme-table-cell-border-color: #eee;' ). + lo_buf->add( '' ). + lo_buf->add( ' --theme-primary-font: "72", Arial, Helvetica, sans-serif;' ). + lo_buf->add( ' --theme-primary-font-color: #333333;' ). + lo_buf->add( ' --theme-primary-font-color-reduced: #ccc;' ). + lo_buf->add( ' --theme-font-size: 12pt;' ). + lo_buf->add( ' --theme-link-color: #4078c0;' ). + lo_buf->add( '' ). + lo_buf->add( ' --theme-greyscale-dark: #808080;' ). + lo_buf->add( ' --theme-greyscale-medium: #b3b3b3;' ). + lo_buf->add( ' --theme-greyscale-light: #ccc;' ). + lo_buf->add( ' --theme-greyscale-lighter: lightgrey;' ). + lo_buf->add( ' --theme-linkhint-background: lightgreen;' ). + lo_buf->add( ' --theme-debug-color: #aaa;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* GLOBALS */' ). + lo_buf->add( '' ). + lo_buf->add( 'body {' ). + lo_buf->add( ' background-color: var(--theme-background-color);' ). + lo_buf->add( ' font-family: var(--theme-primary-font);' ). + lo_buf->add( ' color: var(--theme-primary-font-color);' ). + lo_buf->add( ' font-size: var(--theme-font-size);' ). + lo_buf->add( '}' ). + lo_buf->add( 'a, a:visited { color: var(--theme-link-color); }' ). + lo_buf->add( '.link {' ). + lo_buf->add( ' color: var(--theme-link-color);' ). + lo_buf->add( ' cursor: pointer;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'input, textarea, select { border-color: #ddd; }' ). + lo_buf->add( 'input:focus, textarea:focus { border-color: #8cadd9; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* COLOR PALETTE */' ). + lo_buf->add( '' ). + lo_buf->add( '.grey { color: var(--theme-greyscale-lighter) !important; }' ). + lo_buf->add( '.grey70 { color: var(--theme-greyscale-medium) !important; }' ). + lo_buf->add( '.grey80 { color: var(--theme-greyscale-light) !important; }' ). + lo_buf->add( '.darkgrey { color: var(--theme-greyscale-dark) !important; }' ). + lo_buf->add( '.bgorange { background-color: orange; }' ). + lo_buf->add( '.attention { color: red !important; }' ). + lo_buf->add( '.error { color: #d41919 !important; }' ). + lo_buf->add( '.warning { color: #efb301 !important; }' ). + lo_buf->add( '.success { color: green !important; }' ). + lo_buf->add( '.blue { color: #5e8dc9 !important; }' ). + lo_buf->add( '.red { color: red !important; }' ). + lo_buf->add( '.white { color: white !important; }' ). + lo_buf->add( '.pink { color: pink !important; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* FLOATING BUTTONS AND COLOR SETS */' ). + lo_buf->add( '' ). + lo_buf->add( '.blue-set {' ). + lo_buf->add( ' border-color: #abc3e3;' ). + lo_buf->add( ' color: #5e8dc9;' ). + lo_buf->add( ' background-color: #d9e4f2;' ). + lo_buf->add( '}' ). + lo_buf->add( '.grey-set {' ). + lo_buf->add( ' border-color: #c7c7c7;' ). + lo_buf->add( ' color: var(--theme-greyscale-dark);' ). + lo_buf->add( ' background-color: #e6e6e6;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* ABAPGIT OBJECTS */' ). + lo_buf->add( '' ). + lo_buf->add( 'span.user-box {' ). + lo_buf->add( ' border-color: #c2d4ea;' ). + lo_buf->add( ' background-color: #d9e4f2;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.package-box {' ). + lo_buf->add( ' border-color: #d3ccd2;' ). + lo_buf->add( ' background-color: #ebe3ea;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.path-box,' ). + lo_buf->add( 'span.transport-box {' ). + lo_buf->add( ' border-color: #a7e3cf;' ). + lo_buf->add( ' background-color: #dbf3eb;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* PANELS */' ). + lo_buf->add( '/* TODO: add warning and error colors */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.panel.success {' ). + lo_buf->add( ' color: #589a58 !important;' ). + lo_buf->add( ' background-color: #c5eac5;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.panel.error {' ). + lo_buf->add( ' color: #d41919;' ). + lo_buf->add( ' background-color: #fad6d6;' ). + lo_buf->add( '}' ). + lo_buf->add( '#debug-output { color: var(--theme-debug-color); }' ). + lo_buf->add( 'div.dummydiv { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* STRUCTURE DIVS, HEADER & FOOTER */' ). + lo_buf->add( '' ). + lo_buf->add( 'div#header {' ). + lo_buf->add( ' background-color: var(--theme-background-color);' ). + lo_buf->add( ' border-bottom-color: var(--theme-container-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( 'div#header .page-title { color: var(--theme-greyscale-medium); }' ). + lo_buf->add( 'div#footer .version { color: var(--theme-greyscale-medium); }' ). + lo_buf->add( 'div#footer { border-top-color: var(--theme-container-border-color); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* ERROR LOG */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.log {' ). + lo_buf->add( ' background-color: #fee6e6;' ). + lo_buf->add( ' border-color: #fdcece;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* REPOSITORY */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.repo { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( '.repo_name span.name { color: #333; }' ). + lo_buf->add( '.repo_name span.url { color: var(--theme-primary-font-color-reduced); }' ). + lo_buf->add( '.repo_name a.url { color: var(--theme-primary-font-color-reduced); }' ). + lo_buf->add( '.repo_name a.url:hover { color: var(--theme-link-color); }' ). + lo_buf->add( '.repo_attr { color: grey; }' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_attr span.bg_marker {' ). + lo_buf->add( ' border-color: #d2d2d2;' ). + lo_buf->add( ' background-color: #d8d8d8;' ). + lo_buf->add( ' color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_attr span.branch_head {' ). + lo_buf->add( ' border-color: #d8dff3;' ). + lo_buf->add( ' background-color: #eceff9;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'span.branch {' ). + lo_buf->add( ' border-color: #d9d9d9;' ). + lo_buf->add( ' background-color: #e2e2e2;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'span.branch_branch {' ). + lo_buf->add( ' border-color: #e7d9b1;' ). + lo_buf->add( ' background-color: #f8f0d8;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* REPOSITORY TABLE*/' ). + lo_buf->add( '' ). + lo_buf->add( 'table.repo_tab {' ). + lo_buf->add( ' border-color: var(--theme-table-border-color);' ). + lo_buf->add( ' background-color: var(--theme-table-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_tab th {' ). + lo_buf->add( ' color: var(--theme-link-color);' ). + lo_buf->add( ' background-color: #edf2f9;' ). + lo_buf->add( ' border-bottom-color: var(--theme-table-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_tab td {' ). + lo_buf->add( ' color: var(--theme-primary-font-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab tr.object_row{' ). + lo_buf->add( ' border-top-color: var(--theme-table-cell-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_tab .inactive { color: orange; }' ). + lo_buf->add( '.repo_tab tr.unsupported { color: var(--theme-greyscale-lighter); }' ). + lo_buf->add( '.repo_tab tr.modified { background-color: #fbf7e9; }' ). + lo_buf->add( '.repo_tab td.current_dir { color: var(--theme-primary-font-color-reduced); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* STAGE */' ). + lo_buf->add( '' ). + lo_buf->add( '.stage_tab {' ). + lo_buf->add( ' border-color: #ddd;' ). + lo_buf->add( ' background-color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab th {' ). + lo_buf->add( ' color: var(--theme-greyscale-dark);' ). + lo_buf->add( ' background-color: #edf2f9;' ). + lo_buf->add( ' border-bottom-color: #ddd;' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td {' ). + lo_buf->add( ' color: var(--theme-greyscale-medium);' ). + lo_buf->add( ' border-top-color: var(--theme-table-cell-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td.status {' ). + lo_buf->add( ' color: var(--theme-primary-font-color-reduced);' ). + lo_buf->add( ' background-color: #fafafa;' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td.highlight { color: #444 !important; }' ). + lo_buf->add( '.stage_tab td.method { font-weight: bold; }' ). + lo_buf->add( '.stage_tab mark {' ). + lo_buf->add( ' color: white;' ). + lo_buf->add( ' background-color: #79a0d2;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* COMMIT */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.form-container { background-color: #F8F8F8; }' ). + lo_buf->add( 'form.aligned-form label { color: var(--theme-greyscale-medium); }' ). + lo_buf->add( 'form.aligned-form span.sub-title { color: var(--theme-greyscale-medium); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* SETTINGS STYLES */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.settings_container {' ). + lo_buf->add( ' color: #444;' ). + lo_buf->add( ' background-color: var(--theme-container-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* DIFF */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.diff { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( 'span.diff_name { color: grey; }' ). + lo_buf->add( 'span.diff_name strong { color: #333; }' ). + lo_buf->add( 'span.diff_changed_by { color: grey; }' ). + lo_buf->add( 'span.diff_changed_by span.user {' ). + lo_buf->add( ' border-color: #c2d4ea;' ). + lo_buf->add( ' background-color: #d9e4f2;' ). + lo_buf->add( '}' ). + lo_buf->add( '.diff_ins {' ). + lo_buf->add( ' border-color: #abf2ab;' ). + lo_buf->add( ' background-color: #e0ffe0;' ). + lo_buf->add( '}' ). + lo_buf->add( '.diff_del {' ). + lo_buf->add( ' border-color: #ff667d;' ). + lo_buf->add( ' background-color: #ffccd4;' ). + lo_buf->add( '}' ). + lo_buf->add( '.diff_upd {' ). + lo_buf->add( ' border-color: #dada00;' ). + lo_buf->add( ' background-color: #ffffcc;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.diff_content {' ). + lo_buf->add( ' background-color: #fff;' ). + lo_buf->add( ' border-top-color: #ddd;' ). + lo_buf->add( ' border-bottom-color: #ddd;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* STATE BLOCK COLORS */' ). + lo_buf->add( '' ). + lo_buf->add( 'span.state-block span.added {' ). + lo_buf->add( ' background-color: #69ad74;' ). + lo_buf->add( ' border-color: #579e64;' ). + lo_buf->add( ' color: white;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.state-block span.changed {' ). + lo_buf->add( ' background-color: #e0c150;' ). + lo_buf->add( ' border-color: #d4af25;' ). + lo_buf->add( ' color: white;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.state-block span.mixed {' ). + lo_buf->add( ' background-color: #e0c150;' ). + lo_buf->add( ' border-color: #579e64;' ). + lo_buf->add( ' color: #69ad74;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.state-block span.deleted {' ). + lo_buf->add( ' background-color: #c76861;' ). + lo_buf->add( ' border-color: #b8605a;' ). + lo_buf->add( ' color: white;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.state-block span.none {' ). + lo_buf->add( ' background-color: #e8e8e8;' ). + lo_buf->add( ' border-color: #dbdbdb;' ). + lo_buf->add( ' color: #c8c8c8;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* DIFF TABLE */' ). + lo_buf->add( '' ). + lo_buf->add( 'table.diff_tab td,' ). + lo_buf->add( 'table.diff_tab th {' ). + lo_buf->add( ' color: #444;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab thead.header th {' ). + lo_buf->add( ' color: #eee;' ). + lo_buf->add( ' background-color: var(--theme-greyscale-medium);' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab thead.nav_line {' ). + lo_buf->add( ' background-color: #edf2f9;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab thead.nav_line th {' ). + lo_buf->add( ' color: var(--theme-greyscale-medium);' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab td.num, th.num {' ). + lo_buf->add( ' color: var(--theme-primary-font-color-reduced);' ). + lo_buf->add( ' border-left-color: var(--theme-table-cell-border-color);' ). + lo_buf->add( ' border-right-color: var(--theme-table-cell-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.diff_tab td.patch, th.patch {' ). + lo_buf->add( ' color: var(--theme-primary-font-color-reduced);' ). + lo_buf->add( ' border-left-color: var(--theme-table-cell-border-color);' ). + lo_buf->add( ' border-right-color: var(--theme-table-cell-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* STYLES FOR SYNTAX HIGHLIGHTING */' ). + lo_buf->add( '' ). + lo_buf->add( '/* ABAP */' ). + lo_buf->add( '.syntax-hl span.keyword { color: #0a69ce; }' ). + lo_buf->add( '.syntax-hl span.text { color: #48ce4f; }' ). + lo_buf->add( '.syntax-hl span.comment { color: var(--theme-greyscale-dark); font-style: italic; }' ). + lo_buf->add( '/* XML+HTML */' ). + lo_buf->add( '.syntax-hl span.xml_tag { color: #457ce3; }' ). + lo_buf->add( '.syntax-hl span.attr { color: #b777fb; }' ). + lo_buf->add( '.syntax-hl span.attr_val { color: #7a02f9; }' ). + lo_buf->add( '/* CSS+JS */' ). + lo_buf->add( '.syntax-hl span.properties { color:#0a69ce; }' ). + lo_buf->add( '.syntax-hl span.values { color:blue; }' ). + lo_buf->add( '.syntax-hl span.units { color:maroon; }' ). + lo_buf->add( '.syntax-hl span.selectors { color:purple; }' ). + lo_buf->add( '.syntax-hl span.functions { color:purple; }' ). + lo_buf->add( '.syntax-hl span.colors { color:purple; }' ). + lo_buf->add( '.syntax-hl span.extensions { color:darkblue; }' ). + lo_buf->add( '.syntax-hl span.at_rules { color:darkblue; }' ). + lo_buf->add( '.syntax-hl span.html { color:green; }' ). + lo_buf->add( '.syntax-hl span.variables { color:purple; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* DEBUG INFO STYLES */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.debug_container {' ). + lo_buf->add( ' color: #444;' ). + lo_buf->add( ' background-color: var(--theme-container-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* Repo overview */' ). + lo_buf->add( '' ). + lo_buf->add( '.repo-overview { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( '.repo-overview table {' ). + lo_buf->add( ' background-color: var(--theme-table-background-color);' ). + lo_buf->add( ' border-color: var(--theme-table-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview th {' ). + lo_buf->add( ' color: var(--theme-link-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview thead tr {' ). + lo_buf->add( ' background-color: var(--theme-table-head-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview thead tr,' ). + lo_buf->add( '.repo-overview tfoot tr {' ). + lo_buf->add( ' border-color: var(--theme-table-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo-overview a.remote_repo { color: var(--theme-primary-font-color-reduced); }' ). + lo_buf->add( '.repo-overview a.remote_repo:hover { color: var(--theme-link-color); }' ). + lo_buf->add( '.repo-overview tbody tr:hover td { background-color: hsla(214, 50%, 50%, 0.05); }' ). + lo_buf->add( '.repo-overview tbody tr.selected { background-color: hsla(214, 50%, 75%, 0.33); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* TUTORIAL */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.tutorial { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( 'div.tutorial hr { border-color: var(--theme-greyscale-light); }' ). + lo_buf->add( 'div.tutorial h1, h2 { color: #404040; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* MENU */' ). + lo_buf->add( '' ). + lo_buf->add( '.nav-container ul li:hover { background-color: #fff; }' ). + lo_buf->add( '.nav-container ul ul li:hover { background-color: #f6f6f6; }' ). + lo_buf->add( '.nav-container > ul > li:hover > a { background-color: #ffffff80; }' ). + lo_buf->add( '.nav-container ul ul { background-color: #fff; }' ). + lo_buf->add( '.nav-container.corner > ul > li:hover > a { background-color: inherit; }' ). + lo_buf->add( '' ). + lo_buf->add( '.nav-container ul ul li.separator {' ). + lo_buf->add( ' color: var(--theme-greyscale-medium);' ). + lo_buf->add( ' border-bottom-color: #eee;' ). + lo_buf->add( ' border-top-color: #eee;' ). + lo_buf->add( '}' ). + lo_buf->add( '.nav-container ul ul li.separator:hover { background-color: inherit; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* NEWS ANNOUNCEMENT */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.info-panel { background-color: white; }' ). + lo_buf->add( 'div.info-panel div.info-hint { color: var(--theme-greyscale-light); }' ). + lo_buf->add( 'div.info-panel div.info-title {' ). + lo_buf->add( ' color: #f8f8f8;' ). + lo_buf->add( ' background-color: #888;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.info-panel div.info-title a.close-btn { color: #d8d8d8; }' ). + lo_buf->add( 'div.info-panel div.info-list { color: #444; }' ). + lo_buf->add( 'div.info-panel .version-marker {' ). + lo_buf->add( ' color: white;' ). + lo_buf->add( ' border-color: #c0c0c0;' ). + lo_buf->add( ' background-color: var(--theme-greyscale-light);' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.info-panel .update {' ). + lo_buf->add( ' border-color: #e8ba30;' ). + lo_buf->add( ' background-color: #f5c538;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* TOOLTIPS TEXT */' ). + lo_buf->add( '' ). + lo_buf->add( '.link-hint { color: var(--theme-primary-font-color); }' ). + lo_buf->add( '.link-hint { background-color: var(--theme-linkhint-background) }' ). + lo_buf->add( '.link-hint::after { border-top-color: var(--theme-linkhint-background) }' ). + lo_buf->add( '' ). + lo_buf->add( '/* HOTKEYS */' ). + lo_buf->add( '' ). + lo_buf->add( 'ul.hotkeys span.key-id {' ). + lo_buf->add( ' background-color: #f0f0f0;' ). + lo_buf->add( ' border-color: #dcdcdc;' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.corner-hint {' ). + lo_buf->add( ' color: var(--theme-greyscale-medium);' ). + lo_buf->add( ' border-color: var(--theme-greyscale-light);' ). + lo_buf->add( ' background-color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* CODE INSPECTOR */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-msg span.ci-variant { color: var(--theme-primary-font-color); }' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-stats span.error-count {' ). + lo_buf->add( ' border-color: hsl(350, 100%, 80%);' ). + lo_buf->add( ' background-color: hsl(350, 100%, 90%);' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.ci-stats span.warn-count {' ). + lo_buf->add( ' border-color: hsl(60, 100%, 42%);' ). + lo_buf->add( ' background-color: hsl(60, 100%, 90%);' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.ci-stats span.info-count {' ). + lo_buf->add( ' border-color: hsl(120, 80%, 80%);' ). + lo_buf->add( ' background-color: hsl(120, 80%, 94%);' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.ci-stats span.all-count {' ). + lo_buf->add( ' border-color: hsl(235, 100%, 89%);' ). + lo_buf->add( ' background-color: hsl(235, 100%, 93%);' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.ci-detail table td[data-cid="text"] {' ). + lo_buf->add( ' color: hsl(0, 0%, 40%);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'div.ci-detail table tr[data-kind="error"] td[data-cid="kind"] span {' ). + lo_buf->add( ' background-color: hsl(0, 100%, 68%);' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.ci-detail table tr[data-kind="warning"] td[data-cid="kind"] span {' ). + lo_buf->add( ' background-color:hsl(52, 100%, 49%);' ). + lo_buf->add( '}' ). + lo_buf->add( 'div.ci-detail table tr[data-kind="info"] td[data-cid="kind"] span {' ). + lo_buf->add( ' background-color: hsl(118, 67%, 47%);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* COMMAND PALETTE */' ). + lo_buf->add( '' ). + lo_buf->add( '.cmd-palette {' ). + lo_buf->add( ' border-color: #ccc;' ). + lo_buf->add( '}' ). + lo_buf->add( '.cmd-palette li.selected {' ). + lo_buf->add( ' background-color: hsla(214, 50%, 90%, 1);' ). + lo_buf->add( '}' ). + lo_buf->add( '.cmd-palette mark {' ). + lo_buf->add( ' color: white;' ). + lo_buf->add( ' background-color: #79a0d2;' ). + lo_buf->add( ' /* todo merge with stage search */' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* SETTINGS */' ). + lo_buf->add( '' ). + lo_buf->add( 'table.settings_tab {' ). + lo_buf->add( ' background-color: #fff;' ). + lo_buf->add( ' border-color: #ddd;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.settings_tab th {' ). + lo_buf->add( ' color: #888888;' ). + lo_buf->add( ' border-bottom-color: #ddd;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.settings_tab td {' ). + lo_buf->add( ' color: #333;' ). + lo_buf->add( ' border-top-color: #eee;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.settings_tab input {' ). + lo_buf->add( ' background-color: #f8f8f8;' ). + lo_buf->add( '}' ). + lo_buf->add( 'table.settings_tab input:focus {' ). + lo_buf->add( ' background-color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* HTML FORMS */' ). + lo_buf->add( '' ). + lo_buf->add( '.dialog input::placeholder { color: #ccc }' ). + lo_buf->add( '.dialog textarea::placeholder { color: #ccc }' ). + lo_buf->add( '.dialog input:-ms-input-placeholder { color: #ccc }' ). + lo_buf->add( '.dialog textarea:-ms-input-placeholder { color: #ccc }' ). + lo_buf->add( '.dialog {' ). + lo_buf->add( ' border-color: #ccc;' ). + lo_buf->add( ' background-color: #f0f0f0;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.dialog-commands a,' ). + lo_buf->add( '.dialog li.dialog-commands input[type="submit"] {' ). + lo_buf->add( ' border-color: #ccc;' ). + lo_buf->add( ' background-color: #ddd;' ). + lo_buf->add( ' color: #000;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.dialog-commands a.main,' ). + lo_buf->add( '.dialog li.dialog-commands input[type="submit"].main {' ). + lo_buf->add( ' background-color: #64a8ff;' ). + lo_buf->add( ' color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog label {' ). + lo_buf->add( ' color: #444;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog label em {' ). + lo_buf->add( ' color: #64a8ff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.error small {' ). + lo_buf->add( ' color: #ff5959;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.error input[type="number"],' ). + lo_buf->add( '.dialog li.error input[type="text"] {' ). + lo_buf->add( ' border-color: #ff5959;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .radio-container {' ). + lo_buf->add( ' border-color: #ddd;' ). + lo_buf->add( ' background-color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .radio-container input[type="radio"]:checked + label {' ). + lo_buf->add( ' background-color: #64a8ff;' ). + lo_buf->add( ' color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.with-command input[type="button"]:hover,' ). + lo_buf->add( '.dialog li.with-command input[type="submit"]:hover {' ). + lo_buf->add( ' background-color: #64a8ff;' ). + lo_buf->add( ' color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog fieldset {' ). + lo_buf->add( ' border-color: #dfdfdf;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog fieldset legend {' ). + lo_buf->add( ' color: #444;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog input:read-only {' ). + lo_buf->add( ' background-color: #f4f4f4;' ). + lo_buf->add( ' color: var(--theme-greyscale-dark);' ). + lo_buf->add( '}' ). + lo_buf->add( '/* for IE */' ). + lo_buf->add( '.dialog input[readonly] {' ). + lo_buf->add( ' background-color: #f4f4f4;' ). + lo_buf->add( ' color: var(--theme-greyscale-dark);' ). + lo_buf->add( '}' ). + li_asset_man->register_asset( + iv_url = 'css/theme-default.css' + iv_type = 'text/css' + iv_cacheable = abap_false + iv_mime_name = 'ZABAPGIT_CSS_THEME_DEFAULT' + iv_inline = lo_buf->join_w_newline_and_flush( ) ). + +**************************************************** +* abapmerge Pragma [include] - ZABAPGIT_CSS_THEME_DARK.W3MI.DATA.CSS +**************************************************** + lo_buf->add( '/*' ). + lo_buf->add( ' * ABAPGIT THEME CSS - DARK' ). + lo_buf->add( ' */' ). + lo_buf->add( '' ). + lo_buf->add( '/* https://experience.sap.com/fiori-design-web/colors/ */' ). + lo_buf->add( '' ). + lo_buf->add( ':root {' ). + lo_buf->add( ' --theme-background-color: #333333;' ). + lo_buf->add( ' --theme-container-background-color: #444444;' ). + lo_buf->add( ' --theme-primary-font: "72", Arial, Helvetica, sans-serif;' ). + lo_buf->add( ' --theme-primary-font-color: #cccccc;' ). + lo_buf->add( ' --theme-primary-font-color-reduced: #EEEEEE;' ). + lo_buf->add( ' --theme-font-size: 11pt;' ). + lo_buf->add( ' --theme-link-color: #d9ffff;' ). + lo_buf->add( ' --theme-link-color-hover: #f6f6f6;' ). + lo_buf->add( ' --theme-container-border-color: #D1E0EE;' ). + lo_buf->add( ' --theme-table-border-color: #E5E5E5; /* ALV border color */' ). + lo_buf->add( ' --theme-greyscale-dark: #666666;' ). + lo_buf->add( ' --theme-greyscale-medium: #999999;' ). + lo_buf->add( ' --theme-greyscale-light: #CCCCCC;' ). + lo_buf->add( ' --theme-greyscale-lighter: #E5E5E5;' ). + lo_buf->add( ' --theme-list-hover-background-color: black;' ). + lo_buf->add( '' ). + lo_buf->add( ' --theme-table-background-color: #333333;' ). + lo_buf->add( ' --theme-table-head-background-color: #202020;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* GLOBALS */' ). + lo_buf->add( '' ). + lo_buf->add( 'body {' ). + lo_buf->add( ' background-color: var(--theme-background-color);' ). + lo_buf->add( ' color: var(--theme-primary-font-color);' ). + lo_buf->add( '}' ). + lo_buf->add( 'select, input, textarea {' ). + lo_buf->add( ' color: var(--theme-primary-font-color);' ). + lo_buf->add( ' border-color: #ffffff;' ). + lo_buf->add( ' background-color: var(--theme-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( 'a:hover { color: var(--theme-link-color-hover); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* HEADER */' ). + lo_buf->add( '' ). + lo_buf->add( '#header a, #header a:visited { color: var(--theme-link-color); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* MENU */' ). + lo_buf->add( '' ). + lo_buf->add( 'div#toc .favorites a { opacity: 1; }' ). + lo_buf->add( '.nav-container ul a:hover { text-decoration: underline; }' ). + lo_buf->add( '.nav-container ul ul { background-color: #555555; }' ). + lo_buf->add( '.nav-container ul li:hover { background-color: #555555; }' ). + lo_buf->add( '.nav-container ul ul li:hover { background-color: var(--theme-list-hover-background-color); }' ). + lo_buf->add( 'table.repo_tab {' ). + lo_buf->add( ' border-color: var(--theme-container-background-color);' ). + lo_buf->add( ' background-color: var(--theme-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* ABAPGIT OBJECTS */' ). + lo_buf->add( '' ). + lo_buf->add( 'span.user-box {' ). + lo_buf->add( ' background-color: #4c6782;' ). + lo_buf->add( ' border-color: #7491b2;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.package-box {' ). + lo_buf->add( ' background-color: #705a6d;' ). + lo_buf->add( ' border-color: #987095;' ). + lo_buf->add( '}' ). + lo_buf->add( 'span.path-box,' ). + lo_buf->add( 'span.transport-box {' ). + lo_buf->add( ' background-color: #456d5d;' ). + lo_buf->add( ' border-color: #60a087;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* PANELS */' ). + lo_buf->add( '' ). + lo_buf->add( '#debug-output { color: var(--theme-greyscale-dark); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* abapGit logo in header and footer */' ). + lo_buf->add( '.logo .icon.icon-abapgit {' ). + lo_buf->add( ' color: var(--theme-primary-font-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* TUTORIAL */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.tutorial h1, h2 { color: var(--theme-primary-font-color); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* REPOSITORY */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.repo { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( '.repo_name span.name { color: var(--theme-primary-font-color-reduced); }' ). + lo_buf->add( '.repo_name span.url { color: var(--theme-greyscale-medium); }' ). + lo_buf->add( '.repo_name a.url { color: var(--theme-greyscale-medium); }' ). + lo_buf->add( '.repo_attr { color: var(--theme-primary-font-color); }' ). + lo_buf->add( '' ). + lo_buf->add( 'span.branch_branch {' ). + lo_buf->add( ' border-color: var(--theme-greyscale-medium);' ). + lo_buf->add( ' background-color: #777777;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* REPOSITORY TABLE */' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab td { color: var(--theme-primary-font-color); }' ). + lo_buf->add( '.repo_tab tr.unsupported { background-color: #555; }' ). + lo_buf->add( '.repo_tab tr.modified { background-color: #555; }' ). + lo_buf->add( '.repo_tab tr:hover {background-color: var(--theme-list-hover-background-color) !important;}' ). + lo_buf->add( '' ). + lo_buf->add( '.repo_tab th {' ). + lo_buf->add( ' border-top-color: var(--theme-greyscale-dark);' ). + lo_buf->add( ' background-color: black;' ). + lo_buf->add( '}' ). + lo_buf->add( '.repo_tab td {' ). + lo_buf->add( ' border-top-color: var(--theme-greyscale-dark);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* STAGE */' ). + lo_buf->add( '' ). + lo_buf->add( '.stage_tab {' ). + lo_buf->add( ' border-color: var(--theme-greyscale-dark);' ). + lo_buf->add( ' background-color: var(--theme-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab th {' ). + lo_buf->add( ' border-top-color: var(--theme-greyscale-dark);' ). + lo_buf->add( ' background-color: black;' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td {' ). + lo_buf->add( ' color: var(--theme-primary-font-color);' ). + lo_buf->add( ' border-top-color: var(--theme-greyscale-dark);' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td.status.highlight {' ). + lo_buf->add( ' color: var(--theme-primary-font-color) !important;' ). + lo_buf->add( ' background-color: var(--theme-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab td.status {' ). + lo_buf->add( ' color: #777;' ). + lo_buf->add( ' background-color: var(--theme-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.stage_tab th { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( '.stage_tab tr:hover {background-color: var(--theme-list-hover-background-color) !important;}' ). + lo_buf->add( '' ). + lo_buf->add( '/* COMMIT */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.form-container { background-color: var(--theme-background-color); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* SETTINGS STYLES */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.settings_container { color: var(--theme-primary-font-color); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* DIFF */' ). + lo_buf->add( '' ). + lo_buf->add( '.diff_ins { background-color: #352; }' ). + lo_buf->add( '.diff_del { background-color: #411; }' ). + lo_buf->add( '.diff_upd { background-color: #551; }' ). + lo_buf->add( 'div.diff_content { background-color: var(--theme-background-color); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* DIFF TABLE */' ). + lo_buf->add( '' ). + lo_buf->add( 'table.diff_tab td,th { color: #fff; }' ). + lo_buf->add( 'table.diff_tab thead.nav_line { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* STYLES FOR SYNTAX HIGHLIGHTING */' ). + lo_buf->add( '' ). + lo_buf->add( '/* ABAP */' ). + lo_buf->add( '.syntax-hl span.keyword { color: #4af; }' ). + lo_buf->add( '.syntax-hl span.text { color: #8f8; }' ). + lo_buf->add( '.syntax-hl span.comment { color: #999; }' ). + lo_buf->add( '/* XML+HTML */' ). + lo_buf->add( '.syntax-hl span.xml_tag { color: #659cff; }' ). + lo_buf->add( '.syntax-hl span.attr { color: #bab2f9; }' ). + lo_buf->add( '.syntax-hl span.attr_val { color: #b777fb; }' ). + lo_buf->add( '/* CSS+JS */' ). + lo_buf->add( '.syntax-hl span.properties { color:#0a69ce; }' ). + lo_buf->add( '.syntax-hl span.values { color:blue; }' ). + lo_buf->add( '.syntax-hl span.units { color:maroon; }' ). + lo_buf->add( '.syntax-hl span.selectors { color:purple; }' ). + lo_buf->add( '.syntax-hl span.functions { color:purple; }' ). + lo_buf->add( '.syntax-hl span.colors { color:purple; }' ). + lo_buf->add( '.syntax-hl span.extensions { color:lightblue; }' ). + lo_buf->add( '.syntax-hl span.at_rules { color:lightblue; }' ). + lo_buf->add( '.syntax-hl span.html { color:green; }' ). + lo_buf->add( '.syntax-hl span.variables { color:purple; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* DEBUG INFO STYLES */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.debug_container#debug_info { color: var(--theme-primary-font-color); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* DB ENTRIES */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.db_list { background-color: var(--theme-container-background-color); }' ). + lo_buf->add( 'table.db_tab td { color: var(--theme-primary-font-color); }' ). + lo_buf->add( 'table.db_tab td.data { opacity: 0.5; }' ). + lo_buf->add( 'table.db_tab tbody tr:hover, tr:active { background-color: var(--theme-list-hover-background-color); }' ). + lo_buf->add( 'table.db_tab th {' ). + lo_buf->add( ' color: var(--theme-primary-font-color);' ). + lo_buf->add( ' border-bottom-color: #333;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'table.db_tab tr.selected {' ). + lo_buf->add( ' background: rgba(92, 92, 92, 1) !important;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/* ERROR LOGS */' ). + lo_buf->add( '' ). + lo_buf->add( 'div.log { color: var(--theme-greyscale-dark); }' ). + lo_buf->add( '.close-btn, .message-panel, .message-panel-commands a { color: var(--theme-greyscale-dark); }' ). + lo_buf->add( '.message-panel-commands a:hover { color: var(--theme-greyscale-dark); }' ). + lo_buf->add( '' ). + lo_buf->add( '/* DIALOGS */' ). + lo_buf->add( '' ). + lo_buf->add( '.dialog {' ). + lo_buf->add( ' color: var(--theme-primary-font-color-reduced);' ). + lo_buf->add( ' background-color: var(--theme-container-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.dialog-commands a,' ). + lo_buf->add( '.dialog li.dialog-commands input[type="submit"] {' ). + lo_buf->add( ' border-color: #ccc;' ). + lo_buf->add( ' background-color: var(--theme-greyscale-dark);' ). + lo_buf->add( ' color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.dialog-commands a.main,' ). + lo_buf->add( '.dialog li.dialog-commands input[type="submit"].main {' ). + lo_buf->add( ' background-color: #64a8ff;' ). + lo_buf->add( ' color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog label {' ). + lo_buf->add( ' color: var(--theme-primary-font-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog label em {' ). + lo_buf->add( ' color: #64a8ff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.error small {' ). + lo_buf->add( ' color: #ff5959;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.error input[type="number"],' ). + lo_buf->add( '.dialog li.error input[type="text"] {' ). + lo_buf->add( ' border-color: #ff5959;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .radio-container {' ). + lo_buf->add( ' border-color: #ddd;' ). + lo_buf->add( ' background-color: var(--theme-greyscale-dark);' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .radio-container input[type="radio"] + label {' ). + lo_buf->add( ' color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog .radio-container input[type="radio"]:checked + label {' ). + lo_buf->add( ' background-color: #64a8ff;' ). + lo_buf->add( ' color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog li.with-command input[type="button"]:hover,' ). + lo_buf->add( '.dialog li.with-command input[type="submit"]:hover {' ). + lo_buf->add( ' background-color: #64a8ff;' ). + lo_buf->add( ' color: #fff;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog fieldset {' ). + lo_buf->add( ' border-color: #dfdfdf;' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog fieldset legend {' ). + lo_buf->add( ' color: var(--theme-primary-font-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.dialog input:read-only {' ). + lo_buf->add( ' background-color: var(--theme-greyscale-dark);' ). + lo_buf->add( ' color: var(--theme-greyscale-medium);' ). + lo_buf->add( '}' ). + lo_buf->add( '/* for IE */' ). + lo_buf->add( '.dialog input[readonly] {' ). + lo_buf->add( ' background-color: var(--theme-greyscale-dark);' ). + lo_buf->add( ' color: var(--theme-greyscale-medium);' ). + lo_buf->add( '}' ). + li_asset_man->register_asset( + iv_url = 'css/theme-dark.css' + iv_type = 'text/css' + iv_cacheable = abap_false + iv_mime_name = 'ZABAPGIT_CSS_THEME_DARK' + iv_inline = lo_buf->join_w_newline_and_flush( ) ). + +**************************************************** +* abapmerge Pragma [include] - ZABAPGIT_CSS_THEME_BELIZE_BLUE.W3MI.DATA.CSS +**************************************************** + lo_buf->add( '/*' ). + lo_buf->add( ' * ABAPGIT THEME CSS - BELIZE BLUE' ). + lo_buf->add( ' */' ). + lo_buf->add( '' ). + lo_buf->add( '/* https://experience.sap.com/fiori-design-web/colors/ */' ). + lo_buf->add( '' ). + lo_buf->add( ':root {' ). + lo_buf->add( ' --fiori-color-global-light-base: #EFF4F9; /* Background in SAP GUI */' ). + lo_buf->add( ' --fiori-color-gui-tab-background: #FCFDFE; /* Tabstrip background */' ). + lo_buf->add( ' --fiori-color-gui-container-border: #D1E0EE;' ). + lo_buf->add( ' --fiori-color-gui-uneditable-background: #F2F2F2; /* Textbox not editable */' ). + lo_buf->add( ' --fiori-color-gui-editable-background: #FFFFFF; /* Textbox editable */' ). + lo_buf->add( ' --fiori-color-font-primary: #333333; /* Grayscale 1 */' ). + lo_buf->add( ' --fiori-color-font-secondary: #666666; /* Grayscale 2 */' ). + lo_buf->add( ' --fiori-color-font-highlighted: #003D84;' ). + lo_buf->add( ' --fiori-color-message-box-background: #2F3C48; /* Bottom message container */' ). + lo_buf->add( '' ). + lo_buf->add( ' --theme-background-color: var(--fiori-color-global-light-base);' ). + lo_buf->add( ' --theme-container-background-color: var(--fiori-color-gui-tab-background);' ). + lo_buf->add( ' --theme-primary-font: "72", Arial, Helvetica, sans-serif;' ). + lo_buf->add( ' --theme-primary-font-color: var(--fiori-color-font-primary);' ). + lo_buf->add( ' --theme-primary-font-color-reduced: var(--fiori-color-font-secondary);' ). + lo_buf->add( ' --theme-font-size: 11pt;' ). + lo_buf->add( ' --theme-link-color: var(--fiori-color-font-highlighted);' ). + lo_buf->add( ' --theme-container-border-color: var(--fiori-color-gui-container-border);' ). + lo_buf->add( ' --theme-table-border-color: #E5E5E5; /* ALV border color */' ). + lo_buf->add( ' --theme-greyscale-dark: #666666;' ). + lo_buf->add( ' --theme-greyscale-medium: #BFBFBF;' ). + lo_buf->add( ' --theme-greyscale-light: #CCCCCC;' ). + lo_buf->add( ' --theme-greyscale-lighter: #E5E5E5;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '#header a, #header a:visited {' ). + lo_buf->add( ' color: #346187;' ). + lo_buf->add( '}' ). + li_asset_man->register_asset( + iv_url = 'css/theme-belize-blue.css' + iv_type = 'text/css' + iv_cacheable = abap_false + iv_mime_name = 'ZABAPGIT_CSS_THEME_BELIZE_BLUE' + iv_inline = lo_buf->join_w_newline_and_flush( ) ). + +**************************************************** +* abapmerge Pragma [include] - ZABAPGIT_JS_COMMON.W3MI.DATA.JS +**************************************************** + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * abapGit JavaScript Function Library' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' Global variables used from outside' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '/* exported setInitialFocus */' ). + lo_buf->add( '/* exported setInitialFocusWithQuerySelector */' ). + lo_buf->add( '/* exported submitFormById */' ). + lo_buf->add( '/* exported errorStub */' ). + lo_buf->add( '/* exported confirmInitialized */' ). + lo_buf->add( '/* exported perfOut */' ). + lo_buf->add( '/* exported perfLog */' ). + lo_buf->add( '/* exported perfClear */' ). + lo_buf->add( '/* exported enableArrowListNavigation */' ). + lo_buf->add( '/* exported activateLinkHints */' ). + lo_buf->add( '/* exported setKeyBindings */' ). + lo_buf->add( '/* exported preparePatch */' ). + lo_buf->add( '/* exported registerStagePatch */' ). + lo_buf->add( '/* exported toggleRepoListDetail */' ). + lo_buf->add( '/* exported onTagTypeChange */' ). + lo_buf->add( '/* exported getIndocStyleSheet */' ). + lo_buf->add( '/* exported addMarginBottom */' ). + lo_buf->add( '/* exported enumerateJumpAllFiles */' ). + lo_buf->add( '/* exported createRepoCatalogEnumerator */' ). + lo_buf->add( '/* exported enumerateUiActions */' ). + lo_buf->add( '/* exported onDiffCollapse */' ). + lo_buf->add( '/* exported restoreScrollPosition */' ). + lo_buf->add( '/* exported toggleBrowserControlWarning */' ). + lo_buf->add( '/* exported displayBrowserControlFooter */' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Polyfills' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '// Bind polyfill (for IE7), taken from https://developer.mozilla.org/' ). + lo_buf->add( 'if (!Function.prototype.bind) {' ). + lo_buf->add( ' Function.prototype.bind = function(oThis) {' ). + lo_buf->add( ' if (typeof this !== "function") {' ). + lo_buf->add( ' throw new TypeError("Function.prototype.bind - subject is not callable");' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' var aArgs = Array.prototype.slice.call(arguments, 1);' ). + lo_buf->add( ' var fToBind = this;' ). + lo_buf->add( ' var fNOP = function() { };' ). + lo_buf->add( ' var fBound = function() {' ). + lo_buf->add( ' return fToBind.apply(' ). + lo_buf->add( ' this instanceof fNOP ? this : oThis,' ). + lo_buf->add( ' aArgs.concat(Array.prototype.slice.call(arguments))' ). + lo_buf->add( ' );' ). + lo_buf->add( ' };' ). + lo_buf->add( '' ). + lo_buf->add( ' if (this.prototype) {' ). + lo_buf->add( ' fNOP.prototype = this.prototype;' ). + lo_buf->add( ' }' ). + lo_buf->add( ' fBound.prototype = new fNOP();' ). + lo_buf->add( '' ). + lo_buf->add( ' return fBound;' ). + lo_buf->add( ' };' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// String includes polyfill, taken from https://developer.mozilla.org' ). + lo_buf->add( 'if (!String.prototype.includes) {' ). + lo_buf->add( ' String.prototype.includes = function(search, start) {' ). + lo_buf->add( ' "use strict";' ). + lo_buf->add( ' if (typeof start !== "number") {' ). + lo_buf->add( ' start = 0;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' if (start + search.length > this.length) {' ). + lo_buf->add( ' return false;' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' return this.indexOf(search, start) !== -1;' ). + lo_buf->add( ' }' ). + lo_buf->add( ' };' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// String startsWith polyfill, taken from https://developer.mozilla.org' ). + lo_buf->add( 'if (!String.prototype.startsWith) {' ). + lo_buf->add( ' Object.defineProperty(String.prototype, "startsWith", {' ). + lo_buf->add( ' value: function(search, pos) {' ). + lo_buf->add( ' pos = !pos || pos < 0 ? 0 : +pos;' ). + lo_buf->add( '' ). + lo_buf->add( ' return this.substring(pos, pos + search.length) === search;' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// forEach polyfill, taken from https://developer.mozilla.org' ). + lo_buf->add( '// used for querySelectorAll results' ). + lo_buf->add( 'if (window.NodeList && !NodeList.prototype.forEach) {' ). + lo_buf->add( ' NodeList.prototype.forEach = Array.prototype.forEach;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Common functions' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '// Output text to the debug div' ). + lo_buf->add( 'function debugOutput(text, dstID) {' ). + lo_buf->add( ' var stdout = document.getElementById(dstID || "debug-output");' ). + lo_buf->add( ' var wrapped = "

      " + text + "

      ";' ). + lo_buf->add( '' ). + lo_buf->add( ' stdout.innerHTML = stdout.innerHTML + wrapped;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// Use a supplied form, a pre-created form or create a hidden form' ). + lo_buf->add( '// and submit with sapevent' ). + lo_buf->add( 'function submitSapeventForm(params, action, method, form) {' ). + lo_buf->add( '' ). + lo_buf->add( ' function getSapeventPrefix() {' ). + lo_buf->add( ' // Depending on the used browser control and its version, different URL schemes' ). + lo_buf->add( ' // are used which we distinguish here' ). + lo_buf->add( ' if (document.querySelector(''a[href*="file:///SAPEVENT:"]'')) {' ). + lo_buf->add( ' // Prefix for old (SAPGUI <= 8.00 PL3) chromium based browser control' ). + lo_buf->add( ' return "file:///";' ). + lo_buf->add( ' } else if (document.querySelector(''a[href^="sap-cust"]'')) {' ). + lo_buf->add( ' // Prefix for new (SAPGUI >= 8.00 PL3 Hotfix 1) chromium based browser control' ). + lo_buf->add( ' return "sap-cust://sap-place-holder/";' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' return ""; // No prefix for old IE control' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' var stub_form_id = "form_" + action;' ). + lo_buf->add( '' ). + lo_buf->add( ' form = form' ). + lo_buf->add( ' || document.getElementById(stub_form_id)' ). + lo_buf->add( ' || document.createElement("form");' ). + lo_buf->add( '' ). + lo_buf->add( ' form.setAttribute("method", method || "post");' ). + lo_buf->add( ' if (/sapevent/i.test(action)) {' ). + lo_buf->add( ' form.setAttribute("action", action);' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' form.setAttribute("action", getSapeventPrefix() + "SAPEVENT:" + action);' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' for (var key in params) {' ). + lo_buf->add( ' var hiddenField = document.createElement("input");' ). + lo_buf->add( ' hiddenField.setAttribute("type", "hidden");' ). + lo_buf->add( ' hiddenField.setAttribute("name", key);' ). + lo_buf->add( ' hiddenField.setAttribute("value", params[key]);' ). + lo_buf->add( ' form.appendChild(hiddenField);' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' var formExistsInDOM = form.id && Boolean(document.querySelector("#" + form.id));' ). + lo_buf->add( '' ). + lo_buf->add( ' if (form.id !== stub_form_id && !formExistsInDOM) {' ). + lo_buf->add( ' document.body.appendChild(form);' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' form.submit();' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// Set focus to a control' ). + lo_buf->add( 'function setInitialFocus(id) {' ). + lo_buf->add( ' document.getElementById(id).focus();' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// Set focus to an element with query selector' ). + lo_buf->add( 'function setInitialFocusWithQuerySelector(sSelector, bFocusParent) {' ). + lo_buf->add( ' var oSelected = document.querySelector(sSelector);' ). + lo_buf->add( '' ). + lo_buf->add( ' if (oSelected) {' ). + lo_buf->add( ' if (bFocusParent) {' ). + lo_buf->add( ' oSelected.parentElement.focus();' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' oSelected.focus();' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// Submit an existing form' ). + lo_buf->add( 'function submitFormById(id) {' ). + lo_buf->add( ' document.getElementById(id).submit();' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// JS error stub' ). + lo_buf->add( 'function errorStub(event) {' ). + lo_buf->add( ' var element = event.target || event.srcElement;' ). + lo_buf->add( ' var targetName = element.id || element.name || "???";' ). + lo_buf->add( ' alert("JS Error, please log an issue (@" + targetName + ")");' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// Confirm JS initialization' ). + lo_buf->add( 'function confirmInitialized() {' ). + lo_buf->add( ' var errorBanner = document.getElementById("js-error-banner");' ). + lo_buf->add( ' if (errorBanner) {' ). + lo_buf->add( ' errorBanner.style.display = "none";' ). + lo_buf->add( ' }' ). + lo_buf->add( ' debugOutput("js: OK"); // Final final confirmation :)' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Performance utils (for debugging)' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( 'var gPerf = [];' ). + lo_buf->add( '' ). + lo_buf->add( 'function perfOut(prefix) {' ). + lo_buf->add( ' var totals = {};' ). + lo_buf->add( ' for (var i = gPerf.length - 1; i >= 0; i--) {' ). + lo_buf->add( ' if (!totals[gPerf[i].name]) totals[gPerf[i].name] = { count: 0, time: 0 };' ). + lo_buf->add( '' ). + lo_buf->add( ' totals[gPerf[i].name].time += gPerf[i].time;' ). + lo_buf->add( ' totals[gPerf[i].name].count += 1;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' var keys = Object.keys(totals);' ). + lo_buf->add( ' for (var j = keys.length - 1; j >= 0; j--) {' ). + lo_buf->add( ' console.log(prefix' ). + lo_buf->add( ' + " " + keys[j] + ": "' ). + lo_buf->add( ' + totals[keys[j]].time.toFixed(3) + "ms"' ). + lo_buf->add( ' + " (" + totals[keys[j]].count.toFixed() + ")");' ). + lo_buf->add( ' }' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function perfLog(name, startTime) {' ). + lo_buf->add( ' gPerf.push({ name: name, time: window.performance.now() - startTime });' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function perfClear() {' ). + lo_buf->add( ' gPerf = [];' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Repo Overview Logic' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( 'function findStyleSheetByName(name) {' ). + lo_buf->add( ' for (var s = 0; s < document.styleSheets.length; s++) {' ). + lo_buf->add( ' var styleSheet = document.styleSheets[s];' ). + lo_buf->add( ' var classes = styleSheet.cssRules || styleSheet.rules;' ). + lo_buf->add( ' for (var i = 0; i < classes.length; i++) {' ). + lo_buf->add( ' if (classes[i].selectorText === name) return classes[i];' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function getIndocStyleSheet() {' ). + lo_buf->add( ' for (var s = 0; s < document.styleSheets.length; s++) {' ). + lo_buf->add( ' if (!document.styleSheets[s].href) return document.styleSheets[s]; // One with empty href' ). + lo_buf->add( ' }' ). + lo_buf->add( ' // None found ? create one' ). + lo_buf->add( ' var style = document.createElement("style");' ). + lo_buf->add( ' document.head.appendChild(style);' ). + lo_buf->add( ' return style.sheet;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function RepoOverViewHelper(opts) {' ). + lo_buf->add( ' if (opts && opts.focusFilterKey) {' ). + lo_buf->add( ' this.focusFilterKey = opts.focusFilterKey;' ). + lo_buf->add( ' }' ). + lo_buf->add( ' this.setHooks();' ). + lo_buf->add( ' this.pageId = (opts && opts.pageId) ? opts.pageId : "RepoOverViewHelperState";' ). + lo_buf->add( ' this.isDetailsDisplayed = false;' ). + lo_buf->add( ' this.isOnlyFavoritesDisplayed = false;' ). + lo_buf->add( ' this.detailCssClass = findStyleSheetByName(".repo-overview .ro-detail");' ). + lo_buf->add( '' ). + lo_buf->add( ' var icon = document.getElementById("icon-filter-detail");' ). + lo_buf->add( ' this.toggleFilterIcon(icon, this.isDetailsDisplayed);' ). + lo_buf->add( ' this.registerRowSelection();' ). + lo_buf->add( ' this.registerKeyboardShortcuts();' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.setHooks = function() {' ). + lo_buf->add( ' window.onload = this.onPageLoad.bind(this);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.onPageLoad = function() {' ). + lo_buf->add( ' var data = window.localStorage && JSON.parse(window.localStorage.getItem(this.pageId));' ). + lo_buf->add( ' if (data) {' ). + lo_buf->add( ' if (data.isDetailsDisplayed) {' ). + lo_buf->add( ' this.toggleItemsDetail(true);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' if (data.selectedRepoKey) {' ). + lo_buf->add( ' this.selectRowByRepoKey(data.selectedRepoKey);' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' this.selectRowByIndex(0);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.registerKeyboardShortcuts = function() {' ). + lo_buf->add( ' var self = this;' ). + lo_buf->add( ' document.addEventListener("keypress", function(event) {' ). + lo_buf->add( ' if (document.activeElement.id === "filter") {' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( ' if (self.focusFilterKey && event.key === self.focusFilterKey && !CommandPalette.isVisible()) {' ). + lo_buf->add( ' var filterInput = document.getElementById("filter");' ). + lo_buf->add( ' if (filterInput) filterInput.focus();' ). + lo_buf->add( ' event.preventDefault();' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' var keycode = event.keyCode;' ). + lo_buf->add( ' var rows = Array.prototype.slice.call(self.getVisibleRows());' ). + lo_buf->add( ' var selected = document.querySelector(".repo-overview tr.selected");' ). + lo_buf->add( ' var indexOfSelected = rows.indexOf(selected);' ). + lo_buf->add( ' var lastRow = rows.length - 1;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (keycode == 13 && document.activeElement.tagName.toLowerCase() != "input") {' ). + lo_buf->add( ' // "enter" to open, unless command field has focus' ). + lo_buf->add( ' self.openSelectedRepo();' ). + lo_buf->add( ' } else if ((keycode == 52 || keycode == 56) && indexOfSelected > 0) {' ). + lo_buf->add( ' // "4,8" for previous, digits are the numlock keys' ). + lo_buf->add( ' // NB: numpad must be activated, keypress does not detect arrows' ). + lo_buf->add( ' // if we need arrows it will be keydown. But then mind the keycodes, they may change !' ). + lo_buf->add( ' // e.g. 100 is ''d'' with keypress (and conflicts with diff hotkey), and also it is arrow-left keydown' ). + lo_buf->add( ' self.selectRowByIndex(indexOfSelected - 1);' ). + lo_buf->add( ' } else if ((keycode == 54 || keycode == 50) && indexOfSelected < lastRow) {' ). + lo_buf->add( ' // "6,2" for next' ). + lo_buf->add( ' self.selectRowByIndex(indexOfSelected + 1);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.openSelectedRepo = function() {' ). + lo_buf->add( ' this.selectedRepoKey = document.querySelector(".repo-overview tr.selected").dataset.key;' ). + lo_buf->add( ' this.saveLocalStorage();' ). + lo_buf->add( ' document.querySelector(".repo-overview tr.selected td.ro-go a").click();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.selectRowByIndex = function(index) {' ). + lo_buf->add( ' var rows = this.getVisibleRows();' ). + lo_buf->add( ' if (rows.length >= index) {' ). + lo_buf->add( ' var selectedRow = rows[index];' ). + lo_buf->add( ' if (selectedRow.classList.contains("selected")) {' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' this.deselectAllRows();' ). + lo_buf->add( ' rows[index].classList.add("selected");' ). + lo_buf->add( ' this.selectedRepoKey = selectedRow.dataset.key;' ). + lo_buf->add( ' this.updateActionLinks(selectedRow);' ). + lo_buf->add( ' this.saveLocalStorage();' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.selectRowByRepoKey = function(key) {' ). + lo_buf->add( ' var attributeQuery = "[data-key=''" + key + "'']";' ). + lo_buf->add( ' var row = document.querySelector(".repo-overview tbody tr" + attributeQuery);' ). + lo_buf->add( ' // navigation to already selected repo' ). + lo_buf->add( ' if (row.dataset.key === key && row.classList.contains("selected")) {' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' this.deselectAllRows();' ). + lo_buf->add( ' row.classList.add("selected");' ). + lo_buf->add( ' this.selectedRepoKey = key;' ). + lo_buf->add( ' this.updateActionLinks(row);' ). + lo_buf->add( ' this.saveLocalStorage();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.updateActionLinks = function(selectedRow) {' ). + lo_buf->add( ' // now we have a repo selected, determine which action buttons are relevant' ). + lo_buf->add( ' var selectedRepoKey = selectedRow.dataset.key;' ). + lo_buf->add( ' var selectedRepoIsOffline = selectedRow.dataset.offline === "X";' ). + lo_buf->add( '' ). + lo_buf->add( ' var actionLinks = document.querySelectorAll("a.action_link");' ). + lo_buf->add( ' actionLinks.forEach(function(link) {' ). + lo_buf->add( ' // adjust repo key in urls' ). + lo_buf->add( ' link.href = link.href.replace(/\?key=(#|\d+)/, "?key=" + selectedRepoKey);' ). + lo_buf->add( '' ). + lo_buf->add( ' // toggle button visibility' ). + lo_buf->add( ' if (link.classList.contains("action_offline_repo")) {' ). + lo_buf->add( ' if (selectedRepoIsOffline) {' ). + lo_buf->add( ' link.parentElement.classList.add("enabled");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' link.parentElement.classList.remove("enabled");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' else if (link.classList.contains("action_online_repo")) {' ). + lo_buf->add( ' if (!selectedRepoIsOffline) {' ). + lo_buf->add( ' link.parentElement.classList.add("enabled");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' link.parentElement.classList.remove("enabled");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' else {' ). + lo_buf->add( ' // if the action is for both repository types, it will only have the .action_link class' ). + lo_buf->add( ' // it still needs to be toggled as we want to hide everything if no repo is selected' ). + lo_buf->add( ' link.parentElement.classList.add("enabled");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.deselectAllRows = function() {' ). + lo_buf->add( ' document.querySelectorAll(".repo-overview tbody tr").forEach(function(x) {' ). + lo_buf->add( ' x.classList.remove("selected");' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.getVisibleRows = function() {' ). + lo_buf->add( ' return document.querySelectorAll(".repo-overview tbody tr:not(.nodisplay)");' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.registerRowSelection = function() {' ). + lo_buf->add( ' var self = this;' ). + lo_buf->add( ' document.querySelectorAll(".repo-overview tr td:not(.ro-go)").forEach(function(repoListRowCell) {' ). + lo_buf->add( ' repoListRowCell.addEventListener("click", function() {' ). + lo_buf->add( ' self.selectRowByRepoKey(this.parentElement.dataset.key);' ). + lo_buf->add( ' });' ). + lo_buf->add( ' });' ). + lo_buf->add( '' ). + lo_buf->add( ' document.querySelectorAll(".repo-overview tr td.ro-go").forEach(function(openRepoIcon) {' ). + lo_buf->add( ' openRepoIcon.addEventListener("click", function() {' ). + lo_buf->add( ' var selectedRow = this.parentElement;' ). + lo_buf->add( ' self.selectRowByRepoKey(selectedRow.dataset.key);' ). + lo_buf->add( ' self.openSelectedRepo();' ). + lo_buf->add( ' });' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.toggleRepoListDetail = function(forceDisplay) {' ). + lo_buf->add( ' if (this.detailCssClass) {' ). + lo_buf->add( ' this.toggleItemsDetail(forceDisplay);' ). + lo_buf->add( ' this.saveLocalStorage();' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.toggleItemsDetail = function(forceDisplay) {' ). + lo_buf->add( ' if (this.detailCssClass) {' ). + lo_buf->add( ' this.isDetailsDisplayed = forceDisplay || !this.isDetailsDisplayed;' ). + lo_buf->add( '' ). + lo_buf->add( ' // change layout to wide if details are displayed' ). + lo_buf->add( ' if (this.isDetailsDisplayed) {' ). + lo_buf->add( ' document.body.classList.remove("centered");' ). + lo_buf->add( ' document.body.classList.add("full_width");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' document.body.classList.add("centered");' ). + lo_buf->add( ' document.body.classList.remove("full_width");' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' this.detailCssClass.style.display = this.isDetailsDisplayed ? "" : "none";' ). + lo_buf->add( '' ). + lo_buf->add( ' var icon = document.getElementById("icon-filter-detail");' ). + lo_buf->add( ' this.toggleFilterIcon(icon, this.isDetailsDisplayed);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.toggleFilterIcon = function(icon, isEnabled) {' ). + lo_buf->add( ' if (isEnabled) {' ). + lo_buf->add( ' icon.classList.remove("grey");' ). + lo_buf->add( ' icon.classList.add("blue");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' icon.classList.remove("blue");' ). + lo_buf->add( ' icon.classList.add("grey");' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'RepoOverViewHelper.prototype.saveLocalStorage = function() {' ). + lo_buf->add( ' if (!window.localStorage) return;' ). + lo_buf->add( ' var data = {' ). + lo_buf->add( ' isDetailsDisplayed : this.isDetailsDisplayed,' ). + lo_buf->add( ' isOnlyFavoritesDisplayed: this.isOnlyFavoritesDisplayed,' ). + lo_buf->add( ' selectedRepoKey : this.selectedRepoKey,' ). + lo_buf->add( ' };' ). + lo_buf->add( ' window.localStorage.setItem(this.pageId, JSON.stringify(data));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Staging Logic' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '// Stage helper constructor' ). + lo_buf->add( 'function StageHelper(params) {' ). + lo_buf->add( ' this.pageSeed = params.seed;' ). + lo_buf->add( ' this.formAction = params.formAction;' ). + lo_buf->add( ' this.patchAction = params.patchAction;' ). + lo_buf->add( ' this.user = params.user;' ). + lo_buf->add( ' this.ids = params.ids;' ). + lo_buf->add( ' this.selectedCount = 0;' ). + lo_buf->add( ' this.filteredCount = 0;' ). + lo_buf->add( ' this.lastFilterValue = "";' ). + lo_buf->add( ' this.focusFilterKey = params.focusFilterKey;' ). + lo_buf->add( '' ). + lo_buf->add( ' // DOM nodes' ). + lo_buf->add( ' this.dom = {' ). + lo_buf->add( ' stageTab : document.getElementById(params.ids.stageTab),' ). + lo_buf->add( ' commitAllBtn : document.getElementById(params.ids.commitAllBtn),' ). + lo_buf->add( ' commitSelectedBtn: document.getElementById(params.ids.commitSelectedBtn),' ). + lo_buf->add( ' commitFilteredBtn: document.getElementById(params.ids.commitFilteredBtn),' ). + lo_buf->add( ' patchBtn : document.getElementById(params.ids.patchBtn),' ). + lo_buf->add( ' objectSearch : document.getElementById(params.ids.objectSearch),' ). + lo_buf->add( ' selectedCounter : null,' ). + lo_buf->add( ' filteredCounter : null,' ). + lo_buf->add( ' };' ). + lo_buf->add( ' this.findCounters();' ). + lo_buf->add( '' ). + lo_buf->add( ' // Table columns (autodetection)' ). + lo_buf->add( ' this.colIndex = this.detectColumns();' ). + lo_buf->add( ' this.filterTargets = ["name", "user", "transport"];' ). + lo_buf->add( '' ). + lo_buf->add( ' // Constants' ). + lo_buf->add( ' this.HIGHLIGHT_STYLE = "highlight";' ). + lo_buf->add( ' this.STATUS = {' ). + lo_buf->add( ' add : "A",' ). + lo_buf->add( ' remove : "R",' ). + lo_buf->add( ' ignore : "I",' ). + lo_buf->add( ' reset : "?",' ). + lo_buf->add( ' isValid: function(status) { return "ARI?".indexOf(status) == -1 }' ). + lo_buf->add( ' };' ). + lo_buf->add( '' ). + lo_buf->add( ' this.TEMPLATES = {' ). + lo_buf->add( ' cmdReset : "reset",' ). + lo_buf->add( ' cmdLocal : "add",' ). + lo_buf->add( ' cmdRemote: "ignoreremove"' ). + lo_buf->add( ' };' ). + lo_buf->add( '' ). + lo_buf->add( ' this.setHooks();' ). + lo_buf->add( ' if (this.user) this.injectFilterMe();' ). + lo_buf->add( ' Hotkeys.addHotkeyToHelpSheet("^Enter", "Commit");' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'StageHelper.prototype.findCounters = function() {' ). + lo_buf->add( ' this.dom.selectedCounter = this.dom.commitSelectedBtn.querySelector("span.counter");' ). + lo_buf->add( ' this.dom.filteredCounter = this.dom.commitFilteredBtn.querySelector("span.counter");' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'StageHelper.prototype.injectFilterMe = function() {' ). + lo_buf->add( ' var tabFirstHead = this.dom.stageTab.tHead.rows[0];' ). + lo_buf->add( ' if (!tabFirstHead || tabFirstHead.className !== "local") {' ). + lo_buf->add( ' return; // for the case only "remove part" is displayed' ). + lo_buf->add( ' }' ). + lo_buf->add( ' var changedByHead = tabFirstHead.cells[this.colIndex.user];' ). + lo_buf->add( '' ). + lo_buf->add( ' changedByHead.innerText = changedByHead.innerText + " (";' ). + lo_buf->add( '' ). + lo_buf->add( ' var a = document.createElement("A");' ). + lo_buf->add( ' a.appendChild(document.createTextNode("me"));' ). + lo_buf->add( ' a.onclick = this.onFilterMe.bind(this);' ). + lo_buf->add( ' a.href = "#";' ). + lo_buf->add( ' changedByHead.appendChild(a);' ). + lo_buf->add( ' changedByHead.appendChild(document.createTextNode(")"));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'StageHelper.prototype.onFilterMe = function() {' ). + lo_buf->add( ' this.dom.objectSearch.value = this.user;' ). + lo_buf->add( ' this.onFilter({ type: "keypress", which: 13, target: this.dom.objectSearch });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Hook global click listener on table, load/unload actions' ). + lo_buf->add( 'StageHelper.prototype.setHooks = function() {' ). + lo_buf->add( ' window.onkeypress = this.onCtrlEnter.bind(this);' ). + lo_buf->add( ' this.dom.stageTab.onclick = this.onTableClick.bind(this);' ). + lo_buf->add( ' this.dom.commitSelectedBtn.onclick = this.submit.bind(this);' ). + lo_buf->add( ' this.dom.commitFilteredBtn.onclick = this.submitVisible.bind(this);' ). + lo_buf->add( ' this.dom.patchBtn.onclick = this.submitPatch.bind(this);' ). + lo_buf->add( ' this.dom.objectSearch.oninput = this.onFilter.bind(this);' ). + lo_buf->add( ' this.dom.objectSearch.onkeypress = this.onFilter.bind(this);' ). + lo_buf->add( ' window.onbeforeunload = this.onPageUnload.bind(this);' ). + lo_buf->add( ' window.onload = this.onPageLoad.bind(this);' ). + lo_buf->add( '' ). + lo_buf->add( ' var self = this;' ). + lo_buf->add( ' document.addEventListener("keypress", function(event) {' ). + lo_buf->add( ' if (document.activeElement.id !== self.ids.objectSearch' ). + lo_buf->add( ' && self.focusFilterKey && event.key === self.focusFilterKey' ). + lo_buf->add( ' && !CommandPalette.isVisible()) {' ). + lo_buf->add( '' ). + lo_buf->add( ' self.dom.objectSearch.focus();' ). + lo_buf->add( ' event.preventDefault();' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Detect column index' ). + lo_buf->add( 'StageHelper.prototype.detectColumns = function() {' ). + lo_buf->add( ' var dataRow = this.dom.stageTab.tBodies[0].rows[0];' ). + lo_buf->add( ' var colIndex = {};' ). + lo_buf->add( '' ). + lo_buf->add( ' for (var i = dataRow.cells.length - 1; i >= 0; i--) {' ). + lo_buf->add( ' if (dataRow.cells[i].className) colIndex[dataRow.cells[i].className] = i;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' return colIndex;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Store table state on leaving the page' ). + lo_buf->add( 'StageHelper.prototype.onPageUnload = function() {' ). + lo_buf->add( ' if (!window.sessionStorage) return;' ). + lo_buf->add( '' ). + lo_buf->add( ' var data = this.collectData();' ). + lo_buf->add( ' window.sessionStorage.setItem(this.pageSeed, JSON.stringify(data));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Re-store table state on entering the page' ). + lo_buf->add( 'StageHelper.prototype.onPageLoad = function() {' ). + lo_buf->add( ' var data = window.sessionStorage && JSON.parse(window.sessionStorage.getItem(this.pageSeed));' ). + lo_buf->add( '' ). + lo_buf->add( ' this.iterateStageTab(true, function(row) {' ). + lo_buf->add( ' var status = data && data[row.cells[this.colIndex["name"]].innerText];' ). + lo_buf->add( ' this.updateRow(row, status || this.STATUS.reset);' ). + lo_buf->add( ' });' ). + lo_buf->add( '' ). + lo_buf->add( ' this.updateMenu();' ). + lo_buf->add( ' if (this.dom.objectSearch.value) {' ). + lo_buf->add( ' this.applyFilterValue(this.dom.objectSearch.value);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Table event handler, change status' ). + lo_buf->add( 'StageHelper.prototype.onTableClick = function(event) {' ). + lo_buf->add( ' var target = event.target || event.srcElement;' ). + lo_buf->add( ' if (!target) return;' ). + lo_buf->add( '' ). + lo_buf->add( ' var td;' ). + lo_buf->add( ' if (target.tagName === "A") {' ). + lo_buf->add( ' td = target.parentNode;' ). + lo_buf->add( ' } else if (target.tagName === "TD") {' ). + lo_buf->add( ' td = target;' ). + lo_buf->add( ' if (td.children.length === 1 && td.children[0].tagName === "A") {' ). + lo_buf->add( ' target = td.children[0];' ). + lo_buf->add( ' } else return;' ). + lo_buf->add( ' } else return;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (["TD", "TH"].indexOf(td.tagName) == -1 || td.className != "cmd") return;' ). + lo_buf->add( '' ). + lo_buf->add( ' var status = this.STATUS[target.innerText]; // Convert anchor text to status' ). + lo_buf->add( ' var targetRow = td.parentNode;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (td.tagName === "TD") {' ). + lo_buf->add( ' this.updateRow(targetRow, status);' ). + lo_buf->add( ' } else { // TH' ). + lo_buf->add( ' this.iterateStageTab(true, function(row) {' ). + lo_buf->add( ' if (row.style.display !== "none" // Not filtered out' ). + lo_buf->add( ' && row.className === targetRow.className // Same context as header' ). + lo_buf->add( ' ) {' ). + lo_buf->add( ' this.updateRow(row, status);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' this.updateMenu();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'StageHelper.prototype.onCtrlEnter = function(e) {' ). + lo_buf->add( ' if (e.ctrlKey && (e.which === 10 || e.key === "Enter")) {' ). + lo_buf->add( ' var clickMap = {' ). + lo_buf->add( ' "default" : this.dom.commitAllBtn,' ). + lo_buf->add( ' "selected": this.dom.commitSelectedBtn,' ). + lo_buf->add( ' "filtered": this.dom.commitFilteredBtn' ). + lo_buf->add( ' };' ). + lo_buf->add( ' clickMap[this.calculateActiveCommitCommand()].click();' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Search object' ). + lo_buf->add( 'StageHelper.prototype.onFilter = function(e) {' ). + lo_buf->add( ' if ( // Enter hit or clear, IE SUCKS !' ). + lo_buf->add( ' e.type === "input" && !e.target.value && this.lastFilterValue' ). + lo_buf->add( ' || e.type === "keypress" && (e.which === 13 || e.key === "Enter") && !e.ctrlKey) {' ). + lo_buf->add( '' ). + lo_buf->add( ' this.applyFilterValue(e.target.value);' ). + lo_buf->add( ' submitSapeventForm({ filterValue: e.target.value }, "stage_filter", "post");' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'StageHelper.prototype.applyFilterValue = function(sFilterValue) {' ). + lo_buf->add( ' this.lastFilterValue = sFilterValue;' ). + lo_buf->add( ' this.filteredCount = this.iterateStageTab(true, this.applyFilterToRow, sFilterValue);' ). + lo_buf->add( ' this.updateMenu();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Apply filter to a single stage line - hide or show' ). + lo_buf->add( 'StageHelper.prototype.applyFilterToRow = function(row, filter) {' ). + lo_buf->add( ' // Collect data cells' ). + lo_buf->add( ' var targets = this.filterTargets.map(function(attr) {' ). + lo_buf->add( ' // Get the innermost tag with the text we want to filter' ). + lo_buf->add( ' // text: elem = td-tag' ). + lo_buf->add( ' // text: elem = a-tag' ). + lo_buf->add( ' var elem = row.cells[this.colIndex[attr]];' ). + lo_buf->add( ' var elemA = elem.getElementsByTagName("A")[0];' ). + lo_buf->add( '' ). + lo_buf->add( ' if (elemA) elem = elemA;' ). + lo_buf->add( ' return {' ). + lo_buf->add( ' elem : elem,' ). + lo_buf->add( ' plainText: elem.innerText.replace(/ /g, "\u00a0"), // without tags, with encoded spaces' ). + lo_buf->add( ' curHtml : elem.innerHTML' ). + lo_buf->add( ' };' ). + lo_buf->add( ' }, this);' ). + lo_buf->add( '' ). + lo_buf->add( ' var isVisible = false;' ). + lo_buf->add( '' ). + lo_buf->add( ' // Apply filter to cells, mark filtered text' ). + lo_buf->add( ' for (var i = targets.length - 1; i >= 0; i--) {' ). + lo_buf->add( ' var target = targets[i];' ). + lo_buf->add( ' // Ignore case of filter' ). + lo_buf->add( ' var regFilter = new RegExp("(" + filter + ")", "gi");' ). + lo_buf->add( '' ). + lo_buf->add( ' target.newHtml = (filter)' ). + lo_buf->add( ' ? target.plainText.replace(regFilter, "$1")' ). + lo_buf->add( ' : target.plainText;' ). + lo_buf->add( ' target.isChanged = target.newHtml !== target.curHtml;' ). + lo_buf->add( ' isVisible = isVisible || !filter || target.newHtml !== target.plainText;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Update DOM' ). + lo_buf->add( ' row.style.display = isVisible ? "" : "none";' ). + lo_buf->add( ' for (var j = targets.length - 1; j >= 0; j--) {' ). + lo_buf->add( ' if (targets[j].isChanged) targets[j].elem.innerHTML = targets[j].newHtml;' ). + lo_buf->add( ' }' ). + lo_buf->add( ' return isVisible ? 1 : 0;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Get how status should affect object counter' ). + lo_buf->add( 'StageHelper.prototype.getStatusImpact = function(status) {' ). + lo_buf->add( ' if (typeof status !== "string"' ). + lo_buf->add( ' || status.length !== 1' ). + lo_buf->add( ' || this.STATUS.isValid(status)) {' ). + lo_buf->add( ' alert("Unknown status");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' return (status !== this.STATUS.reset) ? 1: 0;' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Update table line' ). + lo_buf->add( 'StageHelper.prototype.updateRow = function(row, newStatus) {' ). + lo_buf->add( ' var oldStatus = row.cells[this.colIndex["status"]].innerText;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (oldStatus !== newStatus) {' ). + lo_buf->add( ' this.updateRowStatus(row, newStatus);' ). + lo_buf->add( ' this.updateRowCommand(row, newStatus);' ). + lo_buf->add( ' } else if (!row.cells[this.colIndex["cmd"]].children.length) {' ). + lo_buf->add( ' this.updateRowCommand(row, newStatus); // For initial run' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' this.selectedCount += this.getStatusImpact(newStatus) - this.getStatusImpact(oldStatus);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Update Status cell (render set of commands)' ). + lo_buf->add( 'StageHelper.prototype.updateRowStatus = function(row, status) {' ). + lo_buf->add( ' row.cells[this.colIndex["status"]].innerText = status;' ). + lo_buf->add( ' if (status === this.STATUS.reset) {' ). + lo_buf->add( ' row.cells[this.colIndex["status"]].classList.remove(this.HIGHLIGHT_STYLE);' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' row.cells[this.colIndex["status"]].classList.add(this.HIGHLIGHT_STYLE);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Update Command cell (render set of commands)' ). + lo_buf->add( 'StageHelper.prototype.updateRowCommand = function(row, status) {' ). + lo_buf->add( ' var cell = row.cells[this.colIndex["cmd"]];' ). + lo_buf->add( ' if (status === this.STATUS.reset) {' ). + lo_buf->add( ' cell.innerHTML = (row.className == "local")' ). + lo_buf->add( ' ? this.TEMPLATES.cmdLocal' ). + lo_buf->add( ' : this.TEMPLATES.cmdRemote;' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' cell.innerHTML = this.TEMPLATES.cmdReset;' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'StageHelper.prototype.calculateActiveCommitCommand = function() {' ). + lo_buf->add( ' var active;' ). + lo_buf->add( ' if (this.selectedCount > 0) {' ). + lo_buf->add( ' active = "selected";' ). + lo_buf->add( ' } else if (this.lastFilterValue) {' ). + lo_buf->add( ' active = "filtered";' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' active = "default";' ). + lo_buf->add( ' }' ). + lo_buf->add( ' return active;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Update menu items visibility' ). + lo_buf->add( 'StageHelper.prototype.updateMenu = function() {' ). + lo_buf->add( ' var display = this.calculateActiveCommitCommand();' ). + lo_buf->add( '' ). + lo_buf->add( ' if (display === "selected") this.dom.selectedCounter.innerText = this.selectedCount.toString();' ). + lo_buf->add( ' if (display === "filtered") this.dom.filteredCounter.innerText = this.filteredCount.toString();' ). + lo_buf->add( '' ). + lo_buf->add( ' this.dom.commitAllBtn.style.display = display === "default" ? "" : "none";' ). + lo_buf->add( ' this.dom.commitSelectedBtn.style.display = display === "selected" ? "" : "none";' ). + lo_buf->add( ' this.dom.commitFilteredBtn.style.display = display === "filtered" ? "" : "none";' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Submit stage state to the server' ). + lo_buf->add( 'StageHelper.prototype.submit = function() {' ). + lo_buf->add( ' submitSapeventForm(this.collectData(), this.formAction);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'StageHelper.prototype.submitVisible = function() {' ). + lo_buf->add( ' this.markVisiblesAsAdded();' ). + lo_buf->add( ' submitSapeventForm(this.collectData(), this.formAction);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'StageHelper.prototype.submitPatch = function() {' ). + lo_buf->add( ' submitSapeventForm(this.collectData(), this.patchAction);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Extract data from the table' ). + lo_buf->add( 'StageHelper.prototype.collectData = function() {' ). + lo_buf->add( ' var data = {};' ). + lo_buf->add( ' this.iterateStageTab(false, function(row) {' ). + lo_buf->add( ' data[row.cells[this.colIndex["name"]].innerText] = row.cells[this.colIndex["status"]].innerText;' ). + lo_buf->add( ' });' ). + lo_buf->add( ' return data;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'StageHelper.prototype.markVisiblesAsAdded = function() {' ). + lo_buf->add( ' this.iterateStageTab(false, function(row) {' ). + lo_buf->add( ' // TODO refactor, unify updateRow logic' ). + lo_buf->add( ' if (row.style.display === "" && row.className === "local") { // visible' ). + lo_buf->add( ' this.updateRow(row, this.STATUS.add);' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' this.updateRow(row, this.STATUS.reset);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Table iteration helper' ). + lo_buf->add( 'StageHelper.prototype.iterateStageTab = function(changeMode, cb /*, ...*/) {' ). + lo_buf->add( ' var restArgs = Array.prototype.slice.call(arguments, 2);' ). + lo_buf->add( ' var table = this.dom.stageTab;' ). + lo_buf->add( ' var retTotal = 0;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (changeMode) {' ). + lo_buf->add( ' var scrollOffset = window.pageYOffset;' ). + lo_buf->add( '' ). + lo_buf->add( ' this.dom.stageTab.style.display = "none";' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' for (var b = 0, bN = table.tBodies.length; b < bN; b++) {' ). + lo_buf->add( ' var tbody = table.tBodies[b];' ). + lo_buf->add( ' for (var r = 0, rN = tbody.rows.length; r < rN; r++) {' ). + lo_buf->add( ' var args = [tbody.rows[r]].concat(restArgs);' ). + lo_buf->add( ' var retVal = cb.apply(this, args); // callback' ). + lo_buf->add( '' ). + lo_buf->add( ' if (typeof retVal === "number") retTotal += retVal;' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' if (changeMode) {' ). + lo_buf->add( ' this.dom.stageTab.style.display = "";' ). + lo_buf->add( ' window.scrollTo(0, scrollOffset);' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' return retTotal;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Check List Wrapper' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( 'function CheckListWrapper(id, cbAction, cbActionOnlyMyChanges) {' ). + lo_buf->add( ' this.id = document.getElementById(id);' ). + lo_buf->add( ' this.cbAction = cbAction;' ). + lo_buf->add( ' this.cbActionOnlyMyChanges = cbActionOnlyMyChanges;' ). + lo_buf->add( ' this.id.onclick = this.onClick.bind(this);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'CheckListWrapper.prototype.onClick = function(e) { // eslint-disable-line no-unused-vars' ). + lo_buf->add( ' // Get nodes' ). + lo_buf->add( ' var target = event.target || event.srcElement;' ). + lo_buf->add( ' if (!target) return;' ). + lo_buf->add( ' if (target.tagName !== "A") { target = target.parentNode } // icon clicked' ). + lo_buf->add( ' if (target.tagName !== "A") return;' ). + lo_buf->add( ' if (target.parentNode.tagName !== "LI") return;' ). + lo_buf->add( '' ). + lo_buf->add( ' var nodeA = target;' ). + lo_buf->add( ' var nodeLi = target.parentNode;' ). + lo_buf->add( ' var nodeIcon = target.children[0];' ). + lo_buf->add( ' if (!nodeIcon.classList.contains("icon")) return;' ). + lo_buf->add( '' ). + lo_buf->add( ' // Node updates' ). + lo_buf->add( ' var option = nodeA.innerText;' ). + lo_buf->add( ' var oldState = nodeLi.getAttribute("data-check");' ). + lo_buf->add( ' if (oldState === null) return; // no data-check attribute - non-checkbox' ). + lo_buf->add( ' var newState = oldState === "X" ? false : true;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (newState) {' ). + lo_buf->add( ' nodeIcon.classList.remove("grey");' ). + lo_buf->add( ' nodeIcon.classList.add("blue");' ). + lo_buf->add( ' nodeLi.setAttribute("data-check", "X");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' nodeIcon.classList.remove("blue");' ). + lo_buf->add( ' nodeIcon.classList.add("grey");' ). + lo_buf->add( ' nodeLi.setAttribute("data-check", "");' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Action callback, special handling for "Only My Changes"' ). + lo_buf->add( ' if (option === "Only my changes") {' ). + lo_buf->add( ' this.cbActionOnlyMyChanges(nodeLi.getAttribute("data-aux"), newState);' ). + lo_buf->add( '' ). + lo_buf->add( ' // hide "Changed By" menu' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' this.cbAction(nodeLi.getAttribute("data-aux"), option, newState);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Diff Page Logic' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '// Diff helper constructor' ). + lo_buf->add( 'function DiffHelper(params) {' ). + lo_buf->add( ' this.pageSeed = params.seed;' ). + lo_buf->add( ' this.counter = 0;' ). + lo_buf->add( ' this.stageAction = params.stageAction;' ). + lo_buf->add( '' ). + lo_buf->add( ' // DOM nodes' ). + lo_buf->add( ' this.dom = {' ). + lo_buf->add( ' diffList : document.getElementById(params.ids.diffList),' ). + lo_buf->add( ' stageButton: document.getElementById(params.ids.stageButton)' ). + lo_buf->add( ' };' ). + lo_buf->add( '' ). + lo_buf->add( ' this.repoKey = this.dom.diffList.getAttribute("data-repo-key");' ). + lo_buf->add( ' if (!this.repoKey) return; // Unexpected' ). + lo_buf->add( '' ). + lo_buf->add( ' this.dom.jump = document.getElementById(params.ids.jump);' ). + lo_buf->add( ' this.dom.jump.onclick = this.onJump.bind(this);' ). + lo_buf->add( '' ). + lo_buf->add( ' // Checklist wrapper' ). + lo_buf->add( ' if (document.getElementById(params.ids.filterMenu)) {' ). + lo_buf->add( ' this.checkList = new CheckListWrapper(params.ids.filterMenu, this.onFilter.bind(this), this.onFilterOnlyMyChanges.bind(this));' ). + lo_buf->add( ' this.dom.filterButton = document.getElementById(params.ids.filterMenu).parentNode;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Hijack stage command' ). + lo_buf->add( ' if (this.dom.stageButton) {' ). + lo_buf->add( ' this.dom.stageButton.href = "#";' ). + lo_buf->add( ' this.dom.stageButton.onclick = this.onStage.bind(this);' ). + lo_buf->add( ' }' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// Action on jump click' ). + lo_buf->add( 'DiffHelper.prototype.onJump = function(e) {' ). + lo_buf->add( ' var text = ((e.target && e.target.text) || e);' ). + lo_buf->add( ' if (!text) return;' ). + lo_buf->add( '' ). + lo_buf->add( ' var elFile = document.querySelector("[data-file*=''" + text + "'']");' ). + lo_buf->add( ' if (!elFile) return;' ). + lo_buf->add( '' ). + lo_buf->add( ' setTimeout(function() {' ). + lo_buf->add( ' elFile.scrollIntoView();' ). + lo_buf->add( ' }, 100);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Action on filter click' ). + lo_buf->add( 'DiffHelper.prototype.onFilter = function(attr, target, state) {' ). + lo_buf->add( ' this.applyFilter(attr, target, state);' ). + lo_buf->add( ' this.highlightButton(state);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'DiffHelper.prototype.onFilterOnlyMyChanges = function(username, state) {' ). + lo_buf->add( ' this.applyOnlyMyChangesFilter(username, state);' ). + lo_buf->add( ' this.counter = 0;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (state) {' ). + lo_buf->add( ' this.dom.filterButton.classList.add("bgorange");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' this.dom.filterButton.classList.remove("bgorange");' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // apply logic on Changed By list items' ). + lo_buf->add( ' var changedByListItems = Array.prototype.slice.call(document.querySelectorAll("[data-aux*=changed-by]"));' ). + lo_buf->add( '' ). + lo_buf->add( ' changedByListItems' ). + lo_buf->add( ' .map(function(item) {' ). + lo_buf->add( ' var nodeIcon = item.children[0].children[0];' ). + lo_buf->add( '' ). + lo_buf->add( ' if (state === true) {' ). + lo_buf->add( ' if (item.innerText === username) { // current user' ). + lo_buf->add( ' item.style.display = "";' ). + lo_buf->add( ' item.setAttribute("data-check", "X");' ). + lo_buf->add( '' ). + lo_buf->add( ' if (nodeIcon) {' ). + lo_buf->add( ' nodeIcon.classList.remove("grey");' ). + lo_buf->add( ' nodeIcon.classList.add("blue");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' } else { // other users' ). + lo_buf->add( ' item.style.display = "none";' ). + lo_buf->add( ' item.setAttribute("data-check", "");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' item.style.display = "";' ). + lo_buf->add( ' item.setAttribute("data-check", "X");' ). + lo_buf->add( '' ). + lo_buf->add( ' if (nodeIcon) {' ). + lo_buf->add( ' nodeIcon.classList.remove("grey");' ). + lo_buf->add( ' nodeIcon.classList.add("blue");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'DiffHelper.prototype.applyOnlyMyChangesFilter = function(username, state) {' ). + lo_buf->add( ' var jumpListItems = Array.prototype.slice.call(document.querySelectorAll("[id*=li_jump]"));' ). + lo_buf->add( '' ). + lo_buf->add( ' this.iterateDiffList(function(div) {' ). + lo_buf->add( ' if (state === true) { // switching on "Only my changes" filter' ). + lo_buf->add( ' if (div.getAttribute("data-changed-by") === username) {' ). + lo_buf->add( ' div.style.display = state ? "" : "none";' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' div.style.display = state ? "none" : "";' ). + lo_buf->add( ' }' ). + lo_buf->add( ' } else { // disabling' ). + lo_buf->add( ' div.style.display = "";' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // hide the file in the jump list' ). + lo_buf->add( ' var dataFile = div.getAttribute("data-file");' ). + lo_buf->add( ' jumpListItems' ). + lo_buf->add( ' .filter(function(item) { return dataFile.includes(item.text) })' ). + lo_buf->add( ' .map(function(item) { item.style.display = div.style.display });' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Hide/show diff based on params' ). + lo_buf->add( 'DiffHelper.prototype.applyFilter = function(attr, target, state) {' ). + lo_buf->add( ' var jumpListItems = Array.prototype.slice.call(document.querySelectorAll("[id*=li_jump]"));' ). + lo_buf->add( '' ). + lo_buf->add( ' this.iterateDiffList(function(div) {' ). + lo_buf->add( ' if (div.getAttribute("data-" + attr) === target) {' ). + lo_buf->add( ' div.style.display = state ? "" : "none";' ). + lo_buf->add( '' ). + lo_buf->add( ' // hide the file in the jump list' ). + lo_buf->add( ' var dataFile = div.getAttribute("data-file");' ). + lo_buf->add( ' jumpListItems' ). + lo_buf->add( ' .filter(function(item) { return dataFile.includes(item.text) })' ). + lo_buf->add( ' .map(function(item) { item.style.display = div.style.display });' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Action on stage -> save visible diffs as state for stage page' ). + lo_buf->add( 'DiffHelper.prototype.onStage = function(e) { // eslint-disable-line no-unused-vars' ). + lo_buf->add( ' if (window.sessionStorage) {' ). + lo_buf->add( ' var data = this.buildStageCache();' ). + lo_buf->add( ' window.sessionStorage.setItem(this.pageSeed, JSON.stringify(data));' ). + lo_buf->add( ' }' ). + lo_buf->add( ' var getParams = { key: this.repoKey, seed: this.pageSeed };' ). + lo_buf->add( ' submitSapeventForm(getParams, this.stageAction, "get");' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Collect visible diffs' ). + lo_buf->add( 'DiffHelper.prototype.buildStageCache = function() {' ). + lo_buf->add( ' var list = {};' ). + lo_buf->add( ' this.iterateDiffList(function(div) {' ). + lo_buf->add( ' var filename = div.getAttribute("data-file");' ). + lo_buf->add( ' if (!div.style.display && filename) { // No display override - visible !!' ). + lo_buf->add( ' list[filename] = "A"; // Add' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( ' return list;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Table iterator' ). + lo_buf->add( 'DiffHelper.prototype.iterateDiffList = function(cb /*, ...*/) {' ). + lo_buf->add( ' var restArgs = Array.prototype.slice.call(arguments, 1);' ). + lo_buf->add( ' var diffList = this.dom.diffList;' ). + lo_buf->add( '' ). + lo_buf->add( ' for (var i = 0, iN = diffList.children.length; i < iN; i++) {' ). + lo_buf->add( ' var div = diffList.children[i];' ). + lo_buf->add( ' if (div.className !== "diff") continue;' ). + lo_buf->add( ' var args = [div].concat(restArgs);' ). + lo_buf->add( ' cb.apply(this, args);// callback' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Highlight filter button if filter is activated' ). + lo_buf->add( 'DiffHelper.prototype.highlightButton = function(state) {' ). + lo_buf->add( ' this.counter += state ? -1 : 1;' ). + lo_buf->add( ' if (this.counter > 0) {' ). + lo_buf->add( ' this.dom.filterButton.classList.add("bgorange");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' this.dom.filterButton.classList.remove("bgorange");' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Collapse or expand diffs' ). + lo_buf->add( 'function onDiffCollapse(event) {' ). + lo_buf->add( ' var source = event.target || event.srcElement;' ). + lo_buf->add( ' var nextDiffContent = source.parentElement.nextElementSibling;' ). + lo_buf->add( ' var hide;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (source.classList.contains("icon-chevron-down")) {' ). + lo_buf->add( ' source.classList.remove("icon-chevron-down");' ). + lo_buf->add( ' source.classList.add("icon-chevron-right");' ). + lo_buf->add( ' hide = true;' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' source.classList.remove("icon-chevron-right");' ). + lo_buf->add( ' source.classList.add("icon-chevron-down");' ). + lo_buf->add( ' hide = false;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' hide ? nextDiffContent.classList.add("nodisplay"): nextDiffContent.classList.remove("nodisplay");' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// Add bottom margin, so that we can scroll to the top of the last file' ). + lo_buf->add( 'function addMarginBottom() {' ). + lo_buf->add( ' document.getElementsByTagName("body")[0].style.marginBottom = screen.height + "px";' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Diff Page Column Selection' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( 'function DiffColumnSelection() {' ). + lo_buf->add( ' this.selectedColumnIdx = -1;' ). + lo_buf->add( ' this.lineNumColumnIdx = -1;' ). + lo_buf->add( ' //https://stackoverflow.com/questions/2749244/javascript-setinterval-and-this-solution' ). + lo_buf->add( ' document.addEventListener("mousedown", this.mousedownEventListener.bind(this));' ). + lo_buf->add( ' document.addEventListener("copy", this.copyEventListener.bind(this));' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'DiffColumnSelection.prototype.mousedownEventListener = function(e) {' ). + lo_buf->add( ' // Select text in a column of an HTML table and copy to clipboard (in DIFF view)' ). + lo_buf->add( ' // (https://stackoverflow.com/questions/6619805/select-text-in-a-column-of-an-html-table)' ). + lo_buf->add( ' // Process mousedown event for all TD elements -> apply CSS class at TABLE level.' ). + lo_buf->add( ' // (https://stackoverflow.com/questions/40956717/how-to-addeventlistener-to-multiple-elements-in-a-single-line)' ). + lo_buf->add( ' var unifiedLineNumColumnIdx = 0;' ). + lo_buf->add( ' var unifiedCodeColumnIdx = 3;' ). + lo_buf->add( ' var splitLineNumLeftColumnIdx = 0;' ). + lo_buf->add( ' var splitCodeLeftColumnIdx = 2;' ). + lo_buf->add( ' var splitLineNumRightColumnIdx = 3;' ). + lo_buf->add( ' var splitCodeRightColumnIdx = 5;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (e.button !== 0) return; // function is only valid for left button, not right button' ). + lo_buf->add( '' ). + lo_buf->add( ' var td = e.target;' ). + lo_buf->add( '' ). + lo_buf->add( ' while (td != undefined && td.tagName != "TD" && td.tagName != "TBODY") td = td.parentElement;' ). + lo_buf->add( ' if (td == undefined) return;' ). + lo_buf->add( ' var table = td.parentElement.parentElement;' ). + lo_buf->add( '' ). + lo_buf->add( ' var patchColumnCount = 0;' ). + lo_buf->add( ' if (td.parentElement.cells[0].classList.contains("patch")) {' ). + lo_buf->add( ' patchColumnCount = 1;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' if (td.classList.contains("diff_left")) {' ). + lo_buf->add( ' table.classList.remove("diff_select_right");' ). + lo_buf->add( ' table.classList.add("diff_select_left");' ). + lo_buf->add( ' if (window.getSelection() && this.selectedColumnIdx != splitCodeLeftColumnIdx + patchColumnCount) {' ). + lo_buf->add( ' // De-select to avoid effect of dragging selection in case the right column was first selected' ). + lo_buf->add( ' if (document.body.createTextRange) { // All IE but Edge' ). + lo_buf->add( ' // document.getSelection().removeAllRanges() may trigger error' ). + lo_buf->add( ' // so use this code which is equivalent but does not fail' ). + lo_buf->add( ' // (https://stackoverflow.com/questions/22914075/javascript-error-800a025e-using-range-selector)' ). + lo_buf->add( ' range = document.body.createTextRange();' ). + lo_buf->add( ' range.collapse();' ). + lo_buf->add( ' range.select();' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' document.getSelection().removeAllRanges();' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' this.selectedColumnIdx = splitCodeLeftColumnIdx + patchColumnCount;' ). + lo_buf->add( ' this.lineNumColumnIdx = splitLineNumLeftColumnIdx + patchColumnCount;' ). + lo_buf->add( '' ). + lo_buf->add( ' } else if (td.classList.contains("diff_right")) {' ). + lo_buf->add( ' table.classList.remove("diff_select_left");' ). + lo_buf->add( ' table.classList.add("diff_select_right");' ). + lo_buf->add( ' if (window.getSelection() && this.selectedColumnIdx != splitCodeRightColumnIdx + patchColumnCount) {' ). + lo_buf->add( ' if (document.body.createTextRange) { // All IE but Edge' ). + lo_buf->add( ' // document.getSelection().removeAllRanges() may trigger error' ). + lo_buf->add( ' // so use this code which is equivalent but does not fail' ). + lo_buf->add( ' // (https://stackoverflow.com/questions/22914075/javascript-error-800a025e-using-range-selector)' ). + lo_buf->add( ' var range = document.body.createTextRange();' ). + lo_buf->add( ' range.collapse();' ). + lo_buf->add( ' range.select();' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' document.getSelection().removeAllRanges();' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' this.selectedColumnIdx = splitCodeRightColumnIdx + patchColumnCount;' ). + lo_buf->add( ' this.lineNumColumnIdx = splitLineNumRightColumnIdx + patchColumnCount;' ). + lo_buf->add( '' ). + lo_buf->add( ' } else if (td.classList.contains("diff_unified")) {' ). + lo_buf->add( ' this.selectedColumnIdx = unifiedCodeColumnIdx;' ). + lo_buf->add( ' this.lineNumColumnIdx = unifiedLineNumColumnIdx;' ). + lo_buf->add( '' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' this.selectedColumnIdx = -1;' ). + lo_buf->add( ' this.lineNumColumnIdx = -1;' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'DiffColumnSelection.prototype.copyEventListener = function(e) {' ). + lo_buf->add( ' // Select text in a column of an HTML table and copy to clipboard (in DIFF view)' ). + lo_buf->add( ' // (https://stackoverflow.com/questions/6619805/select-text-in-a-column-of-an-html-table)' ). + lo_buf->add( ' var td = e.target;' ). + lo_buf->add( '' ). + lo_buf->add( ' while (td != undefined && td.tagName != "TD" && td.tagName != "TBODY") td = td.parentElement;' ). + lo_buf->add( ' if (td != undefined) {' ). + lo_buf->add( ' // Use window.clipboardData instead of e.clipboardData' ). + lo_buf->add( ' // (https://stackoverflow.com/questions/23470958/ie-10-copy-paste-issue)' ). + lo_buf->add( ' var clipboardData = (e.clipboardData == undefined ? window.clipboardData : e.clipboardData);' ). + lo_buf->add( ' var text = this.getSelectedText();' ). + lo_buf->add( ' clipboardData.setData("text", text);' ). + lo_buf->add( ' e.preventDefault();' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'DiffColumnSelection.prototype.getSelectedText = function() {' ). + lo_buf->add( ' // Select text in a column of an HTML table and copy to clipboard (in DIFF view)' ). + lo_buf->add( ' // (https://stackoverflow.com/questions/6619805/select-text-in-a-column-of-an-html-table)' ). + lo_buf->add( ' var sel = window.getSelection();' ). + lo_buf->add( ' var range = sel.getRangeAt(0);' ). + lo_buf->add( ' var doc = range.cloneContents();' ). + lo_buf->add( ' var nodes = doc.querySelectorAll("tr");' ). + lo_buf->add( ' var text = "";' ). + lo_buf->add( ' if (nodes.length === 0) {' ). + lo_buf->add( ' text = doc.textContent;' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' var newline = "";' ). + lo_buf->add( ' var realThis = this;' ). + lo_buf->add( ' var copySide = "";' ). + lo_buf->add( ' [].forEach.call(nodes, function(tr, i) {' ). + lo_buf->add( ' var cellIdx = (i == 0 ? 0 : realThis.selectedColumnIdx);' ). + lo_buf->add( ' if (tr.cells.length > cellIdx) {' ). + lo_buf->add( ' var tdSelected = tr.cells[cellIdx];' ). + lo_buf->add( ' // decide which side to copy based on first line of selection' ). + lo_buf->add( ' if (i == 0) {' ). + lo_buf->add( ' copySide = (tdSelected.classList.contains("new") ? "new" : "old" );' ). + lo_buf->add( ' }' ). + lo_buf->add( ' // copy is interesting only for one side of code, do not copy lines which exist on other side' ). + lo_buf->add( ' if (i == 0 || copySide == "new" && !tdSelected.classList.contains("old") || copySide == "old" && !tdSelected.classList.contains("new")) {' ). + lo_buf->add( ' text += newline + tdSelected.textContent;' ). + lo_buf->add( ' // special processing for TD tag which sometimes contains newline' ). + lo_buf->add( ' // (expl: /src/ui/zabapgit_js_common.w3mi.data.js) so do not add newline again in that case.' ). + lo_buf->add( ' var lastChar = tdSelected.textContent[tdSelected.textContent.length - 1];' ). + lo_buf->add( ' if (lastChar == "\n") newline = "";' ). + lo_buf->add( ' else newline = "\n";' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' });' ). + lo_buf->add( ' }' ). + lo_buf->add( ' return text;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Display Helper' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '// Toggle display of changelog (news) and message popups' ). + lo_buf->add( 'function toggleDisplay(divId) {' ). + lo_buf->add( ' var div = document.getElementById(divId);' ). + lo_buf->add( '' ). + lo_buf->add( ' if (div) div.style.display = (div.style.display) ? "" : "none";' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Keyboard Navigation' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( 'function KeyNavigation() { }' ). + lo_buf->add( '' ). + lo_buf->add( 'KeyNavigation.prototype.onkeydown = function(event) {' ). + lo_buf->add( ' if (event.defaultPrevented) return;' ). + lo_buf->add( '' ). + lo_buf->add( ' // navigate with arrows through list items and support pressing links with enter and space' ). + lo_buf->add( ' var isHandled = false;' ). + lo_buf->add( ' if (event.key === "Enter" || event.key === "") {' ). + lo_buf->add( ' isHandled = this.onEnterOrSpace();' ). + lo_buf->add( ' } else if (/Down$/.test(event.key)) {' ). + lo_buf->add( ' isHandled = this.onArrowDown();' ). + lo_buf->add( ' } else if (/Up$/.test(event.key)) {' ). + lo_buf->add( ' isHandled = this.onArrowUp();' ). + lo_buf->add( ' } else if (event.key === "Backspace") {' ). + lo_buf->add( ' isHandled = this.onBackspace();' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' if (isHandled) event.preventDefault();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'KeyNavigation.prototype.onEnterOrSpace = function() {' ). + lo_buf->add( ' if (document.activeElement.nodeName !== "A") return;' ). + lo_buf->add( ' var anchor = document.activeElement;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (anchor.href.replace(/#$/, "") === document.location.href.replace(/#$/, "")' ). + lo_buf->add( ' && !anchor.onclick' ). + lo_buf->add( ' && anchor.parentElement' ). + lo_buf->add( ' && anchor.parentElement.nodeName === "LI") {' ). + lo_buf->add( ' anchor.parentElement.classList.toggle("force-nav-hover");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' anchor.click();' ). + lo_buf->add( ' }' ). + lo_buf->add( ' return true;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'KeyNavigation.prototype.focusListItem = function(li) {' ). + lo_buf->add( ' var anchor = li.firstElementChild;' ). + lo_buf->add( ' if (!anchor || anchor.nodeName !== "A") return false;' ). + lo_buf->add( ' anchor.focus();' ). + lo_buf->add( ' return true;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'KeyNavigation.prototype.closeDropdown = function(dropdownLi) {' ). + lo_buf->add( ' dropdownLi.classList.remove("force-nav-hover");' ). + lo_buf->add( ' if (dropdownLi.firstElementChild.nodeName === "A") dropdownLi.firstElementChild.focus();' ). + lo_buf->add( ' return true;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'KeyNavigation.prototype.onBackspace = function() {' ). + lo_buf->add( ' var activeElement = document.activeElement;' ). + lo_buf->add( '' ). + lo_buf->add( ' // Detect opened subsequent dropdown' ). + lo_buf->add( ' if (activeElement.nodeName === "A"' ). + lo_buf->add( ' && activeElement.parentElement' ). + lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). + lo_buf->add( ' && activeElement.parentElement.classList.contains("force-nav-hover")) {' ). + lo_buf->add( ' return this.closeDropdown(activeElement.parentElement);' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Detect opened parent dropdown' ). + lo_buf->add( ' if (activeElement.nodeName === "A"' ). + lo_buf->add( ' && activeElement.parentElement' ). + lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). + lo_buf->add( ' && activeElement.parentElement.parentElement' ). + lo_buf->add( ' && activeElement.parentElement.parentElement.nodeName === "UL"' ). + lo_buf->add( ' && activeElement.parentElement.parentElement.parentElement' ). + lo_buf->add( ' && activeElement.parentElement.parentElement.parentElement.nodeName === "LI"' ). + lo_buf->add( ' && activeElement.parentElement.parentElement.parentElement.classList.contains("force-nav-hover")) {' ). + lo_buf->add( ' return this.closeDropdown(activeElement.parentElement.parentElement.parentElement);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'KeyNavigation.prototype.onArrowDown = function() {' ). + lo_buf->add( ' var activeElement = document.activeElement;' ). + lo_buf->add( '' ). + lo_buf->add( ' // Start of dropdown list: LI > selected A :: UL > LI > A' ). + lo_buf->add( ' if (activeElement.nodeName === "A"' ). + lo_buf->add( ' && activeElement.parentElement' ). + lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). + lo_buf->add( ' && activeElement.parentElement.classList.contains("force-nav-hover") // opened dropdown' ). + lo_buf->add( ' && activeElement.nextElementSibling' ). + lo_buf->add( ' && activeElement.nextElementSibling.nodeName === "UL"' ). + lo_buf->add( ' && activeElement.nextElementSibling.firstElementChild' ). + lo_buf->add( ' && activeElement.nextElementSibling.firstElementChild.nodeName === "LI") {' ). + lo_buf->add( ' return this.focusListItem(activeElement.nextElementSibling.firstElementChild);' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Next item of dropdown list: ( LI > selected A ) :: LI > A' ). + lo_buf->add( ' if (activeElement.nodeName === "A"' ). + lo_buf->add( ' && activeElement.parentElement' ). + lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). + lo_buf->add( ' && activeElement.parentElement.nextElementSibling' ). + lo_buf->add( ' && activeElement.parentElement.nextElementSibling.nodeName === "LI") {' ). + lo_buf->add( ' return this.focusListItem(activeElement.parentElement.nextElementSibling);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'KeyNavigation.prototype.onArrowUp = function() {' ). + lo_buf->add( ' var activeElement = document.activeElement;' ). + lo_buf->add( '' ). + lo_buf->add( ' // Prev item of dropdown list: ( LI > selected A ) <:: LI > A' ). + lo_buf->add( ' if (activeElement.nodeName === "A"' ). + lo_buf->add( ' && activeElement.parentElement' ). + lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). + lo_buf->add( ' && activeElement.parentElement.previousElementSibling' ). + lo_buf->add( ' && activeElement.parentElement.previousElementSibling.nodeName === "LI") {' ). + lo_buf->add( ' return this.focusListItem(activeElement.parentElement.previousElementSibling);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'KeyNavigation.prototype.getHandler = function() {' ). + lo_buf->add( ' return this.onkeydown.bind(this);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// this function enables the navigation with arrows through list items (li)' ). + lo_buf->add( '// e.g. in dropdown menus' ). + lo_buf->add( 'function enableArrowListNavigation() {' ). + lo_buf->add( ' document.addEventListener("keydown", new KeyNavigation().getHandler());' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Link Hints (Vimium-like)' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( 'function LinkHints(linkHintHotKey) {' ). + lo_buf->add( ' this.linkHintHotKey = linkHintHotKey;' ). + lo_buf->add( ' this.areHintsDisplayed = false;' ). + lo_buf->add( ' this.pendingPath = ""; // already typed code prefix' ). + lo_buf->add( ' this.hintsMap = this.deployHintContainers();' ). + lo_buf->add( ' this.activatedDropdown = null;' ). + lo_buf->add( ' this.yankModeActive = false;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.getHintStartValue = function(targetsCount) {' ). + lo_buf->add( ' // e.g. if we have 89 tooltips we start from 10' ). + lo_buf->add( ' // if we have 90 tooltips we start from 100' ). + lo_buf->add( ' // if we have 900 tooltips we start from 1000' ). + lo_buf->add( ' var' ). + lo_buf->add( ' baseLength = Math.pow(10, targetsCount.toString().length - 1),' ). + lo_buf->add( ' maxHintStringLength = (targetsCount + baseLength).toString().length;' ). + lo_buf->add( ' return Math.pow(10, maxHintStringLength - 1);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.deployHintContainers = function() {' ). + lo_buf->add( '' ). + lo_buf->add( ' var hintTargets = document.querySelectorAll("a, input, textarea, i");' ). + lo_buf->add( ' var codeCounter = this.getHintStartValue(hintTargets.length);' ). + lo_buf->add( ' var hintsMap = { first: codeCounter };' ). + lo_buf->add( '' ). + lo_buf->add( ' // ' ). + lo_buf->add( ' // 123' ). + lo_buf->add( ' // ' ). + lo_buf->add( ' for (var i = 0, N = hintTargets.length; i < N; i++) {' ). + lo_buf->add( ' // skip hidden fields' ). + lo_buf->add( ' if (hintTargets[i].type === "HIDDEN") {' ). + lo_buf->add( ' continue;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' var hint = {};' ). + lo_buf->add( '' ). + lo_buf->add( ' hint.container = document.createElement("span");' ). + lo_buf->add( ' hint.pendingSpan = document.createElement("span");' ). + lo_buf->add( ' hint.remainingSpan = document.createElement("span");' ). + lo_buf->add( ' hint.parent = hintTargets[i];' ). + lo_buf->add( ' hint.code = codeCounter.toString();' ). + lo_buf->add( '' ). + lo_buf->add( ' hint.container.appendChild(hint.pendingSpan);' ). + lo_buf->add( ' hint.container.appendChild(hint.remainingSpan);' ). + lo_buf->add( '' ). + lo_buf->add( ' hint.pendingSpan.classList.add("pending");' ). + lo_buf->add( ' hint.container.classList.add("link-hint");' ). + lo_buf->add( ' if (hint.parent.nodeName === "INPUT" || hint.parent.nodeName === "TEXTAREA") {' ). + lo_buf->add( ' hint.container.classList.add("link-hint-input");' ). + lo_buf->add( ' } else if (hint.parent.nodeName === "A") {' ). + lo_buf->add( ' hint.container.classList.add("link-hint-a");' ). + lo_buf->add( ' } else if (hint.parent.nodeName === "I" && hint.parent.classList.contains("cursor-pointer")) {' ). + lo_buf->add( ' hint.container.classList.add("link-hint-i");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' continue;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' hint.container.classList.add("nodisplay"); // hide by default' ). + lo_buf->add( ' hint.container.dataset.code = codeCounter.toString(); // not really needed, more for debug' ). + lo_buf->add( '' ). + lo_buf->add( ' if (hintTargets[i].nodeName === "INPUT" || hintTargets[i].nodeName === "TEXTAREA") {' ). + lo_buf->add( ' // does not work if inside the input node' ). + lo_buf->add( ' if (hintTargets[i].type === "checkbox" || hintTargets[i].type === "radio") {' ). + lo_buf->add( ' if (hintTargets[i].nextElementSibling && hintTargets[i].nextElementSibling.nodeName === "LABEL") {' ). + lo_buf->add( ' // insert at end of label' ). + lo_buf->add( ' hintTargets[i].nextElementSibling.appendChild(hint.container);' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' // inserting right after' ). + lo_buf->add( ' hintTargets[i].insertAdjacentElement("afterend", hint.container);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' // inserting right after' ). + lo_buf->add( ' hintTargets[i].insertAdjacentElement("afterend", hint.container);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' hintTargets[i].appendChild(hint.container);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' hintsMap[codeCounter++] = hint;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' hintsMap.last = codeCounter - 1;' ). + lo_buf->add( ' return hintsMap;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.getHandler = function() {' ). + lo_buf->add( ' return this.handleKey.bind(this);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.handleKey = function(event) {' ). + lo_buf->add( ' if (event.defaultPrevented) {' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' if (event.key === "y") {' ). + lo_buf->add( ' this.yankModeActive = !this.yankModeActive;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' if (event.key === this.linkHintHotKey && Hotkeys.isHotkeyCallPossible()) {' ). + lo_buf->add( '' ). + lo_buf->add( ' // on user hide hints, close an opened dropdown too' ). + lo_buf->add( ' if (this.areHintsDisplayed && this.activatedDropdown) this.closeActivatedDropdown();' ). + lo_buf->add( ' if (this.areHintsDisplayed) this.yankModeActive = false;' ). + lo_buf->add( '' ). + lo_buf->add( ' this.pendingPath = "";' ). + lo_buf->add( ' this.displayHints(!this.areHintsDisplayed);' ). + lo_buf->add( '' ). + lo_buf->add( ' } else if (this.areHintsDisplayed) {' ). + lo_buf->add( '' ). + lo_buf->add( ' // the user tries to reach a hint' ). + lo_buf->add( ' this.pendingPath += event.key;' ). + lo_buf->add( '' ). + lo_buf->add( ' var hint = this.hintsMap[this.pendingPath];' ). + lo_buf->add( '' ). + lo_buf->add( ' if (hint) { // we are there, we have a fully specified tooltip. Let us activate or yank it' ). + lo_buf->add( ' this.displayHints(false);' ). + lo_buf->add( ' event.preventDefault();' ). + lo_buf->add( ' if (this.yankModeActive) {' ). + lo_buf->add( ' submitSapeventForm({ clipboard: hint.parent.firstChild.textContent }, "clipboard");' ). + lo_buf->add( ' this.yankModeActive = false;' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' this.hintActivate(hint);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' // we are not there yet, but let us filter the link so that only' ). + lo_buf->add( ' // the partially matched are shown' ). + lo_buf->add( ' var visibleHints = this.filterHints();' ). + lo_buf->add( ' if (!visibleHints) {' ). + lo_buf->add( ' this.displayHints(false);' ). + lo_buf->add( ' if (this.activatedDropdown) this.closeActivatedDropdown();' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.closeActivatedDropdown = function() {' ). + lo_buf->add( ' if (!this.activatedDropdown) return;' ). + lo_buf->add( ' this.activatedDropdown.classList.remove("force-nav-hover");' ). + lo_buf->add( ' this.activatedDropdown = null;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.displayHints = function(isActivate) {' ). + lo_buf->add( ' this.areHintsDisplayed = isActivate;' ). + lo_buf->add( ' for (var i = this.hintsMap.first; i <= this.hintsMap.last; i++) {' ). + lo_buf->add( ' var hint = this.hintsMap[i];' ). + lo_buf->add( ' if (isActivate) {' ). + lo_buf->add( ' hint.container.classList.remove("nodisplay");' ). + lo_buf->add( ' hint.pendingSpan.innerText = "";' ). + lo_buf->add( ' hint.remainingSpan.innerText = hint.code;' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' hint.container.classList.add("nodisplay");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.hintActivate = function(hint) {' ). + lo_buf->add( ' if (hint.parent.nodeName === "A"' ). + lo_buf->add( ' // hint.parent.href doesn`t have a # at the end while accessing dropdowns the first time.' ). + lo_buf->add( ' // Seems like a idiosyncrasy of SAP GUI`s IE. So let`s ignore the last character.' ). + lo_buf->add( ' && (hint.parent.href.substr(0, hint.parent.href.length - 1) === document.location.href)// href is #' ). + lo_buf->add( ' && !hint.parent.onclick // no handler' ). + lo_buf->add( ' && hint.parent.parentElement && hint.parent.parentElement.nodeName === "LI") {' ). + lo_buf->add( ' // probably it is a dropdown ...' ). + lo_buf->add( ' this.activatedDropdown = hint.parent.parentElement;' ). + lo_buf->add( ' this.activatedDropdown.classList.toggle("force-nav-hover");' ). + lo_buf->add( ' hint.parent.focus();' ). + lo_buf->add( ' } else if (hint.parent.type === "checkbox") {' ). + lo_buf->add( ' this.toggleCheckbox(hint);' ). + lo_buf->add( ' } else if (hint.parent.type === "radio") {' ). + lo_buf->add( ' this.toggleRadioButton(hint);' ). + lo_buf->add( ' } else if (hint.parent.type === "submit") {' ). + lo_buf->add( ' hint.parent.click();' ). + lo_buf->add( ' } else if (hint.parent.nodeName === "INPUT" || hint.parent.nodeName === "TEXTAREA") {' ). + lo_buf->add( ' hint.parent.focus();' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' hint.parent.click();' ). + lo_buf->add( ' if (this.activatedDropdown) this.closeActivatedDropdown();' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.toggleCheckbox = function(hint) {' ). + lo_buf->add( ' var checked = hint.parent.checked;' ). + lo_buf->add( ' this.triggerClickHandler(hint.parent.parentElement);' ). + lo_buf->add( ' if (checked === hint.parent.checked) {' ). + lo_buf->add( ' // fallback if no handler is registered' ). + lo_buf->add( ' hint.parent.checked = !hint.parent.checked;' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.toggleRadioButton = function(hint) {' ). + lo_buf->add( ' this.triggerClickHandler(hint.parent);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.triggerClickHandler = function(el) {' ). + lo_buf->add( ' // ensures that onclick handler is executed' ). + lo_buf->add( ' // https://stackoverflow.com/questions/41981509/trigger-an-event-when-a-checkbox-is-changed-programmatically-via-javascript' ). + lo_buf->add( ' var event = document.createEvent("HTMLEvents");' ). + lo_buf->add( ' event.initEvent("click", false, true);' ). + lo_buf->add( ' el.dispatchEvent(event);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'LinkHints.prototype.filterHints = function() {' ). + lo_buf->add( ' var visibleHints = 0;' ). + lo_buf->add( ' for (var i = this.hintsMap.first; i <= this.hintsMap.last; i++) {' ). + lo_buf->add( ' var hint = this.hintsMap[i];' ). + lo_buf->add( ' if (i.toString().startsWith(this.pendingPath)) {' ). + lo_buf->add( ' hint.pendingSpan.innerText = this.pendingPath;' ). + lo_buf->add( ' hint.remainingSpan.innerText = hint.code.substring(this.pendingPath.length);' ). + lo_buf->add( ' // hint.container.classList.remove("nodisplay"); // for backspace' ). + lo_buf->add( ' visibleHints++;' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' hint.container.classList.add("nodisplay");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' return visibleHints;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'function activateLinkHints(linkHintHotKey) {' ). + lo_buf->add( ' if (!linkHintHotKey) return;' ). + lo_buf->add( ' var oLinkHint = new LinkHints(linkHintHotKey);' ). + lo_buf->add( ' document.addEventListener("keypress", oLinkHint.getHandler());' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Hotkeys' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( 'function Hotkeys(oKeyMap) {' ). + lo_buf->add( ' this.oKeyMap = oKeyMap || {};' ). + lo_buf->add( '' ). + lo_buf->add( ' // these are the hotkeys provided by the backend' ). + lo_buf->add( ' Object.keys(this.oKeyMap).forEach(function(sKey) {' ). + lo_buf->add( '' ). + lo_buf->add( ' var action = this.oKeyMap[sKey];' ). + lo_buf->add( '' ). + lo_buf->add( ' // add a tooltip/title with the hotkey, currently only sapevents are supported' ). + lo_buf->add( ' this.getAllSapEventsForSapEventName(action).forEach(function(elAnchor) {' ). + lo_buf->add( ' elAnchor.title = elAnchor.title + " [" + sKey + "]";' ). + lo_buf->add( ' });' ). + lo_buf->add( '' ). + lo_buf->add( ' // We replace the actions with callback functions to unify' ). + lo_buf->add( ' // the hotkey execution' ). + lo_buf->add( ' this.oKeyMap[sKey] = function(oEvent) {' ). + lo_buf->add( '' ). + lo_buf->add( ' // gHelper is only valid for diff page' ). + lo_buf->add( ' var diffHelper = (window.gHelper || {});' ). + lo_buf->add( '' ). + lo_buf->add( ' // We have either a js function on this' ). + lo_buf->add( ' if (this[action]) {' ). + lo_buf->add( ' this[action].call(this);' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Or a method of the helper object for the diff page' ). + lo_buf->add( ' if (diffHelper[action]) {' ). + lo_buf->add( ' diffHelper[action].call(diffHelper);' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Or a global function' ). + lo_buf->add( ' if (window[action] && typeof (window[action]) === "function") {' ). + lo_buf->add( ' window[action].call(this);' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Or a SAP event link' ). + lo_buf->add( ' var sUiSapEventHref = this.getSapEventHref(action);' ). + lo_buf->add( ' if (sUiSapEventHref) {' ). + lo_buf->add( ' submitSapeventForm({}, sUiSapEventHref, "post");' ). + lo_buf->add( ' oEvent.preventDefault();' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Or an SAP event input' ). + lo_buf->add( ' var sUiSapEventInputAction = this.getSapEventInputAction(action);' ). + lo_buf->add( ' if (sUiSapEventInputAction) {' ). + lo_buf->add( ' submitSapeventForm({}, sUiSapEventInputAction, "post");' ). + lo_buf->add( ' oEvent.preventDefault();' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // Or an SAP event main form' ). + lo_buf->add( ' var elForm = this.getSapEventForm(action);' ). + lo_buf->add( ' if (elForm) {' ). + lo_buf->add( ' elForm.submit();' ). + lo_buf->add( ' oEvent.preventDefault();' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' };' ). + lo_buf->add( '' ). + lo_buf->add( ' }.bind(this));' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'Hotkeys.prototype.showHotkeys = function() {' ). + lo_buf->add( ' var elHotkeys = document.querySelector("#hotkeys");' ). + lo_buf->add( '' ). + lo_buf->add( ' if (elHotkeys) {' ). + lo_buf->add( ' elHotkeys.style.display = (elHotkeys.style.display) ? "" : "none";' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Hotkeys.prototype.getAllSapEventsForSapEventName = function (sSapEvent) {' ). + lo_buf->add( ' if (/^#+$/.test(sSapEvent)){' ). + lo_buf->add( ' // sSapEvent contains only #. Nothing sensible can be done here' ). + lo_buf->add( ' return [];' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' var includesSapEvent = function(text){' ). + lo_buf->add( ' return (text.includes("sapevent") || text.includes("SAPEVENT"));' ). + lo_buf->add( ' };' ). + lo_buf->add( '' ). + lo_buf->add( ' return [].slice' ). + lo_buf->add( ' .call(document.querySelectorAll("a[href*="+ sSapEvent +"], input[formaction*="+ sSapEvent+"]"))' ). + lo_buf->add( ' .filter(function (elem) {' ). + lo_buf->add( ' return (elem.nodeName === "A" && includesSapEvent(elem.href)' ). + lo_buf->add( ' || (elem.nodeName === "INPUT" && includesSapEvent(elem.formAction)));' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Hotkeys.prototype.getSapEventHref = function(sSapEvent) {' ). + lo_buf->add( ' return this.getAllSapEventsForSapEventName(sSapEvent)' ). + lo_buf->add( ' .filter(function(el) {' ). + lo_buf->add( ' // only anchors' ). + lo_buf->add( ' return (!!el.href);' ). + lo_buf->add( ' })' ). + lo_buf->add( ' .map(function(oSapEvent) {' ). + lo_buf->add( ' return oSapEvent.href;' ). + lo_buf->add( ' })' ). + lo_buf->add( ' .filter(this.eliminateSapEventFalsePositives(sSapEvent))' ). + lo_buf->add( ' .pop();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Hotkeys.prototype.getSapEventInputAction = function(sSapEvent) {' ). + lo_buf->add( ' return this.getAllSapEventsForSapEventName(sSapEvent)' ). + lo_buf->add( ' .filter(function(el) {' ). + lo_buf->add( ' // input forms' ). + lo_buf->add( ' return (el.type === "submit");' ). + lo_buf->add( ' })' ). + lo_buf->add( ' .map(function(oSapEvent) {' ). + lo_buf->add( ' return oSapEvent.formAction;' ). + lo_buf->add( ' })' ). + lo_buf->add( ' .filter(this.eliminateSapEventFalsePositives(sSapEvent))' ). + lo_buf->add( ' .pop();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Hotkeys.prototype.getSapEventForm = function(sSapEvent) {' ). + lo_buf->add( ' return this.getAllSapEventsForSapEventName(sSapEvent)' ). + lo_buf->add( ' .filter(function(el) {' ). + lo_buf->add( ' // forms' ). + lo_buf->add( ' var parentForm = el.parentNode.parentNode.parentNode;' ). + lo_buf->add( ' return (el.type === "submit" && parentForm.nodeName === "FORM");' ). + lo_buf->add( ' })' ). + lo_buf->add( ' .map(function(oSapEvent) {' ). + lo_buf->add( ' return oSapEvent.parentNode.parentNode.parentNode;' ). + lo_buf->add( ' })' ). + lo_buf->add( ' .pop();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Hotkeys.prototype.eliminateSapEventFalsePositives = function(sapEvent) {' ). + lo_buf->add( ' return function(sapEventAttr) {' ). + lo_buf->add( ' return sapEventAttr.match(new RegExp("\\b" + sapEvent + "\\b"));' ). + lo_buf->add( ' };' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Hotkeys.prototype.onkeydown = function(oEvent) {' ). + lo_buf->add( ' if (oEvent.defaultPrevented) {' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' if (!Hotkeys.isHotkeyCallPossible()) {' ). + lo_buf->add( ' return;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' var' ). + lo_buf->add( ' sKey = oEvent.key || String.fromCharCode(oEvent.keyCode),' ). + lo_buf->add( ' fnHotkey = this.oKeyMap[sKey];' ). + lo_buf->add( '' ). + lo_buf->add( ' if (fnHotkey) {' ). + lo_buf->add( ' fnHotkey.call(this, oEvent);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Hotkeys.isHotkeyCallPossible = function() {' ). + lo_buf->add( ' var activeElementType = ((document.activeElement && document.activeElement.nodeName) || "");' ). + lo_buf->add( ' var activeElementReadOnly = ((document.activeElement && document.activeElement.readOnly) || false);' ). + lo_buf->add( '' ). + lo_buf->add( ' return (activeElementReadOnly || (activeElementType !== "INPUT" && activeElementType !== "TEXTAREA"));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Hotkeys.addHotkeyToHelpSheet = function(key, description) {' ). + lo_buf->add( ' var hotkeysUl = document.querySelector("#hotkeys ul.hotkeys");' ). + lo_buf->add( ' if (!hotkeysUl) return;' ). + lo_buf->add( '' ). + lo_buf->add( ' var li = document.createElement("li");' ). + lo_buf->add( ' var spanId = document.createElement("span");' ). + lo_buf->add( ' var spanDescr = document.createElement("span");' ). + lo_buf->add( '' ). + lo_buf->add( ' spanId.className = "key-id";' ). + lo_buf->add( ' spanId.innerText = key;' ). + lo_buf->add( ' spanDescr.className = "key-descr";' ). + lo_buf->add( ' spanDescr.innerText = description;' ). + lo_buf->add( ' li.appendChild(spanId);' ). + lo_buf->add( ' li.appendChild(spanDescr);' ). + lo_buf->add( '' ). + lo_buf->add( ' hotkeysUl.appendChild(li);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'function setKeyBindings(oKeyMap) {' ). + lo_buf->add( ' var oHotkeys = new Hotkeys(oKeyMap);' ). + lo_buf->add( '' ). + lo_buf->add( ' document.addEventListener("keypress", oHotkeys.onkeydown.bind(oHotkeys));' ). + lo_buf->add( ' setTimeout(function() {' ). + lo_buf->add( ' var div = document.getElementById("hotkeys-hint");' ). + lo_buf->add( ' if (div) div.style.opacity = 0.2;' ). + lo_buf->add( ' }, 4900);' ). + lo_buf->add( ' setTimeout(function() { toggleDisplay("hotkeys-hint") }, 5000);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Patch Logic (git add -p)' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '/*' ). + lo_buf->add( ' We have three type of cascading checkboxes.' ). + lo_buf->add( ' Which means that by clicking a file or section checkbox all corresponding line checkboxes are checked.' ). + lo_buf->add( '' ). + lo_buf->add( ' The id of the checkbox indicates its semantics and its membership.' ). + lo_buf->add( '*/' ). + lo_buf->add( '' ). + lo_buf->add( '/*' ). + lo_buf->add( ' 1) file links' ). + lo_buf->add( '' ). + lo_buf->add( ' example id of file link' ). + lo_buf->add( '' ). + lo_buf->add( ' patch_file_zcl_abapgit_user_exit.clas.abap' ). + lo_buf->add( ' \________/ \_____________________________/' ). + lo_buf->add( ' | |' ). + lo_buf->add( ' | |____ file name' ). + lo_buf->add( ' |' ). + lo_buf->add( ' |' ). + lo_buf->add( ' |' ). + lo_buf->add( ' constant prefix' ). + lo_buf->add( '*/' ). + lo_buf->add( '' ). + lo_buf->add( 'function PatchFile(sId) {' ). + lo_buf->add( ' var oRegex = new RegExp("(" + this.ID + ")_(.*$)");' ). + lo_buf->add( ' var oMatch = sId.match(oRegex);' ). + lo_buf->add( '' ). + lo_buf->add( ' this.id = sId;' ). + lo_buf->add( ' this.prefix = oMatch[1];' ). + lo_buf->add( ' this.file_name = oMatch[2];' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'PatchFile.prototype.ID = "patch_file";' ). + lo_buf->add( '' ). + lo_buf->add( '/*' ). + lo_buf->add( ' 2) section links within a file' ). + lo_buf->add( '' ). + lo_buf->add( ' example id of section link' ). + lo_buf->add( '' ). + lo_buf->add( ' patch_section_zcl_abapgit_user_exit.clas.abap_1' ). + lo_buf->add( ' \___________/ \_____________________________/ ^' ). + lo_buf->add( ' | | |' ). + lo_buf->add( ' | file name |' ). + lo_buf->add( ' | |' ). + lo_buf->add( ' | ------ section' ). + lo_buf->add( ' |' ). + lo_buf->add( ' constant prefix' ). + lo_buf->add( '*/' ). + lo_buf->add( '' ). + lo_buf->add( 'function PatchSection(sId) {' ). + lo_buf->add( ' var oRegex = new RegExp("(" + this.ID + ")_(.*)_(\\d+$)");' ). + lo_buf->add( ' var oMatch = sId.match(oRegex);' ). + lo_buf->add( '' ). + lo_buf->add( ' this.id = sId;' ). + lo_buf->add( ' this.prefix = oMatch[1];' ). + lo_buf->add( ' this.file_name = oMatch[2];' ). + lo_buf->add( ' this.section = oMatch[3];' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'PatchSection.prototype.ID = "patch_section";' ). + lo_buf->add( '' ). + lo_buf->add( '/*' ). + lo_buf->add( ' 3) line links within a section' ). + lo_buf->add( '' ). + lo_buf->add( ' example id of line link' ). + lo_buf->add( '' ). + lo_buf->add( ' patch_line_zcl_abapgit_user_exit.clas.abap_1_25' ). + lo_buf->add( ' \________/ \_____________________________/ ^ ^' ). + lo_buf->add( ' ^ ^ | |' ). + lo_buf->add( ' | | | ------- line number' ). + lo_buf->add( ' | file name |' ). + lo_buf->add( ' | section' ). + lo_buf->add( ' |' ). + lo_buf->add( ' |' ). + lo_buf->add( ' constant prefix' ). + lo_buf->add( '*/' ). + lo_buf->add( '' ). + lo_buf->add( 'function PatchLine() { }' ). + lo_buf->add( '' ). + lo_buf->add( 'PatchLine.prototype.ID = "patch_line";' ). + lo_buf->add( '' ). + lo_buf->add( 'function Patch() { }' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.ID = {' ). + lo_buf->add( ' STAGE: "stage"' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.ACTION = {' ). + lo_buf->add( ' PATCH_STAGE : "patch_stage",' ). + lo_buf->add( ' REFRESH_LOCAL: "refresh_local",' ). + lo_buf->add( ' REFRESH_ALL : "refresh_all"' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.escape = function(sFileName) {' ). + lo_buf->add( ' return sFileName' ). + lo_buf->add( ' .replace(/\./g, "\\.")' ). + lo_buf->add( ' .replace(/#/g, "\\#");' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.preparePatch = function() {' ). + lo_buf->add( ' this.registerClickHandlerForFiles();' ). + lo_buf->add( ' this.registerClickHandlerForSections();' ). + lo_buf->add( ' this.registerClickHandlerForLines();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.buildSelectorInputStartsWithId = function(sId) {' ). + lo_buf->add( ' return "input[id^=''" + sId + "'']";' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.registerClickHandlerForFiles = function() {' ). + lo_buf->add( ' this.registerClickHandlerForSelectorParent(this.buildSelectorInputStartsWithId(PatchFile.prototype.ID), this.onClickFileCheckbox);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.registerClickHandlerForSections = function() {' ). + lo_buf->add( ' this.registerClickHandlerForSelectorParent(this.buildSelectorInputStartsWithId(PatchSection.prototype.ID), this.onClickSectionCheckbox);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.registerClickHandlerForLines = function() {' ). + lo_buf->add( ' this.registerClickHandlerForSelectorParent(this.buildSelectorInputStartsWithId(PatchLine.prototype.ID), this.onClickLineCheckbox);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.registerClickHandlerForSelectorParent = function(sSelector, fnCallback) {' ). + lo_buf->add( ' var elAll = document.querySelectorAll(sSelector);' ). + lo_buf->add( '' ). + lo_buf->add( ' [].forEach.call(elAll, function(elem) {' ). + lo_buf->add( ' elem.parentElement.addEventListener("click", fnCallback.bind(this));' ). + lo_buf->add( ' }.bind(this));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.getAllLineCheckboxesForFile = function(oFile) {' ). + lo_buf->add( ' return this.getAllLineCheckboxesForId(oFile.id, PatchFile.prototype.ID);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.getAllSectionCheckboxesForFile = function(oFile) {' ). + lo_buf->add( ' return this.getAllSectionCheckboxesForId(oFile.id, PatchFile.prototype.ID);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.getAllLineCheckboxesForSection = function(oSection) {' ). + lo_buf->add( ' return this.getAllLineCheckboxesForId(oSection.id, PatchSection.prototype.ID);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.getAllLineCheckboxesForId = function(sId, sIdPrefix) {' ). + lo_buf->add( ' return this.getAllCheckboxesForId(sId, sIdPrefix, PatchLine.prototype.ID);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.getAllSectionCheckboxesForId = function(sId, sIdPrefix) {' ). + lo_buf->add( ' return this.getAllCheckboxesForId(sId, sIdPrefix, PatchSection.prototype.ID);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.getAllCheckboxesForId = function(sId, sIdPrefix, sNewIdPrefix) {' ). + lo_buf->add( ' var oRegex = new RegExp("^" + sIdPrefix);' ). + lo_buf->add( '' ). + lo_buf->add( ' sId = sId.replace(oRegex, sNewIdPrefix);' ). + lo_buf->add( ' return document.querySelectorAll(this.buildSelectorInputStartsWithId(this.escape(sId)));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.getToggledCheckbox = function(oEvent) {' ). + lo_buf->add( ' var elCheckbox = null;' ). + lo_buf->add( '' ). + lo_buf->add( ' // We have either an input element or any element with input child' ). + lo_buf->add( ' // in the latter case we have to toggle the checkbox manually' ). + lo_buf->add( ' if (oEvent.srcElement.nodeName === "INPUT") {' ). + lo_buf->add( ' elCheckbox = oEvent.srcElement;' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' elCheckbox = this.toggleCheckbox(oEvent.srcElement.querySelector("INPUT"));' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' return elCheckbox;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.toggleCheckbox = function(elCheckbox) {' ). + lo_buf->add( ' elCheckbox.checked = !elCheckbox.checked;' ). + lo_buf->add( ' return elCheckbox;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.onClickFileCheckbox = function(oEvent) {' ). + lo_buf->add( ' var elCheckbox = this.getToggledCheckbox(oEvent);' ). + lo_buf->add( ' var oFile = new PatchFile(elCheckbox.id);' ). + lo_buf->add( ' var elAllLineCheckboxesOfFile = this.getAllLineCheckboxesForFile(oFile);' ). + lo_buf->add( ' var elAllSectionCheckboxesOfFile = this.getAllSectionCheckboxesForFile(oFile);' ). + lo_buf->add( '' ). + lo_buf->add( ' [].forEach.call(elAllLineCheckboxesOfFile, function(elem) {' ). + lo_buf->add( ' elem.checked = elCheckbox.checked;' ). + lo_buf->add( ' }.bind(this));' ). + lo_buf->add( '' ). + lo_buf->add( ' [].forEach.call(elAllSectionCheckboxesOfFile, function(elem) {' ). + lo_buf->add( ' elem.checked = elCheckbox.checked;' ). + lo_buf->add( ' }.bind(this));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.onClickSectionCheckbox = function(oEvent) {' ). + lo_buf->add( ' var elSrcElement = this.getToggledCheckbox(oEvent);' ). + lo_buf->add( ' var oSection = new PatchSection(elSrcElement.id);' ). + lo_buf->add( ' this.clickAllLineCheckboxesInSection(oSection, elSrcElement.checked);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.onClickLineCheckbox = function(oEvent) {' ). + lo_buf->add( ' this.getToggledCheckbox(oEvent);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.clickAllLineCheckboxesInSection = function(oSection, bChecked) {' ). + lo_buf->add( ' var elAllLineCheckboxesOfSection = this.getAllLineCheckboxesForSection(oSection);' ). + lo_buf->add( '' ). + lo_buf->add( ' [].forEach.call(elAllLineCheckboxesOfSection, function(elem) {' ). + lo_buf->add( ' elem.checked = bChecked;' ). + lo_buf->add( ' }.bind(this));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.registerStagePatch = function() {' ). + lo_buf->add( ' var elStage = document.querySelector("#" + this.ID.STAGE);' ). + lo_buf->add( ' var REFRESH_PREFIX = "refresh";' ). + lo_buf->add( '' ). + lo_buf->add( ' elStage.addEventListener("click", this.submitPatch.bind(this, this.ACTION.PATCH_STAGE));' ). + lo_buf->add( '' ). + lo_buf->add( ' var aRefresh = document.querySelectorAll("[id*=" + REFRESH_PREFIX + "]");' ). + lo_buf->add( ' [].forEach.call(aRefresh, function(el) {' ). + lo_buf->add( ' el.addEventListener("click", memorizeScrollPosition(this.submitPatch.bind(this, el.id)).bind(this));' ). + lo_buf->add( ' }.bind(this));' ). + lo_buf->add( '' ). + lo_buf->add( ' // for hotkeys' ). + lo_buf->add( ' window.stagePatch = function() {' ). + lo_buf->add( ' this.submitPatch(this.ACTION.PATCH_STAGE);' ). + lo_buf->add( ' }.bind(this);' ). + lo_buf->add( '' ). + lo_buf->add( ' window.refreshLocal = memorizeScrollPosition(function() {' ). + lo_buf->add( ' this.submitPatch(this.ACTION.REFRESH_LOCAL);' ). + lo_buf->add( ' }.bind(this));' ). + lo_buf->add( '' ). + lo_buf->add( ' window.refreshAll = memorizeScrollPosition(function() {' ). + lo_buf->add( ' this.submitPatch(this.ACTION.REFRESH_ALL);' ). + lo_buf->add( ' }.bind(this));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.submitPatch = function(action) {' ). + lo_buf->add( ' // Collect add and remove info and submit to backend' ). + lo_buf->add( ' var aAddPatch = this.collectElementsForCheckboxId(PatchLine.prototype.ID, true);' ). + lo_buf->add( ' var aRemovePatch = this.collectElementsForCheckboxId(PatchLine.prototype.ID, false);' ). + lo_buf->add( '' ). + lo_buf->add( ' submitSapeventForm({ add: aAddPatch, remove: aRemovePatch }, action, "post");' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'Patch.prototype.collectElementsForCheckboxId = function(sId, bChecked) {' ). + lo_buf->add( ' var sSelector = this.buildSelectorInputStartsWithId(sId);' ). + lo_buf->add( '' ). + lo_buf->add( ' return [].slice.call(document.querySelectorAll(sSelector))' ). + lo_buf->add( ' .filter(function(elem) {' ). + lo_buf->add( ' return (elem.checked === bChecked);' ). + lo_buf->add( ' }).map(function(elem) {' ). + lo_buf->add( ' return elem.id;' ). + lo_buf->add( ' });' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'function preparePatch() {' ). + lo_buf->add( ' var oPatch = new Patch();' ). + lo_buf->add( ' oPatch.preparePatch();' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function registerStagePatch() {' ). + lo_buf->add( ' var oPatch = new Patch();' ). + lo_buf->add( ' oPatch.registerStagePatch();' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Command Palette (F1)' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '// fuzzy match helper' ). + lo_buf->add( '// return non empty marked string in case it fits the filter' ). + lo_buf->add( '// abc + b = abc' ). + lo_buf->add( 'function fuzzyMatchAndMark(str, filter) {' ). + lo_buf->add( ' var markedStr = "";' ). + lo_buf->add( ' var filterLower = filter.toLowerCase();' ). + lo_buf->add( ' var strLower = str.toLowerCase();' ). + lo_buf->add( ' var cur = 0;' ). + lo_buf->add( '' ). + lo_buf->add( ' for (var i = 0; i < filter.length; i++) {' ). + lo_buf->add( ' while (filterLower[i] !== strLower[cur] && cur < str.length) {' ). + lo_buf->add( ' markedStr += str[cur++];' ). + lo_buf->add( ' }' ). + lo_buf->add( ' if (cur === str.length) break;' ). + lo_buf->add( ' markedStr += "" + str[cur++] + "";' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' var matched = i === filter.length;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (matched && cur < str.length) markedStr += str.substring(cur);' ). + lo_buf->add( ' return matched ? markedStr: null;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function CommandPalette(commandEnumerator, opts) {' ). + lo_buf->add( ' if (typeof commandEnumerator !== "function") throw Error("commandEnumerator must be a function");' ). + lo_buf->add( ' if (typeof opts !== "object") throw Error("opts must be an object");' ). + lo_buf->add( ' if (typeof opts.toggleKey !== "string" || !opts.toggleKey) throw Error("toggleKey must be a string");' ). + lo_buf->add( ' this.commands = commandEnumerator();' ). + lo_buf->add( ' if (!this.commands) return;' ). + lo_buf->add( ' // this.commands = [{' ). + lo_buf->add( ' // action: "sap_event_action_code_with_params"' ). + lo_buf->add( ' // iconClass: "icon icon_x ..."' ). + lo_buf->add( ' // title: "my command X"' ). + lo_buf->add( ' // }, ...];' ). + lo_buf->add( '' ). + lo_buf->add( ' if (opts.toggleKey[0] === "^") {' ). + lo_buf->add( ' this.toggleKeyCtrl = true;' ). + lo_buf->add( ' this.toggleKey = opts.toggleKey.substring(1);' ). + lo_buf->add( ' if (!this.toggleKey) throw Error("Incorrect toggleKey");' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' this.toggleKeyCtrl = false;' ). + lo_buf->add( ' this.toggleKey = opts.toggleKey;' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' this.hotkeyDescription = opts.hotkeyDescription;' ). + lo_buf->add( ' this.elements = {' ). + lo_buf->add( ' palette: null,' ). + lo_buf->add( ' ul : null,' ). + lo_buf->add( ' input : null' ). + lo_buf->add( ' };' ). + lo_buf->add( ' this.selectIndex = -1; // not selected' ). + lo_buf->add( ' this.filter = "";' ). + lo_buf->add( ' this.renderAndBindElements();' ). + lo_buf->add( ' this.hookEvents();' ). + lo_buf->add( ' Hotkeys.addHotkeyToHelpSheet(opts.toggleKey, opts.hotkeyDescription);' ). + lo_buf->add( '' ). + lo_buf->add( ' if (!CommandPalette.instances) {' ). + lo_buf->add( ' CommandPalette.instances = [];' ). + lo_buf->add( ' }' ). + lo_buf->add( ' CommandPalette.instances.push(this);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.hookEvents = function() {' ). + lo_buf->add( ' document.addEventListener("keydown", this.handleToggleKey.bind(this));' ). + lo_buf->add( ' this.elements.input.addEventListener("keyup", this.handleInputKey.bind(this));' ). + lo_buf->add( ' this.elements.ul.addEventListener("click", this.handleUlClick.bind(this));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.renderCommandItem = function(cmd) {' ). + lo_buf->add( ' var li = document.createElement("li");' ). + lo_buf->add( ' if (cmd.iconClass) {' ). + lo_buf->add( ' var icon = document.createElement("i");' ). + lo_buf->add( '' ). + lo_buf->add( ' icon.className = cmd.iconClass;' ). + lo_buf->add( ' li.appendChild(icon);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' var titleSpan = document.createElement("span");' ). + lo_buf->add( ' li.appendChild(titleSpan);' ). + lo_buf->add( ' cmd.element = li;' ). + lo_buf->add( ' cmd.titleSpan = titleSpan;' ). + lo_buf->add( ' return li;' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.renderAndBindElements = function() {' ). + lo_buf->add( ' var div = document.createElement("div");' ). + lo_buf->add( ' var input = document.createElement("input");' ). + lo_buf->add( ' var ul = document.createElement("ul");' ). + lo_buf->add( '' ). + lo_buf->add( ' div.className = "cmd-palette";' ). + lo_buf->add( ' div.style.display = "none";' ). + lo_buf->add( ' input.placeholder = this.hotkeyDescription;' ). + lo_buf->add( ' for (var i = 0; i < this.commands.length; i++) ul.appendChild(this.renderCommandItem(this.commands[i]));' ). + lo_buf->add( ' div.appendChild(input);' ). + lo_buf->add( ' div.appendChild(ul);' ). + lo_buf->add( '' ). + lo_buf->add( ' this.elements.palette = div;' ). + lo_buf->add( ' this.elements.input = input;' ). + lo_buf->add( ' this.elements.ul = ul;' ). + lo_buf->add( ' document.body.appendChild(div);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.handleToggleKey = function(event) {' ). + lo_buf->add( ' if (event.key !== this.toggleKey) return;' ). + lo_buf->add( ' if (this.toggleKeyCtrl && !event.ctrlKey) return;' ). + lo_buf->add( ' this.toggleDisplay();' ). + lo_buf->add( ' event.preventDefault();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.handleInputKey = function(event) {' ). + lo_buf->add( ' if (event.key === "ArrowUp" || event.key === "Up") {' ). + lo_buf->add( ' this.selectPrev();' ). + lo_buf->add( ' } else if (event.key === "ArrowDown" || event.key === "Down") {' ). + lo_buf->add( ' this.selectNext();' ). + lo_buf->add( ' } else if (event.key === "Enter") {' ). + lo_buf->add( ' this.exec(this.getSelected());' ). + lo_buf->add( ' } else if (event.key === "Backspace" && !this.filter) {' ). + lo_buf->add( ' this.toggleDisplay(false);' ). + lo_buf->add( ' } else if (this.filter !== this.elements.input.value) {' ). + lo_buf->add( ' this.filter = this.elements.input.value;' ). + lo_buf->add( ' this.applyFilter();' ). + lo_buf->add( ' this.selectFirst();' ). + lo_buf->add( ' }' ). + lo_buf->add( ' event.preventDefault();' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.applyFilter = function() {' ). + lo_buf->add( ' for (var i = 0; i < this.commands.length; i++) {' ). + lo_buf->add( ' var cmd = this.commands[i];' ). + lo_buf->add( ' if (!this.filter) {' ). + lo_buf->add( ' cmd.element.style.display = "";' ). + lo_buf->add( ' cmd.titleSpan.innerText = cmd.title;' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' var matchedTitle = fuzzyMatchAndMark(cmd.title, this.filter);' ). + lo_buf->add( ' if (matchedTitle) {' ). + lo_buf->add( ' cmd.titleSpan.innerHTML = matchedTitle;' ). + lo_buf->add( ' cmd.element.style.display = "";' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' cmd.element.style.display = "none";' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.applySelectIndex = function(newIndex) {' ). + lo_buf->add( ' if (newIndex !== this.selectIndex) {' ). + lo_buf->add( ' if (this.selectIndex >= 0) this.commands[this.selectIndex].element.classList.remove("selected");' ). + lo_buf->add( ' var newCmd = this.commands[newIndex];' ). + lo_buf->add( ' newCmd.element.classList.add("selected");' ). + lo_buf->add( ' this.selectIndex = newIndex;' ). + lo_buf->add( ' this.adjustScrollPosition(newCmd.element);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.selectFirst = function() {' ). + lo_buf->add( ' for (var i = 0; i < this.commands.length; i++) {' ). + lo_buf->add( ' if (this.commands[i].element.style.display === "none") continue; // skip hidden' ). + lo_buf->add( ' this.applySelectIndex(i);' ). + lo_buf->add( ' break;' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.selectNext = function() {' ). + lo_buf->add( ' for (var i = this.selectIndex + 1; i < this.commands.length; i++) {' ). + lo_buf->add( ' if (this.commands[i].element.style.display === "none") continue; // skip hidden' ). + lo_buf->add( ' this.applySelectIndex(i);' ). + lo_buf->add( ' break;' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.selectPrev = function() {' ). + lo_buf->add( ' for (var i = this.selectIndex - 1; i >= 0; i--) {' ). + lo_buf->add( ' if (this.commands[i].element.style.display === "none") continue; // skip hidden' ). + lo_buf->add( ' this.applySelectIndex(i);' ). + lo_buf->add( ' break;' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.getSelected = function() {' ). + lo_buf->add( ' return this.commands[this.selectIndex];' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.adjustScrollPosition = function(itemElement) {' ). + lo_buf->add( ' var bItem = itemElement.getBoundingClientRect();' ). + lo_buf->add( ' var bContainer = this.elements.ul.getBoundingClientRect();' ). + lo_buf->add( '' ). + lo_buf->add( ' bItem.top = Math.round(bItem.top);' ). + lo_buf->add( ' bItem.bottom = Math.round(bItem.bottom);' ). + lo_buf->add( ' bItem.height = Math.round(bItem.height);' ). + lo_buf->add( ' bItem.mid = Math.round(bItem.top + bItem.height / 2);' ). + lo_buf->add( ' bContainer.top = Math.round(bContainer.top);' ). + lo_buf->add( ' bContainer.bottom = Math.round(bContainer.bottom);' ). + lo_buf->add( '' ). + lo_buf->add( ' if (bItem.mid > bContainer.bottom - 2) {' ). + lo_buf->add( ' this.elements.ul.scrollTop += bItem.bottom - bContainer.bottom;' ). + lo_buf->add( ' } else if (bItem.mid < bContainer.top + 2) {' ). + lo_buf->add( ' this.elements.ul.scrollTop += bItem.top - bContainer.top;' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.toggleDisplay = function(forceState) {' ). + lo_buf->add( ' var isDisplayed = (this.elements.palette.style.display !== "none");' ). + lo_buf->add( ' var tobeDisplayed = (forceState !== undefined) ? forceState : !isDisplayed;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (tobeDisplayed) {' ). + lo_buf->add( ' // auto close other command palettes' ). + lo_buf->add( ' CommandPalette.instances.forEach(function(instance) {' ). + lo_buf->add( ' instance.elements.palette.style.display = "none";' ). + lo_buf->add( ' });' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' this.elements.palette.style.display = tobeDisplayed ? "" : "none";' ). + lo_buf->add( ' if (tobeDisplayed) {' ). + lo_buf->add( ' this.elements.input.value = "";' ). + lo_buf->add( ' this.elements.input.focus();' ). + lo_buf->add( ' this.applyFilter();' ). + lo_buf->add( ' this.selectFirst();' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.getCommandByElement = function(element) {' ). + lo_buf->add( ' for (var i = 0; i < this.commands.length; i++) {' ). + lo_buf->add( ' if (this.commands[i].element === element) return this.commands[i];' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.handleUlClick = function(event) {' ). + lo_buf->add( ' var element = event.target || event.srcElement;' ). + lo_buf->add( ' if (!element) return;' ). + lo_buf->add( ' if (element.nodeName === "SPAN") element = element.parentNode;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (element.nodeName === "I") element = element.parentNode;' ). + lo_buf->add( '' ). + lo_buf->add( ' if (element.nodeName !== "LI") return;' ). + lo_buf->add( ' this.exec(this.getCommandByElement(element));' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( 'CommandPalette.prototype.exec = function(cmd) {' ). + lo_buf->add( ' if (!cmd) return;' ). + lo_buf->add( ' this.toggleDisplay(false);' ). + lo_buf->add( ' if (typeof cmd.action === "function") {' ). + lo_buf->add( ' cmd.action();' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' submitSapeventForm(null, cmd.action);' ). + lo_buf->add( ' }' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '// Is any command palette visible?' ). + lo_buf->add( 'CommandPalette.isVisible = function() {' ). + lo_buf->add( ' return CommandPalette.instances.reduce(function(result, instance) { return result || instance.elements.palette.style.display !== "none" }, false);' ). + lo_buf->add( '};' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Command Enumerators' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( 'function createRepoCatalogEnumerator(catalog, action) {' ). + lo_buf->add( ' // expecting [{ key, isOffline, displayName }]' ). + lo_buf->add( ' return function() {' ). + lo_buf->add( ' return catalog.map(function(i) {' ). + lo_buf->add( ' return {' ). + lo_buf->add( ' action : action + "?key=" + i.key,' ). + lo_buf->add( ' iconClass: i.isOffline ? "icon icon-plug darkgrey" : "icon icon-cloud-upload-alt blue",' ). + lo_buf->add( ' title : i.displayName' ). + lo_buf->add( ' };' ). + lo_buf->add( ' });' ). + lo_buf->add( ' };' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function enumerateUiActions() {' ). + lo_buf->add( ' var items = [];' ). + lo_buf->add( ' function processUL(ulNode, prefix) {' ). + lo_buf->add( ' for (var i = 0; i < ulNode.children.length; i++) {' ). + lo_buf->add( ' var item = ulNode.children[i];' ). + lo_buf->add( ' if (item.nodeName !== "LI") continue; // unexpected node' ). + lo_buf->add( ' if (item.children.length >= 2 && item.children[1].nodeName === "UL") {' ). + lo_buf->add( ' // submenu detected' ). + lo_buf->add( ' var menutext = item.children[0].innerText;' ). + lo_buf->add( ' // special treatment for menus without text' ). + lo_buf->add( ' if (!menutext) {' ). + lo_buf->add( ' menutext = item.children[0].getAttribute("title");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' processUL(item.children[1], menutext);' ). + lo_buf->add( ' } else if (item.firstElementChild && item.firstElementChild.nodeName === "A") {' ). + lo_buf->add( ' var anchor = item.firstElementChild;' ). + lo_buf->add( ' if (anchor.href && anchor.href !== "#") items.push([anchor, prefix]);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' // toolbars and actionbars' ). + lo_buf->add( ' [].slice.call(document.querySelectorAll(".nav-container > ul[id*=toolbar], .nav-container > ul[id*=actionbar]"))' ). + lo_buf->add( ' .filter(function(toolbar) {' ). + lo_buf->add( ' return (toolbar && toolbar.nodeName === "UL");' ). + lo_buf->add( ' }).forEach(function(toolbar) {' ). + lo_buf->add( ' processUL(toolbar);' ). + lo_buf->add( ' });' ). + lo_buf->add( '' ). + lo_buf->add( ' items = items.map(function(item) {' ). + lo_buf->add( ' var action = "";' ). + lo_buf->add( ' var anchor = item[0];' ). + lo_buf->add( ' if (anchor.href.includes("#")) {' ). + lo_buf->add( ' action = function() {' ). + lo_buf->add( ' anchor.click();' ). + lo_buf->add( ' };' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' action = anchor.href.replace("sapevent:", "");' ). + lo_buf->add( ' }' ). + lo_buf->add( ' var prefix = item[1];' ). + lo_buf->add( ' return {' ). + lo_buf->add( ' action: action,' ). + lo_buf->add( ' title : (prefix ? prefix + ": " : "") + anchor.innerText.trim()' ). + lo_buf->add( ' };' ). + lo_buf->add( ' });' ). + lo_buf->add( '' ). + lo_buf->add( ' // forms' ). + lo_buf->add( ' [].slice.call(document.querySelectorAll("input[type=''submit'']"))' ). + lo_buf->add( ' .forEach(function(input) {' ). + lo_buf->add( ' items.push({' ). + lo_buf->add( ' action: function() {' ). + lo_buf->add( ' if (input.form.action.includes(input.formAction) || input.classList.contains("main")) {' ). + lo_buf->add( ' input.form.submit();' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' submitSapeventForm({}, input.formAction, "post", input.form);' ). + lo_buf->add( ' }' ). + lo_buf->add( ' },' ). + lo_buf->add( ' title: (input.value === "Submit Query" ? input.title : input.value + " " + input.title.replace(/\[.*\]/, ""))' ). + lo_buf->add( ' });' ). + lo_buf->add( ' });' ). + lo_buf->add( '' ). + lo_buf->add( ' // radio buttons' ). + lo_buf->add( ' [].slice.call(document.querySelectorAll("input[type=''radio'']"))' ). + lo_buf->add( ' .forEach(function(input) {' ). + lo_buf->add( ' items.push({' ). + lo_buf->add( ' action: function() {' ). + lo_buf->add( ' input.click();' ). + lo_buf->add( ' },' ). + lo_buf->add( ' title: document.querySelector("label[for=''" + input.id + "'']").textContent' ). + lo_buf->add( ' });' ). + lo_buf->add( ' });' ). + lo_buf->add( '' ). + lo_buf->add( ' // others:' ). + lo_buf->add( ' // - links inside forms' ). + lo_buf->add( ' // - label links' ). + lo_buf->add( ' // - command links' ). + lo_buf->add( ' // - other header links' ). + lo_buf->add( ' [].slice.call(document.querySelectorAll("form a, a.command:not(.unlisted), #header ul:not([id*=''toolbar'']) a"))' ). + lo_buf->add( ' .filter(function(anchor) {' ). + lo_buf->add( ' return !!anchor.title || !!anchor.text;' ). + lo_buf->add( ' }).forEach(function(anchor) {' ). + lo_buf->add( ' items.push({' ). + lo_buf->add( ' action: function() {' ). + lo_buf->add( ' anchor.click();' ). + lo_buf->add( ' },' ). + lo_buf->add( ' title: (function() {' ). + lo_buf->add( ' var result = anchor.title + anchor.text;' ). + lo_buf->add( ' if (anchor.href.includes("label")) {' ). + lo_buf->add( ' result = "Label: " + result;' ). + lo_buf->add( ' }' ). + lo_buf->add( ' return result.trim();' ). + lo_buf->add( ' })()' ). + lo_buf->add( ' });' ). + lo_buf->add( ' });' ). + lo_buf->add( '' ). + lo_buf->add( ' return items;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function enumerateJumpAllFiles() {' ). + lo_buf->add( ' var root = document.getElementById("jump");' ). + lo_buf->add( ' if (!root || root.nodeName !== "UL") return null;' ). + lo_buf->add( '' ). + lo_buf->add( ' return Array' ). + lo_buf->add( ' .prototype.slice.call(root.children)' ). + lo_buf->add( ' .filter(function(elem) { return elem.nodeName === "LI" })' ). + lo_buf->add( ' .map(function(listItem) {' ). + lo_buf->add( ' var title = listItem.children[0].childNodes[0].textContent;' ). + lo_buf->add( ' return {' ). + lo_buf->add( ' action: root.onclick.bind(null, title),' ). + lo_buf->add( ' title : title' ). + lo_buf->add( ' };' ). + lo_buf->add( ' });' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Save Scroll Position' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( 'function saveScrollPosition() {' ). + lo_buf->add( ' // Not supported by Java GUI' ). + lo_buf->add( ' try { if (!window.sessionStorage) { return } }' ). + lo_buf->add( ' catch (err) { return err }' ). + lo_buf->add( '' ). + lo_buf->add( ' window.sessionStorage.setItem("scrollTop", document.querySelector("html").scrollTop);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function restoreScrollPosition() {' ). + lo_buf->add( ' // Not supported by Java GUI' ). + lo_buf->add( ' try { if (!window.sessionStorage) { return } }' ). + lo_buf->add( ' catch (err) { return err }' ). + lo_buf->add( '' ). + lo_buf->add( ' var scrollTop = window.sessionStorage.getItem("scrollTop");' ). + lo_buf->add( ' if (scrollTop) {' ). + lo_buf->add( ' document.querySelector("html").scrollTop = scrollTop;' ). + lo_buf->add( ' }' ). + lo_buf->add( ' window.sessionStorage.setItem("scrollTop", 0);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( 'function memorizeScrollPosition(fn) {' ). + lo_buf->add( ' return function() {' ). + lo_buf->add( ' saveScrollPosition();' ). + lo_buf->add( ' return fn.call(this, fn.args);' ). + lo_buf->add( ' }.bind(this);' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Sticky Header' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '/* https://www.w3schools.com/howto/howto_js_navbar_sticky.asp */' ). + lo_buf->add( '/* Note: We have to use JS since IE does not support CSS position:sticky */' ). + lo_buf->add( '' ). + lo_buf->add( '// When the user scrolls the page, execute toggleSticky' ). + lo_buf->add( 'window.onscroll = function() { toggleSticky() };' ). + lo_buf->add( '' ). + lo_buf->add( '// Add the sticky class to the navbar when you reach its scroll position.' ). + lo_buf->add( '// Remove "sticky" when you leave the scroll position' ). + lo_buf->add( 'function toggleSticky() {' ). + lo_buf->add( ' var body = document.getElementsByTagName("body")[0];' ). + lo_buf->add( ' var header = document.getElementById("header");' ). + lo_buf->add( ' var sticky = header.offsetTop;' ). + lo_buf->add( '' ). + lo_buf->add( ' var stickyClass = "sticky";' ). + lo_buf->add( ' if (body.classList.contains("full_width")) {' ). + lo_buf->add( ' stickyClass = "sticky_full_width";' ). + lo_buf->add( ' }' ). + lo_buf->add( '' ). + lo_buf->add( ' if (window.pageYOffset >= sticky) {' ). + lo_buf->add( ' header.classList.add(stickyClass);' ). + lo_buf->add( ' } else {' ). + lo_buf->add( ' header.classList.remove(stickyClass);' ). + lo_buf->add( ' }' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '/**********************************************************' ). + lo_buf->add( ' * Browser Control' ). + lo_buf->add( ' **********************************************************/' ). + lo_buf->add( '' ). + lo_buf->add( '// Toggle display of warning message when using Edge (based on Chromium) browser control' ). + lo_buf->add( '// Todo: Remove once https://github.com/abapGit/abapGit/issues/4841 is fixed' ). + lo_buf->add( 'function toggleBrowserControlWarning(){' ). + lo_buf->add( ' if (!navigator.userAgent.includes("Edg")){' ). + lo_buf->add( ' var elBrowserControlWarning = document.getElementById("browser-control-warning");' ). + lo_buf->add( ' if (elBrowserControlWarning) {' ). + lo_buf->add( ' elBrowserControlWarning.style.display = "none";' ). + lo_buf->add( ' }' ). + lo_buf->add( ' }' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '// Output type of HTML control in the abapGit footer' ). + lo_buf->add( 'function displayBrowserControlFooter() {' ). + lo_buf->add( ' var out = document.getElementById("browser-control-footer");' ). + lo_buf->add( ' out.innerHTML = " - " + ( navigator.userAgent.includes("Edg") ? "Edge" : "IE" );' ). + lo_buf->add( '}' ). + li_asset_man->register_asset( + iv_url = 'js/common.js' + iv_type = 'text/javascript' + iv_mime_name = 'ZABAPGIT_JS_COMMON' + iv_inline = lo_buf->join_w_newline_and_flush( ) ). + +**************************************************** +* abapmerge Pragma [include] - ZABAPGIT_ICON_FONT_CSS.W3MI.DATA.CSS +**************************************************** + lo_buf->add( '@font-face {' ). + lo_buf->add( ' font-family: "ag-icons";' ). + lo_buf->add( ' font-weight: normal;' ). + lo_buf->add( ' font-style: normal;' ). + lo_buf->add( ' src: url("../font/ag-icons.woff") format("woff");' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.icon {' ). + lo_buf->add( ' line-height: 1;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.icon:before {' ). + lo_buf->add( ' font-family: ag-icons !important;' ). + lo_buf->add( ' font-style: normal;' ). + lo_buf->add( ' font-weight: normal !important;' ). + lo_buf->add( '' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' text-decoration: none;' ). + lo_buf->add( ' text-align: center;' ). + lo_buf->add( ' vertical-align: text-top;' ). + lo_buf->add( ' /* width: 1.1em; */' ). + lo_buf->add( ' /* padding-right: 0.2em */' ). + lo_buf->add( '' ). + lo_buf->add( ' /* For safety - reset parent styles, that can break glyph codes*/' ). + lo_buf->add( ' font-variant: normal;' ). + lo_buf->add( ' text-transform: none;' ). + lo_buf->add( '}' ). + lo_buf->add( '' ). + lo_buf->add( '.icon.large { font-size: 200%; }' ). + lo_buf->add( '' ). + lo_buf->add( '.icon-abapgit:before { content: "\f101"; }' ). + lo_buf->add( '.icon-abaplint:before { content: "\f102"; }' ). + lo_buf->add( '.icon-arrow-circle-up:before { content: "\f103"; }' ). + lo_buf->add( '.icon-bars:before { content: "\f104"; }' ). + lo_buf->add( '.icon-bolt:before { content: "\f105"; }' ). + lo_buf->add( '.icon-bookmark-solid:before { content: "\f106"; }' ). + lo_buf->add( '.icon-box:before { content: "\f107"; }' ). + lo_buf->add( '.icon-briefcase:before { content: "\f108"; }' ). + lo_buf->add( '.icon-bug-solid:before { content: "\f109"; }' ). + lo_buf->add( '.icon-check:before { content: "\f10a"; }' ). + lo_buf->add( '.icon-chevron-down:before { content: "\f10b"; }' ). + lo_buf->add( '.icon-chevron-left:before { content: "\f10c"; }' ). + lo_buf->add( '.icon-chevron-right:before { content: "\f10d"; }' ). + lo_buf->add( '.icon-chevron-up:before { content: "\f10e"; }' ). + lo_buf->add( '.icon-circle-dot-regular:before { content: "\f10f"; }' ). + lo_buf->add( '.icon-circle-play-regular:before { content: "\f110"; }' ). + lo_buf->add( '.icon-circle-solid:before { content: "\f111"; }' ). + lo_buf->add( '.icon-cloud-commit:before { content: "\f112"; }' ). + lo_buf->add( '.icon-cloud-solid:before { content: "\f113"; }' ). + lo_buf->add( '.icon-cloud-upload-alt:before { content: "\f114"; }' ). + lo_buf->add( '.icon-code-branch:before { content: "\f115"; }' ). + lo_buf->add( '.icon-code-commit:before { content: "\f116"; }' ). + lo_buf->add( '.icon-code-fork-solid:before { content: "\f117"; }' ). + lo_buf->add( '.icon-code-pull-request-solid:before { content: "\f118"; }' ). + lo_buf->add( '.icon-code-solid:before { content: "\f119"; }' ). + lo_buf->add( '.icon-cog:before { content: "\f11a"; }' ). + lo_buf->add( '.icon-copy-solid:before { content: "\f11b"; }' ). + lo_buf->add( '.icon-download-solid:before { content: "\f11c"; }' ). + lo_buf->add( '.icon-edit-solid:before { content: "\f11d"; }' ). + lo_buf->add( '.icon-exclamation-circle:before { content: "\f11e"; }' ). + lo_buf->add( '.icon-exclamation-triangle:before { content: "\f11f"; }' ). + lo_buf->add( '.icon-eye-solid:before { content: "\f120"; }' ). + lo_buf->add( '.icon-file-alt:before { content: "\f121"; }' ). + lo_buf->add( '.icon-file-code:before { content: "\f122"; }' ). + lo_buf->add( '.icon-file-image:before { content: "\f123"; }' ). + lo_buf->add( '.icon-file-zipper-regular:before { content: "\f124"; }' ). + lo_buf->add( '.icon-file:before { content: "\f125"; }' ). + lo_buf->add( '.icon-fire-alt:before { content: "\f126"; }' ). + lo_buf->add( '.icon-flow:before { content: "\f127"; }' ). + lo_buf->add( '.icon-folder:before { content: "\f128"; }' ). + lo_buf->add( '.icon-git-alt:before { content: "\f129"; }' ). + lo_buf->add( '.icon-github:before { content: "\f12a"; }' ). + lo_buf->add( '.icon-heart-regular:before { content: "\f12b"; }' ). + lo_buf->add( '.icon-info-circle-solid:before { content: "\f12c"; }' ). + lo_buf->add( '.icon-language-solid:before { content: "\f12d"; }' ). + lo_buf->add( '.icon-link-solid:before { content: "\f12e"; }' ). + lo_buf->add( '.icon-lock:before { content: "\f12f"; }' ). + lo_buf->add( '.icon-magnifying-glass-solid:before { content: "\f130"; }' ). + lo_buf->add( '.icon-markdown:before { content: "\f131"; }' ). + lo_buf->add( '.icon-paste-solid:before { content: "\f132"; }' ). + lo_buf->add( '.icon-plug:before { content: "\f133"; }' ). + lo_buf->add( '.icon-question-circle-solid:before { content: "\f134"; }' ). + lo_buf->add( '.icon-redo-alt-solid:before { content: "\f135"; }' ). + lo_buf->add( '.icon-server-solid:before { content: "\f136"; }' ). + lo_buf->add( '.icon-sliders-h:before { content: "\f137"; }' ). + lo_buf->add( '.icon-snowflake:before { content: "\f138"; }' ). + lo_buf->add( '.icon-star:before { content: "\f139"; }' ). + lo_buf->add( '.icon-tag-solid:before { content: "\f13a"; }' ). + lo_buf->add( '.icon-times-solid:before { content: "\f13b"; }' ). + lo_buf->add( '.icon-tools-solid:before { content: "\f13c"; }' ). + lo_buf->add( '.icon-truck-solid:before { content: "\f13d"; }' ). + lo_buf->add( '.icon-upload-solid:before { content: "\f13e"; }' ). + lo_buf->add( '.icon-user-cog-solid:before { content: "\f13f"; }' ). + lo_buf->add( '.icon-user-solid:before { content: "\f140"; }' ). + lo_buf->add( '.icon-vial-solid:before { content: "\f141"; }' ). + li_asset_man->register_asset( + iv_url = 'css/ag-icons.css' + iv_type = 'text/css' + iv_mime_name = 'ZABAPGIT_ICON_FONT_CSS' + iv_inline = lo_buf->join_w_newline_and_flush( ) ). + +**************************************************** +* abapmerge Pragma [include-base64] - ZABAPGIT_ICON_FONT.W3MI.DATA.WOFF +**************************************************** + lo_buf->add( 'd09GRgABAAAAACEsAAsAAAAAOygAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABH' ). + lo_buf->add( 'U1VCAAABCAAAADsAAABUIIslek9TLzIAAAFEAAAAPwAAAFZAtU4xY21hcAAA' ). + lo_buf->add( 'AYQAAAFYAAAE8PbieW1nbHlmAAAC3AAAGbEAACz898pmW2hlYWQAAByQAAAA' ). + lo_buf->add( 'MAAAADYu14YpaGhlYQAAHMAAAAAeAAAAJAmVB9NobXR4AAAc4AAAAGcAAAEI' ). + lo_buf->add( 'ggn/6GxvY2EAAB1IAAAAhgAAAIZvkWSUbWF4cAAAHdAAAAAfAAAAIAFnARxu' ). + lo_buf->add( 'YW1lAAAd8AAAASgAAAIWQeF35nBvc3QAAB8YAAACEgAAA67zKOCfeJxjYGRg' ). + lo_buf->add( 'YOBiMGCwY2BycfMJYeDLSSzJY5BiYGGAAJA8MpsxJzM9kYEDxgPKsYBpDiBm' ). + lo_buf->add( 'g4gCACY7BUgAeJxjYGT8wTiBgZWBgXEaYxoDA4M7lP7KIMnQwsDAxMDKzIAV' ). + lo_buf->add( 'BKS5pjA4fGT86MgE4uoxsTKAVDKCOADYRgluAHic7dNnbtwwAAXhWa+8buve' ). + lo_buf->add( '7XXvvfeqq+ZA+ZWL6AQORy/HiICPAxJqACVgGOgW50UFnT908PhdVjvtepfx' ). + lo_buf->add( 'dr3iV3tO5XpT//yUseNY5lU7DpVzq3LHHiOMMlaum6DPJFNMM8Msc8yzwCJL' ). + lo_buf->add( 'LLPCKmusM2CDTbbYZodd9tjngEOOOOaEU87K8y+45IprbrjljnseeOSJZ154' ). + lo_buf->add( '5Y13Pvjki2/q8go9/h99h+7g36x2l6Ldt6HAdsP9b6pwJ5vh8NtoeoEdCexo' ). + lo_buf->add( 'YMcCOx5+M81EYPvh2zWTgZ0K7HRgZwI7G9i5wM4HdiGwi4FdCuxyYFcCuxrY' ). + lo_buf->add( 'tcCuB3YQ2I3AbgZ2K7Dbgd0J7G5g9wK7H9iDwB4G9iiwx4E9CexpYM8Cex7+' ). + lo_buf->add( '581FYC8DexXY68DeBPY2sHeBvQ/sQ2AfA/sU2OfAvgT2NbBvgX0P7EdgPwP7' ). + lo_buf->add( 'FdjvwNZB/RfMwaYceJytWnmQHFd576+P97p7unuO7p6e+9ztnp2Vdlc7p7TS' ). + lo_buf->add( 'aq1dSStZNusjkbAdLMoGC8sFi8EEsA1rbIwTTEqxC8qBgqiKw7gqpFQVF7gq' ). + lo_buf->add( 'JAjbJKRyqZwDjKGy4Q+oFIktF05hJ2E233vdM7u6gBy7M6/f6/fe967v+H3f' ). + lo_buf->add( 'G8HYGAgC/ZQoCBVhQlgSrhPuFu4VPis8Jfyd8APhPMQFYbwTTMEe6PrUJ9Rr' ). + lo_buf->add( 'd1sloC61wCVpbx56ZQgsqPnt7l7w9kIJvNluZwpojdB6p069EhTBAtqbB+zn' ). + lo_buf->add( 'OqRe8wMlpNj+hRSnACnylr1OCVrzYkR1GjhVN4m0qGsj3W46JDuO47VwCKSE' ). + lo_buf->add( 'xQ7SnU1jyzLrWbfENM6sx9722n6NOGks2eFEomk6JA7uOO+8B1od/qjj3F2k' ). + lo_buf->add( 'g7XpFs4NtAyRoD3nH5AO2bZnwNyOGSjOlJqWpFhaJp+w0/UfSJLh52Z2Q28y' ). + lo_buf->add( '4yfEk6QoSyBLv6bnrFw6m7WyGqxnidje5R8UD9kpz4TdMzNiabocEsnmEmB7' ). + lo_buf->add( 'dWh0caTEuDM5lYLuNm/KluSbSUGSZMW9Sy0mnIyH9FSx8zm6U5Y1L9bv9meN' ). + lo_buf->add( 'nC7JoO7MLBTfelw8eqJ6sCTLn8psz+AHqjkinVQKsigpOTiupXU3fs2yJO6Q' ). + lo_buf->add( 'KrUxCYIpb1vynQ0ZZHJ/dwKg1CK4vHQKJ+/7uR0i2HEo7KeGWbZAelcWrBTs' ). + lo_buf->add( 'Xzk4D3HzVFMHIv+X7aeeIwZMlhvbDPXwr0joBxOs3WHTgpmlClJLJsQcklOU' ). + lo_buf->add( 'wX8qijwBM0hx7NrtBt03Mb2oyADiwav2HJBF7DQlvzVhwcmn7hJj1rtk6Qdp' ). + lo_buf->add( 'z8N1eoPP4NAS+Q6f1BPYRW7MSYrj3dsWpUPNQJqSxI9ta4ChCnkB/2AD/kyQ' ). + lo_buf->add( 'BCrEhLhgCx6+LQt1IRAmhWmhJfSEOWGvsCgcFK4W3iTcIBwVbhZuFU4I7xY+' ). + lo_buf->add( 'iH095Ebq9eyWWw+ib+8KeSUqe9GTfemWfHC5p0OYYCEXDzPBMAOTaddd9NLu' ). + lo_buf->add( 'G8Viq9lsVqtH0um5mZm6511VKk0Ui365PPjTmZlitVquVs163c3n1zwvXS7v' ). + lo_buf->add( 'HhvzC4WnX3zx9z/+8ZdXV1/4xjfuzVQ9r5p5Ar+YuzYswX1Vo6bWYtXByxkv' ). + lo_buf->add( 'k83sybC/OcxlMrP4jOF3PjOD6R6s343vF7LZ7EqS9c3EE4yS93ZW8jy2zSLf' ). + lo_buf->add( '69fhdcEQmoJgt+dhtgQOl/O9qBfSczDb3QNeenYvdNvT4NfiQJwypGfVxbsf' ). + lo_buf->add( 'vnuRJ6eWLT2hW8uoLGKUfpQ6+MWcC8Ji1GLxbv/I13TL0r92hNU49CGKHwez' ). + lo_buf->add( 'OLzE53AWnseTLuPpCnaVjdn269UaYQLu/ZJyAk5TTaOD4yy9Qh7u02iDlTA5' ). + lo_buf->add( 'fdksshzqXFjCLcGtgXqv609CDXUPwU2gJN2a7dldHxrvaUqWcUqzoAJW7Den' ). + lo_buf->add( 'sGDRM6jbjn8kZhva+VjiWSNlwIyR4cviyQNI0xGELFNWuJEept1OMlyApavk' ). + lo_buf->add( '058mqm4VnMG6U4Bzg2Xdku+6S7Z0eMYpFML9EQURUBriQhbpoXacBLc1Xsfp' ). + lo_buf->add( 'iS2Kx9TiWwKDlpJNfOKVwaufSGSVWfGV8wUHTiPNg0/EU2fPpuJP0Mp5JOmc' ). + lo_buf->add( 'F4b7LgqwjvLF5EoYdwiumGnXEcV6r95p830oov7FpMqLnRYsaBT39WzRhtN2' ). + lo_buf->add( '8eyplaKNzxW7KArFz6+tnWGbOnPKLhbtU6dn2GOmaK9gdQWH3MA/EXBPFoRD' ). + lo_buf->add( '0aiuQz00F7VpIJsD1gLKxGovsCkx+ZqDTsDErAytHgqbg3YBbYBUQxPVak8h' ). + lo_buf->add( 'RcfsWXs0O6d3Gy2qZBTaanT1nK3tsXqmY5v9aV73I/5uum/aG6V2ab3U/icz' ). + lo_buf->add( 'lagUd7O3vcprCqXKa5Uea7q7WEmk8vbcFK/ir6bmbLCxG36G54t7+A12vr2A' ). + lo_buf->add( 'TZZNr8eStEOB1P7wSUrHqauunlddzNDBizR96Es0TcdU9k4dw+zge+qIV/4Y' ). + lo_buf->add( 'PrpJax4YrTSjhXxY+9tnKbZ26Gc+g0ma0mep8+CzPAvsHfDKZzdpjcNLjJbN' ). + lo_buf->add( 'p1OCOHIe42fcZb9dv0xHSF46wEW0xinrzpRD4HfDxaYdKF6G2CtXphWt0fbY' ). + lo_buf->add( 'sixAZU18NidG79VLu8H9l12ktLHB5UJA3ZUVakgXeQB5wSnB7DyMb1Vl47Pp' ). + lo_buf->add( 'UEPDuf6td9/a58lgZv89j96znycgNPr9lX4fhJ1Rbf/WnQeiyv33fInVrfQv' ). + lo_buf->add( 'HtP/RWP2utGxIfe2rzTu103jVCx2ysheYeA/ouoxmsOvZZ2xRuca6mthc2Cc' ). + lo_buf->add( 'xFZlC69vKudIx4sPwD+jjLfDXgz7udgVBWoKOsxwMXyGwjSPJT/oYlKv0Snw' ). + lo_buf->add( 'QkDW9kGYPDzZ7Ab7gkczlenFqXL26fpcbdc20m8UM+5hlei6iUp2HVup8cPT' ). + lo_buf->add( '2O59ajNfnZ6u5pvq+2pz9akDWjLV6CfGtv0ba2nqQ9l5APVPAQujMbdMD3UQ' ). + lo_buf->add( 'n5CYi8Y5Gk0CVtnoUIxIbo7KRxI218xoz/4S6hTV3VDx1fyIp8kVxvyTq1Cv' ). + lo_buf->add( 'Ue2qmErvlC35TqpeaRbtVaYDVx1sh82Q3WWm92AN9XiPa77rGfcg5EVl6yGc' ). + lo_buf->add( 'Jfy/w6cUvnTZPHH72ZEgxu32Wt0e+5/f5Gc7hB0OsUccvja9b7qSAzcTHytY' ). + lo_buf->add( 'XiJbxnI5yx8FT3HsWBYm3brtQqY0OIdTtHCW4ePF8AGr0bllEJjin0xP0eFZ' ). + lo_buf->add( '0m9H2eyEpuoI6GSie7mm2ryT9bS0wVr4RPPAnxHGQKn5B1x3Rqii1DPVbjEz' ). + lo_buf->add( 'zhe3B5Ucro+dw3AJd5p2pdms2Dm7igjKNjXTTJqmKMSt+2P9A339fiuRsO7X' ). + lo_buf->add( 'MRu730z8BM0tfnB/2TjwTRxHFeYRGa7gWIx3GQ/3GHsP0cxWlufGh3tA3DXp' ). + lo_buf->add( 'he5F1MIbdpeGrskKghjHsm7KpW3ztGmnc7iruXS/MRPlZhp9njsXtnsnS1Ad' ). + lo_buf->add( 'PBE+M5mGFpi2bQZaI8N2kZUb/YObpYP9RlS3M+wyeCakhPuocLvJcEAgzAjL' ). + lo_buf->add( '6BPehBzEPKTWLEu3roKZUBcHjtTqPNDhCrwLVru5FaMlKsNFwyxRE8jz0dL8' ). + lo_buf->add( 'XEI1LWVFVVcU67lwdmpUFz5K0WqXwynDQDJoA2Xhyc31PZnzG9QgorKManxZ' ). + lo_buf->add( 'Ea8Lm+79m80mm9nBelhrhXQjzLLxc3FNlFD/lXAXBEBXVSIl6DJw5jFoStkq' ). + lo_buf->add( 'hmhV2QSs7EWv24bfMj15TTJyPF3UtJtuYmZ9VdNW9dzgeX2YtVkFbEiGOVgw' ). + lo_buf->add( 'PXSL4KzpvRer3/xmVrkaNtSijB2+j/D0K7AR8t940A1QXAMfEVscOJcHPmUq' ). + lo_buf->add( 'iNDA5xKPxp14+MpjPvFe4FLhpbETuvY9L80l3qdDMYcfNwlpot+a9CVVbuZr' ). + lo_buf->add( 'itzryUot35RVyU+iPF5cr3R5/aQU1v8Et3bf9PTz2Xo9K6pyZ0ISxaxn7JAp' ). + lo_buf->add( 'GAZQeYfhZUVRmujIqnhxG4WwNkThbUBmbVKM2L7pCMN/E5efRC9tG66cxRSq' ). + lo_buf->add( 'yGVJBtuSiCdtFC3iJkNk2UminCHGYTC204YFSx+cZ/7BctX78pdZBtChOKFb' ). + lo_buf->add( 'H9hHdXJ8ocFfrerW4LteFY6dwOan+CvVmthHjxN9C55F+fCE7UI30q5F3P1a' ). + lo_buf->add( 'yAGMKZAfxNBraEVexCRwSKOMFChTPIfYGa/h0a6xoz20nkMXGdZY+rYpu5Pa' ). + lo_buf->add( 'DnrE4+tMnH96mLVa01gPWzt8jZ+rsKaYbLft7f2IfcP5XYV7ZApFYRfzUxEf' ). + lo_buf->add( 'iMTfK3ZncS9GnMrmKbnVJPMVutxJGG4bmy+2gsdvkqSXbtFN0F+S1C/uMCqx' ). + lo_buf->add( 'MUm6CY94LHZ2cPZHitQgRB38kEF9OO4U4gr63l9h9S/pYOq3vCQ5O2LYRcU+' ). + lo_buf->add( '2KUyePntsCBNKHF0QU6zTp9TCWlII9/sdXgD5c0VxjEfgpsQ6NAhPAi8ULd2' ). + lo_buf->add( 'eiF23wpAXrfzeT+f36tSZUahmC4odCtYuYfV+vkvPiJTKj9CKOVnufFz3KtF' ). + lo_buf->add( 'lHMLTzNAfkpbgDuBsMqeRyGRrjSyuEsludSgksoR9bxWrWrNywy/nGC+NLqN' ). + lo_buf->add( 'iVgsMfjqZSYQjY+YKYejzzPUFBpoFFP8n+V2uItyzeT5AtTHYl4o2q6D4jzP' ). + lo_buf->add( 'PLWghp2gcufRSi5tEGKkc5Wjf88KpqKYrPAfwb5r9wU8OeXndF2hkr7/moau' ). + lo_buf->add( '7SjLiijB+nUlv1I2jHLFL123Nb8eRN2CfXfkfElU5JjuN9yloBwAVbhMKCP/' ). + lo_buf->add( 'k/nWOxD/7cHyCO8w2ZxN03ooEaF1bPu95FbZZWgocFt2Mgy8JaFClS8zHwkT' ). + lo_buf->add( 'Y5ihd4Tea8H5K8e60Vo7IqPwnga1wOpZck34YMnXB09zxkROw6a7jwzOQMXS' ). + lo_buf->add( 'TwyO41QJny/DSC7ue1NoCYvCm9Eb2sHU6NbwA5MRrj+26pR24NVtlBtu6anP' ). + lo_buf->add( 'fXdszPwUP3B3MDU77Duk9alqFV3RlETFXZK0S6RSUnrxRgtXwWZYcQprR46s' ). + lo_buf->add( 'DNZP4/w+JBPooYLNRE/WEVtTaaeEH9bx88WiqIq2JHXx0RMlpDq4kbn1xzm1' ). + lo_buf->add( 'Iw5f62ncGR/7fx3p0Oh54NKew7Nje5FEb6nIdwN9/4vXTOsdKVpycrzV4XqE' ). + lo_buf->add( 'J70ReL9764raR86x5WwI656sS8cCWZeDGaxsFArwuQummzgyuJ1Pd7A+s5aR' ). + lo_buf->add( 'pGMNSWqcYQ0bhdFZMd7KomfRF/YLR4Xb8KyGjBMJZjQ1ZKkL540nUKdhm1B0' ). + lo_buf->add( '3a0FPJsI+zJvk73xWkxDT/KY9gIPL2i0QrUZ21zR6IbANTSm9k127n285qKE' ). + lo_buf->add( 'ZEQfXYmMmIpZsaQ9qkMysEY1Vlwx7cE61eCcnxtwZQ9+Dumthrj4YPh40zFV' ). + lo_buf->add( 'zY+P51X1WMw0b9vEudJF5/VLzuqyp3LlExjG6piNTXFvl1A/CD2ZyG3zJcID' ). + lo_buf->add( '7KiavB5qKQJLpXxz56Fbd9/xwTt2V/Olbm2yf3Uq3rhtFyFOCv66UNnVWTrd' ). + lo_buf->add( 'nb9zHj/5G5tTg7/M7O/ny9mZ+xdjWuMY91l4fOM8ao+9HHMKdhh5CYPvhGsR' ). + lo_buf->add( 'XGYUvfHbvWGwguHOULGQoarhwRsvRDI1f3wIat5gVjP3eKOPhtc2H88xY7qi' ). + lo_buf->add( 'aW/B70pYhUY2Z/cbvOrB8e44fgZn8+wxDj9mzbP9RoVZYkyyrAv208+wZIXX' ). + lo_buf->add( '8gpMGn1Wuxr2fCkkFPmKuLOCzWLPUL/w2Nj6JFQqHh4anDvb08zHh+qLndSj' ). + lo_buf->add( '+OLPYa2nDRUgJoPzUOlpYRh7g50Z+qHbOD+gWHpdNJwsIWgtAkTjBO0Fh+K9' ). + lo_buf->add( 'gG4qN3jmeTWjNVpmJqbMJvJKtpqk0ynRLegmTcY1ZfZjqvq85mnPqeA8r6oT' ). + lo_buf->add( 'bSWWMWdJqpJVCsmpD2p1VzfH6L0kb7QexmbY5DnNE1Q+qVfRnhNEIY6wKtwj' ). + lo_buf->add( 'fFB4SPgdlFuHtPFQA8LsFkJpdJC7vl3jPiji0D0Ik5i1wzPmSbcVmkLEqt0e' ). + lo_buf->add( 't4PMofA7fq/rodLFc2YW0kuj0cQ2rsPNJ7+v6TFuRcMokTSqZZYgbmdkpsSA' ). + lo_buf->add( 'oNVEuzoFX4opklRG9SiDPqkAGjfYs3914S1HVM0wjaRhKbKMplpRIIZGXSdW' ). + lo_buf->add( 'LpGUzLFUwUrEDFnUtJSZMEtXlc2EkdJVANlScNsKqfGkpl79G7Xqe78rEpmY' ). + lo_buf->add( 'QEVSBhEBMw5lioh8QcLPe2RQWVYUFUlEvCUS+PDC6tINDyIeJnsALQZV4yrq' ). + lo_buf->add( 'DFmWmQ6nMQTNatpAb9jNbrezcc1KpyWqaPwPDXo6belx3bK35xydyFblRoLw' ). + lo_buf->add( '+sEblnb2FgZPspkQUVakcZBFficFJihsFBmVScSfAN9Dj6fLoma4gaOLsTAa' ). + lo_buf->add( 'x8Sr1017tdYODzePexgOngJ3I5hmIPS1mJHdV28tZb2njYrxtJddatUWMwCx' ). + lo_buf->add( '7YltXm17Mn7mTDy5veZtS8AfGEYmTbSVNinvdJ+KxZ5yd5ZJe0Uj6czKdMKU' ). + lo_buf->add( 'SKdO3MD6wheswCX1DpHMxKb+G2LF9kXxqZF3720FH6G7HcIQ5semL7g0WExm' ). + lo_buf->add( 's7Vs9hBVjjHsYBgsRfyGz60I852sUS07YLUZhS7wlCq3UyW0oeIDcJbfIjFE' ). + lo_buf->add( 'cSu6KO0uCnbaHcIcSFaTylRodErserPFsds0ePXxaFpszsi/+N6CaZE15Peg' ). + lo_buf->add( '3V4Uj+72hgHqdtfPidwaDTCFBRAGd4u6oYsLMoknJO2wJiXiRL7e9qGlGrtV' ). + lo_buf->add( 'w1BF0cy5qqwlqG0mUjJNEEJlXTWIkSBxO3aStWkbofsxNHQbAggzBP9O0QQl' ). + lo_buf->add( 'quOoBDNHJ1cNVTYShjxeNOWEJcsxzVCBjywqikESBok7WdZANUb3P+J7Ub9P' ). + lo_buf->add( 'CDcgykbJ566qBcwZRY4KdXnAAr7dKeCIymPe9rgFocM6D6w98aPYt8fCzOEu' ). + lo_buf->add( 'dhkpQsWlgm0X/Hdsg5gcz8XEzJyT8d7tLWZcOQmq4uYplFW/cPjqwuBE2HJS' ). + lo_buf->add( '3GyZWb1My/xrhasPF8a1Mqg5V1EhKbuZRaTpuXMZUc/H5Zg4+Q6fEXvkV204' ). + lo_buf->add( 'ugs7y/FMldmBTjuKF9Yv9hjDoAmcykwcuP7ARGboZxXuO9Xc3YTK8sSBCfws' ). + lo_buf->add( 'F5yzrAqT5VKzWRrGwriP6vAxtlx7bHpVocCEwgOnGx9mJuxDvaVhgPjcJuyH' ). + lo_buf->add( 'maXeh5i9+3Ajih3/xaYzsekTPwDfQv4voGcuQPUCQOLjKmng1jstr9dyvaCF' ). + lo_buf->add( 'cK0lXv/z76PXZItjmA5ent8zP4/fPY/cggl8K28PXmC1MGXnBy+8/8iR979w' ). + lo_buf->add( 'zTUvSHe94x0Cj8FxjMJ88IowK8yxO0UuFrhrTMRoFASYg1HE0mtF/kgIG9Hc' ). + lo_buf->add( '9NiEmN+xVvUesfTr1FKtpLJQkX6iEvrdz56wdB4weMS6G91/uo/Csldd1q14' ). + lo_buf->add( 'Mhm39MEZ3YL3h37369/mkYIZHk/wyXFsO9RVDLtS3JVJzPMjLYJXHfpCPALb' ). + lo_buf->add( '6jAN2grPPeiEAQUQEI3MDPjlYuJQb6F3KIHZn+FLWF1lOGM1waFlZdex2G23' ). + lo_buf->add( 'xY7tqvBiIqy7QE/uRtR8oU8d1KKoUBj6YSoRbSfKFN3qo4X+J2PQkQ++VSO+' ). + lo_buf->add( '2ijmXUmU65IuJTQrlSxqJClm9RRV+ugEK1YuZte69dA13qpxb0vGK7Im5dAI' ). + lo_buf->add( '2VS3rZiq6GDF7JzMNCqoRFYThlspTOdfD73mLXcSb7C7W9TjXq8bYkOO1ffi' ). + lo_buf->add( 'sddDXsZtjC6z+E9B+IpB2HGsNkbxpPSHdYs2vbnK9muntl8zVd7p4eQb6Gf9' ). + lo_buf->add( '+vRieKkxVh2jvJnl0Kab2X7tzddsd1000w0pJpVq0XWHoEWYdR15nkWcdwi7' ). + lo_buf->add( '0Iu8QbhFeBvnf25wmAFgcwyG21cfZrz/hxawPlhghw1nMd0Tsuzh8PH2/0UN' ). + lo_buf->add( 'HLdNXofJsZCrI97+H74f3l/h3tSFg8JJ1PjVC+93I84P2SzSd8HmlWx1qAlH' ). + lo_buf->add( 'bVqXtLmUTtQGzg/OcElY4c4Wz8KW/IDfGsPKZptzPHvuwuxaggteKFOb2dP/' ). + lo_buf->add( 'o9ccmw82NuBZ1AFfYZFaHmBgtixgYVdmvqZh9K7HSj6Ji53eMHYwWu8ocueG' ). + lo_buf->add( 'bVmQIRgGH3jIgdlJj176LpLzvaI7Av6X/uSiE7bleCScFzyDHEcRHMbIyvLy' ). + lo_buf->add( 'ColhlqKRJpKkSqbS0FFZxPGtu7xLUWKKKWdx1UTLYs6Q5V0H04AogBJRC4iJ' ). + lo_buf->add( 'PSTyi8lpYkgufXAX4omt5JSYLM8tc3JIAMkhrJCkz3qaGKM4AKSbTZd1pjFR' ). + lo_buf->add( '82SDWEjSq0cDXNe8cbdssRnlpti5TGX5ZJW5G5vXhdOhNQ8nZ+EkhxRFt9lM' ). + lo_buf->add( 'w/+dohH9NmPj5+I2UeK+Ojs3djaEH1aabTeevj8tIoYB6arHzDhod2ZFdMce' ). + lo_buf->add( 'fBA9LTF7pwZx87GriOfByw+5opPR7njMcAlZWiLENR67Q8s4kH7IUNXN39l8' ). + lo_buf->add( 'FeUuKeQQgbrOlkAUj26MbvTOpDr2w6nUGTv/Saewyj1fG858Mm+fsfF9Bx+F' ). + lo_buf->add( 'NnuXs0e69zicYbbdHvHmiCVHfBWxU/DT2zUtree022/XcnpaY88LyiBcoWJY' ). + lo_buf->add( 'ju4xRUVUEOXPcN2K0oOGKOgE1Gt5nKfDwTgw5kHQONvOLndEGPN3aRBd02y5' ). + lo_buf->add( '2vj3e5LT7sm1hePzJ2Nq8p5YWe/Ent5WtrN23tFEU7l6KXZYkej4obzrwvXG' ). + lo_buf->add( 'zTufsMc79n3GZ0Ml+d57kmrs5PzxhbWT7jR2j3Vipa+W7Vgqf3iMSsrh2NLV' ). + lo_buf->add( 'siVqTt7tFq+Xrt/5e3Zn3L638vDocoljF3ENj4rdr+1kUd/xeic8oE57FIdn' ). + lo_buf->add( 'gS0W1grTULMpw0VUh5keg1TiasK63XK2FZwBB4KJ/kp/Db8zyJ2DiSjmti18' ). + lo_buf->add( '7j617fbTdznYfoYHFrBDo99vsC9XWKth3C38nFu9ffO+Qxjdd7hhqCX61Uz4' ). + lo_buf->add( '2wwUZGU4V26t6pH12rznu/TCY/CdNb/tc4eDB8LgtyND9PhPL73veIo127zy' ). + lo_buf->add( 'ODHc0DB29BHEgnP8F6wfwP3sBmHUPLwMC3wGathVGMM8/CKMB9jDazAWEggv' ). + lo_buf->add( 'wXisnTKXqySS8a3w2KsFdcoj7vznKB3uqAR1XHS9FjrBaKR7fke8TZJzCugZ' ). + lo_buf->add( 'Wcmi21etEieZU2RPByUry1ki6p6s5IY1WUXOYM2jTgGKDfwOvl+fq9XmDrDk' ). + lo_buf->add( 'X0VJpLqeNAqGrKN0G7osxZL1I/Xk2PwYcwPihvhx141LpJKVJcuiJQKUoktE' ). + lo_buf->add( 'rbgoZytEil++1pJ4rYFDFqHQKP5uNCAmP5RkYpYDM0sVVaY5U4NEAkdrOgWN' ). + lo_buf->add( 'KOz3VNxvAcSTNXbnvXV/LtoKxq1TsL65nPu3Tt0pjM2DsDluZThMwWliZuQv' ). + lo_buf->add( 'Auc5FisLr9ZgCE17TM+g4Cs9j8JRxhz64F8K/QYJCuBprDz4x8dbx+FnjH80' ). + lo_buf->add( 'rGoojT5W6ax8FGuQ+n8DjoRJEQAAAHicY2BkYGAA4r+lycXx/DZfGbiZGEDg' ). + lo_buf->add( 'idCiqTD6/9//f9mnMbECuRwMYGkAXp8M93icY2BkYGBiAAH2qf///v/NPo2B' ). + lo_buf->add( 'kQEVOAEAdO8FdgAAeJxlj9ERgDAIQ6E/rtVRHIUl3IchHMQFbKS0PVA/3nE0' ). + lo_buf->add( 'QFIiou1AK1Y7rEZFYxn9AAhtout9aEUCFoDONCNx22frqrg77DsfNPsCfKU8' ). + lo_buf->add( 'y0ej92y/zLan9reZl/d3niKuu8cDcFI4PQAAAAAAAX4CNAJ2AroC5AMGAzID' ). + lo_buf->add( 'bgPUA/oEIARGBGwEkgTMBQwFJgVyBaAF6gZmBpoHCgeMB9wIWAiaCOoJRAmA' ). + lo_buf->add( 'CcAKJAp8CwILUgvaDAoMRAy2DOQNLA4GDloOpA80D7oP7BAkEFwQsBDuEVYR' ). + lo_buf->add( 'nhIsErITshPoFBQUThS6FRIVYhYWFkwWfgAAeJxjYGRgYHBiFGCQZgABJiDm' ). + lo_buf->add( 'AkIGhv9gPgMAE1cBhQB4nGWNS27CMBRFb/j0A1KLVKkd1qMOqAifIQuAOQNm' ). + lo_buf->add( 'HYTghKAkjhyDxKwr6BK6hK6i6gq6oF7cxwRsye+8865tAD38IMBxBbjx53E1' ). + lo_buf->add( 'cM3un5uke+EW+Um4jS6eha/o+8IdvGIi3MUD3vhC0Lql6aESbuAO78JN+g/h' ). + lo_buf->add( 'FvlTuI1HfAlf0X8Ld7DEr3AXL0E/SgdZbMp6odNdHtlTe6pLbevMlGocjk5q' ). + lo_buf->add( 'rkttI6fXanVQ9T6dOJeoxJpCzUzpdJ4bVVmz1bELN85V0+EwER/GpkCEFANk' ). + lo_buf->add( 'iGFQosYCmmaHnBN7MT3vl0xb1sz3CmOEGF2k5kyVPhnBsa6ZXOHAs8ae2Qmt' ). + lo_buf->add( 'Q8I+YcagIM383WM65zY0lZ9taWL6EBt/q8IUQ+7kLB/634s/3IhcMHicbVJn' ). + lo_buf->add( 'e9owGOQSEzAzgYzuvVt375U2/SWyLRs9CMvVgNBfX1kSNB/qD9bdya/vvVdq' ). + lo_buf->add( '7bT80279/znDDnYRoY09dNBFjB76GGCIEcbYxwEmmOIQRzjGCS7hMq7gKq7h' ). + lo_buf->add( 'Om7gJm7hNu7gLu7hPh7gIR7hMZ7gKZ4hwXO8wEu8wmu8wVu8w3t8wEd8wmd8' ). + lo_buf->add( 'wVd8w3ec4gd+4gy/Wh2SkrpkutusnFV6TKQUqyRjMuM0MXWUEqmiVHA9SoWY' ). + lo_buf->add( 'L4icJ0pwlu+m4jxOJaNFRhSNU1N6vZ3NaDYf2PdSiirJxaraEk4LPdwQycqZ' ). + lo_buf->add( '7m2YqSfBMxc6kbQ0nMhpkGpO1httEDRnNsi4MHmSicWC6b4nbmPfY1NzQfKE' ). + lo_buf->add( 'cLspcpqkklTZzGNfNHa4EJtYJ47XhnNr+NtQpb3ec7pPnonS0nrt6aiJ6Gz8' ). + lo_buf->add( 'hzRnoWZCzzNOFkQzG9C3fXhR0pKRquQ0puvw627BbDTbbuxA49lziC1ISacO' ). + lo_buf->add( '/mF1TeVmHFGj2TLpyqKCi9VeIXhOZccea6Pt2XVm0uGMErmd7AGrCpFcHOWI' ). + lo_buf->add( '216MdQkx7GUII4m4yObHtoGKFWtWlUnJiVKh4eZCNAPo10TpUBvV3JRHbnj/' ). + lo_buf->add( 'kgcXSXPRdBXOT1G5tGEciZV9UamSWawqsSo4mdNIaSJjTcLl6mu2oGqDheBb' ). + lo_buf->add( 'LE0W2h2EQ/d+xjrYOYb6nqMeLhnhHrZafwFnhCXLAAA=' ). + li_asset_man->register_asset( + iv_url = 'font/ag-icons.woff' + iv_type = 'font/woff' + iv_mime_name = 'ZABAPGIT_ICON_FONT' + iv_base64 = lo_buf->join_and_flush( ) ). + + ri_asset_man = li_asset_man. + + ENDMETHOD. + METHOD get_frontend_services. + + IF gi_fe_services IS INITIAL. + IF iv_disable_gui IS INITIAL. + CREATE OBJECT gi_fe_services TYPE zcl_abapgit_frontend_services. + ELSE. + CREATE OBJECT gi_fe_services TYPE zcl_abapgit_frontend_no_gui. + ENDIF. + ENDIF. + + ri_fe_serv = gi_fe_services. + + ENDMETHOD. + METHOD get_gui. + + DATA: + li_hotkey_ctl TYPE REF TO zif_abapgit_gui_hotkey_ctl, + li_router TYPE REF TO zif_abapgit_gui_event_handler, + li_asset_man TYPE REF TO zif_abapgit_gui_asset_manager. + + DATA lo_html_preprocessor TYPE REF TO zcl_abapgit_gui_html_processor. + + IF go_gui IS INITIAL. + li_asset_man = get_asset_manager( ). + + CREATE OBJECT lo_html_preprocessor EXPORTING ii_asset_man = li_asset_man. + lo_html_preprocessor->preserve_css( 'css/ag-icons.css' ). + lo_html_preprocessor->preserve_css( 'css/common.css' ). + + CREATE OBJECT li_router TYPE zcl_abapgit_gui_router. + CREATE OBJECT li_hotkey_ctl TYPE zcl_abapgit_gui_hotkey_ctl. + + CREATE OBJECT go_gui + EXPORTING + io_component = li_router + ii_hotkey_ctl = li_hotkey_ctl + ii_html_processor = lo_html_preprocessor + ii_asset_man = li_asset_man. + ENDIF. + ro_gui = go_gui. + + ENDMETHOD. + METHOD get_gui_services. + IF gi_gui_services IS NOT BOUND. + gi_gui_services ?= get_gui( ). + ENDIF. + ri_gui_services = gi_gui_services. + ENDMETHOD. + METHOD get_popups. + + IF gi_popups IS INITIAL. + CREATE OBJECT gi_popups TYPE zcl_abapgit_popups. + ENDIF. + + ri_popups = gi_popups. + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlrVRrOJtQtrmwQhffrvwSNBuVh DEFINITION DEFERRED. +* renamed: zcl_abapgit_popups :: lcl_object_decision_list +CLASS kHGwlrVRrOJtQtrmwQhffrvwSNBuVh DEFINITION FINAL. + PUBLIC SECTION. + + CONSTANTS c_default_column TYPE abap_componentdescr-name VALUE 'DEFAULT_COLUMN'. + CONSTANTS c_fieldname_selected TYPE abap_componentdescr-name VALUE 'SELECTED'. + CONSTANTS c_answer_cancel TYPE c LENGTH 1 VALUE 'A'. + CONSTANTS c_fieldname_obj_type TYPE abap_componentdescr-name VALUE 'OBJ_TYPE'. + CONSTANTS c_own_pfstatus TYPE sy-pfkey VALUE 'DECIDE_DIALOG'. + + METHODS constructor + IMPORTING + !it_list TYPE STANDARD TABLE + !iv_title TYPE lvc_title DEFAULT space + !iv_header_text TYPE csequence DEFAULT space + !is_position TYPE zif_abapgit_popups=>ty_popup_position + !iv_striped_pattern TYPE abap_bool DEFAULT abap_false + !iv_optimize_col_width TYPE abap_bool DEFAULT abap_true + !iv_selection_mode TYPE salv_de_constant DEFAULT if_salv_c_selection_mode=>multiple + !iv_select_column_text TYPE csequence DEFAULT space + !it_columns_to_display TYPE zif_abapgit_popups=>ty_alv_column_tt + !it_preselected_rows TYPE zif_abapgit_popups=>ty_rows OPTIONAL + RAISING + zcx_abapgit_exception. + + METHODS display + RAISING + zcx_abapgit_exception. + METHODS get_selected + EXPORTING + VALUE(et_list) TYPE STANDARD TABLE. + + PRIVATE SECTION. + + DATA mr_table TYPE REF TO data. + DATA mo_table_descr TYPE REF TO cl_abap_tabledescr. + DATA mo_alv TYPE REF TO cl_salv_table. + DATA mv_cancel TYPE abap_bool. + DATA ms_position TYPE zif_abapgit_popups=>ty_popup_position. + + " Events + METHODS on_select_list_link_click + FOR EVENT link_click OF cl_salv_events_table + IMPORTING + !row + !column. + METHODS on_select_list_function_click + FOR EVENT added_function OF cl_salv_events_table + IMPORTING + !e_salv_function. + METHODS on_double_click + FOR EVENT double_click OF cl_salv_events_table + IMPORTING + !row + !column. + + " Methods + METHODS create_new_selectable_table + IMPORTING + it_list TYPE STANDARD TABLE. + METHODS preselect + IMPORTING + it_preselected_rows TYPE zif_abapgit_popups=>ty_rows OPTIONAL + RAISING + zcx_abapgit_exception. + METHODS create_alv + RETURNING + VALUE(ro_alv) TYPE REF TO cl_salv_table + RAISING + cx_salv_msg. + METHODS setup_columns + IMPORTING + io_columns TYPE REF TO cl_salv_columns_table + iv_selection_mode TYPE salv_de_constant + iv_select_column_text TYPE csequence + it_columns_to_display TYPE zif_abapgit_popups=>ty_alv_column_tt + RAISING + cx_salv_msg. + METHODS setup_toolbar + IMPORTING + !iv_selection_mode TYPE salv_de_constant + !iv_object_list TYPE abap_bool. + METHODS ask_user_for_obj_category + RETURNING + VALUE(rv_category) TYPE string. + METHODS mark_category + IMPORTING + iv_category TYPE string. + METHODS mark_all + IMPORTING + iv_selected TYPE abap_bool. + METHODS mark_visible + IMPORTING + iv_selected TYPE abap_bool. + METHODS mark_selected. + METHODS mark_indexed + IMPORTING + iv_selected TYPE abap_bool DEFAULT abap_true + iv_invert TYPE abap_bool DEFAULT abap_false + it_scope TYPE lvc_t_fidx. + METHODS are_all_marked + IMPORTING + it_scope TYPE lvc_t_fidx + RETURNING + VALUE(rv_yes) TYPE abap_bool. + METHODS refresh. + +ENDCLASS. + +CLASS kHGwlrVRrOJtQtrmwQhffrvwSNBuVh IMPLEMENTATION. + + METHOD display. + + mo_alv->display( ). + + IF mv_cancel = abap_true. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + ENDMETHOD. + + METHOD refresh. + + DATA ls_stable TYPE lvc_s_stbl. + + ls_stable-row = 'X'. + ls_stable-col = 'X'. + + mo_alv->refresh( ls_stable ). + + ENDMETHOD. + + METHOD get_selected. + + DATA: + lv_condition TYPE string, + lr_exporting TYPE REF TO data, + lo_data_descr TYPE REF TO cl_abap_datadescr, + lo_selections TYPE REF TO cl_salv_selections, + lt_selected_rows TYPE salv_t_row. + + FIELD-SYMBOLS: + TYPE any, + TYPE STANDARD TABLE, + TYPE any, + TYPE any, + TYPE abap_bool, + TYPE LINE OF salv_t_row. + + CLEAR et_list. + + " Make sure we don't accidentally return anything + IF mv_cancel = abap_true. + RETURN. + ENDIF. + + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + lo_selections = mo_alv->get_selections( ). + + IF lo_selections->get_selection_mode( ) = if_salv_c_selection_mode=>single. + + lt_selected_rows = lo_selections->get_selected_rows( ). + + LOOP AT lt_selected_rows ASSIGNING . + + READ TABLE ASSIGNING INDEX . + CHECK IS ASSIGNED. + + ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . + CHECK IS ASSIGNED. + + = abap_true. + + ENDLOOP. + + ENDIF. + + lv_condition = |{ c_fieldname_selected } = ABAP_TRUE|. + + CREATE DATA lr_exporting LIKE LINE OF et_list. + ASSIGN lr_exporting->* TO . + + lo_data_descr = mo_table_descr->get_table_line_type( ). + + LOOP AT ASSIGNING WHERE (lv_condition). + CLEAR . + + CASE lo_data_descr->kind. + WHEN cl_abap_elemdescr=>kind_elem. + ASSIGN COMPONENT c_default_column OF STRUCTURE TO . + ASSERT IS ASSIGNED. + = . + + WHEN OTHERS. + MOVE-CORRESPONDING TO . + + ENDCASE. + APPEND TO et_list. + ENDLOOP. + + ENDMETHOD. + + METHOD create_alv. + + FIELD-SYMBOLS TYPE STANDARD TABLE. + + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + cl_salv_table=>factory( + IMPORTING + r_salv_table = ro_alv + CHANGING + t_table = ). + + ENDMETHOD. + + METHOD constructor. + + DATA: + lv_object_list TYPE abap_bool, + lo_events TYPE REF TO cl_salv_events_table, + lo_columns TYPE REF TO cl_salv_columns_table, + lo_table_header TYPE REF TO cl_salv_form_text. + + create_new_selectable_table( it_list ). + preselect( it_preselected_rows ). + + TRY. + mo_alv = create_alv( ). + mo_alv->set_screen_popup( + start_column = is_position-start_column + end_column = is_position-end_column + start_line = is_position-start_row + end_line = is_position-end_row ). + ms_position = is_position. + + lo_events = mo_alv->get_event( ). + + SET HANDLER on_select_list_link_click FOR lo_events. + SET HANDLER on_select_list_function_click FOR lo_events. + SET HANDLER on_double_click FOR lo_events. + + IF iv_title CN ' _0'. + mo_alv->get_display_settings( )->set_list_header( iv_title ). + ENDIF. + + IF iv_header_text CN ' _0'. + CREATE OBJECT lo_table_header EXPORTING text = iv_header_text. + mo_alv->set_top_of_list( lo_table_header ). + ENDIF. + + mo_alv->get_display_settings( )->set_striped_pattern( iv_striped_pattern ). + mo_alv->get_selections( )->set_selection_mode( iv_selection_mode ). + + lo_columns = mo_alv->get_columns( ). + lo_columns->set_optimize( iv_optimize_col_width ). + + TRY. + lo_columns->get_column( |{ c_fieldname_obj_type }| ). + lv_object_list = abap_true. + CATCH cx_salv_not_found ##NO_HANDLER. + ENDTRY. + + setup_columns( + io_columns = lo_columns + iv_selection_mode = iv_selection_mode + iv_select_column_text = iv_select_column_text + it_columns_to_display = it_columns_to_display ). + + setup_toolbar( + iv_object_list = lv_object_list + iv_selection_mode = iv_selection_mode ). + + CATCH cx_salv_msg. + zcx_abapgit_exception=>raise( 'ALV error from object decision list' ). + ENDTRY. + ENDMETHOD. + + METHOD create_new_selectable_table. + + " create and populate a table on the fly derived from + " it_data with a select column + + DATA: + lr_struct TYPE REF TO data, + lt_components TYPE cl_abap_structdescr=>component_table, + lo_data_descr TYPE REF TO cl_abap_datadescr, + lo_elem_descr TYPE REF TO cl_abap_elemdescr, + lo_struct_descr TYPE REF TO cl_abap_structdescr, + lo_struct_descr2 TYPE REF TO cl_abap_structdescr. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + TYPE abap_componentdescr, + TYPE data, + TYPE any, + TYPE any. + + mo_table_descr ?= cl_abap_tabledescr=>describe_by_data( it_list ). + lo_data_descr = mo_table_descr->get_table_line_type( ). + + CASE lo_data_descr->kind. + WHEN cl_abap_elemdescr=>kind_elem. + lo_elem_descr ?= mo_table_descr->get_table_line_type( ). + INSERT INITIAL LINE INTO lt_components ASSIGNING INDEX 1. + -name = c_default_column. + -type = lo_elem_descr. + + WHEN cl_abap_elemdescr=>kind_struct. + lo_struct_descr ?= mo_table_descr->get_table_line_type( ). + lt_components = lo_struct_descr->get_components( ). + + ENDCASE. + + IF lt_components IS INITIAL. + RETURN. + ENDIF. + + INSERT INITIAL LINE INTO lt_components ASSIGNING INDEX 1. + -name = c_fieldname_selected. + -type ?= cl_abap_datadescr=>describe_by_name( 'FLAG' ). + + lo_struct_descr2 = cl_abap_structdescr=>create( lt_components ). + mo_table_descr = cl_abap_tabledescr=>create( lo_struct_descr2 ). + + CREATE DATA mr_table TYPE HANDLE mo_table_descr. + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + CREATE DATA lr_struct TYPE HANDLE lo_struct_descr2. + ASSIGN lr_struct->* TO . + ASSERT sy-subrc = 0. + + LOOP AT it_list ASSIGNING . + CLEAR . + CASE lo_data_descr->kind. + WHEN cl_abap_elemdescr=>kind_elem. + ASSIGN COMPONENT c_default_column OF STRUCTURE TO . + ASSERT IS ASSIGNED. + = . + + WHEN OTHERS. + MOVE-CORRESPONDING TO . + + ENDCASE. + INSERT INTO TABLE . + ENDLOOP. + + ENDMETHOD. + + METHOD preselect. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + LIKE LINE OF it_preselected_rows, + TYPE any, + TYPE data. + + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + LOOP AT it_preselected_rows ASSIGNING . + + READ TABLE INDEX ASSIGNING . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Preselected row { } doesn't exist| ). + ENDIF. + + ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = abap_true. + + ENDLOOP. + + ENDMETHOD. + + METHOD on_double_click. + + DATA lo_selections TYPE REF TO cl_salv_selections. + + lo_selections = mo_alv->get_selections( ). + + IF lo_selections->get_selection_mode( ) = if_salv_c_selection_mode=>single. + mo_alv->close_screen( ). + ENDIF. + + ENDMETHOD. + + METHOD on_select_list_function_click. + + " Work for functions of SAPMSVIM and OWN + CASE e_salv_function. + WHEN 'O.K.' OR 'OK'. + mv_cancel = abap_false. + mo_alv->close_screen( ). + + WHEN 'ABR' OR 'CANCEL'. + " Canceled: clear list to overwrite nothing + mv_cancel = abap_true. + mo_alv->close_screen( ). + + WHEN 'SALL' OR 'SEL_ALL'. + mark_visible( abap_true ). + refresh( ). + + WHEN 'DSEL' OR 'SEL_DEL'. + mark_visible( abap_false ). + refresh( ). + + WHEN 'SEL_KEY'. + mark_selected( ). + refresh( ). + + WHEN 'SEL_CAT'. + mark_category( ask_user_for_obj_category( ) ). + refresh( ). + + WHEN OTHERS. + mv_cancel = abap_true. + mo_alv->close_screen( ). + + ENDCASE. + + ENDMETHOD. + + METHOD mark_all. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + TYPE any, + TYPE abap_bool. + + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + LOOP AT ASSIGNING . + + ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = iv_selected. + + ENDLOOP. + + ENDMETHOD. + + METHOD are_all_marked. + + DATA lv_index LIKE LINE OF it_scope. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + TYPE any, + TYPE abap_bool. + + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + LOOP AT it_scope INTO lv_index. + + READ TABLE ASSIGNING INDEX lv_index. + CHECK sy-subrc = 0. + + ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + IF = abap_true. + rv_yes = abap_true. + ELSE. + rv_yes = abap_false. + RETURN. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + + METHOD mark_selected. + + DATA lt_clear TYPE salv_t_row. + DATA lt_scope TYPE lvc_t_fidx. + + lt_scope = mo_alv->get_selections( )->get_selected_rows( ). + + IF lines( lt_scope ) > 0. + mark_indexed( + it_scope = lt_scope + iv_selected = boolc( are_all_marked( lt_scope ) = abap_false ) ). + mo_alv->get_selections( )->set_selected_rows( lt_clear ). + ELSE. + MESSAGE 'Select rows first to mark them' TYPE 'S'. + ENDIF. + + ENDMETHOD. + + METHOD mark_visible. + + DATA lt_filters TYPE lvc_t_filt. + DATA lt_scope TYPE lvc_t_fidx. + + FIELD-SYMBOLS TYPE STANDARD TABLE. + + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + " If nothing selected, select all VISIBLE + lt_filters = cl_salv_controller_metadata=>get_lvc_filter( mo_alv->get_filters( ) ). + IF lines( lt_filters ) = 0. + mark_all( iv_selected ). " No filters - just select all + RETURN. + ENDIF. + + CALL FUNCTION 'LVC_FILTER_APPLY' + EXPORTING + it_filter = lt_filters + IMPORTING + et_filter_index_inside = lt_scope + TABLES + it_data = . + + mark_indexed( + it_scope = lt_scope + iv_selected = iv_selected ). + + ENDMETHOD. + + METHOD mark_indexed. + + DATA lv_index LIKE LINE OF it_scope. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + TYPE any, + TYPE abap_bool. + + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + LOOP AT it_scope INTO lv_index. + + READ TABLE ASSIGNING INDEX lv_index. + CHECK sy-subrc = 0. + + ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + IF iv_invert = abap_true. + = boolc( = abap_false ). + ELSE. + = iv_selected. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + + METHOD ask_user_for_obj_category. + + DATA: + lv_answer TYPE c LENGTH 1, + ls_position TYPE zif_abapgit_popups=>ty_popup_position, + ls_selection TYPE spopli, + lt_selection TYPE TABLE OF spopli. + + ls_selection-varoption = 'Packages'. + APPEND ls_selection TO lt_selection. + ls_selection-varoption = 'DDIC objects'. + APPEND ls_selection TO lt_selection. + ls_selection-varoption = 'Source code'. + APPEND ls_selection TO lt_selection. + ls_selection-varoption = 'Enhancements'. + APPEND ls_selection TO lt_selection. + + ls_position-start_column = ms_position-start_column + 20. + ls_position-start_row = ms_position-start_row + 5. + + CALL FUNCTION 'POPUP_TO_DECIDE_LIST' + EXPORTING + titel = 'Selection' + textline1 = 'Which objects should be added to the selection?' + start_col = ls_position-start_column + start_row = ls_position-start_row + cursorline = 1 + IMPORTING + answer = lv_answer + TABLES + t_spopli = lt_selection + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0 OR lv_answer = c_answer_cancel. + RETURN. + ENDIF. + + READ TABLE lt_selection INDEX lv_answer INTO ls_selection. + IF sy-subrc = 0. + rv_category = ls_selection-varoption. + ENDIF. + + ENDMETHOD. + + METHOD mark_category. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + TYPE tadir-object, + TYPE any, + TYPE abap_bool. + + IF iv_category IS INITIAL. + RETURN. + ENDIF. + + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + LOOP AT ASSIGNING . + + ASSIGN COMPONENT c_fieldname_obj_type OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + CASE iv_category. + WHEN 'Packages'. + IF <> 'DEVC'. + CONTINUE. + ENDIF. + WHEN 'DDIC objects'. + IF zcl_abapgit_objects_activation=>is_ddic_type( ) = abap_false. + CONTINUE. + ENDIF. + WHEN 'Source code'. + IF 'CLAS,FUGR,INTF,PROG,TYPE' NS . + CONTINUE. + ENDIF. + WHEN 'Enhancements'. + IF 'ENHO,ENHS,ENHC,ENSC' NS . + CONTINUE. + ENDIF. + WHEN OTHERS. + RETURN. " Unexpected category + ENDCASE. + + = abap_true. + + ENDLOOP. + + ENDMETHOD. + + METHOD on_select_list_link_click. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + TYPE any, + TYPE abap_bool. + + ASSIGN mr_table->* TO . + ASSERT sy-subrc = 0. + + READ TABLE ASSIGNING INDEX row. + IF sy-subrc = 0. + + ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = boolc( = abap_false ). + + ENDIF. + + refresh( ). + + ENDMETHOD. + + METHOD setup_columns. + + DATA: + lt_columns TYPE salv_t_column_ref, + ls_column TYPE salv_s_column_ref, + lo_column TYPE REF TO cl_salv_column_list. + + FIELD-SYMBOLS TYPE zif_abapgit_popups=>ty_alv_column. + + lt_columns = io_columns->get( ). + + LOOP AT lt_columns INTO ls_column. + + lo_column ?= ls_column-r_column. + + IF iv_selection_mode = if_salv_c_selection_mode=>multiple AND + ls_column-columnname = c_fieldname_selected. + lo_column->set_cell_type( if_salv_c_cell_type=>checkbox_hotspot ). + lo_column->set_output_length( 20 ). + lo_column->set_short_text( |{ iv_select_column_text }| ). + lo_column->set_medium_text( |{ iv_select_column_text }| ). + lo_column->set_long_text( |{ iv_select_column_text }| ). + CONTINUE. + ENDIF. + + READ TABLE it_columns_to_display + ASSIGNING + WITH KEY name = ls_column-columnname. + + CASE sy-subrc. + WHEN 0. + IF -text CN ' _0'. + lo_column->set_short_text( |{ -text }| ). + lo_column->set_medium_text( |{ -text }| ). + lo_column->set_long_text( |{ -text }| ). + ENDIF. + + IF -length > 0. + lo_column->set_output_length( -length ). + ENDIF. + + IF -show_icon = abap_true. + lo_column->set_icon( abap_true ). + ENDIF. + + IF -center = abap_true. + lo_column->set_alignment( if_salv_c_alignment=>centered ). + ENDIF. + + WHEN OTHERS. + lo_column->set_technical( abap_true ). " Hide column + + ENDCASE. + + ENDLOOP. + + ENDMETHOD. + + METHOD setup_toolbar. + + DATA: + lv_report TYPE sy-repid, + lv_pfstatus TYPE sy-pfkey, + lo_functions TYPE REF TO cl_salv_functions_list, + lt_func_list TYPE salv_t_ui_func, + lv_fn TYPE string, + ls_func LIKE LINE OF lt_func_list. + + CALL FUNCTION 'RS_CUA_STATUS_CHECK' + EXPORTING + program = sy-cprog + objectname = c_own_pfstatus + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + + IF sy-subrc = 0. + + mo_alv->set_screen_status( + report = sy-cprog + pfstatus = c_own_pfstatus ). + + ELSE. + + lv_report = 'SAPMSVIM'. + + IF iv_selection_mode = if_salv_c_selection_mode=>single. + lv_pfstatus = '110'. + ELSE. + lv_pfstatus = '102'. + ENDIF. + + mo_alv->set_screen_status( + report = lv_report + pfstatus = lv_pfstatus ). + + ENDIF. + + lo_functions = mo_alv->get_functions( ). + + lt_func_list = lo_functions->get_functions( ). + LOOP AT lt_func_list INTO ls_func. + lv_fn = ls_func-r_function->get_name( ). + IF lv_fn = 'OK' OR lv_fn = 'CANCEL' + OR lv_fn = 'O.K.' OR lv_fn = 'EABR'. + ls_func-r_function->set_visible( abap_true ). + ELSEIF iv_object_list = abap_true. + ls_func-r_function->set_visible( abap_true ). + ELSE. + ls_func-r_function->set_visible( abap_false ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_popups IMPLEMENTATION. + METHOD add_field. + + FIELD-SYMBOLS: LIKE LINE OF ct_fields. + + APPEND INITIAL LINE TO ct_fields ASSIGNING . + -tabname = iv_tabname. + -fieldname = iv_fieldname. + -fieldtext = iv_fieldtext. + -value = iv_value. + -field_attr = iv_field_attr. + -field_obl = iv_obligatory. + + ENDMETHOD. + METHOD center. + + CONSTANTS: + lc_min_size TYPE i VALUE 10, + lc_min_pos TYPE i VALUE 5. + + " Magic math to approximate starting position of popup + IF sy-scols > lc_min_size AND iv_width > 0 AND sy-scols > iv_width. + rs_position-start_column = nmax( + val1 = ( sy-scols - iv_width ) / 2 + val2 = lc_min_pos ). + ELSE. + rs_position-start_column = lc_min_pos. + ENDIF. + + IF sy-srows > lc_min_size AND iv_height > 0 AND sy-srows > iv_height. + rs_position-start_row = nmax( + val1 = ( sy-srows - iv_height ) / 2 - 1 + val2 = lc_min_pos ). + ELSE. + rs_position-start_row = lc_min_pos. + ENDIF. + + rs_position-end_column = rs_position-start_column + iv_width. + rs_position-end_row = rs_position-start_row + iv_height. + + ENDMETHOD. + METHOD commit_list_build. + + DATA: + lv_unix_time TYPE zcl_abapgit_git_time=>ty_unixtime, + lv_date TYPE d, + lv_date_string TYPE c LENGTH 12, + lv_time TYPE t, + lv_time_string TYPE c LENGTH 10. + + FIELD-SYMBOLS: + TYPE zif_abapgit_git_definitions=>ty_commit, + TYPE ty_commit_value_tab. + + CLEAR: et_commits, et_value_tab. + + et_commits = zcl_abapgit_git_commit=>get_by_branch( iv_branch_name = iv_branch_name + iv_repo_url = iv_repo_url + iv_deepen_level = 99 + iv_sorted = abap_false )-commits. + + IF et_commits IS INITIAL. + zcx_abapgit_exception=>raise( |No commits are available in this branch.| ). + ENDIF. + + SORT et_commits BY time DESCENDING. + + LOOP AT et_commits ASSIGNING . + + APPEND INITIAL LINE TO et_value_tab ASSIGNING . + -commit = -sha1. + -message = -message. + lv_unix_time = -time. + zcl_abapgit_git_time=>get_utc( + EXPORTING + iv_unix = lv_unix_time + IMPORTING + ev_time = lv_time + ev_date = lv_date ). + WRITE: lv_date TO lv_date_string, + lv_time TO lv_time_string. + -datetime = |{ lv_date_string }, | && + |{ lv_time_string }|. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_popups~branch_list_popup. + + DATA: lo_branches TYPE REF TO zif_abapgit_git_branch_list, + lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, + lv_answer TYPE c LENGTH 1, + lv_default TYPE i, + lv_head_suffix TYPE string, + lv_head_symref TYPE string, + lv_text TYPE string, + lt_selection TYPE TABLE OF spopli. + + FIELD-SYMBOLS: LIKE LINE OF lt_selection, + LIKE LINE OF lt_branches. + lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). + lt_branches = lo_branches->get_branches_only( ). + lv_head_suffix = | ({ zif_abapgit_git_definitions=>c_head_name })|. + lv_head_symref = lo_branches->get_head_symref( ). + + IF iv_hide_branch IS NOT INITIAL. + DELETE lt_branches WHERE name = iv_hide_branch. + ENDIF. + + IF iv_hide_head IS NOT INITIAL. + DELETE lt_branches WHERE name = zif_abapgit_git_definitions=>c_head_name + OR is_head = abap_true. + ENDIF. + + IF lt_branches IS INITIAL. + IF iv_hide_head IS NOT INITIAL. + lv_text = 'main'. + ENDIF. + IF iv_hide_branch IS NOT INITIAL AND iv_hide_branch <> zif_abapgit_git_definitions=>c_git_branch-main. + IF lv_text IS INITIAL. + lv_text = iv_hide_branch && ' is'. + ELSE. + CONCATENATE lv_text 'and' iv_hide_branch 'are' INTO lv_text SEPARATED BY space. + ENDIF. + ELSE. + lv_text = lv_text && ' is'. + ENDIF. + IF lv_text IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'No branches available to select (' && lv_text && ' hidden)' ). + ELSE. + zcx_abapgit_exception=>raise( 'No branches are available to select' ). + ENDIF. + ENDIF. + + LOOP AT lt_branches ASSIGNING . + + CHECK -name IS NOT INITIAL. " To ensure some below ifs + + IF -is_head = abap_true. + + IF -name = zif_abapgit_git_definitions=>c_head_name. " HEAD + IF -name <> lv_head_symref AND lv_head_symref IS NOT INITIAL. + " HEAD but other HEAD symref exists - ignore + CONTINUE. + ELSE. + INSERT INITIAL LINE INTO lt_selection INDEX 1 ASSIGNING . + -varoption = -name. + ENDIF. + ELSE. + INSERT INITIAL LINE INTO lt_selection INDEX 1 ASSIGNING . + -varoption = -display_name && lv_head_suffix. + ENDIF. + + IF lv_default > 0. " Shift down default if set + lv_default = lv_default + 1. + ENDIF. + ELSE. + APPEND INITIAL LINE TO lt_selection ASSIGNING . + -varoption = -display_name. + ENDIF. + + IF -name = iv_default_branch. + IF -is_head = abap_true. + lv_default = 1. + ELSE. + lv_default = sy-tabix. + ENDIF. + ENDIF. + + ENDLOOP. + + IF iv_show_new_option = abap_true. + APPEND INITIAL LINE TO lt_selection ASSIGNING . + -varoption = zif_abapgit_popups=>c_new_branch_label. + ENDIF. + + ms_position = center( + iv_width = 30 + iv_height = lines( lt_selection ) ). + + CALL FUNCTION 'POPUP_TO_DECIDE_LIST' + EXPORTING + titel = 'Select Branch' + textline1 = 'Select a branch' + start_col = ms_position-start_column + start_row = ms_position-start_row + cursorline = lv_default + IMPORTING + answer = lv_answer + TABLES + t_spopli = lt_selection + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error from POPUP_TO_DECIDE_LIST' ). + ENDIF. + + IF lv_answer = c_answer_cancel. + RETURN. + ENDIF. + + READ TABLE lt_selection ASSIGNING WITH KEY selflag = abap_true. + ASSERT sy-subrc = 0. + + IF iv_show_new_option = abap_true AND -varoption = zif_abapgit_popups=>c_new_branch_label. + rs_branch-name = zif_abapgit_popups=>c_new_branch_label. + ELSE. + REPLACE FIRST OCCURRENCE OF lv_head_suffix IN -varoption WITH ''. + READ TABLE lt_branches WITH KEY display_name = -varoption ASSIGNING . + IF sy-subrc <> 0. +* branch name longer than 65 characters + LOOP AT lt_branches ASSIGNING WHERE display_name CS -varoption. + EXIT. " current loop + ENDLOOP. + ENDIF. + ASSERT IS ASSIGNED. + rs_branch = lo_branches->find_by_name( -name ). + lv_text = |Branch switched from { zcl_abapgit_git_branch_utils=>get_display_name( iv_default_branch ) } to { + zcl_abapgit_git_branch_utils=>get_display_name( rs_branch-name ) } |. + MESSAGE lv_text TYPE 'S'. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_popups~choose_code_insp_check_variant. + + DATA: lt_return TYPE STANDARD TABLE OF ddshretval. + + FIELD-SYMBOLS: LIKE LINE OF lt_return. + + CALL FUNCTION 'F4IF_FIELD_VALUE_REQUEST' + EXPORTING + tabname = 'SCI_DYNP' + fieldname = 'CHKV' + TABLES + return_tab = lt_return + EXCEPTIONS + field_not_found = 1 + no_help_for_field = 2 + inconsistent_help = 3 + no_values_found = 4 + OTHERS = 5. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + READ TABLE lt_return ASSIGNING + WITH KEY retfield = 'SCI_DYNP-CHKV'. + IF sy-subrc = 0. + rv_check_variant = -fieldval. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_popups~commit_list_popup. + + DATA: + lt_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt, + lt_value_tab TYPE ty_commit_value_tab_tt, + lt_selected_values TYPE ty_commit_value_tab_tt, + lt_columns TYPE zif_abapgit_popups=>ty_alv_column_tt. + + FIELD-SYMBOLS: + TYPE ty_commit_value_tab, + TYPE zif_abapgit_popups=>ty_alv_column. + + commit_list_build( + EXPORTING + iv_branch_name = iv_branch_name + iv_repo_url = iv_repo_url + IMPORTING + et_value_tab = lt_value_tab + et_commits = lt_commits ). + + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'COMMIT'. + -text = 'Hash'. + -length = 8. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'MESSAGE'. + -text = 'Message'. + -length = 60. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'DATETIME'. + -text = 'Datetime'. + -length = 17. + + zif_abapgit_popups~popup_to_select_from_list( + EXPORTING + it_list = lt_value_tab + iv_title = |Select a commit| + iv_end_column = 100 + iv_striped_pattern = abap_true + iv_optimize_col_width = abap_false + iv_selection_mode = if_salv_c_selection_mode=>single + it_columns_to_display = lt_columns + IMPORTING + et_list = lt_selected_values ). + + IF lt_selected_values IS INITIAL. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + READ TABLE lt_selected_values ASSIGNING INDEX 1. + ASSERT sy-subrc = 0. + + READ TABLE lt_commits INTO rs_commit WITH KEY sha1 = -commit. + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD zif_abapgit_popups~create_branch_popup. + + DATA: lt_fields TYPE TABLE OF sval. + DATA: lv_name TYPE spo_value. + + CLEAR: ev_name, ev_cancel. + + add_field( EXPORTING iv_tabname = 'TEXTL' + iv_fieldname = 'LINE' + iv_fieldtext = 'Name' + iv_value = 'new-branch-name' + CHANGING ct_fields = lt_fields ). + + TRY. + + _popup_3_get_values( + EXPORTING iv_popup_title = |Create branch from { + zcl_abapgit_git_branch_utils=>get_display_name( iv_source_branch_name ) }| + IMPORTING ev_value_1 = lv_name + CHANGING ct_fields = lt_fields ). + + ev_name = zcl_abapgit_git_branch_utils=>complete_heads_branch_name( + zcl_abapgit_git_branch_utils=>normalize_branch_name( lv_name ) ). + + CATCH zcx_abapgit_cancel. + ev_cancel = abap_true. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_popups~popup_folder_logic. + + DATA: + lt_selection TYPE TABLE OF spopli, + lv_answer TYPE c LENGTH 1. + + FIELD-SYMBOLS: LIKE LINE OF lt_selection. + + APPEND INITIAL LINE TO lt_selection ASSIGNING . + -selflag = abap_true. + -varoption = zif_abapgit_dot_abapgit=>c_folder_logic-prefix. + + APPEND INITIAL LINE TO lt_selection ASSIGNING . + -varoption = zif_abapgit_dot_abapgit=>c_folder_logic-full. + + APPEND INITIAL LINE TO lt_selection ASSIGNING . + -varoption = zif_abapgit_dot_abapgit=>c_folder_logic-mixed. + + CALL FUNCTION 'POPUP_TO_DECIDE_LIST' + EXPORTING + titel = 'Folder logic' + textline1 = 'Select folder logic' + start_col = ms_position-start_column + start_row = ms_position-start_row + IMPORTING + answer = lv_answer + TABLES + t_spopli = lt_selection + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error from POPUP_TO_DECIDE_LIST' ). + ENDIF. + + IF lv_answer = c_answer_cancel. + zcx_abapgit_cancel=>raise( |Canceled| ). + ENDIF. + + READ TABLE lt_selection ASSIGNING WITH KEY selflag = abap_true. + ASSERT sy-subrc = 0. + + rv_folder_logic = -varoption. + + ENDMETHOD. + METHOD zif_abapgit_popups~popup_search_help. + + DATA lt_ret TYPE TABLE OF ddshretval. + DATA ls_ret LIKE LINE OF lt_ret. + DATA lv_tabname TYPE dfies-tabname. + DATA lv_fieldname TYPE dfies-fieldname. + + SPLIT iv_tab_field AT '-' INTO lv_tabname lv_fieldname. + lv_tabname = to_upper( lv_tabname ). + lv_fieldname = to_upper( lv_fieldname ). + + CALL FUNCTION 'F4IF_FIELD_VALUE_REQUEST' + EXPORTING + tabname = lv_tabname + fieldname = lv_fieldname + TABLES + return_tab = lt_ret + EXCEPTIONS + OTHERS = 5. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |F4IF_FIELD_VALUE_REQUEST error [{ iv_tab_field }]| ). + ENDIF. + + IF lines( lt_ret ) > 0. + READ TABLE lt_ret WITH KEY fieldname = lv_fieldname INTO ls_ret. + IF sy-subrc = 0. + rv_value = ls_ret-fieldval. + ELSE. + READ TABLE lt_ret INDEX 1 INTO ls_ret. + ASSERT sy-subrc = 0. + rv_value = ls_ret-fieldval. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_popups~popup_select_tr_requests. + DATA ls_r_trkorr TYPE LINE OF zif_abapgit_definitions=>ty_trrngtrkor_tt. + DATA lr_request TYPE REF TO trwbo_request_header. + DATA lt_request TYPE trwbo_request_headers. + + ms_position = center( + iv_width = 120 + iv_height = 10 ). + + CALL FUNCTION 'TRINT_SELECT_REQUESTS' + EXPORTING + iv_username_pattern = iv_username_pattern + is_selection = is_selection + iv_complete_projects = abap_false + is_popup = ms_position + iv_via_selscreen = 'X' + iv_title = iv_title + IMPORTING + et_requests = lt_request + EXCEPTIONS + action_aborted_by_user = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Selection canceled' ). + ENDIF. + + IF lt_request IS INITIAL. + zcx_abapgit_exception=>raise( 'No Request Found' ). + ENDIF. + + IF lines( lt_request ) > 10000. + zcx_abapgit_exception=>raise( 'Too many requests selected (max 10000)' ). + ENDIF. + + LOOP AT lt_request REFERENCE INTO lr_request. + ls_r_trkorr-sign = 'I'. + ls_r_trkorr-option = 'EQ'. + ls_r_trkorr-low = lr_request->trkorr. + INSERT ls_r_trkorr INTO TABLE rt_r_trkorr. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_popups~popup_select_wb_tc_tr_and_tsk. + DATA ls_selection TYPE trwbo_selection. + DATA lv_title TYPE trwbo_title. + + ls_selection-trkorrpattern = space. + ls_selection-connect_req_task_conditions = 'X'. + ls_selection-reqfunctions = 'KTRXS'. + ls_selection-reqstatus = 'RNODL'. + ls_selection-taskstatus = 'RNODL'. + CONDENSE ls_selection-reqfunctions NO-GAPS. + ls_selection-taskfunctions = 'QRSX'. + CONCATENATE sy-sysid '*' INTO ls_selection-trkorrpattern. + + lv_title = 'Select Transports / Tasks'. + + rt_r_trkorr = zif_abapgit_popups~popup_select_tr_requests( + is_selection = ls_selection + iv_title = lv_title + iv_username_pattern = '*' ). + ENDMETHOD. + METHOD zif_abapgit_popups~popup_to_confirm. + + ms_position = center( + iv_width = 65 + iv_height = 5 ). + + CALL FUNCTION 'POPUP_TO_CONFIRM' + EXPORTING + titlebar = iv_titlebar + text_question = iv_text_question + text_button_1 = iv_text_button_1 + icon_button_1 = iv_icon_button_1 + text_button_2 = iv_text_button_2 + icon_button_2 = iv_icon_button_2 + default_button = iv_default_button + display_cancel_button = iv_display_cancel_button + popup_type = iv_popup_type + start_column = ms_position-start_column + start_row = ms_position-start_row + IMPORTING + answer = rv_answer + EXCEPTIONS + text_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from POPUP_TO_CONFIRM' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_popups~popup_to_create_transp_branch. + DATA: lt_fields TYPE TABLE OF sval, + lv_transports_as_text TYPE string, + lv_desc_as_text TYPE string. + DATA: lv_branch_name TYPE spo_value. + DATA: lv_commit_text TYPE spo_value. + + CLEAR: rs_transport_branch-branch_name, rs_transport_branch-commit_text. + + lv_transports_as_text = iv_trkorr. + lv_desc_as_text = zcl_abapgit_factory=>get_cts_api( )->read_description( iv_trkorr ). + + add_field( EXPORTING iv_tabname = 'TEXTL' + iv_fieldname = 'LINE' + iv_fieldtext = 'Branch name' + iv_value = lv_transports_as_text + CHANGING ct_fields = lt_fields ). + + add_field( EXPORTING iv_tabname = 'ABAPTXT255' + iv_fieldname = 'LINE' + iv_fieldtext = 'Commit text' + iv_value = lv_desc_as_text + CHANGING ct_fields = lt_fields ). + + _popup_3_get_values( EXPORTING iv_popup_title = 'Transport to new Branch' + IMPORTING ev_value_1 = lv_branch_name + ev_value_2 = lv_commit_text + CHANGING ct_fields = lt_fields ). + + rs_transport_branch-branch_name = lv_branch_name. + rs_transport_branch-commit_text = lv_commit_text. + + ENDMETHOD. + METHOD zif_abapgit_popups~popup_to_select_from_list. + + DATA lo_popup TYPE REF TO kHGwlrVRrOJtQtrmwQhffrvwSNBuVh. + + CLEAR et_list. + + ms_position = center( + iv_width = iv_end_column - iv_start_column + iv_height = iv_end_line - iv_start_line ). + + CREATE OBJECT lo_popup + EXPORTING + it_list = it_list + iv_title = iv_title + iv_header_text = iv_header_text + is_position = ms_position + iv_striped_pattern = iv_striped_pattern + iv_optimize_col_width = iv_optimize_col_width + iv_selection_mode = iv_selection_mode + iv_select_column_text = iv_select_column_text + it_columns_to_display = it_columns_to_display + it_preselected_rows = it_preselected_rows. + + lo_popup->display( ). + lo_popup->get_selected( IMPORTING et_list = et_list ). + + ENDMETHOD. + METHOD zif_abapgit_popups~popup_to_select_labels. + + DATA: + lt_all_labels TYPE zif_abapgit_repo_srv=>ty_labels, + ls_label LIKE LINE OF lt_all_labels, + lt_current_labels TYPE string_table, + lt_selected_labels LIKE lt_all_labels, + lt_columns_to_display TYPE zif_abapgit_popups=>ty_alv_column_tt, + lt_preselected_rows TYPE zif_abapgit_popups=>ty_rows, + ls_columns_to_display LIKE LINE OF lt_columns_to_display, + lv_save_tabix TYPE i, + li_popup TYPE REF TO zif_abapgit_popups. + + FIELD-SYMBOLS: TYPE zif_abapgit_repo_srv=>ty_label, + TYPE LINE OF string_table. + + lt_current_labels = zcl_abapgit_repo_labels=>split( iv_labels ). + + lt_all_labels = zcl_abapgit_repo_srv=>get_instance( )->get_label_list( ). + + " Add labels which are not saved yet + LOOP AT lt_current_labels ASSIGNING . + + READ TABLE lt_all_labels TRANSPORTING NO FIELDS + WITH KEY key_label + COMPONENTS label = . + IF sy-subrc <> 0. + ls_label-label = . + INSERT ls_label INTO TABLE lt_all_labels. + ENDIF. + + ENDLOOP. + + IF lines( lt_all_labels ) = 0. + zcx_abapgit_exception=>raise( |No labels maintained yet| ). + ENDIF. + + SORT lt_all_labels. + DELETE ADJACENT DUPLICATES FROM lt_all_labels. + + " Preselect current labels + LOOP AT lt_all_labels ASSIGNING . + + lv_save_tabix = sy-tabix. + + READ TABLE lt_current_labels TRANSPORTING NO FIELDS + WITH KEY table_line = -label. + IF sy-subrc = 0. + INSERT lv_save_tabix INTO TABLE lt_preselected_rows. + ENDIF. + + ENDLOOP. + + ls_columns_to_display-name = 'LABEL'. + ls_columns_to_display-text = 'Label'. + INSERT ls_columns_to_display INTO TABLE lt_columns_to_display. + + li_popup = zcl_abapgit_ui_factory=>get_popups( ). + li_popup->popup_to_select_from_list( + EXPORTING + iv_header_text = 'Select labels' + iv_select_column_text = 'Add label' + it_list = lt_all_labels + iv_selection_mode = if_salv_c_selection_mode=>multiple + it_columns_to_display = lt_columns_to_display + it_preselected_rows = lt_preselected_rows + iv_start_column = 15 + iv_end_column = 55 + IMPORTING + et_list = lt_selected_labels ). + + LOOP AT lt_selected_labels ASSIGNING . + IF rv_labels IS NOT INITIAL. + rv_labels = rv_labels && ','. + ENDIF. + rv_labels = rv_labels && -label. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_popups~popup_to_select_transport. + + CALL FUNCTION 'TR_F4_REQUESTS' + IMPORTING + ev_selected_request = rv_trkorr. + + ENDMETHOD. + METHOD zif_abapgit_popups~popup_transport_request. + + DATA: lt_e071 TYPE STANDARD TABLE OF e071, + lt_e071k TYPE STANDARD TABLE OF e071k, + lv_order TYPE trkorr, + ls_default TYPE zif_abapgit_default_transport=>ty_get. + DATA lv_category TYPE e070-korrdev. + + " If default transport is set and its type matches, then use it as default for the popup + ls_default = zcl_abapgit_factory=>get_default_transport( )->get( ). + + IF ( ls_default-trfunction = is_transport_type-request OR ls_default-trfunction IS INITIAL ) + AND iv_use_default_transport = abap_true. + lv_order = ls_default-ordernum. + ENDIF. + + " Differentiate between customizing and WB requests + IF is_transport_type-request = zif_abapgit_cts_api=>c_transport_type-cust_request. + lv_category = zif_abapgit_cts_api=>c_transport_category-customizing. + ELSE. + lv_category = zif_abapgit_cts_api=>c_transport_category-workbench. + ENDIF. + + CALL FUNCTION 'TRINT_ORDER_CHOICE' + EXPORTING + wi_order_type = is_transport_type-request + wi_task_type = is_transport_type-task + wi_category = lv_category + wi_order = lv_order + IMPORTING + we_order = rv_transport + TABLES + wt_e071 = lt_e071 + wt_e071k = lt_e071k + EXCEPTIONS + no_correction_selected = 1 + display_mode = 2 + object_append_error = 3 + recursive_call = 4 + wrong_order_type = 5 + OTHERS = 6. + + IF sy-subrc = 1. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ELSEIF sy-subrc > 1. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_popups~tag_list_popup. + + DATA: lo_branches TYPE REF TO zif_abapgit_git_branch_list, + lt_tags TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, + ls_branch TYPE zif_abapgit_git_definitions=>ty_git_branch, + lv_answer TYPE c LENGTH 1, + lv_default TYPE i, + lv_tag TYPE string, + lt_selection TYPE TABLE OF spopli. + + FIELD-SYMBOLS: LIKE LINE OF lt_selection, + LIKE LINE OF lt_tags. + lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). + lt_tags = lo_branches->get_tags_only( ). + + LOOP AT lt_tags ASSIGNING WHERE name NP '*' && zif_abapgit_git_definitions=>c_git_branch-peel. + + APPEND INITIAL LINE TO lt_selection ASSIGNING . + -varoption = zcl_abapgit_git_tag=>remove_tag_prefix( -name ). + + ENDLOOP. + + IF lt_selection IS INITIAL. + zcx_abapgit_exception=>raise( 'No tags are available to select' ). + ENDIF. + + ms_position = center( + iv_width = 30 + iv_height = lines( lt_selection ) ). + + CALL FUNCTION 'POPUP_TO_DECIDE_LIST' + EXPORTING + titel = 'Select Tag' + textline1 = 'Select a tag' + start_col = ms_position-start_column + start_row = ms_position-start_row + cursorline = lv_default + IMPORTING + answer = lv_answer + TABLES + t_spopli = lt_selection + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error from POPUP_TO_DECIDE_LIST' ). + ENDIF. + + IF lv_answer = c_answer_cancel. + RETURN. + ENDIF. + + READ TABLE lt_selection ASSIGNING WITH KEY selflag = abap_true. + ASSERT sy-subrc = 0. + + lv_tag = zcl_abapgit_git_tag=>add_tag_prefix( -varoption ). + + READ TABLE lt_tags WITH KEY name_key COMPONENTS name = lv_tag ASSIGNING . + IF sy-subrc <> 0. + " tag name longer than 65 characters + LOOP AT lt_tags ASSIGNING WHERE name CS lv_tag. + EXIT. + ENDLOOP. + ENDIF. + ASSERT IS ASSIGNED. + + ls_branch = lo_branches->find_by_name( -name ). + MOVE-CORRESPONDING ls_branch TO rs_tag. + + ENDMETHOD. + METHOD _popup_3_get_values. + + DATA lv_answer TYPE c LENGTH 1. + FIELD-SYMBOLS: TYPE sval. + + ms_position = center( + iv_width = 120 + iv_height = lines( ct_fields ) ). + + CALL FUNCTION 'POPUP_GET_VALUES' + EXPORTING + no_value_check = iv_no_value_check + popup_title = iv_popup_title + start_column = ms_position-start_column + start_row = ms_position-start_row + IMPORTING + returncode = lv_answer + TABLES + fields = ct_fields + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error from POPUP_GET_VALUES' ). + ENDIF. + + IF lv_answer = c_answer_cancel. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + IF ev_value_1 IS SUPPLIED. + READ TABLE ct_fields INDEX 1 ASSIGNING . + ASSERT sy-subrc = 0. + ev_value_1 = -value. + ENDIF. + + IF ev_value_2 IS SUPPLIED. + READ TABLE ct_fields INDEX 2 ASSIGNING . + ASSERT sy-subrc = 0. + ev_value_2 = -value. + ENDIF. + + IF ev_value_3 IS SUPPLIED. + READ TABLE ct_fields INDEX 3 ASSIGNING . + ASSERT sy-subrc = 0. + ev_value_3 = -value. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_password_dialog IMPLEMENTATION. + METHOD popup. + + DATA: lx_error TYPE REF TO cx_sy_dyn_call_illegal_form. + + IF zcl_abapgit_ui_factory=>get_frontend_services( )->gui_is_available( ) = abap_true. + + TRY. + PERFORM password_popup + IN PROGRAM (sy-cprog) + USING iv_repo_url + CHANGING cv_user cv_pass. + CATCH cx_sy_dyn_call_illegal_form INTO lx_error. + " abapGit was called via API and either wrong or no username/password + " was supplied. It's not possible to call abapGit password popup in + " this case. + " See https://docs.abapgit.org/development/api.html#online-repository + " on how to provide username/password + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ELSE. + "Extract user credentials from the environment... + "Class ZCL_ABAPGIT_DEFAULT_AUTH_INFO is part of https://github.com/abapGit/ADT_Backend. + "It stores the credentials of a private repository as long as the session exists. + "Usually this class should belong to abapGit core and a refactoring is recommended. + "As a temporary solution - and to avoid a DYNPRO_SEND_IN_BACKGROUND dump - a generic + "call of the getter methods for username and password is implemented by PR#2635. + TRY. + CALL METHOD ('ZCL_ABAPGIT_DEFAULT_AUTH_INFO')=>('GET_USER') + RECEIVING + rv_user = cv_user. + CATCH cx_root. + RETURN. + ENDTRY. + TRY. + CALL METHOD ('ZCL_ABAPGIT_DEFAULT_AUTH_INFO')=>('GET_PASSWORD') + RECEIVING + rv_password = cv_pass. + CATCH cx_root. + "check if old version with typo in method name exists + TRY. + CALL METHOD ('ZCL_ABAPGIT_DEFAULT_AUTH_INFO')=>('GET_PASSOWORD') + RECEIVING + rv_password = cv_pass. + CATCH cx_root. + RETURN. + ENDTRY. + ENDTRY. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_hotkey_ctl IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + ms_user_settings = zcl_abapgit_persist_factory=>get_user( )->get_settings( ). + + ENDMETHOD. + METHOD render_scripts. + + DATA lv_json TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF it_hotkeys. + + lv_json = `{`. + + LOOP AT it_hotkeys ASSIGNING . + + IF sy-tabix > 1. + lv_json = lv_json && |,|. + ENDIF. + + lv_json = lv_json && | "{ -hotkey }" : "{ -action }" |. + + ENDLOOP. + + lv_json = lv_json && `}`. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). + ri_html->add( |setKeyBindings({ lv_json });| ). + + ENDMETHOD. + METHOD should_show_hint. + IF gv_hint_was_shown = abap_false. + rv_yes = abap_true. + gv_hint_was_shown = abap_true. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA ls_hotkey LIKE LINE OF rt_hotkey_actions. + + ls_hotkey-ui_component = 'Hotkeys'. + ls_hotkey-action = c_showhotkeys_action. + ls_hotkey-description = 'Show Hotkeys Help'. + ls_hotkey-hotkey = '?'. + INSERT ls_hotkey INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkey_ctl~get_registered_hotkeys. + rt_registered_hotkeys = mt_hotkeys. + ENDMETHOD. + METHOD zif_abapgit_gui_hotkey_ctl~register_hotkeys. + + FIELD-SYMBOLS LIKE LINE OF it_hotkeys. + + " Compress duplicates + LOOP AT it_hotkeys ASSIGNING . + READ TABLE mt_hotkeys WITH KEY hotkey = -hotkey TRANSPORTING NO FIELDS. + IF sy-subrc = 0. " If found command with same hotkey + DELETE mt_hotkeys INDEX sy-tabix. " Later registered commands enjoys the priority + ENDIF. + + IF ms_user_settings-link_hints_enabled = abap_true AND + ms_user_settings-link_hint_key = -hotkey. + " Link hint activation key is more important + CONTINUE. + ENDIF. + + APPEND TO mt_hotkeys. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkey_ctl~reset. + CLEAR mt_hotkeys. + ENDMETHOD. + METHOD zif_abapgit_gui_hotkey_ctl~set_visible. + + mv_visible = iv_visible. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA: + lv_hint TYPE string, + lt_registered_hotkeys TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr, + lv_hotkey TYPE string, + ls_user_settings TYPE zif_abapgit_persist_user=>ty_s_user_settings. + + FIELD-SYMBOLS LIKE LINE OF lt_registered_hotkeys. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + lt_registered_hotkeys = zif_abapgit_gui_hotkey_ctl~get_registered_hotkeys( ). + SORT lt_registered_hotkeys BY ui_component description. + + register_deferred_script( render_scripts( lt_registered_hotkeys ) ). + + " Render hotkeys + ri_html->add( '
        ' ). + LOOP AT lt_registered_hotkeys ASSIGNING . + ri_html->add( |
      • | + && |{ -hotkey }| + && |{ -description }| + && |
      • | ). + ENDLOOP. + + " render link hints activation key + ls_user_settings = zcl_abapgit_persist_factory=>get_user( )->get_settings( ). + IF ls_user_settings-link_hints_enabled = abap_true. + ri_html->add( |
      • | + && |{ ls_user_settings-link_hint_key }| + && |Link Hints| + && |
      • | ). + ri_html->add( |
      • | + && |y{ ls_user_settings-link_hint_key }| + && |Copy Link Text| + && |
      • | ). + ENDIF. + + ri_html->add( '
      ' ). + + CLEAR lv_hotkey. + + READ TABLE lt_registered_hotkeys ASSIGNING + WITH KEY action = c_showhotkeys_action. + IF sy-subrc = 0. + lv_hotkey = -hotkey. + ENDIF. + + lv_hint = |Close window with upper right corner 'X'|. + IF lv_hotkey IS NOT INITIAL. + lv_hint = lv_hint && | or press '{ -hotkey }'|. + ENDIF. + + ri_html = zcl_abapgit_gui_chunk_lib=>render_infopanel( + iv_div_id = 'hotkeys' + iv_title = 'Hotkeys' + iv_hint = lv_hint + iv_hide = boolc( mv_visible = abap_false ) + iv_scrollable = abap_false + io_content = ri_html ). + + IF lv_hotkey IS NOT INITIAL AND should_show_hint( ) = abap_true. + ri_html->add( |
      | + && |Press '{ -hotkey }' to get keyboard shortcuts list| + && |
      | ). + ENDIF. + + " Always reset visibility here. Closing of the popup has to be done by the + " user and is handled in JS. + mv_visible = abap_false. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_frontend_services IMPLEMENTATION. + METHOD get_path_from_fullname. + + DATA lv_len TYPE i. + + FIND FIRST OCCURRENCE OF REGEX '^/(.*/)?' IN iv_fullname MATCH LENGTH lv_len. + IF sy-subrc = 0. + rv_path = iv_fullname(lv_len). + ELSE. + FIND FIRST OCCURRENCE OF REGEX '^(.*\\)?' IN iv_fullname MATCH LENGTH lv_len. + IF sy-subrc = 0. + rv_path = iv_fullname(lv_len). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~clipboard_export. + + DATA lv_rc TYPE i. + + " Note: do not use a string table for 'it_data'! + + TRY. + CALL METHOD cl_gui_frontend_services=>('CLIPBOARD_EXPORT') + EXPORTING + no_auth_check = iv_no_auth_check " >= 740 + IMPORTING + data = it_data + CHANGING + rc = lv_rc + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + no_authority = 4 + OTHERS = 5. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CATCH cx_sy_dyn_call_param_missing. + + cl_gui_frontend_services=>clipboard_export( + IMPORTING + data = it_data + CHANGING + rc = lv_rc + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + no_authority = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~directory_browse. + + IF iv_initial_folder IS NOT INITIAL. + gv_initial_folder = iv_initial_folder. + ENDIF. + + cl_gui_frontend_services=>directory_browse( + EXPORTING + window_title = iv_window_title + initial_folder = gv_initial_folder + CHANGING + selected_folder = cv_selected_folder + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + gv_initial_folder = cv_selected_folder. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~directory_create. + + cl_gui_frontend_services=>directory_create( + EXPORTING + directory = iv_directory + CHANGING + rc = cv_rc + EXCEPTIONS + directory_create_failed = 1 + cntl_error = 2 + error_no_gui = 3 + directory_access_denied = 4 + directory_already_exists = 5 + path_not_found = 6 + unknown_error = 7 + not_supported_by_gui = 8 + wrong_parameter = 9 + OTHERS = 10 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~directory_exist. + + cl_gui_frontend_services=>directory_exist( + EXPORTING + directory = iv_directory + RECEIVING + result = rv_exists + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + wrong_parameter = 3 + not_supported_by_gui = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~execute. + + cl_gui_frontend_services=>execute( + EXPORTING + document = iv_document + application = iv_application + parameter = iv_parameter + default_directory = iv_default_directory + maximized = iv_maximized + minimized = iv_minimized + synchronous = iv_synchronous + operation = iv_operation + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + bad_parameter = 3 + file_not_found = 4 + path_not_found = 5 + file_extension_unknown = 6 + error_execute_failed = 7 + synchronous_failed = 8 + not_supported_by_gui = 9 + OTHERS = 10 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~file_download. + + TYPES ty_hex TYPE x LENGTH 200. + DATA lt_rawdata TYPE STANDARD TABLE OF ty_hex WITH DEFAULT KEY. + + zcl_abapgit_convert=>xstring_to_bintab( + EXPORTING iv_xstr = iv_xstr + IMPORTING et_bintab = lt_rawdata ). + + cl_gui_frontend_services=>gui_download( + EXPORTING + bin_filesize = xstrlen( iv_xstr ) + filename = iv_path + filetype = 'BIN' + CHANGING + data_tab = lt_rawdata + EXCEPTIONS + file_write_error = 1 + no_batch = 2 + gui_refuse_filetransfer = 3 + invalid_type = 4 + no_authority = 5 + unknown_error = 6 + header_not_allowed = 7 + separator_not_allowed = 8 + filesize_not_allowed = 9 + header_too_long = 10 + dp_error_create = 11 + dp_error_send = 12 + dp_error_write = 13 + unknown_dp_error = 14 + access_denied = 15 + dp_out_of_memory = 16 + disk_full = 17 + dp_timeout = 18 + file_not_found = 19 + dataprovider_exception = 20 + control_flush_error = 21 + not_supported_by_gui = 22 + error_no_gui = 23 + OTHERS = 24 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~file_upload. + + TYPES: ty_hex TYPE x LENGTH 255. + + DATA: lt_data TYPE TABLE OF ty_hex WITH DEFAULT KEY, + lv_length TYPE i. + + cl_gui_frontend_services=>gui_upload( + EXPORTING + filename = iv_path + filetype = 'BIN' + IMPORTING + filelength = lv_length + CHANGING + data_tab = lt_data + EXCEPTIONS + file_open_error = 1 + file_read_error = 2 + no_batch = 3 + gui_refuse_filetransfer = 4 + invalid_type = 5 + no_authority = 6 + unknown_error = 7 + bad_data_format = 8 + header_not_allowed = 9 + separator_not_allowed = 10 + header_too_long = 11 + unknown_dp_error = 12 + access_denied = 13 + dp_out_of_memory = 14 + disk_full = 15 + dp_timeout = 16 + not_supported_by_gui = 17 + error_no_gui = 18 + OTHERS = 19 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CONCATENATE LINES OF lt_data INTO rv_xstr IN BYTE MODE. + rv_xstr = rv_xstr(lv_length). + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~get_file_separator. + + cl_gui_frontend_services=>get_file_separator( + CHANGING + file_separator = cv_file_separator + EXCEPTIONS + not_supported_by_gui = 1 + error_no_gui = 2 + cntl_error = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~get_gui_version. + + DATA: + lt_version_table TYPE filetable, + lv_rc TYPE i, + ls_version LIKE LINE OF lt_version_table. + + cl_gui_frontend_services=>get_gui_version( + CHANGING + version_table = lt_version_table + rc = lv_rc + EXCEPTIONS + get_gui_version_failed = 1 + cant_write_version_table = 2 + gui_no_version = 3 + cntl_error = 4 + error_no_gui = 5 + not_supported_by_gui = 6 + OTHERS = 7 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + READ TABLE lt_version_table INTO ls_version INDEX 1. " gui release + ev_gui_release = ls_version-filename. + READ TABLE lt_version_table INTO ls_version INDEX 2. " gui sp + ev_gui_sp = ls_version-filename. + READ TABLE lt_version_table INTO ls_version INDEX 3. " gui patch + ev_gui_patch = ls_version-filename. + + ev_gui_version_string = |{ ev_gui_release }.{ condense( ev_gui_sp ) }.{ condense( ev_gui_patch ) }|. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~get_system_directory. + + cl_gui_frontend_services=>get_system_directory( + CHANGING + system_directory = cv_system_directory + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~gui_is_available. + + TRY. + CALL FUNCTION 'GUI_IS_AVAILABLE' + IMPORTING + return = rv_gui_is_available. + CATCH cx_sy_dyn_call_illegal_func. +* when running on open-abap + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~is_sapgui_for_java. + + TRY. + CALL FUNCTION 'GUI_HAS_JAVABEANS' + IMPORTING + return = rv_result. + CATCH cx_sy_dyn_call_illegal_func. +* when running on open-abap + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~is_sapgui_for_windows. + + TRY. + CALL FUNCTION 'GUI_HAS_ACTIVEX' + IMPORTING + return = rv_result. + CATCH cx_sy_dyn_call_illegal_func. +* when running on open-abap + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~is_webgui. + + TRY. + CALL FUNCTION 'GUI_IS_ITS' + IMPORTING + return = rv_is_webgui. + CATCH cx_sy_dyn_call_illegal_func. +* when running on open-abap + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~open_ie_devtools. + + DATA: lv_system_directory TYPE string, + lv_exe_full_path TYPE string. + + IF zif_abapgit_frontend_services~is_sapgui_for_windows( ) = abap_false. + zcx_abapgit_exception=>raise( |IE DevTools not supported on frontend OS| ). + ENDIF. + + zif_abapgit_frontend_services~get_system_directory( CHANGING cv_system_directory = lv_system_directory ). + + cl_gui_cfw=>flush( ). + + lv_exe_full_path = lv_system_directory && `\F12\IEChooser.exe`. + + zif_abapgit_frontend_services~execute( iv_application = lv_exe_full_path ). + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~show_file_open_dialog. + + DATA: + lt_file_table TYPE filetable, + ls_file_table LIKE LINE OF lt_file_table, + lv_filter TYPE string, + lv_action TYPE i, + lv_rc TYPE i. + + IF iv_extension = 'zip'. + lv_filter = 'ZIP Files (*.zip)|*.zip|' && cl_gui_frontend_services=>filetype_all. + ENDIF. + + cl_gui_frontend_services=>file_open_dialog( + EXPORTING + window_title = iv_title + default_filename = iv_default_filename + file_filter = lv_filter + initial_directory = gv_initial_folder + CHANGING + file_table = lt_file_table + rc = lv_rc + user_action = lv_action + EXCEPTIONS + file_open_dialog_failed = 1 + cntl_error = 2 + error_no_gui = 3 + not_supported_by_gui = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + IF lv_action = cl_gui_frontend_services=>action_cancel. + zcx_abapgit_exception=>raise( 'Cancelled' ). + ENDIF. + + READ TABLE lt_file_table INDEX 1 INTO ls_file_table. + ASSERT sy-subrc = 0. + rv_path = ls_file_table-filename. + + gv_initial_folder = get_path_from_fullname( rv_path ). + + ENDMETHOD. + METHOD zif_abapgit_frontend_services~show_file_save_dialog. + + DATA: + lv_action TYPE i, + lv_filter TYPE string, + lv_filename TYPE string, + lv_path TYPE string. + + IF iv_extension = 'zip'. + lv_filter = 'ZIP Files (*.zip)|*.zip|' && cl_gui_frontend_services=>filetype_all. + ENDIF. + + cl_gui_frontend_services=>file_save_dialog( + EXPORTING + window_title = iv_title + default_extension = iv_extension + default_file_name = iv_default_filename + file_filter = lv_filter + initial_directory = gv_initial_folder + CHANGING + filename = lv_filename + path = lv_path + fullpath = rv_path + user_action = lv_action + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + IF lv_action = cl_gui_frontend_services=>action_cancel. + zcx_abapgit_exception=>raise( 'Cancelled' ). + ENDIF. + + gv_initial_folder = lv_path. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_frontend_no_gui IMPLEMENTATION. + METHOD zif_abapgit_frontend_services~clipboard_export. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~directory_browse. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~directory_create. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~directory_exist. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~execute. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~file_download. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~file_upload. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~get_file_separator. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~get_gui_version. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~get_system_directory. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~gui_is_available. + rv_gui_is_available = abap_false. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~is_sapgui_for_java. + rv_result = abap_false. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~is_sapgui_for_windows. + rv_result = abap_false. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~is_webgui. + rv_is_webgui = abap_false. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~open_ie_devtools. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~show_file_open_dialog. + ENDMETHOD. + METHOD zif_abapgit_frontend_services~show_file_save_dialog. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_services_repo IMPLEMENTATION. + METHOD activate_objects. + + DATA: + li_repo TYPE REF TO zif_abapgit_repo, + lo_browser TYPE REF TO zcl_abapgit_repo_content_list, + lt_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt, + lv_count TYPE i, + lv_message TYPE string. + + FIELD-SYMBOLS LIKE LINE OF lt_repo_items. + + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + + CREATE OBJECT lo_browser + EXPORTING + ii_repo = li_repo. + + lt_repo_items = lo_browser->list( '/' ). + + ri_log = li_repo->create_new_log( 'Activation Log' ). + + " Add all inactive objects to activation queue + zcl_abapgit_objects_activation=>clear( ). + + LOOP AT lt_repo_items ASSIGNING WHERE inactive = abap_true. + zcl_abapgit_objects_activation=>add( + iv_type = -obj_type + iv_name = -obj_name ). + lv_count = lv_count + 1. + ENDLOOP. + + IF lv_count = 0. + MESSAGE 'No inactive objects found' TYPE 'S'. + RETURN. + ENDIF. + + " Activate DDIC + non-DDIC + zcl_abapgit_objects_activation=>activate( + iv_ddic = abap_true + ii_log = ri_log ). + + zcl_abapgit_objects_activation=>activate( + iv_ddic = abap_false + ii_log = ri_log ). + + IF ri_log->get_status( ) <> zif_abapgit_log=>c_status-error. + lv_message = |Successfully activated { lv_count } objects|. + MESSAGE lv_message TYPE 'S'. + ENDIF. + + li_repo->refresh( iv_drop_log = abap_false ). + + ENDMETHOD. + METHOD check_for_restart. + + CONSTANTS: + lc_abapgit_prog TYPE progname VALUE `ZABAPGIT`. + + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + + IF ii_repo->is_offline( ) = abap_true. + RETURN. + ENDIF. + + li_repo_online ?= ii_repo. + + " If abapGit was used to update itself, then restart to avoid LOAD_PROGRAM_&_MISMATCH dumps + " because abapGit code was changed at runtime + IF zcl_abapgit_ui_factory=>get_frontend_services( )->gui_is_available( ) = abap_true AND + zcl_abapgit_url=>is_abapgit_repo( li_repo_online->get_url( ) ) = abap_true AND + sy-batch = abap_false AND + sy-cprog = lc_abapgit_prog. + + IF zcl_abapgit_persist_factory=>get_settings( )->read( )->get_show_default_repo( ) = abap_false. + MESSAGE 'abapGit was updated and will restart itself' TYPE 'I'. + ENDIF. + + SUBMIT (sy-cprog). + + ENDIF. + + ENDMETHOD. + METHOD check_package. + + DATA: + li_repo TYPE REF TO zif_abapgit_repo, + li_repo_srv TYPE REF TO zif_abapgit_repo_srv, + lv_reason TYPE string. + + " make sure package is not already in use for a different repository + " 702: chaining calls with exp&imp parameters causes syntax error + li_repo_srv = zcl_abapgit_repo_srv=>get_instance( ). + li_repo_srv->get_repo_from_package( + EXPORTING + iv_package = is_repo_params-package + iv_ign_subpkg = is_repo_params-ignore_subpackages + IMPORTING + ei_repo = li_repo + ev_reason = lv_reason ). + + IF li_repo IS BOUND. + zcx_abapgit_exception=>raise( lv_reason ). + ENDIF. + + ENDMETHOD. + METHOD check_package_exists. + + IF zcl_abapgit_factory=>get_sap_package( iv_package )->exists( ) = abap_false. + " Check if any package is included in remote + READ TABLE it_remote TRANSPORTING NO FIELDS + WITH KEY file + COMPONENTS filename = zcl_abapgit_filename_logic=>c_package_file. + IF sy-subrc <> 0. + " If not, give error + zcx_abapgit_exception=>raise( + iv_text = |Package { iv_package } does not exist and there's no package included in the repository| + iv_longtext = 'Either select an existing package, create a new one, or add a package to the repository' ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD delete_unnecessary_objects. + + DATA: + ls_checks TYPE zif_abapgit_definitions=>ty_delete_checks, + ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, + lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + + FIELD-SYMBOLS LIKE LINE OF is_checks-overwrite. + + " get confirmed deletions + LOOP AT is_checks-overwrite ASSIGNING + WHERE ( action = zif_abapgit_objects=>c_deserialize_action-delete + OR action = zif_abapgit_objects=>c_deserialize_action-delete_add ) + AND decision = zif_abapgit_definitions=>c_yes. + + ls_tadir-pgmid = 'R3TR'. + ls_tadir-object = -obj_type. + ls_tadir-obj_name = -obj_name. + ls_tadir-devclass = -devclass. + INSERT ls_tadir INTO TABLE lt_tadir. + + ENDLOOP. + + " todo, check if object type supports deletion of parts to avoid deleting complete object + + " delete objects + IF lines( lt_tadir ) > 0. + ls_checks-transport = is_checks-transport. + + zcl_abapgit_objects=>delete( it_tadir = lt_tadir + is_checks = ls_checks + ii_log = ii_log ). + + ii_repo->refresh( iv_drop_log = abap_false ). + ENDIF. + + ENDMETHOD. + METHOD gui_deserialize. + + DATA ls_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks. + + " find troublesome objects + ls_checks = ii_repo->deserialize_checks( ). + + IF ls_checks-overwrite IS INITIAL. + zcx_abapgit_exception=>raise( + 'There is nothing to pull. The local state completely matches the remote repository.' ). + ENDIF. + + " let the user decide what to do + TRY. + popup_decisions( + EXPORTING + ii_repo = ii_repo + CHANGING + cs_checks = ls_checks ). + + CATCH zcx_abapgit_cancel. + RETURN. + ENDTRY. + + real_deserialize( + ii_repo = ii_repo + is_checks = ls_checks ). + + ENDMETHOD. + METHOD new_offline. + + check_package( is_repo_params ). + + " create new repo and add to favorites + ri_repo = zcl_abapgit_repo_srv=>get_instance( )->new_offline( + iv_name = is_repo_params-name + iv_package = is_repo_params-package + iv_folder_logic = is_repo_params-folder_logic + iv_labels = is_repo_params-labels + iv_ign_subpkg = is_repo_params-ignore_subpackages + iv_main_lang_only = is_repo_params-main_lang_only + iv_abap_lang_vers = is_repo_params-abap_lang_vers ). + + " Make sure there're no leftovers from previous repos + ri_repo->checksums( )->rebuild( ). + + toggle_favorite( ri_repo->get_key( ) ). + + " Set default repo for user + zcl_abapgit_persist_factory=>get_user( )->set_repo_show( ri_repo->get_key( ) ). + + COMMIT WORK AND WAIT. + + ENDMETHOD. + METHOD new_online. + + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA lx_error TYPE REF TO zcx_abapgit_exception. + + check_package( is_repo_params ). + + li_repo = zcl_abapgit_repo_srv=>get_instance( )->new_online( + iv_url = is_repo_params-url + iv_branch_name = is_repo_params-branch_name + iv_name = is_repo_params-name + iv_package = is_repo_params-package + iv_display_name = is_repo_params-display_name + iv_folder_logic = is_repo_params-folder_logic + iv_labels = is_repo_params-labels + iv_ign_subpkg = is_repo_params-ignore_subpackages + iv_main_lang_only = is_repo_params-main_lang_only + iv_abap_lang_vers = is_repo_params-abap_lang_vers ). + + TRY. + check_package_exists( + iv_package = is_repo_params-package + it_remote = li_repo->get_files_remote( ) ). + CATCH zcx_abapgit_exception INTO lx_error. + zcl_abapgit_repo_srv=>get_instance( )->delete( li_repo ). + COMMIT WORK. + RAISE EXCEPTION lx_error. + ENDTRY. + + " Make sure there're no leftovers from previous repos + li_repo->checksums( )->rebuild( ). + + toggle_favorite( li_repo->get_key( ) ). + + " Set default repo for user + zcl_abapgit_persist_factory=>get_user( )->set_repo_show( li_repo->get_key( ) ). + + COMMIT WORK AND WAIT. + + ri_repo_online ?= li_repo. + + ENDMETHOD. + METHOD popup_data_loss_overwrite. + + DATA: lt_columns TYPE zif_abapgit_popups=>ty_alv_column_tt, + lt_selected LIKE ct_data_loss, + li_popups TYPE REF TO zif_abapgit_popups. + DATA lt_preselected_rows TYPE zif_abapgit_popups=>ty_rows. + + FIELD-SYMBOLS: LIKE LINE OF it_overwrite, + LIKE LINE OF ct_data_loss, + TYPE zif_abapgit_popups=>ty_alv_column. + + LOOP AT it_overwrite ASSIGNING WHERE decision <> zif_abapgit_definitions=>c_yes. + DELETE ct_data_loss WHERE obj_type = -obj_type AND obj_name = -obj_name. + ENDLOOP. + + IF lines( ct_data_loss ) = 0. + RETURN. + ENDIF. + + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'OBJ_TYPE'. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'OBJ_NAME'. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'ICON'. + -text = 'Action'. + -show_icon = abap_true. + -length = 5. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'TEXT'. + -text = 'Description'. + + LOOP AT ct_data_loss ASSIGNING WHERE decision = zif_abapgit_definitions=>c_yes. + INSERT sy-tabix INTO TABLE lt_preselected_rows. + ENDLOOP. + + li_popups = zcl_abapgit_ui_factory=>get_popups( ). + li_popups->popup_to_select_from_list( + EXPORTING + it_list = ct_data_loss + iv_header_text = |Changes to the following objects could lead to DATA LOSS!| + && | Select the objects which should be changed to the remote version, anyway.| + iv_select_column_text = 'Overwrite?' + it_columns_to_display = lt_columns + it_preselected_rows = lt_preselected_rows + IMPORTING + et_list = lt_selected ). + + LOOP AT ct_data_loss ASSIGNING . + READ TABLE lt_selected WITH TABLE KEY object_type_and_name + COMPONENTS obj_type = -obj_type + obj_name = -obj_name + TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + -decision = zif_abapgit_definitions=>c_yes. + ELSE. + -decision = zif_abapgit_definitions=>c_no. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD popup_decisions. + + DATA: + lt_decision TYPE zif_abapgit_definitions=>ty_overwrite_tt, + lt_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt, + lt_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies. + + FIELD-SYMBOLS: + LIKE LINE OF cs_checks-overwrite, + LIKE LINE OF lt_decision. + + lt_decision = cs_checks-overwrite. + + " If there's a new namespace, it has to be pulled before all other objects + READ TABLE lt_decision ASSIGNING WITH KEY obj_type = 'NSPC'. + IF sy-subrc = 0 AND -action = zif_abapgit_objects=>c_deserialize_action-add. + -decision = zif_abapgit_definitions=>c_yes. + ELSE. + " Set all new objects to YES + LOOP AT lt_decision ASSIGNING WHERE action = zif_abapgit_objects=>c_deserialize_action-add. + -decision = zif_abapgit_definitions=>c_yes. + ENDLOOP. + ENDIF. + + " Ask user what to do + IF cs_checks-requirements-met = zif_abapgit_definitions=>c_no. + lt_requirements = ii_repo->get_dot_abapgit( )->get_data( )-requirements. + zcl_abapgit_repo_requirements=>requirements_popup( lt_requirements ). + cs_checks-requirements-decision = zif_abapgit_definitions=>c_yes. + ENDIF. + + IF cs_checks-dependencies-met = zif_abapgit_definitions=>c_no. + lt_dependencies = ii_repo->get_dot_apack( )->get_manifest_descriptor( )-dependencies. + zcl_abapgit_apack_helper=>dependencies_popup( lt_dependencies ). + cs_checks-dependencies-decision = zif_abapgit_definitions=>c_yes. + ENDIF. + + popup_objects_overwrite( CHANGING ct_overwrite = lt_decision ). + + popup_data_loss_overwrite( + EXPORTING + it_overwrite = lt_decision + CHANGING + ct_data_loss = cs_checks-data_loss ). + + popup_package_overwrite( CHANGING ct_overwrite = cs_checks-warning_package ). + + IF cs_checks-transport-required = abap_true AND cs_checks-transport-transport IS INITIAL. + cs_checks-transport-transport = + zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( cs_checks-transport-type ). + ENDIF. + + " Update decisions + LOOP AT cs_checks-overwrite ASSIGNING . + READ TABLE lt_decision ASSIGNING WITH KEY object_type_and_name COMPONENTS + obj_type = -obj_type + obj_name = -obj_name. + ASSERT sy-subrc = 0. + -decision = -decision. + ENDLOOP. + + ENDMETHOD. + METHOD popup_objects_overwrite. + + DATA: lt_columns TYPE zif_abapgit_popups=>ty_alv_column_tt, + lt_selected LIKE ct_overwrite, + li_popups TYPE REF TO zif_abapgit_popups. + DATA lt_preselected_rows TYPE zif_abapgit_popups=>ty_rows. + + FIELD-SYMBOLS: LIKE LINE OF ct_overwrite, + TYPE zif_abapgit_popups=>ty_alv_column. + IF lines( ct_overwrite ) = 0. + RETURN. + ENDIF. + + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'OBJ_TYPE'. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'OBJ_NAME'. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'DEVCLASS'. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'STATE'. + -text = 'State'. + -length = 3. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'ICON'. + -text = 'Action'. + -show_icon = abap_true. + -length = 5. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'TEXT'. + -text = 'Description'. + + LOOP AT ct_overwrite ASSIGNING WHERE decision = zif_abapgit_definitions=>c_yes. + INSERT sy-tabix INTO TABLE lt_preselected_rows. + ENDLOOP. + + li_popups = zcl_abapgit_ui_factory=>get_popups( ). + li_popups->popup_to_select_from_list( + EXPORTING + it_list = ct_overwrite + iv_header_text = |The following objects are different between local and remote repository.| + && | Select the objects which should be brought in line with the remote version.| + iv_select_column_text = 'Change?' + it_columns_to_display = lt_columns + it_preselected_rows = lt_preselected_rows + IMPORTING + et_list = lt_selected ). + + LOOP AT ct_overwrite ASSIGNING . + READ TABLE lt_selected WITH TABLE KEY object_type_and_name + COMPONENTS obj_type = -obj_type + obj_name = -obj_name + TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + -decision = zif_abapgit_definitions=>c_yes. + ELSE. + -decision = zif_abapgit_definitions=>c_no. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD popup_package_overwrite. + + DATA: lt_columns TYPE zif_abapgit_popups=>ty_alv_column_tt, + lt_selected LIKE ct_overwrite, + li_popups TYPE REF TO zif_abapgit_popups. + + FIELD-SYMBOLS: LIKE LINE OF ct_overwrite, + TYPE zif_abapgit_popups=>ty_alv_column. + + IF lines( ct_overwrite ) = 0. + RETURN. + ENDIF. + + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'OBJ_TYPE'. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'OBJ_NAME'. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'DEVCLASS'. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'STATE'. + -text = 'State'. + -length = 3. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'ICON'. + -text = 'Action'. + -show_icon = abap_true. + -length = 5. + APPEND INITIAL LINE TO lt_columns ASSIGNING . + -name = 'TEXT'. + -text = 'Description'. + + li_popups = zcl_abapgit_ui_factory=>get_popups( ). + li_popups->popup_to_select_from_list( + EXPORTING + it_list = ct_overwrite + iv_header_text = |The following objects have been created in other packages.| + && | Select the objects which should be overwritten.| + iv_select_column_text = |Overwrite?| + it_columns_to_display = lt_columns + IMPORTING + et_list = lt_selected ). + + LOOP AT ct_overwrite ASSIGNING . + + READ TABLE lt_selected WITH TABLE KEY object_type_and_name + COMPONENTS obj_type = -obj_type + obj_name = -obj_name + TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + -decision = zif_abapgit_definitions=>c_yes. + ELSE. + -decision = zif_abapgit_definitions=>c_no. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD purge. + + DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, + lv_answer TYPE c LENGTH 1, + li_repo TYPE REF TO zif_abapgit_repo, + lv_package TYPE devclass, + lv_title TYPE c LENGTH 20, + lv_question TYPE c LENGTH 150, + ls_checks TYPE zif_abapgit_definitions=>ty_delete_checks, + lv_repo_name TYPE string, + lv_message TYPE string. + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + lv_repo_name = li_repo->get_name( ). + + lv_package = li_repo->get_package( ). + lt_tadir = li_repo->get_tadir_objects( ). + + IF lines( lt_tadir ) > 0. + + lv_question = |This will DELETE all objects in package { lv_package + } including subpackages ({ lines( lt_tadir ) } objects) from the system|. + + IF iv_keep_repo = abap_true. + lv_title = 'Remove Objects'. + lv_question = lv_question && ', but keep the reference to the repository'. + ELSE. + lv_title = 'Uninstall'. + lv_question = lv_question && ' and remove the reference to the repository'. + ENDIF. + + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_titlebar = lv_title + iv_text_question = lv_question + iv_text_button_1 = 'Delete' + iv_icon_button_1 = 'ICON_DELETE' + iv_text_button_2 = 'Cancel' + iv_icon_button_2 = 'ICON_CANCEL' + iv_default_button = '2' + iv_popup_type = 'ICON_MESSAGE_WARNING' + iv_display_cancel_button = abap_false ). + + IF lv_answer = '2'. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + ENDIF. + + ls_checks = li_repo->delete_checks( ). + IF ls_checks-transport-required = abap_true. + ls_checks-transport-transport = zcl_abapgit_ui_factory=>get_popups( + )->popup_transport_request( ls_checks-transport-type ). + ENDIF. + + ri_log = zcl_abapgit_repo_srv=>get_instance( )->purge( + ii_repo = li_repo + is_checks = ls_checks + iv_keep_repo = iv_keep_repo ). + + COMMIT WORK. + + IF ri_log IS BOUND AND ri_log->get_status( ) = zif_abapgit_log=>c_status-error. + zcl_abapgit_log_viewer=>show_log( ri_log ). + RETURN. + ENDIF. + + lv_message = |Repository { lv_repo_name } successfully uninstalled from Package { lv_package }. |. + MESSAGE lv_message TYPE 'S'. + + ENDMETHOD. + METHOD real_deserialize. + + DATA li_log TYPE REF TO zif_abapgit_log. + DATA lv_msg TYPE string. + + li_log = ii_repo->create_new_log( 'Pull Log' ). + + " pass decisions to delete + delete_unnecessary_objects( + ii_repo = ii_repo + is_checks = is_checks + ii_log = li_log ). + + " pass decisions to deserialize + ii_repo->deserialize( + is_checks = is_checks + ii_log = li_log ). + + IF li_log->get_status( ) = zif_abapgit_log=>c_status-ok. + lv_msg = |Repository { ii_repo->get_name( ) } successfully pulled for package { ii_repo->get_package( ) }|. + MESSAGE lv_msg TYPE 'S'. + ENDIF. + + check_for_restart( ii_repo ). + + ENDMETHOD. + METHOD refresh. + + zcl_abapgit_repo_srv=>get_instance( )->get( iv_key )->refresh( ). + + ENDMETHOD. + METHOD refresh_local_checksums. + + DATA: lv_answer TYPE c, + lv_question TYPE string, + li_repo TYPE REF TO zif_abapgit_repo. + IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-update_local_checksum ) = abap_false. + zcx_abapgit_exception=>raise( 'Not authorized' ). + ENDIF. + + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + + lv_question = 'This will rebuild and overwrite local repo checksums.'. + + IF li_repo->is_offline( ) = abap_false. + lv_question = lv_question + && ' The logic: if local and remote file differs then:' + && ' if remote branch is ahead then assume changes are remote,' + && ' else (branches are equal) assume changes are local.' + && ' This will lead to incorrect state for files changed on both sides.' + && ' Please make sure you don''t have ones like that.'. + ENDIF. + + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_titlebar = 'Warning' + iv_text_question = lv_question + iv_text_button_1 = 'OK' + iv_icon_button_1 = 'ICON_DELETE' + iv_text_button_2 = 'Cancel' + iv_icon_button_2 = 'ICON_CANCEL' + iv_default_button = '2' + iv_display_cancel_button = abap_false ). + + IF lv_answer = '2'. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + li_repo->checksums( )->rebuild( ). + + COMMIT WORK AND WAIT. + + ENDMETHOD. + METHOD remove. + + DATA: lv_answer TYPE c LENGTH 1, + li_repo TYPE REF TO zif_abapgit_repo, + lv_package TYPE devclass, + lv_question TYPE c LENGTH 200, + lv_repo_name TYPE string, + lv_message TYPE string. + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + lv_repo_name = li_repo->get_name( ). + lv_package = li_repo->get_package( ). + lv_question = |This will remove the repository reference to the package { lv_package + }. All objects will safely remain in the system.|. + + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_titlebar = 'Remove Repository' + iv_text_question = lv_question + iv_text_button_1 = 'Remove' + iv_icon_button_1 = 'ICON_WF_UNLINK' + iv_text_button_2 = 'Cancel' + iv_icon_button_2 = 'ICON_CANCEL' + iv_default_button = '2' + iv_display_cancel_button = abap_false ). + + IF lv_answer = '2'. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + zcl_abapgit_repo_srv=>get_instance( )->delete( li_repo ). + + COMMIT WORK. + + lv_message = |Reference to repository { lv_repo_name } successfully removed from Package { lv_package }. |. + MESSAGE lv_message TYPE 'S'. + + ENDMETHOD. + METHOD toggle_favorite. + + zcl_abapgit_persist_factory=>get_user( )->toggle_favorite( iv_key ). + + ENDMETHOD. + METHOD transport_to_branch. + + DATA: + li_repo_online TYPE REF TO zif_abapgit_repo_online, + lo_transport_to_branch TYPE REF TO zcl_abapgit_transport_2_branch, + lt_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt, + lv_trkorr TYPE trkorr, + ls_transport_to_branch TYPE zif_abapgit_definitions=>ty_transport_to_branch. + IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-transport_to_branch ) = abap_false. + zcx_abapgit_exception=>raise( 'Not authorized' ). + ENDIF. + + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_repository_key ). + + lv_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_transport( ). + " Also include deleted objects that are included in transport + lt_transport_objects = zcl_abapgit_transport=>to_tadir( + iv_trkorr = lv_trkorr + iv_deleted_objects = abap_true ). + IF lt_transport_objects IS INITIAL. + zcx_abapgit_exception=>raise( 'Canceled or List of objects is empty ' ). + ENDIF. + + ls_transport_to_branch = zcl_abapgit_ui_factory=>get_popups( )->popup_to_create_transp_branch( lv_trkorr ). + + CREATE OBJECT lo_transport_to_branch. + lo_transport_to_branch->create( + ii_repo_online = li_repo_online + is_transport_to_branch = ls_transport_to_branch + it_transport_objects = lt_transport_objects ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_services_git IMPLEMENTATION. + METHOD commit. + + DATA: ls_comment TYPE zif_abapgit_git_definitions=>ty_comment, + li_user TYPE REF TO zif_abapgit_persist_user. + + li_user = zcl_abapgit_persist_factory=>get_user( ). + li_user->set_repo_git_user_name( iv_url = ii_repo_online->get_url( ) + iv_username = is_commit-committer_name ). + li_user->set_repo_git_user_email( iv_url = ii_repo_online->get_url( ) + iv_email = is_commit-committer_email ). + + IF is_commit-committer_name IS INITIAL. + zcx_abapgit_exception=>raise( 'Commit: Committer name empty' ). + ELSEIF is_commit-committer_email IS INITIAL. + zcx_abapgit_exception=>raise( 'Commit: Committer email empty' ). + ELSEIF is_commit-author_email IS NOT INITIAL AND is_commit-author_name IS INITIAL. + zcx_abapgit_exception=>raise( 'Commit: Author name empty' ). " Opposite should be OK ? + ELSEIF is_commit-comment IS INITIAL. + zcx_abapgit_exception=>raise( 'Commit: empty comment' ). + ENDIF. + + ls_comment-committer-name = is_commit-committer_name. + ls_comment-committer-email = is_commit-committer_email. + ls_comment-author-name = is_commit-author_name. + ls_comment-author-email = is_commit-author_email. + ls_comment-comment = is_commit-comment. + + IF NOT is_commit-body IS INITIAL. + CONCATENATE ls_comment-comment '' is_commit-body + INTO ls_comment-comment SEPARATED BY cl_abap_char_utilities=>newline. + ENDIF. + + zcl_abapgit_exit=>get_instance( )->validate_before_push( + is_comment = ls_comment + io_stage = io_stage + ii_repo_online = ii_repo_online ). + + ii_repo_online->push( is_comment = ls_comment + io_stage = io_stage ). + + COMMIT WORK. + + ENDMETHOD. + METHOD create_branch. + + DATA: lv_name TYPE string, + lv_cancel TYPE abap_bool, + li_repo_online TYPE REF TO zif_abapgit_repo_online, + lv_msg TYPE string, + li_popups TYPE REF TO zif_abapgit_popups, + lv_source_branch_name TYPE string. + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + lv_source_branch_name = li_repo_online->get_selected_branch( ). + + li_popups = zcl_abapgit_ui_factory=>get_popups( ). + li_popups->create_branch_popup( + EXPORTING + iv_source_branch_name = lv_source_branch_name + IMPORTING + ev_name = lv_name + ev_cancel = lv_cancel ). + + IF lv_cancel = abap_true. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + li_repo_online->create_branch( lv_name ). + + lv_msg = |Branch switched from { zcl_abapgit_git_branch_utils=>get_display_name( lv_source_branch_name ) + } to new branch { zcl_abapgit_git_branch_utils=>get_display_name( lv_name ) }|. + MESSAGE lv_msg TYPE 'S'. + + ENDMETHOD. + METHOD delete_branch. + + DATA: li_repo_online TYPE REF TO zif_abapgit_repo_online, + ls_branch TYPE zif_abapgit_git_definitions=>ty_git_branch, + lv_msg TYPE string, + li_popups TYPE REF TO zif_abapgit_popups. + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + + li_popups = zcl_abapgit_ui_factory=>get_popups( ). + ls_branch = li_popups->branch_list_popup( iv_url = li_repo_online->get_url( ) + iv_hide_branch = li_repo_online->get_selected_branch( ) + iv_hide_head = abap_true ). + IF ls_branch IS INITIAL. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + zcl_abapgit_git_porcelain=>delete_branch( + iv_url = li_repo_online->get_url( ) + is_branch = ls_branch ). + + lv_msg = |Branch { ls_branch-display_name } deleted|. + MESSAGE lv_msg TYPE 'S'. + + ENDMETHOD. + METHOD delete_tag. + + DATA: li_repo_online TYPE REF TO zif_abapgit_repo_online, + ls_tag TYPE zif_abapgit_git_definitions=>ty_git_tag, + lv_text TYPE string. + + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + + ls_tag = zcl_abapgit_ui_factory=>get_popups( )->tag_list_popup( li_repo_online->get_url( ) ). + IF ls_tag IS INITIAL. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + zcl_abapgit_git_porcelain=>delete_tag( + iv_url = li_repo_online->get_url( ) + is_tag = ls_tag ). + + lv_text = |Tag { ls_tag-display_name } deleted|. + + MESSAGE lv_text TYPE 'S'. + + ENDMETHOD. + METHOD pull. + + DATA: li_repo TYPE REF TO zif_abapgit_repo. + + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + + li_repo->refresh( ). + + zcl_abapgit_services_repo=>gui_deserialize( li_repo ). + + ENDMETHOD. + METHOD switch_branch. + + DATA: li_repo_online TYPE REF TO zif_abapgit_repo_online, + ls_branch TYPE zif_abapgit_git_definitions=>ty_git_branch. + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + + ls_branch = zcl_abapgit_ui_factory=>get_popups( )->branch_list_popup( + iv_url = li_repo_online->get_url( ) + iv_default_branch = li_repo_online->get_selected_branch( ) + iv_show_new_option = abap_true ). + IF ls_branch IS INITIAL. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + IF ls_branch-name = zif_abapgit_popups=>c_new_branch_label. + create_branch( iv_key ). + RETURN. + ENDIF. + + " Reset commit and pull request + li_repo_online->select_commit( '' ). + li_repo_online->switch_origin( '' ). + + li_repo_online->select_branch( ls_branch-name ). + COMMIT WORK AND WAIT. + + ENDMETHOD. + METHOD switch_tag. + + DATA: li_repo_online TYPE REF TO zif_abapgit_repo_online, + ls_tag TYPE zif_abapgit_git_definitions=>ty_git_tag, + lv_text TYPE string. + + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + + ls_tag = zcl_abapgit_ui_factory=>get_popups( )->tag_list_popup( li_repo_online->get_url( ) ). + IF ls_tag IS INITIAL. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + " Reset commit and pull request + li_repo_online->select_commit( '' ). + li_repo_online->switch_origin( '' ). + + li_repo_online->select_branch( zcl_abapgit_git_tag=>remove_peel( ls_tag-name ) ). + + COMMIT WORK AND WAIT. + + lv_text = |Tag switched to { ls_tag-display_name } |. + + MESSAGE lv_text TYPE 'S'. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_services_abapgit IMPLEMENTATION. + METHOD get_abapgit_tcode. + CONSTANTS lc_report_tcode_hex TYPE x VALUE '80'. + DATA lt_tcodes TYPE STANDARD TABLE OF tcode. + + TRY. + SELECT tcode + FROM ('TSTC') + INTO TABLE lt_tcodes + WHERE pgmna = sy-cprog + AND cinfo = lc_report_tcode_hex + ORDER BY tcode. + CATCH cx_sy_dynamic_osql_error. +* ABAP Cloud/Steampunk compatibility + RETURN. + ENDTRY. + + IF lines( lt_tcodes ) > 0. + READ TABLE lt_tcodes INDEX 1 INTO rv_tcode. + ENDIF. + ENDMETHOD. + METHOD open_abapgit_changelog. + open_url_in_browser( |{ c_abapgit_repo }{ c_changelog_path }| ). + ENDMETHOD. + METHOD open_abapgit_homepage. + open_url_in_browser( |{ c_abapgit_homepage }/{ iv_page }| ). + ENDMETHOD. + METHOD open_abapgit_wikipage. + open_url_in_browser( |{ c_abapgit_wikipage }/{ iv_page }| ). + ENDMETHOD. + METHOD open_dotabap_homepage. + open_url_in_browser( c_dotabap_homepage ). + ENDMETHOD. + METHOD open_url_in_browser. + DATA lx_error TYPE REF TO zcx_abapgit_exception. + + TRY. + zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = iv_url ). + CATCH zcx_abapgit_exception INTO lx_error. + zcx_abapgit_exception=>raise( iv_text = 'Opening page in external browser failed.' + ix_previous = lx_error ). + ENDTRY. + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_gui_router IMPLEMENTATION. + METHOD abapgit_services_actions. + + IF ii_event->mv_action = zif_abapgit_definitions=>c_action-abapgit_home. + rs_handled-page = zcl_abapgit_gui_page_repo_over=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. + ENDIF. + + ENDMETHOD. + METHOD call_browser. + + zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = |{ iv_url }| ). + + ENDMETHOD. + METHOD call_transaction. + + DATA lv_msg TYPE c LENGTH 200. + + CALL FUNCTION 'ABAP4_CALL_TRANSACTION' + DESTINATION 'NONE' + STARTING NEW TASK 'ABAPGIT' + EXPORTING + tcode = iv_tcode + EXCEPTIONS + communication_failure = 1 MESSAGE lv_msg + system_failure = 2 MESSAGE lv_msg + resource_failure = 3 + OTHERS = 4. + IF sy-subrc <> 0. + lv_msg = |Error starting transaction { iv_tcode }: { lv_msg }|. + MESSAGE lv_msg TYPE 'I'. + ELSE. + lv_msg = |Transaction { iv_tcode } opened in a new window|. + MESSAGE lv_msg TYPE 'S'. + ENDIF. + + ENDMETHOD. + METHOD db_actions. + + DATA ls_db_key TYPE zif_abapgit_persistence=>ty_content. + DATA lo_query TYPE REF TO zcl_abapgit_string_map. + + lo_query = ii_event->query( ). + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-db_edit. + lo_query->to_abap( CHANGING cs_container = ls_db_key ). + rs_handled-page = zcl_abapgit_gui_page_db_entry=>create( + is_key = ls_db_key + iv_edit_mode = abap_true ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-db_display. + lo_query->to_abap( CHANGING cs_container = ls_db_key ). + rs_handled-page = zcl_abapgit_gui_page_db_entry=>create( ls_db_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + ENDCASE. + + ENDMETHOD. + METHOD file_download. + + DATA: + lv_path TYPE string, + lv_default TYPE string, + li_fe_serv TYPE REF TO zif_abapgit_frontend_services, + lv_package TYPE devclass. + + lv_package = iv_package. + TRANSLATE lv_package USING '/#'. + CONCATENATE lv_package '_' sy-datlo '_' sy-timlo '.zip' INTO lv_default. + + li_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + + lv_path = li_fe_serv->show_file_save_dialog( + iv_title = 'Export ZIP' + iv_extension = 'zip' + iv_default_filename = lv_default ). + + li_fe_serv->file_download( + iv_path = lv_path + iv_xstr = iv_xstr ). + + ENDMETHOD. + METHOD general_page_routing. + + DATA: lv_key TYPE zif_abapgit_persistence=>ty_repo-key, + lv_last_repo_key TYPE zif_abapgit_persistence=>ty_repo-key. + + lv_key = ii_event->query( )->get( 'KEY' ). + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-go_home. " Go Home + lv_last_repo_key = zcl_abapgit_persist_factory=>get_user( )->get_repo_show( ). + + IF lv_last_repo_key IS NOT INITIAL. + rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( lv_last_repo_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + ELSE. + rs_handled-page = main_page( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + ENDIF. + WHEN zif_abapgit_definitions=>c_action-go_back. " Go Back + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + WHEN zif_abapgit_definitions=>c_action-go_db. " Go DB util page + rs_handled-page = zcl_abapgit_gui_page_db=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-go_debuginfo. " Go debug info + rs_handled-page = zcl_abapgit_gui_page_debuginfo=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-go_settings. " Go global settings + rs_handled-page = zcl_abapgit_gui_page_sett_glob=>create( ). + rs_handled-state = get_state_settings( ii_event ). + WHEN zif_abapgit_definitions=>c_action-go_settings_personal. " Go personal settings + rs_handled-page = zcl_abapgit_gui_page_sett_pers=>create( ). + rs_handled-state = get_state_settings( ii_event ). + WHEN zif_abapgit_definitions=>c_action-go_background_run. " Go background run page + rs_handled-page = zcl_abapgit_gui_page_run_bckg=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-go_repo_diff " Go Diff page + OR zif_abapgit_definitions=>c_action-go_file_diff. + rs_handled-page = get_page_diff( ii_event ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. + WHEN zif_abapgit_definitions=>c_action-go_patch. " Go Patch page + rs_handled-page = get_page_patch( ii_event ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. + WHEN zif_abapgit_definitions=>c_action-go_stage. " Go Staging page + rs_handled-page = get_page_stage( ii_event ). + rs_handled-state = get_state_diff( ii_event ). + WHEN zif_abapgit_definitions=>c_action-go_stage_transport. " Go Staging page by Transport + rs_handled-page = get_page_stage( ii_event = ii_event + ii_obj_filter = go_stage_transport( lv_key ) ). + rs_handled-state = get_state_diff( ii_event ). + WHEN zif_abapgit_definitions=>c_action-go_tutorial. " Go to tutorial + rs_handled-page = zcl_abapgit_gui_page_tutorial=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-documentation. " abapGit docs + zcl_abapgit_services_abapgit=>open_abapgit_wikipage( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-go_explore. " dotabap + zcl_abapgit_services_abapgit=>open_dotabap_homepage( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-changelog. " abapGit full changelog + zcl_abapgit_services_abapgit=>open_abapgit_changelog( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-homepage. " abapGit homepage + zcl_abapgit_services_abapgit=>open_abapgit_homepage( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-sponsor. " abapGit sponsor us + zcl_abapgit_services_abapgit=>open_abapgit_homepage( 'sponsor.html' ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-show_hotkeys. " show hotkeys + zcl_abapgit_ui_factory=>get_gui_services( + )->get_hotkeys_ctl( + )->set_visible( abap_true ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDCASE. + + ENDMETHOD. + METHOD get_page_diff. + + DATA: ls_file TYPE zif_abapgit_git_definitions=>ty_file, + ls_object TYPE zif_abapgit_definitions=>ty_item, + lv_key TYPE zif_abapgit_persistence=>ty_repo-key. + + lv_key = ii_event->query( )->get( 'KEY' ). + ls_file-path = ii_event->query( )->get( 'PATH' ). + ls_file-filename = ii_event->query( )->get( 'FILENAME' ). " unescape ? + ls_object-obj_type = ii_event->query( )->get( 'OBJ_TYPE' ). + ls_object-obj_name = ii_event->query( )->get( 'OBJ_NAME' ). " unescape ? + + ri_page = zcl_abapgit_gui_page_diff=>create( + iv_key = lv_key + is_file = ls_file + is_object = ls_object ). + + ENDMETHOD. + METHOD get_page_patch. + + DATA: ls_file TYPE zif_abapgit_git_definitions=>ty_file, + ls_object TYPE zif_abapgit_definitions=>ty_item, + lv_key TYPE zif_abapgit_persistence=>ty_repo-key. + + lv_key = ii_event->query( )->get( 'KEY' ). + ls_file-path = ii_event->query( )->get( 'PATH' ). + ls_file-filename = ii_event->query( )->get( 'FILENAME' ). " unescape ? + ls_object-obj_type = ii_event->query( )->get( 'OBJ_TYPE' ). + ls_object-obj_name = ii_event->query( )->get( 'OBJ_NAME' ). " unescape ? + + ri_page = zcl_abapgit_gui_page_patch=>create( + iv_key = lv_key + is_file = ls_file + is_object = ls_object ). + + ENDMETHOD. + METHOD get_page_stage. + + DATA: li_repo_online TYPE REF TO zif_abapgit_repo_online, + li_repo TYPE REF TO zif_abapgit_repo, + lv_key TYPE zif_abapgit_persistence=>ty_repo-key, + lv_seed TYPE string, + lv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result, + lx_error TYPE REF TO cx_sy_move_cast_error. + + lv_key = ii_event->query( )->get( 'KEY' ). + lv_seed = ii_event->query( )->get( 'SEED' ). + + lv_sci_result = zif_abapgit_definitions=>c_sci_result-no_run. + + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + + TRY. + li_repo_online ?= li_repo. + CATCH cx_sy_move_cast_error INTO lx_error. + zcx_abapgit_exception=>raise( `Staging is only possible for online repositories.` ). + ENDTRY. + + IF li_repo_online->get_selected_branch( ) CP zif_abapgit_git_definitions=>c_git_branch-tags. + zcx_abapgit_exception=>raise( |You are working on a tag, must be on branch| ). + ELSEIF li_repo_online->get_selected_commit( ) IS NOT INITIAL. + zcx_abapgit_exception=>raise( |You are working on a commit, must be on branch| ). + ENDIF. + + IF li_repo->get_local_settings( )-code_inspector_check_variant IS NOT INITIAL. + + TRY. + ri_page = zcl_abapgit_gui_page_code_insp=>create( + ii_repo = li_repo + iv_raise_when_no_results = abap_true ). + + CATCH zcx_abapgit_exception. + lv_sci_result = zif_abapgit_definitions=>c_sci_result-passed. + ENDTRY. + + ENDIF. + + IF ri_page IS INITIAL. + ri_page = zcl_abapgit_gui_page_stage=>create( + ii_repo_online = li_repo_online + iv_seed = lv_seed + iv_sci_result = lv_sci_result + ii_obj_filter = ii_obj_filter ). + ENDIF. + + ENDMETHOD. + METHOD get_state_diff. + + " Bookmark current page before jumping to diff page + IF ii_event->mv_current_page_name CP 'ZCL_ABAPGIT_GUI_PAGE_DIFF'. + rv_state = zcl_abapgit_gui=>c_event_state-new_page. + ELSE. + rv_state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. + ENDIF. + + ENDMETHOD. + METHOD get_state_settings. + + " Bookmark current page before jumping to any settings page + IF ii_event->mv_current_page_name CP 'ZCL_ABAPGIT_GUI_PAGE_SETT_*'. + rv_state = zcl_abapgit_gui=>c_event_state-new_page_replacing. + ELSE. + rv_state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. + ENDIF. + + ENDMETHOD. + METHOD git_services. + + DATA lv_key TYPE zif_abapgit_persistence=>ty_repo-key. + DATA li_repo TYPE REF TO zif_abapgit_repo. + + lv_key = ii_event->query( )->get( 'KEY' ). + + IF lv_key IS NOT INITIAL. + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + ENDIF. + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-git_pull. " GIT Pull + zcl_abapgit_services_git=>pull( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-git_branch_create. " GIT Create new branch + zcl_abapgit_services_git=>create_branch( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-git_branch_delete. " GIT Delete remote branch + zcl_abapgit_services_git=>delete_branch( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-git_branch_switch. " GIT Switch branch + zcl_abapgit_services_git=>switch_branch( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-git_branch_merge. " GIT Merge branch + rs_handled-page = zcl_abapgit_gui_page_merge_sel=>create( li_repo ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-git_tag_create. " GIT Tag create + rs_handled-page = zcl_abapgit_gui_page_tags=>create( li_repo ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-git_tag_delete. " GIT Tag delete + zcl_abapgit_services_git=>delete_tag( lv_key ). + zcl_abapgit_services_repo=>refresh( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-git_tag_switch. " GIT Switch Tag + zcl_abapgit_services_git=>switch_tag( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDCASE. + + ENDMETHOD. + METHOD go_stage_transport. + + DATA lt_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt. + DATA li_repo TYPE REF TO zif_abapgit_repo. + + lt_r_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_select_wb_tc_tr_and_tsk( ). + + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + + CREATE OBJECT ro_filter. + ro_filter->set_filter_values( iv_package = li_repo->get_package( ) + it_r_trkorr = lt_r_trkorr ). + + ENDMETHOD. + METHOD jump_display_transport. + + DATA: + ls_e071 TYPE e071, + lv_adt_link TYPE string, + lv_adt_jump_enabled TYPE abap_bool. + + lv_adt_jump_enabled = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_adt_jump_enabled( ). + IF lv_adt_jump_enabled = abap_true AND iv_transport <> zif_abapgit_definitions=>c_multiple_transports. + TRY. + lv_adt_link = zcl_abapgit_adt_link=>link_transport( iv_transport ). + zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = lv_adt_link ). + RETURN. + CATCH zcx_abapgit_exception. + " Fallback if ADT link execution failed or was cancelled + ENDTRY. + ENDIF. + + IF iv_transport = zif_abapgit_definitions=>c_multiple_transports. + ls_e071-pgmid = 'R3TR'. + ls_e071-object = iv_obj_type. + ls_e071-obj_name = iv_obj_name. + + CALL FUNCTION 'TR_SHOW_OBJECT_LOCKS' + EXPORTING + iv_e071 = ls_e071 + EXCEPTIONS + object_not_lockable = 1 + empty_key = 2 + unknown_object = 3 + unallowed_locks = 4 + OTHERS = 5. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ELSE. + CALL FUNCTION 'TR_DISPLAY_REQUEST' + EXPORTING + i_trkorr = iv_transport. + ENDIF. + + ENDMETHOD. + METHOD jump_display_user. + + " todo, user display in ADT + + CALL FUNCTION 'BAPI_USER_DISPLAY' + EXPORTING + username = iv_username. + + ENDMETHOD. + METHOD jump_object. + + DATA: + ls_item TYPE zif_abapgit_definitions=>ty_item, + ls_sub_item TYPE zif_abapgit_definitions=>ty_item, + lx_error TYPE REF TO zcx_abapgit_exception, + lv_line_number TYPE i, + lv_new_window TYPE abap_bool, + li_html_viewer TYPE REF TO zif_abapgit_html_viewer. + + ls_item-obj_type = cl_http_utility=>unescape_url( |{ iv_obj_type }| ). + ls_item-obj_name = cl_http_utility=>unescape_url( |{ iv_obj_name }| ). + ls_sub_item-obj_type = cl_http_utility=>unescape_url( |{ iv_sub_type }| ). + ls_sub_item-obj_name = cl_http_utility=>unescape_url( |{ iv_sub_name }| ). + + IF iv_line CO '0123456789'. + lv_line_number = iv_line. + ENDIF. + lv_new_window = boolc( iv_new_window IS NOT INITIAL ). + + TRY. + li_html_viewer = zcl_abapgit_ui_core_factory=>get_html_viewer( ). + + " Hide HTML Viewer in dummy screen0 for direct CALL SCREEN to work + li_html_viewer->set_visiblity( abap_false ). + + IF ls_item-obj_type = zif_abapgit_data_config=>c_data_type-tabu. + zcl_abapgit_data_utils=>jump( ls_item ). + ELSEIF lv_line_number IS INITIAL OR ls_sub_item IS INITIAL. + zcl_abapgit_objects=>jump( + is_item = ls_item + iv_filename = iv_filename + iv_new_window = lv_new_window ). + ELSE. + zcl_abapgit_objects=>jump( + is_item = ls_item + is_sub_item = ls_sub_item + iv_filename = iv_filename + iv_line_number = lv_line_number + iv_new_window = lv_new_window ). + ENDIF. + + li_html_viewer->set_visiblity( abap_true ). + CATCH zcx_abapgit_exception INTO lx_error. + li_html_viewer->set_visiblity( abap_true ). + RAISE EXCEPTION lx_error. + ENDTRY. + + ENDMETHOD. + METHOD main_page. + + DATA lt_repo_all_list TYPE zif_abapgit_repo_srv=>ty_repo_list. + + " if there are no favorites, check if there are any repositories at all + " if not, go to tutorial where the user can create the first repository + lt_repo_all_list = zcl_abapgit_repo_srv=>get_instance( )->list( ). + IF lt_repo_all_list IS NOT INITIAL. + ri_page = zcl_abapgit_gui_page_repo_over=>create( ). + ELSE. + ri_page = zcl_abapgit_gui_page_tutorial=>create( ). + ENDIF. + + ENDMETHOD. + METHOD other_utilities. + TYPES ty_char600 TYPE c LENGTH 600. + DATA lv_clip_content TYPE string. + DATA lt_clipboard TYPE STANDARD TABLE OF ty_char600. + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-ie_devtools. + zcl_abapgit_ui_factory=>get_frontend_services( )->open_ie_devtools( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-clipboard. + lv_clip_content = ii_event->query( )->get( 'CLIPBOARD' ). + IF lv_clip_content IS INITIAL. + " yank mode sends via form_data + lv_clip_content = ii_event->form_data( )->get( 'CLIPBOARD' ). + ENDIF. + IF lv_clip_content IS INITIAL. + zcx_abapgit_exception=>raise( 'Export to clipboard failed, no data' ). + ENDIF. + APPEND lv_clip_content TO lt_clipboard. + zcl_abapgit_ui_factory=>get_frontend_services( )->clipboard_export( lt_clipboard ). + MESSAGE 'Successfully exported to clipboard' TYPE 'S'. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDCASE. + + ENDMETHOD. + METHOD repository_services. + + DATA: + lv_key TYPE zif_abapgit_persistence=>ty_repo-key, + li_repo TYPE REF TO zif_abapgit_repo, + li_log TYPE REF TO zif_abapgit_log. + + lv_key = ii_event->query( )->get( 'KEY' ). + IF lv_key IS NOT INITIAL. + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + ENDIF. + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-repo_newoffline. " New offline repo + rs_handled-page = zcl_abapgit_gui_page_addofflin=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-repo_add_all_obj_to_trans_req. " Add objects to transport + zcl_abapgit_transport=>add_all_objects_to_trans_req( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-repo_refresh. " Repo refresh + zcl_abapgit_services_repo=>refresh( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-repo_syntax_check. " Syntax check + rs_handled-page = zcl_abapgit_gui_page_syntax=>create( li_repo ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-repo_code_inspector. " Code inspector + rs_handled-page = zcl_abapgit_gui_page_code_insp=>create( li_repo ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-repo_purge. " Purge all objects and repo (uninstall) + zcl_abapgit_services_repo=>purge( lv_key ). + rs_handled-page = zcl_abapgit_gui_page_repo_over=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. + WHEN zif_abapgit_definitions=>c_action-repo_delete_objects. " Purge all objects (uninstall) + zcl_abapgit_services_repo=>purge( + iv_key = lv_key + iv_keep_repo = abap_true ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-repo_remove. " Repo remove + zcl_abapgit_services_repo=>remove( lv_key ). + rs_handled-page = zcl_abapgit_gui_page_repo_over=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. + WHEN zif_abapgit_definitions=>c_action-repo_activate_objects. " Repo activate objects + zcl_abapgit_services_repo=>activate_objects( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-repo_newonline. " New online repo + rs_handled-page = zcl_abapgit_gui_page_addonline=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-flow. " Flow page + rs_handled-page = zcl_abapgit_gui_page_flow=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-repo_refresh_checksums. " Rebuild local checksums + zcl_abapgit_services_repo=>refresh_local_checksums( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-repo_toggle_fav. " Toggle repo as favorite + zcl_abapgit_services_repo=>toggle_favorite( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-repo_transport_to_branch. " Transport to branch + zcl_abapgit_services_repo=>transport_to_branch( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-repo_settings. " Repo settings + rs_handled-page = zcl_abapgit_gui_page_sett_repo=>create( li_repo ). + rs_handled-state = get_state_settings( ii_event ). + WHEN zif_abapgit_definitions=>c_action-repo_local_settings. " Local repo settings + rs_handled-page = zcl_abapgit_gui_page_sett_locl=>create( li_repo ). + rs_handled-state = get_state_settings( ii_event ). + WHEN zif_abapgit_definitions=>c_action-repo_remote_settings. " Remote repo settings + rs_handled-page = zcl_abapgit_gui_page_sett_remo=>create( li_repo ). + rs_handled-state = get_state_settings( ii_event ). + WHEN zif_abapgit_definitions=>c_action-repo_background. " Repo background mode + rs_handled-page = zcl_abapgit_gui_page_sett_bckg=>create( li_repo ). + rs_handled-state = get_state_settings( ii_event ). + WHEN zif_abapgit_definitions=>c_action-repo_infos. " Repo infos + rs_handled-page = zcl_abapgit_gui_page_sett_info=>create( li_repo ). + rs_handled-state = get_state_settings( ii_event ). + WHEN zif_abapgit_definitions=>c_action-repo_change_package. " Repo change package + rs_handled-page = zcl_abapgit_gui_page_chg_pckg=>create( li_repo ). + rs_handled-state = get_state_settings( ii_event ). + WHEN zif_abapgit_definitions=>c_action-repo_log. " Repo log + li_log = li_repo->get_log( ). + zcl_abapgit_log_viewer=>show_log( li_log ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDCASE. + + ENDMETHOD. + METHOD sap_gui_actions. + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-jump. " Open object editor + jump_object( + iv_obj_type = ii_event->query( )->get( 'TYPE' ) + iv_obj_name = ii_event->query( )->get( 'NAME' ) + iv_filename = ii_event->query( )->get( 'FILE' ) + iv_sub_type = ii_event->query( )->get( 'SUBTYPE' ) + iv_sub_name = ii_event->query( )->get( 'SUBNAME' ) + iv_line = ii_event->query( )->get( 'LINE' ) + iv_new_window = ii_event->query( )->get( 'NEW_WINDOW' ) ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + WHEN zif_abapgit_definitions=>c_action-jump_transaction. + call_transaction( |{ ii_event->query( )->get( 'TRANSACTION' ) }| ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + WHEN zif_abapgit_definitions=>c_action-jump_transport. + jump_display_transport( + iv_transport = |{ ii_event->query( )->get( 'TRANSPORT' ) }| + iv_obj_type = |{ ii_event->query( )->get( 'TYPE' ) }| + iv_obj_name = |{ ii_event->query( )->get( 'NAME' ) }| ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + WHEN zif_abapgit_definitions=>c_action-jump_user. + jump_display_user( |{ ii_event->query( )->get( 'USER' ) }| ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + WHEN zif_abapgit_definitions=>c_action-url. + call_browser( ii_event->query( )->get( 'URL' ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + IF rs_handled-state IS INITIAL. + rs_handled = general_page_routing( ii_event ). + ENDIF. + IF rs_handled-state IS INITIAL. + rs_handled = repository_services( ii_event ). + ENDIF. + IF rs_handled-state IS INITIAL. + rs_handled = git_services( ii_event ). + ENDIF. + IF rs_handled-state IS INITIAL. + rs_handled = zip_services( ii_event ). + ENDIF. + IF rs_handled-state IS INITIAL. + rs_handled = db_actions( ii_event ). + ENDIF. + IF rs_handled-state IS INITIAL. + rs_handled = abapgit_services_actions( ii_event ). + ENDIF. + IF rs_handled-state IS INITIAL. + rs_handled = sap_gui_actions( ii_event ). + ENDIF. + IF rs_handled-state IS INITIAL. + rs_handled = other_utilities( ii_event ). + ENDIF. + + IF rs_handled-state IS INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-not_handled. + ENDIF. + + ENDMETHOD. + METHOD zip_export_transport. + + DATA lo_obj_filter_trans TYPE REF TO zcl_abapgit_object_filter_tran. + DATA lt_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt. + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA lv_xstr TYPE xstring. + + lt_r_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_select_wb_tc_tr_and_tsk( ). + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + li_repo->refresh( ). + CREATE OBJECT lo_obj_filter_trans. + lo_obj_filter_trans->set_filter_values( iv_package = li_repo->get_package( ) + it_r_trkorr = lt_r_trkorr ). + + lv_xstr = zcl_abapgit_zip=>encode_files( li_repo->get_files_local_filtered( lo_obj_filter_trans ) ). + li_repo->refresh( ). + file_download( iv_package = li_repo->get_package( ) + iv_xstr = lv_xstr ). + + ENDMETHOD. + METHOD zip_services. + + DATA: lv_key TYPE zif_abapgit_persistence=>ty_repo-key, + li_repo TYPE REF TO zif_abapgit_repo, + lv_path TYPE string, + lv_dest TYPE rfcdest, + lv_xstr TYPE xstring, + lv_msg TYPE c LENGTH 200, + lv_package TYPE zif_abapgit_persistence=>ty_repo-package, + lv_folder_logic TYPE string, + lv_main_lang_only TYPE zif_abapgit_persistence=>ty_local_settings-main_language_only. + + CONSTANTS: + BEGIN OF lc_page, + main_view TYPE string VALUE 'ZCL_ABAPGIT_GUI_PAGE_MAIN', + repo_view TYPE string VALUE 'ZCL_ABAPGIT_GUI_PAGE_REPO_VIEW', + END OF lc_page. + + lv_key = ii_event->query( )->get( 'KEY' ). + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-zip_import " Import repo from ZIP + OR zif_abapgit_definitions=>c_action-rfc_compare. " Compare repo via RFC + + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + + IF ii_event->mv_action = zif_abapgit_definitions=>c_action-zip_import. + lv_path = zcl_abapgit_ui_factory=>get_frontend_services( )->show_file_open_dialog( + iv_title = 'Import ZIP' + iv_extension = 'zip' + iv_default_filename = '*.zip' ). + lv_xstr = zcl_abapgit_ui_factory=>get_frontend_services( )->file_upload( lv_path ). + ELSE. + lv_dest = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'RFCDES-RFCDEST' ). + + IF lv_dest IS INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + RETURN. + ENDIF. + + lv_package = li_repo->get_package( ). + lv_folder_logic = li_repo->get_dot_abapgit( )->get_folder_logic( ). + lv_main_lang_only = li_repo->get_local_settings( )-main_language_only. + + CALL FUNCTION 'Z_ABAPGIT_SERIALIZE_PACKAGE' + DESTINATION lv_dest + EXPORTING + iv_package = lv_package + iv_folder_logic = lv_folder_logic + iv_main_lang_only = lv_main_lang_only + IMPORTING + ev_xstring = lv_xstr + EXCEPTIONS + system_failure = 1 MESSAGE lv_msg + communication_failure = 2 MESSAGE lv_msg + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |RFC import error: { lv_msg }| ). + ENDIF. + ENDIF. + + li_repo->set_files_remote( zcl_abapgit_zip=>load( lv_xstr ) ). + zcl_abapgit_services_repo=>refresh( lv_key ). + + CASE ii_event->mv_current_page_name. + WHEN lc_page-repo_view. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN lc_page-main_view. + rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( li_repo->get_key( ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN OTHERS. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDCASE. + WHEN zif_abapgit_definitions=>c_action-zip_export. " Export repo as ZIP + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + lv_xstr = zcl_abapgit_zip=>encode_files( li_repo->get_files_local( ) ). + file_download( iv_package = li_repo->get_package( ) + iv_xstr = lv_xstr ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-zip_export_transport. " Export repo as ZIP + zip_export_transport( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-zip_package. " Export package as ZIP + rs_handled-page = zcl_abapgit_gui_page_ex_pckage=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-zip_transport. " Export transports as ZIP + zcl_abapgit_transport_mass=>run( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + WHEN zif_abapgit_definitions=>c_action-zip_object. " Export object as ZIP + rs_handled-page = zcl_abapgit_gui_page_ex_object=>create( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-where_used. + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + rs_handled-page = zcl_abapgit_gui_page_whereused=>create( ii_repo = li_repo ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + ENDCASE. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_progress IMPLEMENTATION. + METHOD calc_pct. + + DATA: lv_f TYPE f. + + TRY. + lv_f = ( iv_current / mv_total ) * 100. + rv_pct = lv_f. + + IF rv_pct = 100. + rv_pct = 99. + ELSEIF rv_pct = 0. + rv_pct = 1. + ENDIF. + CATCH cx_sy_zerodivide. + rv_pct = 0. + ENDTRY. + + ENDMETHOD. + METHOD get_instance. + +* max one progress indicator at a time is supported + + IF gi_progress IS INITIAL. + CREATE OBJECT gi_progress TYPE zcl_abapgit_progress. + ENDIF. + + gi_progress->set_total( iv_total ). + + ri_progress = gi_progress. + + ENDMETHOD. + METHOD set_instance. + + gi_progress = ii_progress. + + ENDMETHOD. + METHOD zif_abapgit_progress~off. + + " Clear the status bar + CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'. + + ENDMETHOD. + METHOD zif_abapgit_progress~set_total. + + mv_total = iv_total. + + CLEAR mv_cv_time_next. + CLEAR mv_cv_datum_next. + + ENDMETHOD. + METHOD zif_abapgit_progress~show. + + DATA: lv_pct TYPE i, + lv_time TYPE t. + + CONSTANTS: lc_wait_secs TYPE i VALUE 2. + + GET TIME. + lv_time = sy-uzeit. + IF mv_cv_time_next IS INITIAL AND mv_cv_datum_next IS INITIAL. + mv_cv_time_next = lv_time. + mv_cv_datum_next = sy-datum. + ENDIF. + + "We only do a progress indication if enough time has passed + IF lv_time >= mv_cv_time_next + AND sy-datum = mv_cv_datum_next + OR sy-datum > mv_cv_datum_next. + + lv_pct = calc_pct( iv_current ). + + CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR' + EXPORTING + percentage = lv_pct + text = iv_text. + mv_cv_time_next = lv_time + lc_wait_secs. + + ENDIF. + IF sy-datum > mv_cv_datum_next. + mv_cv_datum_next = sy-datum. + ENDIF. + IF mv_cv_time_next < lv_time. + mv_cv_datum_next = sy-datum + 1. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_popup_tag_list IMPLEMENTATION. + METHOD constructor. + mv_repo_url = iv_url. + ENDMETHOD. + METHOD create. + CREATE OBJECT ri_popup TYPE zcl_abapgit_popup_tag_list + EXPORTING + iv_url = iv_url. + ENDMETHOD. + METHOD fetch_tag_list. + + DATA lo_branches TYPE REF TO zif_abapgit_git_branch_list. + + lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( mv_repo_url ). + rt_tags = lo_branches->get_tags_only( ). + + DELETE rt_tags WHERE name CP '*' && zif_abapgit_git_definitions=>c_git_branch-peel. + + IF lines( rt_tags ) = 0. + zcx_abapgit_exception=>raise( 'No tags are available to select' ). + ENDIF. + + SORT rt_tags BY display_name ASCENDING. + + ENDMETHOD. + METHOD zif_abapgit_gui_render_item~render. + + FIELD-SYMBOLS TYPE zif_abapgit_git_definitions=>ty_git_branch. + + ASSIGN iv_item TO . + + ri_html = zcl_abapgit_html=>create( |{ -display_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_html_popup~create_picklist. + + CREATE OBJECT ro_picklist + EXPORTING + iv_title = 'Choose Tag' + it_list = fetch_tag_list( ) + ii_item_renderer = me. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_popup_pull_request IMPLEMENTATION. + METHOD constructor. + mv_repo_url = iv_url. + ENDMETHOD. + METHOD create. + + CREATE OBJECT ri_popup TYPE zcl_abapgit_popup_pull_request + EXPORTING + iv_url = iv_url. + + ENDMETHOD. + METHOD fetch_pull_request_list. + + rt_pulls = zcl_abapgit_pr_enumerator=>new( mv_repo_url )->get_pulls( ). + + SORT rt_pulls DESCENDING BY number. + + IF lines( rt_pulls ) = 0. + zcx_abapgit_exception=>raise( 'No pull requests found' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_render_item~render. + + FIELD-SYMBOLS TYPE zif_abapgit_pr_enum_provider=>ty_pull_request. + + ASSIGN iv_item TO . + + ri_html = zcl_abapgit_html=>create( |{ -number } - { -title } @{ -user }| ). + + ENDMETHOD. + METHOD zif_abapgit_html_popup~create_picklist. + + CREATE OBJECT ro_picklist + EXPORTING + iv_title = 'Choose Pull Request' + it_list = fetch_pull_request_list( ) + ii_item_renderer = me. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_popup_code_insp IMPLEMENTATION. + METHOD create. + CREATE OBJECT ri_popup TYPE zcl_abapgit_popup_code_insp. + ENDMETHOD. + METHOD fetch_list. + + rt_list = zcl_abapgit_code_inspector=>get_code_inspector( '$TMP' )->list_global_variants( ). + + ENDMETHOD. + METHOD zif_abapgit_gui_render_item~render. + + FIELD-SYMBOLS TYPE LINE OF zif_abapgit_code_inspector=>ty_variants. + + ASSIGN iv_item TO . + + ri_html = zcl_abapgit_html=>create( |{ -name } - { -description }| ). + + ENDMETHOD. + METHOD zif_abapgit_html_popup~create_picklist. + + CREATE OBJECT ro_picklist + EXPORTING + iv_title = 'Choose Variant' + it_list = fetch_list( ) + ii_item_renderer = me. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_popup_branch_list IMPLEMENTATION. + METHOD constructor. + mv_repo_url = iv_url. + mv_default_branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && iv_default_branch. + mv_show_new_option = iv_show_new_option. + ENDMETHOD. + METHOD create. + CREATE OBJECT ri_popup TYPE zcl_abapgit_popup_branch_list + EXPORTING + iv_url = iv_url + iv_default_branch = iv_default_branch + iv_show_new_option = iv_show_new_option. + ENDMETHOD. + METHOD fetch_branch_list. + + DATA lo_branches TYPE REF TO zif_abapgit_git_branch_list. + DATA lv_head_symref TYPE string. + + FIELD-SYMBOLS LIKE LINE OF rt_branches. + + lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( mv_repo_url ). + rt_branches = lo_branches->get_branches_only( ). + lv_head_symref = lo_branches->get_head_symref( ). + + IF rt_branches IS INITIAL. + zcx_abapgit_exception=>raise( 'No branches are available to select' ). + ENDIF. + + " Clean up branches: HEAD duplicates, empty names + LOOP AT rt_branches ASSIGNING . + IF -name IS INITIAL. + DELETE rt_branches INDEX sy-tabix. + ELSEIF -is_head = abap_true AND lv_head_symref IS NOT INITIAL AND -name <> lv_head_symref. + DELETE rt_branches INDEX sy-tabix. + ENDIF. + ENDLOOP. + + SORT rt_branches BY is_head DESCENDING display_name ASCENDING. + + IF mv_show_new_option = abap_true. + APPEND INITIAL LINE TO rt_branches ASSIGNING . + -name = zif_abapgit_popups=>c_new_branch_label. + -display_name = zif_abapgit_popups=>c_new_branch_label. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_render_item~render. + + DATA lv_head_marker TYPE string. + FIELD-SYMBOLS TYPE zif_abapgit_git_definitions=>ty_git_branch. + + ASSIGN iv_item TO . + + " TODO render mv_default_branch properly, needs respecting support from the picklist components + + IF -is_head = abap_true. + lv_head_marker = | ({ zif_abapgit_git_definitions=>c_head_name })|. + ENDIF. + + ri_html = zcl_abapgit_html=>create( |{ -display_name }{ lv_head_marker }| ). + + ENDMETHOD. + METHOD zif_abapgit_html_popup~create_picklist. + + CREATE OBJECT ro_picklist + EXPORTING + iv_title = 'Choose Branch' + it_list = fetch_branch_list( ) + ii_item_renderer = me. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_tutorial IMPLEMENTATION. + METHOD build_main_menu. + + ro_menu = zcl_abapgit_html_toolbar=>create( 'toolbar-tutorial' ). + + ro_menu->add( + iv_txt = zcl_abapgit_gui_buttons=>repo_list( ) + iv_act = zif_abapgit_definitions=>c_action-abapgit_home + )->add( + iv_txt = zcl_abapgit_gui_buttons=>new_online( ) + iv_act = zif_abapgit_definitions=>c_action-repo_newonline + )->add( + iv_txt = zcl_abapgit_gui_buttons=>new_offline( ) + iv_act = zif_abapgit_definitions=>c_action-repo_newoffline + )->add( + iv_txt = zcl_abapgit_gui_buttons=>help( ) + io_sub = zcl_abapgit_gui_menus=>help( ) ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_tutorial. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Tutorial' + io_page_menu = build_main_menu( ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
      ' ). + + ri_html->add( '

      Tutorial

      ' ). + ri_html->add( '
      ' ). + + ri_html->add( '

      Online repositories

      ' ). + ri_html->add( '

        ' ). + + ri_html->add( `
      • To clone a remote repository (e.g. from github) click ` ). + ri_html->add_a( iv_txt = zcl_abapgit_gui_buttons=>new_online( ) + iv_act = zif_abapgit_definitions=>c_action-repo_newonline ). + ri_html->add( ' from the top menu. This will link a remote repository with a package on your system.
      • ' ). + ri_html->add( '
      • Use the pull button to retrieve and activate the remote objects.
      • ' ). + ri_html->add( '
      • If the remote repository is updated,' ). + ri_html->add( ' you will see the changes and can pull to apply the updates.
      • ' ). + + ri_html->add( '

      ' ). + + ri_html->add( '

      Offline repositories

      ' ). + ri_html->add( '

        ' ). + + ri_html->add( `
      • To add a package as an offline repository, click ` ). + ri_html->add_a( iv_txt = zcl_abapgit_gui_buttons=>new_offline( ) + iv_act = zif_abapgit_definitions=>c_action-repo_newoffline ). + ri_html->add( ' from the top menu.' ). + ri_html->add( '
      • abapGit will start tracking changes for the package ' ). + ri_html->add( 'without linking it to an online git repository.
      • ' ). + ri_html->add( '
      • You can link the package later or just export the package content as a ZIP file.
      • ' ). + + ri_html->add( '

      ' ). + + ri_html->add( '

    ' ). + + ri_html->add( '

    Repository list and favorites

    ' ). + ri_html->add( '

      ' ). + ri_html->add( |
    • To favorite a repository, use the { + ri_html->icon( 'star/darkgrey' ) } icon in the repository list.
    • | ). + ri_html->add( |
    • To go to a repository, click on the repository name.
    • | ). + ri_html->add( |
    • To go back to your favorites, use the| ). + ri_html->add_a( + iv_txt = zcl_abapgit_gui_buttons=>repo_list( ) + iv_act = zif_abapgit_definitions=>c_action-abapgit_home ). + ri_html->add( |
    • | ). + + ri_html->add( `
    • ` ). + ri_html->add_a( iv_txt = 'Explore' + iv_act = zif_abapgit_definitions=>c_action-go_explore ). + ri_html->add( ' to find projects using abapGit
    • ' ). + ri_html->add( '

    ' ). + ri_html->add( '' ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_tags IMPLEMENTATION. + METHOD choose_commit. + + DATA li_popups TYPE REF TO zif_abapgit_popups. + + li_popups = zcl_abapgit_ui_factory=>get_popups( ). + + rv_commit = li_popups->commit_list_popup( + iv_repo_url = mi_repo_online->get_url( ) + iv_branch_name = mi_repo_online->get_selected_branch( ) )-sha1. + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + CREATE OBJECT mo_form_data. + CREATE OBJECT mo_validation_log. + mi_repo_online ?= ii_repo. + + " Get settings from DB + mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + + mo_form = get_form_schema( ). + + initialize_form_data( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_tags. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Create Tag' + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + CONSTANTS lc_commitmsg_comment_min_len TYPE i VALUE 1. + CONSTANTS lc_commitmsg_comment_max_len TYPE i VALUE 255. + + IF io_form_data IS BOUND AND io_form_data->is_empty( ) = abap_false. + ms_tag-type = io_form_data->get( c_id-tag_type ). + ENDIF. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'create-tag-form' + iv_help_page = 'https://docs.abapgit.org/' ). " todo, add docs + + ro_form->start_group( + iv_name = c_id-tag_group + iv_label = 'New Tag' + )->radio( + iv_label = 'Type' + iv_name = c_id-tag_type + iv_action = c_event-change_type + )->option( + iv_label = 'Lightweight' + iv_value = zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag + )->option( + iv_label = 'Annotated' + iv_value = zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag + )->text( + iv_name = c_id-name + iv_label = 'Tag Name' + iv_required = abap_true + )->text( + iv_name = c_id-sha1 + iv_label = 'Commit' + iv_min = 40 + iv_max = 40 + iv_condense = abap_true + iv_required = abap_true + iv_side_action = c_event-choose_commit ). + + IF ms_tag-type = zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. + ro_form->start_group( + iv_name = c_id-anno_group + iv_label = 'Annotation' + )->text( + iv_name = c_id-message + iv_label = 'Comment' + iv_min = lc_commitmsg_comment_min_len + iv_max = lc_commitmsg_comment_max_len + iv_placeholder = |Add a mandatory comment with max { lc_commitmsg_comment_max_len } characters| + )->textarea( + iv_name = c_id-body + iv_label = 'Body' + iv_rows = 6 + iv_cols = mo_settings->get_commitmsg_body_size( ) + iv_placeholder = 'Add an optional description...' + )->text( + iv_name = c_id-tagger_name + iv_label = 'Tagger Name' + )->text( + iv_name = c_id-tagger_email + iv_label = 'Tagger Email' ). + ELSE. + ro_form->hidden( c_id-message + )->hidden( c_id-body + )->hidden( c_id-tagger_name + )->hidden( c_id-tagger_email ). + ENDIF. + + ro_form->command( + iv_label = 'Create' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-create + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD get_tagger_email. + + DATA li_user TYPE REF TO zif_abapgit_persist_user. + + li_user = zcl_abapgit_persist_factory=>get_user( ). + + rv_email = li_user->get_repo_git_user_email( mi_repo_online->get_url( ) ). + IF rv_email IS INITIAL. + rv_email = li_user->get_default_git_user_email( ). + ENDIF. + IF rv_email IS INITIAL. + " get default from user record + rv_email = zcl_abapgit_env_factory=>get_user_record( )->get_email( sy-uname ). + ENDIF. + + ENDMETHOD. + METHOD get_tagger_name. + + DATA li_user TYPE REF TO zif_abapgit_persist_user. + + li_user = zcl_abapgit_persist_factory=>get_user( ). + + rv_user = li_user->get_repo_git_user_name( mi_repo_online->get_url( ) ). + IF rv_user IS INITIAL. + rv_user = li_user->get_default_git_user_name( ). + ENDIF. + IF rv_user IS INITIAL. + " get default from user record + rv_user = zcl_abapgit_env_factory=>get_user_record( )->get_name( sy-uname ). + ENDIF. + + ENDMETHOD. + METHOD initialize_form_data. + + ms_tag-type = zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. + + mo_form_data->set( + iv_key = c_id-tag_type + iv_val = ms_tag-type ). + + ms_tag-tagger_name = get_tagger_name( ). + ms_tag-tagger_email = get_tagger_email( ). + + mo_form_data->set( + iv_key = c_id-tagger_name + iv_val = ms_tag-tagger_name ). + mo_form_data->set( + iv_key = c_id-tagger_email + iv_val = ms_tag-tagger_email ). + + ENDMETHOD. + METHOD validate_form. + + DATA: + lt_tags TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, + lv_new_tag_name TYPE string. + + ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). + + IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-tagger_email ) ) = abap_false. + ro_validation_log->set( + iv_key = c_id-tagger_email + iv_val = |Invalid email address| ). + ENDIF. + + lv_new_tag_name = io_form_data->get( c_id-name ). + + IF lv_new_tag_name IS NOT INITIAL. + " Check if tag already exists + lt_tags = zcl_abapgit_git_factory=>get_git_transport( )->branches( mi_repo_online->get_url( ) )->get_tags_only( ). + + READ TABLE lt_tags TRANSPORTING NO FIELDS WITH TABLE KEY name_key + COMPONENTS name = zcl_abapgit_git_tag=>add_tag_prefix( lv_new_tag_name ). + IF sy-subrc = 0. + ro_validation_log->set( + iv_key = c_id-name + iv_val = |Tag already exists| ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA: + lx_error TYPE REF TO zcx_abapgit_exception, + lv_commit TYPE zif_abapgit_git_definitions=>ty_sha1, + lv_text TYPE string. + + mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). + + CASE ii_event->mv_action. + + WHEN c_event-choose_commit. + lv_commit = choose_commit( ). + + IF lv_commit IS INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ELSE. + mo_form_data->set( + iv_key = c_id-sha1 + iv_val = lv_commit ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + + WHEN c_event-change_type. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + mo_validation_log->clear( ). + + WHEN c_event-create. + " Validate form entries before creating tag + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + + mo_form_data->strict( abap_false ). + mo_form_data->to_abap( CHANGING cs_container = ms_tag ). + + REPLACE ALL OCCURRENCES + OF cl_abap_char_utilities=>cr_lf + IN ms_tag-body + WITH cl_abap_char_utilities=>newline. + + ms_tag-name = zcl_abapgit_git_tag=>add_tag_prefix( ms_tag-name ). + ASSERT ms_tag-name CP zif_abapgit_git_definitions=>c_git_branch-tags. + + TRY. + zcl_abapgit_git_porcelain=>create_tag( + iv_url = mi_repo_online->get_url( ) + is_tag = ms_tag ). + CATCH zcx_abapgit_exception INTO lx_error. + zcx_abapgit_exception=>raise( |Cannot create tag { ms_tag-name }: { lx_error->get_text( ) }| ). + ENDTRY. + + lv_text = |Tag { zcl_abapgit_git_tag=>remove_tag_prefix( ms_tag-name ) } created|. + MESSAGE lv_text TYPE 'S'. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + + ENDCASE. + + " If staying on form, initialize it with current settings + IF rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + mo_form = get_form_schema( mo_form_data ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( `
    ` ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo_online + iv_show_commit = abap_false + iv_interactive_branch = abap_false ) ). + + ri_html->add( mo_form->render( io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + + ri_html->add( `
    ` ). + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlRuLHgbrJghgEvobFoEEqzmNhe DEFINITION DEFERRED. +INTERFACE iUFTsRuLHgbrJghgEvobHWVitRcGlb DEFERRED. +*"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + +* renamed: zcl_abapgit_gui_page_stage :: lif_selected +INTERFACE iUFTsRuLHgbrJghgEvobHWVitRcGlb. + + METHODS stage_selected + IMPORTING + ii_event TYPE REF TO zif_abapgit_gui_event + it_status TYPE zif_abapgit_definitions=>ty_results_ts_path + it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + RETURNING + VALUE(ro_stage) TYPE REF TO zcl_abapgit_stage + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +* renamed: zcl_abapgit_gui_page_stage :: lcl_selected +CLASS kHGwlRuLHgbrJghgEvobFoEEqzmNhe DEFINITION CREATE PRIVATE. + + PUBLIC SECTION. + CLASS-METHODS get_instance + RETURNING + VALUE(ro_instance) TYPE REF TO iUFTsRuLHgbrJghgEvobHWVitRcGlb. + + INTERFACES iUFTsRuLHgbrJghgEvobHWVitRcGlb. + + PRIVATE SECTION. + METHODS check_selected + IMPORTING + io_files TYPE REF TO zcl_abapgit_string_map + RAISING + zcx_abapgit_exception. + + METHODS read_status_case_insensitive + IMPORTING + is_file TYPE zif_abapgit_git_definitions=>ty_file + it_status TYPE zif_abapgit_definitions=>ty_results_ts_path + RETURNING + VALUE(rs_status) TYPE zif_abapgit_definitions=>ty_result + RAISING + zcx_abapgit_exception. + + CLASS-DATA: + gi_instance TYPE REF TO iUFTsRuLHgbrJghgEvobHWVitRcGlb. + +ENDCLASS. +CLASS kHGwlRuLHgbrJghgEvobFoEEqzmNhe IMPLEMENTATION. + + METHOD iUFTsRuLHgbrJghgEvobHWVitRcGlb~stage_selected. + + DATA ls_file TYPE zif_abapgit_git_definitions=>ty_file. + DATA ls_status LIKE LINE OF it_status. + DATA lo_files TYPE REF TO zcl_abapgit_string_map. + + FIELD-SYMBOLS: + LIKE LINE OF it_local, + LIKE LINE OF lo_files->mt_entries. + + lo_files = ii_event->form_data( ). + + IF lo_files->size( ) = 0. + zcx_abapgit_exception=>raise( 'process_stage_list: empty list' ). + ENDIF. + + check_selected( lo_files ). + + CREATE OBJECT ro_stage. + + LOOP AT lo_files->mt_entries ASSIGNING + "Ignore Files that we don't want to stage, so any errors don't stop the staging process + WHERE v <> zif_abapgit_definitions=>c_method-skip. + + zcl_abapgit_path=>split_file_location( + EXPORTING + iv_fullpath = -k + IMPORTING + ev_path = ls_file-path + ev_filename = ls_file-filename ). + + " you should remember that ls_file is sent from the client and is always uppercase, + " whereas it_status and it_local path could be lower, upper or mixed case. + ls_status = read_status_case_insensitive( + is_file = ls_file + it_status = it_status ). + + " ls_status has the right case, therefore use it also for ls_file + ls_file-path = ls_status-path. + ls_file-filename = ls_status-filename. + + CASE -v. + WHEN zif_abapgit_definitions=>c_method-add. + READ TABLE it_local ASSIGNING + WITH KEY file-path = ls_file-path + file-filename = ls_file-filename. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |process_stage_list: unknown file { ls_file-path }{ ls_file-filename }| ). + ENDIF. + + ro_stage->add( iv_path = -file-path + iv_filename = -file-filename + is_status = ls_status + iv_data = -file-data ). + WHEN zif_abapgit_definitions=>c_method-ignore. + ro_stage->ignore( iv_path = ls_file-path + iv_filename = ls_file-filename ). + WHEN zif_abapgit_definitions=>c_method-rm. + ro_stage->rm( iv_path = ls_file-path + is_status = ls_status + iv_filename = ls_file-filename ). + WHEN zif_abapgit_definitions=>c_method-skip. + " Do nothing. Never happens as it is filtered out before. Just for completeness. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |process_stage_list: unknown method { -v }| ). + ENDCASE. + ENDLOOP. + ENDMETHOD. + METHOD check_selected. + + DATA: + ls_file TYPE zif_abapgit_git_definitions=>ty_file, + lv_pattern TYPE string, + lv_msg TYPE string. + + FIELD-SYMBOLS: + LIKE LINE OF io_files->mt_entries, + LIKE LINE OF io_files->mt_entries. + + " Check all added files if the exist in different paths (packages) without being removed + LOOP AT io_files->mt_entries ASSIGNING WHERE v = zif_abapgit_definitions=>c_method-add. + + " Allow mixed case path, but check filename to lower case + zcl_abapgit_path=>split_file_location( + EXPORTING + iv_fullpath = -k + IMPORTING + ev_path = ls_file-path + ev_filename = ls_file-filename ). + + ls_file-filename = to_lower( ls_file-filename ). + + " Skip packages since they all have identical filenames + IF NOT ls_file-filename CP 'package.devc.*'. + lv_pattern = '*/' && to_upper( ls_file-filename ). + REPLACE ALL OCCURRENCES OF '#' IN lv_pattern WITH '##'. " for CP + + LOOP AT io_files->mt_entries ASSIGNING + WHERE k CP lv_pattern AND k <> -k AND v <> zif_abapgit_definitions=>c_method-rm. + + lv_msg = |In order to add { to_lower( -k ) }, | && + |you have to remove { to_lower( -k ) }|. + zcx_abapgit_exception=>raise( lv_msg ). + + ENDLOOP. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD get_instance. + + IF gi_instance IS INITIAL. + CREATE OBJECT gi_instance TYPE kHGwlRuLHgbrJghgEvobFoEEqzmNhe. + ENDIF. + + ro_instance = gi_instance. + + ENDMETHOD. + METHOD read_status_case_insensitive. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_result. + + LOOP AT it_status ASSIGNING . + + IF to_upper( -filename ) = to_upper( is_file-filename ) + AND to_upper( -path ) = to_upper( is_file-path ). + rs_status = . + RETURN. + ENDIF. + + ENDLOOP. + + " see https://github.com/abapGit/abapGit/issues/3073 + zcx_abapgit_exception=>raise( + |Unable to stage { is_file-filename }. If the filename contains spaces, this is a known issue.| && + | Consider ignoring or staging the file at a later time.| ). + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_gui_page_stage IMPLEMENTATION. + METHOD constructor. + + DATA lv_ts TYPE timestamp. + + super->constructor( ). + + mi_repo = ii_repo_online. + mi_repo_online = ii_repo_online. + mv_seed = iv_seed. + mv_sci_result = iv_sci_result. + mi_obj_filter = ii_obj_filter. + + " force refresh on stage, to make sure the latest local and remote files are used + IF ii_force_refresh = abap_true. + ii_repo_online->zif_abapgit_repo~refresh( ). + ENDIF. + + IF mv_seed IS INITIAL. " Generate based on time unless obtained from diff page + GET TIME STAMP FIELD lv_ts. + mv_seed = |stage{ lv_ts }|. + ENDIF. + + init_files( ). + + ENDMETHOD. + METHOD count_default_files_to_commit. + + FIELD-SYMBOLS LIKE LINE OF ms_files-status. + FIELD-SYMBOLS LIKE LINE OF ms_files-remote. + + rv_count = lines( ms_files-local ). + + LOOP AT ms_files-remote ASSIGNING . + READ TABLE ms_files-status ASSIGNING + WITH TABLE KEY + path = -path + filename = -filename. + ASSERT sy-subrc = 0. + + IF -lstate = zif_abapgit_definitions=>c_state-deleted + AND -rstate = zif_abapgit_definitions=>c_state-unchanged. + rv_count = rv_count + 1. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_stage. + + CREATE OBJECT lo_component + EXPORTING + ii_repo_online = ii_repo_online + iv_seed = iv_seed + iv_sci_result = iv_sci_result + ii_force_refresh = ii_force_refresh + ii_obj_filter = ii_obj_filter. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Stage' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD find_changed_by. + + DATA: ls_local LIKE LINE OF it_files-local, + ls_remote LIKE LINE OF it_files-remote, + ls_changed_by LIKE LINE OF rt_changed_by, + lt_changed_by_remote LIKE rt_changed_by, + ls_item TYPE zif_abapgit_definitions=>ty_item, + lv_transport LIKE LINE OF it_transports, + lv_user TYPE uname. + + FIELD-SYMBOLS LIKE LINE OF lt_changed_by_remote. + + LOOP AT it_files-local INTO ls_local WHERE NOT item IS INITIAL. + ls_changed_by-item = ls_local-item. + ls_changed_by-filename = ls_local-file-filename. + ls_changed_by-name = zcl_abapgit_objects=>changed_by( + is_item = ls_local-item + iv_filename = ls_local-file-filename ). + INSERT ls_changed_by INTO TABLE rt_changed_by. + ENDLOOP. + + LOOP AT it_files-remote INTO ls_remote WHERE filename IS NOT INITIAL. + TRY. + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = ls_remote-filename + iv_path = ls_remote-path + io_dot = mi_repo->get_dot_abapgit( ) + IMPORTING + es_item = ls_item ). + ls_changed_by-item = ls_item. + INSERT ls_changed_by INTO TABLE lt_changed_by_remote. + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + ENDLOOP. + + LOOP AT lt_changed_by_remote ASSIGNING . + " deleted files might still be in a transport + CLEAR lv_transport. + READ TABLE it_transports WITH KEY + obj_type = -item-obj_type + obj_name = -item-obj_name + INTO lv_transport. + IF sy-subrc = 0. + lv_user = zcl_abapgit_factory=>get_cts_api( )->read_user( lv_transport-trkorr ). + IF lv_user IS NOT INITIAL. + -name = lv_user. + ENDIF. + ENDIF. + IF -name IS INITIAL. + -name = zcl_abapgit_objects_super=>c_user_unknown. + ENDIF. + ENDLOOP. + + INSERT LINES OF lt_changed_by_remote INTO TABLE rt_changed_by. + + ENDMETHOD. + METHOD find_transports. + + DATA li_cts_api TYPE REF TO zif_abapgit_cts_api. + DATA lt_items TYPE zif_abapgit_definitions=>ty_items_tt. + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + DATA lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. + FIELD-SYMBOLS LIKE LINE OF it_files-local. + FIELD-SYMBOLS LIKE LINE OF it_files-remote. + li_cts_api = zcl_abapgit_factory=>get_cts_api( ). + + TRY. + LOOP AT it_files-local ASSIGNING WHERE item IS NOT INITIAL. + IF li_cts_api->is_chrec_possible_for_package( -item-devclass ) = abap_false. + RETURN. " Assume all other objects are also in packages without change recording + ENDIF. + APPEND -item TO lt_items. + ENDLOOP. + + lo_dot = mi_repo->get_dot_abapgit( ). + LOOP AT it_files-remote ASSIGNING WHERE filename IS NOT INITIAL. + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = -filename + iv_path = -path + io_dot = lo_dot + IMPORTING + es_item = ls_item ). + IF ls_item IS INITIAL. + CONTINUE. + ENDIF. + APPEND ls_item TO lt_items. + ENDLOOP. + + SORT lt_items BY obj_type obj_name. + DELETE ADJACENT DUPLICATES FROM lt_items COMPARING obj_type obj_name. + + rt_transports = li_cts_api->get_transports_for_list( lt_items ). + + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD get_page_patch. + + DATA: lv_key TYPE zif_abapgit_persistence=>ty_repo-key, + lt_files TYPE zif_abapgit_definitions=>ty_stage_tt. + + lv_key = mi_repo->get_key( ). + lt_files = io_stage->get_all( ). + + DELETE lt_files WHERE method <> zif_abapgit_definitions=>c_method-add + AND method <> zif_abapgit_definitions=>c_method-rm. + + ri_page = zcl_abapgit_gui_page_patch=>create( + iv_key = lv_key + it_files = lt_files ). + + ENDMETHOD. + METHOD init_files. + ms_files = zcl_abapgit_stage_logic=>get_stage_logic( )->get( ii_repo_online = mi_repo_online + ii_obj_filter = mi_obj_filter ). + + IF lines( ms_files-local ) = 0 AND lines( ms_files-remote ) = 0. + mi_repo->refresh( ). + zcx_abapgit_exception=>raise( 'There are no changes that could be staged' ). + ENDIF. + ENDMETHOD. + METHOD render_actions. + + DATA: lv_local_count TYPE i, + lv_add_all_txt TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + lv_local_count = count_default_files_to_commit( ). + IF lv_local_count > 0. + lv_add_all_txt = |Add All and Commit ({ lv_local_count })|. + " Otherwise empty, but the element (id) is preserved for JS + ENDIF. + + ri_html->add( '' ). + + " Action buttons + ri_html->add( '' ). + + " Filter bar + ri_html->add( '' ). + + ri_html->add( '' ). + ri_html->add( '
    ' ). + ri_html->add_a( iv_act = 'errorStub(event)' " Will be reinit by JS + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_id = 'commitSelectedButton' + iv_style = 'display: none' + iv_txt = 'Commit Selected ()' + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ri_html->add_a( iv_act = 'errorStub(event)' " Will be reinit by JS + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_id = 'commitFilteredButton' + iv_style = 'display: none' + iv_txt = 'Add Filtered and Commit ()' ). + ri_html->add_a( iv_act = |{ c_action-stage_all }| + iv_id = 'commitAllButton' + iv_txt = lv_add_all_txt ). + ri_html->add( '' ). + ri_html->add( '| ). + zcl_abapgit_gui_chunk_lib=>render_sci_result( + ii_html = ri_html + iv_sci_result = mv_sci_result ). + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_deferred_hidden_events. + + DATA ls_event TYPE zcl_abapgit_gui_chunk_lib=>ty_event_signature. + + ls_event-method = 'post'. + ls_event-name = 'stage_commit'. + ri_html = zcl_abapgit_gui_chunk_lib=>render_event_as_form( ls_event ). + ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). + + ENDMETHOD. + METHOD render_file. + + DATA: lv_param TYPE string, + lv_filename TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + lv_filename = is_file-path && is_file-filename. + " make sure whitespace is preserved in the DOM + REPLACE ALL OCCURRENCES OF ` ` IN lv_filename WITH ' '. + + ri_html->add( || ). + ri_html->add( '' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( + iv_lstate = is_status-lstate + iv_rstate = is_status-rstate ) ). + ri_html->add( '' ). + + CASE iv_context. + WHEN 'local'. + lv_param = zcl_abapgit_html_action_utils=>file_encode( + iv_key = mi_repo->get_key( ) + ig_file = is_file ). + + lv_filename = ri_html->a( + iv_txt = lv_filename + iv_act = |{ zif_abapgit_definitions=>c_action-go_file_diff }?{ lv_param }| ). + + ri_html->add( |{ is_item-obj_type }| ). + ri_html->add( |{ lv_filename }| ). + WHEN 'remote'. + ri_html->add( |{ is_item-obj_type }| ). + ri_html->add( |{ lv_filename }| ). + ENDCASE. + + ri_html->add( '' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name( iv_changed_by ) ). + ri_html->add( '' ). + + ri_html->add( '' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_transport( + iv_transport = iv_transport + iv_obj_type = is_item-obj_type + iv_obj_name = is_item-obj_name ) ). + ri_html->add( '' ). + + ri_html->add( '?' ). + ri_html->add( '' ). " Command added in JS + + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_list. + + DATA: lt_changed_by TYPE ty_changed_by_tt, + ls_changed_by LIKE LINE OF lt_changed_by, + lt_transports TYPE zif_abapgit_cts_api=>ty_transport_list, + ls_transport LIKE LINE OF lt_transports, + ls_item_remote TYPE zif_abapgit_definitions=>ty_item. + + FIELD-SYMBOLS: LIKE LINE OF ms_files-remote, + LIKE LINE OF ms_files-status, + LIKE LINE OF ms_files-local. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + + lt_transports = find_transports( ms_files ). + lt_changed_by = find_changed_by( + it_files = ms_files + it_transports = lt_transports ). + + " Local changes + LOOP AT ms_files-local ASSIGNING . + AT FIRST. + ri_html->add( '' ). + ri_html->add( '' ). " Diff state + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). " Status + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ENDAT. + + READ TABLE lt_changed_by INTO ls_changed_by WITH TABLE KEY + item = -item + filename = -file-filename. + IF sy-subrc <> 0. + READ TABLE lt_changed_by INTO ls_changed_by WITH KEY item = -item. + ENDIF. + + READ TABLE lt_transports INTO ls_transport WITH KEY + obj_type = -item-obj_type + obj_name = -item-obj_name. "#EC CI_SUBRC + READ TABLE ms_files-status ASSIGNING + WITH TABLE KEY + path = -file-path + filename = -file-filename. + ASSERT sy-subrc = 0. + + ri_html->add( render_file( + iv_context = 'local' + is_file = -file + is_item = -item + is_status = + iv_changed_by = ls_changed_by-name + iv_transport = ls_transport-trkorr ) ). + + CLEAR ls_transport. + + AT LAST. + ri_html->add( '' ). + ENDAT. + ENDLOOP. + + " Remote changes + LOOP AT ms_files-remote ASSIGNING . + AT FIRST. + ri_html->add( '' ). + ri_html->add( '' ). " Diff state + ri_html->add( '' ). " Type + ri_html->add( '' ). + ri_html->add( '' ). " Transport + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ENDAT. + + READ TABLE ms_files-status ASSIGNING + WITH TABLE KEY + path = -path + filename = -filename. + ASSERT sy-subrc = 0. + + TRY. + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = -filename + iv_path = -path + io_dot = mi_repo->get_dot_abapgit( ) + IMPORTING + es_item = ls_item_remote ). + READ TABLE lt_transports INTO ls_transport WITH KEY + obj_type = ls_item_remote-obj_type + obj_name = ls_item_remote-obj_name. + + READ TABLE lt_changed_by INTO ls_changed_by WITH TABLE KEY + item = ls_item_remote + filename = -filename. + IF sy-subrc <> 0. + READ TABLE lt_changed_by INTO ls_changed_by WITH KEY item = ls_item_remote. + ENDIF. + CATCH zcx_abapgit_exception. + CLEAR ls_transport. + ENDTRY. + + ri_html->add( render_file( + iv_context = 'remote' + is_status = + is_file = + is_item = ls_item_remote + iv_changed_by = ls_changed_by-name + iv_transport = ls_transport-trkorr ) ). + + AT LAST. + ri_html->add( '' ). + ENDAT. + ENDLOOP. + + ri_html->add( '
    TypeFileChanged byTransport' ). + ri_html->add( 'addreset↓' ). + ri_html->add( '
    Files to remove or non-code' ). + ri_html->add( 'ignoreremovereset↓' ). + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_main_language_warning. + + DATA lv_main_language TYPE spras. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + lv_main_language = mi_repo->get_dot_abapgit( )->get_main_language( ). + + IF lv_main_language <> sy-langu. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_warning_banner( + |Caution: Main language of the repo is '{ lv_main_language }', | + && |but you're logged on in '{ sy-langu }'| ) ). + ENDIF. + + ENDMETHOD. + METHOD render_scripts. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). + + ri_html->add( 'var gStageParams = {' ). + ri_html->add( | seed: "{ mv_seed }",| ). " Unique page id + ri_html->add( | user: "{ to_lower( sy-uname ) }",| ). + ri_html->add( ' formAction: "stage_commit",' ). + ri_html->add( | patchAction: "{ zif_abapgit_definitions=>c_action-go_patch }",| ). + ri_html->add( ' focusFilterKey: "f",' ). + + ri_html->add( ' ids: {' ). + ri_html->add( ' stageTab: "stageTab",' ). + ri_html->add( ' commitAllBtn: "commitAllButton",' ). + ri_html->add( ' commitSelectedBtn: "commitSelectedButton",' ). + ri_html->add( ' commitFilteredBtn: "commitFilteredButton",' ). + ri_html->add( ' patchBtn: "patchBtn",' ). + ri_html->add( ' objectSearch: "objectSearch",' ). + ri_html->add( ' }' ). + + ri_html->add( '}' ). + ri_html->add( 'var gHelper = new StageHelper(gStageParams);' ). + + ENDMETHOD. + METHOD stage_all. + + FIELD-SYMBOLS LIKE LINE OF ms_files-local. + FIELD-SYMBOLS LIKE LINE OF ms_files-remote. + FIELD-SYMBOLS LIKE LINE OF ms_files-status. + + CREATE OBJECT ro_stage. + + LOOP AT ms_files-local ASSIGNING . + READ TABLE ms_files-status ASSIGNING + WITH TABLE KEY + path = -file-path + filename = -file-filename. + ASSERT sy-subrc = 0. + + ro_stage->add( + iv_path = -file-path + iv_filename = -file-filename + is_status = + iv_data = -file-data ). + ENDLOOP. + + LOOP AT ms_files-remote ASSIGNING . + READ TABLE ms_files-status ASSIGNING + WITH TABLE KEY + path = -path + filename = -filename. + ASSERT sy-subrc = 0. + + IF -lstate = zif_abapgit_definitions=>c_state-deleted + AND -rstate = zif_abapgit_definitions=>c_state-unchanged. + + ro_stage->rm( + iv_path = -path + iv_filename = -filename + is_status = ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD stage_selected. + + ro_stage = kHGwlRuLHgbrJghgEvobFoEEqzmNhe=>get_instance( )->stage_selected( + ii_event = ii_event + it_status = ms_files-status + it_local = ms_files-local ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA: lo_stage TYPE REF TO zcl_abapgit_stage. + + CASE ii_event->mv_action. + WHEN c_action-stage_all. + + lo_stage = stage_all( ). + + rs_handled-page = zcl_abapgit_gui_page_commit=>create( + ii_repo_online = mi_repo_online + io_stage = lo_stage + iv_sci_result = mv_sci_result ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN c_action-stage_commit. + + lo_stage = stage_selected( ii_event ). + + rs_handled-page = zcl_abapgit_gui_page_commit=>create( + ii_repo_online = mi_repo_online + io_stage = lo_stage + iv_sci_result = mv_sci_result ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN c_action-stage_filter. + + mv_filter_value = ii_event->form_data( )->get( 'filterValue' ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + WHEN zif_abapgit_definitions=>c_action-go_patch. " Go Patch page + + lo_stage = stage_selected( ii_event ). + rs_handled-page = get_page_patch( lo_stage ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN c_action-stage_refresh. + mi_repo->refresh( abap_true ). + init_files( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-git_branch_switch. + zcl_abapgit_services_git=>switch_branch( |{ ii_event->query( )->get( 'KEY' ) }| ). + mi_repo->refresh( abap_true ). + init_files( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + + ls_hotkey_action-ui_component = 'Stage'. + ls_hotkey_action-description = |Patch|. + ls_hotkey_action-action = 'submitPatch'. " JS function in StageHelper + ls_hotkey_action-hotkey = |p|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Diff|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_repo_diff. + ls_hotkey_action-hotkey = |d|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Refresh|. + ls_hotkey_action-action = c_action-stage_refresh. + ls_hotkey_action-hotkey = |r|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + " registered/handled in js + ls_hotkey_action-description = |Focus filter|. + ls_hotkey_action-action = `#`. + ls_hotkey_action-hotkey = |f|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-staging' ). + + IF lines( ms_files-local ) > 0 OR lines( ms_files-remote ) > 0. + ro_toolbar->add( + iv_txt = 'Refresh' + iv_act = |{ c_action-stage_refresh }| + iv_opt = zif_abapgit_html=>c_html_opt-strong + )->add( + iv_txt = |Diff| + iv_act = |{ zif_abapgit_definitions=>c_action-go_repo_diff }?key={ mi_repo->get_key( ) }| + )->add( + iv_txt = |Patch| + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_id = |patchBtn| + )->add( + iv_txt = |Back| + iv_act = zif_abapgit_definitions=>c_action-go_back ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + iv_show_commit = abap_false + iv_interactive_branch = abap_true ) ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_js_error_banner( ) ). + ri_html->add( render_main_language_warning( ) ). + + ri_html->add( '
    ' ). + ri_html->add( render_actions( ) ). + ri_html->add( render_list( ) ). + ri_html->add( '
    ' ). + + ri_html->add( '
    ' ). + + gui_services( )->get_html_parts( )->add_part( + iv_collection = zcl_abapgit_gui_component=>c_html_parts-hidden_forms + ii_part = render_deferred_hidden_events( ) ). + register_deferred_script( render_scripts( ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_run_bckg IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_run_bckg. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Background Run' + io_page_menu = zcl_abapgit_gui_menus=>back( ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD run. + + DATA: lx_error TYPE REF TO zcx_abapgit_exception, + lv_text TYPE string, + lv_line TYPE i VALUE 1. + TRY. + zcl_abapgit_background=>run( ). + + DO. + READ LINE lv_line LINE VALUE INTO lv_text. + IF sy-subrc <> 0. + EXIT. + ENDIF. + APPEND lv_text TO mt_text. + lv_line = lv_line + 1. + ENDDO. + CATCH zcx_abapgit_exception INTO lx_error. + APPEND lx_error->get_text( ) TO mt_text. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA: lv_text LIKE LINE OF mt_text. + + register_handlers( ). + + run( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + LOOP AT mt_text INTO lv_text. + ri_html->add( '
    ' && lv_text && '

    ' ). + ENDLOOP. + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_repo_view IMPLEMENTATION. + METHOD apply_order_by. + + DATA: + lt_sort TYPE abap_sortorder_tab, + ls_sort LIKE LINE OF lt_sort, + lt_non_code_and_metadata_items LIKE ct_repo_items, + lt_code_items LIKE ct_repo_items, + lt_diff_items LIKE ct_repo_items, + li_persist_user TYPE REF TO zif_abapgit_persist_user. + + FIELD-SYMBOLS: + TYPE zif_abapgit_definitions=>ty_repo_item. + + IF mv_order_by IS INITIAL. + RETURN. + ENDIF. + + " we want to preserve non-code and metadata files at the top, + " so we isolate them and sort only the code artifacts + LOOP AT ct_repo_items ASSIGNING . + + IF -obj_type IS INITIAL AND -is_dir = abap_false. + INSERT INTO TABLE lt_non_code_and_metadata_items. + ELSE. + INSERT INTO TABLE lt_code_items. + ENDIF. + + ENDLOOP. + + IF mv_diff_first = abap_true. + " fix diffs on the top, right after non-code and metadata + LOOP AT lt_code_items ASSIGNING + WHERE changes > 0. + INSERT INTO TABLE lt_diff_items. + ENDLOOP. + + DELETE lt_code_items WHERE changes > 0. + ENDIF. + + ls_sort-descending = mv_order_descending. + ls_sort-astext = abap_true. + ls_sort-name = mv_order_by. + INSERT ls_sort INTO TABLE lt_sort. + + " Combine state fields for order of 'Status' column + IF mv_order_by = 'LSTATE'. + ls_sort-name = 'RSTATE'. + INSERT ls_sort INTO TABLE lt_sort. + ENDIF. + + " Use object name as secondary sort criteria + IF mv_order_by <> 'OBJ_NAME'. + ls_sort-name = 'OBJ_NAME'. + INSERT ls_sort INTO TABLE lt_sort. + ENDIF. + + TRY. + SORT lt_code_items STABLE BY (lt_sort). + SORT lt_diff_items STABLE BY (lt_sort). + + CATCH cx_sy_dyn_table_ill_comp_val. + CLEAR: mv_order_by, mv_order_descending. + li_persist_user = zcl_abapgit_persist_factory=>get_user( ). + li_persist_user->set_order_by( mv_order_by ). + li_persist_user->set_order_descending( mv_order_descending ). + RETURN. + ENDTRY. + + CLEAR: ct_repo_items. + + INSERT LINES OF lt_non_code_and_metadata_items INTO TABLE ct_repo_items. + INSERT LINES OF lt_diff_items INTO TABLE ct_repo_items. + INSERT LINES OF lt_code_items INTO TABLE ct_repo_items. + + " Files are listed under the object names so we always sort them by name + LOOP AT ct_repo_items ASSIGNING . + order_files( CHANGING ct_files = -files ). + ENDLOOP. + + ENDMETHOD. + METHOD build_advanced_dropdown. + + CREATE OBJECT ro_advanced_dropdown. + + ro_advanced_dropdown->add( iv_txt = 'Activate Objects' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_activate_objects }?key={ mv_key }| ). + + IF mi_repo->is_offline( ) = abap_false. " Online ? + ro_advanced_dropdown->add( + iv_txt = 'Transport to Branch' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_transport_to_branch }?key={ mv_key }| + iv_opt = get_crossout( zif_abapgit_auth=>c_authorization-transport_to_branch ) ). + ENDIF. + + IF mv_are_changes_recorded_in_tr = abap_true. + ro_advanced_dropdown->add( + iv_txt = 'Add All Objects to Transport' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_add_all_obj_to_trans_req }?key={ mv_key }| ). + ENDIF. + IF mi_repo->is_offline( ) = abap_true. + ro_advanced_dropdown->add( iv_txt = 'Export by Transport' + iv_act = |{ zif_abapgit_definitions=>c_action-zip_export_transport }?key={ mv_key }| ). + ELSE. + ro_advanced_dropdown->add( iv_txt = 'Stage by Transport' + iv_act = |{ zif_abapgit_definitions=>c_action-go_stage_transport }?key={ mv_key }| ). + ENDIF. + + ro_advanced_dropdown->add( iv_txt = 'Change Repository Package' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_change_package }?key={ mv_key }| ). + + ro_advanced_dropdown->add( iv_txt = 'Quality Assurance' + iv_typ = zif_abapgit_html=>c_action_type-separator ). + + ro_advanced_dropdown->add( iv_txt = 'Syntax Check' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_syntax_check }?key={ mv_key }| ). + ro_advanced_dropdown->add( iv_txt = 'Unit Test' + iv_act = |{ c_actions-go_unit }| ). + ro_advanced_dropdown->add( iv_txt = 'Run Code Inspector' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_code_inspector }?key={ mv_key }| ). + ro_advanced_dropdown->add( iv_txt = 'Where Used' + iv_act = |{ zif_abapgit_definitions=>c_action-where_used }?key={ mv_key }| ). + + ro_advanced_dropdown->add( iv_txt = 'Very Advanced' + iv_typ = zif_abapgit_html=>c_action_type-separator ). + + ro_advanced_dropdown->add( iv_txt = 'Update Local Checksums' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_refresh_checksums }?key={ mv_key }| + iv_opt = get_crossout( zif_abapgit_auth=>c_authorization-update_local_checksum ) ). + + ro_advanced_dropdown->add( iv_txt = 'Data Config' + iv_act = |{ c_actions-go_data }?key={ mv_key }| ). + + IF is_repo_lang_logon_lang( ) = abap_false AND zcl_abapgit_services_abapgit=>get_abapgit_tcode( ) IS NOT INITIAL. + ro_advanced_dropdown->add( + iv_txt = 'Open in Main Language' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_open_in_master_lang }?key={ mv_key }| ). + ENDIF. + + ro_advanced_dropdown->add( iv_txt = 'Danger' + iv_typ = zif_abapgit_html=>c_action_type-separator ). + + ro_advanced_dropdown->add( iv_txt = 'Remove Repository' + iv_title = `Remove abapGit's records of the repository (the system's ` + && `development objects will remain unaffected)` + iv_act = |{ zif_abapgit_definitions=>c_action-repo_remove }?key={ mv_key }| ). + + ro_advanced_dropdown->add( iv_txt = 'Remove Objects' + iv_title = `Delete all development objects belonging to this package ` + && `(and subpackages) from the system, but keep repository in abapGit` + iv_act = |{ zif_abapgit_definitions=>c_action-repo_delete_objects }?key={ mv_key }| ). + + ro_advanced_dropdown->add( iv_txt = 'Uninstall' + iv_title = `Delete all development objects belonging to this package ` + && `(and subpackages) from the system, and remove the repository from abapGit` + iv_act = |{ zif_abapgit_definitions=>c_action-repo_purge }?key={ mv_key }| + iv_opt = get_crossout( + iv_authorization = zif_abapgit_auth=>c_authorization-uninstall + iv_protected = abap_true ) ). + + ENDMETHOD. + METHOD build_branch_dropdown. + + CREATE OBJECT ro_branch_dropdown. + + IF mi_repo->is_offline( ) = abap_true. + RETURN. + ENDIF. + + ro_branch_dropdown->add( iv_txt = 'Switch' + iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_switch }?key={ mv_key }| ). + ro_branch_dropdown->add( iv_txt = 'Create' + iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_create }?key={ mv_key }| ). + ro_branch_dropdown->add( iv_txt = 'Delete' + iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_delete }?key={ mv_key }| ). + ro_branch_dropdown->add( iv_txt = 'Merge' + iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_merge }?key={ mv_key }| ). + + ENDMETHOD. + METHOD build_dir_jump_link. + + DATA lv_path TYPE string. + DATA lv_encode TYPE string. + DATA li_html TYPE REF TO zif_abapgit_html. + + CREATE OBJECT li_html TYPE zcl_abapgit_html. + + lv_path = iv_path. + REPLACE FIRST OCCURRENCE OF mv_cur_dir IN lv_path WITH ''. + lv_encode = zcl_abapgit_html_action_utils=>dir_encode( lv_path ). + + " remove leading and trailing / for display + IF lv_path <> '/'. + IF lv_path(1) = '/'. + lv_path = lv_path+1. + ENDIF. + IF substring( val = reverse( lv_path ) + len = 1 ) = '/'. + lv_path = substring( val = lv_path + len = strlen( lv_path ) - 1 ). + ENDIF. + ENDIF. + + rv_html = li_html->a( + iv_txt = lv_path + iv_act = |{ c_actions-change_dir }?{ lv_encode }| ). + + ENDMETHOD. + METHOD build_inactive_object_code. + + IF is_item-inactive = abap_true. + rv_inactive_html_code = zcl_abapgit_html=>icon( + iv_name = 'bolt/orange' + iv_hint = 'Object or object part is inactive' + iv_class = 'inactive' ). + ENDIF. + + ENDMETHOD. + METHOD build_main_toolbar. + + DATA: + li_log TYPE REF TO zif_abapgit_log. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'actionbar-repo-view' ). + + IF mi_repo->is_offline( ) = abap_false. + " online repo + + ro_toolbar->add( iv_txt = 'Pull' + iv_act = |{ zif_abapgit_definitions=>c_action-git_pull }?key={ mv_key }| + iv_opt = get_crossout( iv_protected = abap_true + iv_strong = abap_true ) ). + ro_toolbar->add( iv_txt = 'Stage' + iv_act = |{ zif_abapgit_definitions=>c_action-go_stage }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + + IF mo_repo_aggregated_state->is_unchanged( ) = abap_false. " Any changes + ro_toolbar->add( iv_txt = 'Patch' + iv_act = |{ zif_abapgit_definitions=>c_action-go_patch }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ro_toolbar->add( iv_txt = 'Diff' + iv_act = |{ zif_abapgit_definitions=>c_action-go_repo_diff }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ENDIF. + li_log = mi_repo->get_log( ). + IF li_log IS BOUND AND li_log->count( ) > 0. + ro_toolbar->add( iv_txt = 'Log' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_log }?key={ mv_key }| ). + ENDIF. + ro_toolbar->add( iv_txt = 'Branch' + io_sub = build_branch_dropdown( ) ). + ro_toolbar->add( iv_txt = 'Tag' + io_sub = build_tag_dropdown( ) ). + + ELSE. + " offline repo + + IF mi_repo->has_remote_source( ) = abap_true AND mo_repo_aggregated_state->is_unchanged( ) = abap_false. + ro_toolbar->add( iv_txt = 'Pull zip' + iv_act = |{ zif_abapgit_definitions=>c_action-git_pull }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ro_toolbar->add( iv_txt = 'Diff' + iv_act = |{ zif_abapgit_definitions=>c_action-go_repo_diff }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ENDIF. + ro_toolbar->add( iv_txt = 'Import zip' + iv_act = |{ zif_abapgit_definitions=>c_action-zip_import }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + IF mi_repo->get_local_settings( )-write_protected = abap_true. + ro_toolbar->add( iv_txt = 'Compare rfc' + iv_act = |{ zif_abapgit_definitions=>c_action-rfc_compare }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ENDIF. + ro_toolbar->add( iv_txt = 'Export zip' + iv_act = |{ zif_abapgit_definitions=>c_action-zip_export }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + li_log = mi_repo->get_log( ). + IF li_log IS BOUND AND li_log->count( ) > 0. + ro_toolbar->add( iv_txt = 'Log' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_log }?key={ mv_key }| ). + ENDIF. + + ENDIF. + + ro_toolbar->add( iv_txt = 'Advanced' + io_sub = build_advanced_dropdown( ) ). + + ro_toolbar->add( iv_txt = 'View' + io_sub = build_view_dropdown( ) ). + + ro_toolbar->add( iv_txt = 'Refresh' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_refresh }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + + ro_toolbar->add( iv_txt = 'Repo Settings' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_settings }?key={ mv_key }| + iv_opt = zif_abapgit_html=>c_html_opt-strong + iv_title = `Repository Settings` ). + + ENDMETHOD. + METHOD build_origlang_code. + + IF is_item-origlang IS NOT INITIAL AND is_item-origlang <> mi_repo->get_dot_abapgit( )->get_main_language( ). + rv_html_code = zcl_abapgit_html=>icon( + iv_name = 'language-solid/grey' + iv_hint = |Original language: { is_item-origlang }| + iv_class = 'cursor-pointer' ). + ENDIF. + + ENDMETHOD. + METHOD build_srcsystem_code. + + IF is_item-srcsystem IS NOT INITIAL AND is_item-srcsystem <> sy-sysid. + rv_srcsystem_html_code = zcl_abapgit_html=>icon( + iv_name = 'server-solid/grey' + iv_hint = |Original system: { is_item-srcsystem }| + iv_class = 'cursor-pointer' ). + ENDIF. + + ENDMETHOD. + METHOD build_tag_dropdown. + + CREATE OBJECT ro_tag_dropdown. + + IF mi_repo->is_offline( ) = abap_true. + RETURN. + ENDIF. + + ro_tag_dropdown->add( iv_txt = 'Switch' + iv_act = |{ zif_abapgit_definitions=>c_action-git_tag_switch }?key={ mv_key }| ). + ro_tag_dropdown->add( iv_txt = 'Create' + iv_act = |{ zif_abapgit_definitions=>c_action-git_tag_create }?key={ mv_key }| ). + ro_tag_dropdown->add( iv_txt = 'Delete' + iv_act = |{ zif_abapgit_definitions=>c_action-git_tag_delete }?key={ mv_key }| ). + ENDMETHOD. + METHOD build_view_dropdown. + + CREATE OBJECT ro_toolbar. + + ro_toolbar->add( + iv_txt = 'Changes First' + iv_chk = mv_diff_first + iv_act = c_actions-toggle_diff_first ). + + ro_toolbar->add( + iv_txt = 'Changes Only' + iv_chk = mv_changes_only + iv_act = c_actions-toggle_changes ). + + ro_toolbar->add( + iv_txt = 'File Paths' + iv_chk = boolc( NOT mv_hide_files = abap_true ) + iv_act = c_actions-toggle_hide_files ). + + ro_toolbar->add( + iv_txt = 'Folders' + iv_chk = mv_show_folders + iv_act = c_actions-toggle_folders ). + + ENDMETHOD. + METHOD check_branch. + + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + + IF mi_repo->is_offline( ) = abap_false. + li_repo_online ?= mi_repo. + li_repo_online->check_for_valid_branch( ). + ENDIF. + + ENDMETHOD. + METHOD check_connection. + + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + + mv_connection_error = abap_true. + + IF mi_repo->is_offline( ) = abap_false. + li_repo_online ?= mi_repo. + zcl_abapgit_http=>check_connection( li_repo_online->get_url( ) ). + ENDIF. + + mv_connection_error = abap_false. + + ENDMETHOD. + METHOD constructor. + + DATA: lo_settings TYPE REF TO zcl_abapgit_settings, + lx_error TYPE REF TO zcx_abapgit_exception, + lo_persistence_user TYPE REF TO zif_abapgit_persist_user. + + super->constructor( ). + + TRY. + lo_persistence_user = zcl_abapgit_persist_factory=>get_user( ). + + mv_key = iv_key. + mi_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + mv_cur_dir = '/'. " Root + + mv_hide_files = lo_persistence_user->get_hide_files( ). + mv_changes_only = lo_persistence_user->get_changes_only( ). + mv_order_by = lo_persistence_user->get_order_by( ). + mv_order_descending = lo_persistence_user->get_order_descending( ). + mv_diff_first = lo_persistence_user->get_diff_first( ). + mv_show_folders = lo_persistence_user->get_show_folders( ). + + " Read global settings to get max # of objects to be listed + lo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + mv_max_lines = lo_settings->get_max_lines( ). + mv_max_setting = mv_max_lines. + + CATCH zcx_abapgit_exception INTO lx_error. + " Reset 'last shown repo' so next start will go to repo overview + " and allow troubleshooting of issue + zcl_abapgit_persist_factory=>get_user( )->set_repo_show( || ). + + RAISE EXCEPTION lx_error. + ENDTRY. + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_repo_view. + + CREATE OBJECT lo_component + EXPORTING + iv_key = iv_key. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Repository' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_crossout. + IF iv_strong = abap_true. + rv_crossout = zif_abapgit_html=>c_html_opt-strong. + ENDIF. + IF iv_protected = abap_true AND mi_repo->get_local_settings( )-write_protected = abap_true. + rv_crossout = zif_abapgit_html=>c_html_opt-crossout. + ENDIF. + IF iv_authorization IS NOT INITIAL AND zcl_abapgit_auth=>is_allowed( iv_authorization ) = abap_false. + rv_crossout = zif_abapgit_html=>c_html_opt-crossout. + ENDIF. + ENDMETHOD. + METHOD get_item_class. + + DATA lt_class TYPE TABLE OF string. + + IF iv_is_object_row = abap_true. + APPEND 'object_row' TO lt_class. + ELSE. + APPEND 'file_row' TO lt_class. + ENDIF. + + IF is_item-is_dir = abap_true. + APPEND 'folder' TO lt_class. + ELSEIF is_item-changes > 0. + APPEND 'modified' TO lt_class. + ELSEIF is_item-obj_name IS INITIAL. + APPEND 'unsupported' TO lt_class. + ENDIF. + + IF lines( lt_class ) > 0. + rv_html = | class="{ concat_lines_of( table = lt_class + sep = ` ` ) }"|. + ENDIF. + + ENDMETHOD. + METHOD is_repo_lang_logon_lang. + rv_repo_lang_is_logon_lang = boolc( mi_repo->get_dot_abapgit( )->get_main_language( ) = sy-langu ). + ENDMETHOD. + METHOD open_in_main_language. + + DATA: + lv_main_language TYPE spras, + ls_item TYPE zif_abapgit_definitions=>ty_item, + lv_tcode TYPE tcode. + + lv_main_language = mi_repo->get_dot_abapgit( )->get_main_language( ). + lv_tcode = zcl_abapgit_services_abapgit=>get_abapgit_tcode( ). + ASSERT lv_tcode IS NOT INITIAL. + + IF lv_main_language = sy-langu. + zcx_abapgit_exception=>raise( |Repo already opened in main language| ). + ENDIF. + + ls_item-obj_name = lv_tcode. + ls_item-obj_type = |TRAN|. + + IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. + zcx_abapgit_exception=>raise( |Please install the abapGit repository| ). + ENDIF. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_abapgit( + iv_language = lv_main_language + iv_key = mi_repo->get_key( ) ). + + ENDMETHOD. + METHOD order_files. + + DATA: + lt_sort TYPE abap_sortorder_tab, + ls_sort LIKE LINE OF lt_sort. + + IF lines( ct_files ) = 0. + RETURN. + ENDIF. + + ls_sort-descending = mv_order_descending. + ls_sort-astext = abap_true. + ls_sort-name = 'PATH'. + INSERT ls_sort INTO TABLE lt_sort. + + ls_sort-descending = mv_order_descending. + ls_sort-astext = abap_true. + ls_sort-name = 'FILENAME'. + INSERT ls_sort INTO TABLE lt_sort. + + SORT ct_files STABLE BY (lt_sort). + + ENDMETHOD. + METHOD render_file_command. + + DATA: lv_difflink TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + IF is_file-is_changed = abap_true. + lv_difflink = zcl_abapgit_html_action_utils=>file_encode( + iv_key = mi_repo->get_key( ) + ig_file = is_file ). + ri_html->add_a( iv_txt = 'diff' + iv_act = |{ zif_abapgit_definitions=>c_action-go_file_diff }?{ lv_difflink }| ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = is_file-lstate + iv_rstate = is_file-rstate ) ). + ELSE. + ri_html->add( ' ' ). + ENDIF. + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_head_line. + + DATA: + lo_toolbar TYPE REF TO zcl_abapgit_html_toolbar, + ls_settings TYPE zif_abapgit_persist_user=>ty_s_user_settings, + lo_label_colors TYPE REF TO zcl_abapgit_string_map, + lt_labels TYPE string_table. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + lo_toolbar = build_main_toolbar( ). + + ri_html->add( '
    ' ). + ri_html->add( '' ). + + IF mv_show_folders = abap_true. + ri_html->add( '' ). + ENDIF. + + lt_labels = zcl_abapgit_repo_labels=>split( mi_repo->ms_data-local_settings-labels ). + + IF lines( lt_labels ) > 0. + ls_settings = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_user_settings( ). + lo_label_colors = zcl_abapgit_repo_labels=>split_colors_into_map( ls_settings-label_colors ). + + ri_html->td( + iv_content = zcl_abapgit_gui_chunk_lib=>render_label_list( + it_labels = lt_labels + io_label_colors = lo_label_colors ) + iv_class = 'labels' ). + ENDIF. + + ri_html->add( '' ). + ri_html->add( '
    ' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_path( mv_cur_dir ) ). + ri_html->add( '' ). + ri_html->add( lo_toolbar->render( iv_right = abap_true ) ). + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_item. + + DATA: lv_link TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( || ). + + IF is_item-obj_name IS INITIAL AND is_item-is_dir = abap_false. + ri_html->add( || + && '' + && 'non-code and meta files' + && '' ). + ELSE. + ri_html->add( |{ zcl_abapgit_gui_chunk_lib=>get_item_icon( is_item ) }| ). + + IF is_item-is_dir = abap_true. " Subdir + lv_link = build_dir_jump_link( is_item-path ). + ri_html->add( |{ lv_link }| ). + ELSE. + lv_link = zcl_abapgit_gui_chunk_lib=>get_item_link( is_item ). + ri_html->add( |{ is_item-obj_type }| ). + ri_html->add( |{ lv_link } { build_inactive_object_code( is_item ) + } { build_srcsystem_code( is_item ) } { build_origlang_code( is_item ) }| ). + ENDIF. + ENDIF. + + " Changed by + ri_html->add( '' ). + ri_html->add( render_item_changed_by( is_item ) ). + ri_html->add( '' ). + + IF iv_render_transports = abap_true. + ri_html->add( render_item_transport( is_item ) ). + ENDIF. + + " Command + ri_html->add( '' ). + IF mi_repo->has_remote_source( ) = abap_true. + ri_html->add( render_item_command( is_item ) ). + ENDIF. + ri_html->add( '' ). + + ri_html->add( '' ). + + ri_html->add( render_item_files( is_item ) ). + + ENDMETHOD. + METHOD render_item_changed_by. + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF is_item-changes = 0 OR is_item-changed_by IS INITIAL. + ri_html->add( ' ' ). + ELSE. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name( is_item-changed_by ) ). + ENDIF. + + ENDMETHOD. + METHOD render_item_command. + + DATA lv_difflink TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF is_item-is_dir = abap_true. " Directory + ri_html->add( '
    ' ). + ri_html->add( |{ is_item-changes } changes| ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = is_item-lstate + iv_rstate = is_item-rstate ) ). + ri_html->add( '
    ' ). + + ELSEIF is_item-changes > 0. + IF mv_hide_files = abap_true AND is_item-obj_name IS NOT INITIAL. + + lv_difflink = zcl_abapgit_html_action_utils=>obj_encode( + iv_key = mi_repo->get_key( ) + ig_object = is_item ). + + ri_html->add( '
    ' ). + ri_html->add_a( iv_txt = |diff ({ is_item-changes })| + iv_act = |{ zif_abapgit_definitions=>c_action-go_file_diff }?{ lv_difflink }| ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = is_item-lstate + iv_rstate = is_item-rstate ) ). + ri_html->add( '
    ' ). + + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD render_item_files. + + DATA: ls_file LIKE LINE OF is_item-files. + DATA li_exit TYPE REF TO zif_abapgit_exit. + DATA lv_filename TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF mv_hide_files = abap_true AND is_item-obj_type IS NOT INITIAL. + RETURN. + ENDIF. + + li_exit = zcl_abapgit_exit=>get_instance( ). + + LOOP AT is_item-files INTO ls_file. + ri_html->add( || ). + + ri_html->add( || ). + + ri_html->add( || ). + ri_html->add( || ). + + IF mv_show_folders = abap_true. + lv_filename = ls_file-filename. + ELSE. + lv_filename = ls_file-path && ls_file-filename. + ENDIF. + + lv_filename = li_exit->adjust_display_filename( + is_repo_meta = mi_repo->ms_data + iv_filename = lv_filename ). + + ri_html->add( |
    { lv_filename }
    | ). + + ri_html->add( || ). + + " Changed by (not applicable to file) + ri_html->add( '' ). + ri_html->add( '' ). + + " Transport (not applicable to file) + IF mv_are_changes_recorded_in_tr = abap_true. + ri_html->add( `` ). + ENDIF. + + " Command + ri_html->add( '' ). + IF mi_repo->has_remote_source( ) = abap_true. + ri_html->add( render_file_command( ls_file ) ). + ENDIF. + ri_html->add( '' ). + + ri_html->add( '' ). + + ENDLOOP. + + ENDMETHOD. + METHOD render_item_transport. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_transport( + iv_transport = is_item-transport + iv_obj_type = is_item-obj_type + iv_obj_name = is_item-obj_name ) ). + + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_parent_dir. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + ri_html->add( |{ ri_html->icon( 'folder' ) }| ). + ri_html->add( |{ build_dir_jump_link( '..' ) }| ). + IF mi_repo->has_remote_source( ) = abap_true. + ri_html->add( || ). " Dummy for online + ENDIF. + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_scripts. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_palette( + iv_action = zif_abapgit_definitions=>c_action-go_repo ) ). + + ENDMETHOD. + METHOD render_table_footer. + + DATA lv_action TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF mv_changes_only = abap_true. + lv_action = ri_html->a( + iv_txt = 'Show All' + iv_act = c_actions-toggle_changes ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_table_footer( |(Only changes are shown. { lv_action })| ) ). + ENDIF. + + ENDMETHOD. + METHOD render_table_header. + + DATA: + lt_col_spec TYPE zcl_abapgit_gui_chunk_lib=>ty_col_spec_tt, + ls_col_spec TYPE zcl_abapgit_gui_chunk_lib=>ty_col_spec. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + " icon + APPEND INITIAL LINE TO lt_col_spec. + + ls_col_spec-tech_name = 'OBJ_TYPE'. + ls_col_spec-display_name = 'Type'. + ls_col_spec-allow_order_by = abap_true. + APPEND ls_col_spec TO lt_col_spec. + + ls_col_spec-tech_name = 'OBJ_NAME'. + ls_col_spec-display_name = 'Name'. + ls_col_spec-allow_order_by = abap_true. + APPEND ls_col_spec TO lt_col_spec. + + ls_col_spec-tech_name = 'CHANGED_BY'. + ls_col_spec-display_name = 'Changed by'. + ls_col_spec-allow_order_by = abap_true. + APPEND ls_col_spec TO lt_col_spec. + + IF mv_are_changes_recorded_in_tr = abap_true. + ls_col_spec-tech_name = 'TRANSPORT'. + ls_col_spec-display_name = 'Transport'. + ls_col_spec-allow_order_by = abap_true. + APPEND ls_col_spec TO lt_col_spec. + ENDIF. + + ls_col_spec-tech_name = 'LSTATE'. + ls_col_spec-display_name = 'Status'. + ls_col_spec-allow_order_by = abap_true. + ls_col_spec-css_class = 'cmd'. + APPEND ls_col_spec TO lt_col_spec. + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_table_header( + it_col_spec = lt_col_spec + iv_order_by = mv_order_by + iv_order_descending = mv_order_descending ) ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA lv_path TYPE string. + DATA lv_key TYPE zif_abapgit_persistence=>ty_value. + + lv_key = ii_event->query( )->get( 'KEY' ). + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-go_repo. " Switch to another repo + rs_handled-page = create( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. + + WHEN c_actions-go_data. + rs_handled-page = zcl_abapgit_gui_page_data=>create( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN c_actions-go_unit. + rs_handled-page = zcl_abapgit_gui_page_runit=>create( mi_repo ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN c_actions-toggle_hide_files. " Toggle file display + mv_hide_files = zcl_abapgit_persist_factory=>get_user( )->toggle_hide_files( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_actions-change_dir. " Change dir + lv_path = ii_event->query( )->get( 'PATH' ). + mv_cur_dir = zcl_abapgit_path=>change_dir( + iv_cur_dir = mv_cur_dir + iv_cd = lv_path ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_actions-toggle_folders. " Toggle folder view + mv_show_folders = zcl_abapgit_persist_factory=>get_user( )->toggle_show_folders( ). + mv_cur_dir = '/'. " Root + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_actions-toggle_changes. " Toggle changes only view + mv_changes_only = zcl_abapgit_persist_factory=>get_user( )->toggle_changes_only( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_actions-toggle_diff_first. + mv_diff_first = zcl_abapgit_persist_factory=>get_user( )->set_diff_first( + boolc( mv_diff_first = abap_false ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_actions-display_more. " Increase MAX lines limit + mv_max_lines = mv_max_lines + mv_max_setting. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN zif_abapgit_definitions=>c_action-change_order_by. + mv_order_by = zcl_abapgit_persist_factory=>get_user( )->set_order_by( + ii_event->query( )->get( 'ORDERBY' ) ). + mv_order_descending = zcl_abapgit_persist_factory=>get_user( )->set_order_descending( abap_false ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN zif_abapgit_definitions=>c_action-direction. + mv_order_descending = zcl_abapgit_persist_factory=>get_user( )->set_order_descending( + boolc( ii_event->query( )->get( 'DIRECTION' ) = 'DESCENDING' ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN zif_abapgit_definitions=>c_action-repo_open_in_master_lang. + open_in_main_language( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + ls_hotkey_action-ui_component = 'Repo'. + + ls_hotkey_action-description = |Stage|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_stage. + ls_hotkey_action-hotkey = |s|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Switch Branch|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-git_branch_switch. + ls_hotkey_action-hotkey = |b|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Repository List|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-abapgit_home. + ls_hotkey_action-hotkey = |o|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Refresh Repository|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_refresh. + ls_hotkey_action-hotkey = |r|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Pull|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-git_pull. + ls_hotkey_action-hotkey = |p|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Patch|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_patch. + ls_hotkey_action-hotkey = |a|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Diff|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_repo_diff. + ls_hotkey_action-hotkey = |d|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Uninstall Repository|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_purge. + ls_hotkey_action-hotkey = |u|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Run Syntax Check|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_syntax_check. + ls_hotkey_action-hotkey = |c|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Run Unit Tests|. + ls_hotkey_action-action = c_actions-go_unit. + ls_hotkey_action-hotkey = |t|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Run Code Inspector|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_code_inspector. + ls_hotkey_action-hotkey = |i|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Show Log|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_log. + ls_hotkey_action-hotkey = |l|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-repo-view' ). + + ro_toolbar->add( + iv_txt = zcl_abapgit_gui_buttons=>repo_list( ) + iv_act = zif_abapgit_definitions=>c_action-abapgit_home + )->add( + iv_txt = zcl_abapgit_gui_buttons=>help( ) + io_sub = zcl_abapgit_gui_menus=>help( ) ). + + zcl_abapgit_gui_menus=>experimental( ro_toolbar ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA: lt_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt, + lo_browser TYPE REF TO zcl_abapgit_repo_content_list, + lx_error TYPE REF TO zcx_abapgit_exception, + lv_max TYPE abap_bool, + lv_max_str TYPE string, + lv_add_str TYPE string, + li_log TYPE REF TO zif_abapgit_log, + lv_msg TYPE string, + lo_news TYPE REF TO zcl_abapgit_repo_news. + + FIELD-SYMBOLS LIKE LINE OF lt_repo_items. + + register_handlers( ). + + CREATE OBJECT mo_repo_aggregated_state. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + TRY. + " Reinit, for the case of type change + mi_repo = zcl_abapgit_repo_srv=>get_instance( )->get( mi_repo->get_key( ) ). + + IF mv_connection_error = abap_true. + " If connection doesn't work, render a minimal header + ri_html->add( |
    | ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + iv_show_edit = abap_true + iv_show_branch = abap_false + iv_show_commit = abap_false + iv_interactive_branch = abap_false ) ). + ri_html->add( '
    ' ). + + ri_html->add( render_head_line( ) ). + + " Reset error flag to try connecting again next time + CLEAR mv_connection_error. + RETURN. + ENDIF. + + check_connection( ). + + check_branch( ). + + mv_are_changes_recorded_in_tr = zcl_abapgit_factory=>get_sap_package( mi_repo->get_package( ) + )->are_changes_recorded_in_tr_req( ). + + lo_news = zcl_abapgit_repo_news=>create( mi_repo ). + + ri_html->add( |
    | ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + io_news = lo_news + iv_show_edit = abap_true + iv_interactive_branch = abap_true ) ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_news( io_news = lo_news ) ). + + zcl_abapgit_exit=>get_instance( )->wall_message_repo( + is_repo_meta = mi_repo->ms_data + ii_html = ri_html ). + + CREATE OBJECT lo_browser + EXPORTING + ii_repo = mi_repo. + + lt_repo_items = lo_browser->list( iv_path = mv_cur_dir + iv_by_folders = mv_show_folders + iv_changes_only = mv_changes_only + iv_transports = mv_are_changes_recorded_in_tr ). + + apply_order_by( CHANGING ct_repo_items = lt_repo_items ). + + LOOP AT lt_repo_items ASSIGNING . + mo_repo_aggregated_state->sum_with_repo_item( ). + ENDLOOP. + + ri_html->add( render_head_line( ) ). + + li_log = lo_browser->get_log( ). + IF li_log->count( ) > 0. + ri_html->add( '
    ' ). + ri_html->add( zcl_abapgit_log_viewer=>to_html( li_log ) ). " shows eg. list of unsupported objects + ri_html->add( '
    ' ). + ENDIF. + + ri_html->add( '
    ' ). + + CLEAR lv_msg. + + IF lines( lt_repo_items ) = 0. + IF mv_changes_only = abap_true. + IF mi_repo->is_offline( ) = abap_true. + " Offline match banner + IF mi_repo->has_remote_source( ) = abap_true. + lv_msg = 'Local state completely matches the ZIP file'. + ELSE. + lv_msg = 'Import a ZIP file to see if there are any changes'. + ENDIF. + ELSE. + " Online match banner + lv_msg = 'Local state completely matches the remote repository'. + ENDIF. + ELSE. + lv_msg = |Package is empty. Show { build_dir_jump_link( 'parent' ) } package|. + ENDIF. + ELSE. + " Repo content table + ri_html->add( '' ). + + ri_html->add( render_table_header( ) ). + + IF zcl_abapgit_path=>is_root( mv_cur_dir ) = abap_false. + ri_html->add( render_parent_dir( ) ). + ENDIF. + + LOOP AT lt_repo_items ASSIGNING . + IF mv_max_lines > 0 AND sy-tabix > mv_max_lines. + lv_max = abap_true. + EXIT. " current loop + ENDIF. + ri_html->add( render_item( is_item = + iv_render_transports = mv_are_changes_recorded_in_tr ) ). + ENDLOOP. + + ri_html->add( render_table_footer( ) ). + + ri_html->add( '
    ' ). + ENDIF. + + IF NOT lv_msg IS INITIAL. + ri_html->add( |
    { lv_msg }
    | ). + ENDIF. + + IF lv_max = abap_true. + ri_html->add( '
    ' ). + IF mv_max_lines = 1. + lv_max_str = '1 object'. + ELSE. + lv_max_str = |first { mv_max_lines } objects|. + ENDIF. + lv_add_str = |+{ mv_max_setting }|. + ri_html->add( |Only { lv_max_str } objects shown in list. Display { + ri_html->a( iv_txt = lv_add_str + iv_act = c_actions-display_more ) + } more (change in Settings > { + ri_html->a( iv_txt = 'Personal Settings' + iv_act = zif_abapgit_definitions=>c_action-go_settings_personal ) + })| ). + ri_html->add( '
    ' ). + ENDIF. + + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + CATCH zcx_abapgit_exception INTO lx_error. + " Reset 'last shown repo' so next start will go to repo overview + " and allow troubleshooting of issue + zcl_abapgit_persist_factory=>get_user( )->set_repo_show( || ). + + RAISE EXCEPTION lx_error. + ENDTRY. + + register_deferred_script( render_scripts( ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlZbCwKVqbmulVBzOHKguCDENGa DEFINITION DEFERRED. +* renamed: zcl_abapgit_gui_page_repo_over :: lcl_table_scheme +CLASS kHGwlZbCwKVqbmulVBzOHKguCDENGa DEFINITION FINAL. + " TODO: move to a global class, when table is separated as a component + PUBLIC SECTION. + DATA mt_col_spec TYPE zcl_abapgit_gui_chunk_lib=>ty_col_spec_tt READ-ONLY. + + METHODS add_column + IMPORTING + iv_tech_name TYPE string OPTIONAL + iv_display_name TYPE string OPTIONAL + iv_css_class TYPE string OPTIONAL + iv_add_tz TYPE abap_bool OPTIONAL + iv_title TYPE string OPTIONAL + iv_allow_order_by TYPE any OPTIONAL + RETURNING + VALUE(ro_me) TYPE REF TO kHGwlZbCwKVqbmulVBzOHKguCDENGa. + +ENDCLASS. + +CLASS kHGwlZbCwKVqbmulVBzOHKguCDENGa IMPLEMENTATION. + + METHOD add_column. + + FIELD-SYMBOLS LIKE LINE OF mt_col_spec. + APPEND INITIAL LINE TO mt_col_spec ASSIGNING . + -display_name = iv_display_name. + -tech_name = iv_tech_name. + -title = iv_title. + -css_class = iv_css_class. + -add_tz = iv_add_tz. + -allow_order_by = iv_allow_order_by. + + ro_me = me. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. + METHOD apply_filter. + + DATA lv_pfxl TYPE i. + DATA lv_idx TYPE i. + DATA lv_filter_label TYPE string. + FIELD-SYMBOLS LIKE LINE OF ct_overview. + + IF ms_list_settings-filter IS INITIAL. + RETURN. + ENDIF. + + lv_pfxl = strlen( c_label_filter_prefix ). + + IF strlen( ms_list_settings-filter ) > lv_pfxl AND ms_list_settings-filter+0(lv_pfxl) = c_label_filter_prefix. + lv_filter_label = ms_list_settings-filter+lv_pfxl. + IF lv_filter_label = 'all'. + DELETE ct_overview WHERE labels IS INITIAL. + ELSEIF lv_filter_label = 'none'. + DELETE ct_overview WHERE labels IS NOT INITIAL. + ELSE. + LOOP AT ct_overview ASSIGNING . + lv_idx = sy-tabix. + READ TABLE -labels TRANSPORTING NO FIELDS WITH KEY table_line = lv_filter_label. + IF sy-subrc <> 0. + DELETE ct_overview INDEX lv_idx. + ENDIF. + ENDLOOP. + ENDIF. + ELSE. " Regular filter + DELETE ct_overview WHERE + key NS ms_list_settings-filter + AND name NS ms_list_settings-filter + AND url NS ms_list_settings-filter + AND package NS ms_list_settings-filter + AND branch NS ms_list_settings-filter + AND created_by NS ms_list_settings-filter + AND created_at NS ms_list_settings-filter + AND deserialized_by NS ms_list_settings-filter + AND deserialized_at NS ms_list_settings-filter. + ENDIF. + + ENDMETHOD. + METHOD apply_order_by. + + DATA: + lt_sort TYPE abap_sortorder_tab, + ls_sort LIKE LINE OF lt_sort. + + ls_sort-name = 'FAVORITE'. + ls_sort-descending = abap_true. + ls_sort-astext = abap_true. + INSERT ls_sort INTO TABLE lt_sort. + + IF ms_list_settings-order_by IS NOT INITIAL. + + CLEAR ls_sort. + + IF ms_list_settings-order_by = 'CREATED_AT' OR ms_list_settings-order_by = 'DESERIALIZED_AT'. + ls_sort-name = ms_list_settings-order_by && c_raw_field_suffix. + ELSE. + ls_sort-name = ms_list_settings-order_by. + ls_sort-astext = abap_true. + ENDIF. + + ls_sort-descending = ms_list_settings-order_descending. + INSERT ls_sort INTO TABLE lt_sort. + + ENDIF. + + SORT ct_overview BY (lt_sort). + + ENDMETHOD. + METHOD build_table_scheme. + + DATA lo_tab_scheme TYPE REF TO kHGwlZbCwKVqbmulVBzOHKguCDENGa. + + CREATE OBJECT lo_tab_scheme. + + lo_tab_scheme->add_column( + iv_tech_name = 'FAVORITE' + iv_css_class = 'wmin' + iv_allow_order_by = abap_false + )->add_column( + iv_tech_name = 'OFFLINE' + iv_display_name = '#' + iv_allow_order_by = abap_true + )->add_column( + iv_tech_name = 'NAME' + iv_display_name = 'Name' + iv_allow_order_by = abap_true ). + + IF mt_all_labels IS NOT INITIAL. + lo_tab_scheme->add_column( + iv_tech_name = 'LABELS' + iv_display_name = 'Labels' + iv_allow_order_by = abap_false ). + ENDIF. + + lo_tab_scheme->add_column( + iv_tech_name = 'PACKAGE' + iv_display_name = 'Package' + iv_css_class = 'package' + iv_allow_order_by = abap_true + )->add_column( + iv_tech_name = 'URL' + iv_display_name = 'Remote' + iv_allow_order_by = abap_true + )->add_column( + iv_tech_name = 'BRANCH' + iv_display_name = 'Branch/Tag' + iv_allow_order_by = abap_true + )->add_column( + iv_tech_name = 'DESERIALIZED_BY' + iv_display_name = 'Deserialized by' + iv_css_class = 'ro-detail' + iv_allow_order_by = abap_true + )->add_column( + iv_tech_name = 'DESERIALIZED_AT' + iv_display_name = 'Deserialized at' + iv_css_class = 'ro-detail' + iv_allow_order_by = abap_true + )->add_column( + iv_tech_name = 'CREATED_BY' + iv_display_name = 'Created by' + iv_css_class = 'ro-detail' + iv_allow_order_by = abap_true + )->add_column( + iv_tech_name = 'CREATED_AT' + iv_display_name = 'Created at' + iv_css_class = 'ro-detail' + iv_add_tz = abap_true + iv_allow_order_by = abap_true + )->add_column( + iv_tech_name = 'KEY' + iv_display_name = 'Key' + iv_css_class = 'ro-detail' + iv_allow_order_by = abap_true + )->add_column( + iv_tech_name = 'GO' + iv_css_class = 'ro-go wmin' + iv_allow_order_by = abap_false ). + + rt_tab_scheme = lo_tab_scheme->mt_col_spec. + + ENDMETHOD. + METHOD collect_all_labels. + + FIELD-SYMBOLS LIKE LINE OF it_overview. + + LOOP AT it_overview ASSIGNING . + APPEND LINES OF -labels TO rt_list. + ENDLOOP. + + SORT rt_list. + DELETE rt_list WHERE table_line IS INITIAL. + DELETE ADJACENT DUPLICATES FROM rt_list. + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + + ms_list_settings = zcl_abapgit_persist_factory=>get_user( )->get_list_settings( ). + + " Overwrite setting + IF iv_only_favorites = abap_true. + ms_list_settings-only_favorites = abap_true. + ENDIF. + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_repo_over. + + CREATE OBJECT lo_component + EXPORTING + iv_only_favorites = iv_only_favorites. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Repository List' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD map_repo_list_to_overview. + + DATA ls_overview LIKE LINE OF rt_overview. + FIELD-SYMBOLS LIKE LINE OF it_repo_obj_list. + + LOOP AT it_repo_obj_list ASSIGNING . + + CLEAR ls_overview. + + ls_overview-favorite = zcl_abapgit_persist_factory=>get_user( + )->is_favorite_repo( ->ms_data-key ). + ls_overview-offline = ->ms_data-offline. + ls_overview-key = ->ms_data-key. + ls_overview-name = ->get_name( ). + ls_overview-labels = zcl_abapgit_repo_labels=>split( ->ms_data-local_settings-labels ). + ls_overview-url = ->ms_data-url. + ls_overview-package = ->ms_data-package. + ls_overview-branch = ->ms_data-branch_name. + ls_overview-created_by = ->ms_data-created_by. + ls_overview-write_protected = ->ms_data-local_settings-write_protected. + ls_overview-flow = ->ms_data-local_settings-flow. + ls_overview-created_at_raw = ->ms_data-created_at. + + IF ->ms_data-created_at IS NOT INITIAL. + ls_overview-created_at = zcl_abapgit_gui_chunk_lib=>render_timestamp( ->ms_data-created_at ). + ENDIF. + + ls_overview-deserialized_by = ->ms_data-deserialized_by. + ls_overview-deserialized_at_raw = ->ms_data-deserialized_at. + + IF ->ms_data-deserialized_at IS NOT INITIAL. + ls_overview-deserialized_at = zcl_abapgit_gui_chunk_lib=>render_timestamp( ->ms_data-deserialized_at ). + ENDIF. + + INSERT ls_overview INTO TABLE rt_overview. + + ENDLOOP. + + ENDMETHOD. + METHOD prepare_overviews. + + DATA lt_repo_obj_list TYPE zif_abapgit_repo_srv=>ty_repo_list. + + IF ms_list_settings-only_favorites = abap_true. + lt_repo_obj_list = zcl_abapgit_repo_srv=>get_instance( )->list_favorites( ). + ELSE. + lt_repo_obj_list = zcl_abapgit_repo_srv=>get_instance( )->list( ). + ENDIF. + + rt_overviews = map_repo_list_to_overview( lt_repo_obj_list ). + + " Hmmm, side effect, not ideal, but we need label list before filter applied + mt_all_labels = collect_all_labels( rt_overviews ). + + apply_order_by( CHANGING ct_overview = rt_overviews ). + apply_filter( CHANGING ct_overview = rt_overviews ). + + ENDMETHOD. + METHOD render_action_toolbar. + + CONSTANTS: + lc_dummy_key TYPE string VALUE `?key=#`, + lc_offline_class TYPE string VALUE `action_offline_repo`, + lc_online_class TYPE string VALUE `action_online_repo`, + lc_action_class TYPE string VALUE `action_link`. + + DATA lo_toolbar TYPE REF TO zcl_abapgit_html_toolbar. + DATA lo_toolbar_more_sub TYPE REF TO zcl_abapgit_html_toolbar. + + lo_toolbar = zcl_abapgit_html_toolbar=>create( 'actionbar-repo-list' ). + + lo_toolbar->add( + iv_txt = |Pull| + iv_act = |{ zif_abapgit_definitions=>c_action-git_pull }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_online_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar->add( + iv_txt = |Stage| + iv_act = |{ zif_abapgit_definitions=>c_action-go_stage }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_online_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar->add( + iv_txt = |Patch| + iv_act = |{ zif_abapgit_definitions=>c_action-go_patch }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_online_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar->add( + iv_txt = |Diff| + iv_act = |{ zif_abapgit_definitions=>c_action-go_repo_diff }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_online_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar->add( + iv_txt = |Check| + iv_act = |{ zif_abapgit_definitions=>c_action-repo_code_inspector }{ lc_dummy_key }| + iv_class = |{ lc_action_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar->add( + iv_txt = |Import| + iv_act = |{ zif_abapgit_definitions=>c_action-zip_import }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_offline_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar->add( + iv_txt = |Export| + iv_act = |{ zif_abapgit_definitions=>c_action-zip_export }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_offline_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar->add( + iv_txt = |Repo Settings| + iv_act = |{ zif_abapgit_definitions=>c_action-repo_settings }{ lc_dummy_key }| + iv_class = |{ lc_action_class }| + iv_li_class = |{ lc_action_class }| ). + + CREATE OBJECT lo_toolbar_more_sub EXPORTING iv_id = 'toolbar-ovp-more_sub'. + + lo_toolbar_more_sub->add( + iv_txt = |Stage by Transport| + iv_act = |{ zif_abapgit_definitions=>c_action-go_stage_transport }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_online_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar_more_sub->add( + iv_txt = |Export by Transport| + iv_act = |{ zif_abapgit_definitions=>c_action-zip_export_transport }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_offline_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar_more_sub->add( + iv_txt = |Change Repository Package| + iv_act = |{ zif_abapgit_definitions=>c_action-repo_change_package }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_online_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar_more_sub->add( + iv_txt = 'Danger' + iv_typ = zif_abapgit_html=>c_action_type-separator ). + + lo_toolbar_more_sub->add( + iv_txt = |Remove Repository| + iv_title = |Remove abapGit's records of the repository (the system's | + && |development objects will remain unaffected)| + iv_act = |{ zif_abapgit_definitions=>c_action-repo_remove }{ lc_dummy_key }| + iv_class = |{ lc_action_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar_more_sub->add( + iv_txt = |Remove Objects| + iv_title = |Delete all development objects belonging to this package | + && |(and subpackages) from the system, but keep repository in abapGit| + iv_act = |{ zif_abapgit_definitions=>c_action-repo_delete_objects }{ lc_dummy_key }| + iv_class = |{ lc_action_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar_more_sub->add( + iv_txt = |Uninstall| + iv_title = |Delete all development objects belonging to this package | + && |(and subpackages) from the system, and remove the repository from abapGit| + iv_act = |{ zif_abapgit_definitions=>c_action-repo_purge }{ lc_dummy_key }| + iv_class = |{ lc_action_class }| + iv_li_class = |{ lc_action_class }| ). + + lo_toolbar->add( + iv_txt = |More| + io_sub = lo_toolbar_more_sub + iv_class = |{ lc_action_class }| + iv_li_class = |{ lc_action_class }| ). + + zcl_abapgit_exit=>get_instance( )->enhance_any_toolbar( lo_toolbar ). + + ri_html = lo_toolbar->render( iv_right = abap_true ). + + ENDMETHOD. + METHOD render_filter_bar. + + DATA lv_icon_class TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( |
    | ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_text_input( + iv_name = |filter| + iv_label = |Filter: { render_filter_help_hint( ) }| + iv_value = ms_list_settings-filter ) ). + ri_html->add( || ). + ri_html->add( |
    | ). + + ri_html->add( '' ). + + IF ms_list_settings-filter IS NOT INITIAL. + ri_html->add( ri_html->a( + iv_txt = || + iv_class = 'command' + iv_act = |{ c_action-clear_filter }| ) ). + ENDIF. + + IF ms_list_settings-only_favorites = abap_true. + lv_icon_class = `blue`. + ELSE. + lv_icon_class = `grey`. + ENDIF. + + ri_html->add( ri_html->a( + iv_txt = | Only Favorites| + iv_class = 'command' + iv_act = |{ zif_abapgit_definitions=>c_action-toggle_favorites }| ) ). + ri_html->add( ri_html->a( + iv_txt = ' Detail' + iv_act = |gHelper.toggleRepoListDetail()| + iv_class = 'command' + iv_typ = zif_abapgit_html=>c_action_type-onclick ) ). + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_filter_help_hint. + + DATA lt_fragments TYPE string_table. + + APPEND `Filter is applied to all text fields in the below table.` TO lt_fragments. + APPEND ` Search works for any portion of the text (so can be a mid part as well).` TO lt_fragments. + APPEND `
    Starting query from label:xxx will filter appropriate label.` TO lt_fragments. + APPEND `Two "special" label queries are available:` TO lt_fragments. + APPEND ` all (to select all repos that has at least one label)` TO lt_fragments. + APPEND ` and none (to select unlabeled repos).` TO lt_fragments. + + rv_html = zcl_abapgit_gui_chunk_lib=>render_help_hint( concat_lines_of( table = lt_fragments ) ). + + ENDMETHOD. + METHOD render_header_bar. + + ii_html->add( |
    | ). + ii_html->add( render_filter_bar( ) ). + ii_html->add( render_action_toolbar( ) ). + ii_html->add( |
    | ). + + ENDMETHOD. + METHOD render_header_label_list. + + IF mt_all_labels IS INITIAL. + RETURN. + ENDIF. + + ii_html->add( |
    | ). + ii_html->add( '' ). + ii_html->add( zcl_abapgit_gui_chunk_lib=>render_label_list( + it_labels = mt_all_labels + io_label_colors = mo_label_colors + iv_clickable_action = c_action-label_filter ) ). + ii_html->add( |
    | ). + + ENDMETHOD. + METHOD render_repo_list. + + ii_html->add( || ). + + render_table_header( ii_html ). + render_table_body( + ii_html = ii_html + it_repo_list = it_overview ). + render_table_footer( ii_html ). + + ii_html->add( |
    | ). + + ENDMETHOD. + METHOD render_scripts. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). + ri_html->add( 'var gHelper = new RepoOverViewHelper({ focusFilterKey: "f" });' ). + + ENDMETHOD. + METHOD render_table_body. + + FIELD-SYMBOLS LIKE LINE OF it_repo_list. + + ii_html->add( '' ). + + LOOP AT it_repo_list ASSIGNING . + render_table_item( + ii_html = ii_html + is_repo = ). + ENDLOOP. + + ii_html->add( || ). + + ENDMETHOD. + METHOD render_table_footer. + + DATA lv_action TYPE string. + + IF ms_list_settings-only_favorites = abap_true. + lv_action = ii_html->a( + iv_txt = 'Show All' + iv_act = |{ zif_abapgit_definitions=>c_action-toggle_favorites }?force_state={ abap_false }| ). + + ii_html->add( zcl_abapgit_gui_chunk_lib=>render_table_footer( |(Only favorites are shown. { lv_action })| ) ). + ENDIF. + + ENDMETHOD. + METHOD render_table_header. + + ii_html->add( zcl_abapgit_gui_chunk_lib=>render_table_header( + it_col_spec = build_table_scheme( ) + iv_order_by = ms_list_settings-order_by + iv_order_descending = ms_list_settings-order_descending ) ). + + ENDMETHOD. + METHOD render_table_item. + + DATA: + lv_is_online_repo TYPE abap_bool, + lv_repo_type_icon TYPE string, + lv_favorite_icon TYPE string, + lv_fav_tr_class TYPE string, + lv_lock TYPE string, + lv_flow TYPE string. + + lv_is_online_repo = boolc( is_repo-offline = abap_false ). + + " Start of row + IF is_repo-favorite = abap_true. + lv_fav_tr_class = ' class="favorite"'. + ELSE. + lv_fav_tr_class = ''. + ENDIF. + + ii_html->add( || ). + + " Favorite + lv_favorite_icon = ii_html->icon( + iv_name = 'star/grey' " blue is added in css, based on TR style + iv_class = 'pad-sides' + iv_hint = 'Click to toggle favorite' ). + + ii_html->td( + iv_class = 'wmin' + iv_content = ii_html->a( + iv_act = |{ zif_abapgit_definitions=>c_action-repo_toggle_fav }?key={ is_repo-key }| + iv_txt = lv_favorite_icon ) ). + + " Online/Offline + IF lv_is_online_repo = abap_true. + lv_repo_type_icon = 'cloud-upload-alt/darkgrey'. + ELSE. + lv_repo_type_icon = 'plug/darkgrey'. + ENDIF. + + ii_html->td( ii_html->icon( lv_repo_type_icon ) ). + + " Repo name + IF is_repo-write_protected = abap_true. + lv_lock = ii_html->icon( + iv_name = 'lock/grey70' + iv_class = 'm-em5-sides' + iv_hint = 'Locked from pulls' ). + ENDIF. + IF is_repo-flow = abap_true. + lv_flow = ii_html->icon( + iv_name = 'flow/grey70' + iv_class = 'm-em5-sides' + iv_hint = 'Flow' ). + ENDIF. + + ii_html->td( + ii_html->a( + iv_txt = is_repo-name + iv_act = |{ c_action-select }?key={ is_repo-key }| ) && lv_lock && lv_flow ). + + " Labels + IF mt_all_labels IS NOT INITIAL. + ii_html->td( + iv_content = zcl_abapgit_gui_chunk_lib=>render_label_list( + it_labels = is_repo-labels + io_label_colors = mo_label_colors + iv_unlisted = abap_true + iv_clickable_action = c_action-label_filter ) + iv_class = 'labels' ). + ENDIF. + + " Package + ii_html->td( ii_content = zcl_abapgit_gui_chunk_lib=>render_package_name( + iv_package = is_repo-package + iv_suppress_title = boolc( NOT ms_list_settings-only_favorites = abap_true ) ) ). + + " Repo URL + IF lv_is_online_repo = abap_true. + ii_html->td( ii_content = zcl_abapgit_gui_chunk_lib=>render_repo_url( + iv_url = is_repo-url + iv_render_remote_edit_for_key = is_repo-key ) ). + ELSE. + ii_html->td( ). + ENDIF. + + " Branch + IF is_repo-branch IS INITIAL. + ii_html->td( ). + ELSE. + ii_html->td( ii_content = zcl_abapgit_gui_chunk_lib=>render_branch_name( + iv_branch = is_repo-branch + iv_repo_key = is_repo-key ) ). + ENDIF. + + " Details: deserialized by + ii_html->td( + iv_class = 'ro-detail' + ii_content = zcl_abapgit_gui_chunk_lib=>render_user_name( + iv_username = is_repo-deserialized_by + iv_suppress_title = boolc( NOT ms_list_settings-only_favorites = abap_true ) ) ). + + " Details: deserialized at + ii_html->td( + iv_class = 'ro-detail' + iv_content = is_repo-deserialized_at ). + + " Details: created by + ii_html->td( + iv_class = 'ro-detail' + ii_content = zcl_abapgit_gui_chunk_lib=>render_user_name( + iv_username = is_repo-created_by + iv_suppress_title = boolc( NOT ms_list_settings-only_favorites = abap_true ) ) ). + + " Details: created at + ii_html->td( + iv_class = 'ro-detail' + iv_content = is_repo-created_at ). + + " Details: repo key + ii_html->td( + iv_class = 'ro-detail' + iv_content = |{ is_repo-key }| ). + + " Go-to action + ii_html->td( + iv_class = 'ro-go wmin' + iv_content = ii_html->a( + iv_title = 'Open' + iv_txt = '▸' + iv_act = |{ c_action-select }?key={ is_repo-key }| ) ). + + ii_html->add( `` ). + + ENDMETHOD. + METHOD save_settings. + zcl_abapgit_persist_factory=>get_user( )->set_list_settings( ms_list_settings ). + ENDMETHOD. + METHOD set_filter. + + FIELD-SYMBOLS LIKE LINE OF it_postdata. + + READ TABLE it_postdata ASSIGNING INDEX 1. + IF sy-subrc = 0. + FIND FIRST OCCURRENCE OF REGEX `filter=(.*)` + IN + SUBMATCHES ms_list_settings-filter. + ENDIF. + + ms_list_settings-filter = condense( ms_list_settings-filter ). + save_settings( ). + + ENDMETHOD. + METHOD set_order_by. + IF ms_list_settings-order_by <> iv_order_by. + set_order_direction( abap_false ). " Reset ordering + ENDIF. + ms_list_settings-order_by = iv_order_by. + save_settings( ). + ENDMETHOD. + METHOD set_order_direction. + ms_list_settings-order_descending = iv_order_descending. + save_settings( ). + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA lv_key TYPE zif_abapgit_persistence=>ty_value. + + lv_key = ii_event->query( )->get( 'KEY' ). + + CASE ii_event->mv_action. + WHEN c_action-select. + + zcl_abapgit_persist_factory=>get_user( )->set_repo_show( lv_key ). + + TRY. + zcl_abapgit_repo_srv=>get_instance( )->get( lv_key )->refresh( ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( lv_key ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN zif_abapgit_definitions=>c_action-change_order_by. + + set_order_by( ii_event->query( )->get( 'ORDERBY' ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN zif_abapgit_definitions=>c_action-toggle_favorites. + + IF ii_event->query( )->has( 'FORCE_STATE' ) = abap_true. + ms_list_settings-only_favorites = ii_event->query( )->get( 'FORCE_STATE' ). + ELSE. + ms_list_settings-only_favorites = boolc( ms_list_settings-only_favorites = abap_false ). + ENDIF. + save_settings( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN zif_abapgit_definitions=>c_action-direction. + + set_order_direction( boolc( ii_event->query( )->get( 'DIRECTION' ) = 'DESCENDING' ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_action-apply_filter. + + set_filter( ii_event->mt_postdata ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_action-label_filter. + + IF ii_event->mv_getdata IS NOT INITIAL. + ms_list_settings-filter = c_label_filter_prefix && ii_event->mv_getdata. + ELSE. + CLEAR ms_list_settings-filter. " Unexpected request + ENDIF. + save_settings( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_action-clear_filter. + + CLEAR ms_list_settings-filter. + save_settings( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_action-refresh_list. + + zcl_abapgit_repo_srv=>get_instance( )->init( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + + ls_hotkey_action-ui_component = 'Repo overview'. + + ls_hotkey_action-description = |New Online Repository|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_newonline. + ls_hotkey_action-hotkey = |n|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |New Offline Repository|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_newoffline. + ls_hotkey_action-hotkey = |o|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Global Settings|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_settings. + ls_hotkey_action-hotkey = |x|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Stage|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_stage. + ls_hotkey_action-hotkey = |s|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Diff|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_repo_diff. + ls_hotkey_action-hotkey = |d|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Check|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_code_inspector. + ls_hotkey_action-hotkey = |c|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Pull|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-git_pull. + ls_hotkey_action-hotkey = |p|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Patch|. + ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_patch. + ls_hotkey_action-hotkey = |a|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Refresh|. + ls_hotkey_action-action = c_action-refresh_list. + ls_hotkey_action-hotkey = |r|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + " registered/handled in js + ls_hotkey_action-description = |Previous Repository|. + ls_hotkey_action-action = `#`. + ls_hotkey_action-hotkey = |4|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Next Repository|. + ls_hotkey_action-action = `##`. + ls_hotkey_action-hotkey = |6|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Open Repository|. + ls_hotkey_action-action = `###`. + ls_hotkey_action-hotkey = |Enter|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Focus Filter|. + ls_hotkey_action-action = `####`. + ls_hotkey_action-hotkey = |f|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-repo-list' ). + + ro_toolbar->add( + iv_txt = zcl_abapgit_gui_buttons=>flow( ) + iv_act = zif_abapgit_definitions=>c_action-flow ). + + ro_toolbar->add( + iv_txt = zcl_abapgit_gui_buttons=>new_online( ) + iv_act = zif_abapgit_definitions=>c_action-repo_newonline + )->add( + iv_txt = zcl_abapgit_gui_buttons=>new_offline( ) + iv_act = zif_abapgit_definitions=>c_action-repo_newoffline + )->add( + iv_txt = zcl_abapgit_gui_buttons=>settings( ) + iv_act = zif_abapgit_definitions=>c_action-go_settings + )->add( + iv_txt = zcl_abapgit_gui_buttons=>refresh( ) + iv_act = c_action-refresh_list + )->add( + iv_txt = zcl_abapgit_gui_buttons=>advanced( ) + io_sub = zcl_abapgit_gui_menus=>advanced( ) + )->add( + iv_txt = zcl_abapgit_gui_buttons=>help( ) + io_sub = zcl_abapgit_gui_menus=>help( ) ). + + zcl_abapgit_gui_menus=>experimental( ro_toolbar ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA lt_overview TYPE ty_overviews. + DATA ls_settings TYPE zif_abapgit_persist_user=>ty_s_user_settings. + + register_handlers( ). + + ls_settings = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_user_settings( ). + mo_label_colors = zcl_abapgit_repo_labels=>split_colors_into_map( ls_settings-label_colors ). + + lt_overview = prepare_overviews( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + zcl_abapgit_exit=>get_instance( )->wall_message_list( ri_html ). + + IF zcl_abapgit_factory=>get_environment( )->is_repo_object_changes_allowed( ) = abap_false. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_error( + iv_error = |Repository changes are not allowed in this system/client! Pull not possible!| ) ). + ENDIF. + + ri_html->add( |
    | ). + render_header_bar( ri_html ). + render_header_label_list( ri_html ). + render_repo_list( + ii_html = ri_html + it_overview = lt_overview ). + ri_html->add( |
    | ). + + register_deferred_script( render_scripts( ) ). + register_deferred_script( zcl_abapgit_gui_chunk_lib=>render_repo_palette( c_action-select ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_pull IMPLEMENTATION. + METHOD choose_transport_request. + + DATA lv_transport_request TYPE trkorr. + + lv_transport_request = zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( ). + + IF lv_transport_request IS NOT INITIAL. + mo_form_data->set( + iv_key = c_id-transport_request + iv_val = lv_transport_request ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + + mi_repo = ii_repo. + mi_obj_filter = ii_obj_filter. + + CREATE OBJECT mo_form_data. + mo_form_data->set( + iv_key = c_id-transport_request + iv_val = iv_trkorr ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_pull. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo + iv_trkorr = iv_trkorr + ii_obj_filter = ii_obj_filter. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Pull' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD form. + + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + + FIELD-SYMBOLS LIKE LINE OF ms_checks-overwrite. + IF mi_obj_filter IS NOT INITIAL. + lt_filter = mi_obj_filter->get_filter( ). + ENDIF. + + ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'pull-form' ). + + ro_form->start_group( + iv_name = 'id-objects' + iv_label = 'Objects' ). + + LOOP AT ms_checks-overwrite ASSIGNING . + IF lines( lt_filter ) > 0. + READ TABLE lt_filter WITH KEY object = -obj_type + obj_name = -obj_name TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + ENDIF. + ro_form->checkbox( + iv_label = |{ -obj_type } { -obj_name }| + iv_name = |{ -obj_type }-{ -obj_name }| ). + ENDLOOP. + + ro_form->text( + iv_name = c_id-transport_request + iv_required = abap_true + iv_upper_case = abap_true + iv_side_action = c_action-choose_tr + iv_max = 10 + iv_label = |Transport Request| ). + + ro_form->command( + iv_label = 'Pull' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_action-pull + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD pull. + + DATA lv_value TYPE string. + + FIELD-SYMBOLS LIKE LINE OF ms_checks-overwrite. + FIELD-SYMBOLS LIKE LINE OF ms_checks-warning_package. + ms_checks-transport-transport = mo_form_data->get( c_id-transport_request ). + + LOOP AT ms_checks-overwrite ASSIGNING . + lv_value = mo_form_data->get( |{ -obj_type }-{ -obj_name }| ). + IF lv_value = 'on'. + -decision = zif_abapgit_definitions=>c_yes. + ELSE. + -decision = zif_abapgit_definitions=>c_no. + ENDIF. + ENDLOOP. + + LOOP AT ms_checks-warning_package ASSIGNING . + lv_value = mo_form_data->get( |{ -obj_type }-{ -obj_name }| ). + IF lv_value = 'on'. + -decision = zif_abapgit_definitions=>c_yes. + ELSE. + -decision = zif_abapgit_definitions=>c_no. + ENDIF. + ENDLOOP. + +* todo, show log? + zcl_abapgit_services_repo=>real_deserialize( + is_checks = ms_checks + ii_repo = mi_repo ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + mo_form_data->merge( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_action-refresh. + mi_repo->refresh( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-choose_tr. + choose_transport_request( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-pull. + pull( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-pull' ). + + ro_toolbar->add( + iv_txt = 'Refresh' + iv_act = c_action-refresh ). + + ro_toolbar->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '
    ' ). + + ms_checks = mi_repo->deserialize_checks( ). + + IF lines( ms_checks-overwrite ) = 0. + zcx_abapgit_exception=>raise( + 'There is nothing to pull. The local state completely matches the remote repository.' ). + ENDIF. + + ri_html->add( form( )->render( mo_form_data ) ). + + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_merge_sel IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + CREATE OBJECT mo_form_data. + mi_repo_online ?= ii_repo. + + read_branches( ). + + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_merge_sel. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Merge Branches' + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + FIELD-SYMBOLS LIKE LINE OF mt_branches. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'merge-branches-form' + iv_help_page = 'https://docs.abapgit.org/' ). " todo, add docs + + ro_form->start_group( + iv_name = c_id-branches + iv_label = 'Branch Selection' + iv_hint = 'Select the branches that should be merged' + )->radio( + iv_name = c_id-source + iv_label = 'Source Branch' + iv_default_value = substring( + val = mi_repo_online->get_selected_branch( ) + off = 11 ) + iv_condense = abap_true ). + + LOOP AT mt_branches ASSIGNING . + ro_form->option( + iv_label = -display_name + iv_value = -display_name ). + ENDLOOP. + + ro_form->radio( + iv_name = c_id-target + iv_label = 'Target Branch' + iv_condense = abap_true ). + + LOOP AT mt_branches ASSIGNING . + ro_form->option( + iv_label = -display_name + iv_value = -display_name ). + ENDLOOP. + + ro_form->command( + iv_label = 'Preview Merge' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-merge + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD read_branches. + + DATA lo_branches TYPE REF TO zif_abapgit_git_branch_list. + + lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( mi_repo_online->get_url( ) ). + mt_branches = lo_branches->get_branches_only( ). + + DELETE mt_branches WHERE name = zif_abapgit_git_definitions=>c_head_name. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + + WHEN c_event-merge. + IF mo_form_data->get( c_id-source ) = mo_form_data->get( c_id-target ). + zcx_abapgit_exception=>raise( 'Select different branches' ). + ENDIF. + + rs_handled-page = zcl_abapgit_gui_page_merge=>create( + ii_repo_online = mi_repo_online + iv_source = mo_form_data->get( c_id-source ) + iv_target = mo_form_data->get( c_id-target ) ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN OTHERS. + ASSERT 1 = 1. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( `
    ` ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo_online + iv_show_commit = abap_false + iv_interactive_branch = abap_false ) ). + + ri_html->add( mo_form->render( io_values = mo_form_data ) ). + + ri_html->add( `
    ` ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_merge_res IMPLEMENTATION. + METHOD apply_merged_content. + + DATA: + lv_merge_content TYPE string, + lv_new_file_content TYPE xstring. + + FIELD-SYMBOLS: + TYPE zif_abapgit_merge=>ty_merge_conflict. + + lv_merge_content = ii_event->form_data( )->get( 'MERGE_CONTENT' ). + + REPLACE ALL OCCURRENCES + OF cl_abap_char_utilities=>cr_lf IN lv_merge_content WITH cl_abap_char_utilities=>newline. + + lv_new_file_content = zcl_abapgit_convert=>string_to_xstring_utf8( lv_merge_content ). + + READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. + -result_sha1 = zcl_abapgit_hash=>sha1_blob( lv_new_file_content ). + -result_data = lv_new_file_content. + mo_merge->resolve_conflict( ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + + mi_repo_online = ii_repo_online. + + mo_merge_page = io_merge_page. + mo_merge = io_merge. + mv_merge_mode = c_merge_mode-selection. + mv_current_conflict_index = 1. + mt_conflicts = io_merge->get_conflicts( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_merge_res. + + CREATE OBJECT lo_component + EXPORTING + ii_repo_online = ii_repo_online + io_merge_page = io_merge_page + io_merge = io_merge. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Resolve Merge Conflicts' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD is_binary. + + FIELD-SYMBOLS LIKE iv_d1. + + IF iv_d1 IS NOT INITIAL. " One of them might be new and so empty + ASSIGN iv_d1 TO . + ELSE. + ASSIGN iv_d2 TO . + ENDIF. + + rv_yes = zcl_abapgit_utils=>is_binary( ). + + ENDMETHOD. + METHOD render_beacon. + + DATA: lv_beacon TYPE string, + lt_beacons TYPE zif_abapgit_definitions=>ty_string_tt. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF is_diff_line-beacon > 0. + lt_beacons = is_diff-o_diff->get_beacons( ). + READ TABLE lt_beacons INTO lv_beacon INDEX is_diff_line-beacon. + ELSE. + lv_beacon = '---'. + ENDIF. + + ri_html->add( '' ). + ri_html->add( '' ). + + ri_html->add( '' ). + ri_html->add( |@@ { is_diff_line-new_num } @@ { lv_beacon }| ). + + ri_html->add( '' ). + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_diff. + + DATA lv_target_content TYPE string. + + FIELD-SYMBOLS TYPE zif_abapgit_merge=>ty_merge_conflict. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( |
    | ). + ri_html->add( render_diff_head( is_diff ) ). + + " Content + IF is_diff-type <> 'binary'. + + IF mv_merge_mode = c_merge_mode-selection. + ri_html->add( '
    ' ). + ri_html->add( '' ). + ri_html->add( render_table_head( ) ). + ri_html->add( render_lines( is_diff ) ). + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + ELSE. + + "Table for Div-Table and textarea + ri_html->add( '
    ' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( ' ' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '
    CodeMerge - ' ). + ri_html->add_a( iv_act = 'submitFormById(''merge_form'');' + iv_txt = 'Apply' + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ri_html->add( '
    ' ). + + "Diff-Table of source and target file + ri_html->add( '' ). + ri_html->add( render_table_head( ) ). + ri_html->add( render_lines( is_diff ) ). + ri_html->add( '
    ' ). + + READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. + IF sy-subrc = 0. + lv_target_content = zcl_abapgit_convert=>xstring_to_string_utf8( -target_data ). + lv_target_content = escape( val = lv_target_content + format = cl_abap_format=>e_html_text ). + ENDIF. + + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + ri_html->add( |
    add( |method="post" action="sapevent:apply_merge">| ). + ri_html->add( || ). + ri_html->add( '' ). + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + ENDIF. + ELSE. + ri_html->add( '
    ' ). + ri_html->add( 'The content seems to be binary.' ). + ri_html->add( 'Cannot display as diff.' ). + ri_html->add( '
    ' ). + ENDIF. + + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_diff_head. + + DATA ls_stats TYPE zif_abapgit_definitions=>ty_count. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + + IF is_diff-type <> 'binary' AND is_diff-o_diff IS NOT INITIAL. + ls_stats = is_diff-o_diff->stats( ). + ri_html->add( |+ { ls_stats-insert }| ). + ri_html->add( |- { ls_stats-delete }| ). + ri_html->add( |~ { ls_stats-update }| ). + ENDIF. + + ri_html->add( |{ is_diff-filename }| ). + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_lines. + + DATA: lo_highlighter TYPE REF TO zcl_abapgit_syntax_highlighter, + lt_diffs TYPE zif_abapgit_definitions=>ty_diffs_tt, + lv_insert_nav TYPE abap_bool. + + FIELD-SYMBOLS LIKE LINE OF lt_diffs. + + lo_highlighter = zcl_abapgit_syntax_factory=>create( is_diff-filename ). + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + lt_diffs = is_diff-o_diff->get( ). + + LOOP AT lt_diffs ASSIGNING . + IF -short = abap_false. + lv_insert_nav = abap_true. + CONTINUE. + ENDIF. + + IF lv_insert_nav = abap_true. " Insert separator line with navigation + ri_html->add( render_beacon( is_diff_line = + is_diff = is_diff ) ). + lv_insert_nav = abap_false. + ENDIF. + + IF lo_highlighter IS BOUND. + -new = lo_highlighter->process_line( -new ). + -old = lo_highlighter->process_line( -old ). + ELSE. + -new = escape( val = -new + format = cl_abap_format=>e_html_attr ). + -old = escape( val = -old + format = cl_abap_format=>e_html_attr ). + ENDIF. + + CONDENSE -new_num. "get rid of leading spaces + CONDENSE -old_num. + + ri_html->add( render_line_split( ) ). + + ENDLOOP. + + ENDMETHOD. + METHOD render_line_split. + + DATA: lv_new TYPE string, + lv_old TYPE string, + lv_mark TYPE string, + lv_bg TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + " New line + lv_mark = ` `. + IF is_diff_line-result = zif_abapgit_definitions=>c_diff-update. + lv_bg = ' diff_upd'. + lv_mark = `~`. + ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-insert. + lv_bg = ' diff_ins'. + lv_mark = `+`. + ENDIF. + lv_new = || + && |{ lv_mark }{ is_diff_line-new }|. + + " Old line + CLEAR lv_bg. + lv_mark = ` `. + IF is_diff_line-result = zif_abapgit_definitions=>c_diff-update. + lv_bg = ' diff_upd'. + lv_mark = `~`. + ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-delete. + lv_bg = ' diff_del'. + lv_mark = `-`. + ENDIF. + lv_old = || + && |{ lv_mark }{ is_diff_line-old }|. + + " render line, inverse sides if remote is newer + ri_html->add( '' ). + ri_html->add( lv_old ). " Target + ri_html->add( lv_new ). " Source + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_table_head. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + + IF mv_merge_mode = c_merge_mode-selection. + ri_html->add( '
    ' ). + ri_html->add( 'Target - ' && mi_repo_online->get_selected_branch( ) && ' - ' ). + ri_html->add_a( iv_act = 'submitFormById(''target_form'');' + iv_txt = 'Apply' + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ri_html->add( ' ' ). + ri_html->add( '
    ' ). + ri_html->add( '' ). + ri_html->add( '
    ' ). + ri_html->add( 'Source - ' && mo_merge->get_source_branch( ) && ' - ' ). + ri_html->add_a( iv_act = 'submitFormById(''source_form'');' + iv_txt = 'Apply' + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ri_html->add( ' ' ). + ri_html->add( '
    ' ). + ELSE. + ri_html->add( 'Target - ' && mi_repo_online->get_selected_branch( ) && ' ' ). + ri_html->add( '' ). + ri_html->add( 'Source - ' && mo_merge->get_source_branch( ) && ' ' ). + ENDIF. + + ri_html->add( '' ). + ri_html->add( '' ). + + ENDMETHOD. + METHOD resolve_diff. + + DATA lv_offs TYPE i. + + FIELD-SYMBOLS TYPE zif_abapgit_merge=>ty_merge_conflict. + + CLEAR ms_diff_file. + + READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + ms_diff_file-path = -path. + ms_diff_file-filename = -filename. + ms_diff_file-type = reverse( -filename ). + + FIND FIRST OCCURRENCE OF '.' IN ms_diff_file-type MATCH OFFSET lv_offs. + ms_diff_file-type = reverse( substring( val = ms_diff_file-type + len = lv_offs ) ). + IF ms_diff_file-type <> 'xml' AND ms_diff_file-type <> 'abap'. + ms_diff_file-type = 'other'. + ENDIF. + + IF ms_diff_file-type = 'other' + AND is_binary( iv_d1 = -source_data + iv_d2 = -target_data ) = abap_true. + ms_diff_file-type = 'binary'. + ENDIF. + + IF ms_diff_file-type <> 'binary'. + ms_diff_file-o_diff = zcl_abapgit_diff_factory=>get( )->create( + iv_new = -source_data + iv_old = -target_data ). + ENDIF. + + ENDMETHOD. + METHOD toggle_merge_mode. + + IF mv_merge_mode = c_merge_mode-selection. + mv_merge_mode = c_merge_mode-merge. + ELSE. + mv_merge_mode = c_merge_mode-selection. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + FIELD-SYMBOLS TYPE zif_abapgit_merge=>ty_merge_conflict. + + CASE ii_event->mv_action. + WHEN c_actions-apply_merge + OR c_actions-apply_source + OR c_actions-apply_target + OR c_actions-cancel. + + CASE ii_event->mv_action. + WHEN c_actions-apply_merge. + apply_merged_content( ii_event ). + + WHEN c_actions-apply_source. + READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. + -result_sha1 = -source_sha1. + -result_data = -source_data. + mo_merge->resolve_conflict( ). + + WHEN c_actions-apply_target. + READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. + -result_sha1 = -target_sha1. + -result_data = -target_data. + mo_merge->resolve_conflict( ). + + ENDCASE. + + mv_current_conflict_index = mv_current_conflict_index + 1. + IF mv_current_conflict_index > lines( mt_conflicts ). + CLEAR mv_current_conflict_index. + ENDIF. + + IF mv_current_conflict_index IS NOT INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rs_handled-page = mo_merge_page. + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ENDIF. + + WHEN c_actions-toggle_mode. + toggle_merge_mode( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-merge-res' ). + + ro_toolbar->add( iv_txt = 'Toggle merge mode' + iv_act = c_actions-toggle_mode ). + ro_toolbar->add( iv_txt = 'Cancel' + iv_act = c_actions-cancel ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA: li_repo TYPE REF TO zif_abapgit_repo. + + li_repo = mi_repo_online. + + register_handlers( ). + + resolve_diff( ). + + IF ms_diff_file IS INITIAL. + zcx_abapgit_exception=>raise( 'no conflict found' ). + ENDIF. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( |
    | ). + ri_html->add( render_diff( ms_diff_file ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_merge IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + mi_repo_online = ii_repo_online. + + ii_repo_online->select_branch( |{ zif_abapgit_git_definitions=>c_git_branch-heads_prefix }{ iv_target }| ). + + CREATE OBJECT mi_merge TYPE zcl_abapgit_merge + EXPORTING + ii_repo_online = ii_repo_online + iv_source_branch = iv_source. + + mi_merge->run( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_merge. + + CREATE OBJECT lo_component + EXPORTING + ii_repo_online = ii_repo_online + iv_source = iv_source + iv_target = iv_target. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Merge' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD show_file. + + FIELD-SYMBOLS LIKE LINE OF it_expanded. + + READ TABLE it_expanded ASSIGNING + WITH KEY path_name + COMPONENTS path = is_file-path name = is_file-name. + IF sy-subrc = 0. + IF -sha1 = is_result-sha1. + ii_html->add( |{ -path }{ -name }{ -sha1(7) }| ). + ELSE. + ii_html->add( |{ -path }{ -name }{ -sha1(7) }| ). + ENDIF. + ELSE. + ii_html->add( '' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA: li_repo TYPE REF TO zif_abapgit_repo. + + CASE ii_event->mv_action. + WHEN c_actions-merge. + IF mi_merge->has_conflicts( ) = abap_true. + zcx_abapgit_exception=>raise( 'conflicts exists' ). + ENDIF. + + IF mi_merge->get_result( )-stage->count( ) = 0. + zcx_abapgit_exception=>raise( 'nothing to merge' ). + ENDIF. + + li_repo = mi_repo_online. + + IF li_repo->get_local_settings( )-code_inspector_check_variant IS NOT INITIAL. + + rs_handled-page = zcl_abapgit_gui_page_code_insp=>create( + ii_repo = mi_repo_online + io_stage = mi_merge->get_result( )-stage ). + + ELSE. + + rs_handled-page = zcl_abapgit_gui_page_commit=>create( + ii_repo_online = mi_repo_online + io_stage = mi_merge->get_result( )-stage ). + + ENDIF. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN c_actions-res_conflicts. + + rs_handled-page = zcl_abapgit_gui_page_merge_res=>create( + ii_repo_online = mi_repo_online + io_merge_page = me + io_merge = mi_merge ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-merge' ). + + ro_toolbar->add( iv_txt = 'Merge' + iv_act = c_actions-merge + iv_cur = abap_false ). + + IF mi_merge->has_conflicts( ) = abap_true. + ro_toolbar->add( iv_txt = 'Resolve Conflicts' + iv_act = c_actions-res_conflicts ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA: ls_merge TYPE zif_abapgit_merge=>ty_merge, + lt_files LIKE ls_merge-stree, + ls_result LIKE LINE OF ls_merge-result. + + FIELD-SYMBOLS LIKE LINE OF lt_files. + + register_handlers( ). + + ls_merge = mi_merge->get_result( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo_online + iv_show_package = abap_false + iv_show_branch = abap_false ) ). + + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '
    Source' ). + ri_html->add( ls_merge-source-name ). + ri_html->add( '
    Target' ). + ri_html->add( ls_merge-target-name ). + ri_html->add( '
    Ancestor' ). + ri_html->add( ls_merge-common-commit ). + ri_html->add( '
    ' ). + + ri_html->add( '
    ' ). + + APPEND LINES OF ls_merge-stree TO lt_files. + APPEND LINES OF ls_merge-ttree TO lt_files. + APPEND LINES OF ls_merge-ctree TO lt_files. + SORT lt_files BY path DESCENDING name ASCENDING. + DELETE ADJACENT DUPLICATES FROM lt_files COMPARING path name. + + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + LOOP AT lt_files ASSIGNING . + CLEAR ls_result. + READ TABLE ls_merge-result INTO ls_result + WITH KEY path_name + COMPONENTS path = -path name = -name. + + ri_html->add( '' ). + show_file( it_expanded = ls_merge-stree + ii_html = ri_html + is_file = + is_result = ls_result ). + show_file( it_expanded = ls_merge-ttree + ii_html = ri_html + is_file = + is_result = ls_result ). + show_file( it_expanded = ls_merge-ctree + ii_html = ri_html + is_file = + is_result = ls_result ). + show_file( it_expanded = ls_merge-result + ii_html = ri_html + is_file = + is_result = ls_result ). + ri_html->add( '' ). + ENDLOOP. + ri_html->add( '
    SourceTargetAncestorResult
    ' ). + ri_html->add( '
    ' ). + ri_html->add( '' ). + ri_html->add( ls_merge-conflict ). + ri_html->add( '' ). + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_ex_pckage IMPLEMENTATION. + METHOD constructor. + super->constructor( ). + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + ENDMETHOD. + METHOD create. + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_ex_pckage. + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Export Package to ZIP' + ii_child_component = lo_component ). + ENDMETHOD. + METHOD export_package. + DATA lv_package TYPE devclass. + DATA lv_folder_logic TYPE string. + DATA lv_ign_subpkg TYPE abap_bool. + DATA lv_main_lang_only TYPE abap_bool. + + lv_package = mo_form_data->get( c_id-package ). + lv_folder_logic = mo_form_data->get( c_id-folder_logic ). + lv_ign_subpkg = mo_form_data->get( c_id-ignore_subpackages ). + lv_main_lang_only = mo_form_data->get( c_id-main_lang_only ). + + zcl_abapgit_zip=>export_package( + iv_package = lv_package + iv_folder_logic = lv_folder_logic + iv_ign_subpkg = lv_ign_subpkg + iv_main_lang_only = lv_main_lang_only ). + ENDMETHOD. + METHOD get_form_schema. + ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'export-package-to-files' ). + + ro_form->text( + iv_name = c_id-package + iv_label = 'Package' + iv_required = abap_true + iv_upper_case = abap_true + iv_side_action = c_event-choose_package + iv_max = 30 + )->radio( + iv_name = c_id-folder_logic + iv_label = 'Folder Logic' + iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix + iv_hint = 'Define how package folders are named in repository' + )->option( + iv_label = 'Prefix' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix + )->option( + iv_label = 'Full' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-full + )->option( + iv_label = 'Mixed' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-mixed + )->checkbox( + iv_name = c_id-ignore_subpackages + iv_label = 'Ignore Subpackages' + iv_hint = 'Export selected package only' + )->checkbox( + iv_name = c_id-main_lang_only + iv_label = 'Serialize Main Language Only' + iv_hint = 'Ignore translations, export just main language' + )->command( + iv_label = 'Export Package to ZIP' + iv_action = c_event-export_package + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_event-export_package. + + mo_validation_log = mo_form_util->validate( mo_form_data ). + IF mo_validation_log->is_empty( ) = abap_false. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + export_package( ). + MESSAGE 'Package successfully exported' TYPE 'S'. + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ENDIF. + + WHEN c_event-choose_package. + + mo_form_data->set( + iv_key = c_id-package + iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ). + + IF mo_form_data->get( c_id-package ) IS NOT INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDIF. + ENDCASE. + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_PAGE_EX_OBJECT IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + CREATE OBJECT mo_validation_log. + + CREATE OBJECT mo_form_data. + mo_form_data->set( + iv_key = c_id-only_main + iv_val = abap_true ). + + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_ex_object. + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Export Objects to Files' + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD export_object. + + DATA lv_object_type TYPE trobjtype. + DATA lt_names TYPE STANDARD TABLE OF sobj_name WITH DEFAULT KEY. + DATA lv_name LIKE LINE OF lt_names. + DATA lv_list TYPE string. + DATA lv_only_main TYPE abap_bool. + DATA lv_use_lxe TYPE abap_bool. + DATA lt_lang_list TYPE zif_abapgit_definitions=>ty_languages. + + lv_object_type = mo_form_data->get( c_id-object_type ). + lv_list = mo_form_data->get( c_id-object_name ). + lv_only_main = mo_form_data->get( c_id-only_main ). + lv_use_lxe = mo_form_data->get( c_id-use_lxe ). + lt_lang_list = zcl_abapgit_lxe_texts=>convert_lang_string_to_table( mo_form_data->get( c_id-i18n_langs ) ). + + REPLACE ALL OCCURRENCES OF |\r| IN lv_list WITH ''. + SPLIT lv_list AT |\n| INTO TABLE lt_names. + + LOOP AT lt_names INTO lv_name. + IF lv_name IS INITIAL. + CONTINUE. + ENDIF. + zcl_abapgit_zip=>export_object( + iv_main_language_only = lv_only_main + iv_use_lxe = lv_use_lxe + it_translation_langs = lt_lang_list + iv_object_type = lv_object_type + iv_object_name = lv_name ). + ENDLOOP. + + ENDMETHOD. + METHOD get_form_schema. + + ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'export-object-to-files' ). + + ro_form->text( + iv_label = 'Object Type' + iv_name = c_id-object_type + iv_required = abap_true + iv_upper_case = abap_true + iv_side_action = c_event-choose_object_type ). + + ro_form->textarea( + iv_label = 'Object Names' + iv_name = c_id-object_name + iv_required = abap_true + iv_placeholder = 'One object name per line' + iv_upper_case = abap_true ). + + ro_form->checkbox( + iv_label = 'Only Main Language' + iv_name = c_id-only_main + )->checkbox( + iv_name = c_id-use_lxe + iv_label = 'Use LXE Approach for Translations' + iv_hint = 'It''s mandatory to specify the list of languages above in addition to this setting' + )->text( + iv_name = c_id-i18n_langs + iv_label = 'Serialize Translations for Additional Languages' + iv_hint = 'Comma-separate 2-letter ISO language codes e.g. "DE,ES,..." - should not include main language' ). + + ro_form->command( + iv_label = 'Export' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-export + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA lt_lang_list TYPE zif_abapgit_definitions=>ty_languages. + + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_event-export. + + mo_validation_log = mo_form_util->validate( mo_form_data ). + + lt_lang_list = zcl_abapgit_lxe_texts=>convert_lang_string_to_table( mo_form_data->get( c_id-i18n_langs ) ). + IF mo_form_data->get( c_id-use_lxe ) = abap_true AND lt_lang_list IS INITIAL. + mo_validation_log->set( + iv_key = c_id-i18n_langs + iv_val = 'LXE approach requires a non-empty list of languages' ). + ENDIF. + + IF mo_validation_log->is_empty( ) = abap_false. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + export_object( ). + MESSAGE 'Object successfully exported' TYPE 'S'. + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ENDIF. + + WHEN c_event-choose_object_type. + + mo_form_data->set( + iv_key = c_id-object_type + iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TADIR-OBJECT' ) ). + + IF mo_form_data->get( c_id-object_type ) IS NOT INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDIF. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_debuginfo IMPLEMENTATION. + METHOD build_toolbar. + + ro_menu = zcl_abapgit_html_toolbar=>create( 'toolbar-debug-info' ). + + ro_menu->add( + iv_txt = 'Save' + iv_act = c_action-save ). + ro_menu->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_debuginfo. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Debug Info' + io_page_menu = build_toolbar( ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_jump_object. + + DATA lv_encode TYPE string. + DATA li_html TYPE REF TO zif_abapgit_html. + + CREATE OBJECT li_html TYPE zcl_abapgit_html. + + lv_encode = zcl_abapgit_html_action_utils=>jump_encode( iv_obj_type = |{ iv_obj_type }| + iv_obj_name = |{ iv_obj_name }| ). + + rv_html = li_html->a( + iv_txt = |{ iv_obj_name }| + iv_act = |{ zif_abapgit_definitions=>c_action-jump }?{ lv_encode }| ). + + ENDMETHOD. + METHOD render_debug_info. + + DATA: ls_release TYPE zif_abapgit_environment=>ty_release_sp, + lv_gui_version TYPE string, + lv_devclass TYPE devclass, + lo_frontend_serv TYPE REF TO zif_abapgit_frontend_services. + + lo_frontend_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + TRY. + lo_frontend_serv->get_gui_version( IMPORTING ev_gui_version_string = lv_gui_version ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + " Continue rendering even if this fails + ENDTRY. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. + ri_html->add( '

    abapGit - Standalone Version

    ' ). + ri_html->add( '
    To keep abapGit up-to-date (or also to contribute) you need to' ). + ri_html->add( |install it as a repository ({ ri_html->a( + iv_txt = 'Developer Version' + iv_act = 'https://github.com/abapGit/abapGit' + iv_typ = zif_abapgit_html=>c_action_type-url ) }).
    | ). + ELSE. + lv_devclass = zcl_abapgit_factory=>get_tadir( )->get_object_package( + iv_object = 'CLAS' + iv_obj_name = 'ZCX_ABAPGIT_EXCEPTION' ). + ri_html->add( '

    abapGit - Developer Version

    ' ). + ri_html->add( |
    abapGit is installed in package { lv_devclass }
    | ). + ENDIF. + + ri_html->add( '
    ' ). + ri_html->add_a( + iv_txt = 'Contribution guidelines for abapGit' + iv_act = |{ zif_abapgit_definitions=>c_action-url + }?url=https://github.com/abapGit/abapGit/blob/main/CONTRIBUTING.md| + iv_class = |url| ). + ri_html->add( '
    ' ). + + ls_release = zcl_abapgit_factory=>get_environment( )->get_basis_release( ). + + ri_html->add( '

    Environment

    ' ). + + ri_html->add( || ). + ri_html->add( || ). + ri_html->add( || ). + ri_html->add( || ). + ri_html->add( || ). + ri_html->add( || ). + ri_html->add( || ). + ri_html->add( || ). + ri_html->add( |
    abapGit version:{ zif_abapgit_version=>c_abap_version }
    XML version: { zif_abapgit_version=>c_xml_version }
    GUI version: { lv_gui_version }
    APACK version: { + zcl_abapgit_apack_migration=>c_apack_interface_version }
    LCL_TIME: { zcl_abapgit_git_time=>get_unix( ) }
    SY time: { sy-datum } { sy-uzeit } { sy-tzone }
    SY release: { ls_release-release } SP { ls_release-sp }
    | ). + ri_html->add( |
    | ). + + ENDMETHOD. + METHOD render_exit_info. + + DATA lt_source TYPE string_table. + DATA ls_class_key TYPE seoclskey. + DATA lo_oo_serializer TYPE REF TO zcl_abapgit_oo_serializer. + DATA lo_class TYPE REF TO cl_oo_class. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '

    User Exits

    ' ). + + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. + " Standalone version + TRY. + lt_source = zcl_abapgit_factory=>get_sap_report( )->read_report( c_exit_standalone ). + + resolve_exit_include( + CHANGING + cv_clsname = ls_class_key-clsname + ct_source = lt_source ). + ri_html->add( |
    User exits are active (include { get_jump_object( + iv_obj_type = 'PROG' + iv_obj_name = c_exit_standalone ) } found)

    | ). + ri_html->add( render_exit_info_methods( + it_source = lt_source + iv_clsname = to_upper( ls_class_key-clsname ) ) ). + + CATCH zcx_abapgit_exception. + ri_html->add( |
    No user exits implemented (include { c_exit_standalone } not found)

    | ). + ENDTRY. + ELSE. + " Developer version + TRY. + ls_class_key-clsname = c_exit_class. + DO. + CREATE OBJECT lo_oo_serializer. + lt_source = lo_oo_serializer->serialize_abap_clif_source( ls_class_key ). + + ri_html->add( '
    ' ). + ri_html->add( |User exits are active (class { get_jump_object( ls_class_key-clsname ) } found)| ). + ri_html->add( '

    ' ). + ri_html->add( render_exit_info_methods( + it_source = lt_source + iv_clsname = ls_class_key-clsname ) ). + + " Is there a super class of exit? + CREATE OBJECT lo_class EXPORTING clsname = ls_class_key-clsname. + ls_class_key-clsname = lo_class->get_superclass( ). + IF ls_class_key-clsname IS INITIAL. + EXIT. + ENDIF. + ri_html->add( '
    ' ). + ENDDO. + CATCH cx_root. + ri_html->add( |
    No user exits implemented (class { c_exit_class } not found)

    | ). + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD render_exit_info_methods. + + DATA: + lo_scanner TYPE REF TO cl_oo_source_scanner_class, + lx_exc TYPE REF TO cx_root, + lt_methods TYPE cl_oo_source_scanner_class=>type_method_implementations, + lv_method LIKE LINE OF lt_methods, + lt_source TYPE seop_source_string, + lv_count TYPE i, + lv_source TYPE string, + lv_rest TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + + TRY. + lo_scanner = cl_oo_source_scanner_class=>create_class_scanner( + clif_name = iv_clsname + source = it_source ). + lo_scanner->scan( ). + + lt_methods = lo_scanner->get_method_implementations( ). + + LOOP AT lt_methods INTO lv_method WHERE table_line CS c_exit_interface. + lt_source = lo_scanner->get_method_impl_source( lv_method ). + DELETE lt_source INDEX 1. + DELETE lt_source INDEX lines( lt_source ). + CONCATENATE LINES OF lt_source INTO lv_source. + lv_source = to_upper( condense( + val = lv_source + del = ` ` ) ). + SPLIT lv_method AT '~' INTO lv_rest lv_method. + ri_html->add( || ). + lv_count = lv_count + 1. + ENDLOOP. + + IF lv_count = 0. + ri_html->add( || ). + ENDIF. + + CATCH cx_root INTO lx_exc. + ri_html->add( || ). + ENDTRY. + + ri_html->add( '
    ExitImplemented?
    { lv_method }| ). + IF lv_source IS INITIAL OR lv_source = 'RETURN.' OR lv_source = 'EXIT.'. + ri_html->add( 'No' ). + ELSE. + ri_html->add( 'Yes' ). + ENDIF. + ri_html->add( |
    No exit methods implemented
    { lx_exc->get_text( ) }
    ' ). + + ENDMETHOD. + METHOD render_scripts. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). + ri_html->add( 'debugOutput("
    Browser:" + navigator.userAgent + ' && + '"
    Frontend time:" + new Date() + "
    ", "debug_info");' ). + + ENDMETHOD. + METHOD render_supported_object_types. + + DATA: lv_list TYPE string, + li_html TYPE REF TO zif_abapgit_html, + lt_types TYPE zif_abapgit_objects=>ty_types_tt, + lv_type LIKE LINE OF lt_types, + lt_obj TYPE STANDARD TABLE OF ko100 WITH DEFAULT KEY, + lv_class TYPE seoclsname, + li_object TYPE REF TO zif_abapgit_object, + ls_item TYPE zif_abapgit_definitions=>ty_item, + ls_metadata TYPE zif_abapgit_definitions=>ty_metadata, + lv_step TYPE zif_abapgit_objects=>ty_deserialization_step, + lt_steps TYPE zif_abapgit_objects=>ty_deserialization_step_tt, + lt_descr TYPE zif_abapgit_oo_object_fnc=>ty_seoclasstx_tt, + ls_descr LIKE LINE OF lt_descr. + + FIELD-SYMBOLS: TYPE ko100. + + CALL FUNCTION 'TR_OBJECT_TABLE' + TABLES + wt_object_text = lt_obj. + + lt_types = zcl_abapgit_objects=>supported_list( ). + + CREATE OBJECT li_html TYPE zcl_abapgit_html. + + rv_html = '

    Object Types

    '. + + rv_html = rv_html && li_html->a( + iv_txt = 'Complete list of object types supported by abapGit' + iv_act = |{ zif_abapgit_definitions=>c_action-url }?url=https://docs.abapgit.org/ref-supported.html| + iv_class = |url| ). + + rv_html = rv_html && |

    Supported object types in this system:

    |. + + rv_html = rv_html && ||. + rv_html = rv_html && ||. + rv_html = rv_html && ||. + rv_html = rv_html && ||. + + LOOP AT lt_types INTO lv_type. + lv_class = 'ZCL_ABAPGIT_OBJECT_' && lv_type. + + rv_html = rv_html && ||. + + rv_html = rv_html && ||. + + READ TABLE lt_obj ASSIGNING WITH KEY pgmid = 'R3TR' object = lv_type. + IF sy-subrc = 0. + rv_html = rv_html && ||. + ELSE. + lt_descr = zcl_abapgit_oo_factory=>get_by_type( 'CLAS' )->read_descriptions_class( lv_class ). + + READ TABLE lt_descr INTO ls_descr WITH KEY langu = sy-langu. + IF sy-subrc = 0. + ls_descr-descript = replace( + val = ls_descr-descript + sub = 'abapGit - ' + with = '' ). + ELSE. + ls_descr-descript = 'No description'. + ENDIF. + rv_html = rv_html && ||. + ENDIF. + + TRY. + ls_item-obj_type = lv_type. + ls_item-obj_name = 'TEST'. + + CREATE OBJECT li_object TYPE (lv_class) + EXPORTING + is_item = ls_item + iv_language = sy-langu. + + rv_html = rv_html && ||. + + CATCH cx_sy_create_object_error zcx_abapgit_exception. + TRY. " 2nd step, try looking for plugins + CREATE OBJECT li_object TYPE zcl_abapgit_objects_bridge + EXPORTING + is_item = ls_item. + CATCH cx_sy_create_object_error zcx_abapgit_exception. + rv_html = rv_html && ||. + CONTINUE. + ENDTRY. + + rv_html = rv_html && ||. + ENDTRY. + + ls_metadata = li_object->get_metadata( ). + + rv_html = rv_html && ||. + + lt_steps = li_object->get_deserialize_steps( ). + + CLEAR lv_list. + LOOP AT lt_steps INTO lv_step. + CASE lv_step. + WHEN zif_abapgit_object=>gc_step_id-early. + lv_step = |{ lv_step } (1)|. + WHEN zif_abapgit_object=>gc_step_id-ddic. + lv_step = |{ lv_step } (2)|. + WHEN zif_abapgit_object=>gc_step_id-abap. + lv_step = |{ lv_step } (3)|. + WHEN zif_abapgit_object=>gc_step_id-late. + lv_step = |{ lv_step } (4)|. + WHEN zif_abapgit_object=>gc_step_id-lxe. + lv_step = |{ lv_step } (5)|. + WHEN OTHERS. + ASSERT 1 = 2. + ENDCASE. + IF lv_list IS INITIAL. + lv_list = lv_step. + ELSE. + lv_list = lv_list && `, ` && lv_step. + ENDIF. + ENDLOOP. + + rv_html = rv_html && ||. + + rv_html = rv_html && ||. + + ENDLOOP. + + rv_html = rv_html && |
    ObjectDescriptionClassVersionSteps
    { lv_type }{ -text }abapGit Enhancement: { ls_descr-descript }{ get_jump_object( lv_class ) }{ lv_class } - error instantiating class{ get_jump_object( lv_class ) } (Plug-in){ ls_metadata-version }{ lv_list }
    |. + rv_html = rv_html && |
    |. + + ENDMETHOD. + METHOD resolve_exit_include. + + DATA lv_include TYPE progname. + + cv_clsname = c_exit_class. + + DO. + FIND REGEX 'CLASS\s+(.*)\s+DEFINITION' IN TABLE ct_source SUBMATCHES cv_clsname IGNORING CASE. + IF sy-subrc = 0. + RETURN. + ENDIF. + FIND REGEX 'INCLUDE\s+(.*)\s*\.' IN TABLE ct_source SUBMATCHES lv_include IGNORING CASE. + IF sy-subrc = 0. + TRY. + ct_source = zcl_abapgit_factory=>get_sap_report( )->read_report( lv_include ). + CATCH zcx_abapgit_exception. + RETURN. " rely on original include + ENDTRY. + ELSE. + RETURN. + ENDIF. + ENDDO. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA: + lv_path TYPE string, + lv_filename TYPE string, + li_fe_serv TYPE REF TO zif_abapgit_frontend_services. + + CASE ii_event->mv_action. + WHEN c_action-save. + + CONCATENATE 'abapGit_Debug_Info_' sy-datlo '_' sy-timlo '.html' INTO lv_filename. + + li_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + + lv_path = li_fe_serv->show_file_save_dialog( + iv_title = 'abapGit - Debug Info' + iv_extension = 'html' + iv_default_filename = lv_filename ). + + li_fe_serv->file_download( + iv_path = lv_path + iv_xstr = zcl_abapgit_convert=>string_to_xstring_utf8( mv_html ) ). + + MESSAGE 'abapGit Debug Info successfully saved' TYPE 'S'. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN OTHERS. + ASSERT 1 = 1. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + ri_html->add( render_debug_info( ) ). + ri_html->add( '
    ' ). + + ri_html->add( '
    ' ). + ri_html->add( render_exit_info( ) ). + ri_html->add( '
    ' ). + + ri_html->add( '
    ' ). + ri_html->add( render_supported_object_types( ) ). + ri_html->add( '
    ' ). + + mv_html = 'abapGit Debug Info'. + mv_html = |{ ri_html->render( ) }|. + + register_deferred_script( render_scripts( ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_data IMPLEMENTATION. + METHOD add_via_transport. + + DATA lv_trkorr TYPE trkorr. + DATA ls_request TYPE zif_abapgit_cts_api=>ty_transport_data. + DATA ls_key LIKE LINE OF ls_request-keys. + DATA lv_where TYPE string. + DATA ls_config TYPE zif_abapgit_data_config=>ty_config. + lv_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_transport( ). + IF lv_trkorr IS INITIAL. + RETURN. + ENDIF. + + ls_request = zcl_abapgit_factory=>get_cts_api( )->read( lv_trkorr ). + + IF lines( ls_request-keys ) = 0. + zcx_abapgit_exception=>raise( |No keys found, select task| ). + ENDIF. + + LOOP AT ls_request-keys INTO ls_key WHERE object = 'TABU'. + ASSERT ls_key-objname IS NOT INITIAL. + ASSERT ls_key-tabkey IS NOT INITIAL. + + CLEAR ls_config. + ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. + ls_config-name = to_upper( ls_key-objname ). + lv_where = concatenated_key_to_where( + iv_table = ls_key-objname + iv_tabkey = ls_key-tabkey ). + APPEND lv_where TO ls_config-where. + mi_config->add_config( ls_config ). + ENDLOOP. + + ENDMETHOD. + METHOD build_where. + + DATA lv_where LIKE LINE OF rt_where. + + rt_where = zcl_abapgit_convert=>split_string( io_map->get( c_id-where ) ). + + DELETE rt_where WHERE table_line IS INITIAL. + + LOOP AT rt_where INTO lv_where. + IF strlen( lv_where ) <= 2. + DELETE rt_where INDEX sy-tabix. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD concatenated_key_to_where. + + DATA lo_structdescr TYPE REF TO cl_abap_structdescr. + DATA lo_typedescr TYPE REF TO cl_abap_typedescr. + DATA lt_fields TYPE zcl_abapgit_data_utils=>ty_names. + DATA lv_field LIKE LINE OF lt_fields. + DATA lv_table TYPE tadir-obj_name. + DATA lv_length TYPE i. + DATA lv_tabix TYPE i. + DATA lv_key TYPE c LENGTH 900. + + lv_key = iv_tabkey. + lo_structdescr ?= cl_abap_typedescr=>describe_by_name( iv_table ). + + lv_table = iv_table. + lt_fields = zcl_abapgit_data_utils=>list_key_fields( lv_table ). + + LOOP AT lt_fields INTO lv_field. + lv_tabix = sy-tabix. + lo_typedescr = cl_abap_typedescr=>describe_by_name( |{ iv_table }-{ lv_field }| ). + lv_length = lo_typedescr->length / cl_abap_char_utilities=>charsize. + + IF lv_tabix = 1 AND lo_typedescr->get_relative_name( ) = 'MANDT'. + lv_key = lv_key+lv_length. + CONTINUE. + ENDIF. + + IF lv_key = |*|. + EXIT. " current loop + ENDIF. + IF NOT rv_where IS INITIAL. + rv_where = |{ rv_where } AND |. + ENDIF. + rv_where = |{ rv_where }{ to_lower( lv_field ) } = '{ lv_key(lv_length) }'|. + lv_key = lv_key+lv_length. + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + + mi_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + mi_config = mi_repo->get_data_config( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_data. + + CREATE OBJECT lo_component + EXPORTING + iv_key = iv_key. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Data Config' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD event_add. + + DATA lo_map TYPE REF TO zcl_abapgit_string_map. + DATA ls_config TYPE zif_abapgit_data_config=>ty_config. + + lo_map = ii_event->form_data( ). + + ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. + ls_config-name = to_upper( lo_map->get( c_id-table ) ). + ls_config-skip_initial = lo_map->get( c_id-skip_initial ). + ls_config-where = build_where( lo_map ). + + mi_config->add_config( ls_config ). + + ENDMETHOD. + METHOD event_remove. + + DATA lo_map TYPE REF TO zcl_abapgit_string_map. + DATA ls_config TYPE zif_abapgit_data_config=>ty_config. + + lo_map = ii_event->form_data( ). + + ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. + ls_config-name = to_upper( lo_map->get( c_id-table ) ). + + mi_config->remove_config( ls_config ). + + ENDMETHOD. + METHOD event_update. + + DATA lo_map TYPE REF TO zcl_abapgit_string_map. + DATA ls_config TYPE zif_abapgit_data_config=>ty_config. + + lo_map = ii_event->form_data( ). + + ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. + ls_config-name = to_upper( lo_map->get( c_id-table ) ). + ls_config-skip_initial = lo_map->has( to_upper( c_id-skip_initial ) ). + ls_config-where = build_where( lo_map ). + + mi_config->update_config( ls_config ). + + ENDMETHOD. + METHOD get_form_schema. + ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'data-config' ). + + ro_form->text( + iv_label = 'Table' + iv_name = c_id-table + iv_required = abap_true + iv_max = 16 ). + + ro_form->checkbox( + iv_label = 'Skip Initial Values' + iv_name = c_id-skip_initial ). + + ro_form->textarea( + iv_label = 'Where' + iv_placeholder = 'Conditions separated by newline' + iv_name = c_id-where ). + + ro_form->command( + iv_label = 'Add' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-add ). + ENDMETHOD. + METHOD render_existing. + + DATA lo_form TYPE REF TO zcl_abapgit_html_form. + DATA lo_form_data TYPE REF TO zcl_abapgit_string_map. + DATA lt_configs TYPE zif_abapgit_data_config=>ty_config_tt. + DATA ls_config LIKE LINE OF lt_configs. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + CREATE OBJECT lo_form_data. + + lt_configs = mi_config->get_configs( ). + + LOOP AT lt_configs INTO ls_config. + lo_form = zcl_abapgit_html_form=>create( ). + CREATE OBJECT lo_form_data. + + lo_form_data->set( + iv_key = c_id-table + iv_val = |{ ls_config-name }| ). + lo_form->text( + iv_label = 'Table' + iv_name = c_id-table + iv_readonly = abap_true + iv_max = 16 ). + + lo_form_data->set( + iv_key = c_id-skip_initial + iv_val = ls_config-skip_initial ). + lo_form->checkbox( + iv_label = 'Skip Initial Values' + iv_name = c_id-skip_initial ). + + lo_form_data->set( + iv_key = c_id-where + iv_val = concat_lines_of( table = ls_config-where sep = |\n| ) ). + lo_form->textarea( + iv_label = 'Where' + iv_placeholder = 'Conditions separated by newline' + iv_name = c_id-where ). + + lo_form->command( + iv_label = 'Update' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-update ). + lo_form->command( + iv_label = 'Remove' + iv_action = c_event-remove ). + ri_html->add( lo_form->render( lo_form_data ) ). + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_event-add. + mo_validation_log = mo_form_util->validate( mo_form_data ). + validate_table_name( + EXPORTING + iv_table_name = mo_form_data->get( c_id-table ) + CHANGING + co_validation_log = mo_validation_log ). + IF mo_validation_log->is_empty( ) = abap_false. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + event_add( ii_event ). + mi_repo->refresh( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + WHEN c_event-update. + event_update( ii_event ). + mi_repo->refresh( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_event-remove. + event_remove( ii_event ). + mi_repo->refresh( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_event-add_via_transport. + add_via_transport( ). + mi_repo->refresh( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-advanced-data' ). + + ro_toolbar->add( iv_txt = 'Add Via Transport' + iv_act = c_event-add_via_transport ). + ro_toolbar->add( iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '
    ' ). + ri_html->add( render_existing( ) ). + mo_form_data->delete( 'table' ). + mo_form_data->delete( 'skip_initial' ). + mo_form_data->delete( 'where' ). + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD validate_table_name. + DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, + lv_exists TYPE abap_bool, + lv_table_name TYPE sobj_name. + + lv_table_name = to_upper( condense( iv_table_name ) ). + + CLEAR ls_item. + ls_item-obj_name = lv_table_name. + ls_item-obj_type = 'TABL'. + lv_exists = zcl_abapgit_objects=>exists( ls_item ). + + IF lv_exists = abap_false. + co_validation_log->set( + iv_key = c_id-table + iv_val = |Table { lv_table_name } does not exists | ). + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_gui_page_cpackage IMPLEMENTATION. + METHOD zif_abapgit_gui_menu_provider~get_menu. + RETURN. + ENDMETHOD. + + METHOD constructor. + + super->constructor( ). + + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + + ENDMETHOD. + + METHOD get_form_schema. + ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'create-package' ). + + ro_form->text( + iv_label = 'Package' + iv_name = c_id-package + iv_required = abap_true + iv_upper_case = abap_true + iv_max = 30 ). + + ro_form->text( + iv_label = 'Description' + iv_name = c_id-description + iv_required = abap_true + iv_max = 60 ). + + ro_form->text( + iv_label = 'Software Component' + iv_name = c_id-software_component + iv_required = abap_true + iv_upper_case = abap_true + iv_placeholder = 'typically HOME or LOCAL' + iv_max = 20 ). + +* not required for local packages + ro_form->text( + iv_label = 'Transport Layer' + iv_name = c_id-transport_layer + iv_upper_case = abap_true + iv_max = 4 ). + + ro_form->text( + iv_label = 'Super Package' + iv_name = c_id-super_package + iv_upper_case = abap_true + iv_max = 30 ). + +********* + + ro_form->command( + iv_label = 'Create' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-create ). + + ro_form->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_cpackage. + + CREATE OBJECT lo_component. + lo_component->mv_default_name = iv_name. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Create Package' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA ls_create TYPE zif_abapgit_sap_package=>ty_create. + + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_event-create. + mo_validation_log = mo_form_util->validate( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + ls_create-devclass = mo_form_data->get( c_id-package ). + IF zcl_abapgit_factory=>get_sap_package( ls_create-devclass )->exists( ) = abap_true. + zcx_abapgit_exception=>raise( |Package { ls_create-devclass } already exists| ). + ENDIF. + ls_create-ctext = mo_form_data->get( c_id-description ). + ls_create-dlvunit = mo_form_data->get( c_id-software_component ). + ls_create-parentcl = mo_form_data->get( c_id-super_package ). + ls_create-pdevclass = mo_form_data->get( c_id-transport_layer ). + ls_create-as4user = sy-uname. + + zcl_abapgit_factory=>get_sap_package( ls_create-devclass )->create( ls_create ). + MESSAGE 'Package created' TYPE 'S'. + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + WHEN OTHERS. + " do nothing + ENDCASE. + + ENDMETHOD. + METHOD get_defaults. + + mo_form_data->set( + iv_key = c_id-transport_layer + iv_val = zcl_abapgit_factory=>get_sap_package( 'DUMMY' )->get_default_transport_layer( ) ). + + mo_form_data->set( + iv_key = c_id-package + iv_val = mv_default_name ). + + ENDMETHOD. + + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + IF mo_form_util->is_empty( mo_form_data ) = abap_true. + get_defaults( ). + ENDIF. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_commit IMPLEMENTATION. + METHOD branch_name_to_internal. + rv_new_branch_name = zcl_abapgit_git_branch_utils=>complete_heads_branch_name( + zcl_abapgit_git_branch_utils=>normalize_branch_name( iv_branch_name ) ). + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + + mi_repo_online = ii_repo_online. + mo_stage = io_stage. + mt_stage = mo_stage->get_all( ). + mv_sci_result = iv_sci_result. + + " Get settings from DB + mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_commit. + + CREATE OBJECT lo_component + EXPORTING + ii_repo_online = ii_repo_online + io_stage = io_stage + iv_sci_result = iv_sci_result. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Commit' + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_comment_default. + + rv_text = mo_settings->get_commitmsg_comment_default( ). + + IF rv_text IS INITIAL. + RETURN. + ENDIF. + + REPLACE '$FILE' IN rv_text WITH get_comment_file( mt_stage ). + REPLACE '$OBJECT' IN rv_text WITH get_comment_object( mt_stage ). + + ENDMETHOD. + METHOD get_comment_file. + + DATA lv_count TYPE i. + + FIELD-SYMBOLS LIKE LINE OF it_stage. + + lv_count = lines( it_stage ). + + IF lv_count = 1. + " Just one file so we use the file name + READ TABLE it_stage ASSIGNING INDEX 1. + ASSERT sy-subrc = 0. + + rv_text = -file-filename. + ELSE. + " For multiple file we use the count instead + rv_text = |{ lv_count } files|. + ENDIF. + + ENDMETHOD. + METHOD get_comment_object. + + DATA: + lv_count TYPE i, + ls_item TYPE zif_abapgit_definitions=>ty_item, + lt_items TYPE zif_abapgit_definitions=>ty_items_tt. + + FIELD-SYMBOLS LIKE LINE OF it_stage. + + " Get objects + LOOP AT it_stage ASSIGNING . + CLEAR ls_item. + ls_item-obj_type = -status-obj_type. + ls_item-obj_name = -status-obj_name. + COLLECT ls_item INTO lt_items. + ENDLOOP. + + lv_count = lines( lt_items ). + + IF lv_count = 1. + " Just one object so we use the object name + READ TABLE lt_items INTO ls_item INDEX 1. + ASSERT sy-subrc = 0. + + CONCATENATE ls_item-obj_type ls_item-obj_name INTO rv_text SEPARATED BY space. + ELSE. + " For multiple objects we use the count instead + rv_text = |{ lv_count } objects|. + ENDIF. + + ENDMETHOD. + METHOD get_committer_email. + + DATA li_user TYPE REF TO zif_abapgit_persist_user. + + li_user = zcl_abapgit_persist_factory=>get_user( ). + + rv_email = li_user->get_repo_git_user_email( mi_repo_online->get_url( ) ). + IF rv_email IS INITIAL. + rv_email = li_user->get_default_git_user_email( ). + ENDIF. + IF rv_email IS INITIAL. + " get default from user record + rv_email = zcl_abapgit_env_factory=>get_user_record( )->get_email( sy-uname ). + ENDIF. + + ENDMETHOD. + METHOD get_committer_name. + + DATA li_user TYPE REF TO zif_abapgit_persist_user. + + li_user = zcl_abapgit_persist_factory=>get_user( ). + + rv_user = li_user->get_repo_git_user_name( mi_repo_online->get_url( ) ). + IF rv_user IS INITIAL. + rv_user = li_user->get_default_git_user_name( ). + ENDIF. + IF rv_user IS INITIAL. + " get default from user record + rv_user = zcl_abapgit_env_factory=>get_user_record( )->get_name( sy-uname ). + ENDIF. + + ENDMETHOD. + METHOD get_defaults. + + DATA li_exit TYPE REF TO zif_abapgit_exit. + + ms_commit-committer_name = get_committer_name( ). + ms_commit-committer_email = get_committer_email( ). + ms_commit-comment = get_comment_default( ). + + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->change_committer_info( + EXPORTING + iv_repo_url = mi_repo_online->get_url( ) + CHANGING + cv_name = ms_commit-committer_name + cv_email = ms_commit-committer_email ). + + " Committer + mo_form_data->set( + iv_key = c_id-committer_name + iv_val = ms_commit-committer_name ). + mo_form_data->set( + iv_key = c_id-committer_email + iv_val = ms_commit-committer_email ). + + " Message + mo_form_data->set( + iv_key = c_id-comment + iv_val = ms_commit-comment ). + + ENDMETHOD. + METHOD get_form_schema. + + DATA lv_commitmsg_comment_length TYPE i. + CONSTANTS lc_commitmsg_comment_min_len TYPE i VALUE 1. + CONSTANTS lc_commitmsg_comment_max_len TYPE i VALUE 255. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'commit-form' + iv_help_page = 'https://docs.abapgit.org/guide-stage-commit.html' ). + + lv_commitmsg_comment_length = mo_settings->get_commitmsg_comment_length( ). + + ro_form->text( + iv_name = c_id-comment + iv_label = 'Comment' + iv_required = abap_true + iv_min = lc_commitmsg_comment_min_len + iv_max = lv_commitmsg_comment_length + iv_placeholder = |Add a mandatory comment with max { lc_commitmsg_comment_max_len } characters| + )->textarea( + iv_name = c_id-body + iv_label = 'Body' + iv_rows = 6 + iv_cols = mo_settings->get_commitmsg_body_size( ) + iv_placeholder = 'Add an optional description...' + )->text( + iv_name = c_id-committer_name + iv_label = 'Committer Name' + iv_required = abap_true + )->text( + iv_name = c_id-committer_email + iv_label = 'Committer Email' + iv_required = abap_true ). + + IF mo_settings->get_commitmsg_hide_author( ) IS INITIAL. + ro_form->text( + iv_name = c_id-author_name + iv_label = 'Author Name' + iv_placeholder = 'Optionally, specify an author (same as committer by default)' + )->text( + iv_name = c_id-author_email + iv_label = 'Author Email' ). + ENDIF. + + ro_form->text( + iv_name = c_id-new_branch_name + iv_label = 'New Branch Name' + iv_placeholder = 'Optionally, enter a new branch name for this commit' + iv_condense = abap_true ). + ro_form->command( + iv_label = 'Commit' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-commit + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD render_stage_details. + + FIELD-SYMBOLS LIKE LINE OF mt_stage. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + + ri_html->add( '' ). + LOOP AT mt_stage ASSIGNING . + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + ENDLOOP. + ri_html->add( '' ). + + ri_html->add( '
    Staged Files (See Summary Above)
    ' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( + iv_lstate = -status-lstate + iv_rstate = -status-rstate ) ). + ri_html->add( '' ). + ri_html->add( zcl_abapgit_stage=>method_description( -method ) ). + ri_html->add( '' ). + ri_html->add( -file-path && -file-filename ). + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_stage_summary. + + DATA: + BEGIN OF ls_sum, + method TYPE string, + count TYPE i, + END OF ls_sum, + lt_sum LIKE STANDARD TABLE OF ls_sum WITH DEFAULT KEY. + + FIELD-SYMBOLS LIKE LINE OF mt_stage. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + LOOP AT mt_stage ASSIGNING . + ls_sum-method = -method. + ls_sum-count = 1. + COLLECT ls_sum INTO lt_sum. + ENDLOOP. + + ri_html->add( 'Stage Summary: ' ). + + READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-add. + IF sy-subrc = 0. + ri_html->add( |+ { ls_sum-count }| ). + ENDIF. + READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-rm. + IF sy-subrc = 0. + ri_html->add( |- { ls_sum-count }| ). + ENDIF. + READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-ignore. + IF sy-subrc = 0. + ri_html->add( |~ { ls_sum-count }| ). + ENDIF. + + IF lines( mt_stage ) = 1. + ri_html->add( 'file' ). + ELSE. + ri_html->add( 'files' ). + ENDIF. + + ri_html->add( '(See Details Below)' ). + + ENDMETHOD. + METHOD validate_form. + + DATA: lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, + lv_new_branch_name TYPE string. + + ro_validation_log = mo_form_util->validate( io_form_data ). + + IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-committer_email ) ) = abap_false. + ro_validation_log->set( + iv_key = c_id-committer_email + iv_val = |Invalid email address| ). + ENDIF. + + IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-author_email ) ) = abap_false. + ro_validation_log->set( + iv_key = c_id-author_email + iv_val = |Invalid email address| ). + ENDIF. + + lv_new_branch_name = io_form_data->get( c_id-new_branch_name ). + IF lv_new_branch_name IS NOT INITIAL. + " check if branch already exists + lt_branches = zcl_abapgit_git_factory=>get_git_transport( + )->branches( mi_repo_online->get_url( ) + )->get_branches_only( ). + READ TABLE lt_branches TRANSPORTING NO FIELDS WITH TABLE KEY name_key + COMPONENTS name = branch_name_to_internal( lv_new_branch_name ). + IF sy-subrc = 0. + ro_validation_log->set( + iv_key = c_id-new_branch_name + iv_val = |Branch already exists| ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + DATA lv_new_branch_name TYPE string. + + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_event-commit. + " Validate form entries before committing + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + + " new branch fields not needed in commit data + mo_form_data->strict( abap_false ). + + mo_form_data->to_abap( CHANGING cs_container = ms_commit ). + + REPLACE ALL OCCURRENCES + OF cl_abap_char_utilities=>cr_lf + IN ms_commit-body + WITH cl_abap_char_utilities=>newline. + + lv_new_branch_name = mo_form_data->get( c_id-new_branch_name ). + " create new branch and commit to it if branch name is not empty + IF lv_new_branch_name IS NOT INITIAL. + lv_new_branch_name = branch_name_to_internal( lv_new_branch_name ). + " creates a new branch and automatically switches to it + mi_repo_online->create_branch( lv_new_branch_name ). + ENDIF. + + zcl_abapgit_services_git=>commit( + is_commit = ms_commit + ii_repo_online = mi_repo_online + io_stage = mo_stage ). + MESSAGE 'Commit was successful' TYPE 'S'. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + WHEN OTHERS. + ASSERT 1 = 1. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + IF mo_form_util->is_empty( mo_form_data ) = abap_true. + get_defaults( ). + ENDIF. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + iv_show_commit = abap_false + ii_repo = mi_repo_online ) ). + ri_html->add( '
    ' ). + + ri_html->add( '
    ' ). + ri_html->add( render_stage_summary( ) ). + ri_html->add( '
    ' ). + + ri_html->add( mo_form->render( + iv_form_class = 'w800px' + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + + ri_html->add( '
    ' ). + ri_html->add( render_stage_details( ) ). + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_chg_pckg IMPLEMENTATION. + METHOD change_package. + + DATA: + lt_mapping TYPE ty_mapping, + lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + + ASSERT iv_old_package <> iv_new_package. + + lt_mapping = get_package_mapping( + iv_old_package = iv_old_package + iv_new_package = iv_new_package ). + + lt_tadir = mi_repo->get_tadir_objects( ). + + create_package_hierarchy( lt_mapping ). + + change_package_assignment( + it_mapping = lt_mapping + it_tadir = lt_tadir ). + + update_sotr_package_assignment( lt_mapping ). + + update_repo_persistence( + iv_old_package = iv_old_package + iv_new_package = iv_new_package ). + + update_repo_checksums( lt_mapping ). + + IF iv_remove_old = abap_true. + delete_packages( lt_tadir ). + ENDIF. + + zcl_abapgit_repo_srv=>get_instance( )->init( ). + + ENDMETHOD. + METHOD change_package_assignment. + + DATA ls_tadir LIKE LINE OF it_tadir. + + FIELD-SYMBOLS LIKE LINE OF it_mapping. + + " TODO: Transportable packages (add to transport) + LOOP AT it_tadir INTO ls_tadir WHERE object <> 'DEVC' AND object <> 'NSPC'. + READ TABLE it_mapping ASSIGNING WITH KEY old_package = ls_tadir-devclass. + ASSERT sy-subrc = 0. + + zcl_abapgit_factory=>get_tadir( )->insert_single( + iv_pgmid = ls_tadir-pgmid + iv_object = ls_tadir-object + iv_obj_name = ls_tadir-obj_name + iv_package = -new_package ). + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + mi_repo = ii_repo. + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + + IF mi_repo->get_dot_abapgit( )->get_folder_logic( ) <> zif_abapgit_dot_abapgit=>c_folder_logic-prefix. + zcx_abapgit_exception=>raise( 'Feature is only supported repositories with prefix folder logic' ). + ENDIF. + + IF zcl_abapgit_factory=>get_cts_api( )->is_chrec_possible_for_package( mi_repo->get_package( ) ) = abap_true. + zcx_abapgit_exception=>raise( 'Feature is only supported local packages (no transport)' ). + ENDIF. + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_chg_pckg. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Change Repository Package' + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD create_package_hierarchy. + + DATA: + ls_package TYPE zif_abapgit_sap_package=>ty_create, + ls_map TYPE ty_map. + + FIELD-SYMBOLS LIKE LINE OF it_mapping. + + LOOP AT it_mapping ASSIGNING . + ls_package = zcl_abapgit_factory=>get_sap_package( -old_package )->get( ). + + ls_package-devclass = -new_package. + ls_package-as4user = sy-uname. + + READ TABLE it_mapping INTO ls_map WITH KEY old_package = ls_package-parentcl. + IF sy-subrc = 0. + ls_package-parentcl = ls_map-new_package. + ENDIF. + + zcl_abapgit_factory=>get_sap_package( ls_map-new_package )->create( ls_package ). + ENDLOOP. + + " TODO: Transportable packages (add to transport and tadir) + + ENDMETHOD. + METHOD delete_packages. + + DATA lt_tadir LIKE it_tadir. + + lt_tadir = it_tadir. + + DELETE lt_tadir WHERE object <> 'DEVC'. + + SORT lt_tadir DESCENDING BY obj_name. + + zcl_abapgit_objects=>delete( lt_tadir ). + + ENDMETHOD. + METHOD get_form_schema. + + ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'change-package' ). + + ro_form->text( + iv_name = c_id-new_package + iv_label = 'New Package' + iv_required = abap_true + iv_upper_case = abap_true + iv_side_action = c_event-choose_package_new + iv_max = 30 + )->text( + iv_name = c_id-old_package + iv_label = 'Old Package' + iv_readonly = abap_true + iv_required = abap_true + iv_upper_case = abap_true + iv_side_action = c_event-choose_package_old + iv_max = 30 + )->checkbox( + iv_name = c_id-remove_old + iv_label = 'Delete Old Packages' + )->command( + iv_label = 'Change Package' + iv_action = c_event-change_package + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD get_package_mapping. + + DATA: + lt_old_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt, + lv_old_package TYPE string, + lv_new_package TYPE string. + + FIELD-SYMBOLS LIKE LINE OF rt_mapping. + + IF mi_repo->get_local_settings( )-ignore_subpackages = abap_false. + lt_old_packages = zcl_abapgit_factory=>get_sap_package( iv_old_package )->list_subpackages( ). + ENDIF. + INSERT iv_old_package INTO TABLE lt_old_packages. + + " Check new package names and make sure they don't exists + LOOP AT lt_old_packages INTO lv_old_package. + lv_new_package = lv_old_package. + REPLACE FIRST OCCURRENCE OF iv_old_package IN lv_new_package WITH iv_new_package. + IF strlen( lv_new_package ) > 30. + zcx_abapgit_exception=>raise( |Package { lv_new_package } longer than 30 characters| ). + ENDIF. + IF zcl_abapgit_factory=>get_sap_package( |{ lv_new_package }| )->exists( ) = abap_true. + zcx_abapgit_exception=>raise( |Package { lv_new_package } already exists| ). + ENDIF. + APPEND INITIAL LINE TO rt_mapping ASSIGNING . + -old_package = lv_old_package. + -new_package = lv_new_package. + ENDLOOP. + + SORT rt_mapping. + + ENDMETHOD. + METHOD init_form. + + mo_form_data->set( + iv_key = c_id-old_package + iv_val = mi_repo->get_package( ) ). + + mo_form_data->set( + iv_key = c_id-remove_old + iv_val = abap_true ). + + ENDMETHOD. + METHOD update_repo_checksums. + + DATA: + lv_key TYPE zif_abapgit_persistence=>ty_repo-key, + lo_checksums TYPE REF TO zcl_abapgit_repo_checksums, + lt_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt. + + FIELD-SYMBOLS: + LIKE LINE OF lt_checksums, + LIKE LINE OF it_mapping. + + lv_key = mi_repo->get_key( ). + + CREATE OBJECT lo_checksums EXPORTING iv_repo_key = lv_key. + + lt_checksums = lo_checksums->zif_abapgit_repo_checksums~get( ). + + LOOP AT lt_checksums ASSIGNING WHERE item-devclass IS NOT INITIAL. + READ TABLE it_mapping ASSIGNING WITH KEY old_package = -item-devclass. + ASSERT sy-subrc = 0. + + -item-devclass = -new_package. + ENDLOOP. + + lo_checksums->force_write( lt_checksums ). + + ENDMETHOD. + METHOD update_repo_persistence. + + DATA: + lv_key TYPE zif_abapgit_persistence=>ty_repo-key, + lo_persist TYPE REF TO zif_abapgit_persist_repo, + ls_repo_data TYPE zif_abapgit_persistence=>ty_repo, + ls_meta TYPE zif_abapgit_persistence=>ty_repo_xml, + ls_change_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask. + + lv_key = mi_repo->get_key( ). + lo_persist = zcl_abapgit_persist_factory=>get_repo( ). + + TRY. + ls_repo_data = lo_persist->read( lv_key ). + CATCH zcx_abapgit_not_found. + zcx_abapgit_exception=>raise( 'Repository not found' ). + ENDTRY. + + ASSERT ls_repo_data-package = iv_old_package. + + ls_repo_data-package = iv_new_package. + + MOVE-CORRESPONDING ls_repo_data TO ls_meta. + ls_change_mask-package = abap_true. + + lo_persist->update_metadata( + iv_key = lv_key + is_meta = ls_meta + is_change_mask = ls_change_mask ). + + ENDMETHOD. + METHOD update_sotr_package_assignment. + + FIELD-SYMBOLS LIKE LINE OF it_mapping. + + LOOP AT it_mapping ASSIGNING . + zcl_abapgit_sotr_handler=>change_sotr_package( + iv_old_package = -old_package + iv_new_package = -new_package ). + ENDLOOP. + + ENDMETHOD. + METHOD validate_form. + + DATA lv_new_package TYPE devclass. + + ro_validation_log = mo_form_util->validate( io_form_data ). + + lv_new_package = io_form_data->get( c_id-new_package ). + + IF lv_new_package IS NOT INITIAL AND lv_new_package = io_form_data->get( c_id-old_package ). + ro_validation_log->set( + iv_key = c_id-new_package + iv_val = 'New package must be different from old package' ). + ENDIF. + + IF zcl_abapgit_factory=>get_cts_api( )->is_chrec_possible_for_package( lv_new_package ) = abap_true. + ro_validation_log->set( + iv_key = c_id-new_package + iv_val = 'Feature is only supported local packages (no transport)' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_event-change_package. + + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_false. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + change_package( + iv_old_package = |{ mo_form_data->get( c_id-old_package ) }| + iv_new_package = |{ mo_form_data->get( c_id-new_package ) }| + iv_remove_old = |{ mo_form_data->get( c_id-remove_old ) }| ). + + MESSAGE 'Package successfully changed' TYPE 'S'. + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ENDIF. + + WHEN c_event-choose_package_old. + + mo_form_data->set( + iv_key = c_id-old_package + iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ). + + IF mo_form_data->get( c_id-old_package ) IS NOT INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDIF. + + WHEN c_event-choose_package_new. + + mo_form_data->set( + iv_key = c_id-new_package + iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ). + + IF mo_form_data->get( c_id-new_package ) IS NOT INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDIF. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + init_form( ). + + register_handlers( ). + + ri_html = zcl_abapgit_html=>create( ). + + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_PAGE_SETT_REPO IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + + mi_repo = ii_repo. + mo_form = get_form_schema( ). + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_repo. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Repository Settings' + io_page_menu = zcl_abapgit_gui_menus=>repo_settings( + iv_key = ii_repo->get_key( ) + iv_act = zif_abapgit_definitions=>c_action-repo_settings ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'repo-settings-form' + iv_help_page = 'https://docs.abapgit.org/settings-dot-abapgit.html' ). + + ro_form->start_group( + iv_name = c_id-dot + iv_label = 'Repository Settings (.abapgit.xml)' + iv_hint = 'Settings stored in root folder in .abapgit.xml file' + )->text( + iv_name = c_id-name + iv_label = 'Name' + iv_hint = 'Official name (can be overwritten by local display name)' + )->text( + iv_name = c_id-version_constant + iv_label = 'Version Constant' + iv_placeholder = 'CLASS=>VERSION_CONSTANT or INTERFACE=>VERSION_CONSTANT' + iv_upper_case = abap_true + )->text( + iv_name = c_id-version_value + iv_label = 'Version Value' + iv_readonly = abap_true + )->start_group( + iv_name = c_id-i18n + iv_label = 'Texts' + )->text( + iv_name = c_id-main_language + iv_label = 'Main Language' + iv_hint = 'Main language of repository (cannot be changed)' + iv_readonly = abap_true + )->text( + iv_name = c_id-i18n_langs + iv_label = 'Serialize Translations for Additional Languages' + iv_hint = 'Comma-separate 2-letter ISO language codes e.g. "DE,ES,..." - should not include main language' + )->checkbox( + iv_name = c_id-use_lxe + iv_label = 'Use LXE Approach for Translations' + iv_hint = 'It''s mandatory to specify the list of languages above in addition to this setting' + )->textarea( + iv_name = c_id-wo_transaltion + iv_label = 'Objects (wildcard) to keep in main language only (without translation)' + iv_hint = |List of patterns to exclude from translation. The check builds a simplified path to object:| + && | like `/src/pkg/subpkg/obj.type` which is then checked versus patterns with CP.| + && | So to exclude specific object use `*/zcl_xy.clas`, object of the specific type - `*.clas`,| + && | all objects in the package `*/pkg/*`. For additional compatibility, if line does NOT start| + && | wildcard `*` or `/` - then `*/` is prepended. So `zcl_xy.clas` = `*/zcl_xy.clas`| + )->start_group( + iv_name = c_id-file_system + iv_label = 'Files' + )->radio( + iv_name = c_id-folder_logic + iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix + iv_label = 'Folder Logic' + iv_hint = 'Define how package folders are named in repository' + )->option( + iv_label = 'Prefix' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix + )->option( + iv_label = 'Full' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-full + )->option( + iv_label = 'Mixed' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-mixed + )->text( + iv_name = c_id-starting_folder + iv_label = 'Starting Folder' + iv_hint = 'Root folder that defines where serialization starts' + )->textarea( + iv_name = c_id-ignore + iv_label = 'Ignore Files' + iv_hint = 'List of files in starting folder that shall not be serialized' + )->start_group( + iv_name = c_id-abap_system + iv_label = 'ABAP' + )->table( + iv_name = c_id-requirements + iv_label = 'Requirements' + iv_hint = 'List of software components with minimum release and patch' + )->column( + iv_label = 'Software Component' + iv_width = '40%' + )->column( + iv_label = 'Minimum Release' + iv_width = '30%' + )->column( + iv_label = 'Minimum Patch' + iv_width = '30%' + )->text( + iv_name = c_id-original_system + iv_label = 'Original System' + iv_upper_case = abap_true + iv_max = 3 + iv_hint = 'Sets the source system of objects during deserialize in downstream systems' + && ' (use "SID" to force the source system to sy-sysid)' ). + + IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. + ro_form->radio( + iv_name = c_id-abap_langu_vers + iv_default_value = '' + iv_condense = abap_true + iv_label = 'ABAP Language Version' + iv_hint = 'Define the ABAP language version for objects in the repository' + )->option( + iv_label = 'Any (Object-specific ABAP Language Version)' + iv_value = '' + )->option( + iv_label = 'Ignore (ABAP Language Version not serialized)' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-ignore + )->option( + iv_label = 'Standard ABAP' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-standard + )->option( + iv_label = 'ABAP for Key Users' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user + )->option( + iv_label = 'ABAP for Cloud Development' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development ). + ENDIF. + + ro_form->command( + iv_label = 'Save Settings' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-save + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD read_settings. + + DATA: + lo_dot TYPE REF TO zcl_abapgit_dot_abapgit, + ls_dot TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit, + lv_main_lang TYPE spras, + lv_ignore TYPE string, + ls_requirements LIKE LINE OF ls_dot-requirements, + lv_row TYPE i, + lv_val TYPE string. + + " Get settings from DB + lo_dot = mi_repo->get_dot_abapgit( ). + ls_dot = lo_dot->get_data( ). + lv_main_lang = lo_dot->get_main_language( ). + CREATE OBJECT ro_form_data. + + " Repository Settings + ro_form_data->set( + iv_key = c_id-name + iv_val = ls_dot-name ). + ro_form_data->set( + iv_key = c_id-main_language + iv_val = |{ lv_main_lang } ({ zcl_abapgit_convert=>language_sap1_to_text( lv_main_lang ) })| ). + ro_form_data->set( + iv_key = c_id-i18n_langs + iv_val = zcl_abapgit_lxe_texts=>convert_table_to_lang_string( lo_dot->get_i18n_languages( ) ) ). + ro_form_data->set( + iv_key = c_id-use_lxe + iv_val = boolc( lo_dot->use_lxe( ) = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-wo_transaltion + iv_val = concat_lines_of( + table = lo_dot->get_objs_without_translation( ) + sep = cl_abap_char_utilities=>newline ) ). + ro_form_data->set( + iv_key = c_id-folder_logic + iv_val = ls_dot-folder_logic ). + ro_form_data->set( + iv_key = c_id-starting_folder + iv_val = ls_dot-starting_folder ). + ro_form_data->set( + iv_key = c_id-version_constant + iv_val = ls_dot-version_constant ). + TRY. + ro_form_data->set( + iv_key = c_id-version_value + iv_val = zcl_abapgit_version=>get_version_constant_value( ls_dot-version_constant ) ). + CATCH zcx_abapgit_exception. + ro_form_data->set( + iv_key = c_id-version_value + iv_val = '' ). + ENDTRY. + + lv_ignore = concat_lines_of( + table = ls_dot-ignore + sep = cl_abap_char_utilities=>newline ). + + ro_form_data->set( + iv_key = c_id-ignore + iv_val = lv_ignore ). + + LOOP AT ls_dot-requirements INTO ls_requirements. + lv_row = lv_row + 1. + DO 3 TIMES. + CASE sy-index. + WHEN 1. + lv_val = ls_requirements-component. + WHEN 2. + lv_val = ls_requirements-min_release. + WHEN 3. + lv_val = ls_requirements-min_patch. + ENDCASE. + ro_form_data->set( + iv_key = |{ c_id-requirements }-{ lv_row }-{ sy-index }| + iv_val = lv_val ). + ENDDO. + ENDLOOP. + + DO c_empty_rows TIMES. + lv_row = lv_row + 1. + DO 3 TIMES. + ro_form_data->set( + iv_key = |{ c_id-requirements }-{ lv_row }-{ sy-index }| + iv_val = '' ). + ENDDO. + ENDDO. + + mv_requirements_count = lv_row. + + ro_form_data->set( + iv_key = |{ c_id-requirements }-{ zif_abapgit_html_form=>c_rows }| + iv_val = |{ mv_requirements_count }| ). + + IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. + ro_form_data->set( + iv_key = c_id-abap_langu_vers + iv_val = ls_dot-abap_language_version ). + ENDIF. + + ro_form_data->set( + iv_key = c_id-original_system + iv_val = ls_dot-original_system ). + + ENDMETHOD. + METHOD save_settings. + + DATA: + lo_dot TYPE REF TO zcl_abapgit_dot_abapgit, + lv_ignore TYPE string, + lt_ignore TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + lt_wo_transl TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + ls_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement, + lt_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt. + + lo_dot = mi_repo->get_dot_abapgit( ). + + lo_dot->set_name( mo_form_data->get( c_id-name ) ). + lo_dot->set_folder_logic( mo_form_data->get( c_id-folder_logic ) ). + lo_dot->set_starting_folder( mo_form_data->get( c_id-starting_folder ) ). + lo_dot->set_version_constant( mo_form_data->get( c_id-version_constant ) ). + lo_dot->set_original_system( mo_form_data->get( c_id-original_system ) ). + + IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. + lo_dot->set_abap_language_version( mo_form_data->get( c_id-abap_langu_vers ) ). + ENDIF. + + lo_dot->set_i18n_languages( + zcl_abapgit_lxe_texts=>convert_lang_string_to_table( + iv_langs = mo_form_data->get( c_id-i18n_langs ) + iv_skip_main_language = lo_dot->get_main_language( ) ) ). + lo_dot->use_lxe( boolc( mo_form_data->get( c_id-use_lxe ) = abap_true ) ). + + lt_wo_transl = zcl_abapgit_i18n_params=>normalize_obj_patterns( + zcl_abapgit_convert=>split_string( mo_form_data->get( c_id-wo_transaltion ) ) ). + lo_dot->set_objs_without_translation( lt_wo_transl ). + + " Remove all ignores + lt_ignore = lo_dot->get_data( )-ignore. + LOOP AT lt_ignore INTO lv_ignore. + lo_dot->remove_ignore( iv_path = '' + iv_filename = lv_ignore ). + ENDLOOP. + + " Add newly entered ignores + lt_ignore = zcl_abapgit_convert=>split_string( mo_form_data->get( c_id-ignore ) ). + LOOP AT lt_ignore INTO lv_ignore. + lv_ignore = condense( lv_ignore ). + IF lv_ignore IS NOT INITIAL. + lo_dot->add_ignore( iv_path = '' + iv_filename = lv_ignore ). + ENDIF. + ENDLOOP. + + " Requirements + DO mv_requirements_count TIMES. + ls_requirements-component = to_upper( mo_form_data->get( |{ c_id-requirements }-{ sy-index }-1| ) ). + ls_requirements-min_release = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-2| ). + ls_requirements-min_patch = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-3| ). + APPEND ls_requirements TO lt_requirements. + ENDDO. + + SORT lt_requirements BY component min_release min_patch. + DELETE lt_requirements WHERE component IS INITIAL. + DELETE ADJACENT DUPLICATES FROM lt_requirements COMPARING ALL FIELDS. + + lo_dot->set_requirements( lt_requirements ). + + mi_repo->set_dot_abapgit( lo_dot ). + mi_repo->refresh( ). + + COMMIT WORK AND WAIT. + + MESSAGE 'Settings successfully saved' TYPE 'S'. + + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD validate_form. + + CONSTANTS lc_allowed(36) TYPE c VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'. + + DATA: + lt_lang_list TYPE zif_abapgit_definitions=>ty_languages, + lv_folder TYPE string, + lv_len TYPE i, + lv_component TYPE zif_abapgit_dot_abapgit=>ty_requirement-component, + lv_min_release TYPE zif_abapgit_dot_abapgit=>ty_requirement-min_release, + lv_min_patch TYPE zif_abapgit_dot_abapgit=>ty_requirement-min_patch, + lv_version_constant TYPE string, + lv_original_system TYPE string, + lx_exception TYPE REF TO zcx_abapgit_exception. + + ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). + + lv_folder = io_form_data->get( c_id-starting_folder ). + lv_len = strlen( lv_folder ) - 1. + IF lv_len > 0 AND lv_folder(1) <> '/'. + ro_validation_log->set( + iv_key = c_id-starting_folder + iv_val = |The folder must begin with /| ). + ELSEIF lv_len > 0 AND lv_folder+lv_len(1) <> '/'. + ro_validation_log->set( + iv_key = c_id-starting_folder + iv_val = |The folder must end with /| ). + ELSEIF lv_folder CA '\'. + ro_validation_log->set( + iv_key = c_id-starting_folder + iv_val = |Use / instead of \\| ). + ENDIF. + + DO mv_requirements_count TIMES. + lv_component = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-1| ). + lv_min_release = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-2| ). + lv_min_patch = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-3| ). + + IF lv_component IS INITIAL AND ( lv_min_release IS NOT INITIAL OR lv_min_patch IS NOT INITIAL ). + ro_validation_log->set( + iv_key = c_id-requirements + iv_val = |If you enter a release or patch, you must also enter a software component| ). + ELSEIF lv_component IS NOT INITIAL AND lv_min_release IS INITIAL. + ro_validation_log->set( + iv_key = c_id-requirements + iv_val = |If you enter a software component, you must also enter a minimum release| ). + ENDIF. + ENDDO. + + TRY. + lv_version_constant = io_form_data->get( c_id-version_constant ). + IF lv_version_constant IS NOT INITIAL. + zcl_abapgit_version=>get_version_constant_value( lv_version_constant ). + validate_version_constant( lv_version_constant ). + ENDIF. + CATCH zcx_abapgit_exception INTO lx_exception. + ro_validation_log->set( + iv_key = c_id-version_constant + iv_val = lx_exception->get_text( ) ). + ENDTRY. + + lt_lang_list = zcl_abapgit_lxe_texts=>convert_lang_string_to_table( + iv_langs = io_form_data->get( c_id-i18n_langs ) + iv_skip_main_language = mi_repo->get_dot_abapgit( )->get_main_language( ) ). + IF io_form_data->get( c_id-use_lxe ) = abap_true AND lt_lang_list IS INITIAL. + ro_validation_log->set( + iv_key = c_id-i18n_langs + iv_val = 'LXE approach requires a non-empty list of languages' ). + ENDIF. + + TRY. + zcl_abapgit_i18n_params=>normalize_obj_patterns( + zcl_abapgit_convert=>split_string( mo_form_data->get( c_id-wo_transaltion ) ) ). + CATCH zcx_abapgit_exception INTO lx_exception. + ro_validation_log->set( + iv_key = c_id-wo_transaltion + iv_val = lx_exception->get_text( ) ). + ENDTRY. + + lv_original_system = io_form_data->get( c_id-original_system ). + IF lv_original_system CN lc_allowed. + ro_validation_log->set( + iv_key = c_id-original_system + iv_val = 'System name must be alphanumerical' ). + ENDIF. + + ENDMETHOD. + METHOD validate_version_constant. + + DATA: lv_version_class TYPE seoclsname, + lv_version_component TYPE string, + lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. + + SPLIT iv_version_constant AT '=>' INTO lv_version_class lv_version_component. + + lt_local = mi_repo->get_files_local( ). + + READ TABLE lt_local TRANSPORTING NO FIELDS WITH KEY + item-obj_type = 'CLAS' item-obj_name = lv_version_class. + IF sy-subrc <> 0. + READ TABLE lt_local TRANSPORTING NO FIELDS WITH KEY + item-obj_type = 'INTF' item-obj_name = lv_version_class. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Object { lv_version_class } is not included in this repository| ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-go_back. + rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( + io_form_data = mo_form_data + io_compare_with = read_settings( ) ). + + WHEN c_event-save. + " Validate all form entries + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + save_settings( ). + ENDIF. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( `
    ` ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + iv_show_commit = abap_false + iv_interactive_branch = abap_true ) ). + + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + + ri_html->add( `
    ` ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_sett_remo IMPLEMENTATION. + METHOD check_protection. + + IF mi_repo->is_offline( ) = abap_true. + zcx_abapgit_exception=>raise( 'Unexpected switch for offline repo' ). + ENDIF. + IF mi_repo->get_local_settings( )-write_protected = abap_true. + zcx_abapgit_exception=>raise( 'Cannot switch. Repository is write-protected in local settings' ). + ENDIF. + + ENDMETHOD. + METHOD choose_branch. + + DATA lv_url TYPE zif_abapgit_persistence=>ty_repo-url. + DATA lv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name. + DATA ls_branch TYPE zif_abapgit_git_definitions=>ty_git_branch. + DATA lv_popup_cancelled TYPE abap_bool. + + IF iv_is_return = abap_false. + + IF mo_form_data->get( c_id-offline ) = abap_true. + RETURN. + ENDIF. + + lv_url = mo_form_data->get( c_id-url ). + lv_branch_name = mo_form_data->get( c_id-branch ). + + mo_popup_picklist = zcl_abapgit_popup_branch_list=>create( + iv_show_new_option = abap_false + iv_url = lv_url + iv_default_branch = lv_branch_name + )->create_picklist( + )->set_id( c_event-choose_branch + )->set_in_page( ). + + ELSE. + + lv_popup_cancelled = mo_popup_picklist->was_cancelled( ). + IF lv_popup_cancelled = abap_false. + mo_popup_picklist->get_result_item( CHANGING cs_selected = ls_branch ). + IF ls_branch IS NOT INITIAL. + mo_form_data->set( + iv_key = c_id-branch + iv_val = ls_branch-display_name ). + ENDIF. + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD choose_commit. + + DATA: + lv_url TYPE string, + lv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name, + li_popups TYPE REF TO zif_abapgit_popups. + + IF mo_form_data->get( c_id-offline ) = abap_true. + RETURN. + ENDIF. + + lv_url = mo_form_data->get( c_id-url ). + lv_branch_name = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && mo_form_data->get( c_id-branch ). + + li_popups = zcl_abapgit_ui_factory=>get_popups( ). + + rv_commit = li_popups->commit_list_popup( + iv_repo_url = lv_url + iv_branch_name = lv_branch_name )-sha1. + + ENDMETHOD. + METHOD choose_pr. + + DATA ls_pull TYPE zif_abapgit_pr_enum_provider=>ty_pull_request. + DATA lv_url TYPE ty_remote_settings-url. + DATA lv_popup_cancelled TYPE abap_bool. + + IF iv_is_return = abap_false. + + IF mo_form_data->get( c_id-offline ) = abap_true. + zcx_abapgit_exception=>raise( 'Not possible for offline repositories' ). + ENDIF. + + lv_url = mo_form_data->get( c_id-url ). + mo_popup_picklist = zcl_abapgit_popup_pull_request=>create( lv_url + )->create_picklist( + )->set_id( c_event-choose_pull_request + )->set_in_page( abap_true ). + + ELSE. + + lv_popup_cancelled = mo_popup_picklist->was_cancelled( ). + IF lv_popup_cancelled = abap_false. + mo_popup_picklist->get_result_item( CHANGING cs_selected = ls_pull ). + IF ls_pull IS NOT INITIAL. + mo_form_data->set( + iv_key = c_id-pull_request + iv_val = ls_pull-head_url && '@' && ls_pull-head_branch ). + ENDIF. + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD choose_tag. + + DATA ls_tag TYPE zif_abapgit_git_definitions=>ty_git_branch. + DATA lv_url TYPE ty_remote_settings-url. + DATA lv_popup_cancelled TYPE abap_bool. + + IF iv_is_return = abap_false. + + IF mo_form_data->get( c_id-offline ) = abap_true. + RETURN. + ELSEIF mi_repo->is_offline( ) = abap_true. + MESSAGE 'Please save conversion to online repository before choosing a tag' TYPE 'S'. + RETURN. + ENDIF. + + lv_url = mo_form_data->get( c_id-url ). + mo_popup_picklist = zcl_abapgit_popup_tag_list=>create( lv_url + )->create_picklist( + )->set_id( c_event-choose_tag + )->set_in_page( ). + + ELSE. + + lv_popup_cancelled = mo_popup_picklist->was_cancelled( ). + IF lv_popup_cancelled = abap_false. + mo_popup_picklist->get_result_item( CHANGING cs_selected = ls_tag ). + IF ls_tag IS NOT INITIAL. + mo_form_data->set( + iv_key = c_id-tag + iv_val = ls_tag-display_name ). + ENDIF. + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD choose_url. + + " todo, get url history from DB and show selection popup #3639 + rv_url = ''. + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + mi_repo = ii_repo. + ms_settings_snapshot = get_remote_settings_from_repo( mi_repo ). + mo_form = get_form_schema( ). + mo_form_data = initialize_form_data( ). + CREATE OBJECT mo_validation_log. + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_remo. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Remote Settings' + io_page_menu = zcl_abapgit_gui_menus=>repo_settings( + iv_key = ii_repo->get_key( ) + iv_act = zif_abapgit_definitions=>c_action-repo_remote_settings ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + DATA: + lv_button TYPE string, + lv_icon TYPE string, + lv_offline TYPE abap_bool, + lv_head_type TYPE zif_abapgit_git_definitions=>ty_head_type. + + IF io_existing_form_data IS BOUND AND io_existing_form_data->is_empty( ) = abap_false. + lv_offline = io_existing_form_data->get( c_id-offline ). + IF lv_offline = abap_false. + lv_head_type = io_existing_form_data->get( c_id-head_type ). + ENDIF. + ELSE. + lv_offline = ms_settings_snapshot-offline. + lv_head_type = ms_settings_snapshot-head_type. + ENDIF. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'repo-remote-settings-form' + iv_help_page = 'https://docs.abapgit.org/settings-remote.html' ). + + IF lv_offline = abap_true. + lv_button = 'Switch to Online'. + lv_icon = 'plug/darkgrey'. + ELSE. + lv_button = 'Switch to Offline'. + lv_icon = 'cloud-upload-alt/darkgrey'. + ENDIF. + + ro_form->start_group( + iv_name = c_id-general + iv_label = 'General' + iv_hint = 'Change the general type and origin of the repository' + )->text( + iv_name = c_id-repo_type + iv_label = |Type of Repository: { zcl_abapgit_html=>icon( lv_icon ) }| + iv_readonly = abap_true + )->hidden( c_id-offline ). + + IF lv_offline = abap_false. + + ro_form->text( + iv_name = c_id-url + iv_condense = abap_true + iv_label = 'Git Repository URL' + iv_hint = 'URL of original repository' + iv_placeholder = 'https://github.com/...git' ). + + ro_form->start_group( + iv_name = c_id-head_group + iv_label = 'Head' + )->radio( + iv_label = 'Type' + iv_name = c_id-head_type + iv_action = c_event-change_head_type + )->option( + iv_label = 'Branch' + iv_value = zif_abapgit_git_definitions=>c_head_types-branch + )->option( + iv_label = 'Tag' + iv_value = zif_abapgit_git_definitions=>c_head_types-tag + )->option( + iv_label = 'Commit' + iv_value = zif_abapgit_git_definitions=>c_head_types-commit + )->option( + iv_label = 'Pull Request' + iv_value = zif_abapgit_git_definitions=>c_head_types-pull_request ). + + IF lv_head_type = zif_abapgit_git_definitions=>c_head_types-branch OR + lv_head_type = zif_abapgit_git_definitions=>c_head_types-commit. + ro_form->text( + iv_name = c_id-branch + iv_label = 'Branch' + iv_required = abap_true + iv_side_action = c_event-choose_branch ). + ENDIF. + + IF lv_head_type = zif_abapgit_git_definitions=>c_head_types-tag. + ro_form->text( + iv_name = c_id-tag + iv_label = 'Tag' + iv_required = abap_true + iv_side_action = c_event-choose_tag ). + ENDIF. + + IF lv_head_type = zif_abapgit_git_definitions=>c_head_types-commit. + ro_form->text( + iv_name = c_id-commit + iv_label = 'Commit' + iv_required = abap_true + iv_min = 40 + iv_max = 40 + iv_side_action = c_event-choose_commit ). + ENDIF. + + IF lv_head_type = zif_abapgit_git_definitions=>c_head_types-pull_request. + ro_form->text( + iv_name = c_id-pull_request + iv_label = 'Pull Request' + iv_required = abap_true + iv_side_action = c_event-choose_pull_request ). + ENDIF. + + ENDIF. + + ro_form->command( + iv_label = 'Save Settings' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-save + )->command( + iv_label = lv_button + iv_action = c_event-switch + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD get_remote_settings_from_form. + + rs_settings-offline = io_form_data->get( c_id-offline ). + + IF rs_settings-offline = abap_false. + rs_settings-url = io_form_data->get( c_id-url ). + rs_settings-head_type = io_form_data->get( c_id-head_type ). + + CASE rs_settings-head_type. + WHEN zif_abapgit_git_definitions=>c_head_types-branch. + rs_settings-branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && + io_form_data->get( c_id-branch ). + WHEN zif_abapgit_git_definitions=>c_head_types-tag. + rs_settings-tag = zif_abapgit_git_definitions=>c_git_branch-tags_prefix && + io_form_data->get( c_id-tag ). + WHEN zif_abapgit_git_definitions=>c_head_types-commit. + rs_settings-branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && + io_form_data->get( c_id-branch ). + rs_settings-commit = io_form_data->get( c_id-commit ). + WHEN zif_abapgit_git_definitions=>c_head_types-pull_request. + rs_settings-pull_request = io_form_data->get( c_id-pull_request ). + ENDCASE. + ENDIF. + + ENDMETHOD. + METHOD get_remote_settings_from_repo. + + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + + IF ii_repo->is_offline( ) = abap_false. + li_repo_online ?= ii_repo. + rs_settings = li_repo_online->get_remote_settings( ). + ELSE. + rs_settings-offline = abap_true. + ENDIF. + + ENDMETHOD. + METHOD handle_picklist_state. + + IF mo_popup_picklist IS BOUND AND + ( mo_popup_picklist->is_fulfilled( ) = abap_true OR mo_popup_picklist->is_in_page( ) = abap_false ). + " Picklist is either fulfilled OR + " it was on its own page and user went back from it via F3/ESC and the picklist had no "graceful back" handler + CASE mo_popup_picklist->id( ). + WHEN c_event-choose_pull_request. + choose_pr( abap_true ). + WHEN c_event-choose_branch. + choose_branch( abap_true ). + WHEN c_event-choose_tag. + choose_tag( abap_true ). + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Unexpected picklist id { mo_popup_picklist->id( ) }| ). + ENDCASE. + + CLEAR mo_popup_picklist. + ENDIF. + + ENDMETHOD. + METHOD initialize_form_data. + + DATA: + lv_type TYPE string, + lv_head TYPE string. + + CREATE OBJECT ro_form_data. + + IF ms_settings_snapshot-offline = abap_true. + lv_type = c_repo_type-offline. + ELSE. + lv_type = c_repo_type-online. + ENDIF. + + ro_form_data->set( + iv_key = c_id-offline + iv_val = ms_settings_snapshot-offline ). + ro_form_data->set( + iv_key = c_id-repo_type + iv_val = lv_type ). + + IF ms_settings_snapshot-offline = abap_false. + ro_form_data->set( + iv_key = c_id-url + iv_val = ms_settings_snapshot-url ). + + ro_form_data->set( + iv_key = c_id-head_type + iv_val = ms_settings_snapshot-head_type ). + + " When pull request is selected the previously selected branch/tag is also loaded to be able to switch back to it + lv_head = zcl_abapgit_git_branch_utils=>get_display_name( ms_settings_snapshot-branch ). + ro_form_data->set( + iv_key = c_id-branch + iv_val = lv_head ). + + lv_head = zcl_abapgit_git_branch_utils=>get_display_name( ms_settings_snapshot-tag ). + ro_form_data->set( + iv_key = c_id-tag + iv_val = lv_head ). + + ro_form_data->set( + iv_key = c_id-commit + iv_val = ms_settings_snapshot-commit ). + + ro_form_data->set( + iv_key = c_id-pull_request + iv_val = ms_settings_snapshot-pull_request ). + ENDIF. + + ENDMETHOD. + METHOD prepare_for_compare. + + ro_form_data = zcl_abapgit_string_map=>create( )->merge( io_form_data ). + + CASE ro_form_data->get( c_id-head_type ). + WHEN zif_abapgit_git_definitions=>c_head_types-branch. + ro_form_data->set( + iv_key = c_id-pull_request + iv_val = '' ). + ro_form_data->set( + iv_key = c_id-commit + iv_val = '' ). + ro_form_data->set( + iv_key = c_id-tag + iv_val = '' ). + WHEN zif_abapgit_git_definitions=>c_head_types-tag. + ro_form_data->set( + iv_key = c_id-pull_request + iv_val = '' ). + ro_form_data->set( + iv_key = c_id-commit + iv_val = '' ). + ro_form_data->set( + iv_key = c_id-branch + iv_val = '' ). + WHEN zif_abapgit_git_definitions=>c_head_types-commit. + ro_form_data->set( + iv_key = c_id-pull_request + iv_val = '' ). + WHEN zif_abapgit_git_definitions=>c_head_types-pull_request. + ro_form_data->set( + iv_key = c_id-commit + iv_val = '' ). + ENDCASE. + + ENDMETHOD. + METHOD render_content. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + iv_show_commit = abap_false + iv_interactive_branch = abap_false ) ). + + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + + ENDMETHOD. + METHOD save_settings. + + DATA: + li_repo_online TYPE REF TO zif_abapgit_repo_online, + ls_settings_new TYPE ty_remote_settings. + + ls_settings_new = get_remote_settings_from_form( mo_form_data ). + + " Switch online / offline + IF ls_settings_new-offline <> ms_settings_snapshot-offline. + " Remember key, switch, retrieve new instance (todo, refactor #2244) + mi_repo->switch_repo_type( ls_settings_new-offline ). + mi_repo = zcl_abapgit_repo_srv=>get_instance( )->get( mi_repo->get_key( ) ). + ENDIF. + + IF mi_repo->is_offline( ) = abap_false. + " Online: Save url + li_repo_online ?= mi_repo. + li_repo_online->set_url( ls_settings_new-url ). + ENDIF. + + CASE ls_settings_new-head_type. + WHEN zif_abapgit_git_definitions=>c_head_types-branch. + switch_to_pull_req( iv_revert = abap_true ). + switch_to_commit( iv_revert = abap_true ). + switch_to_branch_tag( ls_settings_new-branch ). + WHEN zif_abapgit_git_definitions=>c_head_types-tag. + switch_to_pull_req( iv_revert = abap_true ). + switch_to_commit( iv_revert = abap_true ). + switch_to_branch_tag( ls_settings_new-tag ). + WHEN zif_abapgit_git_definitions=>c_head_types-commit. + switch_to_pull_req( iv_revert = abap_true ). + switch_to_commit( iv_commit = ls_settings_new-commit ). + WHEN zif_abapgit_git_definitions=>c_head_types-pull_request. + switch_to_commit( iv_revert = abap_true ). + switch_to_pull_req( iv_pull = ls_settings_new-pull_request ). + ENDCASE. + + IF mi_repo->is_offline( ) = abap_false AND + ls_settings_new-head_type <> zif_abapgit_git_definitions=>c_head_types-pull_request. + " Switching from PR to something else will reset the URL in repo->switch_origin( space ) + " -> set URL again + li_repo_online->set_url( ls_settings_new-url ). + ENDIF. + + COMMIT WORK AND WAIT. + + MESSAGE 'Settings successfully saved' TYPE 'S'. + + mv_refresh_on_back = abap_true. + ms_settings_snapshot = get_remote_settings_from_repo( mi_repo ). + + ENDMETHOD. + METHOD switch_online_offline. + + DATA: lv_offline_new TYPE abap_bool, + lv_url TYPE ty_remote_settings-url, + lv_branch TYPE ty_remote_settings-branch. + + lv_offline_new = boolc( mo_form_data->get( c_id-offline ) = abap_false ). + mo_form_data->set( + iv_key = c_id-offline + iv_val = lv_offline_new ). + + IF lv_offline_new = abap_true. + lv_url = mo_form_data->get( c_id-url ). + mv_offline_switch_saved_url = lv_url. + mo_form_data->set( + iv_key = c_id-url + iv_val = '' ). + mo_form_data->set( + iv_key = c_id-repo_type + iv_val = c_repo_type-offline ). + ELSE. + mo_form_data->set( + iv_key = c_id-repo_type + iv_val = c_repo_type-online ). + IF mv_offline_switch_saved_url IS NOT INITIAL. + mo_form_data->set( + iv_key = c_id-url + iv_val = mv_offline_switch_saved_url ). + ENDIF. + + lv_url = mo_form_data->get( c_id-url ). + IF mo_form_data->get( c_id-head_type ) IS INITIAL. + TRY. + mo_form_data->set( + iv_key = c_id-head_type + iv_val = zif_abapgit_git_definitions=>c_head_types-branch ). + + IF lv_url CP 'http*'. + lv_branch = zcl_abapgit_git_factory=>get_git_transport( )->branches( lv_url )->get_head_symref( ). + mo_form_data->set( + iv_key = c_id-branch + iv_val = lv_branch ). + ENDIF. + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD switch_to_branch_tag. + + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + + check_protection( ). + li_repo_online ?= mi_repo. + li_repo_online->select_branch( iv_name ). + + ENDMETHOD. + METHOD switch_to_commit. + + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + + check_protection( ). + + li_repo_online ?= mi_repo. + + IF iv_revert = abap_true. + li_repo_online->select_commit( '' ). + ELSE. + li_repo_online->select_commit( iv_commit ). + ENDIF. + + ENDMETHOD. + METHOD switch_to_pull_req. + + DATA: + li_repo_online TYPE REF TO zif_abapgit_repo_online, + lv_url TYPE ty_remote_settings-url, + lv_branch TYPE ty_remote_settings-branch. + + check_protection( ). + + li_repo_online ?= mi_repo. + + " Switching twice does not work so reset to original repo first + li_repo_online->switch_origin( '' ). + + IF iv_revert = abap_false. + SPLIT iv_pull AT '@' INTO lv_url lv_branch. + li_repo_online->switch_origin( + iv_url = lv_url + iv_branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && lv_branch ). + ENDIF. + + ENDMETHOD. + METHOD validate_form. + + DATA: + lx_error TYPE REF TO zcx_abapgit_exception, + lo_branch_list TYPE REF TO zif_abapgit_git_branch_list, + lo_url TYPE REF TO zcl_abapgit_git_url, + lv_offline TYPE abap_bool, + lv_head_type TYPE zif_abapgit_git_definitions=>ty_head_type, + lv_branch TYPE ty_remote_settings-branch, + lv_url TYPE ty_remote_settings-url, + lv_branch_check_error_id TYPE string, + lv_pull_request TYPE ty_remote_settings-pull_request, + lv_commit TYPE ty_remote_settings-commit. + + ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). + lv_offline = io_form_data->get( c_id-offline ). + lv_url = io_form_data->get( c_id-url ). + + IF lv_offline = abap_false AND lv_url NP 'http*'. + ro_validation_log->set( + iv_key = c_id-url + iv_val = 'Enter the URL of the repository and save' ). + ELSEIF lv_offline = abap_false. + TRY. + zcl_abapgit_url=>name( + iv_url = lv_url + iv_validate = abap_true ). + + " Provider-specific URL check + CREATE OBJECT lo_url. + lo_url->validate_url( lv_url ). + CATCH zcx_abapgit_exception INTO lx_error. + ro_validation_log->set( + iv_key = c_id-url + iv_val = lx_error->get_text( ) ). + ENDTRY. + + IF iv_connection_check = abap_true. + zcl_abapgit_http=>check_connection( lv_url ). + ENDIF. + ENDIF. + + IF lv_offline = abap_false. + lv_head_type = io_form_data->get( c_id-head_type ). + + CASE lv_head_type. + WHEN zif_abapgit_git_definitions=>c_head_types-branch. + lv_branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && io_form_data->get( c_id-branch ). + CONDENSE lv_branch. + lv_branch_check_error_id = c_id-branch. + WHEN zif_abapgit_git_definitions=>c_head_types-tag. + lv_branch = zif_abapgit_git_definitions=>c_git_branch-tags_prefix && io_form_data->get( c_id-tag ). + CONDENSE lv_branch. + lv_branch_check_error_id = c_id-tag. + WHEN zif_abapgit_git_definitions=>c_head_types-pull_request. + lv_pull_request = io_form_data->get( c_id-pull_request ). + SPLIT lv_pull_request AT '@' INTO lv_url lv_branch. + IF lv_branch IS NOT INITIAL. + lv_branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && lv_branch. + ENDIF. + lv_branch_check_error_id = c_id-pull_request. + WHEN zif_abapgit_git_definitions=>c_head_types-commit. + lv_commit = io_form_data->get( c_id-commit ). + + " Cannot check for commit existence currently (needs API that doesn't rely on finding the first commit + " in the branch), check format instead + IF lv_commit CN '0123456789abcdef' AND ro_validation_log->get( c_id-commit ) IS INITIAL. + ro_validation_log->set( + iv_key = c_id-commit + iv_val = 'Commit needs to be hexadecimal and in lowercase' ). + ENDIF. + WHEN OTHERS. + ro_validation_log->set( + iv_key = c_id-head_type + iv_val = 'Unknown head type' ). + ENDCASE. + + IF lv_branch IS NOT INITIAL. + " Problems with getting branches in general are raised to the page + lo_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( lv_url ). + + TRY. + " Issues with finding a particular branch are shown next to corresponding field + lo_branch_list->find_by_name( lv_branch ). + CATCH zcx_abapgit_exception INTO lx_error. + ro_validation_log->set( + iv_key = lv_branch_check_error_id + iv_val = lx_error->get_text( ) ). + ENDTRY. + ENDIF. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA: + lv_url TYPE ty_remote_settings-url, + lv_commit TYPE ty_remote_settings-commit. + + mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-go_back. + IF mv_refresh_on_back = abap_true. + " Note this doesn't trigger if the tab is switched first + mi_repo->refresh( ). + ENDIF. + + rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( + io_form_data = prepare_for_compare( mo_form_data ) + io_compare_with = initialize_form_data( ) ). + + WHEN c_event-choose_url. + lv_url = choose_url( ). + + IF lv_url IS INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ELSE. + mo_form_data->set( + iv_key = c_id-url + iv_val = lv_url ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + + WHEN c_event-change_head_type. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + mo_validation_log->clear( ). + + WHEN c_event-choose_branch. + choose_branch( ). " Uniformly handle state below + + WHEN c_event-choose_tag. + choose_tag( ). " Uniformly handle state below + + WHEN c_event-choose_pull_request. + choose_pr( ). " Uniformly handle state below + + WHEN c_event-choose_commit. + lv_commit = choose_commit( ). + + IF lv_commit IS INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ELSE. + mo_form_data->set( + iv_key = c_id-commit + iv_val = lv_commit ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + + WHEN c_event-switch. + switch_online_offline( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_event-save. + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + save_settings( ). + ENDIF. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDCASE. + + IF mo_popup_picklist IS BOUND. " Uniform popup state handling + " This should happen only for a new popup because + " on the first re-render main component event handling is blocked + " and not called again until the popup destruction + IF mo_popup_picklist->is_in_page( ) = abap_true. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + rs_handled-page = zcl_abapgit_gui_page_hoc=>create( + ii_child_component = mo_popup_picklist + iv_show_as_modal = abap_true ). + ENDIF. + ENDIF. + + " If staying on form, initialize it with current settings + IF rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render AND mo_popup_picklist IS NOT BOUND. + " Switching tabs must change the form layout + mo_form = get_form_schema( mo_form_data ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions, + lv_head_type TYPE zif_abapgit_git_definitions=>ty_head_type, + lv_offline TYPE abap_bool. + + IF mo_form_data IS BOUND AND mo_form_data->is_empty( ) = abap_false. + lv_offline = mo_form_data->get( c_id-offline ). + IF lv_offline = abap_false. + lv_head_type = mo_form_data->get( c_id-head_type ). + ENDIF. + ELSE. + lv_offline = ms_settings_snapshot-offline. + IF lv_offline = abap_false. + lv_head_type = ms_settings_snapshot-head_type. + ENDIF. + ENDIF. + + ls_hotkey_action-ui_component = 'Remote'. + + ls_hotkey_action-description = 'Choose URL'. + ls_hotkey_action-action = c_event-choose_url. + ls_hotkey_action-hotkey = 'u'. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + IF lv_head_type = zif_abapgit_git_definitions=>c_head_types-branch OR + lv_head_type = zif_abapgit_git_definitions=>c_head_types-commit. + ls_hotkey_action-description = 'Choose Branch'. + ls_hotkey_action-action = c_event-choose_branch. + ls_hotkey_action-hotkey = 'b'. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + ENDIF. + + IF lv_head_type = zif_abapgit_git_definitions=>c_head_types-tag. + ls_hotkey_action-description = 'Choose Tag'. + ls_hotkey_action-action = c_event-choose_tag. + ls_hotkey_action-hotkey = 't'. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + ENDIF. + + IF lv_head_type = zif_abapgit_git_definitions=>c_head_types-commit. + ls_hotkey_action-description = 'Choose Commit'. + ls_hotkey_action-action = c_event-choose_commit. + ls_hotkey_action-hotkey = 'c'. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + ENDIF. + + IF lv_head_type = zif_abapgit_git_definitions=>c_head_types-pull_request. + ls_hotkey_action-description = 'Choose Pull Request'. + ls_hotkey_action-action = c_event-choose_pull_request. + ls_hotkey_action-hotkey = 'p'. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + ENDIF. + + IF lv_offline = abap_true. + ls_hotkey_action-description = 'Switch to Online'. + ls_hotkey_action-action = c_event-switch. + ls_hotkey_action-hotkey = 'o'. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + ELSE. + ls_hotkey_action-description = 'Switch to Offline'. + ls_hotkey_action-action = c_event-switch. + ls_hotkey_action-hotkey = 'o'. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + handle_picklist_state( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->wrap( + iv_tag = 'div' + iv_class = 'repo' " It's OK because it's repo settings ... for now + ii_content = render_content( ) ). + + IF mo_popup_picklist IS NOT BOUND OR mo_popup_picklist->is_in_page( ) = abap_false. + register_handlers( ). + ELSEIF mo_popup_picklist->is_in_page( ) = abap_true. + " Block usual page events if the popup is an in-page popup + ri_html->add( zcl_abapgit_gui_in_page_modal=>create( mo_popup_picklist ) ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_sett_pers IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + mo_form = get_form_schema( ). + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_pers. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Personal Settings' + io_page_menu = zcl_abapgit_gui_menus=>settings( zif_abapgit_definitions=>c_action-go_settings_personal ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'personal-setting-form' + iv_help_page = 'https://docs.abapgit.org/guide-settings-personal.html' ). + + ro_form->start_group( + iv_name = c_id-startup + iv_label = 'Startup' + )->checkbox( + iv_name = c_id-show_default_repo + iv_label = 'Show Last Opened Repository' + iv_hint = 'Recommended to check, if you are using ADT' + )->start_group( + iv_name = c_id-ui + iv_label = 'User Interface' + )->radio( + iv_name = c_id-ui_theme + iv_default_value = zcl_abapgit_settings=>c_ui_theme-default + iv_label = 'Theme' + )->option( + iv_label = 'Default' + iv_value = zcl_abapgit_settings=>c_ui_theme-default + )->option( + iv_label = 'Dark' + iv_value = zcl_abapgit_settings=>c_ui_theme-dark + )->option( + iv_label = 'Belize' + iv_value = zcl_abapgit_settings=>c_ui_theme-belize + )->option( + iv_label = 'Synced with SAP GUI' + iv_value = zcl_abapgit_settings=>c_ui_theme-synced_with_gui + )->radio( + iv_name = c_id-icon_scaling + iv_default_value = '' + iv_label = 'Icon Scaling (HDPI)' + iv_hint = 'Adjust size of icons for High DPI displays' + )->option( + iv_label = 'No scaling' + iv_value = '' + )->option( + iv_label = 'Small' + iv_value = zcl_abapgit_settings=>c_icon_scaling-small + )->option( + iv_label = 'Large' + iv_value = zcl_abapgit_settings=>c_icon_scaling-large + )->number( + iv_name = c_id-max_lines + iv_label = 'List Size' + iv_hint = 'Maximum number of objects listed (0 = All)' + iv_min = 0 + iv_max = 10000 + )->textarea( + iv_name = c_id-label_colors + iv_rows = 3 + iv_label = `Repo label colors ` && render_repo_labels_help_hint( ) + )->start_group( + iv_name = c_id-interaction + iv_label = 'Interaction' + )->checkbox( + iv_name = c_id-activate_wo_popup + iv_label = 'Activate Objects Without Popup' + iv_hint = 'Activates objects automatically without showing popup' + )->checkbox( + iv_name = c_id-adt_jump_enabled + iv_label = 'Enable Jump to ABAP Development Tools (If Available)' + iv_hint = 'Recommended to check, if you are using ADT' + )->checkbox( + iv_name = c_id-link_hints_enabled + iv_label = 'Enable Vimium-like Link Hints' + iv_hint = 'When you hit the key, abapGit will identify clickable things and put a label beside it' + )->text( + iv_name = c_id-link_hint_key + iv_label = 'Key to Activate Link Hints' + iv_min = 0 + iv_max = 1 + )->start_group( + iv_name = c_id-resources + iv_label = 'System Resources' + )->checkbox( + iv_name = c_id-parallel_proc_disabled + iv_label = 'Disable Parallel Processing' + iv_hint = 'If disabled, abapGit will use only a single thread to serialize objects' + )->start_group( + iv_name = c_id-git_default_values + iv_label = 'Git Default Values' + )->text( + iv_name = c_id-default_git_uname + iv_label = 'Default User' + )->text( + iv_name = c_id-default_git_email + iv_label = 'Default Email' + )->command( + iv_label = 'Save Settings' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-save + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + " Not available via this form: + " - User-specific hotkey settings have been discontinued + " - hide_sapgui_hint is set via ZCL_ABAPGIT_SERVICES_ABAPGIT-CHECK_SAPGUI + + ENDMETHOD. + METHOD read_settings. + + " Get settings from DB + mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + ms_settings = mo_settings->get_user_settings( ). + CREATE OBJECT ro_form_data. + + " Startup + ro_form_data->set( + iv_key = c_id-show_default_repo + iv_val = boolc( ms_settings-show_default_repo = abap_true ) ) ##TYPE. + + " UI + ro_form_data->set( + iv_key = c_id-ui_theme + iv_val = ms_settings-ui_theme ). + ro_form_data->set( + iv_key = c_id-icon_scaling + iv_val = |{ ms_settings-icon_scaling }| ). + ro_form_data->set( + iv_key = c_id-max_lines + iv_val = |{ ms_settings-max_lines }| ). + ro_form_data->set( + iv_key = c_id-label_colors + iv_val = ms_settings-label_colors ). + + " Interaction + ro_form_data->set( + iv_key = c_id-activate_wo_popup + iv_val = boolc( ms_settings-activate_wo_popup = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-adt_jump_enabled + iv_val = boolc( ms_settings-adt_jump_enabled = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-link_hints_enabled + iv_val = boolc( ms_settings-link_hints_enabled = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-link_hint_key + iv_val = |{ ms_settings-link_hint_key }| ). + + " Resources + ro_form_data->set( + iv_key = c_id-parallel_proc_disabled + iv_val = boolc( ms_settings-parallel_proc_disabled = abap_true ) ) ##TYPE. + + " Git Default Values + ro_form_data->set( + iv_key = c_id-default_git_uname + iv_val = |{ ms_settings-default_git_uname }| ). + ro_form_data->set( + iv_key = c_id-default_git_email + iv_val = |{ ms_settings-default_git_email }| ). + + ENDMETHOD. + METHOD render_repo_labels_help_hint. + + DATA lt_fragments TYPE string_table. + DATA lt_labels TYPE string_table. + DATA lv_l TYPE string. + DATA lo_colors TYPE REF TO zcl_abapgit_string_map. + + APPEND `

    ` TO lt_fragments. + APPEND `Comma-separated list of label:color pairs.` TO lt_fragments. + APPEND ` color part can be either a pre-defined style (see below), or` TO lt_fragments. + APPEND ` #fg/bg/border styles, where fg, ` TO lt_fragments. + APPEND ` bg, and border are RGB color codes (3 or 6 long).` TO lt_fragments. + APPEND ` You can also specify just fg, bg, or` TO lt_fragments. + APPEND ` border (defaults will be used for missing parts).` TO lt_fragments. + APPEND ` E.g. utils:brown, work:#ff0000/880000, client X:#ddd, client Y:#/333` TO lt_fragments. + APPEND `
    Available styles:` TO lt_fragments. + APPEND `

    ` TO lt_fragments. + + APPEND `white` TO lt_labels. + APPEND `white-b` TO lt_labels. + APPEND `white-r` TO lt_labels. + APPEND `grey` TO lt_labels. + APPEND `dark-w` TO lt_labels. + APPEND `dark-y` TO lt_labels. + APPEND `dark-r` TO lt_labels. + APPEND `dark-b` TO lt_labels. + APPEND `lightblue` TO lt_labels. + APPEND `darkblue` TO lt_labels. + APPEND `lightgreen` TO lt_labels. + APPEND `darkgreen` TO lt_labels. + APPEND `lightred` TO lt_labels. + APPEND `darkred` TO lt_labels. + APPEND `yellow` TO lt_labels. + APPEND `darkyellow` TO lt_labels. + APPEND `orange` TO lt_labels. + APPEND `brown` TO lt_labels. + APPEND `pink` TO lt_labels. + APPEND `teal` TO lt_labels. + APPEND `darkviolet` TO lt_labels. + + lo_colors = zcl_abapgit_string_map=>create( ). + LOOP AT lt_labels INTO lv_l. + TRY. + lo_colors->set( + iv_key = lv_l + iv_val = lv_l ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + ENDLOOP. + + APPEND zcl_abapgit_gui_chunk_lib=>render_label_list( + it_labels = lt_labels + io_label_colors = lo_colors ) TO lt_fragments. + + APPEND + `

    see also rl-* styles in common.css

    ` + TO lt_fragments. + + rv_html = zcl_abapgit_gui_chunk_lib=>render_help_hint( concat_lines_of( table = lt_fragments ) ). + + ENDMETHOD. + METHOD save_settings. + + DATA li_persistence TYPE REF TO zif_abapgit_persist_settings. + + " Startup + ms_settings-show_default_repo = mo_form_data->get( c_id-show_default_repo ). + + " UI + ms_settings-ui_theme = mo_form_data->get( c_id-ui_theme ). + ms_settings-icon_scaling = mo_form_data->get( c_id-icon_scaling ). + ms_settings-max_lines = mo_form_data->get( c_id-max_lines ). + ms_settings-label_colors = zcl_abapgit_repo_labels=>normalize_colors( mo_form_data->get( c_id-label_colors ) ). + + " Interaction + ms_settings-activate_wo_popup = mo_form_data->get( c_id-activate_wo_popup ). + ms_settings-adt_jump_enabled = mo_form_data->get( c_id-adt_jump_enabled ). + ms_settings-link_hints_enabled = mo_form_data->get( c_id-link_hints_enabled ). + ms_settings-link_hint_key = mo_form_data->get( c_id-link_hint_key ). + + " Resources + ms_settings-parallel_proc_disabled = mo_form_data->get( c_id-parallel_proc_disabled ). + + " Git Default Values + ms_settings-default_git_uname = mo_form_data->get( c_id-default_git_uname ). + ms_settings-default_git_email = mo_form_data->get( c_id-default_git_email ). + + " Store in DB + mo_settings->set_user_settings( ms_settings ). + + li_persistence = zcl_abapgit_persist_factory=>get_settings( ). + li_persistence->modify( mo_settings ). + + COMMIT WORK AND WAIT. + + MESSAGE 'Settings successfully saved' TYPE 'S'. + + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD validate_form. + + DATA lx_error TYPE REF TO zcx_abapgit_exception. + + ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). + + TRY. + zcl_abapgit_repo_labels=>validate_colors( io_form_data->get( c_id-label_colors ) ). + CATCH zcx_abapgit_exception INTO lx_error. + ro_validation_log->set( + iv_key = c_id-label_colors + iv_val = lx_error->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-go_back. + rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( + io_form_data = mo_form_data + io_compare_with = read_settings( ) ). + + WHEN c_event-save. + " Validate form entries before saving + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + save_settings( ). + ENDIF. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '
    ' ). + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_PAGE_SETT_LOCL IMPLEMENTATION. + METHOD choose_check_variant. + + DATA ls_variant TYPE zif_abapgit_code_inspector=>ty_variant. + DATA lv_popup_cancelled TYPE abap_bool. + + IF iv_is_return = abap_false. + + mo_popup_picklist = zcl_abapgit_popup_code_insp=>create( + )->create_picklist( + )->set_id( c_event-choose_check_variant + )->set_in_page( abap_false ). + + ELSE. + + lv_popup_cancelled = mo_popup_picklist->was_cancelled( ). + IF lv_popup_cancelled = abap_false. + mo_popup_picklist->get_result_item( CHANGING cs_selected = ls_variant ). + IF ls_variant IS NOT INITIAL. + mo_form_data->set( + iv_key = c_id-code_inspector_check_variant + iv_val = ls_variant-name ). + ENDIF. + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD choose_customizing_request. + + DATA: + ls_transport_type TYPE zif_abapgit_definitions=>ty_transport_type, + lv_customizing_request TYPE trkorr. + + ls_transport_type-request = zif_abapgit_cts_api=>c_transport_type-cust_request. + ls_transport_type-task = zif_abapgit_cts_api=>c_transport_type-cust_task. + + lv_customizing_request = zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( ls_transport_type ). + + IF lv_customizing_request IS NOT INITIAL. + mo_form_data->set( + iv_key = c_id-customizing_request + iv_val = lv_customizing_request ). + ENDIF. + + ENDMETHOD. + METHOD choose_labels. + + DATA: + lv_old_labels TYPE string, + lv_new_labels TYPE string. + + lv_old_labels = mo_form_data->get( c_id-labels ). + + lv_new_labels = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_labels( lv_old_labels ). + + mo_form_data->set( + iv_key = c_id-labels + iv_val = lv_new_labels ). + + ENDMETHOD. + METHOD choose_transport_request. + + DATA: lv_transport_request TYPE trkorr. + + lv_transport_request = zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( ). + + IF lv_transport_request IS NOT INITIAL. + mo_form_data->set( + iv_key = c_id-transport_request + iv_val = lv_transport_request ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + mi_repo = ii_repo. + mo_form = get_form_schema( ). + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_locl. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Local Settings & Checks' + io_page_menu = zcl_abapgit_gui_menus=>repo_settings( + iv_key = ii_repo->get_key( ) + iv_act = zif_abapgit_definitions=>c_action-repo_local_settings ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + DATA: li_package TYPE REF TO zif_abapgit_sap_package. + + li_package = zcl_abapgit_factory=>get_sap_package( mi_repo->get_package( ) ). + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'repo-local-settings-form' + iv_help_page = 'https://docs.abapgit.org/settings-local.html' ). + + ro_form->start_group( + iv_name = c_id-local + iv_label = 'Local Settings' + iv_hint = 'Settings valid for this system only' + )->text( + iv_name = c_id-display_name + iv_label = 'Display Name' + iv_hint = 'Name to show instead of original repo name (optional)' ). + + IF li_package->are_changes_recorded_in_tr_req( ) = abap_true. + ro_form->text( + iv_name = c_id-transport_request + iv_side_action = c_event-choose_transport_request + iv_label = |Transport Request| + iv_hint = 'Transport request; All changes are recorded therein and no transport popup appears|' ). + ENDIF. + + IF is_customizing_included( ) = abap_true. + ro_form->text( + iv_name = c_id-customizing_request + iv_side_action = c_event-choose_customizing_request + iv_label = |Customizing Request| + iv_hint = 'Customizing request; All changes are recorded therein and no customizing popup appears|' ). + ENDIF. + + ro_form->text( + iv_name = c_id-labels + iv_side_action = c_event-choose_labels + iv_label = |Labels (comma-separated, allowed chars: "{ zcl_abapgit_repo_labels=>c_allowed_chars }")| + iv_hint = 'Comma-separated labels for grouping and repo organization (optional)' + )->checkbox( + iv_name = c_id-write_protected + iv_label = 'Write Protected' + iv_hint = 'Lock repository against changes from remote (pull)' + )->checkbox( + iv_name = c_id-ignore_subpackages + iv_label = 'Ignore Subpackages' + iv_hint = 'Synchronize root package only' + )->checkbox( + iv_name = c_id-only_local_objects + iv_label = 'Only Local Objects' + iv_hint = 'Ignore objects imported from other systems; serialize only objects created in this system' + )->checkbox( + iv_name = c_id-main_language_only + iv_label = 'Only Serialize Main Language' + iv_hint = 'Ignore translations; serialize only main language of repository' + )->checkbox( + iv_name = c_id-suppress_lxe_po_comments + iv_label = 'Suppress comments in LXE PO files' + iv_hint = 'Generate "clean" PO files for translation, don''t add metadata comments' ). + + ro_form->checkbox( + iv_name = c_id-flow + iv_readonly = boolc( li_package->are_changes_recorded_in_tr_req( ) = abap_false ) + iv_label = 'BETA: Enable abapGit flow for this repository (requires transported packages)' ). + + ro_form->textarea( + iv_name = c_id-exclude_remote_paths + iv_label = 'Exclude Paths' + iv_hint = 'List of files patterns (CP operator) to exclude from' && + ' syncronization (e.g. unwanted parts of the package, examples...)' ). + + ro_form->start_group( + iv_name = c_id-checks + iv_label = 'Local Checks' + iv_hint = 'Code Inspector check performed to run from menu and before commit' + )->text( + iv_name = c_id-code_inspector_check_variant + iv_side_action = c_event-choose_check_variant + iv_label = 'Code Inspector Check Variant' + iv_hint = 'Global check variant for Code Inspector or ABAP Test Cockpit' + )->checkbox( + iv_name = c_id-block_commit + iv_label = 'Block Commit If Code Inspection Has Errors' + iv_hint = 'Prevent staging if errors of priority 1 or 2 were found during check' + )->command( + iv_label = 'Save Settings' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-save + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD handle_picklist_state. + + IF mo_popup_picklist IS BOUND AND + ( mo_popup_picklist->is_fulfilled( ) = abap_true OR mo_popup_picklist->is_in_page( ) = abap_false ). + " Picklist is either fulfilled OR + " it was on its own page and user went back from it via F3/ESC and the picklist had no "graceful back" handler + CASE mo_popup_picklist->id( ). + WHEN c_event-choose_check_variant. + choose_check_variant( abap_true ). + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Unexpected picklist id { mo_popup_picklist->id( ) }| ). + ENDCASE. + + CLEAR mo_popup_picklist. + ENDIF. + + ENDMETHOD. + METHOD is_customizing_included. + + DATA lt_files TYPE zif_abapgit_definitions=>ty_files_item_tt. + + lt_files = mi_repo->get_files_local( ). + + READ TABLE lt_files TRANSPORTING NO FIELDS + WITH KEY item-obj_type = zif_abapgit_data_config=>c_data_type-tabu. "todo + IF sy-subrc = 0. + rv_result = abap_true. + ENDIF. + + ENDMETHOD. + METHOD read_settings. + + DATA li_package TYPE REF TO zif_abapgit_sap_package. + DATA lv_excl_rem TYPE string. + + li_package = zcl_abapgit_factory=>get_sap_package( mi_repo->get_package( ) ). + + " Get settings from DB + ms_settings = mi_repo->get_local_settings( ). + CREATE OBJECT ro_form_data. + + " Local Settings + ro_form_data->set( + iv_key = c_id-display_name + iv_val = ms_settings-display_name ). + + IF li_package->are_changes_recorded_in_tr_req( ) = abap_true. + ro_form_data->set( + iv_key = c_id-transport_request + iv_val = ms_settings-transport_request ). + ENDIF. + + IF is_customizing_included( ) = abap_true. + ro_form_data->set( + iv_key = c_id-customizing_request + iv_val = ms_settings-customizing_request ). + ENDIF. + + ro_form_data->set( + iv_key = c_id-labels + iv_val = ms_settings-labels ). + ro_form_data->set( + iv_key = c_id-ignore_subpackages + iv_val = boolc( ms_settings-ignore_subpackages = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-main_language_only + iv_val = boolc( ms_settings-main_language_only = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-suppress_lxe_po_comments + iv_val = boolc( ms_settings-suppress_lxe_po_comments = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-flow + iv_val = boolc( ms_settings-flow = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-write_protected + iv_val = boolc( ms_settings-write_protected = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-only_local_objects + iv_val = boolc( ms_settings-only_local_objects = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-code_inspector_check_variant + iv_val = |{ ms_settings-code_inspector_check_variant }| ). + ro_form_data->set( + iv_key = c_id-block_commit + iv_val = boolc( ms_settings-block_commit = abap_true ) ) ##TYPE. + + lv_excl_rem = concat_lines_of( + table = ms_settings-exclude_remote_paths + sep = cl_abap_char_utilities=>newline ). + ro_form_data->set( + iv_key = c_id-exclude_remote_paths + iv_val = lv_excl_rem ). + + ENDMETHOD. + METHOD save_settings. + + ms_settings-display_name = mo_form_data->get( c_id-display_name ). + ms_settings-transport_request = mo_form_data->get( c_id-transport_request ). + ms_settings-customizing_request = mo_form_data->get( c_id-customizing_request ). + ms_settings-labels = zcl_abapgit_repo_labels=>normalize( mo_form_data->get( c_id-labels ) ). + ms_settings-ignore_subpackages = mo_form_data->get( c_id-ignore_subpackages ). + ms_settings-main_language_only = mo_form_data->get( c_id-main_language_only ). + ms_settings-suppress_lxe_po_comments = mo_form_data->get( c_id-suppress_lxe_po_comments ). + ms_settings-flow = mo_form_data->get( c_id-flow ). + ms_settings-write_protected = mo_form_data->get( c_id-write_protected ). + ms_settings-only_local_objects = mo_form_data->get( c_id-only_local_objects ). + ms_settings-code_inspector_check_variant = mo_form_data->get( c_id-code_inspector_check_variant ). + ms_settings-block_commit = mo_form_data->get( c_id-block_commit ). + ms_settings-exclude_remote_paths = + zcl_abapgit_convert=>split_string( mo_form_data->get( c_id-exclude_remote_paths ) ). + + DELETE ms_settings-exclude_remote_paths WHERE table_line IS INITIAL. + + mi_repo->set_local_settings( ms_settings ). + + COMMIT WORK AND WAIT. + + MESSAGE 'Settings successfully saved' TYPE 'S'. + + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD validate_form. + + DATA: + lx_error TYPE REF TO zcx_abapgit_exception, + lv_transport_request TYPE trkorr, + lv_customizing_request TYPE trkorr, + lv_check_variant TYPE sci_chkv. + + ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). + + lv_transport_request = io_form_data->get( c_id-transport_request ). + IF lv_transport_request IS NOT INITIAL. + TRY. + zcl_abapgit_factory=>get_cts_api( )->validate_transport_request( lv_transport_request ). + CATCH zcx_abapgit_exception INTO lx_error. + ro_validation_log->set( + iv_key = c_id-transport_request + iv_val = lx_error->get_text( ) ). + ENDTRY. + ENDIF. + + lv_customizing_request = io_form_data->get( c_id-customizing_request ). + IF lv_customizing_request IS NOT INITIAL. + TRY. + zcl_abapgit_factory=>get_cts_api( )->validate_transport_request( lv_customizing_request ). + CATCH zcx_abapgit_exception INTO lx_error. + ro_validation_log->set( + iv_key = c_id-customizing_request + iv_val = lx_error->get_text( ) ). + ENDTRY. + ENDIF. + + lv_check_variant = to_upper( io_form_data->get( c_id-code_inspector_check_variant ) ). + IF lv_check_variant IS NOT INITIAL. + TRY. + zcl_abapgit_code_inspector=>get_code_inspector( mi_repo->get_package( ) + )->validate_check_variant( lv_check_variant ). + CATCH zcx_abapgit_exception INTO lx_error. + ro_validation_log->set( + iv_key = c_id-code_inspector_check_variant + iv_val = lx_error->get_text( ) ). + ENDTRY. + ENDIF. + + IF io_form_data->get( c_id-block_commit ) = abap_true AND lv_check_variant IS INITIAL. + ro_validation_log->set( + iv_key = c_id-block_commit + iv_val = |If block commit is active, a check variant has to be maintained| ). + ENDIF. + + TRY. + zcl_abapgit_repo_labels=>validate( io_form_data->get( c_id-labels ) ). + CATCH zcx_abapgit_exception INTO lx_error. + ro_validation_log->set( + iv_key = c_id-labels + iv_val = lx_error->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-go_back. + rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( + io_form_data = mo_form_data + io_compare_with = read_settings( ) ). + + WHEN c_event-choose_transport_request. + + choose_transport_request( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_event-choose_customizing_request. + + choose_customizing_request( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_event-choose_labels. + + choose_labels( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_event-choose_check_variant. + + choose_check_variant( ). + + WHEN c_event-save. + " Validate form entries before saving + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + save_settings( ). + ENDIF. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDCASE. + + IF mo_popup_picklist IS BOUND. " Uniform popup state handling + " This should happen only for a new popup because + " on the first re-render main component event handling is blocked + " and not called again until the popup destruction + IF mo_popup_picklist->is_in_page( ) = abap_true. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + rs_handled-page = zcl_abapgit_gui_page_hoc=>create( + ii_child_component = mo_popup_picklist + iv_show_as_modal = abap_true ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + handle_picklist_state( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( `
    ` ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + iv_show_commit = abap_false + iv_interactive_branch = abap_true ) ). + + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + + ri_html->add( `
    ` ). + + IF mo_popup_picklist IS NOT BOUND OR mo_popup_picklist->is_in_page( ) = abap_false. + register_handlers( ). + ELSEIF mo_popup_picklist->is_in_page( ) = abap_true. + " Block usual page events if the popup is an in-page popup + ri_html->add( zcl_abapgit_gui_in_page_modal=>create( mo_popup_picklist ) ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_sett_info IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + CREATE OBJECT mo_form_data. + mi_repo = ii_repo. + mo_form = get_form_schema( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_info. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Repository Stats' + io_page_menu = zcl_abapgit_gui_menus=>repo_settings( + iv_key = ii_repo->get_key( ) + iv_act = zif_abapgit_definitions=>c_action-repo_infos ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD format_size. + + DATA: + lv_size TYPE p LENGTH 16 DECIMALS 2. + + IF iv_size > 1024 * 1024 * 1024. + lv_size = iv_size / 1024 / 1024 / 1024. + rv_size = |{ lv_size } GB|. + ELSEIF iv_size > 1024 * 1024. + lv_size = iv_size / 1024 / 1024. + rv_size = |{ lv_size } MB|. + ELSEIF iv_size > 1024. + lv_size = iv_size / 1024. + rv_size = |{ lv_size } KB|. + ELSE. + rv_size = |{ iv_size } Bytes|. + ENDIF. + + ENDMETHOD. + METHOD format_timestamp. + + DATA lv_short TYPE timestamp. + + IF iv_timestamp IS INITIAL. + rv_timestamp = 'n/a'. + RETURN. + ENDIF. + + cl_abap_tstmp=>move( + EXPORTING tstmp_src = iv_timestamp + IMPORTING tstmp_tgt = lv_short ). + + rv_timestamp = |{ lv_short TIMESTAMP = ISO }|. + + ENDMETHOD. + METHOD format_user. + + DATA lv_title TYPE string. + + IF iv_username IS INITIAL. + rv_user = 'n/a'. + RETURN. + ENDIF. + + IF iv_username <> zcl_abapgit_objects_super=>c_user_unknown. + lv_title = zcl_abapgit_env_factory=>get_user_record( )->get_title( iv_username ). + ENDIF. + + rv_user = iv_username. + IF lv_title IS NOT INITIAL. + rv_user = |{ rv_user } ({ lv_title })|. + ENDIF. + + ENDMETHOD. + METHOD get_form_schema. + + DATA lv_label TYPE string. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'repo-infos-form' + iv_help_page = 'https://docs.abapgit.org/settings-stats.html' ). + + IF mi_repo->is_offline( ) = abap_true. + lv_label = 'ZIP File'. + ELSE. + lv_label = 'Remote'. + ENDIF. + + ro_form->start_group( + iv_name = c_id-info + iv_label = 'Stats' + )->text( + iv_name = c_id-created_by + iv_label = 'Created By' + iv_readonly = abap_true + )->text( + iv_name = c_id-created_at + iv_label = 'Created At' + iv_readonly = abap_true + )->text( + iv_name = c_id-deserialized_by + iv_label = 'Last Deserialized By' + iv_readonly = abap_true + )->text( + iv_name = c_id-deserialized_at + iv_label = 'Last Deserialized At' + iv_readonly = abap_true + )->table( + iv_name = c_id-stats_table + iv_label = 'Statistics' + )->column( + iv_label = 'Measure' + iv_width = '50%' + iv_readonly = abap_true + )->column( + iv_label = 'Local' + iv_width = '25%' + iv_readonly = abap_true + )->column( + iv_label = lv_label + iv_width = '25%' + iv_readonly = abap_true + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD read_settings. + + DATA: + ls_repo TYPE zif_abapgit_persistence=>ty_repo, + ls_stats TYPE ty_stats, + lv_row TYPE i, + lv_int TYPE i, + lv_val TYPE string. + + " Get infos from DB + TRY. + ls_repo = zcl_abapgit_persist_factory=>get_repo( )->read( mi_repo->get_key( ) ). + CATCH zcx_abapgit_not_found. + zcx_abapgit_exception=>raise( |Repo not found, key { mi_repo->get_key( ) }| ). + ENDTRY. + + read_stats( ). + + " Infos + mo_form_data->set( + iv_key = c_id-created_by + iv_val = format_user( ls_repo-created_by ) ). + mo_form_data->set( + iv_key = c_id-created_at + iv_val = format_timestamp( ls_repo-created_at ) ). + mo_form_data->set( + iv_key = c_id-deserialized_by + iv_val = format_user( ls_repo-deserialized_by ) ). + mo_form_data->set( + iv_key = c_id-deserialized_at + iv_val = format_timestamp( ls_repo-deserialized_at ) ). + + LOOP AT mt_stats INTO ls_stats. + lv_row = sy-tabix. + DO 3 TIMES. + CASE sy-index. + WHEN 1. + lv_val = ls_stats-measure. + WHEN 2. + lv_val = ls_stats-local. + WHEN 3. + lv_val = ls_stats-remote. + ENDCASE. + + IF ls_stats-measure CS 'Size' AND sy-index BETWEEN 2 AND 3. + lv_int = lv_val. + lv_val = format_size( lv_int ). + ENDIF. + + mo_form_data->set( + iv_key = |{ c_id-stats_table }-{ lv_row }-{ sy-index }| + iv_val = lv_val ). + ENDDO. + ENDLOOP. + + mo_form_data->set( + iv_key = |{ c_id-stats_table }-{ zif_abapgit_html_form=>c_rows }| + iv_val = |{ lv_row }| ). + + ENDMETHOD. + METHOD read_stats. + + DATA: + lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt, + lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt, + lt_local_items TYPE zif_abapgit_definitions=>ty_items_tt, + lt_remote_items TYPE zif_abapgit_definitions=>ty_items_tt. + + CLEAR mt_stats. + + read_stats_files( + IMPORTING + et_local = lt_local + et_remote = lt_remote ). + + read_stats_state( ). + + read_stats_size_lines_sloc( + EXPORTING + it_local = lt_local + it_remote = lt_remote + IMPORTING + et_local_items = lt_local_items + et_remote_items = lt_remote_items ). + + read_stats_objects( + CHANGING + ct_local_items = lt_local_items + ct_remote_items = lt_remote_items ). + + ENDMETHOD. + METHOD read_stats_file. + + TYPES ty_char255 TYPE c LENGTH 255. + + DATA: + lv_code TYPE string, + lt_code TYPE STANDARD TABLE OF ty_char255 WITH DEFAULT KEY. + + FIELD-SYMBOLS: + LIKE LINE OF lt_code. + + rs_info-size = xstrlen( is_file-data ). + + IF is_file-filename CP '*.abap'. + TRY. + lv_code = zcl_abapgit_convert=>xstring_to_string_utf8( is_file-data ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + SPLIT lv_code AT cl_abap_char_utilities=>newline INTO TABLE lt_code. + + rs_info-line = lines( lt_code ). + + LOOP AT lt_code ASSIGNING WHERE table_line IS NOT INITIAL AND table_line(1) <> '*'. + SHIFT LEFT DELETING LEADING space. + IF (1) <> '"'. + rs_info-sloc = rs_info-sloc + 1. + ENDIF. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD read_stats_files. + + DATA ls_stats TYPE ty_stats. + DATA lt_remote_wo_ignored TYPE zif_abapgit_git_definitions=>ty_files_tt. + + et_local = mi_repo->get_files_local( ). + + ls_stats-measure = 'Number of Files'. + ls_stats-local = lines( et_local ). + + IF mi_repo->has_remote_source( ) = abap_true. + et_remote = mi_repo->get_files_remote( ). + ls_stats-remote = lines( et_remote ). + lt_remote_wo_ignored = mi_repo->get_files_remote( iv_ignore_files = abap_true ). + ENDIF. + + APPEND ls_stats TO mt_stats. + + IF et_remote IS NOT INITIAL. + CLEAR ls_stats. + ls_stats-measure = 'Number of Ignored Files'. + ls_stats-remote = lines( et_remote ) - lines( lt_remote_wo_ignored ). + APPEND ls_stats TO mt_stats. + ENDIF. + + ENDMETHOD. + METHOD read_stats_objects. + + DATA: + ls_stats TYPE ty_stats, + ls_item TYPE zif_abapgit_definitions=>ty_item, + lt_supported_types TYPE zif_abapgit_objects=>ty_types_tt. + + ls_stats-measure = 'Number of Objects'. + + DELETE ct_local_items WHERE obj_type IS INITIAL OR obj_name IS INITIAL. + ls_stats-local = lines( ct_local_items ). + + DELETE ct_remote_items WHERE obj_type IS INITIAL OR obj_name IS INITIAL. + ls_stats-remote = lines( ct_remote_items ). + + APPEND ls_stats TO mt_stats. + + CLEAR ls_stats. + ls_stats-measure = 'Number of Unsupported Objects'. + ls_stats-local = lines( mi_repo->get_unsupported_objects_local( ) ). + + lt_supported_types = zcl_abapgit_objects=>supported_list( ). + + LOOP AT ct_remote_items INTO ls_item. + READ TABLE lt_supported_types WITH KEY table_line = ls_item-obj_type TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + ls_stats-remote = ls_stats-remote + 1. + ENDIF. + ENDLOOP. + + APPEND ls_stats TO mt_stats. + + ENDMETHOD. + METHOD read_stats_size_lines_sloc. + + DATA: + ls_stats TYPE ty_stats, + lv_ignored TYPE abap_bool, + ls_info_file TYPE ty_infos, + ls_info_local TYPE ty_infos, + ls_info_remote TYPE ty_infos, + ls_item TYPE zif_abapgit_definitions=>ty_item. + + FIELD-SYMBOLS: + LIKE LINE OF it_local, + LIKE LINE OF it_remote. + + LOOP AT it_local ASSIGNING . + ls_info_file = read_stats_file( -file ). + + ls_info_local-size = ls_info_local-size + ls_info_file-size. + ls_info_local-line = ls_info_local-line + ls_info_file-line. + ls_info_local-sloc = ls_info_local-sloc + ls_info_file-sloc. + + COLLECT -item INTO et_local_items. + ENDLOOP. + + IF mi_repo->has_remote_source( ) = abap_true. + LOOP AT it_remote ASSIGNING WHERE filename IS NOT INITIAL. + lv_ignored = mi_repo->get_dot_abapgit( )->is_ignored( + iv_filename = -filename + iv_path = -path ). + + IF lv_ignored = abap_false. + ls_info_file = read_stats_file( ). + + ls_info_remote-size = ls_info_remote-size + ls_info_file-size. + ls_info_remote-line = ls_info_remote-line + ls_info_file-line. + ls_info_remote-sloc = ls_info_remote-sloc + ls_info_file-sloc. + + TRY. + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = -filename + iv_path = -path + iv_devclass = mi_repo->get_package( ) + io_dot = mi_repo->get_dot_abapgit( ) + IMPORTING + es_item = ls_item ). + COLLECT ls_item INTO et_remote_items. + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDLOOP. + ENDIF. + + ls_stats-measure = 'Size of Files'. + ls_stats-local = ls_info_local-size. + ls_stats-remote = ls_info_remote-size. + APPEND ls_stats TO mt_stats. + ls_stats-measure = 'Lines in ABAP Files'. + ls_stats-local = ls_info_local-line. + ls_stats-remote = ls_info_remote-line. + APPEND ls_stats TO mt_stats. + ls_stats-measure = 'Lines of Code in ABAP Files'. + ls_stats-local = ls_info_local-sloc. + ls_stats-remote = ls_info_remote-sloc. + APPEND ls_stats TO mt_stats. + + ENDMETHOD. + METHOD read_stats_state. + + DATA: + lt_results TYPE zif_abapgit_definitions=>ty_results_tt, + lv_state TYPE c LENGTH 1, + ls_stats TYPE ty_stats. + + FIELD-SYMBOLS: + LIKE LINE OF lt_results. + + lt_results = zcl_abapgit_repo_status=>calculate( mi_repo ). + + DO 3 TIMES. + CLEAR ls_stats. + + CASE sy-index. + WHEN 1. + ls_stats-measure = 'Number of Modified Files'. + lv_state = zif_abapgit_definitions=>c_state-modified. + WHEN 2. + ls_stats-measure = 'Number of Added Files'. + lv_state = zif_abapgit_definitions=>c_state-added. + WHEN 3. + ls_stats-measure = 'Number of Deleted Files'. + lv_state = zif_abapgit_definitions=>c_state-deleted. + ENDCASE. + + LOOP AT lt_results ASSIGNING . + IF -lstate = lv_state. + ls_stats-local = ls_stats-local + 1. + ENDIF. + IF -rstate = lv_state AND mi_repo->has_remote_source( ) = abap_true. + ls_stats-remote = ls_stats-remote + 1. + ENDIF. + ENDLOOP. + + APPEND ls_stats TO mt_stats. + ENDDO. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + IF ii_event->mv_action = zif_abapgit_definitions=>c_action-go_back. + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + read_settings( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( `
    ` ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + iv_show_commit = abap_false + iv_interactive_branch = abap_true ) ). + + ri_html->add( mo_form->render( mo_form_data ) ). + + ri_html->add( `
    ` ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_sett_glob IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + mo_form = get_form_schema( ). + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_glob. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Global Settings' + io_page_menu = zcl_abapgit_gui_menus=>settings( zif_abapgit_definitions=>c_action-go_settings ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + CONSTANTS lc_commitmsg_comment_min_len TYPE i VALUE 1. + CONSTANTS lc_commitmsg_comment_max_len TYPE i VALUE 255. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'global-setting-form' + iv_help_page = 'https://docs.abapgit.org/guide-settings-global.html' ). + + ro_form->start_group( + iv_name = c_id-proxy_settings + iv_label = 'Proxy Settings' + )->text( + iv_name = c_id-proxy_url + iv_label = 'Proxy Host' + iv_hint = 'Hostname or IP of proxy required to access the Internet (do not enter http://)' + iv_placeholder = 'Hostname or IP without http://' + )->number( + iv_name = c_id-proxy_port + iv_label = 'Proxy Port' + iv_hint = 'Port of proxy required to access the Internet' + iv_min = 0 + iv_max = 65535 + )->checkbox( + iv_name = c_id-proxy_auth + iv_label = 'Proxy Authentication' + iv_hint = 'Check, if proxy requires you to login' + )->textarea( + iv_name = c_id-proxy_bypass + iv_label = 'Proxy Bypass' + iv_hint = 'List of hosts/domains for which to bypass using proxy' + )->start_group( + iv_name = c_id-commit_settings + iv_label = 'Commit Message Settings' + )->number( + iv_name = c_id-commitmsg_comment_length + iv_required = abap_true + iv_label = 'Maximum Length of Comment' + iv_hint = |At most { lc_commitmsg_comment_max_len } characters| + iv_min = lc_commitmsg_comment_min_len + iv_max = lc_commitmsg_comment_max_len + )->text( + iv_name = c_id-commitmsg_comment_deflt + iv_label = 'Default Text For Comment' + iv_hint = 'You can use $OBJECT or $FILE to include the number of objects/files' + )->number( + iv_name = c_id-commitmsg_body_size + iv_required = abap_true + iv_label = 'Maximum Line Size of Body' + iv_hint = |Wrap body message at { zcl_abapgit_settings=>c_commitmsg_body_size_dft } characters per line| + iv_min = zcl_abapgit_settings=>c_commitmsg_body_size_dft + )->checkbox( + iv_name = c_id-commitmsg_hide_author + iv_label = 'Hide Author Fields' ). + + ro_form->start_group( + iv_name = c_id-devint_settings + iv_label = 'Development Internal Settings' + )->checkbox( + iv_name = c_id-run_critical_tests + iv_label = 'Enable Critical Unit Tests' + iv_readonly = zcl_abapgit_factory=>get_environment( )->is_merged( ) + )->text( + iv_name = c_id-experimental_features + iv_label = 'Experimental Features (might require restarting abapGit)' + iv_readonly = zcl_abapgit_factory=>get_environment( )->is_merged( ) + iv_hint = 'Set to "X" to enable all features or add feature values as a comma-separated list' ). + + ro_form->command( + iv_label = 'Save Settings' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-save + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD read_proxy_bypass. + + DATA: + lt_proxy_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url, + ls_proxy_bypass LIKE LINE OF lt_proxy_bypass, + lv_val TYPE string. + + lt_proxy_bypass = io_settings->get_proxy_bypass( ). + LOOP AT lt_proxy_bypass INTO ls_proxy_bypass. + lv_val = lv_val && ls_proxy_bypass-low && cl_abap_char_utilities=>newline. + ENDLOOP. + + io_form_data->set( + iv_key = c_id-proxy_bypass + iv_val = lv_val ). + + ENDMETHOD. + METHOD read_settings. + + " Get settings from DB + mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + CREATE OBJECT ro_form_data. + + " Proxy + ro_form_data->set( + iv_key = c_id-proxy_url + iv_val = mo_settings->get_proxy_url( ) ). + ro_form_data->set( + iv_key = c_id-proxy_port + iv_val = mo_settings->get_proxy_port( ) ). + ro_form_data->set( + iv_key = c_id-proxy_auth + iv_val = boolc( mo_settings->get_proxy_authentication( ) = abap_true ) ) ##TYPE. + + read_proxy_bypass( + io_settings = mo_settings + io_form_data = ro_form_data ). + + " Commit Message + ro_form_data->set( + iv_key = c_id-commitmsg_comment_length + iv_val = |{ mo_settings->get_commitmsg_comment_length( ) }| ). + ro_form_data->set( + iv_key = c_id-commitmsg_comment_deflt + iv_val = mo_settings->get_commitmsg_comment_default( ) ). + ro_form_data->set( + iv_key = c_id-commitmsg_body_size + iv_val = |{ mo_settings->get_commitmsg_body_size( ) }| ). + ro_form_data->set( + iv_key = c_id-commitmsg_hide_author + iv_val = boolc( mo_settings->get_commitmsg_hide_author( ) = abap_true ) ) ##TYPE. + + " Dev Internal + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. + ro_form_data->set( + iv_key = c_id-run_critical_tests + iv_val = boolc( mo_settings->get_run_critical_tests( ) = abap_true ) ) ##TYPE. + ro_form_data->set( + iv_key = c_id-experimental_features + iv_val = mo_settings->get_experimental_features( ) ). + ENDIF. + + ENDMETHOD. + METHOD save_proxy_bypass. + + DATA: + lt_textarea TYPE TABLE OF string, + lt_proxy_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url, + ls_proxy_bypass LIKE LINE OF lt_proxy_bypass. + + lt_textarea = zcl_abapgit_convert=>split_string( mo_form_data->get( c_id-proxy_bypass ) ). + + ls_proxy_bypass-sign = 'I'. + LOOP AT lt_textarea INTO ls_proxy_bypass-low WHERE table_line IS NOT INITIAL. + IF ls_proxy_bypass-low CA '*+'. + ls_proxy_bypass-option = 'CP'. + ELSE. + ls_proxy_bypass-option = 'EQ'. + ENDIF. + APPEND ls_proxy_bypass TO lt_proxy_bypass. + ENDLOOP. + + mo_settings->set_proxy_bypass( lt_proxy_bypass ). + + ENDMETHOD. + METHOD save_settings. + + DATA: + li_persistence TYPE REF TO zif_abapgit_persist_settings, + lv_value TYPE i. + + " Proxy + mo_settings->set_proxy_url( mo_form_data->get( c_id-proxy_url ) ). + mo_settings->set_proxy_port( mo_form_data->get( c_id-proxy_port ) ). + mo_settings->set_proxy_authentication( boolc( mo_form_data->get( c_id-proxy_auth ) = abap_true ) ). + + save_proxy_bypass( ). + + " Commit Message + lv_value = mo_form_data->get( c_id-commitmsg_comment_length ). + mo_settings->set_commitmsg_comment_length( lv_value ). + mo_settings->set_commitmsg_comment_default( mo_form_data->get( c_id-commitmsg_comment_deflt ) ). + lv_value = mo_form_data->get( c_id-commitmsg_body_size ). + mo_settings->set_commitmsg_body_size( lv_value ). + mo_settings->set_commitmsg_hide_author( boolc( mo_form_data->get( c_id-commitmsg_hide_author ) = abap_true ) ). + + " Dev Internal + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. + mo_settings->set_run_critical_tests( boolc( mo_form_data->get( c_id-run_critical_tests ) = abap_true ) ). + mo_settings->set_experimental_features( mo_form_data->get( c_id-experimental_features ) ). + ENDIF. + + " Store in DB + li_persistence = zcl_abapgit_persist_factory=>get_settings( ). + li_persistence->modify( mo_settings ). + + COMMIT WORK AND WAIT. + + MESSAGE 'Settings successfully saved' TYPE 'S'. + + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD validate_form. + + ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). + + IF io_form_data->get( c_id-proxy_url ) IS NOT INITIAL AND io_form_data->get( c_id-proxy_port ) IS INITIAL OR + io_form_data->get( c_id-proxy_url ) IS INITIAL AND io_form_data->get( c_id-proxy_port ) IS NOT INITIAL. + ro_validation_log->set( + iv_key = c_id-proxy_url + iv_val = |If you specify a proxy, you have to specify host and port| ). + ENDIF. + + IF ( io_form_data->get( c_id-proxy_url ) IS INITIAL OR io_form_data->get( c_id-proxy_port ) IS INITIAL ) AND + io_form_data->get( c_id-proxy_auth ) = abap_true. + ro_validation_log->set( + iv_key = c_id-proxy_auth + iv_val = |To turn on authentication, you have to specify host and port| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-go_back. + rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( + io_form_data = mo_form_data + io_compare_with = read_settings( ) ). + + WHEN c_event-save. + " Validate form entries before saving + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + save_settings( ). + ENDIF. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '
    ' ). + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_sett_bckg IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + CREATE OBJECT mo_form_data. + mi_repo = ii_repo. + mo_form = get_form_schema( ). + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_bckg. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Background Mode' + io_page_menu = zcl_abapgit_gui_menus=>repo_settings( + iv_key = ii_repo->get_key( ) + iv_act = zif_abapgit_definitions=>c_action-repo_background ) + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + DATA: + lt_methods TYPE zcl_abapgit_background=>ty_methods, + ls_method LIKE LINE OF lt_methods, + lv_hint TYPE string. + + lt_methods = zcl_abapgit_background=>list_methods( ). + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'repo-background-form' + iv_help_page = 'https://docs.abapgit.org/settings-background-mode.html' ). + + ro_form->start_group( + iv_name = c_id-mode_selection + iv_label = 'Mode' + )->radio( + iv_name = c_id-method + iv_default_value = '' + iv_label = 'Selection' + iv_hint = 'Define the action that will be executed in background mode' + )->option( + iv_label = 'Do Nothing' + iv_value = '' ). + + LOOP AT lt_methods INTO ls_method. + ro_form->option( + iv_label = ls_method-description + iv_value = ls_method-class ). + ENDLOOP. + + ro_form->table( + iv_name = c_id-settings + iv_hint = 'Settings required for selected background action' + iv_label = 'Additional Settings' + )->column( + iv_label = 'Key' + iv_width = '50%' + iv_readonly = abap_true + )->column( + iv_label = 'Value' + iv_width = '50%' ). + + lv_hint = 'Password will be saved in clear text!'. + + ro_form->start_group( + iv_name = c_id-authentication + iv_label = 'HTTP Authentication (Optional)' + iv_hint = lv_hint + )->text( + iv_name = c_id-username + iv_label = 'Username' + iv_hint = lv_hint + )->text( + iv_name = c_id-password + iv_label = 'Password' + iv_hint = lv_hint + iv_placeholder = lv_hint ). + + ro_form->command( + iv_label = 'Save Settings' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-save + )->command( + iv_label = 'Run Background Logic' + iv_action = zif_abapgit_definitions=>c_action-go_background_run + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD read_persist. + + TRY. + rs_persist = zcl_abapgit_persist_factory=>get_background( )->get_by_key( mi_repo->get_key( ) ). + CATCH zcx_abapgit_not_found. + CLEAR rs_persist. + ENDTRY. + + ENDMETHOD. + METHOD read_settings. + + DATA: + ls_per TYPE zif_abapgit_persist_background=>ty_background, + lv_row TYPE i, + lv_val TYPE string, + lt_settings LIKE ls_per-settings, + ls_settings LIKE LINE OF ls_per-settings. + + ls_per = read_persist( ). + CREATE OBJECT ro_form_data. + + " Mode Selection + ro_form_data->set( + iv_key = c_id-method + iv_val = ls_per-method ). + + " Mode Settings + IF ls_per-method IS NOT INITIAL. + + lt_settings = ls_per-settings. + + " skip invalid values, from old background logic + IF ls_per-method <> 'push' AND ls_per-method <> 'pull' AND ls_per-method <> 'nothing'. + TRY. + CALL METHOD (ls_per-method)=>zif_abapgit_background~get_settings + CHANGING + ct_settings = lt_settings. + CATCH cx_sy_dyn_call_illegal_class. + CLEAR lt_settings. + ENDTRY. + ENDIF. + + LOOP AT lt_settings INTO ls_settings. + lv_row = lv_row + 1. + DO 3 TIMES. + CASE sy-index. + WHEN 1. + lv_val = ls_settings-key. + WHEN 2. + lv_val = ls_settings-value. + ENDCASE. + ro_form_data->set( + iv_key = |{ c_id-settings }-{ lv_row }-{ sy-index }| + iv_val = lv_val ). + ENDDO. + ENDLOOP. + + ENDIF. + + mv_settings_count = lv_row. + + ro_form_data->set( + iv_key = |{ c_id-settings }-{ zif_abapgit_html_form=>c_rows }| + iv_val = |{ mv_settings_count }| ). + + " Authentication + ro_form_data->set( + iv_key = c_id-username + iv_val = ls_per-username ). + ro_form_data->set( + iv_key = c_id-password + iv_val = ls_per-password ). + + ENDMETHOD. + METHOD save_settings. + + DATA: + ls_per TYPE zif_abapgit_persist_background=>ty_background, + lt_settings LIKE ls_per-settings. + + FIELD-SYMBOLS: + LIKE LINE OF ls_per-settings. + + ls_per-key = mi_repo->get_key( ). + + " Mode Selection + ls_per-method = mo_form_data->get( c_id-method ). + + " Mode Settings + IF ls_per-method IS NOT INITIAL. + + lt_settings = ls_per-settings. + + " skip invalid values, from old background logic + IF ls_per-method <> 'push' AND ls_per-method <> 'pull' AND ls_per-method <> 'nothing'. + CALL METHOD (ls_per-method)=>zif_abapgit_background~get_settings + CHANGING + ct_settings = lt_settings. + ENDIF. + + LOOP AT lt_settings ASSIGNING . + -value = mo_form_data->get( |{ c_id-settings }-{ sy-tabix }-2| ). + ENDLOOP. + + ls_per-settings = lt_settings. + + ENDIF. + + " Authentication + ls_per-username = mo_form_data->get( c_id-username ). + ls_per-password = mo_form_data->get( c_id-password ). + + IF ls_per-method IS INITIAL. + zcl_abapgit_persist_factory=>get_background( )->delete( ls_per-key ). + ELSE. + zcl_abapgit_persist_factory=>get_background( )->modify( ls_per ). + ENDIF. + + COMMIT WORK AND WAIT. + + MESSAGE 'Settings successfully saved' TYPE 'S'. + + mo_form_data = read_settings( ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-go_back. + rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( + io_form_data = mo_form_data + io_compare_with = read_settings( ) ). + + WHEN c_event-save. + save_settings( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( `
    ` ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + iv_show_commit = abap_false + iv_interactive_branch = abap_true ) ). + + ri_html->add( mo_form->render( + iv_form_class = 'w800px' + io_values = mo_form_data ) ). + + ri_html->add( `
    ` ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_cr_repo IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + + mv_url = iv_url. + + set_defaults( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_cr_repo. + + CREATE OBJECT lo_component + EXPORTING + iv_url = iv_url. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Create GitHub Repository' + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'create-github-repository' ). + + ro_form->radio( + iv_name = c_id-repo_type + iv_default_value = abap_false + iv_label = 'Type of Repository' + )->option( + iv_label = 'User' + iv_value = abap_false + )->option( + iv_label = 'Organization' + iv_value = abap_true + )->text( + iv_label = 'User or Organization' + iv_name = c_id-user_or_org + iv_required = abap_true + )->text( + iv_label = 'Repository Name' + iv_name = c_id-name + iv_required = abap_true + )->text( + iv_label = 'Description' + iv_name = c_id-description + )->checkbox( + iv_label = 'Private' + iv_name = c_id-private + iv_hint = 'Set visibility to private (organization) or public' + )->command( + iv_label = 'Create GitHub Repository' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-create + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD set_defaults. + + DATA lv_rest TYPE string ##NEEDED. + DATA lv_org TYPE string. + DATA lv_name TYPE string. + + FIND ALL OCCURRENCES OF REGEX 'github\.com\/([^\/]+)\/([^\/]+)' + IN mv_url + SUBMATCHES lv_org lv_name. + IF sy-subrc = 0. + mo_form_data->set( + iv_key = c_id-user_or_org + iv_val = lv_org ). + + mo_form_data->set( + iv_key = c_id-name + iv_val = lv_name ). + ENDIF. + + mo_form_data->set( + iv_key = c_id-private + iv_val = abap_true ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA lv_url TYPE string. + DATA lv_msg TYPE string. + + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_event-create. + mo_validation_log = mo_form_util->validate( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + + " So far, this is only implemented for GitHub + " The following trigges a login which is required for the API call to work + zcl_abapgit_http=>create_by_url( 'https://api.github.com/user/repos' ). + + lv_url = |https://github.com/{ mo_form_data->get( c_id-user_or_org ) }/{ mo_form_data->get( c_id-name ) }|. + + zcl_abapgit_pr_enumerator=>new( lv_url )->create_repository( + iv_description = mo_form_data->get( c_id-description ) + iv_is_org = |{ mo_form_data->get( c_id-repo_type ) }| + iv_private = |{ mo_form_data->get( c_id-private ) }| ). + + lv_msg = |GitHub repository { lv_url } created successfully|. + + MESSAGE lv_msg TYPE 'S'. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + WHEN OTHERS. + " do nothing + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + ri_html = zcl_abapgit_html=>create( ). + + ri_html->add( '
    ' ). + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_addonline IMPLEMENTATION. + METHOD choose_labels. + + DATA: + lv_old_labels TYPE string, + lv_new_labels TYPE string. + + lv_old_labels = mo_form_data->get( c_id-labels ). + + lv_new_labels = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_labels( lv_old_labels ). + + mo_form_data->set( + iv_key = c_id-labels + iv_val = lv_new_labels ). + + ENDMETHOD. + METHOD constructor. + super->constructor( ). + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_addonline. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'New Online Repository' + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'add-repo-online-form' + iv_help_page = 'https://docs.abapgit.org/guide-online-install.html' ). + + ro_form->text( + iv_name = c_id-url + iv_required = abap_true + iv_condense = abap_true + iv_label = 'Git Repository URL' + iv_hint = 'HTTPS address of the repository' + iv_placeholder = 'https://github.com/...git' + )->text( + iv_name = c_id-package + iv_side_action = c_event-choose_package + iv_required = abap_true + iv_upper_case = abap_true + iv_label = 'Package' + iv_hint = 'SAP package for repository (should be a dedicated one)' + iv_placeholder = 'Z... / $...' + iv_max = 30 + )->text( + iv_name = c_id-branch_name + iv_side_action = c_event-choose_branch + iv_label = 'Branch' + iv_hint = 'Switch to a specific branch (default: autodetect)' + iv_placeholder = 'Autodetect default branch' + )->radio( + iv_name = c_id-folder_logic + iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix + iv_label = 'Folder Logic' + iv_hint = 'Define how package folders are named in repository' + )->option( + iv_label = 'Prefix' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix + )->option( + iv_label = 'Full' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-full + )->option( + iv_label = 'Mixed' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-mixed + )->text( + iv_name = c_id-display_name + iv_label = 'Display Name' + iv_hint = 'Name to show instead of original repository name (optional)' + )->text( + iv_name = c_id-labels + iv_side_action = c_event-choose_labels + iv_label = |Labels (comma-separated, allowed chars: "{ zcl_abapgit_repo_labels=>c_allowed_chars }")| + iv_hint = 'Comma-separated labels for grouping and repo organization (optional)' + )->checkbox( + iv_name = c_id-ignore_subpackages + iv_label = 'Ignore Subpackages' + iv_hint = 'Synchronize root package only' + )->checkbox( + iv_name = c_id-main_lang_only + iv_label = 'Serialize Main Language Only' + iv_hint = 'Ignore translations, serialize just main language' ). + + IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. + ro_form->radio( + iv_name = c_id-abap_lang_vers + iv_default_value = '' + iv_label = 'ABAP Language Version' + iv_hint = 'Define the ABAP language version for objects in the repository' + )->option( + iv_label = 'Any' + iv_value = '' + )->option( + iv_label = 'Ignore' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-ignore + )->option( + iv_label = 'Standard' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-standard + )->option( + iv_label = 'For Key Users' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user + )->option( + iv_label = 'For Cloud Development' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development ). + ENDIF. + + ro_form->command( + iv_label = 'Create Online Repo' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-add_online_repo + )->command( + iv_label = 'Create Package' + iv_action = c_event-create_package + )->command( + iv_label = 'Create GitHub Repo' + iv_action = c_event-create_repo + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD validate_form. + + DATA: + lv_url TYPE string, + lo_url TYPE REF TO zcl_abapgit_git_url, + lx_err TYPE REF TO zcx_abapgit_exception. + + ro_validation_log = mo_form_util->validate( io_form_data ). + + lv_url = io_form_data->get( c_id-url ). + IF lv_url IS NOT INITIAL. + TRY. + zcl_abapgit_repo_srv=>get_instance( )->validate_url( lv_url ). + + " Provider-specific URL check + CREATE OBJECT lo_url. + lo_url->validate_url( lv_url ). + CATCH zcx_abapgit_exception INTO lx_err. + ro_validation_log->set( + iv_key = c_id-url + iv_val = lx_err->get_text( ) ). + ENDTRY. + + zcl_abapgit_http=>check_connection( lv_url ). + ENDIF. + + IF io_form_data->get( c_id-package ) IS NOT INITIAL. + TRY. + zcl_abapgit_repo_srv=>get_instance( )->validate_package( + iv_package = |{ io_form_data->get( c_id-package ) }| + iv_ign_subpkg = |{ io_form_data->get( c_id-ignore_subpackages ) }| ). + CATCH zcx_abapgit_exception INTO lx_err. + ro_validation_log->set( + iv_key = c_id-package + iv_val = lx_err->get_text( ) ). + ENDTRY. + ENDIF. + + IF io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-prefix + AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-full + AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-mixed. + ro_validation_log->set( + iv_key = c_id-folder_logic + iv_val = |Invalid folder logic { io_form_data->get( c_id-folder_logic ) }| ). + ENDIF. + + TRY. + zcl_abapgit_repo_labels=>validate( io_form_data->get( c_id-labels ) ). + CATCH zcx_abapgit_exception INTO lx_err. + ro_validation_log->set( + iv_key = c_id-labels + iv_val = lx_err->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA ls_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params. + DATA li_new_repo TYPE REF TO zif_abapgit_repo. + DATA lv_package TYPE devclass. + + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_event-create_package. + lv_package = mo_form_data->get( c_id-package ). + IF zcl_abapgit_factory=>get_sap_package( lv_package )->exists( ) = abap_true. + zcx_abapgit_exception=>raise( |Package { lv_package } already exists| ). + ENDIF. + rs_handled-page = zcl_abapgit_gui_page_cpackage=>create( lv_package ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN c_event-create_repo. + + rs_handled-page = zcl_abapgit_gui_page_cr_repo=>create( mo_form_data->get( c_id-url ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN c_event-choose_package. + + mo_form_data->set( + iv_key = c_id-package + iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ). + IF mo_form_data->get( c_id-package ) IS NOT INITIAL. + mo_validation_log = validate_form( mo_form_data ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDIF. + + WHEN c_event-choose_branch. + + mo_validation_log = validate_form( mo_form_data ). + IF mo_validation_log->has( c_id-url ) = abap_true. + mo_validation_log->set( + iv_key = c_id-branch_name + iv_val = 'Check URL issues' ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. " Display errors + RETURN. + ENDIF. + mo_form_data->set( + iv_key = c_id-branch_name + iv_val = zcl_abapgit_ui_factory=>get_popups( )->branch_list_popup( mo_form_data->get( c_id-url ) )-name ). + + IF mo_form_data->get( c_id-branch_name ) IS INITIAL. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ELSE. + mo_form_data->set( + iv_key = c_id-branch_name + iv_val = replace( " strip technical + val = mo_form_data->get( c_id-branch_name ) + sub = zif_abapgit_git_definitions=>c_git_branch-heads_prefix + with = '' ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + + WHEN c_event-choose_labels. + + choose_labels( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_event-add_online_repo. + + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + mo_form_data->to_abap( CHANGING cs_container = ls_repo_params ). + li_new_repo = zcl_abapgit_services_repo=>new_online( ls_repo_params ). + rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( li_new_repo->get_key( ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. " Display errors + ENDIF. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + ri_html->add( '
    ' ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_addofflin IMPLEMENTATION. + METHOD choose_labels. + + DATA: + lv_old_labels TYPE string, + lv_new_labels TYPE string. + + lv_old_labels = mo_form_data->get( c_id-labels ). + + lv_new_labels = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_labels( lv_old_labels ). + + mo_form_data->set( + iv_key = c_id-labels + iv_val = lv_new_labels ). + + ENDMETHOD. + METHOD constructor. + super->constructor( ). + CREATE OBJECT mo_validation_log. + CREATE OBJECT mo_form_data. + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_addofflin. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'New Offline Repository' + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_form_schema. + + ro_form = zcl_abapgit_html_form=>create( + iv_form_id = 'add-repo-offline-form' + iv_help_page = 'https://docs.abapgit.org/guide-offline-install.html' ). + + ro_form->text( + iv_name = c_id-name + iv_required = abap_true + iv_label = 'Name' + iv_hint = 'Unique name for repository' + )->text( + iv_name = c_id-package + iv_side_action = c_event-choose_package + iv_required = abap_true + iv_upper_case = abap_true + iv_label = 'Package' + iv_hint = 'SAP package for repository (should be a dedicated one)' + iv_placeholder = 'Z... / $...' + iv_max = 30 + )->radio( + iv_name = c_id-folder_logic + iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix + iv_label = 'Folder Logic' + iv_hint = 'Define how package folders are named in repository' + )->option( + iv_label = 'Prefix' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix + )->option( + iv_label = 'Full' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-full + )->option( + iv_label = 'Mixed' + iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-mixed + )->text( + iv_name = c_id-labels + iv_side_action = c_event-choose_labels + iv_label = |Labels (comma-separated, allowed chars: "{ zcl_abapgit_repo_labels=>c_allowed_chars }")| + iv_hint = 'Comma-separated labels for grouping and repo organization (optional)' + )->checkbox( + iv_name = c_id-ignore_subpackages + iv_label = 'Ignore Subpackages' + iv_hint = 'Synchronize root package only' + )->checkbox( + iv_name = c_id-main_lang_only + iv_label = 'Serialize Main Language Only' + iv_hint = 'Ignore translations, serialize just main language' ). + + IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. + ro_form->radio( + iv_name = c_id-abap_lang_vers + iv_default_value = '' + iv_label = 'ABAP Language Version' + iv_hint = 'Define the ABAP language version for objects in the repository' + )->option( + iv_label = 'Any' + iv_value = '' + )->option( + iv_label = 'Ignore' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-ignore + )->option( + iv_label = 'Standard' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-standard + )->option( + iv_label = 'For Key Users' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user + )->option( + iv_label = 'For Cloud Development' + iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development ). + ENDIF. + + ro_form->command( + iv_label = 'Create Offline Repo' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-add_offline_repo + )->command( + iv_label = 'Create Package' + iv_action = c_event-create_package + )->command( + iv_label = 'Back' + iv_action = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD validate_form. + + DATA lx_err TYPE REF TO zcx_abapgit_exception. + + ro_validation_log = mo_form_util->validate( io_form_data ). + + IF io_form_data->get( c_id-package ) IS NOT INITIAL. + TRY. + zcl_abapgit_repo_srv=>get_instance( )->validate_package( + iv_package = |{ io_form_data->get( c_id-package ) }| + iv_ign_subpkg = |{ io_form_data->get( c_id-ignore_subpackages ) }| ). + CATCH zcx_abapgit_exception INTO lx_err. + ro_validation_log->set( + iv_key = c_id-package + iv_val = lx_err->get_text( ) ). + ENDTRY. + ENDIF. + + IF io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-prefix + AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-full + AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-mixed. + ro_validation_log->set( + iv_key = c_id-folder_logic + iv_val = |Invalid folder logic { io_form_data->get( c_id-folder_logic ) }| ). + ENDIF. + + TRY. + zcl_abapgit_repo_labels=>validate( io_form_data->get( c_id-labels ) ). + CATCH zcx_abapgit_exception INTO lx_err. + ro_validation_log->set( + iv_key = c_id-labels + iv_val = lx_err->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA ls_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params. + DATA li_new_offline_repo TYPE REF TO zif_abapgit_repo. + DATA lv_package TYPE devclass. + + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + + CASE ii_event->mv_action. + WHEN c_event-create_package. + lv_package = mo_form_data->get( c_id-package ). + IF zcl_abapgit_factory=>get_sap_package( lv_package )->exists( ) = abap_true. + zcx_abapgit_exception=>raise( |Package { lv_package } already exists| ). + ENDIF. + rs_handled-page = zcl_abapgit_gui_page_cpackage=>create( lv_package ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN c_event-choose_package. + + mo_form_data->set( + iv_key = c_id-package + iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ). + IF mo_form_data->get( c_id-package ) IS NOT INITIAL. + mo_validation_log = validate_form( mo_form_data ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDIF. + + WHEN c_event-choose_labels. + + choose_labels( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN c_event-add_offline_repo. + + mo_validation_log = validate_form( mo_form_data ). + + IF mo_validation_log->is_empty( ) = abap_true. + mo_form_data->to_abap( CHANGING cs_container = ls_repo_params ). + li_new_offline_repo = zcl_abapgit_services_repo=>new_offline( ls_repo_params ). + rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( li_new_offline_repo->get_key( ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. + ELSE. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. " Display errors + ENDIF. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + ri_html->add( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_patch IMPLEMENTATION. + METHOD add_menu_begin. + + io_menu->add( + iv_txt = c_action_texts-refresh_local + iv_typ = zif_abapgit_html=>c_action_type-dummy + iv_act = c_actions-refresh_local + iv_id = c_actions-refresh_local + iv_title = c_action_titles-refresh_local ). + + io_menu->add( + iv_txt = c_action_texts-refresh_all + iv_typ = zif_abapgit_html=>c_action_type-dummy + iv_act = c_actions-refresh_all + iv_id = c_actions-refresh_all + iv_title = c_action_titles-refresh_all ). + + ENDMETHOD. + METHOD add_menu_end. + + io_menu->add( iv_txt = 'Stage' + iv_act = c_patch_actions-stage + iv_id = 'stage' + iv_typ = zif_abapgit_html=>c_action_type-dummy ). + + add_view_sub_menu( io_menu ). + + io_menu->add( iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD add_to_stage. + + DATA: lt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, + lv_something_patched TYPE abap_bool, + ls_status TYPE zif_abapgit_definitions=>ty_result, + lv_patch TYPE xstring, + lo_git_add_patch TYPE REF TO zcl_abapgit_git_add_patch. + + FIELD-SYMBOLS: LIKE LINE OF mt_diff_files. + + LOOP AT mt_diff_files ASSIGNING . + + IF -o_diff IS NOT BOUND. + " When we deal with binary files we don't have a diff object. + " There's nothing to do because they cannot be patched + CONTINUE. + ENDIF. + + lt_diff = -o_diff->get( ). + + READ TABLE lt_diff TRANSPORTING NO FIELDS + WITH KEY patch_flag = abap_true. + CHECK sy-subrc = 0. + + lv_something_patched = abap_true. + + CREATE OBJECT lo_git_add_patch + EXPORTING + it_diff = -o_diff->get( ). + + lv_patch = lo_git_add_patch->get_patch_binary( ). + + IF -lstate = 'D' AND are_all_lines_patched( lt_diff ) = abap_true. + + ls_status-lstate = zif_abapgit_definitions=>c_state-deleted. + mo_stage->rm( + iv_path = -path + is_status = ls_status + iv_filename = -filename ). + + ELSE. + + IF -lstate = 'A' AND are_all_lines_patched( lt_diff ) = abap_true. + ls_status-lstate = zif_abapgit_definitions=>c_state-added. + ELSE. + ls_status-lstate = zif_abapgit_definitions=>c_state-modified. + ENDIF. + + mo_stage->add( + iv_path = -path + iv_filename = -filename + is_status = ls_status + iv_data = lv_patch ). + + ENDIF. + + ENDLOOP. + + IF lv_something_patched = abap_false. + zcx_abapgit_exception=>raise( |Nothing added| ). + ENDIF. + + ENDMETHOD. + METHOD apply_patch_all. + + DATA: lv_filename TYPE string, + lt_patch TYPE string_table, + lv_line_index TYPE string. + + FIELD-SYMBOLS: TYPE LINE OF string_table. + + SPLIT iv_patch AT ',' INTO TABLE lt_patch. + + LOOP AT lt_patch ASSIGNING . + + get_patch_data( + EXPORTING + iv_patch = + IMPORTING + ev_filename = lv_filename + ev_line_index = lv_line_index ). + + apply_patch_for( iv_filename = lv_filename + iv_line_index = lv_line_index + iv_patch_flag = iv_patch_flag ). + + ENDLOOP. + + ENDMETHOD. + METHOD apply_patch_for. + + DATA: lo_diff TYPE REF TO zif_abapgit_diff, + ls_diff_line TYPE zif_abapgit_definitions=>ty_diff, + lv_line TYPE i. + + lo_diff = get_diff_object( iv_filename ). + + ls_diff_line = get_diff_line( io_diff = lo_diff + iv_line_index = iv_line_index ). + + CASE ls_diff_line-result. + WHEN zif_abapgit_definitions=>c_diff-update + OR zif_abapgit_definitions=>c_diff-insert. + + lv_line = ls_diff_line-new_num. + + lo_diff->set_patch_new( iv_line_new = lv_line + iv_patch_flag = iv_patch_flag ). + + WHEN zif_abapgit_definitions=>c_diff-delete. + + lv_line = ls_diff_line-old_num. + + lo_diff->set_patch_old( iv_line_old = lv_line + iv_patch_flag = iv_patch_flag ). + + ENDCASE. + + ENDMETHOD. + METHOD apply_patch_from_form_fields. + + DATA: + lv_add TYPE string, + lv_remove TYPE string. + + lv_add = ii_event->form_data( )->get( c_patch_action-add ). + lv_remove = ii_event->form_data( )->get( c_patch_action-remove ). + + apply_patch_all( iv_patch = lv_add + iv_patch_flag = abap_true ). + + apply_patch_all( iv_patch = lv_remove + iv_patch_flag = abap_false ). + + ENDMETHOD. + METHOD are_all_lines_patched. + + DATA: lv_patch_count TYPE i. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. + + LOOP AT it_diff ASSIGNING + WHERE patch_flag = abap_true. + lv_patch_count = lv_patch_count + 1. + ENDLOOP. + + rv_are_all_lines_patched = boolc( lv_patch_count = lines( it_diff ) ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( + iv_key = iv_key + is_file = is_file + is_object = is_object + it_files = it_files ). + + IF mi_repo->is_offline( ) = abap_true. + zcx_abapgit_exception=>raise( |Patching is only possible for online repositories.| ). + ENDIF. + +* access "me" after the super constructor has been called + mi_extra = me. + + mi_repo_online ?= mi_repo. + + " While patching we always want to be in split mode + CLEAR mv_unified. + CREATE OBJECT mo_stage. + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_patch. + + CREATE OBJECT lo_component + EXPORTING + iv_key = iv_key + is_file = is_file + is_object = is_object + it_files = it_files. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Patch' + iv_page_layout = zcl_abapgit_gui_page=>c_page_layout-full_width + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD get_diff_line. + + DATA: lt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, + lv_line_index TYPE sy-tabix. + lv_line_index = iv_line_index. + lt_diff = io_diff->get( ). + + READ TABLE lt_diff INTO rs_diff + INDEX lv_line_index. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Invalid line index { lv_line_index }| ). + ENDIF. + + ENDMETHOD. + METHOD get_diff_object. + + FIELD-SYMBOLS: LIKE LINE OF mt_diff_files. + + LOOP AT mt_diff_files ASSIGNING . + IF get_normalized_fname_with_path( ) = iv_filename. + ro_diff = -o_diff. + EXIT. + ENDIF. + ENDLOOP. + + IF ro_diff IS NOT BOUND. + zcx_abapgit_exception=>raise( |Invalid filename { iv_filename }| ). + ENDIF. + + ENDMETHOD. + METHOD get_patch_data. + + DATA: lv_section TYPE string. + + CLEAR: ev_filename, ev_line_index. + + FIND FIRST OCCURRENCE OF REGEX `patch_line` && `_(.*)_(\d)+_(\d+)` + IN iv_patch + SUBMATCHES ev_filename lv_section ev_line_index. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Invalid patch| ). + ENDIF. + + ENDMETHOD. + METHOD is_patch_line_possible. + + IF is_diff_line-result = zif_abapgit_definitions=>c_diff-update + OR is_diff_line-result = zif_abapgit_definitions=>c_diff-insert + OR is_diff_line-result = zif_abapgit_definitions=>c_diff-delete. + rv_is_patch_line_possible = abap_true. + ENDIF. + + ENDMETHOD. + METHOD refresh. + + DATA lt_diff_files_old LIKE mt_diff_files. + + lt_diff_files_old = mt_diff_files. + + super->refresh( iv_action ). + + restore_patch_flags( lt_diff_files_old ). + + ENDMETHOD. + METHOD render_patch. + + CONSTANTS: + BEGIN OF lc_css_class, + patch TYPE string VALUE `patch`, + END OF lc_css_class. + + DATA: + lv_id TYPE string, + lv_patched TYPE abap_bool, + lv_is_patch_possible TYPE abap_bool. + + " In case an object is falsely detected as changed, filename is empty and there's no diff object + IF iv_filename IS NOT INITIAL. + lv_patched = get_diff_object( iv_filename )->is_line_patched( iv_index ). + ENDIF. + + lv_is_patch_possible = is_patch_line_possible( is_diff_line ). + + IF lv_is_patch_possible = abap_true. + + lv_id = |{ iv_filename }_{ mv_section_count }_{ iv_index }|. + + ii_html->add( || ). + ii_html->add_checkbox( + iv_id = |patch_line_{ lv_id }| + iv_checked = lv_patched ). + ii_html->add( || ). + + ELSE. + + ii_html->add( || ). + ii_html->add( || ). + + ENDIF. + + ENDMETHOD. + METHOD render_patch_head. + + ii_html->add( || ). + ii_html->add_checkbox( |patch_file_{ get_normalized_fname_with_path( is_diff ) }| ). + ii_html->add( '' ). + + ENDMETHOD. + METHOD render_scripts. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). + ri_html->add( 'preparePatch();' ). + ri_html->add( 'registerStagePatch();' ). + + ENDMETHOD. + METHOD restore_patch_flags. + + DATA: + lt_diff_old TYPE zif_abapgit_definitions=>ty_diffs_tt. + + FIELD-SYMBOLS: + LIKE LINE OF mt_diff_files, + LIKE LINE OF it_diff_files_old, + TYPE zif_abapgit_definitions=>ty_diff. + + LOOP AT mt_diff_files ASSIGNING . + + READ TABLE it_diff_files_old ASSIGNING + WITH KEY secondary + COMPONENTS path = -path + filename = -filename. + IF sy-subrc <> 0. + CONTINUE. " e.g. new objects + ENDIF. + + IF -o_diff IS NOT BOUND. + CONTINUE. " e.g. binary files + ENDIF. + + lt_diff_old = -o_diff->get( ). + + LOOP AT lt_diff_old ASSIGNING + WHERE patch_flag = abap_true. + + -o_diff->set_patch_by_old_diff( + is_diff_old = + iv_patch_flag = abap_true ). + + ENDLOOP. + + ENDLOOP. + + ENDMETHOD. + METHOD start_staging. + + apply_patch_from_form_fields( ii_event ). + add_to_stage( ). + + ENDMETHOD. + METHOD zif_abapgit_gui_diff_extra~insert_nav. + + " add beacon at beginning of file + rv_insert_nav = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_gui_diff_extra~render_beacon_begin_of_row. + + mv_section_count = mv_section_count + 1. + + ii_html->add( || ). + ii_html->add_checkbox( |patch_section_{ get_normalized_fname_with_path( is_diff ) }_{ mv_section_count }| ). + ii_html->add( '' ). + + ENDMETHOD. + METHOD zif_abapgit_gui_diff_extra~render_diff_head_after_state. + + DATA: lv_act_id TYPE string. + + lv_act_id = |{ c_actions-refresh_local_object }_{ is_diff-obj_type }_{ is_diff-obj_name }|. + + IF is_diff-obj_type IS NOT INITIAL AND is_diff-obj_name IS NOT INITIAL. + " Dummy link is handled in JS (based on ID) + ii_html->add( '' ). + ii_html->add_a( iv_txt = ii_html->icon( iv_name = 'redo-alt-solid' + iv_class = 'pad-sides' + iv_hint = 'Local refresh of this object' ) + iv_id = lv_act_id + iv_act = lv_act_id + iv_typ = zif_abapgit_html=>c_action_type-dummy + iv_class = |url| ). + ii_html->add( '' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_diff_extra~render_line_split_row. + + render_patch( ii_html = ii_html + iv_filename = iv_filename + is_diff_line = is_diff_line + iv_index = iv_index ). + + ENDMETHOD. + METHOD zif_abapgit_gui_diff_extra~render_table_head_non_unified. + + render_patch_head( ii_html = ii_html + is_diff = is_diff ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + CASE ii_event->mv_action. + WHEN c_patch_actions-stage. + + start_staging( ii_event ). + + rs_handled-page = zcl_abapgit_gui_page_commit=>create( + ii_repo_online = mi_repo_online + io_stage = mo_stage ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + WHEN OTHERS. + + IF is_refresh( ii_event->mv_action ) = abap_true. + + apply_patch_from_form_fields( ii_event ). + refresh( ii_event->mv_action ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ELSE. + + rs_handled = super->zif_abapgit_gui_event_handler~on_event( ii_event ). + + ENDIF. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + + ls_hotkey_action-ui_component = 'Patch'. + + ls_hotkey_action-description = |Stage Changes|. + ls_hotkey_action-action = |stagePatch|. + ls_hotkey_action-hotkey = |s|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Refresh Local|. + ls_hotkey_action-action = |refreshLocal|. + ls_hotkey_action-hotkey = |r|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Refresh All|. + ls_hotkey_action-action = |refreshAll|. + ls_hotkey_action-hotkey = |a|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CLEAR mv_section_count. + + IF mv_pushed = abap_true. + refresh_full( ). + calculate_diff( ). + CLEAR mv_pushed. + ENDIF. + + ri_html = super->zif_abapgit_gui_renderable~render( ). + + register_deferred_script( render_scripts( ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_PAGE_DIFF_FILE IMPLEMENTATION. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_diff_file. + + ASSERT is_local IS NOT INITIAL. + ASSERT is_remote IS NOT INITIAL. + + CREATE OBJECT lo_component. + + lo_component->do_diff( + iv_obj_type = iv_obj_type + iv_obj_name = iv_obj_name + is_local = is_local + is_remote = is_remote ). + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Diff File' + iv_page_layout = zcl_abapgit_gui_page=>c_page_layout-full_width + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD do_diff. + + DATA lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt. + DATA lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. + DATA ls_local LIKE LINE OF lt_local. + DATA ls_status TYPE zif_abapgit_definitions=>ty_result. + + ls_status-path = is_remote-path. + ls_status-filename = is_remote-filename. + ls_status-obj_type = iv_obj_type. + ls_status-obj_name = iv_obj_name. + + INSERT is_remote INTO TABLE lt_remote. + + ls_local-file = is_local. + ls_local-item-obj_type = iv_obj_type. + ls_local-item-obj_name = iv_obj_name. + INSERT ls_local INTO TABLE lt_local. + + append_diff( + it_remote = lt_remote + it_local = lt_local + is_status = ls_status ). + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlwVszAmStrZjgYsfmgPrpXDFKn DEFINITION DEFERRED. +* renamed: zcl_abapgit_gui_page_diff_base :: lcl_filter +CLASS kHGwlwVszAmStrZjgYsfmgPrpXDFKn DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_object_filter. + + METHODS constructor + IMPORTING + is_item TYPE zif_abapgit_definitions=>ty_item. + + PRIVATE SECTION. + DATA mt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. +ENDCLASS. + +CLASS kHGwlwVszAmStrZjgYsfmgPrpXDFKn IMPLEMENTATION. + METHOD constructor. + DATA ls_filter TYPE zif_abapgit_definitions=>ty_tadir. + ls_filter-object = is_item-obj_type. + ls_filter-obj_name = is_item-obj_name. + INSERT ls_filter INTO TABLE mt_filter. + ENDMETHOD. + + METHOD zif_abapgit_object_filter~get_filter. + rt_filter = mt_filter. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_diff_base IMPLEMENTATION. + METHOD add_filter_sub_menu. + + DATA: + lo_sub_filter TYPE REF TO zcl_abapgit_html_toolbar, + lv_user TYPE string, + lt_extensions TYPE SORTED TABLE OF string WITH UNIQUE DEFAULT KEY, + lt_obj_types TYPE SORTED TABLE OF string WITH UNIQUE DEFAULT KEY, + lt_users TYPE SORTED TABLE OF string WITH UNIQUE DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF mt_diff_files, + TYPE string. + + " Get unique filter values + LOOP AT mt_diff_files ASSIGNING . + lv_user = -changed_by. + INSERT -type INTO TABLE lt_extensions. + INSERT -obj_type INTO TABLE lt_obj_types. + INSERT lv_user INTO TABLE lt_users. + ENDLOOP. + + IF lines( lt_extensions ) > 1 OR lines( lt_obj_types ) > 1 OR lines( lt_users ) > 1. + CREATE OBJECT lo_sub_filter EXPORTING iv_id = 'diff-filter'. + + IF lines( lt_users ) > 1. + lo_sub_filter->add( iv_txt = 'Only my changes' + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_aux = |{ sy-uname }| + iv_chk = abap_false ). + ENDIF. + + " File extensions + IF lines( lt_extensions ) > 1. + lo_sub_filter->add( iv_txt = 'Extension' + iv_typ = zif_abapgit_html=>c_action_type-separator ). + LOOP AT lt_extensions ASSIGNING . + lo_sub_filter->add( iv_txt = + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_aux = 'extension' + iv_chk = abap_true ). + ENDLOOP. + ENDIF. + + " Object types + IF lines( lt_obj_types ) > 1. + lo_sub_filter->add( iv_txt = 'Object Type' + iv_typ = zif_abapgit_html=>c_action_type-separator ). + LOOP AT lt_obj_types ASSIGNING . + lo_sub_filter->add( iv_txt = + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_aux = 'object-type' + iv_chk = abap_true ). + ENDLOOP. + ENDIF. + + " Changed by + IF lines( lt_users ) > 1. + lo_sub_filter->add( iv_txt = 'Changed By' + iv_typ = zif_abapgit_html=>c_action_type-separator ). + LOOP AT lt_users ASSIGNING . + lo_sub_filter->add( iv_txt = + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_aux = 'changed-by' + iv_chk = abap_true ). + ENDLOOP. + ENDIF. + + io_menu->add( iv_txt = 'Filter' + io_sub = lo_sub_filter ). + ENDIF. + + ENDMETHOD. + METHOD add_jump_sub_menu. + + DATA: lo_sub_jump TYPE REF TO zcl_abapgit_html_toolbar, + lv_jump_target TYPE string. + FIELD-SYMBOLS: LIKE LINE OF mt_diff_files. + + CREATE OBJECT lo_sub_jump EXPORTING iv_id = 'jump'. + + LOOP AT mt_diff_files ASSIGNING . + + lv_jump_target = -path && -filename. + + lo_sub_jump->add( + iv_id = |li_jump_{ sy-tabix }| + iv_txt = lv_jump_target + iv_typ = zif_abapgit_html=>c_action_type-onclick ). + + ENDLOOP. + + io_menu->add( iv_txt = 'Jump' + io_sub = lo_sub_jump ). + + ENDMETHOD. + METHOD add_menu_begin. + + IF mi_repo IS NOT INITIAL. + io_menu->add( + iv_txt = c_action_texts-refresh_local + iv_typ = zif_abapgit_html=>c_action_type-sapevent + iv_act = c_actions-refresh_local + iv_id = c_actions-refresh_local + iv_title = c_action_titles-refresh_local ). + + io_menu->add( + iv_txt = c_action_texts-refresh_all + iv_typ = zif_abapgit_html=>c_action_type-sapevent + iv_act = c_actions-refresh_all + iv_id = c_actions-refresh_all + iv_title = c_action_titles-refresh_all ). + ENDIF. + + ENDMETHOD. + METHOD add_menu_end. + + io_menu->add( iv_txt = 'Split/Unified' + iv_act = c_actions-toggle_unified ). + + add_view_sub_menu( io_menu ). + + io_menu->add( iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD add_view_sub_menu. + + DATA lo_sub_view TYPE REF TO zcl_abapgit_html_toolbar. + DATA lv_txt TYPE string. + + CREATE OBJECT lo_sub_view EXPORTING iv_id = 'diff-view'. + + IF ms_view-hide_diffs = abap_true. + lv_txt = 'Expand All Diffs'. + ELSE. + lv_txt = 'Collapse All Diffs'. + ENDIF. + + lo_sub_view->add( iv_txt = lv_txt + iv_act = c_actions-toggle_hide_diffs ). + + lo_sub_view->add( iv_txt = 'Show Hidden Characters' + iv_act = c_actions-toggle_hidden_chars + iv_chk = ms_view-hidden_chars ). + + lo_sub_view->add( iv_txt = 'Ignore Whitespace' + iv_act = c_actions-toggle_ignore_indent + iv_chk = ms_view-ignore_indent ). + + lo_sub_view->add( iv_txt = 'Ignore Comments' + iv_act = c_actions-toggle_ignore_comments + iv_chk = ms_view-ignore_comments ). + + lo_sub_view->add( iv_txt = 'Ignore Pretty-Print Case' + iv_act = c_actions-toggle_ignore_case + iv_chk = ms_view-ignore_case ). + + io_menu->add( iv_txt = 'View' + io_sub = lo_sub_view ). + + ENDMETHOD. + METHOD append_diff. + + DATA: + lv_offs TYPE i, + ls_r_dummy LIKE LINE OF it_remote ##NEEDED, + ls_l_dummy LIKE LINE OF it_local ##NEEDED. + + FIELD-SYMBOLS: LIKE LINE OF it_remote, + LIKE LINE OF it_local, + LIKE LINE OF mt_diff_files. + READ TABLE it_remote ASSIGNING + WITH KEY file_path + COMPONENTS path = is_status-path + filename = is_status-filename. + IF sy-subrc <> 0. + ASSIGN ls_r_dummy TO . + ENDIF. + + READ TABLE it_local ASSIGNING + WITH KEY file-filename = is_status-filename + file-path = is_status-path. + IF sy-subrc <> 0. + ASSIGN ls_l_dummy TO . + ENDIF. + + IF IS INITIAL AND IS INITIAL. + zcx_abapgit_exception=>raise( |DIFF: file not found { is_status-filename }| ). + ENDIF. + + APPEND INITIAL LINE TO mt_diff_files ASSIGNING . + -path = is_status-path. + -filename = is_status-filename. + -obj_type = is_status-obj_type. + -obj_name = is_status-obj_name. + -lstate = is_status-lstate. + -rstate = is_status-rstate. + + IF -lstate IS NOT INITIAL AND -rstate IS NOT INITIAL. + -fstate = c_fstate-both. + ELSEIF -lstate IS NOT INITIAL. + -fstate = c_fstate-local. + ELSE. "rstate IS NOT INITIAL, lstate = empty. + -fstate = c_fstate-remote. + ENDIF. + + " Changed by + IF -item-obj_type IS NOT INITIAL. + -changed_by = zcl_abapgit_objects=>changed_by( + is_item = -item + iv_filename = is_status-filename ). + ENDIF. + IF -changed_by IS INITIAL. + -changed_by = zcl_abapgit_objects_super=>c_user_unknown. + ENDIF. + + " Extension + IF -file-filename IS NOT INITIAL. + -type = reverse( -file-filename ). + ELSE. + -type = reverse( -filename ). + ENDIF. + + FIND FIRST OCCURRENCE OF '.' IN -type MATCH OFFSET lv_offs. + -type = reverse( substring( val = -type + len = lv_offs ) ). + IF -type <> 'xml' AND -type <> 'abap' AND -type <> 'po'. + -type = 'other'. + ENDIF. + + IF -type = 'other' + AND is_binary( iv_d1 = -data + iv_d2 = -file-data ) = abap_true. + -type = 'binary'. + ENDIF. + + " Diff data + IF -type <> 'binary'. + IF -fstate = c_fstate-remote. " Remote file leading changes + -o_diff = zcl_abapgit_diff_factory=>get( )->create( + iv_new = -data + iv_old = -file-data + iv_ignore_indentation = ms_view-ignore_indent + iv_ignore_comments = ms_view-ignore_comments + iv_ignore_case = ms_view-ignore_case ). + ELSE. " Local leading changes or both were modified + -o_diff = zcl_abapgit_diff_factory=>get( )->create( + iv_new = -file-data + iv_old = -data + iv_ignore_indentation = ms_view-ignore_indent + iv_ignore_comments = ms_view-ignore_comments + iv_ignore_case = ms_view-ignore_case ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD calculate_diff. + + DATA: lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt, + lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt, + lt_status TYPE zif_abapgit_definitions=>ty_results_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_status. + + CLEAR: mt_diff_files. + + get_files_and_status( + EXPORTING + is_file = is_file + is_object = is_object + IMPORTING + et_local = lt_local + et_remote = lt_remote + et_status = lt_status ). + + IF is_file IS NOT INITIAL. " Diff for one file + + READ TABLE lt_status ASSIGNING + WITH KEY path = is_file-path filename = is_file-filename. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |File { is_file-path }{ is_file-filename } not found| ). + ENDIF. + + append_diff( it_remote = lt_remote + it_local = lt_local + is_status = ). + + ELSEIF is_object IS NOT INITIAL. " Diff for whole object + + LOOP AT lt_status ASSIGNING + USING KEY sec_key + WHERE obj_type = is_object-obj_type + AND obj_name = is_object-obj_name + AND match IS INITIAL. + append_diff( it_remote = lt_remote + it_local = lt_local + is_status = ). + ENDLOOP. + + ELSE. " Diff for the whole repo + + SORT lt_status BY + path ASCENDING + filename ASCENDING. + LOOP AT lt_status ASSIGNING WHERE match IS INITIAL. + + IF is_file_requested( it_files = it_files + is_status = ) = abap_true. + + append_diff( it_remote = lt_remote + it_local = lt_local + is_status = ). + + ENDIF. + + ENDLOOP. + + ENDIF. + + ENDMETHOD. + METHOD constructor. + + DATA: lv_ts TYPE timestamp. + + super->constructor( ). + mv_unified = zcl_abapgit_persist_factory=>get_user( )->get_diff_unified( ). + mv_repo_key = iv_key. + IF iv_key IS NOT INITIAL. + mi_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + ENDIF. + + GET TIME STAMP FIELD lv_ts. + mv_seed = |diff{ lv_ts }|. " Generate based on time + + ASSERT is_file IS INITIAL OR is_object IS INITIAL. " just one passed + + IF mi_repo IS NOT INITIAL. + calculate_diff( + is_file = is_file + is_object = is_object + it_files = it_files ). + + IF lines( mt_diff_files ) = 0. + zcx_abapgit_exception=>raise( + 'There are no differences to show. The local state completely matches the remote repository.' ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD get_files_and_status. + + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + DATA lo_filter TYPE REF TO kHGwlwVszAmStrZjgYsfmgPrpXDFKn. + + " For single file or object, use a filter instead of processing complete repo + IF is_file IS NOT INITIAL. + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = is_file-filename + iv_path = is_file-path + io_dot = mi_repo->get_dot_abapgit( ) + iv_devclass = mi_repo->get_package( ) + IMPORTING + es_item = ls_item ). + ELSEIF is_object IS NOT INITIAL. + ls_item = is_object. + ENDIF. + + IF ls_item IS NOT INITIAL. + CREATE OBJECT lo_filter EXPORTING is_item = ls_item. + + et_local = mi_repo->get_files_local_filtered( lo_filter ). + et_remote = mi_repo->get_files_remote( + iv_ignore_files = abap_true + ii_obj_filter = lo_filter ). + + et_status = zcl_abapgit_repo_status=>calculate( + ii_repo = mi_repo + ii_obj_filter = lo_filter ). + ELSE. + et_remote = mi_repo->get_files_remote( ). + et_local = mi_repo->get_files_local( ). + + et_status = zcl_abapgit_repo_status=>calculate( mi_repo ). + ENDIF. + + ENDMETHOD. + METHOD get_normalized_fname_with_path. + + rv_filename = normalize_path( is_diff-path ) + && `_` + && normalize_filename( is_diff-filename ). + + ENDMETHOD. + METHOD get_page_layout. + + TRY. + IF zcl_abapgit_persist_factory=>get_user( )->get_diff_unified( ) = abap_true. + rv_page_layout = zcl_abapgit_gui_page=>c_page_layout-centered. + ELSE. + rv_page_layout = zcl_abapgit_gui_page=>c_page_layout-full_width. + ENDIF. + CATCH zcx_abapgit_exception. + rv_page_layout = zcl_abapgit_gui_page=>c_page_layout-full_width. + ENDTRY. + + ENDMETHOD. + METHOD has_diffs. + + LOOP AT it_diffs TRANSPORTING NO FIELDS WHERE result IS NOT INITIAL. + rv_has_diffs = abap_true. + EXIT. + ENDLOOP. + + ENDMETHOD. + METHOD is_binary. + + FIELD-SYMBOLS LIKE iv_d1. + + IF iv_d1 IS NOT INITIAL. " One of them might be new and so empty + ASSIGN iv_d1 TO . + ELSE. + ASSIGN iv_d2 TO . + ENDIF. + + rv_yes = zcl_abapgit_utils=>is_binary( ). + + ENDMETHOD. + METHOD is_file_requested. + + IF lines( it_files ) = 0. + rv_is_file_requested = abap_true. + RETURN. + ENDIF. + + READ TABLE it_files WITH KEY file-path = is_status-path + file-filename = is_status-filename + TRANSPORTING NO FIELDS. + rv_is_file_requested = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD is_refresh. + + FIND FIRST OCCURRENCE OF REGEX |^{ c_actions-refresh_prefix }| IN iv_action. + rv_is_refrseh = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD modify_files_before_diff_calc. + + DATA ls_file LIKE LINE OF rt_files. + + FIELD-SYMBOLS TYPE zif_abapgit_gui_diff=>ty_file_diff. + + " We need to supply files again in calculate_diff. Because + " we only want to refresh the visible files. Otherwise all + " diff files would appear. + " Which is not wanted when we previously only selected particular files. + LOOP AT it_diff_files_old ASSIGNING . + CLEAR ls_file. + MOVE-CORRESPONDING TO ls_file-file. + INSERT ls_file INTO TABLE rt_files. + ENDLOOP. + + ENDMETHOD. + METHOD normalize_filename. + + rv_normalized = replace( val = iv_filename + sub = '.' + occ = 0 + with = '_' ). + + ENDMETHOD. + METHOD normalize_path. + + rv_normalized = replace( val = iv_path + sub = '/' + occ = 0 + with = '_' ). + + ENDMETHOD. + METHOD refresh. + + DATA: + lt_diff_files_old TYPE zif_abapgit_gui_diff=>ty_file_diffs, + lt_files TYPE zif_abapgit_definitions=>ty_stage_tt. + lt_diff_files_old = mt_diff_files. + + CASE iv_action. + WHEN c_actions-refresh_all. + refresh_full( ). + WHEN c_actions-refresh_local. + refresh_local( ). + WHEN OTHERS. + refresh_local_object( iv_action ). + ENDCASE. + + lt_files = modify_files_before_diff_calc( lt_diff_files_old ). + + calculate_diff( it_files = lt_files ). + + ENDMETHOD. + METHOD refresh_full. + mi_repo->refresh( abap_true ). + ENDMETHOD. + METHOD refresh_local. + mi_repo->refresh_local_objects( ). + ENDMETHOD. + METHOD refresh_local_object. + + DATA: + lv_regex TYPE string, + lv_obj_type TYPE tadir-object, + lv_obj_name TYPE tadir-obj_name. + + lv_regex = c_actions-refresh_local_object && `_(\w{4})_(.*)`. + + FIND FIRST OCCURRENCE OF REGEX lv_regex + IN iv_action + SUBMATCHES lv_obj_type lv_obj_name. + + IF sy-subrc = 0. + mi_repo->refresh_local_object( + iv_obj_type = to_upper( lv_obj_type ) + iv_obj_name = to_upper( lv_obj_name ) ). + ELSE. + zcx_abapgit_exception=>raise( |Invalid refresh action { iv_action }| ). + ENDIF. + + ENDMETHOD. + METHOD render_beacon. + + DATA: lv_beacon TYPE string, + lt_beacons TYPE zif_abapgit_definitions=>ty_string_tt. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF is_diff_line-beacon > 0. + lt_beacons = is_diff-o_diff->get_beacons( ). + READ TABLE lt_beacons INTO lv_beacon INDEX is_diff_line-beacon. + ELSE. + lv_beacon = '---'. + ENDIF. + + ri_html->add( '' ). + ri_html->add( '' ). + + IF mi_extra IS BOUND. + " Extra interface for rendering the beacon row + mi_extra->render_beacon_begin_of_row( + ii_html = ri_html + is_diff = is_diff ). + ELSE. + render_beacon_begin_of_row( ri_html ). + ENDIF. + + IF mv_unified = abap_true. + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( |@@ { is_diff_line-new_num } @@ { lv_beacon }| ). + ELSE. + ri_html->add( |@@ { is_diff_line-new_num } @@ { lv_beacon }| ). + ENDIF. + + ri_html->add( '' ). + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_beacon_begin_of_row. + + ii_html->add( '' ). + + ENDMETHOD. + METHOD render_diff. + + DATA lv_display TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( |
    | ). + ri_html->add( render_diff_head( is_diff ) ). + + " Content + IF ms_view-hide_diffs = abap_true. + lv_display = ' nodisplay'. + ENDIF. + + IF is_diff-type <> 'binary'. + ri_html->add( |
    | ). + ri_html->add( || ). + ri_html->add( render_table_head( is_diff ) ). + ri_html->add( render_lines( is_diff ) ). + ri_html->add( '
    ' ). + ELSE. + ri_html->add( '
    ' ). + ri_html->add( 'The content seems to be binary.' ). + ri_html->add( 'Cannot display as diff.' ). + ENDIF. + ri_html->add( '
    ' ). + + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_diff_head. + + DATA: ls_stats TYPE zif_abapgit_definitions=>ty_count, + lv_icon TYPE string, + lv_jump TYPE string, + lv_link TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + + IF ms_view-hide_diffs = abap_true. + lv_icon = 'chevron-right'. + ELSE. + lv_icon = 'chevron-down'. + ENDIF. + + ri_html->add_icon( + iv_name = lv_icon + iv_hint = 'Collapse/Expand' + iv_class = 'cursor-pointer' + iv_onclick = 'onDiffCollapse(event)' ). + + IF is_diff-type <> 'binary'. + ls_stats = is_diff-o_diff->stats( ). + IF is_diff-fstate = c_fstate-both. " Merge stats into 'update' if both were changed + ls_stats-update = ls_stats-update + ls_stats-insert + ls_stats-delete. + CLEAR: ls_stats-insert, ls_stats-delete. + ENDIF. + + ri_html->add( |+ { ls_stats-insert }| ). + ri_html->add( |- { ls_stats-delete }| ). + ri_html->add( |~ { ls_stats-update }| ). + ENDIF. + + " no links for nonexistent or deleted objects + IF NOT ( is_diff-lstate = zif_abapgit_definitions=>c_state-unchanged AND + is_diff-rstate = zif_abapgit_definitions=>c_state-added ) AND + NOT is_diff-lstate = zif_abapgit_definitions=>c_state-deleted. + + lv_jump = zcl_abapgit_html_action_utils=>jump_encode( + iv_obj_type = |{ is_diff-obj_type }| + iv_obj_name = |{ is_diff-obj_name }| + iv_filename = is_diff-filename ). + + lv_link = ri_html->a( + iv_txt = |{ is_diff-path }{ is_diff-filename }| + iv_act = |{ zif_abapgit_definitions=>c_action-jump }?{ lv_jump }| ). + ENDIF. + + IF lv_link IS NOT INITIAL. + ri_html->add( |{ lv_link }| ). + ELSE. + ri_html->add( |{ is_diff-path }{ is_diff-filename }| ). + ENDIF. + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( + iv_lstate = is_diff-lstate + iv_rstate = is_diff-rstate ) ). + + IF mi_extra IS BOUND. + mi_extra->render_diff_head_after_state( + ii_html = ri_html + is_diff = is_diff ). + ELSE. + render_diff_head_after_state( + ii_html = ri_html + is_diff = is_diff ). + ENDIF. + + ri_html->add( 'Last Changed by: ' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name( is_diff-changed_by ) ). + ri_html->add( '' ). + + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_diff_head_after_state. + + IF is_diff-fstate = c_fstate-both AND mv_unified = abap_true. + ii_html->add( 'Attention: Unified mode' + && ' highlighting for MM assumes local file is newer ! ' ). + ENDIF. + + IF is_diff-obj_type IS NOT INITIAL + AND is_diff-obj_name IS NOT INITIAL + AND mi_repo IS NOT INITIAL. + ii_html->add( '' ). + ii_html->add_a( iv_txt = ii_html->icon( iv_name = 'redo-alt-solid' + iv_class = 'pad-sides' + iv_hint = 'Local refresh of this object' ) + iv_act = |{ c_actions-refresh_local_object }_{ is_diff-obj_type }_{ is_diff-obj_name }| + iv_class = |url| ). + ii_html->add( '' ). + ENDIF. + + ENDMETHOD. + METHOD render_lines. + + DATA: lo_highlighter TYPE REF TO zcl_abapgit_syntax_highlighter, + lt_diffs TYPE zif_abapgit_definitions=>ty_diffs_tt, + lv_insert_nav TYPE abap_bool, + lv_tabix TYPE syst-tabix. + + FIELD-SYMBOLS LIKE LINE OF lt_diffs. + FIELD-SYMBOLS LIKE LINE OF lt_diffs. + + lo_highlighter = zcl_abapgit_syntax_factory=>create( iv_filename = is_diff-filename + iv_hidden_chars = ms_view-hidden_chars ). + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + lt_diffs = is_diff-o_diff->get( ). + + IF has_diffs( lt_diffs ) = abap_false. + ri_html->add( render_line_no_diffs( ) ). + RETURN. + ENDIF. + + IF mi_extra IS BOUND. + lv_insert_nav = mi_extra->insert_nav( ). + ENDIF. + + LOOP AT lt_diffs ASSIGNING . + + lv_tabix = sy-tabix. + + IF -short = abap_false. + lv_insert_nav = abap_true. + CONTINUE. + ENDIF. + + IF lv_insert_nav = abap_true. " Insert separator line with navigation + " Get line where diff really starts + READ TABLE lt_diffs ASSIGNING INDEX lv_tabix + 8. + IF sy-subrc <> 0. + " Occurs only for small files/diffs with less than 8 lines. + " Therefore let's use the first line as beacon + ASSIGN TO . + ASSERT IS ASSIGNED. + ENDIF. + ri_html->add( render_beacon( is_diff_line = + is_diff = is_diff ) ). + lv_insert_nav = abap_false. + ENDIF. + + IF lo_highlighter IS BOUND. + -new = lo_highlighter->process_line( -new ). + -old = lo_highlighter->process_line( -old ). + ELSE. + -new = escape( val = -new + format = cl_abap_format=>e_html_attr ). + -old = escape( val = -old + format = cl_abap_format=>e_html_attr ). + ENDIF. + + CONDENSE -new_num. "get rid of leading spaces + CONDENSE -old_num. + + IF mv_unified = abap_true. + ri_html->add( render_line_unified( is_diff_line = ) ). + ELSE. + ri_html->add( render_line_split( is_diff_line = + iv_filename = get_normalized_fname_with_path( is_diff ) + iv_fstate = is_diff-fstate + iv_index = lv_tabix ) ). + ENDIF. + + ENDLOOP. + + IF mv_unified = abap_true. + ri_html->add( render_line_unified( ) ). " Release delayed lines + ENDIF. + + ENDMETHOD. + METHOD render_line_no_diffs. + + DATA ls_diff_line TYPE zif_abapgit_definitions=>ty_diff. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF mv_unified = abap_true. + ls_diff_line-old = 'No diffs found'. + ri_html->add( render_line_unified( is_diff_line = ls_diff_line ) ). + ELSE. + ls_diff_line-new = 'No diffs found'. + ri_html->add( render_line_split( is_diff_line = ls_diff_line + iv_filename = '' + iv_fstate = '' + iv_index = 1 ) ). + ENDIF. + + ENDMETHOD. + METHOD render_line_split. + + DATA: lv_new TYPE string, + lv_old TYPE string, + lv_mark TYPE string, + lv_bg TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + " Note: CSS classes "new" and "old" are used to enable column-based copy to clipboard + + " New line + lv_mark = ` `. + IF is_diff_line-result IS NOT INITIAL. + IF iv_fstate = c_fstate-both OR is_diff_line-result = zif_abapgit_definitions=>c_diff-update. + lv_bg = ' diff_upd'. + lv_mark = `~`. + ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-insert. + lv_bg = ' diff_ins'. + lv_mark = `+`. + ENDIF. + ENDIF. + lv_new = || + && |{ lv_mark }| + && |{ is_diff_line-new }|. + + " Old line + CLEAR lv_bg. + lv_mark = ` `. + IF is_diff_line-result IS NOT INITIAL. + IF iv_fstate = c_fstate-both OR is_diff_line-result = zif_abapgit_definitions=>c_diff-update. + lv_bg = ' diff_upd'. + lv_mark = `~`. + ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-delete. + lv_bg = ' diff_del'. + lv_mark = `-`. + ENDIF. + ENDIF. + lv_old = || + && |{ lv_mark }| + && |{ is_diff_line-old }|. + + " render line, inverse sides if remote is newer + ri_html->add( '' ). + + IF mi_extra IS BOUND. + mi_extra->render_line_split_row( + ii_html = ri_html + iv_filename = iv_filename + is_diff_line = is_diff_line + iv_index = iv_index + iv_fstate = iv_fstate + iv_old = lv_old + iv_new = lv_new ). + ENDIF. + + render_line_split_row( + ii_html = ri_html + iv_fstate = iv_fstate + iv_old = lv_old + iv_new = lv_new ). + + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_line_split_row. + + IF iv_fstate = c_fstate-remote. " Remote file leading changes + ii_html->add( iv_old ). " local + ii_html->add( iv_new ). " remote + ELSE. " Local leading changes or both were modified + ii_html->add( iv_new ). " local + ii_html->add( iv_old ). " remote + ENDIF. + + ENDMETHOD. + METHOD render_line_unified. + + FIELD-SYMBOLS LIKE LINE OF mt_delayed_lines. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + " Note: CSS classes "new" and "old" are used to enable column-based copy to clipboard + + " Release delayed subsequent update lines + IF is_diff_line-result <> zif_abapgit_definitions=>c_diff-update. + LOOP AT mt_delayed_lines ASSIGNING . + ri_html->add( '' ). + ri_html->add( || + && || + && |-| + && |{ -old }| ). + ri_html->add( '' ). + ENDLOOP. + LOOP AT mt_delayed_lines ASSIGNING . + ri_html->add( '' ). + ri_html->add( || + && || + && |+| + && |{ -new }| ). + ri_html->add( '' ). + ENDLOOP. + CLEAR mt_delayed_lines. + ENDIF. + + ri_html->add( '' ). + CASE is_diff_line-result. + WHEN zif_abapgit_definitions=>c_diff-update. + APPEND is_diff_line TO mt_delayed_lines. " Delay output of subsequent updates + WHEN zif_abapgit_definitions=>c_diff-insert. + ri_html->add( || + && || + && |+| + && |{ is_diff_line-new }| ). + WHEN zif_abapgit_definitions=>c_diff-delete. + ri_html->add( || + && || + && |-| + && |{ is_diff_line-old }| ). + WHEN OTHERS. "none + ri_html->add( || + && || + && | | + && |{ is_diff_line-old }| ). + ENDCASE. + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_scripts. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). + + ri_html->add( 'restoreScrollPosition();' ). + ri_html->add( 'var gHelper = new DiffHelper({' ). + ri_html->add( | seed: "{ mv_seed }",| ). + ri_html->add( ' ids: {' ). + ri_html->add( ' jump: "jump",' ). + ri_html->add( ' diffList: "diff-list",' ). + ri_html->add( ' filterMenu: "diff-filter",' ). + ri_html->add( ' }' ). + ri_html->add( '});' ). + + ri_html->add( 'addMarginBottom();' ). + + IF mi_repo IS NOT INITIAL. + ri_html->add( 'var gGoJumpPalette = new CommandPalette(enumerateJumpAllFiles, {' ). + ri_html->add( ' toggleKey: "F2",' ). + ri_html->add( ' hotkeyDescription: "Jump to File ..."' ). + ri_html->add( '});' ). + ENDIF. + + " Feature for selecting ABAP code by column and copy to clipboard + ri_html->add( 'var columnSelection = new DiffColumnSelection();' ). + + ENDMETHOD. + METHOD render_table_head. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '' ). + ri_html->add( '' ). + + IF mv_unified = abap_true. + + render_table_head_unified( ri_html ). + + ELSE. + IF mi_extra IS BOUND. + " Extra interface for rendering the table head + mi_extra->render_table_head_non_unified( + is_diff = is_diff + ii_html = ri_html ). + ENDIF. + + render_table_head_non_unified( ri_html ). + + ENDIF. + + ri_html->add( '' ). + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_table_head_non_unified. + + ii_html->add( '' ). + ii_html->add( '' ). + ii_html->add( 'LOCAL' ). + ii_html->add( '' ). + ii_html->add( '' ). + ii_html->add( 'REMOTE' ). + + ENDMETHOD. + METHOD render_table_head_unified. + + ii_html->add( 'old' ). + ii_html->add( 'new' ). + ii_html->add( '' ). + ii_html->add( 'code' ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA ls_view LIKE ms_view. + + ls_view = ms_view. + + CASE ii_event->mv_action. + WHEN c_actions-toggle_unified. " Toggle file display + + mv_unified = zcl_abapgit_persist_factory=>get_user( )->toggle_diff_unified( ). + + rs_handled-page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Diff' + iv_page_layout = get_page_layout( ) + ii_page_menu_provider = me + ii_child_component = me ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. + + WHEN c_actions-toggle_hide_diffs. " Toggle display of diffs + + ms_view-hide_diffs = boolc( ms_view-hide_diffs = abap_false ). + + WHEN c_actions-toggle_hidden_chars. " Toggle display of hidden characters + + ms_view-hidden_chars = boolc( ms_view-hidden_chars = abap_false ). + + WHEN c_actions-toggle_ignore_indent. " Toggle ignore indentation + + ms_view-ignore_indent = boolc( ms_view-ignore_indent = abap_false ). + + WHEN c_actions-toggle_ignore_comments. " Toggle ignore comments + + ms_view-ignore_comments = boolc( ms_view-ignore_comments = abap_false ). + + WHEN c_actions-toggle_ignore_case. " Toggle case sensitivity + + ms_view-ignore_case = boolc( ms_view-ignore_case = abap_false ). + + WHEN OTHERS. + + IF is_refresh( ii_event->mv_action ) = abap_true. + + refresh( ii_event->mv_action ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + ENDIF. + + ENDCASE. + + " If view has changed, refresh local files recalculating diff, and update menu + IF ms_view <> ls_view. + IF ms_view-hide_diffs = ls_view-hide_diffs. + refresh( c_actions-refresh_local ). + ENDIF. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + + ls_hotkey_action-ui_component = 'Diff'. + + ls_hotkey_action-description = |Refresh Local|. + ls_hotkey_action-action = c_actions-refresh_local. + ls_hotkey_action-hotkey = |r|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Refresh All|. + ls_hotkey_action-action = c_actions-refresh_all. + ls_hotkey_action-hotkey = |a|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Toggle Split/Unified|. + ls_hotkey_action-action = c_actions-toggle_unified. + ls_hotkey_action-hotkey = |u|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Toggle Hidden Characters|. + ls_hotkey_action-action = c_actions-toggle_hidden_chars. + ls_hotkey_action-hotkey = |h|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-diff' ). + + add_menu_begin( ro_toolbar ). + add_jump_sub_menu( ro_toolbar ). + add_filter_sub_menu( ro_toolbar ). + add_menu_end( ro_toolbar ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA: ls_diff_file LIKE LINE OF mt_diff_files, + li_progress TYPE REF TO zif_abapgit_progress. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + li_progress = zcl_abapgit_progress=>get_instance( lines( mt_diff_files ) ). + + IF mi_repo IS NOT INITIAL. + ri_html->add( `
    ` ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( mi_repo ) ). + ri_html->add( `
    ` ). + ENDIF. + + ri_html->add( |
    | ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_js_error_banner( ) ). + LOOP AT mt_diff_files INTO ls_diff_file. + li_progress->show( + iv_current = sy-tabix + iv_text = |Render Diff - { ls_diff_file-filename }| ). + + ri_html->add( render_diff( ls_diff_file ) ). + ENDLOOP. + IF sy-subrc <> 0. + ri_html->add( |No more diffs| ). + ENDIF. + ri_html->add( '
    ' ). + + register_deferred_script( render_scripts( ) ). + + li_progress->off( ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_diff. + + CREATE OBJECT lo_component + EXPORTING + iv_key = iv_key + is_file = is_file + is_object = is_object + it_files = it_files. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Diff' + iv_page_layout = get_page_layout( ) + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_db_entry IMPLEMENTATION. + METHOD build_toolbar. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-database-entry' ). + + IF mv_edit_mode = abap_true. + ro_toolbar->add( + iv_act = |submitFormById('{ c_edit_form_id }');| + iv_txt = 'Save' + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ELSE. + ro_toolbar->add( + iv_act = |{ c_action-switch_mode }| + iv_txt = 'Edit' ). + ENDIF. + + ro_toolbar->add( + iv_act = zif_abapgit_definitions=>c_action-go_back + iv_txt = 'Back' ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + register_stylesheet( ). + mv_edit_mode = iv_edit_mode. + ms_key = is_key. + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_db_entry. + + CREATE OBJECT lo_component + EXPORTING + iv_edit_mode = iv_edit_mode + is_key = is_key. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_extra_css_url = c_css_url + ii_page_title_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD dbcontent_decode. + + rs_content-type = io_form_data->get( 'TYPE' ). + rs_content-value = io_form_data->get( 'VALUE' ). + rs_content-data_str = io_form_data->get( 'XMLDATA' ). + + IF rs_content-data_str(1) <> '<' AND rs_content-data_str+1(1) = '<'. " Hmmm ??? + rs_content-data_str = rs_content-data_str+1. + ENDIF. + + ENDMETHOD. + METHOD do_update. + + ASSERT is_content-type IS NOT INITIAL. + + zcl_abapgit_persistence_db=>get_instance( )->update( + iv_type = is_content-type + iv_value = is_content-value + iv_data = is_content-data_str ). + + COMMIT WORK. + + ENDMETHOD. + METHOD register_stylesheet. + + DATA lo_buf TYPE REF TO zcl_abapgit_string_buffer. + + CREATE OBJECT lo_buf. + +**************************************************** +* abapmerge Pragma [include] - ZABAPGIT_CSS_PAGE_DB_ENTRY.W3MI.DATA.CSS +**************************************************** + lo_buf->add( '/*' ). + lo_buf->add( ' * PAGE DB ENTRY CSS' ). + lo_buf->add( ' */' ). + lo_buf->add( '' ). + lo_buf->add( '/* LAYOUT */' ). + lo_buf->add( '' ). + lo_buf->add( '.db-entry {' ). + lo_buf->add( ' padding: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry pre {' ). + lo_buf->add( ' display: block;' ). + lo_buf->add( ' font-size: 10pt;' ). + lo_buf->add( ' overflow: hidden;' ). + lo_buf->add( ' word-wrap:break-word;' ). + lo_buf->add( ' white-space: pre-wrap;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' padding: 0.5em;' ). + lo_buf->add( ' margin: 0.5em 0em;' ). + lo_buf->add( ' width: 98%;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry textarea {' ). + lo_buf->add( ' margin: 0.5em 0em;' ). + lo_buf->add( ' width: 98%;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry .toolbar {' ). + lo_buf->add( ' padding-left: 0.5em;' ). + lo_buf->add( ' padding-right: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry dl.entry-tag div {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' border: 1px solid;' ). + lo_buf->add( ' border-radius: 3px;' ). + lo_buf->add( ' margin-right: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry dl.entry-tag div:last-child {' ). + lo_buf->add( ' margin-right: 0px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry dt, .db-entry dd {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' margin-left: 0px;' ). + lo_buf->add( ' padding: 2px 5px;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry dt::after { content: ":" }' ). + lo_buf->add( '' ). + lo_buf->add( '/* COLORS */' ). + lo_buf->add( '' ). + lo_buf->add( '.db-entry {' ). + lo_buf->add( ' background-color: var(--theme-container-background-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry pre {' ). + lo_buf->add( ' background-color: #f4f4f4;' ). + lo_buf->add( ' border-color: var(--theme-container-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry textarea {' ). + lo_buf->add( ' background-color: var(--theme-table-background-color);' ). + lo_buf->add( ' border-color: var(--theme-container-border-color);' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry dl.entry-tag div {' ). + lo_buf->add( ' border-color: hsl(206, 20%, 75%);' ). + lo_buf->add( ' background-color: hsl(206, 20%, 90%);' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-entry dt {' ). + lo_buf->add( ' background-color: hsl(206, 20%, 75%);' ). + lo_buf->add( '}' ). + gui_services( )->register_page_asset( + iv_url = c_css_url + iv_type = 'text/css' + iv_mime_name = 'ZABAPGIT_CSS_PAGE_DB_ENTRY' + iv_inline = lo_buf->join_w_newline_and_flush( ) ). + + ENDMETHOD. + METHOD render_edit. + + DATA lv_formatted TYPE string. + + lv_formatted = escape( + val = zcl_abapgit_xml_pretty=>print( iv_raw_db_value ) + format = cl_abap_format=>e_html_attr ). + + " Form + ii_html->add( |
    | ). + ii_html->add( || ). + ii_html->add( || ). + ii_html->add( || ). + ii_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_entry_tag. + + rv_html = + ||. + + ENDMETHOD. + METHOD render_header. + + ii_html->add( '
    ' ). + ii_html->add( io_toolbar->render( iv_right = abap_true ) ). + ii_html->add( render_entry_tag( ms_key ) ). + ii_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_view. + + DATA lo_highlighter TYPE REF TO zcl_abapgit_syntax_highlighter. + DATA lv_formatted TYPE string. + + " Create syntax highlighter + lo_highlighter = zcl_abapgit_syntax_factory=>create( '*.xml' ). + lv_formatted = lo_highlighter->process_line( zcl_abapgit_xml_pretty=>print( iv_raw_db_value ) ). + + ii_html->add( |
    { lv_formatted }
    | ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + CASE ii_event->mv_action. + WHEN c_action-switch_mode. + mv_edit_mode = boolc( mv_edit_mode = abap_false ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-update. + do_update( dbcontent_decode( ii_event->form_data( ) ) ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_page_title~get_page_title. + + IF mv_edit_mode = abap_true. + rv_title = 'Config Edit'. + ELSE. + rv_title = 'Config Display'. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA lv_raw_db_value TYPE zif_abapgit_persistence=>ty_content-data_str. + + register_handlers( ). + + TRY. + lv_raw_db_value = zcl_abapgit_persistence_db=>get_instance( )->read( + iv_type = ms_key-type + iv_value = ms_key-value ). + CATCH zcx_abapgit_not_found ##NO_HANDLER. + ENDTRY. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + + render_header( + ii_html = ri_html + io_toolbar = build_toolbar( ) ). + + IF mv_edit_mode = abap_true. + zcl_abapgit_persistence_db=>get_instance( )->lock( + iv_type = ms_key-type + iv_value = ms_key-value ). + render_edit( + iv_raw_db_value = lv_raw_db_value + ii_html = ri_html ). + ELSE. + render_view( + iv_raw_db_value = lv_raw_db_value + ii_html = ri_html ). + ENDIF. + + ri_html->add( '
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_db IMPLEMENTATION. + METHOD constructor. + super->constructor( ). + register_stylesheet( ). + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_db. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Database Utility' + iv_extra_css_url = c_css_url + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD do_backup_db. + + DATA: + lt_data TYPE zif_abapgit_persistence=>ty_contents, + lv_text TYPE string, + lt_toc TYPE string_table, + lo_zip TYPE REF TO cl_abap_zip, + lv_zip TYPE xstring, + lv_path TYPE string, + lv_filename TYPE string, + li_fe_serv TYPE REF TO zif_abapgit_frontend_services. + + FIELD-SYMBOLS: + LIKE LINE OF lt_data. + + lt_data = zcl_abapgit_persistence_db=>get_instance( )->list( ). + + lv_text = |Table of Content\n|. + INSERT lv_text INTO TABLE lt_toc. + lv_text = |================\n|. + INSERT lv_text INTO TABLE lt_toc. + lv_text = |\n|. + INSERT lv_text INTO TABLE lt_toc. + + CREATE OBJECT lo_zip. + + LOOP AT lt_data ASSIGNING . + IF -type = zcl_abapgit_persistence_db=>c_type_repo_csum. + CONCATENATE -type '_' -value '.txt' INTO lv_filename. + ELSE. + CONCATENATE -type '_' -value '.xml' INTO lv_filename. + ENDIF. + lo_zip->add( + name = lv_filename + content = zcl_abapgit_convert=>string_to_xstring_utf8( -data_str ) ). + + lv_text = explain_content( ). + REPLACE '' IN lv_text WITH ''. + REPLACE '' IN lv_text WITH ''. + lv_text = |{ -type },{ -value },{ lv_text }\n|. + INSERT lv_text INTO TABLE lt_toc. + ENDLOOP. + + lo_zip->add( + name = c_toc_filename + content = zcl_abapgit_convert=>string_to_xstring_utf8( concat_lines_of( lt_toc ) ) ). + + lv_zip = lo_zip->save( ). + + CONCATENATE 'abapGit_Backup_' sy-datlo '_' sy-timlo '.zip' INTO lv_filename. + + li_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + + lv_path = li_fe_serv->show_file_save_dialog( + iv_title = 'abapGit Backup' + iv_extension = 'zip' + iv_default_filename = lv_filename ). + + li_fe_serv->file_download( + iv_path = lv_path + iv_xstr = lv_zip ). + + MESSAGE 'abapGit Backup successfully saved' TYPE 'S'. + + ENDMETHOD. + METHOD do_delete_entry. + + DATA lv_answer TYPE c LENGTH 1. + + ASSERT is_key-type IS NOT INITIAL. + + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_titlebar = 'Warning' + iv_text_question = |Are you sure you want to delete entry { is_key-type } { is_key-value }?| + iv_text_button_1 = 'Yes' + iv_icon_button_1 = 'ICON_DELETE' + iv_text_button_2 = 'No' + iv_icon_button_2 = 'ICON_CANCEL' + iv_default_button = '2' + iv_display_cancel_button = abap_false ). + + IF lv_answer = '2'. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + zcl_abapgit_persistence_db=>get_instance( )->delete( + iv_type = is_key-type + iv_value = is_key-value ). + + " If deleting repo, also delete corresponding checksums + " Other way around is ok, since checksums are automatically recreated + IF is_key-type = zcl_abapgit_persistence_db=>c_type_repo. + zcl_abapgit_persistence_db=>get_instance( )->delete( + iv_type = zcl_abapgit_persistence_db=>c_type_repo_csum + iv_value = is_key-value ). + + " Initialize repo list + zcl_abapgit_repo_srv=>get_instance( )->init( ). + " TODO: think how to remove this code, + " maybe implement subscription in persistence_db, + " so that repo_srv receive a notification on add/delete + ENDIF. + + COMMIT WORK. + + ENDMETHOD. + METHOD do_restore_db. + + DATA: + lv_answer TYPE c LENGTH 1, + lo_zip TYPE REF TO cl_abap_zip, + lv_zip TYPE xstring, + lv_path TYPE string, + lv_filename TYPE string, + lv_data TYPE xstring, + ls_data TYPE zif_abapgit_persistence=>ty_content, + lt_data TYPE zif_abapgit_persistence=>ty_contents, + lt_data_old TYPE zif_abapgit_persistence=>ty_contents, + li_fe_serv TYPE REF TO zif_abapgit_frontend_services. + + FIELD-SYMBOLS: + LIKE LINE OF lo_zip->files. + + li_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + + lv_path = li_fe_serv->show_file_open_dialog( + iv_title = 'Restore abapGit Backup' + iv_extension = 'zip' + iv_default_filename = 'abapGit_Backup_*.zip' ). + + lv_zip = li_fe_serv->file_upload( lv_path ). + + CREATE OBJECT lo_zip. + + lo_zip->load( + EXPORTING + zip = lv_zip + EXCEPTIONS + zip_parse_error = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error loading ZIP file' ). + ENDIF. + + LOOP AT lo_zip->files ASSIGNING WHERE name <> c_toc_filename. + CLEAR ls_data. + lv_filename = -name. + REPLACE '.xml' IN lv_filename WITH ''. + REPLACE '.txt' IN lv_filename WITH ''. + IF lv_filename CP 'REPO_CS*'. + ls_data-type = lv_filename(7). + ls_data-value = lv_filename+8(*). + ELSE. + SPLIT lv_filename AT '_' INTO ls_data-type ls_data-value. + ENDIF. + + " Validate DB key + TRY. + zcl_abapgit_persistence_db=>validate_entry_type( ls_data-type ). + CATCH zcx_abapgit_exception. + zcx_abapgit_exception=>raise( |Invalid DB entry type. This is not an abapGit Backup| ). + ENDTRY. + + lo_zip->get( + EXPORTING + name = -name + IMPORTING + content = lv_data + EXCEPTIONS + zip_index_error = 1 + zip_decompression_error = 2 + OTHERS = 3 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error getting file { -name } from ZIP| ). + ENDIF. + + ls_data-data_str = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). + INSERT ls_data INTO TABLE lt_data. + ENDLOOP. + + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_titlebar = 'Warning' + iv_text_question = 'All existing repositories and settings will be deleted and overwritten! Continue?' + iv_text_button_1 = 'Restore' + iv_icon_button_1 = 'ICON_IMPORT' + iv_text_button_2 = 'Cancel' + iv_icon_button_2 = 'ICON_CANCEL' + iv_default_button = '2' + iv_display_cancel_button = abap_false ). + + IF lv_answer <> '1'. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + lt_data_old = zcl_abapgit_persistence_db=>get_instance( )->list( ). + LOOP AT lt_data_old INTO ls_data. + zcl_abapgit_persistence_db=>get_instance( )->delete( + iv_type = ls_data-type + iv_value = ls_data-value ). + ENDLOOP. + + COMMIT WORK AND WAIT. + + LOOP AT lt_data INTO ls_data. + zcl_abapgit_persistence_db=>get_instance( )->add( + iv_type = ls_data-type + iv_value = ls_data-value + iv_data = ls_data-data_str ). + ENDLOOP. + + COMMIT WORK AND WAIT. + + MESSAGE 'abapGit Backup successfully restored' TYPE 'S'. + + ENDMETHOD. + METHOD explain_content. + + DATA lv_descr TYPE string. + DATA ls_explanation TYPE ty_explanation. + + CASE is_data-type. + WHEN zcl_abapgit_persistence_db=>c_type_repo. + lv_descr = 'Repo Settings'. + ls_explanation = explain_content_repo( is_data ). + + WHEN zcl_abapgit_persistence_db=>c_type_background. + lv_descr = 'Background Settings'. + ls_explanation = explain_content_background( is_data ). + + WHEN zcl_abapgit_persistence_db=>c_type_user. + lv_descr = 'Personal Settings'. + ls_explanation-value = zcl_abapgit_env_factory=>get_user_record( )->get_name( is_data-value ). + + WHEN zcl_abapgit_persistence_db=>c_type_settings. + lv_descr = 'Global Settings'. + + WHEN zcl_abapgit_persistence_db=>c_type_packages. + lv_descr = 'Local Package Details'. + + WHEN zcl_abapgit_persistence_db=>c_type_repo_csum. + lv_descr = 'Repo Checksums'. + ls_explanation = explain_content_repo_cs( is_data ). + + WHEN OTHERS. + IF strlen( is_data-data_str ) >= 250. + ls_explanation-value = is_data-data_str(250). + ELSE. + ls_explanation-value = is_data-data_str. + ENDIF. + + ls_explanation-value = escape( + val = ls_explanation-value + format = cl_abap_format=>e_html_attr ). + ls_explanation-value = |
    { ls_explanation-value }
    |. + + ENDCASE. + + IF ls_explanation-value IS NOT INITIAL. + lv_descr = |{ lv_descr }: |. + ENDIF. + + IF ls_explanation-extra IS NOT INITIAL. + ls_explanation-extra = | ({ ls_explanation-extra })|. + ENDIF. + + rv_text = |{ lv_descr }{ ls_explanation-value }{ ls_explanation-extra }|. + + IF strlen( rv_text ) >= 250. + rv_text = rv_text(250) && '...'. + ENDIF. + + ENDMETHOD. + METHOD explain_content_background. + + DATA: + ls_result TYPE match_result, + ls_match TYPE submatch_result, + lv_class TYPE string, + ls_method LIKE LINE OF mt_methods. + + rs_expl-value = |{ zcl_abapgit_repo_srv=>get_instance( )->get( is_data-value )->get_name( ) }|. + + FIND FIRST OCCURRENCE OF REGEX '(.*)' + IN is_data-data_str IGNORING CASE RESULTS ls_result. + READ TABLE ls_result-submatches INTO ls_match INDEX 1. + IF sy-subrc = 0. + lv_class = is_data-data_str+ls_match-offset(ls_match-length). + ENDIF. + + IF mt_methods IS INITIAL. + mt_methods = zcl_abapgit_background=>list_methods( ). + ENDIF. + + READ TABLE mt_methods INTO ls_method WITH TABLE KEY class = lv_class. + IF sy-subrc = 0. + rs_expl-extra = ls_method-description. + ELSE. + rs_expl-extra = lv_class. + ENDIF. + + ENDMETHOD. + METHOD explain_content_repo. + + DATA: + ls_result TYPE match_result, + ls_match TYPE submatch_result, + lv_cnt TYPE i. + + FIND FIRST OCCURRENCE OF REGEX '' + IN is_data-data_str IGNORING CASE MATCH COUNT lv_cnt. + IF lv_cnt > 0. + rs_expl-extra = 'Online'. + ELSE. + rs_expl-extra = 'Offline'. + ENDIF. + + FIND FIRST OCCURRENCE OF REGEX '(.*)' + IN is_data-data_str IGNORING CASE RESULTS ls_result. + READ TABLE ls_result-submatches INTO ls_match INDEX 1. + IF sy-subrc = 0. + rs_expl-value = is_data-data_str+ls_match-offset(ls_match-length). + ELSE. + FIND FIRST OCCURRENCE OF REGEX '(.*)' + IN is_data-data_str IGNORING CASE RESULTS ls_result. + READ TABLE ls_result-submatches INTO ls_match INDEX 1. + IF sy-subrc = 0. + rs_expl-value = is_data-data_str+ls_match-offset(ls_match-length). + ENDIF. + ENDIF. + + IF rs_expl-value IS INITIAL. + FIND FIRST OCCURRENCE OF REGEX '(.*)' + IN is_data-data_str IGNORING CASE RESULTS ls_result. + READ TABLE ls_result-submatches INTO ls_match INDEX 1. + IF sy-subrc = 0. + rs_expl-value = is_data-data_str+ls_match-offset(ls_match-length). + IF lv_cnt > 0. + rs_expl-value = zcl_abapgit_url=>name( rs_expl-value ). + ENDIF. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD explain_content_repo_cs. + + DATA lt_lines TYPE string_table. + + IF strlen( is_data-data_str ) > 0. + SPLIT is_data-data_str AT cl_abap_char_utilities=>newline INTO TABLE lt_lines. + rs_expl-extra = |{ lines( lt_lines ) } lines|. + + READ TABLE lt_lines INDEX 1 INTO rs_expl-value. + IF sy-subrc = 0. + REPLACE '#repo_name#' IN rs_expl-value WITH ''. + rs_expl-value = escape( + val = rs_expl-value + format = cl_abap_format=>e_html_attr ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD register_stylesheet. + + DATA lo_buf TYPE REF TO zcl_abapgit_string_buffer. + + CREATE OBJECT lo_buf. + +**************************************************** +* abapmerge Pragma [include] - ZABAPGIT_CSS_PAGE_DB.W3MI.DATA.CSS +**************************************************** + lo_buf->add( '/*' ). + lo_buf->add( ' * PAGE DB CSS' ). + lo_buf->add( ' */' ). + lo_buf->add( '' ). + lo_buf->add( '/* LAYOUT */' ). + lo_buf->add( '' ). + lo_buf->add( '.db-list {' ). + lo_buf->add( ' padding: 0.5em;' ). + lo_buf->add( ' overflow-x: auto;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-list table { table-layout: fixed; }' ). + lo_buf->add( '.db-list table pre {' ). + lo_buf->add( ' display: inline-block;' ). + lo_buf->add( ' overflow: hidden;' ). + lo_buf->add( ' word-wrap:break-word;' ). + lo_buf->add( ' white-space: pre-wrap;' ). + lo_buf->add( ' margin: 0px;' ). + lo_buf->add( ' width: 30em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-list table th {' ). + lo_buf->add( ' text-align: left;' ). + lo_buf->add( ' padding: 0.5em;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-list table thead tr { border-bottom: 1px solid; }' ). + lo_buf->add( '.db-list table td {' ). + lo_buf->add( ' padding: 4px 0.5em;' ). + lo_buf->add( ' vertical-align: middle;' ). + lo_buf->add( ' word-break: break-all;' ). + lo_buf->add( '}' ). + lo_buf->add( '.db-list table td.data { font-style: italic; }' ). + lo_buf->add( '' ). + lo_buf->add( '/* COLORS */' ). + lo_buf->add( '' ). + lo_buf->add( '.db-list { background-color: var(--theme-table-background-color); }' ). + lo_buf->add( '.db-list table td { color: var(--theme-primary-font-color); }' ). + lo_buf->add( '.db-list table td.data { color: var(--theme-greyscale-dark); }' ). + lo_buf->add( '.db-list table tbody tr:hover td { background-color: rgba(0, 0, 0, 0.075); }' ). + lo_buf->add( '.db-list table tbody tr:active td { background-color: #f4f4f4; } /* Needed? */' ). + lo_buf->add( '.db-list table th { color: var(--theme-link-color); }' ). + lo_buf->add( '.db-list table thead tr { border-color: var(--theme-table-border-color); }' ). + gui_services( )->register_page_asset( + iv_url = c_css_url + iv_type = 'text/css' + iv_mime_name = 'ZABAPGIT_CSS_PAGE_DB' + iv_inline = lo_buf->join_w_newline_and_flush( ) ). + + ENDMETHOD. + METHOD render_stats. + + DATA: + lv_cnt TYPE i, + lv_online TYPE i, + lv_offline TYPE i, + lv_users TYPE i. + + FIELD-SYMBOLS LIKE LINE OF it_db_entries. + + LOOP AT it_db_entries ASSIGNING . + IF -type = zcl_abapgit_persistence_db=>c_type_repo. + FIND FIRST OCCURRENCE OF REGEX '' + IN -data_str IGNORING CASE MATCH COUNT lv_cnt. + IF lv_cnt > 0. + lv_online = lv_online + 1. + ELSE. + lv_offline = lv_offline + 1. + ENDIF. + ELSEIF -type = zcl_abapgit_persistence_db=>c_type_user. + lv_users = lv_users + 1. + ENDIF. + ENDLOOP. + + ri_html = zcl_abapgit_html=>create( ). + + ri_html->add( |Repositories: { lv_online + lv_offline } ({ lv_online } online, { lv_offline } offline),| ). + ri_html->add( |Users: { lv_users }| ). + + ENDMETHOD. + METHOD render_table. + + ri_html = zcl_abapgit_html_table=>create( me + )->define_column( + iv_column_id = 'type' + iv_column_title = 'Type' + )->define_column( + iv_column_id = 'value' + iv_column_title = 'Key' + )->define_column( + iv_column_id = 'expl' + iv_column_title = 'Data' + )->define_column( 'cmd' + )->render( it_db_entries ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA ls_db TYPE zif_abapgit_persistence=>ty_content. + DATA lo_query TYPE REF TO zcl_abapgit_string_map. + + lo_query = ii_event->query( ). + CASE ii_event->mv_action. + WHEN c_action-delete. + lo_query->to_abap( CHANGING cs_container = ls_db ). + do_delete_entry( ls_db ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-backup. + do_backup_db( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-restore. + do_restore_db( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-database-utility' ). + + ro_toolbar->add( + iv_txt = 'Backup' + iv_act = c_action-backup ). + ro_toolbar->add( + iv_txt = 'Restore' + iv_act = c_action-restore ). + ro_toolbar->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA lt_db_entries TYPE zif_abapgit_persistence=>ty_contents. + + register_handlers( ). + + lt_db_entries = zcl_abapgit_persistence_db=>get_instance( )->list( ). + + ri_html = zcl_abapgit_html=>create( ). + + ri_html->add( '
    ' ). + ri_html->add( render_stats( lt_db_entries ) ). + ri_html->add( '
    ' ). + + ri_html->add( '
    ' ). + ri_html->add( render_table( lt_db_entries ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD zif_abapgit_html_table~get_row_attrs. + ENDMETHOD. + METHOD zif_abapgit_html_table~render_cell. + + DATA lv_action TYPE string. + DATA lo_toolbar TYPE REF TO zcl_abapgit_html_toolbar. + + CASE iv_column_id. + WHEN 'type' OR 'value'. + rs_render-content = |{ iv_value }|. + WHEN 'expl'. + rs_render-content = explain_content( is_row ). + rs_render-css_class = 'data'. + WHEN 'cmd'. + lv_action = zcl_abapgit_html_action_utils=>dbkey_encode( is_row ). + lo_toolbar = zcl_abapgit_html_toolbar=>create( 'actionbar-database-utility' + )->add( + iv_txt = 'Display' + iv_act = |{ zif_abapgit_definitions=>c_action-db_display }?{ lv_action }| + )->add( + iv_txt = 'Edit' + iv_act = |{ zif_abapgit_definitions=>c_action-db_edit }?{ lv_action }| + )->add( + iv_txt = 'Delete' + iv_act = |{ c_action-delete }?{ lv_action }| ). + + zcl_abapgit_exit=>get_instance( )->enhance_any_toolbar( lo_toolbar ). + + rs_render-html = lo_toolbar->render( ). + + ENDCASE. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_PAGE_WHEREUSED IMPLEMENTATION. + METHOD constructor. + super->constructor( ). + IF ii_repo IS BOUND. + mv_package = ii_repo->get_package( ). + mv_ignore_subpackages = ii_repo->get_local_settings( )-ignore_subpackages. + ELSE. + mv_package = iv_package. + ENDIF. + + IF mv_package IS INITIAL OR zcl_abapgit_factory=>get_sap_package( mv_package )->exists( ) = abap_false. + zcx_abapgit_exception=>raise( |Package { mv_package } does not exist| ). + ENDIF. + + run_where_used( ). + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_whereused. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo + iv_package = iv_package. + + ri_page = zcl_abapgit_gui_page_hoc=>create( lo_component ). + + ENDMETHOD. + METHOD init_table_component. + + DATA ls_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state. + DATA lv_package_col_id TYPE string. + DATA lv_package_col_title TYPE string. + + IF mi_table IS BOUND. + RETURN. + ENDIF. + + IF mv_show_root_pkg = abap_true. + ls_sorting_state-column_id = 'root_package'. + lv_package_col_id = 'root_package'. + lv_package_col_title = 'Root package'. + ELSE. + ls_sorting_state-column_id = 'package'. + lv_package_col_id = 'package'. + lv_package_col_title = 'Package'. + ENDIF. + + mi_table = zcl_abapgit_html_table=>create( + ii_renderer = me + is_initial_sorting_state = ls_sorting_state ). + mi_table->define_column_group( + iv_group_title = 'Repo object' + iv_group_id = '' " No need + )->define_column( + iv_column_id = 'dep_package' + iv_column_title = 'Package' + )->define_column( + iv_column_id = 'dep_obj_type' + iv_column_title = 'Type' + )->define_column( + iv_column_id = 'dep_obj_name' + iv_column_title = 'Name' ). + mi_table->define_column_group( + iv_group_title = 'Used in' + iv_group_id = 'where' " Needed for CSS + )->define_column( + iv_column_id = lv_package_col_id + iv_column_title = lv_package_col_title + )->define_column( + iv_column_id = 'obj_type' + iv_column_title = 'Type' + )->define_column( + iv_column_id = 'obj_name' + iv_column_title = 'Name' ). + + ENDMETHOD. + METHOD render_filter_help_hint. + + DATA li_html TYPE REF TO zif_abapgit_html. + + li_html = zcl_abapgit_html=>create( + )->add( `

    This tool cycles through all objects in the repo ` + )->add( `and runs the standard where-used function against it. ` + )->add( `The result is displayed here less the usages ` + )->add( `inside the repo itself.

    ` + )->add( `

    The tool can be used to detect ` + )->add( `potential regressions in the code which uses the repo ` + )->add( `and external to it (e.g. when deploying updates ` + )->add( `to a library-like repo).

    ` ). + + rv_html = zcl_abapgit_gui_chunk_lib=>render_help_hint( li_html->render( iv_no_line_breaks = abap_true ) ). + + ENDMETHOD. + METHOD render_header. + + DATA lv_sub_hint TYPE string. + + IF mv_ignore_subpackages = abap_false. + lv_sub_hint = ' and its subpackages'. + ENDIF. + + ii_html->div( + iv_class = 'wu-header' + iv_content = |Where used for package { + zcl_abapgit_gui_chunk_lib=>render_package_name( mv_package )->render( iv_no_line_breaks = abap_true ) + }{ lv_sub_hint } in other packages. { render_filter_help_hint( ) }| ). + + ENDMETHOD. + METHOD run_where_used. + mt_where_used = zcl_abapgit_where_used_tools=>new( )->select_external_usages( + iv_ignore_subpackages = mv_ignore_subpackages + iv_package = mv_package ). + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + IF mi_table->process_sorting_request( ii_event->mv_action ) = abap_true. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + RETURN. + ENDIF. + + CASE ii_event->mv_action. + WHEN c_action-refresh. + run_where_used( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-show_used_obj. + mv_show_used_obj = boolc( mv_show_used_obj = abap_false ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-show_root_pkg. + mv_show_root_pkg = boolc( mv_show_root_pkg = abap_false ). + CLEAR mi_table. " To reinit structure + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + rt_hotkey_actions = zif_abapgit_gui_menu_provider~get_menu( )->get_hotkeys( c_title ). + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + DATA lv_show_used_txt TYPE string. + DATA lv_show_root_txt TYPE string. + + IF mv_show_used_obj = abap_true. + lv_show_used_txt = 'Hide Used Type'. + ELSE. + lv_show_used_txt = 'Show Used Type'. + ENDIF. + + IF mv_show_root_pkg = abap_true. + lv_show_root_txt = 'Show parent package'. + ELSE. + lv_show_root_txt = 'Show root package'. + ENDIF. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-where-used' + )->add( + iv_txt = lv_show_root_txt + iv_title = 'Show root package or direct parent package' + iv_act = c_action-show_root_pkg + iv_hotkey = 'p' + )->add( + iv_txt = lv_show_used_txt + iv_title = 'Show/Hide used type or object (when available)' + iv_act = c_action-show_used_obj + iv_hotkey = 'u' + )->add( + iv_txt = 'Refresh' + iv_act = c_action-refresh + iv_hotkey = 'r' + )->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD zif_abapgit_gui_page_title~get_page_title. + rv_title = c_title. + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + init_table_component( ). + + ri_html = zcl_abapgit_html=>create( ). + + render_header( ri_html ). + + IF mt_where_used IS INITIAL. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_success( 'No usages found' ) ). + ELSE. + ri_html->div( + iv_class = 'wu' + ii_content = mi_table->render( + iv_wrap_in_div = 'default-table-container' + iv_css_class = 'default-table' + iv_with_cids = abap_true + it_data = mt_where_used ) ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_html_table~get_row_attrs. + ENDMETHOD. + METHOD zif_abapgit_html_table~render_cell. + + FIELD-SYMBOLS TYPE zcl_abapgit_where_used_tools=>ty_dependency. + + ASSIGN is_row TO . + + CASE iv_column_id. + WHEN 'dep_obj_name'. + rs_render-content = -dep_obj_name. + IF mv_show_used_obj = abap_true. + rs_render-content = rs_render-content && |{ -dep_used_obj }|. + ENDIF. + WHEN 'obj_type'. + IF -obj_prog_type IS INITIAL. + rs_render-content = -obj_type. + ELSE. + rs_render-content = -obj_type && ':' && -obj_prog_type. + ENDIF. + WHEN 'obj_name'. + rs_render-content = zcl_abapgit_gui_chunk_lib=>get_item_link( + iv_obj_type = -obj_type + iv_obj_name = -obj_name ). + WHEN OTHERS. + rs_render-content = iv_value. + ENDCASE. + " TODO maybe add title for object cls ? + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_syntax IMPLEMENTATION. + METHOD constructor. + super->constructor( ). + mi_repo = ii_repo. + run_syntax_check( ). + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_syntax. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( lo_component ). + + ENDMETHOD. + METHOD run_syntax_check. + + DATA: li_syntax_check TYPE REF TO zif_abapgit_code_inspector. + + li_syntax_check = zcl_abapgit_code_inspector=>get_code_inspector( mi_repo->get_package( ) ). + + TRY. + mt_result = li_syntax_check->run( c_variant ). + CATCH zcx_abapgit_exception. + " Variant SYNTAX_CHECK does not exist in 702 + mt_result = li_syntax_check->run( 'VERI_' && c_variant ). + ENDTRY. + + mv_summary = li_syntax_check->get_summary( ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + CASE ii_event->mv_action. + WHEN c_actions-rerun. + + run_syntax_check( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN OTHERS. + rs_handled = on_event( ii_event ). + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + + ls_hotkey_action-ui_component = 'Syntax Check'. + + ls_hotkey_action-description = |Re-Run|. + ls_hotkey_action-action = c_actions-rerun. + ls_hotkey_action-hotkey = |r|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = build_base_menu( ). + + ro_toolbar->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD zif_abapgit_gui_page_title~get_page_title. + rv_title = 'Syntax Check'. + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->div( + iv_class = 'repo' + ii_content = zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + iv_show_commit = abap_false ) ). + + render_ci_report( + ii_html = ri_html + iv_variant = c_variant + iv_success_msg = 'No syntax errors' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_runit IMPLEMENTATION. + METHOD build_tadir. + + DATA lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA ls_tadir LIKE LINE OF lt_tadir. + DATA ls_row LIKE LINE OF rt_tadir. + + lt_tadir = mi_repo->get_tadir_objects( ). + + LOOP AT lt_tadir INTO ls_tadir. + CLEAR ls_row. + ls_row-obj_type = ls_tadir-object. + ls_row-obj_name = ls_tadir-obj_name. + APPEND ls_row TO rt_tadir. + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + mi_repo = ii_repo. + + TRY. + CALL METHOD ('\PROGRAM=SAPLSAUCV_GUI_RUNNER\CLASS=PASSPORT')=>get. + CATCH cx_root. + zcx_abapgit_exception=>raise( |Not supported in your NW release| ). + ENDTRY. + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_runit. + + TRY. + CREATE OBJECT lo_component EXPORTING ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = |Unit Tests| + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + CATCH zcx_abapgit_exception. + + " Fallback as either SAPLSAUCV_GUI_RUNNER is not available in old releases + " or passport=>get is private in newer releases NW >= 756 + ri_page = zcl_abapgit_gui_page_code_insp=>create( + ii_repo = ii_repo + iv_check_variant = 'SWF_ABAP_UNIT' ). + + ENDTRY. + + ENDMETHOD. + METHOD get_text_for_method. + + DATA lv_params TYPE string. + DATA lv_runtime TYPE timestampl. + DATA lv_msec TYPE string. + + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE string_table. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE timestampl. + FIELD-SYMBOLS TYPE timestampl. + + READ TABLE it_indices WITH KEY + ('PROGRAM_NDX') = iv_program_ndx + ('CLASS_NDX') = iv_class_ndx + ('METHOD_NDX') = iv_method_ndx + ASSIGNING . + IF sy-subrc = 0. + ASSIGN COMPONENT 'ALERTS' OF STRUCTURE TO . + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'HEADER-PARAMS' OF STRUCTURE TO . + LOOP AT INTO lv_params. + rv_text = lv_params. + ENDLOOP. + ENDLOOP. + ENDIF. + + CLEAR: lv_msec, lv_runtime. + ASSIGN COMPONENT 'INFO-START_ON' OF STRUCTURE is_method TO . + IF sy-subrc = 0. + ASSIGN COMPONENT 'INFO-END_ON' OF STRUCTURE is_method TO . + IF sy-subrc = 0. + TRY. + lv_runtime = cl_abap_tstmp=>subtract( + tstmp1 = + tstmp2 = ) * 1000. + lv_msec = |{ lv_runtime DECIMALS = 0 } ms|. + CATCH cx_parameter_invalid ##NO_HANDLER. "ignore + ENDTRY. + ENDIF. + ENDIF. + + IF rv_text IS INITIAL. + rv_text = |PASSED|. + IF lv_runtime > 100. + rv_text = rv_text && | { lv_msec }|. + ELSE. + rv_text = rv_text && | { lv_msec }|. + ENDIF. + ELSE. + rv_text = |{ rv_text }|. + ENDIF. + + ASSIGN COMPONENT 'INFO-NAME' OF STRUCTURE is_method TO . + rv_text = |        { }{ rv_text }|. + + ENDMETHOD. + METHOD run. + + DATA lo_passport TYPE REF TO object. + DATA lo_runner TYPE REF TO object. + DATA lo_timer TYPE REF TO zcl_abapgit_timer. + DATA lt_keys TYPE ty_keys_tt. + DATA li_result TYPE REF TO data. + FIELD-SYMBOLS TYPE any. + + lt_keys = build_tadir( ). + + lo_timer = zcl_abapgit_timer=>create( iv_count = lines( lt_keys ) )->start( ). + + TRY. + CALL METHOD ('\PROGRAM=SAPLSAUCV_GUI_RUNNER\CLASS=PASSPORT')=>get + RECEIVING + result = lo_passport. + + CALL METHOD ('CL_AUCV_TEST_RUNNER_STANDARD')=>create + EXPORTING + i_passport = lo_passport + RECEIVING + result = lo_runner. + CATCH cx_root. + zcx_abapgit_exception=>raise( |Not supported in your NW release| ). + ENDTRY. + + CREATE DATA li_result TYPE REF TO ('IF_SAUNIT_INTERNAL_RESULT'). + ASSIGN li_result->* TO . + + CALL METHOD lo_runner->('RUN_FOR_PROGRAM_KEYS') + EXPORTING + i_limit_on_duration_category = '36' " long + i_limit_on_risk_level = '33' " critical + i_program_keys = lt_keys + IMPORTING + e_aunit_result = . + + mv_summary = lo_timer->end( ). + + ro_result = . + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + CASE ii_event->mv_action. + WHEN c_actions-rerun. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN OTHERS. + ASSERT 1 = 1. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-unit-tests' ). + + ro_toolbar->add( + iv_txt = 'Re-Run' + iv_act = c_actions-rerun + iv_cur = abap_false ). + + ro_toolbar->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA lo_result TYPE REF TO object. + DATA lv_program_ndx TYPE i. + DATA lv_class_ndx TYPE i. + DATA lv_text TYPE string. + DATA lv_count TYPE i. + DATA lv_params TYPE string. + DATA ls_item TYPE zif_abapgit_definitions=>ty_repo_item. + + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE string_table. + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '
    ' ). + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( ii_repo = mi_repo + iv_show_commit = abap_false ) ). + + lo_result = run( ). + + ASSIGN lo_result->('F_TASK_DATA') TO . + ASSIGN COMPONENT 'ALERTS_BY_INDICIES' OF STRUCTURE TO . + ASSIGN COMPONENT 'PROGRAMS' OF STRUCTURE TO . + + IF IS INITIAL. + ri_html->add( '
    ' ). + ri_html->add( 'No unit tests found' ). + ri_html->add( '
    ' ). + RETURN. + ENDIF. + + ri_html->add( || ). + + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'ALERTS' OF STRUCTURE TO . + LOOP AT ASSIGNING WHERE ('KIND = ''F'' OR KIND = ''S'' OR KIND = ''E'' OR KIND = ''W'''). + CLEAR lv_text. + ASSIGN COMPONENT 'HEADER-PARAMS' OF STRUCTURE TO . + LOOP AT INTO lv_params. + lv_text = lv_text && lv_params. + ENDLOOP. + + ASSIGN COMPONENT 'TEXT_INFOS' OF STRUCTURE TO . + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'PARAMS' OF STRUCTURE TO . + LOOP AT INTO lv_params. + lv_text = lv_text && lv_params. + ENDLOOP. + ENDLOOP. + IF lv_text NP '*SAUNIT_NO_TEST_CLASS*'. + ri_html->add( || ). + lv_count = lv_count + 1. + ENDIF. + ENDLOOP. + ENDLOOP. + + ri_html->add( '
    { lv_text }
    ' ). + + ri_html->add( '
    ' ). + ri_html->add( |Unit tests completed with { lv_count } errors ({ mv_summary })| ). + ri_html->add( '
    ' ). + + ri_html->add( |
    | ). + + LOOP AT ASSIGNING . + CLEAR ls_item. + lv_program_ndx = sy-tabix. + + ASSIGN COMPONENT 'INFO-KEY-OBJ_TYPE' OF STRUCTURE TO . + IF sy-subrc = 0. + ls_item-obj_type = . + ASSIGN COMPONENT 'INFO-KEY-OBJ_NAME' OF STRUCTURE TO . + ls_item-obj_name = . + ri_html->add( || ). + ELSE. + " KEY field does not exist in 750 + ASSIGN COMPONENT 'INFO-NAME' OF STRUCTURE TO . + ri_html->add( || ). + ENDIF. + + ASSIGN COMPONENT 'CLASSES' OF STRUCTURE TO . + + LOOP AT ASSIGNING . + lv_class_ndx = sy-tabix. + + ASSIGN COMPONENT 'INFO-NAME' OF STRUCTURE TO . + ri_html->add( || ). + ASSIGN COMPONENT 'METHODS' OF STRUCTURE TO . + + LOOP AT ASSIGNING . + + ri_html->add( get_text_for_method( + is_method = + it_indices = + iv_program_ndx = lv_program_ndx + iv_class_ndx = lv_class_ndx + iv_method_ndx = sy-tabix ) ). + + ENDLOOP. + ENDLOOP. + ENDLOOP. + + ri_html->add( '
    { zcl_abapgit_gui_chunk_lib=>get_item_icon( ls_item ) } { ls_item-obj_type }| + && | { zcl_abapgit_gui_chunk_lib=>get_item_link( ls_item ) }
    { }
        { }
    ' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_codi_base IMPLEMENTATION. + METHOD apply_filter_kind. + + CASE mv_filter_kind. + WHEN 'error'. + DELETE ct_view WHERE kind <> 'E'. + WHEN 'warn'. + DELETE ct_view WHERE kind <> 'W'. + WHEN 'info'. + DELETE ct_view WHERE NOT ( kind = 'E' OR kind = 'W' ). + WHEN OTHERS. + RETURN. + ENDCASE. + + ENDMETHOD. + METHOD apply_sorting. + + DATA lv_field TYPE abap_compname. + + CASE ms_sorting_state-column_id. + WHEN 'kind' OR 'obj_type' OR 'location' OR 'text' OR 'author'. + lv_field = to_upper( ms_sorting_state-column_id ). + WHEN OTHERS. + RETURN. + ENDCASE. + + IF ms_sorting_state-descending = abap_true. + SORT ct_view BY (lv_field) DESCENDING. + ELSE. + SORT ct_view BY (lv_field) ASCENDING. + ENDIF. + + ENDMETHOD. + METHOD build_base_menu. + + ro_menu = zcl_abapgit_html_toolbar=>create( 'toolbar-code-inspector' )->add( + iv_txt = 'Re-Run' + iv_act = c_actions-rerun ). + + ENDMETHOD. + METHOD build_nav_link. + + rv_link = |{ c_ci_sig }| && + |{ is_result-objtype }{ is_result-objname }| && + |{ c_object_separator }{ is_result-sobjtype }{ is_result-sobjname }| && + |{ c_object_separator }{ is_result-line }|. + + ENDMETHOD. + METHOD convert_result_to_view. + + FIELD-SYMBOLS LIKE LINE OF it_result. + FIELD-SYMBOLS LIKE LINE OF rt_view. + DATA lv_line TYPE i. + + LOOP AT it_result ASSIGNING . + APPEND INITIAL LINE TO rt_view ASSIGNING . + -kind = -kind. + -obj_type = -objtype. + -nav = build_nav_link( ). + -text = -text. + -author = -author. + + IF -sobjname IS INITIAL OR + ( -sobjname = -objname AND + -sobjtype = -objtype ). + -location = to_lower( -objname ). + ELSEIF -objtype = 'CLAS' OR + ( -objtype = 'PROG' AND NOT -sobjname+30(*) IS INITIAL ). + -location = explain_include( ). + ENDIF. + + IF -location IS INITIAL. " Fallback to a reasonable default + -location = to_lower( |{ -objname } > { -sobjtype } { -sobjname }| ). + ENDIF. + + lv_line = -line. " convert from numc to integer + -location = |{ -location } @{ lv_line }|. + + ENDLOOP. + + ENDMETHOD. + METHOD explain_include. + + DATA ls_mtdkey TYPE seocpdkey. + + TRY. + CASE is_result-sobjname+30(*). + WHEN 'CCDEF'. + rv_txt = |{ to_lower( is_result-objname ) }: Local Definitions|. + WHEN 'CCIMP'. + rv_txt = |{ to_lower( is_result-objname ) }: Local Implementations|. + WHEN 'CCMAC'. + rv_txt = |{ to_lower( is_result-objname ) }: Macros|. + WHEN 'CCAU'. + rv_txt = |{ to_lower( is_result-objname ) }: Test Classes|. + WHEN 'CU'. + rv_txt = |{ to_lower( is_result-objname ) }: Public Section|. + WHEN 'CO'. + rv_txt = |{ to_lower( is_result-objname ) }: Protected Section|. + WHEN 'CI'. + rv_txt = |{ to_lower( is_result-objname ) }: Private Section|. + WHEN OTHERS. + cl_oo_classname_service=>get_method_by_include( + EXPORTING + incname = is_result-sobjname + RECEIVING + mtdkey = ls_mtdkey + EXCEPTIONS + class_not_existing = 1 + method_not_existing = 2 + OTHERS = 3 ). + IF sy-subrc = 0. + rv_txt = to_lower( |{ ls_mtdkey-clsname }->{ ls_mtdkey-cpdname }| ). + ELSE. + rv_txt = to_lower( |{ is_result-sobjname }| ). + ENDIF. + + ENDCASE. + CATCH cx_root ##NO_HANDLER. + " leave empty, fallback to default, defined elsewhere + ENDTRY. + + ENDMETHOD. + METHOD handle_navigation. + + DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, + ls_sub_item TYPE zif_abapgit_definitions=>ty_item, + lv_main_object TYPE string, + lv_sub_object TYPE string, + lv_line_number_s TYPE string, + lv_line_number TYPE i. + + SPLIT iv_link AT c_object_separator INTO lv_main_object lv_sub_object lv_line_number_s. + ls_item-obj_type = to_upper( lv_main_object(4) ). + ls_item-obj_name = to_upper( lv_main_object+4(*) ). + + IF lv_sub_object IS NOT INITIAL. + ls_sub_item-obj_type = to_upper( lv_sub_object(4) ). + ls_sub_item-obj_name = to_upper( lv_sub_object+4(*) ). + ENDIF. + + lv_line_number = lv_line_number_s. + + jump( + is_item = ls_item + is_sub_item = ls_sub_item + iv_line_number = lv_line_number ). + + ENDMETHOD. + METHOD jump. + + DATA: lo_test TYPE REF TO cl_ci_test_root, + ls_info TYPE scir_rest, + lo_result TYPE REF TO cl_ci_result_root, + lv_adt_jump_enabled TYPE abap_bool, + lv_line_number TYPE i, + ls_item TYPE zif_abapgit_definitions=>ty_item, + ls_sub_item TYPE zif_abapgit_definitions=>ty_item. + + FIELD-SYMBOLS: LIKE LINE OF mt_result. + IF is_sub_item IS NOT INITIAL. + READ TABLE mt_result WITH KEY objtype = is_item-obj_type + objname = is_item-obj_name + sobjtype = is_sub_item-obj_type + sobjname = is_sub_item-obj_name + line = iv_line_number + ASSIGNING . + ELSE. + READ TABLE mt_result WITH KEY objtype = is_item-obj_type + objname = is_item-obj_name + line = iv_line_number + ASSIGNING . + ENDIF. + ASSERT IS ASSIGNED. + ls_item-obj_name = -objname. + ls_item-obj_type = -objtype. + + ls_sub_item-obj_name = -sobjname. + ls_sub_item-obj_type = -sobjtype. + + " see SCI_LCL_DYNP_530 / HANDLE_DOUBLE_CLICK + + lv_adt_jump_enabled = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_adt_jump_enabled( ). + + TRY. + IF lv_adt_jump_enabled = abap_true. + + lv_line_number = -line. + + zcl_abapgit_objects=>jump( + is_item = ls_item + is_sub_item = ls_sub_item + iv_line_number = lv_line_number ). + RETURN. + + ENDIF. + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + TRY. + CALL METHOD ('CL_CI_TESTS')=>('GET_TEST_REF') + EXPORTING + p_test = -test + RECEIVING + p_result = lo_test. + CATCH cx_root. + zcx_abapgit_exception=>raise( |Jump to object not supported in your NW release| ). + ENDTRY. + + lo_result = lo_test->get_result_node( -kind ). + + MOVE-CORRESPONDING TO ls_info. + + lo_result->set_info( ls_info ). + lo_result->if_ci_test~navigate( ). + + ENDMETHOD. + METHOD on_event. + + DATA lv_temp TYPE string. + DATA ls_sorting_req TYPE zif_abapgit_html_table=>ty_sorting_state. + + lv_temp = replace( + val = ii_event->mv_action + regex = |^{ c_ci_sig }| + with = `` ). + + IF lv_temp <> ii_event->mv_action. " CI navigation request detected + handle_navigation( lv_temp ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDIF. + + ls_sorting_req = zcl_abapgit_html_table=>detect_sorting_request( ii_event->mv_action ). + IF ls_sorting_req IS NOT INITIAL. + ms_sorting_state = ls_sorting_req. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + + IF ii_event->mv_action = c_actions-filter_kind. + mv_filter_kind = ii_event->query( )->get( 'kind' ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDIF. + + ENDMETHOD. + METHOD render_ci_report. + + ii_html->add( '
    ' ). + + render_head( + ii_html = ii_html + iv_variant = iv_variant + iv_summary = mv_summary ). + + IF lines( mt_result ) = 0. + ii_html->add( zcl_abapgit_gui_chunk_lib=>render_success( iv_success_msg ) ). + ELSE. + render_stats( + ii_html = ii_html + it_result = mt_result ). + render_detail( + ii_html = ii_html + it_result = mt_result ). + ENDIF. + + ii_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_detail. + + DATA li_table TYPE REF TO zcl_abapgit_html_table. + DATA lt_view TYPE ty_view_tab. + + li_table = zcl_abapgit_html_table=>create( + )->define_column( + iv_column_id = 'kind' + iv_column_title = zcl_abapgit_html=>icon( 'exclamation-circle' ) + )->define_column( + iv_column_id = 'obj_type' + iv_column_title = 'Type' + )->define_column( + iv_column_id = 'location' + iv_column_title = 'Obj. name / location' + )->define_column( + iv_column_id = 'author' + iv_column_title = 'Changed by' + )->define_column( + iv_column_id = 'text' + iv_column_title = 'Text' ). + + lt_view = convert_result_to_view( it_result ). + + IF ms_sorting_state-column_id IS INITIAL. + ms_sorting_state-column_id = 'kind'. + ENDIF. + + apply_sorting( CHANGING ct_view = lt_view ). + apply_filter_kind( CHANGING ct_view = lt_view ). + + ii_html->div( + iv_class = 'ci-detail' + ii_content = li_table->render( + ii_renderer = me + is_sorting_state = ms_sorting_state + iv_wrap_in_div = 'default-table-container' + iv_css_class = 'default-table' + iv_with_cids = abap_true + it_data = lt_view ) ). + + IF lines( it_result ) > c_limit. + render_limit_warning( ii_html ). + ENDIF. + + ENDMETHOD. + METHOD render_head. + + ii_html->div( + iv_class = 'ci-msg' + iv_content = + |Code inspector check variant { + iv_variant } completed ({ iv_summary })| ). + + ENDMETHOD. + METHOD render_limit_warning. + ii_html->add( '
    ' ). + ii_html->add( ii_html->icon( 'exclamation-triangle' ) ). + ii_html->add( |Only first { c_limit } findings shown in list!| ). + ii_html->add( '
    ' ). + ENDMETHOD. + METHOD render_stat. + + DATA lv_txt TYPE string. + + lv_txt = |{ iv_count } { iv_title }|. + + IF iv_type <> mv_filter_kind. + lv_txt = ii_html->a( + iv_txt = lv_txt + iv_act = |{ c_actions-filter_kind }?kind={ iv_type }| + iv_typ = zif_abapgit_html=>c_action_type-sapevent ). + ENDIF. + + ii_html->add( |{ lv_txt }| ). + + ENDMETHOD. + METHOD render_stats. + + FIELD-SYMBOLS LIKE LINE OF it_result. + + DATA lv_errors TYPE i. + DATA lv_warnings TYPE i. + DATA lv_infos TYPE i. + + IF mv_filter_kind IS INITIAL. + mv_filter_kind = 'all'. + ENDIF. + + LOOP AT it_result ASSIGNING . + CASE -kind. + WHEN 'E'. + lv_errors = lv_errors + 1. + WHEN 'W'. + lv_warnings = lv_warnings + 1. + WHEN OTHERS. + lv_infos = lv_infos + 1. + ENDCASE. + ENDLOOP. + + ii_html->add( '
    ' ). + + IF lv_errors > 0. + render_stat( + ii_html = ii_html + iv_count = lv_errors + iv_type = 'error' + iv_title = 'errors' ). + ENDIF. + IF lv_warnings > 0. + render_stat( + ii_html = ii_html + iv_count = lv_warnings + iv_type = 'warn' + iv_title = 'warnings' ). + ENDIF. + IF lv_infos > 0. + render_stat( + ii_html = ii_html + iv_count = lv_infos + iv_type = 'info' + iv_title = 'infos' ). + ENDIF. + render_stat( + ii_html = ii_html + iv_count = lv_infos + lv_errors + lv_warnings + iv_type = 'all' + iv_title = 'all' ). + + ii_html->add( '
    ' ). + + ENDMETHOD. + METHOD zif_abapgit_html_table~get_row_attrs. + + FIELD-SYMBOLS TYPE ty_result_view. + + ASSIGN is_row TO . + rs_attrs-data-name = 'kind'. + + CASE -kind. + WHEN 'E'. + rs_attrs-data-value = 'error'. + WHEN 'W'. + rs_attrs-data-value = 'warning'. + WHEN OTHERS. + rs_attrs-data-value = 'info'. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_html_table~render_cell. + + FIELD-SYMBOLS TYPE ty_result_view. + + ASSIGN is_row TO . + + CASE iv_column_id. + WHEN 'kind'. + rs_render-content = |{ -kind }|. + WHEN 'obj_type'. + rs_render-content = -obj_type. + WHEN 'location'. + rs_render-content = zcl_abapgit_html=>create( )->a( + iv_txt = -location + iv_act = -nav + iv_typ = zif_abapgit_html=>c_action_type-sapevent ). + WHEN 'author'. + rs_render-content = zcl_abapgit_gui_chunk_lib=>render_user_name( |{ -author }| )->render( ). + WHEN 'text'. + rs_render-content = escape( + val = -text + format = cl_abap_format=>e_html_attr ). + ENDCASE. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_code_insp IMPLEMENTATION. + METHOD ask_user_for_check_variant. + + rv_check_variant = zcl_abapgit_ui_factory=>get_popups( )->choose_code_insp_check_variant( ). + + IF rv_check_variant IS INITIAL. + zcx_abapgit_exception=>raise( |Please select a check variant.| ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + mi_repo = ii_repo. + mo_stage = io_stage. + mv_check_variant = iv_check_variant. + determine_check_variant( ). + run_code_inspector( ). + + IF mt_result IS INITIAL AND iv_raise_when_no_results = abap_true. + zcx_abapgit_exception=>raise( 'No results' ). + ENDIF. + + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_code_insp. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo + io_stage = io_stage + iv_check_variant = iv_check_variant + iv_raise_when_no_results = iv_raise_when_no_results. + + ri_page = zcl_abapgit_gui_page_hoc=>create( lo_component ). + + ENDMETHOD. + METHOD determine_check_variant. + + IF mv_check_variant IS NOT INITIAL. + RETURN. + ENDIF. + + mv_check_variant = mi_repo->get_local_settings( )-code_inspector_check_variant. + + IF mv_check_variant IS INITIAL. + mv_check_variant = ask_user_for_check_variant( ). + ENDIF. + + ENDMETHOD. + METHOD has_inspection_errors. + + READ TABLE mt_result TRANSPORTING NO FIELDS WITH KEY kind = 'E'. + rv_has_inspection_errors = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD is_stage_allowed. + + rv_is_stage_allowed = boolc( NOT ( + mi_repo->get_local_settings( )-block_commit = abap_true AND has_inspection_errors( ) = abap_true ) ). + + ENDMETHOD. + METHOD run_code_inspector. + + DATA li_code_inspector TYPE REF TO zif_abapgit_code_inspector. + + li_code_inspector = zcl_abapgit_code_inspector=>get_code_inspector( mi_repo->get_package( ) ). + + mt_result = li_code_inspector->run( + iv_variant = |{ mv_check_variant }| + iv_save = abap_true ). + + mv_summary = li_code_inspector->get_summary( ). + + DELETE mt_result WHERE kind = 'N'. + + ENDMETHOD. + METHOD status. + + READ TABLE mt_result TRANSPORTING NO FIELDS WITH KEY kind = 'E'. + IF sy-subrc = 0. + rv_status = zif_abapgit_definitions=>c_sci_result-failed. + ELSE. + READ TABLE mt_result TRANSPORTING NO FIELDS WITH KEY kind = 'W'. + IF sy-subrc = 0. + rv_status = zif_abapgit_definitions=>c_sci_result-warning. + ELSE. + rv_status = zif_abapgit_definitions=>c_sci_result-passed. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + + CASE ii_event->mv_action. + WHEN c_actions-stage. + + li_repo_online ?= mi_repo. + + IF is_stage_allowed( ) = abap_true. + + rs_handled-page = zcl_abapgit_gui_page_stage=>create( + ii_repo_online = li_repo_online + iv_sci_result = status( ) ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + ELSE. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + ENDIF. + + WHEN c_actions-commit. + + li_repo_online ?= mi_repo. + + IF is_stage_allowed( ) = abap_true. + + rs_handled-page = zcl_abapgit_gui_page_commit=>create( + ii_repo_online = li_repo_online + io_stage = mo_stage ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + ELSE. + + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + ENDIF. + + WHEN c_actions-rerun. + + run_code_inspector( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + + WHEN OTHERS. + rs_handled = on_event( ii_event ). + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + + ls_hotkey_action-ui_component = 'Code Inspector'. + + ls_hotkey_action-description = |Stage|. + ls_hotkey_action-action = c_actions-stage. + ls_hotkey_action-hotkey = |s|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ls_hotkey_action-description = |Re-Run|. + ls_hotkey_action-action = c_actions-rerun. + ls_hotkey_action-hotkey = |r|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + DATA: lv_opt TYPE c LENGTH 1. + + ro_toolbar = build_base_menu( ). + + IF is_stage_allowed( ) = abap_false. + lv_opt = zif_abapgit_html=>c_html_opt-crossout. + ENDIF. + + IF mi_repo->is_offline( ) = abap_true. + RETURN. + ENDIF. + + IF mo_stage IS BOUND. + + " Staging info already available, we can directly + " offer to commit + + ro_toolbar->add( + iv_txt = 'Commit' + iv_act = c_actions-commit + iv_opt = lv_opt ). + + ELSE. + + ro_toolbar->add( + iv_txt = 'Stage' + iv_act = c_actions-stage + iv_opt = lv_opt ). + + ENDIF. + + ro_toolbar->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD zif_abapgit_gui_page_title~get_page_title. + rv_title = 'Code Inspector'. + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->div( + iv_class = 'repo' + ii_content = zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mi_repo + iv_show_commit = abap_false ) ). + + IF mv_check_variant IS INITIAL. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_error( iv_error = 'No check variant supplied.' ) ). + RETURN. + ENDIF. + + render_ci_report( + ii_html = ri_html + iv_variant = mv_check_variant + iv_success_msg = 'No code inspector findings' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_log_viewer IMPLEMENTATION. + METHOD calculate_cell_type. + + FIELD-SYMBOLS: LIKE LINE OF gt_log. + DATA: ls_cell_type LIKE LINE OF -cell_type. + + LOOP AT gt_log ASSIGNING . + + IF -longtext IS NOT INITIAL. + ls_cell_type-columnname = `LONGTEXT`. + ls_cell_type-value = if_salv_c_cell_type=>hotspot. + INSERT ls_cell_type INTO TABLE -cell_type. + ENDIF. + + IF -t100 IS NOT INITIAL. + ls_cell_type-columnname = `T100`. + ls_cell_type-value = if_salv_c_cell_type=>hotspot. + INSERT ls_cell_type INTO TABLE -cell_type. + ENDIF. + + IF -source IS NOT INITIAL. + ls_cell_type-columnname = `SOURCE`. + ls_cell_type-value = if_salv_c_cell_type=>hotspot. + INSERT ls_cell_type INTO TABLE -cell_type. + ENDIF. + + IF -callstack IS NOT INITIAL. + ls_cell_type-columnname = `CALLSTACK`. + ls_cell_type-value = if_salv_c_cell_type=>hotspot. + INSERT ls_cell_type INTO TABLE -cell_type. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD dispatch. + + CASE iv_column. + WHEN `LONGTEXT`. + + show_longtext( is_log ). + + WHEN `T100`. + + goto_t100_message( is_log ). + + WHEN `SOURCE`. + + goto_source( is_log ). + + WHEN `CALLSTACK`. + + goto_callstack( is_log ). + + ENDCASE. + + ENDMETHOD. + METHOD get_exception_viewer. + + DATA: + lx_abapgit TYPE REF TO zcx_abapgit_exception. + + ASSERT is_log-exception IS BOUND. + lx_abapgit ?= is_log-exception. + + CREATE OBJECT ro_exception_viewer + EXPORTING + ix_error = lx_abapgit. + + ENDMETHOD. + METHOD goto_callstack. + + get_exception_viewer( is_log )->show_callstack( ). + + ENDMETHOD. + METHOD goto_source. + + get_exception_viewer( is_log )->goto_source( ). + + ENDMETHOD. + METHOD goto_t100_message. + + get_exception_viewer( is_log )->goto_message( ). + + ENDMETHOD. + METHOD on_link_click. + + DATA: lx_error TYPE REF TO zcx_abapgit_exception. + FIELD-SYMBOLS: TYPE ty_log_out. + + IF row IS INITIAL + OR column IS INITIAL. + RETURN. + ENDIF. + + READ TABLE gt_log ASSIGNING + INDEX row. + ASSERT sy-subrc = 0. + + TRY. + dispatch( + is_log = + iv_column = column ). + + CATCH zcx_abapgit_exception INTO lx_error. + MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. + ENDTRY. + + ENDMETHOD. + METHOD prepare_log_for_display. + + DATA: lt_message TYPE zif_abapgit_log=>ty_log_outs, + lr_message TYPE REF TO zif_abapgit_log=>ty_log_out, + ls_log TYPE ty_log_out, + li_t100_message TYPE REF TO if_t100_message, + lx_abapgit TYPE REF TO zcx_abapgit_exception. + + lt_message = ii_log->get_messages( ). + + LOOP AT lt_message REFERENCE INTO lr_message. + + CLEAR: ls_log. + + ls_log-msg = lr_message->text. + ls_log-exception = lr_message->exception. + + CASE lr_message->type. + WHEN 'E' OR 'A' OR 'X'. + ls_log-type = icon_led_red. + WHEN 'W'. + ls_log-type = icon_led_yellow. + WHEN 'I' OR 'S'. + ls_log-type = icon_led_green. + WHEN OTHERS. + ls_log-type = icon_led_inactive. + ENDCASE. + + IF lr_message->exception IS BOUND. + + TRY. + li_t100_message ?= lr_message->exception. + + IF li_t100_message->t100key IS NOT INITIAL. + ls_log-t100 = icon_message_information. + ENDIF. + + CATCH cx_sy_move_cast_error ##NO_HANDLER. + ENDTRY. + + TRY. + lx_abapgit ?= lr_message->exception. + + IF lx_abapgit->mt_callstack IS NOT INITIAL. + ls_log-longtext = icon_system_help. + ls_log-callstack = icon_stack. + ls_log-source = icon_abap. + ENDIF. + + CATCH cx_sy_move_cast_error ##NO_HANDLER. + ENDTRY. + + ELSEIF lr_message->id IS NOT INITIAL AND lr_message->number IS NOT INITIAL. + ls_log-id = lr_message->id. + ls_log-number = lr_message->number. + ls_log-longtext = icon_system_help. + ENDIF. + + ls_log-obj_type = lr_message->obj_type. + ls_log-obj_name = lr_message->obj_name. + + INSERT ls_log INTO TABLE rt_log_out. + + ENDLOOP. + + ENDMETHOD. + METHOD show_log. + + DATA: lr_log TYPE REF TO ty_log_out, + lo_alv TYPE REF TO cl_salv_table, + lx_error TYPE REF TO cx_salv_error, + lo_form_header TYPE REF TO cl_salv_form_header_info, + lo_columns TYPE REF TO cl_salv_columns_table, + lo_column TYPE REF TO cl_salv_column, + lo_functions TYPE REF TO cl_salv_functions_list, + ls_position TYPE zif_abapgit_popups=>ty_popup_position, + lv_add_obj_col TYPE abap_bool, + lo_event TYPE REF TO cl_salv_events_table. + + gt_log = prepare_log_for_display( ii_log ). + + "check if log contains any object info + LOOP AT gt_log REFERENCE INTO lr_log. + IF lr_log->obj_type IS NOT INITIAL OR lr_log->obj_name IS NOT INITIAL. + lv_add_obj_col = abap_true. + ENDIF. + ENDLOOP. + + TRY. + cl_salv_table=>factory( + IMPORTING + r_salv_table = lo_alv + CHANGING + t_table = gt_log ). + + lo_functions = lo_alv->get_functions( ). + lo_functions->set_all( ). + + lo_alv->get_display_settings( )->set_list_header( |abapGit Log Viewer| ). + + lo_columns = lo_alv->get_columns( ). + + lo_columns->set_optimize( ). + lo_columns->set_cell_type_column( |CELL_TYPE| ). + + calculate_cell_type( ). + + lo_column = lo_columns->get_column( |TYPE| ). + lo_column->set_medium_text( |Type| ). + + lo_column = lo_columns->get_column( |MSG| ). + lo_column->set_medium_text( |Message| ). + + lo_column = lo_columns->get_column( |LONGTEXT| ). + lo_column->set_medium_text( |Longtext| ). + + lo_column = lo_columns->get_column( |T100| ). + lo_column->set_medium_text( |Goto message| ). + + lo_column = lo_columns->get_column( |SOURCE| ). + lo_column->set_medium_text( |Goto source| ). + + lo_column = lo_columns->get_column( |CALLSTACK| ). + lo_column->set_medium_text( |Show callstack| ). + + IF lv_add_obj_col = abap_true. + lo_column = lo_columns->get_column( |OBJ_TYPE| ). + lo_column->set_medium_text( |Object Type| ). + + lo_column = lo_columns->get_column( |OBJ_NAME| ). + lo_column->set_medium_text( |Object Name| ). + ELSE. + "hide object columns + lo_column = lo_columns->get_column( |OBJ_TYPE| ). + lo_column->set_technical( abap_true ). + + lo_column = lo_columns->get_column( |OBJ_NAME| ). + lo_column->set_technical( abap_true ). + ENDIF. + + "hide empty columns + LOOP AT gt_log TRANSPORTING NO FIELDS WHERE t100 IS NOT INITIAL. + EXIT. + ENDLOOP. + IF sy-subrc <> 0. + lo_column = lo_columns->get_column( |T100| ). + lo_column->set_technical( abap_true ). + ENDIF. + + LOOP AT gt_log TRANSPORTING NO FIELDS WHERE source IS NOT INITIAL. + EXIT. + ENDLOOP. + IF sy-subrc <> 0. + lo_column = lo_columns->get_column( |SOURCE| ). + lo_column->set_technical( abap_true ). + ENDIF. + + LOOP AT gt_log TRANSPORTING NO FIELDS WHERE longtext IS NOT INITIAL. + EXIT. + ENDLOOP. + IF sy-subrc <> 0. + lo_column = lo_columns->get_column( |LONGTEXT| ). + lo_column->set_technical( abap_true ). + ENDIF. + + LOOP AT gt_log TRANSPORTING NO FIELDS WHERE callstack IS NOT INITIAL. + EXIT. + ENDLOOP. + IF sy-subrc <> 0. + lo_column = lo_columns->get_column( |CALLSTACK| ). + lo_column->set_technical( abap_true ). + ENDIF. + + LOOP AT gt_log TRANSPORTING NO FIELDS WHERE id IS NOT INITIAL. + EXIT. + ENDLOOP. + IF sy-subrc <> 0. + lo_column = lo_columns->get_column( |ID| ). + lo_column->set_technical( abap_true ). + lo_column = lo_columns->get_column( |NUMBER| ). + lo_column->set_technical( abap_true ). + ENDIF. + + ls_position = zcl_abapgit_popups=>center( + iv_width = 125 + iv_height = 20 ). + + lo_alv->set_screen_popup( start_column = ls_position-start_column + end_column = ls_position-end_column + start_line = ls_position-start_row + end_line = ls_position-end_row ). + + CREATE OBJECT lo_form_header + EXPORTING + text = ii_log->get_title( ). + + lo_alv->set_top_of_list( lo_form_header ). + + lo_event = lo_alv->get_event( ). + + SET HANDLER on_link_click FOR lo_event. + + lo_alv->display( ). + + CATCH cx_salv_error INTO lx_error. + MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. + ENDTRY. + + ENDMETHOD. + METHOD show_longtext. + + DATA: lx_abapgit TYPE REF TO zcx_abapgit_exception. + + DATA: lv_docu_object TYPE dokhl-object, + lt_dummy1 TYPE TABLE OF dselc, + lt_dummy2 TYPE TABLE OF dval, + ls_help_info TYPE help_info. + + IF is_log-exception IS BOUND. + TRY. + lx_abapgit ?= is_log-exception. + CATCH cx_sy_move_cast_error. + RETURN. + ENDTRY. + + lv_docu_object = lx_abapgit->if_t100_message~t100key-msgid && lx_abapgit->if_t100_message~t100key-msgno. + ls_help_info-messageid = lx_abapgit->if_t100_message~t100key-msgid. + ls_help_info-messagenr = lx_abapgit->if_t100_message~t100key-msgno. + ls_help_info-msgv1 = lx_abapgit->msgv1. + ls_help_info-msgv2 = lx_abapgit->msgv2. + ls_help_info-msgv3 = lx_abapgit->msgv3. + ls_help_info-msgv4 = lx_abapgit->msgv4. + ELSEIF is_log-id IS NOT INITIAL AND is_log-number IS NOT INITIAL. + lv_docu_object = is_log-id && is_log-number. + ls_help_info-messageid = is_log-id. + ls_help_info-messagenr = is_log-number. + ELSE. + RETURN. + ENDIF. + + ls_help_info-call = 'D'. + ls_help_info-spras = sy-langu. + ls_help_info-message = is_log-msg. + ls_help_info-title = 'Longtext'. + ls_help_info-docuid = 'NA'. + ls_help_info-docuobject = condense( lv_docu_object ). + + CALL FUNCTION 'HELP_START' + EXPORTING + help_infos = ls_help_info + TABLES + dynpselect = lt_dummy1 + dynpvaluetab = lt_dummy2 + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc IS NOT INITIAL. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD to_html. + + DATA: lt_message TYPE zif_abapgit_log=>ty_log_outs, + lr_message TYPE REF TO zif_abapgit_log=>ty_log_out, + lv_class TYPE string, + lv_icon TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF ii_log->count( ) = 0. + RETURN. + ENDIF. + + lt_message = ii_log->get_messages( ). + + LOOP AT lt_message REFERENCE INTO lr_message. + CASE lr_message->type. + WHEN 'W'. + lv_icon = 'attention'. + lv_class = 'warning'. + WHEN 'E'. + lv_icon = 'error'. + lv_class = 'error'. + WHEN OTHERS. " ??? unexpected + lv_icon = 'error'. + lv_class = 'error'. + ENDCASE. + + ri_html->add( || ). + ri_html->add_icon( lv_icon ). + ri_html->add( lr_message->text ). + ri_html->add( '' ). + ENDLOOP. + + ENDMETHOD. + METHOD write_log. + + DATA: lt_message TYPE zif_abapgit_log=>ty_log_outs, + lr_message TYPE REF TO zif_abapgit_log=>ty_log_out, + lv_text TYPE string. + + lt_message = ii_log->get_messages( ). + + LOOP AT lt_message REFERENCE INTO lr_message. + IF lr_message->obj_name IS NOT INITIAL AND lr_message->obj_type IS NOT INITIAL. + lv_text = |{ lr_message->type }: { lr_message->text } ({ lr_message->obj_type }/{ lr_message->obj_name })|. + ELSE. + lv_text = |{ lr_message->type }: { lr_message->text }|. + ENDIF. + WRITE: / lv_text. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_HTML_TOOLBAR IMPLEMENTATION. + METHOD add. + DATA ls_item TYPE ty_item. + + ASSERT iv_typ = zif_abapgit_html=>c_action_type-separator " sep doesn't have action + OR iv_typ = zif_abapgit_html=>c_action_type-onclick " click may have no action (assigned in JS) + OR iv_typ = zif_abapgit_html=>c_action_type-dummy " dummy may have no action + OR iv_act IS INITIAL AND io_sub IS NOT INITIAL + OR iv_act IS NOT INITIAL AND io_sub IS INITIAL. " Only one supplied + + ASSERT NOT ( iv_chk <> abap_undefined AND io_sub IS NOT INITIAL ). + + ASSERT iv_hotkey IS INITIAL OR strlen( iv_hotkey ) = 1. + + ls_item-txt = iv_txt. + ls_item-act = iv_act. + ls_item-ico = iv_ico. + ls_item-sub = io_sub. + ls_item-opt = iv_opt. + ls_item-typ = iv_typ. + ls_item-cur = iv_cur. + ls_item-chk = iv_chk. + ls_item-aux = iv_aux. + ls_item-id = iv_id. + ls_item-title = iv_title. + ls_item-class = iv_class. + ls_item-li_class = iv_li_class. + ls_item-hotkey = to_lower( iv_hotkey ). + + APPEND ls_item TO mt_items. + + ro_self = me. + + ENDMETHOD. + METHOD constructor. + mv_id = iv_id. + ENDMETHOD. + METHOD count_items. + rv_count = lines( mt_items ). + ENDMETHOD. + METHOD create. + CREATE OBJECT ro_instance + EXPORTING + iv_id = iv_id. + ENDMETHOD. + METHOD get_hotkeys. + + DATA ls_hotkey_action LIKE LINE OF rt_hotkeys. + FIELD-SYMBOLS LIKE LINE OF mt_items. + + ls_hotkey_action-ui_component = iv_component_name. + + LOOP AT mt_items ASSIGNING WHERE hotkey IS NOT INITIAL. + ls_hotkey_action-description = -txt. + ls_hotkey_action-action = -act. + ls_hotkey_action-hotkey = -hotkey. + INSERT ls_hotkey_action INTO TABLE rt_hotkeys. + ENDLOOP. + + ENDMETHOD. + METHOD render. + + DATA: lv_class TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + lv_class = 'nav-container'. + IF iv_right = abap_true. + lv_class = lv_class && ' float-right'. + ENDIF. + + ri_html->add( |
    | ). + ri_html->add( render_items( iv_sort = iv_sort ) ). + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_as_droplist. + + DATA: lv_class TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + lv_class = 'nav-container'. + IF iv_right = abap_true. + lv_class = lv_class && ' float-right'. + ENDIF. + IF iv_corner = abap_true. + lv_class = lv_class && ' corner'. + ENDIF. + + ri_html->add( |
    | ). + ri_html->add( '
    • ' ). + ri_html->add_a( iv_txt = iv_label + iv_typ = zif_abapgit_html=>c_action_type-sapevent + iv_act = iv_action ). + ri_html->add( '
      ' ). + ri_html->add( render_items( iv_sort = iv_sort ) ). + ri_html->add( '
    ' ). + ri_html->add( '
    ' ). + + ENDMETHOD. + METHOD render_items. + + DATA: lv_class TYPE string, + lv_class_value TYPE string, + lv_icon TYPE string, + lv_id TYPE string, + lv_check TYPE string, + lv_aux TYPE string, + lv_txt TYPE string, + lv_hkidx TYPE i, + lv_has_icons TYPE abap_bool. + + FIELD-SYMBOLS LIKE LINE OF mt_items. + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF iv_sort = abap_true. + SORT mt_items BY txt ASCENDING AS TEXT. + ENDIF. + + " Check has icons or check boxes + LOOP AT mt_items ASSIGNING WHERE ico IS NOT INITIAL OR chk <> abap_undefined. + lv_has_icons = abap_true. + lv_class = ' class="with-icons"'. + EXIT. + ENDLOOP. + + IF mv_id IS NOT INITIAL. + lv_id = | id="{ mv_id }"|. + ENDIF. + + ri_html->add( || ). + + " Render items + LOOP AT mt_items ASSIGNING . + CLEAR: lv_class, lv_class_value, lv_icon. + lv_txt = -txt. + + IF -hotkey IS NOT INITIAL. + ASSERT strlen( -hotkey ) = 1. + lv_hkidx = find( + val = lv_txt + sub = to_upper( -hotkey ) ). + IF lv_hkidx < 0. + lv_hkidx = find( + val = lv_txt + sub = -hotkey ). + ENDIF. + IF lv_hkidx >= 0. + lv_txt = replace( + val = lv_txt + off = lv_hkidx + len = 1 + with = |{ lv_txt+lv_hkidx(1) }| ). + ENDIF. + ENDIF. + + IF -typ = zif_abapgit_html=>c_action_type-separator. + ri_html->add( |
  • { lv_txt }
  • | ). + CONTINUE. + ENDIF. + + IF lv_has_icons = abap_true. + IF -chk = abap_true. + lv_icon = ri_html->icon( 'check/blue' ). + lv_check = ' data-check="X"'. + ELSEIF -chk = abap_false. + lv_icon = ri_html->icon( 'check/grey' ). + lv_check = ' data-check=""'. + ELSE. " abap_undefined -> not a check box + lv_icon = ri_html->icon( -ico ). + ENDIF. + ENDIF. + IF -cur = abap_true. + IF -li_class IS INITIAL. + lv_class_value = 'current-menu-item'. + ELSE. + lv_class_value = |current-menu-item { -li_class }|. + ENDIF. + ELSE. + lv_class_value = -li_class. + ENDIF. + IF lv_class_value IS NOT INITIAL. + lv_class = | class="{ lv_class_value }"|. + ENDIF. + IF -aux IS NOT INITIAL. + lv_aux = | data-aux="{ -aux }"|. + ENDIF. + + ri_html->add( || ). + + IF -sub IS INITIAL. + ri_html->add_a( iv_txt = lv_icon && lv_txt + iv_typ = -typ + iv_act = -act + iv_id = -id + iv_opt = -opt + iv_title = -title + iv_class = -class ). + ELSE. + ri_html->add_a( iv_txt = lv_icon && lv_txt + iv_typ = zif_abapgit_html=>c_action_type-dummy + iv_act = '' + iv_id = -id + iv_opt = -opt + iv_title = -title + iv_class = -class ). + ri_html->add( -sub->render_items( iv_sort ) ). + ENDIF. + ri_html->add( '' ). + + ENDLOOP. + + ri_html->add( '
' ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. + METHOD apply_sorting. + + DATA lv_field TYPE abap_compname. + DATA ls_col LIKE LINE OF mt_columns. + + IF ms_sorting_state-column_id IS INITIAL. + RETURN. + ENDIF. + + READ TABLE mt_columns INTO ls_col WITH KEY column_id = ms_sorting_state-column_id. + IF sy-subrc <> 0. + RETURN. " ??? but let's not throw errors here + ENDIF. + + IF ls_col-from_field IS NOT INITIAL. + lv_field = to_upper( ls_col-from_field ). + ELSE. + lv_field = to_upper( ms_sorting_state-column_id ). + ENDIF. + + " What to do if column_id is not a table field ? + " Well ... then it is a complex case for an external sorting, don't use the simple one + + IF ms_sorting_state-descending = abap_true. + SORT ct_data BY (lv_field) DESCENDING. + ELSE. + SORT ct_data BY (lv_field) ASCENDING. + ENDIF. + + ENDMETHOD. + METHOD cid_attr. + + rs_data_attr-name = 'cid'. + rs_data_attr-value = iv_column_id. + + ENDMETHOD. + METHOD create. + CREATE OBJECT ro_instance. + ro_instance->mi_renderer = ii_renderer. + ro_instance->ms_sorting_state = is_initial_sorting_state. + ENDMETHOD. + METHOD define_column. + + FIELD-SYMBOLS LIKE LINE OF mt_columns. + + ASSERT iv_column_id IS NOT INITIAL. + ro_self = me. + + APPEND INITIAL LINE TO mt_columns ASSIGNING . + -column_id = iv_column_id. + -column_title = iv_column_title. + -from_field = to_upper( iv_from_field ). + -sortable = iv_sortable. + + IF mr_last_grp IS NOT INITIAL. + mr_last_grp->group_span = mr_last_grp->group_span + 1. + ENDIF. + + ENDMETHOD. + METHOD define_column_group. + + IF lines( mt_columns ) > 0 AND mr_last_grp IS INITIAL. + " Groups should cover all columns + " you can create a group with empty title if groups start later VISUALLY + zcx_abapgit_exception=>raise( 'Start groups from the beginning' ). + ENDIF. + + ro_self = me. + + APPEND INITIAL LINE TO mt_columns REFERENCE INTO mr_last_grp. + mr_last_grp->is_group = abap_true. + mr_last_grp->column_id = iv_group_id. + mr_last_grp->column_title = iv_group_title. + + ENDMETHOD. + METHOD detect_sorting_request. + + DATA lv_req TYPE string. + + IF find( + val = iv_event + regex = c_sort_by_event_regex ) = 0. + + lv_req = replace( + val = iv_event + sub = c_sort_by_event_prefix + with = '' ). + SPLIT lv_req AT ':' INTO rs_sorting_request-column_id lv_req. + rs_sorting_request-descending = boolc( lv_req = 'dsc' ). + + ENDIF. + + ENDMETHOD. + METHOD gid_attr. + + rs_data_attr-name = 'gid'. + rs_data_attr-value = iv_column_id. + + ENDMETHOD. + METHOD process_sorting_request. + + DATA ls_sorting_req LIKE ms_sorting_state. + + ls_sorting_req = detect_sorting_request( iv_event ). + IF ls_sorting_req IS NOT INITIAL. + ms_sorting_state = ls_sorting_req. + rv_processed = abap_true. + ENDIF. + + ENDMETHOD. + METHOD render. + + DATA lv_attrs TYPE string. + DATA lr_data_copy TYPE REF TO data. + FIELD-SYMBOLS TYPE ANY TABLE. + + IF ii_renderer IS BOUND. + mi_renderer = ii_renderer. + ENDIF. + + ASSERT mi_renderer IS BOUND. + + mv_with_cids = iv_with_cids. + mv_table_id = iv_id. + ASSIGN it_data TO . + + IF is_sorting_state IS NOT INITIAL. + ms_sorting_state = is_sorting_state. + ELSEIF ms_sorting_state IS NOT INITIAL. + " If sorting state is not passed, + " but there is non empty sort state then suppose simple sorting mode + " so that table sorts the data itself before rendering + " TODO not efficient, maybe bind changing data from outside + CREATE DATA lr_data_copy LIKE it_data. + ASSIGN lr_data_copy->* TO . + = it_data. + apply_sorting( CHANGING ct_data = ). + ENDIF. + + IF iv_id IS NOT INITIAL. + lv_attrs = lv_attrs && | id="{ iv_id }"|. + ENDIF. + + IF iv_css_class IS NOT INITIAL. + lv_attrs = lv_attrs && | class="{ iv_css_class }"|. + ENDIF. + + CREATE OBJECT mi_html TYPE zcl_abapgit_html. + ri_html = mi_html. + + IF iv_wrap_in_div IS NOT INITIAL. + mi_html->add( |
| ). + ENDIF. + + mi_html->add( || ). + render_thead( ). + render_tbody( ). + mi_html->add( '' ). + + IF iv_wrap_in_div IS NOT INITIAL. + mi_html->add( '
' ). + ENDIF. + + ENDMETHOD. + METHOD render_column_title. + + DATA lv_direction TYPE string. + DATA lv_arrow TYPE string. + DATA lv_sort_active TYPE string. + + IF is_col-sortable = abap_true AND ms_sorting_state IS NOT INITIAL. + + IF is_col-column_id = ms_sorting_state-column_id AND ms_sorting_state-descending = abap_false. + lv_direction = 'dsc'. + ELSE. + lv_direction = 'asc'. + ENDIF. + + IF is_col-column_id = ms_sorting_state-column_id AND ms_sorting_state-descending = abap_true. + lv_arrow = '▴'. " arrow up + ELSE. + lv_arrow = '▾'. " arrow down + ENDIF. + + IF is_col-column_id = ms_sorting_state-column_id. + lv_sort_active = | { mv_sort_active_class }|. + ENDIF. + + rv_text = mi_html->a( + iv_txt = is_col-column_title + iv_act = |{ c_sort_by_event_prefix }{ is_col-column_id }:{ lv_direction }| ). + + rv_text = rv_text && |{ lv_arrow }|. + + ELSE. + rv_text = is_col-column_title. + ENDIF. + + ENDMETHOD. + METHOD render_row. + + DATA ls_render TYPE zif_abapgit_html_table=>ty_cell_render. + DATA lv_dummy TYPE string. + DATA lt_attrs TYPE zif_abapgit_html=>ty_data_attrs. + + FIELD-SYMBOLS LIKE LINE OF mt_columns. + FIELD-SYMBOLS LIKE LINE OF mt_columns. + FIELD-SYMBOLS TYPE any. + + LOOP AT mt_columns ASSIGNING . + IF -is_group = abap_true. + ASSIGN TO . + CONTINUE. + ENDIF. + + IF -from_field IS NOT INITIAL AND -from_field <> '-'. + ASSIGN COMPONENT -from_field OF STRUCTURE is_row TO . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |html_table: cannot assign field [{ -from_field }]| ). + ENDIF. + ELSEIF -from_field <> '-'. + -from_field = to_upper( -column_id ). " Try column_id + ASSIGN COMPONENT -from_field OF STRUCTURE is_row TO . + IF sy-subrc <> 0. + -from_field = '-'. " Don't try assignments anymore + ASSIGN lv_dummy TO . + ENDIF. + ELSE. + ASSIGN lv_dummy TO . + ENDIF. + + ls_render = mi_renderer->render_cell( + iv_table_id = mv_table_id + iv_row_index = iv_row_index + is_row = is_row + iv_column_id = -column_id + iv_value = |{ }| ). + + IF mv_with_cids = abap_true. + CLEAR lt_attrs. + APPEND cid_attr( -column_id ) TO lt_attrs. + IF IS ASSIGNED AND -column_id IS NOT INITIAL. + APPEND gid_attr( -column_id ) TO lt_attrs. + ENDIF. + ENDIF. + + mi_html->td( + iv_content = ls_render-content + ii_content = ls_render-html + it_data_attrs = lt_attrs + iv_class = ls_render-css_class ). + ENDLOOP. + + ENDMETHOD. + METHOD render_tbody. + + DATA ls_row_attrs TYPE zif_abapgit_html_table=>ty_row_attrs. + DATA lv_row_attrs TYPE string. + DATA lv_index TYPE i. + + FIELD-SYMBOLS TYPE any. + + mi_html->add( '' ). + + LOOP AT it_data ASSIGNING . + lv_index = sy-tabix. + ls_row_attrs = mi_renderer->get_row_attrs( + iv_table_id = mv_table_id + iv_row_index = lv_index + is_row = ). + CLEAR lv_row_attrs. + IF ls_row_attrs-css_class IS NOT INITIAL. + lv_row_attrs = lv_row_attrs && | class="{ ls_row_attrs-css_class }"|. + ENDIF. + IF ls_row_attrs-data IS NOT INITIAL. + lv_row_attrs = lv_row_attrs && | data-{ ls_row_attrs-data-name }="{ ls_row_attrs-data-value }"|. + ENDIF. + mi_html->add( || ). + render_row( + iv_row_index = lv_index + is_row = ). + mi_html->add( '' ). + ENDLOOP. + + mi_html->add( '' ). + + ENDMETHOD. + METHOD render_thead. + + FIELD-SYMBOLS LIKE LINE OF mt_columns. + FIELD-SYMBOLS LIKE LINE OF mt_columns. + DATA lt_attrs TYPE zif_abapgit_html=>ty_data_attrs. + DATA ls_grp_span TYPE string. + DATA lv_grp_data TYPE string. + + mi_html->add( '' ). + + " Group headers + IF mr_last_grp IS NOT INITIAL. " Has groups + + mi_html->add( '' ). + + LOOP AT mt_columns ASSIGNING WHERE is_group = abap_true. + IF mv_with_cids = abap_true AND -column_id IS NOT INITIAL. + lv_grp_data = | data-gid="{ -column_id }"|. + ELSE. + CLEAR lv_grp_data. + ENDIF. + + IF -group_span > 1. + ls_grp_span = | colspan="{ -group_span }"|. + ELSE. + CLEAR ls_grp_span. + ENDIF. + + mi_html->add( |{ -column_title }| ). + ENDLOOP. + + mi_html->add( '' ). + + ENDIF. + + " Regular headers + mi_html->add( '' ). + + LOOP AT mt_columns ASSIGNING . + IF -is_group = abap_true. + ASSIGN TO . + CONTINUE. + ENDIF. + + IF mv_with_cids = abap_true. + CLEAR lt_attrs. + APPEND cid_attr( -column_id ) TO lt_attrs. + IF IS ASSIGNED AND -column_id IS NOT INITIAL. + APPEND gid_attr( -column_id ) TO lt_attrs. + ENDIF. + ENDIF. + + mi_html->th( + iv_content = render_column_title( ) + it_data_attrs = lt_attrs ). + ENDLOOP. + + mi_html->add( '' ). + mi_html->add( '' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_html_form_utils IMPLEMENTATION. + METHOD constructor. + mo_form = io_form. + ENDMETHOD. + METHOD create. + CREATE OBJECT ro_form_util + EXPORTING + io_form = io_form. + ENDMETHOD. + METHOD exit. + + DATA lv_answer TYPE c LENGTH 1. + + IF is_dirty( + io_form_data = io_form_data + io_compare_with = io_compare_with ) = abap_true. + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_display_cancel_button = abap_false + iv_titlebar = 'abapGit - Unsaved Changes' + iv_text_question = 'There are unsaved changes. Do you want to exit the form?' + iv_default_button = '2' ). + + IF lv_answer = '1'. + rv_state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark. + ELSE. + rv_state = zcl_abapgit_gui=>c_event_state-no_more_act. + ENDIF. + ELSE. + rv_state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark. + ENDIF. + + ENDMETHOD. + METHOD is_dirty. + rv_dirty = boolc( io_form_data->mt_entries <> io_compare_with->mt_entries ). + ENDMETHOD. + METHOD is_empty. + + DATA: + lt_fields TYPE zif_abapgit_html_form=>ty_fields, + lv_value TYPE string, + lv_rows TYPE i, + lv_row TYPE i. + + FIELD-SYMBOLS LIKE LINE OF lt_fields. + + rv_empty = abap_true. + lt_fields = mo_form->get_fields( ). + LOOP AT lt_fields ASSIGNING WHERE type <> zif_abapgit_html_form=>c_field_type-field_group. + lv_value = condense( + val = io_form_data->get( -name ) + del = ` ` ). + + IF -type = zif_abapgit_html_form=>c_field_type-number. + rv_empty = boolc( lv_value IS INITIAL OR lv_value = '0' ). + ELSEIF -type = zif_abapgit_html_form=>c_field_type-table. + lv_rows = io_form_data->get( |{ -name }-{ zif_abapgit_html_form=>c_rows }| ). + DO lv_rows TIMES. + lv_row = sy-index. + DO lines( -subitems ) TIMES. + lv_value = io_form_data->get( |{ -name }-{ lv_row }-{ sy-index }| ). + rv_empty = boolc( lv_value IS INITIAL ). + IF rv_empty <> abap_true. + RETURN. + ENDIF. + ENDDO. + ENDDO. + ELSEIF -type = zif_abapgit_html_form=>c_field_type-textarea. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_value WITH ''. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN lv_value WITH ''. + rv_empty = boolc( lv_value IS INITIAL ). + ELSE. + rv_empty = boolc( lv_value IS INITIAL ). + ENDIF. + + IF rv_empty <> abap_true. + RETURN. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD normalize. + + DATA: + lt_fields TYPE zif_abapgit_html_form=>ty_fields, + lv_value TYPE string, + lv_rows TYPE i, + lv_row TYPE i, + lv_len TYPE i. + + FIELD-SYMBOLS LIKE LINE OF lt_fields. + + CREATE OBJECT ro_form_data. + + IF io_form_data->is_empty( ) = abap_true. + RETURN. + ENDIF. + + lt_fields = mo_form->get_fields( ). + LOOP AT lt_fields ASSIGNING WHERE type <> zif_abapgit_html_form=>c_field_type-field_group + AND type <> zif_abapgit_html_form=>c_field_type-hidden. + + CLEAR lv_value. + lv_value = io_form_data->get( -name ). + IF -condense = abap_true. + lv_value = condense( val = lv_value + del = ` ` ). + ENDIF. + + IF -type = zif_abapgit_html_form=>c_field_type-checkbox. + ro_form_data->set( + iv_key = -name + iv_val = boolc( lv_value = 'on' ) ) ##TYPE. + ELSEIF ( -type = zif_abapgit_html_form=>c_field_type-text + OR -type = zif_abapgit_html_form=>c_field_type-textarea ) + AND -upper_case = abap_true. + ro_form_data->set( + iv_key = -name + iv_val = to_upper( lv_value ) ). + ELSEIF -type = zif_abapgit_html_form=>c_field_type-number. + " Numeric value is checked in validation + ro_form_data->set( + iv_key = -name + iv_val = condense( val = lv_value del = ` ` ) ). + ELSEIF -type = zif_abapgit_html_form=>c_field_type-table. + lv_rows = io_form_data->get( |{ -name }-{ zif_abapgit_html_form=>c_rows }| ). + DO lv_rows TIMES. + lv_row = sy-index. + DO lines( -subitems ) TIMES. + lv_value = io_form_data->get( |{ -name }-{ lv_row }-{ sy-index }| ). + ro_form_data->set( + iv_key = |{ -name }-{ lv_row }-{ sy-index }| + iv_val = lv_value ). + ENDDO. + ENDDO. + ro_form_data->set( + iv_key = |{ -name }-{ zif_abapgit_html_form=>c_rows }| + iv_val = |{ lv_rows }| ). + ELSEIF -type = zif_abapgit_html_form=>c_field_type-textarea. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_value + WITH cl_abap_char_utilities=>newline. + + " Remove last line if empty (ie 2x newline) + lv_len = strlen( lv_value ) - 2. + IF lv_len >= 0 AND lv_value+lv_len(1) = cl_abap_char_utilities=>newline. + lv_len = lv_len + 1. + lv_value = lv_value(lv_len). + ENDIF. + + ro_form_data->set( + iv_key = -name + iv_val = lv_value ). + ELSE. + ro_form_data->set( + iv_key = -name + iv_val = lv_value ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD set_data. + mo_form_data = io_form_data. + ENDMETHOD. + METHOD validate. + + DATA: + lt_fields TYPE zif_abapgit_html_form=>ty_fields, + lv_value TYPE string, + lv_number TYPE p LENGTH 16 DECIMALS 0. + + FIELD-SYMBOLS LIKE LINE OF lt_fields. + + CREATE OBJECT ro_validation_log. + + lt_fields = mo_form->get_fields( ). + LOOP AT lt_fields ASSIGNING . + lv_value = io_form_data->get( -name ). + IF -condense = abap_true. + lv_value = condense( val = lv_value + del = ` ` ). + ENDIF. + IF -required IS NOT INITIAL AND lv_value IS INITIAL. + ro_validation_log->set( + iv_key = -name + iv_val = |{ -label } cannot be empty| ). + ENDIF. + CASE -type. + WHEN zif_abapgit_html_form=>c_field_type-text. + IF -min = -max AND strlen( lv_value ) <> -min. + ro_validation_log->set( + iv_key = -name + iv_val = |{ -label } must be exactly { -min } characters long| ). + ELSE. + IF -min <> cl_abap_math=>min_int4 AND strlen( lv_value ) < -min. + ro_validation_log->set( + iv_key = -name + iv_val = |{ -label } must not be shorter than { -min } characters| ). + ENDIF. + IF -max <> cl_abap_math=>max_int4 AND strlen( lv_value ) > -max. + ro_validation_log->set( + iv_key = -name + iv_val = |{ -label } must not be longer than { -max } characters| ). + ENDIF. + ENDIF. + WHEN zif_abapgit_html_form=>c_field_type-number. + TRY. + lv_number = lv_value. + CATCH cx_root. + ro_validation_log->set( + iv_key = -name + iv_val = |{ -label } is not numeric| ). + CONTINUE. + ENDTRY. + IF -min <> cl_abap_math=>min_int4 AND lv_number < -min. + ro_validation_log->set( + iv_key = -name + iv_val = |{ -label } must not be lower than { -min }| ). + ENDIF. + IF -max <> cl_abap_math=>max_int4 AND lv_number > -max. + ro_validation_log->set( + iv_key = -name + iv_val = |{ -label } must not be higher than { -max }| ). + ENDIF. + ENDCASE. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_html_form IMPLEMENTATION. + METHOD checkbox. + + DATA ls_field LIKE LINE OF mt_fields. + + ls_field-type = zif_abapgit_html_form=>c_field_type-checkbox. + ls_field-name = iv_name. + ls_field-label = iv_label. + ls_field-hint = iv_hint. + ls_field-readonly = iv_readonly. + + APPEND ls_field TO mt_fields. + + ro_self = me. + + ENDMETHOD. + METHOD column. + + FIELD-SYMBOLS LIKE LINE OF mt_fields. + DATA ls_column LIKE LINE OF -subitems. + DATA lv_size TYPE i. + + lv_size = lines( mt_fields ). + ASSERT lv_size > 0. " Exception ? Maybe add zcx_no_check ? + + READ TABLE mt_fields INDEX lv_size ASSIGNING . + ASSERT sy-subrc = 0. + ASSERT -type = zif_abapgit_html_form=>c_field_type-table. + + ls_column-label = iv_label. + ls_column-value = iv_width. + ls_column-readonly = iv_readonly. + + APPEND ls_column TO -subitems. + + ro_self = me. + + ENDMETHOD. + METHOD command. + + DATA ls_cmd LIKE LINE OF mt_commands. + + ASSERT iv_cmd_type BETWEEN 1 AND 4. + + ls_cmd-label = iv_label. + ls_cmd-action = iv_action. + ls_cmd-cmd_type = iv_cmd_type. + + APPEND ls_cmd TO mt_commands. + + ro_self = me. + + ENDMETHOD. + METHOD create. + + DATA lv_ts TYPE timestampl. + + CREATE OBJECT ro_form. + ro_form->mv_form_id = iv_form_id. + ro_form->mv_help_page = iv_help_page. + + IF ro_form->mv_form_id IS INITIAL. + GET TIME STAMP FIELD lv_ts. + ro_form->mv_form_id = |form_{ lv_ts }|. + ENDIF. + + ro_form->mv_webgui = zcl_abapgit_ui_factory=>get_frontend_services( )->is_webgui( ). + + ENDMETHOD. + METHOD get_fields. + rt_fields = mt_fields. + ENDMETHOD. + METHOD hidden. + + DATA ls_field LIKE LINE OF mt_fields. + + ls_field-type = zif_abapgit_html_form=>c_field_type-hidden. + ls_field-name = iv_name. + APPEND ls_field TO mt_fields. + + ro_self = me. + + ENDMETHOD. + METHOD number. + + DATA ls_field LIKE LINE OF mt_fields. + + ls_field-type = zif_abapgit_html_form=>c_field_type-number. + ls_field-name = iv_name. + ls_field-label = iv_label. + ls_field-readonly = iv_readonly. + ls_field-min = iv_min. + ls_field-max = iv_max. + ls_field-hint = iv_hint. + ls_field-required = iv_required. + + APPEND ls_field TO mt_fields. + + ro_self = me. + + ENDMETHOD. + METHOD option. + + FIELD-SYMBOLS LIKE LINE OF mt_fields. + DATA ls_option LIKE LINE OF -subitems. + DATA lv_size TYPE i. + + lv_size = lines( mt_fields ). + ASSERT lv_size > 0. " Exception ? Maybe add zcx_no_check ? + + READ TABLE mt_fields INDEX lv_size ASSIGNING . + ASSERT sy-subrc = 0. + ASSERT -type = zif_abapgit_html_form=>c_field_type-radio. " Or dropdown - TODO in future + + ls_option-label = iv_label. + ls_option-value = iv_value. + + APPEND ls_option TO -subitems. + + ro_self = me. + + ENDMETHOD. + METHOD radio. + + DATA ls_field LIKE LINE OF mt_fields. + + ls_field-type = zif_abapgit_html_form=>c_field_type-radio. + ls_field-name = iv_name. + ls_field-label = iv_label. + ls_field-default_value = iv_default_value. + ls_field-hint = iv_hint. + ls_field-click = iv_action. + + " put options into one column instead of side-by-side + ls_field-condense = iv_condense. + + APPEND ls_field TO mt_fields. + + ro_self = me. + + ENDMETHOD. + METHOD render. + + FIELD-SYMBOLS LIKE LINE OF mt_fields. + FIELD-SYMBOLS LIKE LINE OF mt_commands. + DATA lv_hint TYPE string. + DATA ls_form_id TYPE string. + DATA ls_form_action TYPE string. + DATA lv_cur_group TYPE string. + DATA lv_url TYPE string. + DATA lv_autofocus TYPE abap_bool. + + register_handlers( ). + + IF mv_form_id IS NOT INITIAL. + ls_form_id = | id="{ mv_form_id }"|. + ENDIF. + LOOP AT mt_commands ASSIGNING WHERE cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main. + ls_form_action = | action="sapevent:{ -action }"|. + EXIT. + ENDLOOP. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( |
| ). " to center use 'dialog-form-center' + ri_html->add( |
| ). + + " Add hidden button that triggers main command when pressing enter + LOOP AT mt_commands ASSIGNING WHERE cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main. + ri_html->add( || ). + EXIT. + ENDLOOP. + + lv_autofocus = abap_true. + LOOP AT mt_fields ASSIGNING . + AT FIRST. + IF -type <> zif_abapgit_html_form=>c_field_type-field_group. + ri_html->add( |
    | ). + ENDIF. + ENDAT. + + IF -type = zif_abapgit_html_form=>c_field_type-field_group. + IF lv_cur_group IS NOT INITIAL AND lv_cur_group <> -name. + ri_html->add( |
| ). + ri_html->add( || ). + ENDIF. + IF -hint IS NOT INITIAL. + lv_hint = | title="{ -hint }"|. + ELSE. + lv_hint = ''. + ENDIF. + lv_cur_group = -name. + ri_html->add( |
| ). + ri_html->add( |{ -label }| ). + ri_html->add( |
    | ). + CONTINUE. + ENDIF. + + render_field( + ii_html = ri_html + io_values = io_values + io_validation_log = io_validation_log + is_field = + iv_autofocus = lv_autofocus ). + + lv_autofocus = abap_false. + + AT LAST. + ri_html->add( |
| ). + IF lv_cur_group IS NOT INITIAL. + ri_html->add( |
| ). + ENDIF. + ENDAT. + ENDLOOP. + + ri_html->add( |
    | ). + ri_html->add( |
  • | ). + + IF mv_help_page IS NOT INITIAL. + lv_url = escape( val = mv_help_page + format = cl_abap_format=>e_url ). + ri_html->add_a( + iv_txt = zcl_abapgit_gui_buttons=>help( ) + iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ lv_url }| + iv_class = 'dialog-help' + iv_title = 'Help' ). + ENDIF. + + LOOP AT mt_commands ASSIGNING . + render_command( + ii_html = ri_html + is_cmd = ). + ENDLOOP. + + ri_html->add( |
  • | ). + ri_html->add( |
| ). + ri_html->add( || ). + ri_html->add( |
| ). + + ENDMETHOD. + METHOD render_command. + + " HTML GUI supports only links for submitting forms + IF mv_webgui = abap_true. + render_command_link( + is_cmd = is_cmd + ii_html = ii_html ). + RETURN. + ENDIF. + + CASE is_cmd-cmd_type. + WHEN zif_abapgit_html_form=>c_cmd_type-link. + + render_command_link( + is_cmd = is_cmd + ii_html = ii_html ). + + WHEN zif_abapgit_html_form=>c_cmd_type-button. + + ii_html->add( || ). + + WHEN zif_abapgit_html_form=>c_cmd_type-input. + + ii_html->add( || ). + + WHEN zif_abapgit_html_form=>c_cmd_type-input_main. + + ii_html->add( || ). + + WHEN OTHERS. + ASSERT 0 = 1. + + ENDCASE. + + ENDMETHOD. + METHOD render_command_link. + + DATA lv_class TYPE string VALUE 'dialog-commands'. + + IF is_cmd-cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main. + lv_class = lv_class && ' main'. + ENDIF. + + ii_html->add_a( + iv_txt = is_cmd-label + iv_act = is_cmd-action + iv_class = lv_class ). + + ENDMETHOD. + METHOD render_field. + + DATA: + ls_attr TYPE ty_attr, + lv_item_class TYPE string. + + " Get value and validation error + ls_attr-value = io_values->get( is_field-name ). + + IF is_field-type <> zif_abapgit_html_form=>c_field_type-textarea. + ls_attr-value = escape( val = ls_attr-value + format = cl_abap_format=>e_html_attr ). + ENDIF. + + IF io_validation_log IS BOUND. + ls_attr-error = io_validation_log->get( is_field-name ). + IF ls_attr-error IS NOT INITIAL. + ls_attr-error = escape( val = ls_attr-error + format = cl_abap_format=>e_html_text ). + ls_attr-error = |{ ls_attr-error }|. + ENDIF. + ENDIF. + + " Prepare field attributes + IF is_field-required = abap_true. + ls_attr-required = ' *'. + ENDIF. + + IF is_field-hint IS NOT INITIAL. + ls_attr-hint = escape( val = is_field-hint + format = cl_abap_format=>e_html_attr ). + ls_attr-hint = | title="{ ls_attr-hint }"|. + ENDIF. + + IF is_field-placeholder IS NOT INITIAL. + ls_attr-placeholder = escape( val = is_field-placeholder + format = cl_abap_format=>e_html_attr ). + ls_attr-placeholder = | placeholder="{ ls_attr-placeholder }"|. + ENDIF. + + IF is_field-readonly = abap_true. + ls_attr-readonly = ' readonly'. + ENDIF. + + IF iv_autofocus = abap_true. + ls_attr-autofocus = ' autofocus'. + ENDIF. + + " Prepare item class + lv_item_class = is_field-item_class. + IF ls_attr-error IS NOT INITIAL. + lv_item_class = condense( lv_item_class && ' error' ). + ENDIF. + IF is_field-type = zif_abapgit_html_form=>c_field_type-text AND is_field-max BETWEEN 1 AND 20. + " Reduced width for short fields + lv_item_class = lv_item_class && ' w40'. + ENDIF. + IF is_field-type = zif_abapgit_html_form=>c_field_type-hidden. + lv_item_class = lv_item_class && ' hidden'. + ENDIF. + IF lv_item_class IS NOT INITIAL. + lv_item_class = | class="{ lv_item_class }"|. + ENDIF. + + " Render field + ii_html->add( || ). + + CASE is_field-type. + WHEN zif_abapgit_html_form=>c_field_type-text OR zif_abapgit_html_form=>c_field_type-number. + + render_field_text( + ii_html = ii_html + is_field = is_field + is_attr = ls_attr ). + + WHEN zif_abapgit_html_form=>c_field_type-textarea. + + render_field_textarea( + ii_html = ii_html + is_field = is_field + is_attr = ls_attr ). + + WHEN zif_abapgit_html_form=>c_field_type-checkbox. + + render_field_checkbox( + ii_html = ii_html + is_field = is_field + is_attr = ls_attr ). + + WHEN zif_abapgit_html_form=>c_field_type-radio. + + render_field_radio( + ii_html = ii_html + is_field = is_field + is_attr = ls_attr ). + + WHEN zif_abapgit_html_form=>c_field_type-table. + + render_field_table( + ii_html = ii_html + is_field = is_field + is_attr = ls_attr + io_values = io_values ). + + WHEN zif_abapgit_html_form=>c_field_type-hidden. + + render_field_hidden( + ii_html = ii_html + is_field = is_field + is_attr = ls_attr ). + + WHEN OTHERS. + ASSERT 1 = 0. + ENDCASE. + + ii_html->add( '' ). + + ENDMETHOD. + METHOD render_field_checkbox. + + DATA lv_checked TYPE string. + DATA lv_disabled TYPE string. + + IF is_attr-error IS NOT INITIAL. + ii_html->add( is_attr-error ). + ENDIF. + + IF is_attr-value = abap_true OR is_attr-value = 'on'. + " boolc return ` ` which is not initial -> bug after 1st validation + lv_checked = ' checked'. + ENDIF. + + IF is_attr-readonly IS NOT INITIAL. + lv_disabled = ' disabled'. + ENDIF. + + ii_html->add( || ). + ii_html->add( || ). + + ENDMETHOD. + METHOD render_field_hidden. + + ii_html->add( || ). + + ENDMETHOD. + METHOD render_field_radio. + + DATA: + lv_checked TYPE string, + lv_opt_id TYPE string, + lv_opt_value TYPE string, + lv_onclick TYPE string. + + FIELD-SYMBOLS LIKE LINE OF is_field-subitems. + + ii_html->add( |{ is_field-label }| ). + + IF is_attr-error IS NOT INITIAL. + ii_html->add( is_attr-error ). + ENDIF. + + ii_html->add( |
| ). + + LOOP AT is_field-subitems ASSIGNING . + + lv_opt_id = |{ is_field-name }{ sy-tabix }|. + lv_opt_value = escape( val = -value + format = cl_abap_format=>e_html_attr ). + + CLEAR lv_checked. + IF is_attr-value = lv_opt_value OR ( is_attr-value IS INITIAL AND lv_opt_value = is_field-default_value ). + lv_checked = ' checked'. + ENDIF. + + " With edge browser control radio buttons aren't checked automatically when + " activated with link hints. Therefore we need to check them manually. + IF is_field-click IS NOT INITIAL. + lv_onclick = |onclick="| + && |var form = document.getElementById('{ mv_form_id }');| + && |document.getElementById('{ lv_opt_id }').checked = true;| + && |form.action = 'sapevent:{ is_field-click }';| + && |form.submit();"|. + ELSE. + lv_onclick = |onclick="document.getElementById('{ lv_opt_id }').checked = true;"|. + ENDIF. + + IF is_field-condense = abap_true. + ii_html->add( '
' ). + ENDIF. + ii_html->add( || ). + ii_html->add( || ). + IF is_field-condense = abap_true. + ii_html->add( '
' ). + ENDIF. + ENDLOOP. + + ii_html->add( '
' ). + + ENDMETHOD. + METHOD render_field_table. + + DATA: + lv_value TYPE string, + lv_readonly TYPE string, + lv_rows TYPE i, + lv_cell_id TYPE string. + + FIELD-SYMBOLS LIKE LINE OF is_field-subitems. + + ii_html->add( || ). + + IF is_attr-error IS NOT INITIAL. + ii_html->add( is_attr-error ). + ENDIF. + + lv_rows = io_values->get( |{ is_field-name }-{ zif_abapgit_html_form=>c_rows }| ). + + " Render table only if there are some data rows + IF lv_rows > 0. + + ii_html->add( || ). + + ii_html->add( || ). + ii_html->add( || ). + LOOP AT is_field-subitems ASSIGNING . + CLEAR lv_value. + IF -value IS NOT INITIAL. + lv_value = escape( val = -value + format = cl_abap_format=>e_html_attr ). + lv_value = | width="{ lv_value }"|. + ENDIF. + ii_html->add( |{ -label }| ). + ENDLOOP. + ii_html->add( || ). + ii_html->add( || ). + + ii_html->add( || ). + DO lv_rows TIMES. + lv_rows = sy-index. + ii_html->add( || ). + LOOP AT is_field-subitems ASSIGNING . + lv_cell_id = |{ is_field-name }-{ lv_rows }-{ sy-tabix }|. + lv_value = escape( val = io_values->get( lv_cell_id ) + format = cl_abap_format=>e_html_attr ). + CLEAR lv_readonly. + IF -readonly = abap_true. + lv_readonly = | readonly|. + ENDIF. + ii_html->add( || ). + ENDLOOP. + ii_html->add( || ). + ENDDO. + ii_html->add( || ). + + ii_html->add( |
| ). + + ELSE. + ii_html->add( || ). + ENDIF. + + " Hidden field with number of rows to simplify getting values from form + lv_value = |{ is_field-name }-{ zif_abapgit_html_form=>c_rows }|. + ii_html->add( || ). + + ENDMETHOD. + METHOD render_field_text. + + DATA: + lv_type TYPE string, + lv_minlength TYPE string, + lv_maxlength TYPE string. + + ii_html->add( || ). + + IF is_attr-error IS NOT INITIAL. + ii_html->add( is_attr-error ). + ENDIF. + + IF is_field-side_action IS NOT INITIAL. + ii_html->add( '
' ). " Ugly :( + ENDIF. + + IF is_field-type = zif_abapgit_html_form=>c_field_type-number. + lv_type = 'number'. + ELSEIF is_field-password = abap_true. + lv_type = 'password'. + ELSE. + lv_type = 'text'. + ENDIF. + + IF is_field-min > 0. + lv_minlength = | minlength={ is_field-min }|. + ENDIF. + IF is_field-max > 0 AND is_field-max < cl_abap_math=>max_int4. + lv_maxlength = | maxlength={ is_field-max }|. + ENDIF. + + ii_html->add( || ). + + IF is_field-side_action IS NOT INITIAL. + ii_html->add( '
' ). + ii_html->add( '
' ). + ii_html->add( || ). + ii_html->add( '
' ). + ENDIF. + + ENDMETHOD. + METHOD render_field_textarea. + + DATA lv_rows TYPE string. + DATA lv_cols TYPE string. + DATA lv_html TYPE string. + + ii_html->add( || ). + + IF is_attr-error IS NOT INITIAL. + ii_html->add( is_attr-error ). + ENDIF. + + IF is_field-rows > 0. + lv_rows = | rows="{ is_field-rows }"|. + ELSEIF is_attr-value IS NOT INITIAL. + lv_rows = | rows="{ lines( zcl_abapgit_convert=>split_string( is_attr-value ) ) + 1 }"|. + ENDIF. + + IF is_field-cols > 0. + lv_cols = | cols="{ is_field-cols }"|. + ENDIF. + + " Avoid adding line-breaks inside textarea tag (except for the actual value) + lv_html = ||. + + ii_html->add( lv_html ). + + ENDMETHOD. + METHOD start_group. + + DATA ls_field LIKE LINE OF mt_fields. + + ls_field-type = zif_abapgit_html_form=>c_field_type-field_group. + ls_field-label = iv_label. + ls_field-name = iv_name. + ls_field-hint = iv_hint. + + APPEND ls_field TO mt_fields. + + ro_self = me. + + ENDMETHOD. + METHOD table. + + DATA ls_field LIKE LINE OF mt_fields. + + ls_field-type = zif_abapgit_html_form=>c_field_type-table. + ls_field-name = iv_name. + ls_field-label = iv_label. + ls_field-hint = iv_hint. + + APPEND ls_field TO mt_fields. + + ro_self = me. + + ENDMETHOD. + METHOD text. + + DATA ls_field LIKE LINE OF mt_fields. + + ls_field-type = zif_abapgit_html_form=>c_field_type-text. + ls_field-name = iv_name. + ls_field-label = iv_label. + ls_field-upper_case = iv_upper_case. + ls_field-readonly = iv_readonly. + ls_field-min = iv_min. + ls_field-max = iv_max. + ls_field-password = iv_password. + ls_field-condense = iv_condense. + ls_field-hint = iv_hint. + ls_field-required = iv_required. + ls_field-placeholder = iv_placeholder. + + IF iv_side_action IS NOT INITIAL AND mv_form_id IS NOT INITIAL. + ls_field-item_class = 'with-command'. + ls_field-side_action = iv_side_action. + ls_field-dblclick = | ondblclick="document.getElementById('{ mv_form_id }').action = 'sapevent:| + && |{ iv_side_action }'; document.getElementById('{ mv_form_id }').submit()"|. + ENDIF. + + APPEND ls_field TO mt_fields. + + ro_self = me. + + ENDMETHOD. + METHOD textarea. + + DATA ls_field LIKE LINE OF mt_fields. + + ls_field-type = zif_abapgit_html_form=>c_field_type-textarea. + ls_field-name = iv_name. + ls_field-label = iv_label. + ls_field-readonly = iv_readonly. + ls_field-hint = iv_hint. + ls_field-required = iv_required. + ls_field-placeholder = iv_placeholder. + ls_field-rows = iv_rows. + ls_field-cols = iv_cols. + ls_field-upper_case = iv_upper_case. + + APPEND ls_field TO mt_fields. + + ro_self = me. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + FIELD-SYMBOLS: TYPE zif_abapgit_html_form=>ty_command. + + ls_hotkey_action-ui_component = |Form-{ mv_form_id }|. + + READ TABLE mt_commands WITH KEY cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + ASSIGNING . + IF sy-subrc = 0. + ls_hotkey_action-description = -label. + ls_hotkey_action-action = -action. + ls_hotkey_action-hotkey = |Enter|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + ENDIF. + + READ TABLE mt_commands WITH KEY action = zif_abapgit_definitions=>c_action-go_back + ASSIGNING . + IF sy-subrc = 0. + ls_hotkey_action-description = -label. + ls_hotkey_action-action = -action. + ls_hotkey_action-hotkey = |F3|. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_html_action_utils IMPLEMENTATION. + METHOD add_field. + + DATA ls_field LIKE LINE OF ct_field. + + FIELD-SYMBOLS TYPE any. + + ls_field-name = iv_name. + + CASE cl_abap_typedescr=>describe_by_data( ig_field )->kind. + WHEN cl_abap_typedescr=>kind_elem. + ls_field-value = ig_field. + WHEN cl_abap_typedescr=>kind_struct. + ASSIGN COMPONENT iv_name OF STRUCTURE ig_field TO . + ASSERT IS ASSIGNED. + ls_field-value = . + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + + APPEND ls_field TO ct_field. + + ENDMETHOD. + METHOD dbkey_encode. + + DATA lt_fields TYPE ty_name_value_tt. + + add_field( EXPORTING iv_name = 'TYPE' + ig_field = is_key-type CHANGING ct_field = lt_fields ). + add_field( EXPORTING iv_name = 'VALUE' + ig_field = is_key-value CHANGING ct_field = lt_fields ). + + rv_string = fields_to_string( lt_fields ). + + ENDMETHOD. + METHOD dir_encode. + + DATA lt_fields TYPE ty_name_value_tt. + add_field( EXPORTING iv_name = 'PATH' + ig_field = iv_path CHANGING ct_field = lt_fields ). + rv_string = fields_to_string( lt_fields ). + + ENDMETHOD. + METHOD fields_to_string. + +* There is no equivalent to cl_http_utility=>fields_to_string released in ABAP Cloud, +* see cl_web_http_utility + + DATA lt_tab TYPE STANDARD TABLE OF string WITH DEFAULT KEY. + DATA lv_str TYPE string. + DATA ls_field LIKE LINE OF it_fields. + + LOOP AT it_fields INTO ls_field. + ls_field-value = cl_http_utility=>escape_url( ls_field-value ). + lv_str = ls_field-name && '=' && ls_field-value. + APPEND lv_str TO lt_tab. + ENDLOOP. + rv_string = concat_lines_of( + table = lt_tab + sep = '&' ). + + ENDMETHOD. + METHOD file_encode. + + DATA lt_fields TYPE ty_name_value_tt. + add_field( + EXPORTING + iv_name = 'KEY' + ig_field = iv_key + CHANGING + ct_field = lt_fields ). + + add_field( + EXPORTING + iv_name = 'PATH' + ig_field = ig_file + CHANGING + ct_field = lt_fields ). + + add_field( + EXPORTING + iv_name = 'FILENAME' + ig_field = ig_file + CHANGING + ct_field = lt_fields ). + + IF iv_extra IS SUPPLIED. + add_field( + EXPORTING + iv_name = 'EXTRA' + ig_field = iv_extra + CHANGING + ct_field = lt_fields ). + ENDIF. + + rv_string = fields_to_string( lt_fields ). + + ENDMETHOD. + METHOD jump_encode. + + DATA lt_fields TYPE ty_name_value_tt. + add_field( EXPORTING iv_name = 'TYPE' + ig_field = iv_obj_type CHANGING ct_field = lt_fields ). + add_field( EXPORTING iv_name = 'NAME' + ig_field = iv_obj_name CHANGING ct_field = lt_fields ). + + IF iv_filename IS NOT INITIAL. + add_field( EXPORTING iv_name = 'FILE' + ig_field = iv_filename CHANGING ct_field = lt_fields ). + ENDIF. + + rv_string = fields_to_string( lt_fields ). + + ENDMETHOD. + METHOD obj_encode. + + DATA lt_fields TYPE ty_name_value_tt. + add_field( EXPORTING iv_name = 'KEY' + ig_field = iv_key CHANGING ct_field = lt_fields ). + add_field( EXPORTING iv_name = 'OBJ_TYPE' + ig_field = ig_object CHANGING ct_field = lt_fields ). + add_field( EXPORTING iv_name = 'OBJ_NAME' + ig_field = ig_object CHANGING ct_field = lt_fields ). + + rv_string = fields_to_string( lt_fields ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_picklist IMPLEMENTATION. + METHOD constructor. + + FIELD-SYMBOLS TYPE STANDARD TABLE. + + super->constructor( ). + + " copy contents of table to local scope + CREATE DATA mr_list LIKE it_list. + ASSIGN mr_list->* TO . + APPEND LINES OF it_list TO . + + mv_attr_name = to_upper( iv_attr_name ). + mi_item_renderer = ii_item_renderer. + mv_in_page = iv_in_page. + mv_id = iv_id. + mv_title = iv_title. + + IF mi_item_renderer IS NOT BOUND AND mv_attr_name IS INITIAL. + zcx_abapgit_exception=>raise( 'Renderer or attr name required' ). + ENDIF. + + CREATE OBJECT mo_form_data. + CREATE OBJECT mo_validation_log. + mo_form = get_form_schema( ). + mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). + + ENDMETHOD. + METHOD get_form_schema. + + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + DATA lv_index TYPE i. + DATA lv_label TYPE string. + + ro_form = zcl_abapgit_html_form=>create( ). + + ro_form->radio( + iv_name = c_radio_name + iv_label = mv_title ). + + ASSIGN mr_list->* TO . + LOOP AT ASSIGNING . + lv_index = sy-tabix. + + IF mv_attr_name IS NOT INITIAL. + ASSIGN COMPONENT mv_attr_name OF STRUCTURE TO . + ASSERT sy-subrc = 0. + lv_label = . + ELSEIF mi_item_renderer IS BOUND. + lv_label = mi_item_renderer->render( + iv_item = + iv_index = lv_index )->render( ). + ENDIF. + + ro_form->option( + iv_label = lv_label + iv_value = |{ lv_index }| ). + + ENDLOOP. + + ro_form->command( + iv_label = 'Choose' + iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main + iv_action = c_event-choose + )->command( + iv_label = 'Back' + iv_action = c_event-back ). + + ENDMETHOD. + METHOD get_result_idx. + rv_index = mv_selected. + ENDMETHOD. + METHOD get_result_item. + + FIELD-SYMBOLS TYPE STANDARD TABLE. + + CLEAR cs_selected. + + IF mv_selected > 0. + ASSIGN mr_list->* TO . + READ TABLE INDEX mv_selected INTO cs_selected. + ASSERT sy-subrc = 0. + ENDIF. + + ENDMETHOD. + METHOD id. + rv_id = mv_id. + ENDMETHOD. + METHOD is_fulfilled. + rv_yes = mv_fulfilled. + ENDMETHOD. + METHOD is_in_page. + rv_yes = mv_in_page. + ENDMETHOD. + METHOD return_state. + IF mv_in_page = abap_true. + rv_state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + rv_state = zcl_abapgit_gui=>c_event_state-go_back. + ENDIF. + ENDMETHOD. + METHOD set_id. + mv_id = iv_id. + ro_me = me. + ENDMETHOD. + METHOD set_in_page. + mv_in_page = iv_in_page. + ro_me = me. + ENDMETHOD. + METHOD was_cancelled. + rv_yes = mv_cancelled. + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). + mo_validation_log->clear( ). + + CASE ii_event->mv_action. + WHEN c_event-back OR zif_abapgit_definitions=>c_action-go_back. + " Handle go_back as a "graceful back" - implicit cancel by F3/ESC + mv_fulfilled = abap_true. + mv_cancelled = abap_true. + rs_handled-state = return_state( ). + WHEN c_event-choose. + mv_selected = mo_form_data->get( c_radio_name ). + IF mv_selected = 0. + mo_validation_log->set( + iv_key = c_radio_name + iv_val = 'You have to select one item' ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ELSE. + mv_fulfilled = abap_true. + rs_handled-state = return_state( ). + ENDIF. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_page_title~get_page_title. + rv_title = mv_title. + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + ri_html = zcl_abapgit_html=>create( mo_form->render( + io_values = mo_form_data + io_validation_log = mo_validation_log ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_hoc IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + mi_child = ii_child_component. + ms_control = is_control. + + IF ms_control-show_as_modal = abap_false. + ms_control-show_as_modal = detect_modal( ). + ENDIF. + + IF ms_control-page_menu_provider IS NOT BOUND. + ms_control-page_menu_provider = detect_menu_provider( ). + ENDIF. + + IF ms_control-page_title_provider IS NOT BOUND. + ms_control-page_title_provider = detect_title_provider( ). + ENDIF. + + ENDMETHOD. + METHOD create. + + DATA lo_page TYPE REF TO zcl_abapgit_gui_page_hoc. + DATA ls_control TYPE zcl_abapgit_gui_page=>ty_control. + + ls_control-page_title = iv_page_title. + ls_control-page_layout = iv_page_layout. + ls_control-page_menu = io_page_menu. + ls_control-page_menu_provider = ii_page_menu_provider. + ls_control-page_title_provider = ii_page_title_provider. + ls_control-extra_css_url = iv_extra_css_url. + ls_control-extra_js_url = iv_extra_js_url. + ls_control-show_as_modal = iv_show_as_modal. + + IF ls_control-page_menu_provider IS NOT BOUND. " try component itself + TRY. + ls_control-page_menu_provider ?= ii_child_component. + CATCH cx_sy_move_cast_error ##NO_HANDLER. + ENDTRY. + ENDIF. + + IF ls_control-page_title_provider IS NOT BOUND. " try component itself + TRY. + ls_control-page_title_provider ?= ii_child_component. + CATCH cx_sy_move_cast_error ##NO_HANDLER. + ENDTRY. + ENDIF. + + CREATE OBJECT lo_page + EXPORTING + ii_child_component = ii_child_component + is_control = ls_control. + + ri_page_wrap = lo_page. + + ENDMETHOD. + METHOD detect_menu_provider. + TRY. + ri_ref ?= mi_child. + CATCH cx_sy_move_cast_error. + ENDTRY. + ENDMETHOD. + METHOD detect_modal. + + DATA li_modal TYPE REF TO zif_abapgit_gui_modal. + + TRY. + li_modal ?= mi_child. + rv_is_modal = li_modal->is_modal( ). + CATCH cx_sy_move_cast_error ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD detect_title_provider. + TRY. + ri_ref ?= mi_child. + CATCH cx_sy_move_cast_error ##NO_HANDLER. + ENDTRY. + ENDMETHOD. + METHOD get_child. + ri_child = mi_child. + ENDMETHOD. + METHOD render_content. + + IF mi_child IS BOUND. + ri_html = mi_child->render( ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + ms_control-page_layout = c_page_layout-centered. + + ENDMETHOD. + METHOD footer. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + + ENDMETHOD. + METHOD get_version_details. + + DATA lo_frontend_serv TYPE REF TO zif_abapgit_frontend_services. + + rv_version = zif_abapgit_version=>c_abap_version. + + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. + rv_version = rv_version && ` - Standalone Version`. + ELSE. + rv_version = rv_version && ` - Developer Version`. + ENDIF. + + lo_frontend_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + + CASE abap_true. + WHEN lo_frontend_serv->is_webgui( ). + rv_version = rv_version && ` - Web`. + WHEN lo_frontend_serv->is_sapgui_for_windows( ). + rv_version = rv_version && ` - Win`. + WHEN lo_frontend_serv->is_sapgui_for_java( ). + rv_version = rv_version && ` - Java`. + WHEN OTHERS. +* eg. open-abap? + rv_version = rv_version && ` - Unknown`. + ENDCASE. + + " Will be filled by JS method displayBrowserControlFooter + rv_version = rv_version && ''. + + ENDMETHOD. + METHOD header_script_links. + + ii_html->add( '' ). + + IF ms_control-extra_js_url IS NOT INITIAL. + ii_html->add( || ). + ENDIF. + + ENDMETHOD. + METHOD header_stylesheet_links. + + ii_html->add( '' ). + ii_html->add( '' ). + + " Themes + ii_html->add( '' ). " Theme basis + CASE mo_settings->get_ui_theme( ). + WHEN zcl_abapgit_settings=>c_ui_theme-dark. + ii_html->add( '' ). + WHEN zcl_abapgit_settings=>c_ui_theme-belize. + ii_html->add( '' ). + ENDCASE. + + " Page stylesheets + IF ms_control-extra_css_url IS NOT INITIAL. + ii_html->add( || ). + ENDIF. + + ENDMETHOD. + METHOD html_head. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + + ri_html->add( '' ). + ri_html->add( '' ). + + ri_html->add( 'abapGit' ). + + header_stylesheet_links( ri_html ). + header_script_links( ri_html ). + + " Overwrite the automatic icon scaling done in zcl_abapgit_html=>icon + CASE mo_settings->get_icon_scaling( ). + WHEN mo_settings->c_icon_scaling-large. + ri_html->add( '' ). + WHEN mo_settings->c_icon_scaling-small. + ri_html->add( '' ). + ENDCASE. + + ri_html->add( '' ). + + ENDMETHOD. + METHOD is_edge_control_warning_needed. + + DATA: + lv_gui_release TYPE zif_abapgit_frontend_services=>ty_gui_release, + lv_gui_sp TYPE zif_abapgit_frontend_services=>ty_gui_sp, + lv_gui_patch TYPE zif_abapgit_frontend_services=>ty_gui_patch, + li_frontend_services TYPE REF TO zif_abapgit_frontend_services. + + " With SAP GUI 8.00 PL3 and 7.70 PL13 Edge browser control is basically working. + " For lower releases we render the browser control warning + " and toggle it via JS function toggleBrowserControlWarning. + + rv_result = abap_true. + + TRY. + li_frontend_services = zcl_abapgit_ui_factory=>get_frontend_services( ). + li_frontend_services->get_gui_version( + IMPORTING + ev_gui_release = lv_gui_release + ev_gui_sp = lv_gui_sp + ev_gui_patch = lv_gui_patch ). + + CATCH zcx_abapgit_exception. + RETURN. + ENDTRY. + + IF lv_gui_release >= '7700' AND lv_gui_sp >= '1' AND lv_gui_patch >= '13' + OR lv_gui_release >= '8000' AND lv_gui_sp >= '1' AND lv_gui_patch >= '3'. + rv_result = abap_false. + ENDIF. + + ENDMETHOD. + METHOD render_browser_control_warning. + + DATA li_documentation_link TYPE REF TO zif_abapgit_html. + + CREATE OBJECT li_documentation_link TYPE zcl_abapgit_html. + + li_documentation_link->add_a( + iv_txt = 'Documentation' + iv_typ = zif_abapgit_html=>c_action_type-url + iv_act = 'https://docs.abapgit.org/guide-sapgui.html#sap-gui-for-windows' ). + + ii_html->add( '
' ). + ii_html->add( zcl_abapgit_gui_chunk_lib=>render_warning_banner( + |Attention: You use Edge browser control. | + && |There are several known malfunctions. See | + && li_documentation_link->render( ) ) ). + ii_html->add( '
' ). + + ENDMETHOD. + METHOD render_command_palettes. + + ii_html->add( 'var gCommandPalette = new CommandPalette(enumerateUiActions, {' ). + ii_html->add( ' toggleKey: "F1",' ). + ii_html->add( ' hotkeyDescription: "Command Palette"' ). + ii_html->add( '});' ). + + ENDMETHOD. + METHOD render_deferred_parts. + + DATA lt_parts TYPE zif_abapgit_html=>ty_table_of. + DATA li_part LIKE LINE OF lt_parts. + + lt_parts = gui_services( )->get_html_parts( )->get_parts( iv_part_category ). + LOOP AT lt_parts INTO li_part. + ii_html->add( li_part ). + ENDLOOP. + + ENDMETHOD. + METHOD render_error_message_box. + + " You should remember that the we have to instantiate ro_html even + " it's overwritten further down. Because ADD checks whether it's + " bound. + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + " You should remember that we render the message panel only + " if we have an error. + IF mx_error IS NOT BOUND. + RETURN. + ENDIF. + + ri_html = zcl_abapgit_gui_chunk_lib=>render_error_message_box( mx_error ). + + " You should remember that the exception viewer dispatches the events of + " error message panel + CREATE OBJECT mo_exception_viewer + EXPORTING + ix_error = mx_error. + + " You should remember that we render the message panel just once + " for each exception/error text. + CLEAR: + mx_error. + + ENDMETHOD. + METHOD render_hotkey_overview. + + DATA lo_hotkeys_component TYPE REF TO zif_abapgit_gui_renderable. + + lo_hotkeys_component ?= gui_services( )->get_hotkeys_ctl( ). " Mmmm ... + ro_html = lo_hotkeys_component->render( ). + + ENDMETHOD. + METHOD render_link_hints. + + DATA: lv_link_hint_key TYPE c LENGTH 1. + + lv_link_hint_key = mo_settings->get_link_hint_key( ). + + IF mo_settings->get_link_hints_enabled( ) = abap_true AND lv_link_hint_key IS NOT INITIAL. + + ii_html->add( |activateLinkHints("{ lv_link_hint_key }");| ). + ii_html->add( |setInitialFocusWithQuerySelector('#header', false);| ). + ii_html->add( |enableArrowListNavigation();| ). + + ENDIF. + + ENDMETHOD. + METHOD scripts. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + render_deferred_parts( + ii_html = ri_html + iv_part_category = c_html_parts-scripts ). + + render_link_hints( ri_html ). + render_command_palettes( ri_html ). + ri_html->add( |toggleBrowserControlWarning();| ). + ri_html->add( |displayBrowserControlFooter();| ). + + ENDMETHOD. + METHOD title. + + DATA lo_page_menu LIKE ms_control-page_menu. + DATA lv_page_title TYPE string. + + lo_page_menu = ms_control-page_menu. + IF lo_page_menu IS NOT BOUND AND ms_control-page_menu_provider IS BOUND. + lo_page_menu = ms_control-page_menu_provider->get_menu( ). + ENDIF. + + zcl_abapgit_exit=>get_instance( )->enhance_any_toolbar( lo_page_menu ). + + lv_page_title = ms_control-page_title. + IF ms_control-page_title_provider IS BOUND. + lv_page_title = ms_control-page_title_provider->get_page_title( ). + ENDIF. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + + ENDMETHOD. + METHOD zif_abapgit_gui_error_handler~handle_error. + + mx_error = ix_error. + rv_handled = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + CASE ii_event->mv_action. + WHEN zif_abapgit_definitions=>c_action-goto_source. + + IF mo_exception_viewer IS BOUND. + mo_exception_viewer->goto_source( ). + ENDIF. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + WHEN zif_abapgit_definitions=>c_action-show_callstack. + + IF mo_exception_viewer IS BOUND. + mo_exception_viewer->show_callstack( ). + ENDIF. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + WHEN zif_abapgit_definitions=>c_action-goto_message. + + IF mo_exception_viewer IS BOUND. + mo_exception_viewer->goto_message( ). + ENDIF. + rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_modal~is_modal. + rv_yes = boolc( ms_control-show_as_modal = abap_true ). + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA: + li_script TYPE REF TO zif_abapgit_html, + lo_timer TYPE REF TO zcl_abapgit_timer. + + register_handlers( ). + + lo_timer = zcl_abapgit_timer=>create( )->start( ). + + " Real page + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( html_head( ) ). + ri_html->add( || ). + + ri_html->add( title( ) ). + + ri_html->add( '
' ). + + ri_html->add( render_content( ) ). " TODO -> render child + + ri_html->add( render_hotkey_overview( ) ). + ri_html->add( render_error_message_box( ) ). + + render_deferred_parts( + ii_html = ri_html + iv_part_category = c_html_parts-hidden_forms ). + + ri_html->add( footer( lo_timer->end( ) ) ). + + ri_html->add( '
' ). + + li_script = scripts( ). + + IF li_script IS BOUND AND li_script->is_empty( ) = abap_false. + ri_html->add( '' ). + ENDIF. + + ri_html->add( '' ). + ri_html->add( '' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_menus IMPLEMENTATION. + METHOD advanced. + + ro_menu = zcl_abapgit_html_toolbar=>create( 'toolbar-advanced' ). + + ro_menu->add( + iv_txt = 'Database Utility' + iv_act = zif_abapgit_definitions=>c_action-go_db + )->add( + iv_txt = 'Package to ZIP' + iv_act = zif_abapgit_definitions=>c_action-zip_package + )->add( + iv_txt = 'Transport to ZIP' + iv_act = zif_abapgit_definitions=>c_action-zip_transport + )->add( + iv_txt = 'Object to Files' + iv_act = zif_abapgit_definitions=>c_action-zip_object + )->add( + iv_txt = 'Debug Info' + iv_act = zif_abapgit_definitions=>c_action-go_debuginfo ). + + IF zcl_abapgit_ui_factory=>get_frontend_services( )->is_sapgui_for_windows( ) = abap_true. + ro_menu->add( + iv_txt = 'Open IE DevTools' + iv_act = zif_abapgit_definitions=>c_action-ie_devtools ). + ENDIF. + + ENDMETHOD. + METHOD back. + + ro_menu = zcl_abapgit_html_toolbar=>create( 'toolbar-back' ). + + ro_menu->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD experimental. + + IF zcl_abapgit_persist_factory=>get_settings( )->read( )->get_experimental_features( ) IS NOT INITIAL. + io_menu->add( + iv_txt = zcl_abapgit_gui_buttons=>experimental( ) + iv_act = zif_abapgit_definitions=>c_action-go_settings ). + ENDIF. + + ENDMETHOD. + METHOD help. + + ro_menu = zcl_abapgit_html_toolbar=>create( 'toolbar-help' ). + + ro_menu->add( + iv_txt = 'Tutorial' + iv_act = zif_abapgit_definitions=>c_action-go_tutorial + )->add( + iv_txt = 'Documentation' + iv_act = zif_abapgit_definitions=>c_action-documentation + )->add( + iv_txt = 'Explore' + iv_act = zif_abapgit_definitions=>c_action-go_explore + )->add( + iv_txt = 'Changelog' + iv_act = zif_abapgit_definitions=>c_action-changelog + )->add( + iv_txt = 'Hotkeys' + iv_act = zif_abapgit_definitions=>c_action-show_hotkeys ). + + ENDMETHOD. + METHOD repo_settings. + + ro_menu = zcl_abapgit_html_toolbar=>create( 'toolbar-repo-settings' ). + + ro_menu->add( + iv_txt = 'Repository' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_settings }?key={ iv_key }| + iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_settings ) + )->add( + iv_txt = 'Local' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_local_settings }?key={ iv_key }| + iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_local_settings ) + )->add( + iv_txt = 'Remote' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_remote_settings }?key={ iv_key }| + iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_remote_settings ) + )->add( + iv_txt = 'Background' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_background }?key={ iv_key }| + iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_background ) + )->add( + iv_txt = 'Stats' + iv_act = |{ zif_abapgit_definitions=>c_action-repo_infos }?key={ iv_key }| + iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_infos ) ). + + zcl_abapgit_exit=>get_instance( )->enhance_repo_toolbar( + io_menu = ro_menu + iv_key = iv_key + iv_act = iv_act ). + + ENDMETHOD. + METHOD settings. + + ro_menu = zcl_abapgit_html_toolbar=>create( 'toolbar-abapgit-settings' ). + + ro_menu->add( + iv_txt = 'Global' + iv_act = zif_abapgit_definitions=>c_action-go_settings + iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-go_settings ) + )->add( + iv_txt = 'Personal' + iv_act = zif_abapgit_definitions=>c_action-go_settings_personal + iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-go_settings_personal ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_in_page_modal IMPLEMENTATION. + METHOD constructor. + + ms_attrs-width = iv_width. + ms_attrs-height = iv_height. + mi_child = ii_child. + + ENDMETHOD. + METHOD create. + CREATE OBJECT ro_wrap + EXPORTING + ii_child = ii_child + iv_width = iv_width + iv_height = iv_height. + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA lo_style TYPE REF TO zcl_abapgit_string_buffer. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + CREATE OBJECT lo_style. + + IF ms_attrs-width IS NOT INITIAL. + lo_style->add( |width:{ ms_attrs-width }px;| ). + ENDIF. + IF ms_attrs-height IS NOT INITIAL. + lo_style->add( |height:{ ms_attrs-height }px;| ). + ENDIF. + + ri_html->add( || ). + ri_html->add( || ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_COMPONENT IMPLEMENTATION. + METHOD gui_services. + IF mi_gui_services IS NOT BOUND. + mi_gui_services = zcl_abapgit_ui_factory=>get_gui_services( ). + ENDIF. + ri_gui_services = mi_gui_services. + ENDMETHOD. + METHOD register_deferred_script. + gui_services( )->get_html_parts( )->add_part( + iv_collection = c_html_parts-scripts + ii_part = ii_part ). + ENDMETHOD. + METHOD register_event_handler. + + DATA li_event_handler TYPE REF TO zif_abapgit_gui_event_handler. + + IF ii_event_handler IS BOUND. + li_event_handler = ii_event_handler. + ELSE. + TRY. + li_event_handler ?= me. + CATCH cx_root. + RETURN. + ENDTRY. + ENDIF. + + gui_services( )->register_event_handler( li_event_handler ). + + ENDMETHOD. + METHOD register_handlers. + register_event_handler( ). + register_hotkeys( ). + ENDMETHOD. + METHOD register_hotkeys. + + DATA li_hotkey_provider TYPE REF TO zif_abapgit_gui_hotkeys. + + IF ii_hotkey_provider IS BOUND. + li_hotkey_provider = ii_hotkey_provider. + ELSE. + TRY. + li_hotkey_provider ?= me. + CATCH cx_root. + RETURN. + ENDTRY. + ENDIF. + + gui_services( )->get_hotkeys_ctl( )->register_hotkeys( li_hotkey_provider->get_hotkey_actions( ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_chunk_lib IMPLEMENTATION. + METHOD class_constructor. + + DATA lv_fm TYPE string. + lv_fm = 'GET_SYSTEM_TIMEZONE'. + + TRY. + CALL METHOD ('CL_ABAP_TSTMP')=>get_system_timezone + RECEIVING + system_timezone = gv_time_zone. + CATCH cx_sy_dyn_call_illegal_method. + CALL FUNCTION lv_fm + IMPORTING + timezone = gv_time_zone + EXCEPTIONS + customizing_missing = 1 + OTHERS = 2 ##FM_SUBRC_OK. + ENDTRY. + + ENDMETHOD. + METHOD get_item_icon. + + CASE is_item-obj_type. + WHEN 'PROG' OR 'CLAS' OR 'FUGR' OR 'INTF' OR 'TYPE'. + rv_html = zcl_abapgit_html=>icon( iv_name = 'file-code/darkgrey' + iv_hint = 'Code' ). + WHEN 'W3MI' OR 'W3HT' OR 'SFPF'. + rv_html = zcl_abapgit_html=>icon( iv_name = 'file-image/darkgrey' + iv_hint = 'Binary' ). + WHEN 'DEVC'. + rv_html = zcl_abapgit_html=>icon( iv_name = 'box/darkgrey' + iv_hint = 'Package' ). + WHEN ''. + rv_html = space. " no icon + WHEN OTHERS. + rv_html = zcl_abapgit_html=>icon( 'file-alt/darkgrey' ). + ENDCASE. + + IF is_item-is_dir = abap_true. + rv_html = zcl_abapgit_html=>icon( iv_name = 'folder/darkgrey' + iv_hint = 'Folder' ). + ENDIF. + + ENDMETHOD. + METHOD get_item_link. + + DATA lv_encode TYPE string. + DATA li_html TYPE REF TO zif_abapgit_html. + DATA ls_item LIKE is_item. + + IF is_item IS INITIAL. + ls_item-obj_type = iv_obj_type. + ls_item-obj_name = iv_obj_name. + ELSE. + ls_item = is_item. + ENDIF. + + CREATE OBJECT li_html TYPE zcl_abapgit_html. + + lv_encode = zcl_abapgit_html_action_utils=>jump_encode( + iv_obj_type = ls_item-obj_type + iv_obj_name = ls_item-obj_name ). + + rv_html = li_html->a( + iv_txt = |{ ls_item-obj_name }| + iv_act = |{ zif_abapgit_definitions=>c_action-jump }?{ lv_encode }| ). + + ENDMETHOD. + METHOD get_t100_text. + + MESSAGE ID iv_msgid TYPE 'S' NUMBER iv_msgno WITH '&1' '&2' '&3' '&4' INTO rv_text. + + " Don't return any generic messages like `&1 &2 &3 &4` + IF rv_text CO ' 0123456789&'. + CLEAR rv_text. + ENDIF. + + ENDMETHOD. + METHOD normalize_program_name. + + rv_normalized_program_name = substring_before( + val = iv_program_name + regex = `(=+CP)?$` ). + + ENDMETHOD. + METHOD render_branch_name. + + DATA: + lv_key TYPE string, + lv_branch TYPE string, + lv_selected_commit TYPE string, + lv_commit_short_sha TYPE string, + lv_text TYPE string, + lv_icon TYPE string, + lv_hint TYPE string, + lv_class TYPE string, + li_repo TYPE REF TO zif_abapgit_repo. + + IF iv_repo_key IS NOT INITIAL. + lv_key = iv_repo_key. + ELSEIF ii_repo_online IS BOUND. + li_repo = ii_repo_online. + lv_key = li_repo->get_key( ). + ELSE. + zcx_abapgit_exception=>raise( 'Either iv_repo_key or ii_repo_online must be supplied' ). + ENDIF. + + IF iv_branch IS NOT INITIAL. + lv_branch = iv_branch. + lv_text = zcl_abapgit_git_branch_utils=>get_display_name( lv_branch ). + ELSEIF ii_repo_online IS BOUND. + lv_selected_commit = ii_repo_online->get_selected_commit( ). + IF lv_selected_commit IS NOT INITIAL. + "Convert to short commit. Example: (ae623b9...) + lv_commit_short_sha = lv_selected_commit+0(7). + lv_text = |({ lv_commit_short_sha }...)|. + ELSE. + lv_branch = ii_repo_online->get_selected_branch( ). + lv_text = zcl_abapgit_git_branch_utils=>get_display_name( lv_branch ). + ENDIF. + ELSE. + zcx_abapgit_exception=>raise( 'Either iv_branch or ii_repo_online must be supplied' ). + ENDIF. + + CASE zcl_abapgit_git_branch_utils=>get_type( lv_branch ). + WHEN zif_abapgit_git_definitions=>c_git_branch_type-branch. + lv_class = 'branch branch_branch'. + lv_icon = 'code-branch/grey70'. + lv_hint = 'Current branch'. + WHEN zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag + OR zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. + lv_class = 'branch'. + lv_icon = 'tag-solid/grey70'. + lv_hint = 'Current tag'. + WHEN OTHERS. + lv_class = 'branch branch_branch'. + lv_icon = 'code-branch/grey70'. + lv_hint = 'Current commit'. + ENDCASE. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( || ). + ri_html->add_icon( iv_name = lv_icon + iv_hint = lv_hint ). + IF iv_interactive = abap_true. + ri_html->add_a( iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_switch }?key={ lv_key }| + iv_txt = lv_text ). + ELSE. + ri_html->add( lv_text ). + ENDIF. + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_error. + + DATA lv_error TYPE string. + DATA lv_class TYPE string VALUE 'panel error center'. + + IF iv_extra_style IS NOT INITIAL. + lv_class = lv_class && ` ` && iv_extra_style. + ENDIF. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF ix_error IS BOUND. + lv_error = ix_error->get_text( ). + ELSE. + lv_error = iv_error. + ENDIF. + + ri_html->add( |
| ). + ri_html->add( |{ ri_html->icon( 'exclamation-circle/red' ) } { lv_error }| ). + ri_html->add( '
' ). + + ENDMETHOD. + METHOD render_error_message_box. + + DATA: + lv_error_text TYPE string, + lv_longtext TYPE string, + lt_longtext_paragraphs TYPE string_table, + lv_program_name TYPE sy-repid, + lv_title TYPE string, + lv_text TYPE string. + FIELD-SYMBOLS: + TYPE string. + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + lv_error_text = ix_error->get_text( ). + lv_longtext = ix_error->if_message~get_longtext( abap_true ). + + IF lv_longtext IS NOT INITIAL. + lv_error_text = |{ lv_error_text } More...|. + + REPLACE FIRST OCCURRENCE OF REGEX + |({ zcx_abapgit_exception=>c_section_text-cause }{ cl_abap_char_utilities=>newline })| + IN lv_longtext WITH |

$1

|. + + REPLACE FIRST OCCURRENCE OF REGEX + |({ zcx_abapgit_exception=>c_section_text-system_response }{ cl_abap_char_utilities=>newline })| + IN lv_longtext WITH |

$1

|. + + REPLACE FIRST OCCURRENCE OF REGEX + |({ zcx_abapgit_exception=>c_section_text-what_to_do }{ cl_abap_char_utilities=>newline })| + IN lv_longtext WITH |

$1

|. + + REPLACE FIRST OCCURRENCE OF REGEX + |({ zcx_abapgit_exception=>c_section_text-sys_admin }{ cl_abap_char_utilities=>newline })| + IN lv_longtext WITH |

$1

|. + + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf + IN lv_longtext + WITH cl_abap_char_utilities=>newline. + + SPLIT lv_longtext AT cl_abap_char_utilities=>newline INTO TABLE lt_longtext_paragraphs. + CLEAR lv_longtext. + + LOOP AT lt_longtext_paragraphs ASSIGNING . + CONDENSE . + + IF IS INITIAL. + CONTINUE. + ENDIF. + + lv_longtext = |{ lv_longtext }

{ }

{ cl_abap_char_utilities=>newline }|. + ENDLOOP. + + lv_longtext = |{ lv_longtext }
|. + ENDIF. + + ri_html->add( |
| ). + ri_html->add( |{ ri_html->icon( 'exclamation-circle/red' ) } { lv_error_text }| ). + ri_html->add( |
| ). + + ri_html->add_a( + iv_txt = `❌` + iv_act = `toggleDisplay('message')` + iv_class = `close-btn` + iv_typ = zif_abapgit_html=>c_action_type-onclick ). + + ri_html->add( |
| ). + + ri_html->add( |
| ). + + IF ix_error->if_t100_message~t100key-msgid IS NOT INITIAL. + + lv_title = get_t100_text( + iv_msgid = ix_error->if_t100_message~t100key-msgid + iv_msgno = ix_error->if_t100_message~t100key-msgno ). + + IF lv_title IS NOT INITIAL. + lv_text = |Message E{ ix_error->if_t100_message~t100key-msgno }({ ix_error->if_t100_message~t100key-msgid })|. + + ri_html->add_a( + iv_txt = lv_text + iv_typ = zif_abapgit_html=>c_action_type-sapevent + iv_act = zif_abapgit_definitions=>c_action-goto_message + iv_title = lv_title + iv_id = `a_goto_message` ). + ENDIF. + ENDIF. + + ix_error->get_source_position( IMPORTING program_name = lv_program_name ). + + lv_title = normalize_program_name( lv_program_name ). + + ri_html->add_a( + iv_txt = `Goto source` + iv_act = zif_abapgit_definitions=>c_action-goto_source + iv_typ = zif_abapgit_html=>c_action_type-sapevent + iv_title = lv_title + iv_id = `a_goto_source` ). + + ri_html->add_a( + iv_txt = `Callstack` + iv_act = zif_abapgit_definitions=>c_action-show_callstack + iv_typ = zif_abapgit_html=>c_action_type-sapevent + iv_id = `a_callstack` ). + + ri_html->add( |
| ). + ri_html->add( |
| ). + ri_html->add( |{ lv_longtext }| ). + ri_html->add( |
| ). + ri_html->add( |
| ). + + ENDMETHOD. + METHOD render_event_as_form. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( + |
| ). + + ENDMETHOD. + METHOD render_help_hint. + + DATA li_html TYPE REF TO zif_abapgit_html. + DATA lv_add_class TYPE string. + + li_html = zcl_abapgit_html=>create( ). + + IF iv_add_class IS NOT INITIAL. + lv_add_class = ` ` && iv_add_class. + ENDIF. + + li_html->add( |
| ). + li_html->add_icon( + iv_name = 'question-circle-solid' + iv_class = 'blue' ). + li_html->add( `
` ). + li_html->add( iv_text_to_wrap ). + li_html->add( `
` ). + li_html->add( `
` ). + + rv_html = li_html->render( iv_no_line_breaks = abap_true ). + + ENDMETHOD. + METHOD render_infopanel. + + DATA lv_display TYPE string. + DATA lv_class TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF iv_hide = abap_true. " Initially hide + lv_display = 'display:none'. + ENDIF. + + lv_class = 'info-panel'. + IF iv_scrollable = abap_false. " Initially hide + lv_class = lv_class && ' info-panel-fixed'. + ENDIF. + + ri_html->add( |
| ). + + ri_html->add( |
{ iv_title }| + && '
' + && ri_html->a( + iv_txt = '❌' + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_act = |toggleDisplay('{ iv_div_id }')| + iv_class = 'close-btn' ) + && '
' ). + + IF iv_hint IS NOT INITIAL. + ri_html->add( '
' + && ri_html->icon( iv_name = 'exclamation-triangle' + iv_class = 'pad-right' ) + && iv_hint + && '
' ). + ENDIF. + + ri_html->add( |
| ). + ri_html->add( io_content ). + ri_html->add( '
' ). + ri_html->add( '
' ). + + ENDMETHOD. + METHOD render_item_state. + + DATA: lv_system TYPE string. + + FIELD-SYMBOLS TYPE char1. + rv_html = ''. + + DO 2 TIMES. + CASE sy-index. + WHEN 1. + ASSIGN iv_lstate TO . + lv_system = 'Local:'. + WHEN 2. + ASSIGN iv_rstate TO . + lv_system = 'Remote:'. + ENDCASE. + + CASE . + WHEN zif_abapgit_definitions=>c_state-unchanged. "None or unchanged + IF iv_lstate = zif_abapgit_definitions=>c_state-added OR iv_rstate = zif_abapgit_definitions=>c_state-added. + rv_html = rv_html && |X|. + ELSE. + rv_html = rv_html && | |. + ENDIF. + WHEN zif_abapgit_definitions=>c_state-modified. "Changed + rv_html = rv_html && |M|. + WHEN zif_abapgit_definitions=>c_state-added. "Added new + rv_html = rv_html && |A|. + WHEN zif_abapgit_definitions=>c_state-mixed. "Multiple changes (multifile) + rv_html = rv_html && ||. + WHEN zif_abapgit_definitions=>c_state-deleted. "Deleted + rv_html = rv_html && |D|. + ENDCASE. + ENDDO. + + rv_html = rv_html && ''. + + ENDMETHOD. + METHOD render_js_error_banner. + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '
' ). + ri_html->add( |{ ri_html->icon( 'exclamation-triangle/red' ) }| && + ' If this does not disappear soon,' && + ' then there is a JS init error, please log an issue' ). + ri_html->add( '
' ). + ENDMETHOD. + METHOD render_label_list. + + DATA lt_fragments TYPE string_table. + DATA lv_l TYPE string. + DATA lv_class TYPE string. + DATA lv_class_cmd TYPE string. + DATA lv_style TYPE string. + DATA ls_parsed_color TYPE zcl_abapgit_repo_labels=>ty_color. + DATA li_html TYPE REF TO zif_abapgit_html. + + IF it_labels IS INITIAL. + RETURN. + ENDIF. + + lv_class_cmd = 'command'. + IF iv_unlisted = abap_true. + lv_class_cmd = lv_class_cmd && ' unlisted'. + ENDIF. + + li_html = zcl_abapgit_html=>create( ). + + APPEND `
    ` TO lt_fragments. + + LOOP AT it_labels INTO lv_l WHERE table_line IS NOT INITIAL. + CLEAR lv_class. + CLEAR lv_style. + ls_parsed_color = zcl_abapgit_repo_labels=>parse_color( io_label_colors->get( lv_l ) ). + IF ls_parsed_color-cls IS NOT INITIAL. + lv_class = | class="rl-{ ls_parsed_color-cls }"|. + ELSEIF ls_parsed_color-fg IS NOT INITIAL OR ls_parsed_color-bg IS NOT INITIAL. + lv_style = ` style="`. + IF ls_parsed_color-fg IS NOT INITIAL. + lv_style = lv_style && |color:#{ ls_parsed_color-fg };|. + ENDIF. + IF ls_parsed_color-bg IS NOT INITIAL. + lv_style = lv_style && |background-color:#{ ls_parsed_color-bg };|. + IF ls_parsed_color-border IS INITIAL. + lv_style = lv_style && |border-color:#{ ls_parsed_color-bg };|. + ELSE. + lv_style = lv_style && |border-color:#{ ls_parsed_color-border };|. + ENDIF. + ENDIF. + lv_style = lv_style && `"`. + ENDIF. + + IF iv_clickable_action IS NOT INITIAL. + lv_l = li_html->a( + iv_txt = lv_l + iv_act = |{ iv_clickable_action }| + iv_class = lv_class_cmd + iv_query = lv_l ). + ENDIF. + lv_l = |{ lv_l }|. + APPEND lv_l TO lt_fragments. + ENDLOOP. + + APPEND `
` TO lt_fragments. + + rv_html = concat_lines_of( lt_fragments ). + + ENDMETHOD. + METHOD render_news. + + DATA: lv_text TYPE string, + lv_hint TYPE string, + lv_ul TYPE abap_bool, + lt_log TYPE zcl_abapgit_repo_news=>ty_logs. + + FIELD-SYMBOLS: LIKE LINE OF lt_log. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF io_news IS NOT BOUND OR io_news->has_news( ) = abap_false. + RETURN. + ENDIF. + + lt_log = io_news->get_log( ). + + " Render news + LOOP AT lt_log ASSIGNING . + IF -is_header = abap_true. + IF -pos_to_cur > 0. + lv_text = -text && 'update'. + ELSEIF -pos_to_cur = 0. + lv_text = -text && 'current'. + ELSE. " < 0 + lv_text = -text. + ENDIF. + IF lv_ul = abap_true. + ri_html->add( || ). + ENDIF. + ri_html->add( |

{ lv_text }

| ). + ri_html->add( |
    | ). + lv_ul = abap_true. + ELSE. + -text = escape( val = -text + format = cl_abap_format=>e_html_text ). + ri_html->add( |
  • { -text }
  • | ). + ENDIF. + ENDLOOP. + IF lv_ul = abap_true. + ri_html->add( |
| ). + ENDIF. + + " Wrap + IF io_news->has_important( ) = abap_true. + lv_hint = 'Please note changes marked with "!"'. + ENDIF. + + ri_html = render_infopanel( + iv_div_id = 'news' + iv_title = 'Announcement of the latest changes' + iv_hint = lv_hint + iv_hide = boolc( io_news->has_unseen( ) = abap_false ) + io_content = ri_html ). + + ENDMETHOD. + METHOD render_package_name. + + DATA: + lv_obj_name TYPE tadir-obj_name, + lv_jump TYPE string, + lv_title TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF iv_package IS INITIAL. + RETURN. + ENDIF. + + IF iv_suppress_title = abap_false. + lv_title = zcl_abapgit_factory=>get_sap_package( iv_package )->read_description( ). + ENDIF. + + lv_obj_name = iv_package. + lv_jump = zcl_abapgit_html_action_utils=>jump_encode( + iv_obj_type = 'DEVC' + iv_obj_name = lv_obj_name ). + + ri_html->add( || ). + ri_html->add_icon( iv_name = 'box/grey70' + iv_hint = 'SAP package' ). + IF iv_interactive = abap_true. + ri_html->add_a( iv_act = |{ zif_abapgit_definitions=>c_action-jump }?{ lv_jump }| + iv_title = lv_title + iv_txt = |{ iv_package }| ). + ELSE. + ri_html->add( iv_package ). + ENDIF. + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_path. + + DATA: + lv_path TYPE string, + lv_jump TYPE string, + lv_folder TYPE string, + lt_folders TYPE STANDARD TABLE OF string WITH DEFAULT KEY. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF iv_path IS INITIAL. + RETURN. + ENDIF. + + lv_jump = |{ zcl_abapgit_gui_page_repo_view=>c_actions-change_dir }?PATH=|. + + ri_html->add( || ). + + IF iv_interactive = abap_true. + SPLIT iv_path AT '/' INTO TABLE lt_folders. + + LOOP AT lt_folders INTO lv_folder. + IF lv_folder IS INITIAL. + " root + lv_path = '/'. + ELSEIF sy-tabix < lines( lt_folders ). + lv_path = lv_path && lv_folder && '/'. + ri_html->add_a( iv_act = lv_jump && lv_path + iv_txt = lv_folder ). + ELSE. + " no link for current folder + ri_html->add( | { lv_folder } | ). + ENDIF. + ri_html->add( '/' ). + ENDLOOP. + ELSE. + ri_html->add( iv_path ). + ENDIF. + + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_repo_palette. + + DATA lt_repo_obj_list TYPE zif_abapgit_repo_srv=>ty_repo_list. + DATA lt_repo_list TYPE zif_abapgit_persistence=>ty_repos. + DATA lv_repo_json TYPE string. + DATA lv_size TYPE i. + DATA ls_repo_data LIKE LINE OF lt_repo_list. + + FIELD-SYMBOLS: + LIKE LINE OF lt_repo_list, + LIKE LINE OF lt_repo_obj_list. + + lt_repo_obj_list = zcl_abapgit_repo_srv=>get_instance( )->list( ). + + LOOP AT lt_repo_obj_list ASSIGNING . + ls_repo_data = ->ms_data. + ls_repo_data-local_settings-display_name = ->get_name( ). + APPEND ls_repo_data TO lt_repo_list. + ENDLOOP. + + lv_size = lines( lt_repo_list ). + SORT lt_repo_list BY local_settings-display_name AS TEXT. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( 'var repoCatalog = [' ). " Maybe separate this into another method if needed in more places + LOOP AT lt_repo_list ASSIGNING . + lv_repo_json = |\{ key: "{ -key + }", isOffline: "{ -offline + }", displayName: "{ escape( val = -local_settings-display_name + format = cl_abap_format=>e_html_js ) }" \}|. + IF sy-tabix < lv_size. + lv_repo_json = lv_repo_json && ','. + ENDIF. + ri_html->add( lv_repo_json ). + ENDLOOP. + ri_html->add( '];' ). + + ri_html->add( |var gGoRepoPalette = new CommandPalette(createRepoCatalogEnumerator(repoCatalog, "{ + iv_action }"), \{| ). + ri_html->add( ' toggleKey: "F2",' ). + ri_html->add( ' hotkeyDescription: "Go to Repository ..."' ). + ri_html->add( '});' ). + + ENDMETHOD. + METHOD render_repo_top. + + DATA: li_repo_online TYPE REF TO zif_abapgit_repo_online, + lx_error TYPE REF TO zcx_abapgit_exception, + lv_hint TYPE string, + lv_icon TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF ii_repo->is_offline( ) = abap_true. + lv_icon = 'plug/darkgrey'. + lv_hint = 'Offline Repository'. + ELSE. + lv_icon = 'cloud-upload-alt/blue'. + lv_hint = 'On-line Repository'. + ENDIF. + + ri_html->add( '' ). + + ri_html->add( '' ). + + ri_html->add( '' ). + ri_html->add( '
' ). + + " Repo type and name + ri_html->add_icon( iv_name = lv_icon + iv_hint = lv_hint ). + ri_html->add( |{ ii_repo->get_name( ) }| ). + IF ii_repo->is_offline( ) = abap_false. + li_repo_online ?= ii_repo. + + ri_html->add( render_repo_url( li_repo_online->get_url( ) ) ). + ENDIF. + + IF iv_show_edit = abap_true. + ri_html->add_a( iv_txt = ri_html->icon( iv_name = 'edit-solid' + iv_class = 'pad-sides' + iv_hint = 'Change Remote' ) + iv_act = |{ zif_abapgit_definitions=>c_action-repo_remote_settings }?| && + |key={ ii_repo->get_key( ) }| + iv_class = |url| ). + ENDIF. + + IF ii_repo->is_offline( ) = abap_false. + li_repo_online ?= ii_repo. + + ri_html->add_a( iv_txt = ri_html->icon( iv_name = 'copy-solid' + iv_class = 'pad-sides' + iv_hint = 'Copy URL to Clipboard' ) + iv_act = |{ zif_abapgit_definitions=>c_action-clipboard }| && + |?clipboard={ li_repo_online->get_url( ) }| + iv_class = |url| ). + ENDIF. + + IF ii_repo->is_offline( ) = abap_false AND iv_show_commit = abap_true. + TRY. + render_repo_top_commit_hash( ii_html = ri_html + ii_repo_online = li_repo_online ). + CATCH zcx_abapgit_exception INTO lx_error. + " In case of missing or wrong credentials, show message in status bar + lv_hint = lx_error->get_text( ). + IF lv_hint CS 'credentials'. + MESSAGE lv_hint TYPE 'S' DISPLAY LIKE 'E'. + ENDIF. + ENDTRY. + ENDIF. + + " News + IF io_news IS BOUND AND io_news->has_news( ) = abap_true. + IF io_news->has_updates( ) = abap_true. + lv_icon = 'arrow-circle-up/warning'. + ELSE. + lv_icon = 'arrow-circle-up'. + ENDIF. + ri_html->add_a( iv_act = |toggleDisplay('news')| + iv_typ = zif_abapgit_html=>c_action_type-onclick + iv_txt = ri_html->icon( iv_name = lv_icon + iv_class = 'pad-sides' + iv_hint = 'Display Changelog' ) + iv_class = |url| ). + ENDIF. + ri_html->add( '' ). + + " Fav + IF abap_true = zcl_abapgit_persist_factory=>get_user( )->is_favorite_repo( ii_repo->get_key( ) ). + lv_icon = 'star/blue'. + ELSE. + lv_icon = 'star/grey'. + ENDIF. + IF iv_interactive_favorite = abap_true. + ri_html->add_a( iv_act = |{ zif_abapgit_definitions=>c_action-repo_toggle_fav }?key={ ii_repo->get_key( ) }| + iv_txt = ri_html->icon( iv_name = lv_icon + iv_class = 'pad-sides' + iv_hint = 'Toggle Favorite' ) ). + ELSE. + ri_html->add( ri_html->icon( + iv_name = lv_icon + iv_class = 'pad-sides' ) ). + ENDIF. + + " BG + IF zcl_abapgit_persist_factory=>get_background( )->exists( ii_repo->get_key( ) ) = abap_true. + ri_html->add( 'BG' ). + ENDIF. + + " Write protect + IF ii_repo->get_local_settings( )-write_protected = abap_true. + ri_html->add_icon( iv_name = 'lock/grey70' + iv_hint = 'Locked from Pulls' ). + ENDIF. + IF ii_repo->get_local_settings( )-flow = abap_true. + ri_html->add_icon( iv_name = 'flow/grey70' + iv_hint = 'Flow' ). + ENDIF. + + " Branch + IF ii_repo->is_offline( ) = abap_false. + li_repo_online ?= ii_repo. + IF iv_show_branch = abap_true. + ri_html->add( render_branch_name( ii_repo_online = li_repo_online + iv_interactive = iv_interactive_branch ) ). + ENDIF. + ENDIF. + + " Package + IF iv_show_package = abap_true. + ri_html->add( render_package_name( ii_repo->get_package( ) ) ). + ENDIF. + + ri_html->add( '
' ). + + ENDMETHOD. + METHOD render_repo_top_commit_hash. + + DATA: lv_commit_hash TYPE zif_abapgit_git_definitions=>ty_sha1, + lv_commit_short_hash TYPE zif_abapgit_git_definitions=>ty_sha1, + lv_display_url TYPE zif_abapgit_persistence=>ty_repo-url, + lo_url TYPE REF TO zcl_abapgit_git_url, + lv_icon_commit TYPE string. + + lv_commit_hash = ii_repo_online->get_current_remote( ). + lv_commit_short_hash = lv_commit_hash(7). + + lv_icon_commit = ii_html->icon( iv_name = 'code-commit' + iv_class = 'pad-sides' + iv_hint = 'Commit' ). + + CREATE OBJECT lo_url. + + TRY. + lv_display_url = lo_url->get_commit_display_url( ii_repo_online ). + + ii_html->add_a( iv_txt = |{ lv_icon_commit }{ lv_commit_short_hash }| + iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ lv_display_url }| + iv_title = 'Commit' + iv_class = |url| ). + CATCH zcx_abapgit_exception. + ii_html->add( |{ lv_icon_commit }{ lv_commit_short_hash }| ). + ENDTRY. + + ENDMETHOD. + METHOD render_repo_url. + + ri_html = zcl_abapgit_html=>create( )->add_a( + iv_txt = shorten_repo_url( iv_url ) + iv_title = iv_url + iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ iv_url }| + iv_class = 'url' ). + + IF iv_render_remote_edit_for_key IS NOT INITIAL. + ri_html->add_a( + iv_txt = ri_html->icon( + iv_name = 'edit-solid' + iv_class = 'pad-sides' + iv_hint = 'Change remote' ) + iv_act = |{ zif_abapgit_definitions=>c_action-repo_remote_settings }?key={ iv_render_remote_edit_for_key }| + iv_class = |remote_repo| ). + ENDIF. + + ENDMETHOD. + METHOD render_sci_result. + + DATA lv_icon TYPE string. + + lv_icon = ii_html->icon( + iv_name = 'bug-solid' + iv_hint = 'Code inspector result' ). + + CASE iv_sci_result. + WHEN zif_abapgit_definitions=>c_sci_result-passed. + ii_html->add( |{ lv_icon }PASSED| ). + WHEN zif_abapgit_definitions=>c_sci_result-failed. + ii_html->add( |{ lv_icon }FAILED| ). + WHEN zif_abapgit_definitions=>c_sci_result-warning. + ii_html->add( |{ lv_icon }WARN| ). + WHEN OTHERS. " Including NO_RUN + RETURN. + ENDCASE. + + ENDMETHOD. + METHOD render_success. + + ri_html = zcl_abapgit_html=>create( ). + ri_html->add( '
' ). + ri_html->add_icon( 'check' ). + ri_html->add( iv_message ). + ri_html->add( '
' ). + + ENDMETHOD. + METHOD render_table_footer. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + + ri_html->add( iv_message ). + + ri_html->add( '' ). + ri_html->add( '' ). + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_table_header. + + DATA: + lv_tmp TYPE string, + lv_disp_name TYPE string. + + FIELD-SYMBOLS LIKE LINE OF it_col_spec. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( '' ). + ri_html->add( '' ). + + LOOP AT it_col_spec ASSIGNING . + " e.g. Created at [{ gv_time_zone }] + lv_tmp = '-css_class IS NOT INITIAL. + lv_tmp = lv_tmp && | class="{ -css_class }"|. + ENDIF. + lv_tmp = lv_tmp && '>'. + + IF -display_name IS NOT INITIAL. + lv_disp_name = -display_name. + IF -add_tz = abap_true. + lv_disp_name = lv_disp_name && | [{ gv_time_zone }]|. + ENDIF. + IF -tech_name = iv_order_by. + IF iv_order_descending = abap_true. + lv_tmp = lv_tmp && ri_html->a( + iv_txt = lv_disp_name + iv_act = |{ zif_abapgit_definitions=>c_action-change_order_by }| + iv_title = -title ). + ELSE. + lv_tmp = lv_tmp && ri_html->a( + iv_txt = lv_disp_name + iv_act = |{ zif_abapgit_definitions=>c_action-direction }?direction=DESCENDING| + iv_title = -title ). + ENDIF. + ELSEIF -allow_order_by = abap_true. + lv_tmp = lv_tmp && ri_html->a( + iv_txt = lv_disp_name + iv_act = |{ zif_abapgit_definitions=>c_action-change_order_by }?orderBy={ -tech_name }| + iv_title = -title ). + ELSE. + lv_tmp = lv_tmp && lv_disp_name. + ENDIF. + ENDIF. + IF -tech_name = iv_order_by + AND iv_order_by IS NOT INITIAL. + IF iv_order_descending = abap_true. + lv_tmp = lv_tmp && | ▾|. " arrow down + ELSE. + lv_tmp = lv_tmp && | ▴|. " arrow up + ENDIF. + ENDIF. + + lv_tmp = lv_tmp && ''. + ri_html->add( lv_tmp ). + ENDLOOP. + + ri_html->add( '' ). + ri_html->add( '' ). + + ENDMETHOD. + METHOD render_text_input. + + DATA lv_attrs TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF iv_value IS NOT INITIAL. + lv_attrs = | value="{ iv_value }"|. + ENDIF. + + IF iv_max_length IS NOT INITIAL. + lv_attrs = lv_attrs && | maxlength="{ iv_max_length }"|. + ENDIF. + + IF iv_autofocus = abap_true. + lv_attrs = lv_attrs && | autofocus|. + ENDIF. + + ri_html->add( || ). + ri_html->add( || ). + + ENDMETHOD. + METHOD render_timestamp. + + DATA lv_date TYPE d. + DATA lv_time TYPE t. + + CONVERT TIME STAMP iv_timestamp + TIME ZONE gv_time_zone + INTO DATE lv_date + TIME lv_time. + + rv_rendered = |{ lv_date DATE = USER } { lv_time TIME = USER }|. + + ENDMETHOD. + METHOD render_transport. + + DATA: + lv_title TYPE string, + lv_jump TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF iv_transport IS INITIAL. + RETURN. + ENDIF. + + lv_title = zcl_abapgit_factory=>get_cts_api( )->read_description( iv_transport ). + + lv_jump = |{ zif_abapgit_definitions=>c_action-jump_transport }?transport={ iv_transport }|. + + IF iv_obj_type IS NOT INITIAL AND iv_obj_name IS NOT INITIAL. + lv_jump = lv_jump && |&type={ iv_obj_type }&name={ iv_obj_name }|. + ENDIF. + + IF iv_icon_only = abap_true. + ri_html->add_a( iv_act = lv_jump + iv_title = |Transport { iv_transport }| + iv_txt = zcl_abapgit_html=>icon( 'truck-solid/darkgrey' ) ). + ELSE. + ri_html->add( || ). + + ri_html->add_icon( iv_name = 'truck-solid/grey70' + iv_hint = 'Transport' ). + IF iv_interactive = abap_true. + ri_html->add_a( iv_act = lv_jump + iv_title = lv_title + iv_txt = |{ iv_transport }| ). + ELSE. + ri_html->add( iv_transport ). + ENDIF. + + ri_html->add( '' ). + ENDIF. + + ENDMETHOD. + METHOD render_user_name. + + DATA: + lv_title TYPE string, + lv_jump TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF iv_username IS INITIAL. + RETURN. + ENDIF. + + IF iv_username <> zcl_abapgit_objects_super=>c_user_unknown AND iv_suppress_title = abap_false. + lv_title = zcl_abapgit_env_factory=>get_user_record( )->get_title( iv_username ). + ENDIF. + + lv_jump = |{ zif_abapgit_definitions=>c_action-jump_user }?user={ iv_username }|. + + IF iv_icon_only = abap_true. + ri_html->add_a( iv_act = lv_jump + iv_title = lv_title + iv_txt = zcl_abapgit_html=>icon( 'user-solid/darkgrey' ) ). + ELSE. + ri_html->add( || ). + + ri_html->add_icon( iv_name = 'user-solid/grey70' + iv_hint = 'User name' ). + IF iv_interactive = abap_true AND iv_username <> zcl_abapgit_objects_super=>c_user_unknown. + ri_html->add_a( iv_act = lv_jump + iv_title = lv_title + iv_txt = |{ iv_username }| ). + ELSE. + ri_html->add( iv_username ). + ENDIF. + + ri_html->add( '' ). + ENDIF. + + ENDMETHOD. + METHOD render_warning_banner. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '
' ). + ri_html->add( |{ ri_html->icon( 'exclamation-triangle/yellow' ) } { iv_text }| ). + ri_html->add( '
' ). + + ENDMETHOD. + METHOD shorten_repo_url. + DATA lv_new_length TYPE i. + DATA lv_length_to_truncate_to TYPE i. + + rv_shortened = iv_full_url. + + REPLACE FIRST OCCURRENCE OF 'https://' IN rv_shortened WITH ''. + REPLACE FIRST OCCURRENCE OF 'http://' IN rv_shortened WITH ''. + IF rv_shortened CP '*.git'. + lv_new_length = strlen( rv_shortened ) - 4. + rv_shortened = rv_shortened(lv_new_length). + ENDIF. + + IF strlen( rv_shortened ) > iv_max_length. + lv_length_to_truncate_to = iv_max_length - 3. + rv_shortened = rv_shortened(lv_length_to_truncate_to) && `...`. + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_buttons IMPLEMENTATION. + METHOD advanced. + rv_html_string = zcl_abapgit_html=>icon( + iv_name = 'tools-solid' + iv_hint = 'Utilities' ). + ENDMETHOD. + METHOD experimental. + rv_html_string = zcl_abapgit_html=>icon( + iv_name = 'vial-solid/red' + iv_hint = 'Experimental Features are Enabled' ). + ENDMETHOD. + METHOD flow. + rv_html_string = zcl_abapgit_html=>icon( 'flow' ) && ' Flow'. + ENDMETHOD. + METHOD help. + rv_html_string = zcl_abapgit_html=>icon( + iv_name = 'question-circle-solid' + iv_hint = 'Help' ). + ENDMETHOD. + METHOD new_offline. + rv_html_string = zcl_abapgit_html=>icon( 'plug' ) && ' New Offline'. + ENDMETHOD. + METHOD new_online. + rv_html_string = zcl_abapgit_html=>icon( 'cloud-upload-alt' ) && ' New Online'. + ENDMETHOD. + METHOD refresh. + rv_html_string = zcl_abapgit_html=>icon( + iv_name = 'redo-alt-solid' + iv_hint = 'Refresh' ). + ENDMETHOD. + METHOD repo_list. + rv_html_string = zcl_abapgit_html=>icon( 'bars' ) && ' Repository List'. + ENDMETHOD. + METHOD settings. + rv_html_string = zcl_abapgit_html=>icon( 'cog' ) && ' Global Settings'. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_exception_viewer IMPLEMENTATION. + METHOD add_row. + + DATA: lo_row TYPE REF TO cl_salv_form_layout_flow. + + lo_row = io_grid->add_row( ). + + lo_row->create_label( position = 1 + text = iv_col_1 ). + + lo_row->create_label( position = 2 + text = iv_col_2 ). + + ENDMETHOD. + METHOD build_top_of_list. + + DATA: lo_grid TYPE REF TO cl_salv_form_layout_grid. + + CREATE OBJECT lo_grid + EXPORTING + columns = 2. + + add_row( io_grid = lo_grid + iv_col_1 = 'Main program:' + iv_col_2 = is_top_of_stack-mainprogram ). + + add_row( io_grid = lo_grid + iv_col_1 = 'Include name:' + iv_col_2 = is_top_of_stack-include ). + + add_row( io_grid = lo_grid + iv_col_1 = 'Source line' + iv_col_2 = |{ is_top_of_stack-line }| ). + + ro_form = lo_grid. + + ENDMETHOD. + METHOD constructor. + + mx_error = ix_error. + mt_callstack = mx_error->mt_callstack. + + ENDMETHOD. + METHOD extract_classname. + + rv_classname = substring_before( val = iv_mainprogram + regex = '=*CP$' ). + + ENDMETHOD. + METHOD get_top_of_callstack. + + READ TABLE mt_callstack INDEX 1 + INTO rs_top_of_callstack. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Callstack is empty| ). + ENDIF. + + ENDMETHOD. + METHOD goto_message. + + DATA: lv_msg TYPE c LENGTH 100. + DATA: lt_bdcdata TYPE STANDARD TABLE OF bdcdata, + ls_bdcdata LIKE LINE OF lt_bdcdata. + + ls_bdcdata-program = 'SAPLWBMESSAGES'. + ls_bdcdata-dynpro = '0100'. + ls_bdcdata-dynbegin = abap_true. + INSERT ls_bdcdata INTO TABLE lt_bdcdata. + + CLEAR: ls_bdcdata. + ls_bdcdata-fnam = 'RSDAG-ARBGB'. + ls_bdcdata-fval = mx_error->if_t100_message~t100key-msgid. + INSERT ls_bdcdata INTO TABLE lt_bdcdata. + + CLEAR: ls_bdcdata. + ls_bdcdata-fnam = 'MSG_NUMMER'. + ls_bdcdata-fval = mx_error->if_t100_message~t100key-msgno. + INSERT ls_bdcdata INTO TABLE lt_bdcdata. + + CLEAR: ls_bdcdata. + ls_bdcdata-fnam = 'RSDAG-MSGFLAG'. + ls_bdcdata-fval = 'X'. + INSERT ls_bdcdata INTO TABLE lt_bdcdata. + + CLEAR: ls_bdcdata. + ls_bdcdata-fnam = 'BDC_OKCODE'. + ls_bdcdata-fval = '=WB_DISPLAY'. + INSERT ls_bdcdata INTO TABLE lt_bdcdata. + + CALL FUNCTION 'ABAP4_CALL_TRANSACTION' + STARTING NEW TASK 'GIT' + EXPORTING + tcode = 'SE91' + mode_val = 'E' + TABLES + using_tab = lt_bdcdata + EXCEPTIONS + system_failure = 1 MESSAGE lv_msg + communication_failure = 2 MESSAGE lv_msg + resource_failure = 3 + OTHERS = 4. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( lv_msg ). + ENDIF. + + ENDMETHOD. + METHOD goto_source. + + goto_source_code( get_top_of_callstack( ) ). + + ENDMETHOD. + METHOD goto_source_code. + + CONSTANTS: + BEGIN OF lc_obj_type, + class TYPE trobjtype VALUE `CLAS`, + program TYPE trobjtype VALUE `PROG`, + END OF lc_obj_type. + + DATA: + ls_item TYPE zif_abapgit_definitions=>ty_item, + ls_sub_item TYPE zif_abapgit_definitions=>ty_item, + lv_classname LIKE ls_item-obj_name. + + " you should remember that we distinct two cases + " 1) we navigate to a global class + " 2) we navigate to a program + " the latter one is the default case + + lv_classname = extract_classname( is_callstack-mainprogram ). + + IF lv_classname IS NOT INITIAL. + ls_item-obj_name = lv_classname. + ls_item-obj_type = lc_obj_type-class. + ELSE. + ls_item-obj_name = is_callstack-mainprogram. + ls_item-obj_type = lc_obj_type-program. + ENDIF. + + ls_sub_item-obj_name = is_callstack-include. + ls_sub_item-obj_type = lc_obj_type-program. + + zcl_abapgit_objects=>jump( + is_item = ls_item + is_sub_item = ls_sub_item + iv_line_number = is_callstack-line ). + + ENDMETHOD. + METHOD on_double_click. + + DATA: lx_error TYPE REF TO zcx_abapgit_exception. + FIELD-SYMBOLS: TYPE abap_callstack_line. + + READ TABLE mt_callstack ASSIGNING + INDEX row. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + TRY. + goto_source_code( ). + + CATCH zcx_abapgit_exception INTO lx_error. + MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. + ENDTRY. + + ENDMETHOD. + METHOD set_text. + + DATA: lo_column TYPE REF TO cl_salv_column, + lv_short_text TYPE scrtext_s, + lv_medium_text TYPE scrtext_m, + lv_long_text TYPE scrtext_l. + + lo_column = io_columns->get_column( iv_column ). + + lv_short_text = iv_text. + lv_medium_text = iv_text. + lv_long_text = iv_text. + + lo_column->set_short_text( lv_short_text ). + lo_column->set_medium_text( lv_medium_text ). + lo_column->set_long_text( lv_long_text ). + + ENDMETHOD. + METHOD show_callstack. + + DATA: lx_error TYPE REF TO cx_static_check, + lo_event TYPE REF TO cl_salv_events_table, + lo_columns TYPE REF TO cl_salv_columns_table, + lo_alv TYPE REF TO cl_salv_table. + DATA ls_position TYPE zif_abapgit_popups=>ty_popup_position. + + TRY. + cl_salv_table=>factory( + IMPORTING + r_salv_table = lo_alv + CHANGING + t_table = mt_callstack ). + + lo_alv->get_columns( )->set_optimize( ). + + lo_alv->set_top_of_list( build_top_of_list( get_top_of_callstack( ) ) ). + + ls_position = zcl_abapgit_popups=>center( + iv_width = 150 + iv_height = 25 ). + + lo_alv->set_screen_popup( start_column = ls_position-start_column + end_column = ls_position-end_column + start_line = ls_position-start_row + end_line = ls_position-end_row ). + + lo_event = lo_alv->get_event( ). + + lo_columns = lo_alv->get_columns( ). + + set_text( io_columns = lo_columns + iv_column = |LINE| + iv_text = |Line| ). + + set_text( io_columns = lo_columns + iv_column = |LINE| + iv_text = |Line| ). + + set_text( io_columns = lo_columns + iv_column = |BLOCKTYPE| + iv_text = |Event Type| ). + + set_text( io_columns = lo_columns + iv_column = |BLOCKNAME| + iv_text = |Event| ). + + set_text( io_columns = lo_columns + iv_column = |FLAG_SYSTEM| + iv_text = |System| ). + + SET HANDLER on_double_click FOR lo_event. + + lo_alv->display( ). + + CATCH cx_static_check INTO lx_error. + MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_PAGE_FLOWCONS IMPLEMENTATION. + + METHOD constructor. + super->constructor( ). + mo_repo = ii_repo. + ENDMETHOD. + + METHOD stage_missing_remote. +* Stage and commit "ms_consolidate-missing_remote" files to new branch + + DATA lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. + DATA ls_main_branch LIKE LINE OF lt_branches. + DATA lv_branch_name TYPE string. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA ls_filter LIKE LINE OF lt_filter. + DATA ls_file LIKE LINE OF ms_consolidate-missing_remote. + DATA lv_package TYPE devclass. + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + DATA lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. + DATA ls_local LIKE LINE OF lt_local. + DATA lo_filter TYPE REF TO zcl_abapgit_object_filter_obj. + DATA lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. + DATA lo_stage TYPE REF TO zcl_abapgit_stage. + lt_branches = zcl_abapgit_git_factory=>get_v2_porcelain( )->list_branches( + iv_url = mo_repo->get_url( ) + iv_prefix = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && zif_abapgit_flow_logic=>c_main )->get_all( ). + ASSERT lines( lt_branches ) = 1. + + READ TABLE lt_branches INDEX 1 INTO ls_main_branch. + ASSERT sy-subrc = 0. + + lv_branch_name = |consolidate{ sy-datum }{ sy-uzeit }|. + zcl_abapgit_git_porcelain=>create_branch( + iv_url = mo_repo->get_url( ) + iv_name = |{ zif_abapgit_git_definitions=>c_git_branch-heads_prefix }{ lv_branch_name }| + iv_from = ls_main_branch-sha1 ). + + lv_package = mo_repo->zif_abapgit_repo~get_package( ). + lo_dot = mo_repo->zif_abapgit_repo~get_dot_abapgit( ). + + LOOP AT ms_consolidate-missing_remote INTO ls_file. + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = ls_file-filename + iv_path = ls_file-path + iv_devclass = lv_package + io_dot = lo_dot + IMPORTING + es_item = ls_item ). + ls_filter-object = ls_item-obj_type. + ls_filter-obj_name = ls_item-obj_name. + INSERT ls_filter INTO TABLE lt_filter. + ENDLOOP. + SORT lt_filter BY object obj_name. + DELETE ADJACENT DUPLICATES FROM lt_filter COMPARING object obj_name. + + CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. + lt_local = mo_repo->zif_abapgit_repo~get_files_local_filtered( lo_filter ). + +* just add all files, some will match, but its okay + CREATE OBJECT lo_stage. + LOOP AT lt_local INTO ls_local. + lo_stage->add( iv_path = ls_local-file-path + iv_filename = ls_local-file-filename + iv_data = ls_local-file-data ). + ENDLOOP. + + push( + io_stage = lo_stage + iv_branch_name = lv_branch_name + iv_sha1 = ls_main_branch-sha1 ). + + ENDMETHOD. + + METHOD stage_only_remote. +* remove and commit "ms_consolidate-only_remote" files to new branch + + DATA lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. + DATA ls_main_branch LIKE LINE OF lt_branches. + DATA lv_branch_name TYPE string. + DATA ls_file LIKE LINE OF ms_consolidate-missing_remote. + DATA lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. + DATA lo_stage TYPE REF TO zcl_abapgit_stage. + lt_branches = zcl_abapgit_git_factory=>get_v2_porcelain( )->list_branches( + iv_url = mo_repo->get_url( ) + iv_prefix = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && zif_abapgit_flow_logic=>c_main )->get_all( ). + ASSERT lines( lt_branches ) = 1. + + READ TABLE lt_branches INDEX 1 INTO ls_main_branch. + ASSERT sy-subrc = 0. + + lv_branch_name = |consolidate{ sy-datum }{ sy-uzeit }|. + zcl_abapgit_git_porcelain=>create_branch( + iv_url = mo_repo->get_url( ) + iv_name = |{ zif_abapgit_git_definitions=>c_git_branch-heads_prefix }{ lv_branch_name }| + iv_from = ls_main_branch-sha1 ). + + lo_dot = mo_repo->zif_abapgit_repo~get_dot_abapgit( ). + + CREATE OBJECT lo_stage. + LOOP AT ms_consolidate-only_remote INTO ls_file. + lo_stage->rm( iv_path = ls_file-path + iv_filename = ls_file-filename ). + ENDLOOP. + + push( + io_stage = lo_stage + iv_branch_name = lv_branch_name + iv_sha1 = ls_main_branch-sha1 ). + + ENDMETHOD. + + METHOD push. + + DATA ls_comment TYPE zif_abapgit_git_definitions=>ty_comment. + DATA lt_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt. + DATA lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + + ls_comment-committer-name = 'consolidate'. + ls_comment-committer-email = 'consolidate@localhost'. + ls_comment-comment = |Consolidate { sy-datum DATE = ISO } { sy-uzeit TIME = ISO }|. + + INSERT iv_sha1 INTO TABLE lt_sha1. + lt_objects = zcl_abapgit_git_factory=>get_v2_porcelain( )->list_no_blobs_multi( + iv_url = mo_repo->get_url( ) + it_sha1 = lt_sha1 ). + + zcl_abapgit_git_porcelain=>push( + is_comment = ls_comment + io_stage = io_stage + iv_branch_name = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && iv_branch_name + iv_url = mo_repo->get_url( ) + iv_parent = iv_sha1 + it_old_objects = lt_objects ). + + MESSAGE 'Done, commited' TYPE 'S'. + + ENDMETHOD. + + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_flowcons. + + CREATE OBJECT lo_component EXPORTING ii_repo = ii_repo. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Flow Consolidate' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + CASE ii_event->mv_action. + WHEN c_action-stage_missing_remote. + stage_missing_remote( ). + CLEAR ms_consolidate. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-stage_only_remote. + stage_only_remote( ). + CLEAR ms_consolidate. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-refresh. + CLEAR ms_consolidate. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN zif_abapgit_definitions=>c_action-go_file_diff. + rs_handled = zcl_abapgit_flow_page_utils=>call_diff( ii_event ). + WHEN OTHERS. +* the back button is handled in the default router + RETURN. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-flow' ). + + ro_toolbar->add( + iv_txt = 'Refresh' + iv_act = c_action-refresh ). + + ro_toolbar->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + DATA lv_text TYPE string. + DATA lo_timer TYPE REF TO zcl_abapgit_timer. + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA lo_toolbar TYPE REF TO zcl_abapgit_html_toolbar. + + register_handlers( ). + + li_repo ?= mo_repo. + lo_timer = zcl_abapgit_timer=>create( )->start( ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '
' ). + + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( + ii_repo = mo_repo + iv_interactive_favorite = abap_false + iv_show_commit = abap_false + iv_show_branch = abap_false ) ). + + IF ms_consolidate IS INITIAL. + ms_consolidate = zcl_abapgit_flow_logic=>consolidate( mo_repo ). + ENDIF. + + LOOP AT ms_consolidate-errors INTO lv_text. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_error( iv_error = lv_text ) ). + ENDLOOP. + LOOP AT ms_consolidate-warnings INTO lv_text. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_warning_banner( lv_text ) ). + ENDLOOP. + LOOP AT ms_consolidate-success INTO lv_text. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_success( lv_text ) ). + ENDLOOP. + + IF lines( ms_consolidate-missing_remote ) > 0. + ri_html->add( '

Missing Remote Files

' ). + CREATE OBJECT lo_toolbar EXPORTING iv_id = 'toolbar-flow-cons'. + lo_toolbar->add( iv_txt = |Stage and commit { lines( ms_consolidate-missing_remote ) } files to new branch| + iv_act = c_action-stage_missing_remote + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ri_html->add( lo_toolbar->render( ) ). + + ri_html->add( zcl_abapgit_flow_page_utils=>render_table( + it_files = ms_consolidate-missing_remote + iv_repo_key = li_repo->get_key( ) ) ). + ENDIF. + + IF lines( ms_consolidate-only_remote ) > 0. + ri_html->add( '

Files Only Remote

' ). + CREATE OBJECT lo_toolbar EXPORTING iv_id = 'toolbar-flow-cons'. + lo_toolbar->add( iv_txt = |Remove and commit { lines( ms_consolidate-only_remote ) } files to new branch| + iv_act = c_action-stage_only_remote + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ri_html->add( lo_toolbar->render( ) ). + + ri_html->add( zcl_abapgit_flow_page_utils=>render_table( + it_files = ms_consolidate-only_remote + iv_repo_key = li_repo->get_key( ) ) ). + ENDIF. + + ri_html->add( |

{ lo_timer->end( ) }
| ). + + ri_html->add( '
' ). + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn DEFINITION DEFERRED. +* renamed: zcl_abapgit_gui_page_flow :: lcl_filter +CLASS kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_object_filter. + + METHODS constructor + IMPORTING + it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + + PRIVATE SECTION. + DATA mt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. +ENDCLASS. + +CLASS kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn IMPLEMENTATION. + METHOD constructor. + mt_filter = it_filter. + ENDMETHOD. + + METHOD zif_abapgit_object_filter~get_filter. + rt_filter = mt_filter. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_flow IMPLEMENTATION. + METHOD call_consolidate. + + DATA lt_repos TYPE zcl_abapgit_flow_logic=>ty_repos_tt. + DATA li_repo LIKE LINE OF lt_repos. + + lt_repos = zcl_abapgit_flow_logic=>list_repos( abap_false ). + IF lines( lt_repos ) <> 1. + MESSAGE 'Todo, repository selection popup' TYPE 'S'. + ELSE. + READ TABLE lt_repos INTO li_repo INDEX 1. + ASSERT sy-subrc = 0. + rs_handled-page = zcl_abapgit_gui_page_flowcons=>create( li_repo ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + ENDIF. + + ENDMETHOD. + METHOD call_pull. + + DATA lv_key TYPE zif_abapgit_persistence=>ty_value. + DATA lv_branch TYPE string. + DATA lo_filter TYPE REF TO kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lv_index TYPE i. + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + DATA ls_feature LIKE LINE OF ms_information-features. + + FIELD-SYMBOLS LIKE LINE OF ls_feature-changed_objects. + FIELD-SYMBOLS LIKE LINE OF lt_filter. + + lv_key = ii_event->query( )->get( 'KEY' ). + lv_index = ii_event->query( )->get( 'INDEX' ). + lv_branch = ii_event->query( )->get( 'BRANCH' ). + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + + READ TABLE ms_information-features INTO ls_feature INDEX lv_index. + ASSERT sy-subrc = 0. + + LOOP AT ls_feature-changed_objects ASSIGNING . + APPEND INITIAL LINE TO lt_filter ASSIGNING . + -object = -obj_type. + -obj_name = -obj_name. + ENDLOOP. + CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. + + set_branch( + iv_branch = lv_branch + iv_key = lv_key ). + + rs_handled-page = zcl_abapgit_gui_page_pull=>create( + ii_repo = li_repo_online + iv_trkorr = ls_feature-transport-trkorr + ii_obj_filter = lo_filter ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + + refresh( ). + + ENDMETHOD. + METHOD call_stage_commit. + + DATA lv_key TYPE zif_abapgit_persistence=>ty_value. + DATA lv_branch TYPE string. + DATA lo_filter TYPE REF TO kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lv_index TYPE i. + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + DATA ls_feature LIKE LINE OF ms_information-features. + + FIELD-SYMBOLS LIKE LINE OF ls_feature-changed_objects. + FIELD-SYMBOLS LIKE LINE OF lt_filter. + + lv_key = ii_event->query( )->get( 'KEY' ). + lv_index = ii_event->query( )->get( 'INDEX' ). + lv_branch = ii_event->query( )->get( 'BRANCH' ). + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + + READ TABLE ms_information-features INTO ls_feature INDEX lv_index. + ASSERT sy-subrc = 0. + + LOOP AT ls_feature-changed_objects ASSIGNING . + APPEND INITIAL LINE TO lt_filter ASSIGNING . + -object = -obj_type. + -obj_name = -obj_name. + ENDLOOP. + CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. + + set_branch( + iv_branch = lv_branch + iv_key = lv_key ). + + rs_handled-page = zcl_abapgit_gui_page_stage=>create( + ii_force_refresh = abap_false + ii_repo_online = li_repo_online + ii_obj_filter = lo_filter ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. + + refresh( ). + + ENDMETHOD. + METHOD constructor. + super->constructor( ). + ms_user_settings = zcl_abapgit_persist_factory=>get_user( )->get_flow_settings( ). + ENDMETHOD. + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_flow. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( + iv_page_title = 'Flow' + ii_page_menu_provider = lo_component + ii_child_component = lo_component ). + + ENDMETHOD. + METHOD refresh. + + DATA ls_feature LIKE LINE OF ms_information-features. + DATA li_repo TYPE REF TO zif_abapgit_repo. + LOOP AT ms_information-features INTO ls_feature. + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( ls_feature-repo-key ). + li_repo->refresh( ). + ENDLOOP. + + CLEAR ms_information. + + ENDMETHOD. + METHOD render_toolbar. + + DATA lo_toolbar TYPE REF TO zcl_abapgit_html_toolbar. + DATA lv_extra TYPE string. + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA lv_opt TYPE c LENGTH 1. + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + CREATE OBJECT lo_toolbar EXPORTING iv_id = 'toolbar-flow'. + + li_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( is_feature-repo-key ). + IF li_repo->get_local_settings( )-write_protected = abap_true. + lv_opt = zif_abapgit_html=>c_html_opt-crossout. + ELSE. + lv_opt = zif_abapgit_html=>c_html_opt-strong. + ENDIF. + + IF is_feature-full_match = abap_false AND is_feature-branch-display_name IS NOT INITIAL. + lv_extra = |?index={ iv_index }&key={ is_feature-repo-key }&branch={ is_feature-branch-display_name }|. + lo_toolbar->add( iv_txt = 'Pull' + iv_act = |{ c_action-pull }{ lv_extra }| + iv_opt = lv_opt ). + + IF is_feature-transport-trkorr IS NOT INITIAL. + IF zcl_abapgit_flow_exit=>get_instance( )->get_settings( is_feature-repo-key )-allow_not_up_to_date = abap_true + OR is_feature-branch-up_to_date = abap_undefined + OR is_feature-branch-up_to_date = abap_true. +* its only remote, so there is no changes to stage + lo_toolbar->add( iv_txt = 'Stage and Commit' + iv_act = |{ c_action-stage_and_commit }{ lv_extra }| + iv_opt = zif_abapgit_html=>c_html_opt-strong ). + ENDIF. + ENDIF. + ENDIF. + + zcl_abapgit_flow_exit=>get_instance( )->toolbar_extras( + io_toolbar = lo_toolbar + iv_index = iv_index + is_feature = is_feature ). + + ri_html->add( lo_toolbar->render( ) ). + + ENDMETHOD. + METHOD render_user_settings. + + DATA lv_icon_class TYPE string. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '' ). + + IF ms_user_settings-only_my_transports = abap_true. + lv_icon_class = `blue`. + ELSE. + lv_icon_class = `grey`. + ENDIF. + ri_html->add( ri_html->a( + iv_txt = | Only my transports| + iv_class = 'command' + iv_act = |{ c_action-only_my_transports }| ) ). + + IF ms_user_settings-hide_full_matches = abap_true. + lv_icon_class = `blue`. + ELSE. + lv_icon_class = `grey`. + ENDIF. + ri_html->add( ri_html->a( + iv_txt = | Hide full matches| + iv_class = 'command' + iv_act = |{ c_action-hide_full_matches }| ) ). + + IF ms_user_settings-hide_matching_files = abap_true. + lv_icon_class = `blue`. + ELSE. + lv_icon_class = `grey`. + ENDIF. + ri_html->add( ri_html->a( + iv_txt = | Hide matching files| + iv_class = 'command' + iv_act = |{ c_action-hide_matching_files }| ) ). + + IF ms_user_settings-hide_conflicts = abap_true. + lv_icon_class = `blue`. + ELSE. + lv_icon_class = `grey`. + ENDIF. + ri_html->add( ri_html->a( + iv_txt = | Hide transports with conflicts| + iv_class = 'command' + iv_act = |{ c_action-hide_conflicts }| ) ). + + ri_html->add( '' ). + + ENDMETHOD. + METHOD set_branch. + + DATA lv_branch TYPE string. + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + + IF iv_branch IS NOT INITIAL. + lv_branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && iv_branch. + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + IF li_repo_online->get_selected_branch( ) <> lv_branch. + li_repo_online->select_branch( lv_branch ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + DATA ls_event_result TYPE zif_abapgit_flow_exit=>ty_event_result. + CASE ii_event->mv_action. + WHEN c_action-only_my_transports. + ms_user_settings-only_my_transports = boolc( ms_user_settings-only_my_transports <> abap_true ). + zcl_abapgit_persist_factory=>get_user( )->set_flow_settings( ms_user_settings ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-hide_full_matches. + ms_user_settings-hide_full_matches = boolc( ms_user_settings-hide_full_matches <> abap_true ). + zcl_abapgit_persist_factory=>get_user( )->set_flow_settings( ms_user_settings ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-hide_conflicts. + ms_user_settings-hide_conflicts = boolc( ms_user_settings-hide_conflicts <> abap_true ). + zcl_abapgit_persist_factory=>get_user( )->set_flow_settings( ms_user_settings ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-hide_matching_files. + ms_user_settings-hide_matching_files = boolc( ms_user_settings-hide_matching_files <> abap_true ). + zcl_abapgit_persist_factory=>get_user( )->set_flow_settings( ms_user_settings ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-refresh. + refresh( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-consolidate. + rs_handled = call_consolidate( ). + WHEN zif_abapgit_definitions=>c_action-go_file_diff. + rs_handled = zcl_abapgit_flow_page_utils=>call_diff( ii_event ). + WHEN c_action-stage_and_commit. + rs_handled = call_stage_commit( ii_event ). + WHEN c_action-pull. + rs_handled = call_pull( ii_event ). + WHEN OTHERS. + ls_event_result = zcl_abapgit_flow_exit=>get_instance( )->on_event( + ii_event = ii_event + it_features = ms_information-features ). + + rs_handled = ls_event_result-handled. + + IF ls_event_result-refresh = abap_true. + refresh( ). + ENDIF. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-flow' ). + + ro_toolbar->add( + iv_txt = 'Refresh' + iv_act = c_action-refresh ). + + ro_toolbar->add( + iv_txt = 'Consolidate' + iv_act = c_action-consolidate ). + + ro_toolbar->add( + iv_txt = zcl_abapgit_gui_buttons=>repo_list( ) + iv_act = zif_abapgit_definitions=>c_action-abapgit_home ). + + ro_toolbar->add( + iv_txt = 'Back' + iv_act = zif_abapgit_definitions=>c_action-go_back ). + + ENDMETHOD. + + METHOD skip_show. + + DATA lt_my_transports TYPE zif_abapgit_cts_api=>ty_trkorr_tt. + DATA lt_user TYPE zif_abapgit_cts_api=>ty_user_range. + DATA ls_user LIKE LINE OF lt_user. + DATA ls_duplicate LIKE LINE OF ms_information-transport_duplicates. + + rv_skip = abap_false. + + IF ms_user_settings-only_my_transports = abap_true. + ls_user-low = sy-uname. + ls_user-sign = 'I'. + ls_user-option = 'EQ'. + INSERT ls_user INTO TABLE lt_user. + lt_my_transports = zcl_abapgit_factory=>get_cts_api( )->list_open_requests( it_user = lt_user ). + ENDIF. + + IF ms_user_settings-hide_full_matches = abap_true + AND NOT is_feature-transport IS INITIAL + AND is_feature-full_match = abap_true. + rv_skip = abap_true. + RETURN. + ENDIF. + + IF ms_user_settings-only_my_transports = abap_true AND is_feature-transport-trkorr IS NOT INITIAL. + READ TABLE lt_my_transports WITH KEY table_line = is_feature-transport-trkorr TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + rv_skip = abap_true. + RETURN. + ENDIF. + ENDIF. + + IF ms_user_settings-hide_conflicts = abap_true. + LOOP AT ms_information-transport_duplicates INTO ls_duplicate. + READ TABLE is_feature-changed_objects WITH KEY + obj_type = ls_duplicate-obj_type + obj_name = ls_duplicate-obj_name + TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + rv_skip = abap_true. + RETURN. + ENDIF. + ENDLOOP. + + ENDIF. + + IF lines( is_feature-changed_files ) = 0. +* no changes, eg. only files outside of starting folder changed + rv_skip = abap_true. + ENDIF. + + ENDMETHOD. + + METHOD render_info. + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + IF is_feature-branch-display_name IS INITIAL. + ri_html->add( |No branch found, comparing with main| ). + ELSEIF is_feature-pr IS NOT INITIAL. + ri_html->add( 'Pull Request: ' ). + ri_html->add_a( + iv_txt = is_feature-pr-title + iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ is_feature-pr-url }| + iv_class = |url| ). + + ri_html->add( |
| ). + IF is_feature-pr-draft = abap_true. + ri_html->add( 'Status: Draft' ). + ELSE. + ri_html->add( 'Status: Ready for Review' ). + ENDIF. + + ri_html->add( |
| ). + ri_html->add( |First commit: { is_feature-branch-first_commit(7) }| ). + + ri_html->add( |
| ). + IF is_feature-branch-up_to_date = abap_true. + ri_html->add( 'Branch up to date: True' ). + ELSE. + ri_html->add( 'Branch up to date: False' ). + ENDIF. + ELSE. + ri_html->add( |No PR found| ). + ENDIF. + ri_html->add( |
| ). + + IF is_feature-transport IS NOT INITIAL. + ri_html->add( |Transport: { is_feature-transport-trkorr } - { is_feature-transport-title }
| ). + ELSE. + ri_html->add( |No corresponding transport found
| ). + ENDIF. + + zcl_abapgit_flow_exit=>get_instance( )->info_extras( + ii_html = ri_html + is_feature = is_feature ). + + ENDMETHOD. + + METHOD zif_abapgit_gui_renderable~render. + + DATA ls_feature LIKE LINE OF ms_information-features. + DATA lv_index TYPE i. + DATA lv_rendered TYPE abap_bool. + DATA lo_timer TYPE REF TO zcl_abapgit_timer. + DATA lv_message LIKE LINE OF ms_information-errors. + lo_timer = zcl_abapgit_timer=>create( )->start( ). + + register_handlers( ). + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + ri_html->add( '
' ). + + IF ms_information IS INITIAL. + ms_information = zcl_abapgit_flow_logic=>get( ). + ENDIF. + + ri_html->add( render_user_settings( ) ). + + ri_html->add( '
' ). + ri_html->add( '
' ). + + IF lines( ms_information-errors ) > 0. + LOOP AT ms_information-errors INTO lv_message. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_error( iv_error = lv_message ) ). + ENDLOOP. + ri_html->add( '
' ). + ENDIF. + + LOOP AT ms_information-features INTO ls_feature. + lv_index = sy-tabix. + + IF skip_show( ls_feature ) = abap_true. + CONTINUE. + ENDIF. + lv_rendered = abap_true. + + ri_html->add( '' && ls_feature-repo-name ). + IF ls_feature-branch-display_name IS NOT INITIAL. + ri_html->add( | - | ). + ri_html->add_icon( 'code-branch' ). + ri_html->add( ls_feature-branch-display_name ). + ENDIF. + IF ls_feature-transport-trkorr IS NOT INITIAL. + ri_html->add( | - | ). + ri_html->add_icon( 'truck-solid' ). + ri_html->add( |{ ls_feature-transport-trkorr }| ). + ENDIF. + ri_html->add( |
| ). + + ri_html->add( render_info( ls_feature ) ). + + ri_html->add( render_toolbar( + iv_index = lv_index + is_feature = ls_feature ) ). + + IF ls_feature-branch IS NOT INITIAL AND ls_feature-branch-up_to_date = abap_false + AND zcl_abapgit_flow_exit=>get_instance( )->get_settings( ls_feature-repo-key )-allow_not_up_to_date = abap_false. + ri_html->add( 'Branch not up to date

' ). + CONTINUE. + ENDIF. + + IF ls_feature-full_match = abap_true. + ri_html->add( |Full Match, { + lines( ls_feature-changed_files ) } files, { + lines( ls_feature-changed_objects ) } objects
| ). + ELSE. + ri_html->add( zcl_abapgit_flow_page_utils=>render_table( + it_files = ls_feature-changed_files + it_transport_duplicates = ms_information-transport_duplicates + is_user_settings = ms_user_settings + iv_repo_key = ls_feature-repo-key ) ). + ENDIF. + +* todo LOOP AT ls_feature-changed_objects INTO ls_item. +* todo ri_html->add( |{ ls_item-obj_type } { ls_item-obj_name }
| ). +* todo ENDLOOP. + + ri_html->add( '
' ). + ENDLOOP. + + IF lines( ms_information-features ) = 0 OR lv_rendered = abap_false. + ri_html->add( 'Empty, repositories must be favorite + flow enabled

' ). + + ri_html->add( 'Or nothing in progress

' ). + + ri_html->add_a( + iv_txt = 'abapGit flow documentation' + iv_act = |{ zif_abapgit_definitions=>c_action-url + }?url=https://docs.abapgit.org/user-guide/reference/flow.html| + iv_class = |url| ). + ELSE. + ri_html->add( |{ lines( ms_information-features ) } features in { lo_timer->end( ) }| ). + ENDIF. + + ri_html->add( '
' ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_FLOW_PAGE_UTILS IMPLEMENTATION. + METHOD call_diff. + + DATA lv_key TYPE zif_abapgit_persistence=>ty_value. + DATA lv_remote_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1. + DATA ls_file TYPE zif_abapgit_git_definitions=>ty_file. + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA lv_blob TYPE xstring. + DATA ls_local TYPE zif_abapgit_git_definitions=>ty_file. + DATA ls_remote TYPE zif_abapgit_git_definitions=>ty_file. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lo_filter TYPE REF TO zcl_abapgit_object_filter_obj. + DATA lt_files_item TYPE zif_abapgit_definitions=>ty_files_item_tt. + DATA ls_file_item LIKE LINE OF lt_files_item. + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + + FIELD-SYMBOLS LIKE LINE OF lt_filter. + + lv_key = ii_event->query( )->get( 'KEY' ). + li_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + li_repo ?= li_repo_online. + + lv_remote_sha1 = ii_event->query( )->get( 'REMOTE_SHA1' ). + + ls_file-path = ii_event->query( )->get( 'PATH' ). + ls_file-filename = ii_event->query( )->get( 'FILENAME' ). " unescape ? + + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = ls_file-filename + iv_path = ls_file-path + iv_devclass = li_repo->get_package( ) + io_dot = li_repo->get_dot_abapgit( ) + IMPORTING + es_item = ls_item ). + + APPEND INITIAL LINE TO lt_filter ASSIGNING . + -object = ls_item-obj_type. + -obj_name = ls_item-obj_name. + CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. + + lt_files_item = li_repo_online->zif_abapgit_repo~get_files_local_filtered( lo_filter ). + READ TABLE lt_files_item INTO ls_file_item WITH KEY file-path = ls_file-path + file-filename = ls_file-filename. + + lv_blob = zcl_abapgit_git_factory=>get_v2_porcelain( )->fetch_blob( + iv_url = li_repo_online->get_url( ) + iv_sha1 = lv_remote_sha1 ). + + ls_remote-path = ls_file-path. + ls_remote-filename = ls_file-filename. + ls_remote-sha1 = lv_remote_sha1. + ls_remote-data = lv_blob. + + ls_local-path = ls_remote-path. + ls_local-filename = ls_remote-filename. + ls_local-sha1 = ls_file_item-file-sha1. + ls_local-data = ls_file_item-file-data. + + rs_handled-page = zcl_abapgit_gui_page_diff_file=>create( + iv_obj_type = ls_item-obj_type + iv_obj_name = ls_item-obj_name + is_local = ls_local + is_remote = ls_remote ). + + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. + + ENDMETHOD. + METHOD render_table. + + DATA ls_path_name LIKE LINE OF it_files. + DATA lv_status TYPE string. + DATA lv_param TYPE string. + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + DATA lv_duplicate TYPE abap_bool. + ASSERT iv_repo_key IS NOT INITIAL. + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_repo_key ). + + CREATE OBJECT ri_html TYPE zcl_abapgit_html. + + ri_html->add( || ). + ri_html->add( || ). + + LOOP AT it_files INTO ls_path_name. + CLEAR lv_status. + + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = ls_path_name-filename + iv_path = ls_path_name-path + iv_devclass = li_repo->get_package( ) + io_dot = li_repo->get_dot_abapgit( ) + IMPORTING + es_item = ls_item ). + READ TABLE it_transport_duplicates + TRANSPORTING NO FIELDS + WITH KEY obj_type = ls_item-obj_type + obj_name = ls_item-obj_name. + lv_duplicate = boolc( sy-subrc = 0 ). + + IF ls_path_name-remote_sha1 = ls_path_name-local_sha1. + IF is_user_settings-hide_matching_files = abap_true AND lv_duplicate = abap_false. + CONTINUE. + ENDIF. + lv_status = 'Match'. + ELSEIF ls_path_name-remote_sha1 IS NOT INITIAL + AND ls_path_name-local_sha1 IS NOT INITIAL. + + lv_param = zcl_abapgit_html_action_utils=>file_encode( + iv_key = iv_repo_key + ig_file = ls_path_name ). + lv_status = ri_html->a( + iv_txt = 'Diff' + iv_act = |{ zif_abapgit_definitions=>c_action-go_file_diff }?{ + lv_param }&remote_sha1={ ls_path_name-remote_sha1 }| ). + ENDIF. + + ri_html->add( || ). + ENDLOOP. + ri_html->add( |
FilenameRemoteLocal
{ ls_path_name-path }{ ls_path_name-filename }{ + ls_path_name-remote_sha1(7) }{ + ls_path_name-local_sha1(7) }{ lv_status }| ). + IF lv_duplicate = abap_true. + ri_html->add_icon( iv_name = 'exclamation-triangle/red' + iv_hint = 'In duplicate transports' ). + ENDIF. + ri_html->add( |
| ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_FLOW_LOGIC IMPLEMENTATION. + METHOD add_local_status. + + FIELD-SYMBOLS LIKE LINE OF ct_features. + FIELD-SYMBOLS LIKE LINE OF it_local. + FIELD-SYMBOLS TYPE zif_abapgit_flow_logic=>ty_path_name. + LOOP AT ct_features ASSIGNING . + LOOP AT -changed_files ASSIGNING . + READ TABLE it_local ASSIGNING + WITH KEY file-filename = -filename + file-path = -path. + IF sy-subrc = 0. + -local_sha1 = -file-sha1. + ENDIF. + ENDLOOP. + ENDLOOP. + + ENDMETHOD. + METHOD add_objects_and_files_from_tr. + + DATA ls_changed LIKE LINE OF cs_feature-changed_objects. + DATA ls_changed_file LIKE LINE OF cs_feature-changed_files. + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + DATA lv_filename TYPE string. + DATA lv_extension TYPE string. + DATA lv_main_file TYPE string. + FIELD-SYMBOLS LIKE LINE OF it_transports. + FIELD-SYMBOLS LIKE LINE OF it_local. + FIELD-SYMBOLS LIKE LINE OF it_main_expanded. + LOOP AT it_transports ASSIGNING WHERE trkorr = iv_trkorr. + ls_changed-obj_type = -object. + ls_changed-obj_name = -obj_name. + INSERT ls_changed INTO TABLE cs_feature-changed_objects. + + LOOP AT it_local ASSIGNING + WHERE file-filename <> zif_abapgit_definitions=>c_dot_abapgit + AND item-obj_type = -object + AND item-obj_name = -obj_name. + + CLEAR ls_changed_file. + ls_changed_file-path = -file-path. + ls_changed_file-filename = -file-filename. + ls_changed_file-local_sha1 = -file-sha1. + + READ TABLE it_main_expanded ASSIGNING + WITH TABLE KEY path_name COMPONENTS + path = ls_changed_file-path + name = ls_changed_file-filename. + IF sy-subrc = 0. + ls_changed_file-remote_sha1 = -sha1. + ENDIF. + + INSERT ls_changed_file INTO TABLE cs_feature-changed_files. + ENDLOOP. + IF sy-subrc <> 0. +* then its a deletion + CLEAR ls_item. + ls_item-obj_type = -object. + ls_item-obj_name = -obj_name. + + IF zcl_abapgit_aff_factory=>get_registry( )->is_supported_object_type( -object ) = abap_true. + lv_extension = 'json'. + ELSE. + lv_extension = 'xml'. + ENDIF. + + lv_main_file = zcl_abapgit_filename_logic=>object_to_file( + is_item = ls_item + iv_ext = lv_extension ). + CONCATENATE '.' lv_extension INTO lv_extension. + lv_filename = lv_main_file. + REPLACE FIRST OCCURRENCE OF lv_extension IN lv_filename WITH '*'. + + LOOP AT it_main_expanded ASSIGNING + WHERE name CP lv_filename. + CLEAR ls_changed_file. + ls_changed_file-filename = -name. + ls_changed_file-path = -path. + ls_changed_file-remote_sha1 = -sha1. + INSERT ls_changed_file INTO TABLE cs_feature-changed_files. + ENDLOOP. + IF sy-subrc <> 0. + CLEAR ls_changed_file. + ls_changed_file-filename = lv_main_file. + ls_changed_file-path = '/src/'. " todo? +* after its deleted locally and remote then remote and local sha1 will match(be empty) + INSERT ls_changed_file INTO TABLE cs_feature-changed_files. + ENDIF. + + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD build_repo_data. + rs_data-name = ii_repo->get_name( ). + rs_data-key = ii_repo->get_key( ). + rs_data-package = ii_repo->get_package( ). + ENDMETHOD. + METHOD check_files. + + DATA ls_missing LIKE LINE OF ct_missing_remote. + DATA lv_found_main TYPE abap_bool. + DATA ls_feature LIKE LINE OF it_features. + DATA lv_found_branch TYPE abap_bool. + + FIELD-SYMBOLS LIKE LINE OF it_local. + FIELD-SYMBOLS LIKE LINE OF ct_main_expanded. + + LOOP AT it_local ASSIGNING WHERE file-filename <> zif_abapgit_definitions=>c_dot_abapgit. + READ TABLE ct_main_expanded WITH KEY name = -file-filename ASSIGNING . + lv_found_main = boolc( sy-subrc = 0 ). + + lv_found_branch = abap_false. + LOOP AT it_features INTO ls_feature. + READ TABLE ls_feature-changed_files TRANSPORTING NO FIELDS + WITH KEY filename = -file-filename. + IF sy-subrc = 0. + lv_found_branch = abap_true. + EXIT. + ENDIF. + ENDLOOP. + + IF lv_found_main = abap_false AND lv_found_branch = abap_false. + CLEAR ls_missing. + ls_missing-path = -file-path. + ls_missing-filename = -file-filename. + ls_missing-local_sha1 = -file-sha1. + INSERT ls_missing INTO TABLE ct_missing_remote. + ELSEIF lv_found_branch = abap_false AND -path <> -file-path. +* todo + ELSEIF lv_found_branch = abap_false AND -sha1 <> -file-sha1. + CLEAR ls_missing. + ls_missing-path = -file-path. + ls_missing-filename = -file-filename. + ls_missing-local_sha1 = -file-sha1. + ls_missing-remote_sha1 = -sha1. + INSERT ls_missing INTO TABLE ct_missing_remote. + ENDIF. + + IF lv_found_main = abap_true OR lv_found_branch = abap_true. + DELETE ct_main_expanded WHERE name = -file-filename AND path = -file-path. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD consolidate. + + DATA lt_features TYPE zif_abapgit_flow_logic=>ty_features. + DATA ls_feature LIKE LINE OF lt_features. + DATA lv_string TYPE string. + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA ls_transport TYPE zif_abapgit_cts_api=>ty_transport_data. +* todo: handling multiple repositories + + li_repo ?= ii_online. + lt_features = get( )-features. + + LOOP AT lt_features INTO ls_feature WHERE repo-key = li_repo->get_key( ). + IF ls_feature-branch-display_name IS NOT INITIAL + AND ls_feature-branch-up_to_date = abap_false. + lv_string = |Branch { ls_feature-branch-display_name } is not up to date|. + INSERT lv_string INTO TABLE rs_consolidate-errors. + ELSEIF ls_feature-branch-display_name IS NOT INITIAL + AND ls_feature-transport-trkorr IS INITIAL + AND lines( ls_feature-changed_files ) > 0. +* its okay if the changes are outside the starting folder + lv_string = |Branch { ls_feature-branch-display_name } has no transport|. + INSERT lv_string INTO TABLE rs_consolidate-errors. + ELSEIF ls_feature-transport-trkorr IS NOT INITIAL + AND ls_feature-branch-display_name IS INITIAL + AND ls_feature-full_match = abap_false. + ls_transport = zcl_abapgit_factory=>get_cts_api( )->read( ls_feature-transport-trkorr ). + lv_string = |Transport { ls_feature-transport-trkorr } has no branch, created { + ls_transport-as4date DATE = ISO }|. + INSERT lv_string INTO TABLE rs_consolidate-errors. + ENDIF. +* todo: branches without pull requests? + ENDLOOP. + + consolidate_files( + EXPORTING + ii_online = ii_online + CHANGING + cs_information = rs_consolidate ). + + ENDMETHOD. + METHOD consolidate_files. + + DATA lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. + DATA lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lo_filter TYPE REF TO zcl_abapgit_object_filter_obj. + DATA lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. + DATA lt_features TYPE zif_abapgit_flow_logic=>ty_features. + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA lt_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt. + DATA ls_expanded LIKE LINE OF lt_main_expanded. + DATA ls_branch LIKE LINE OF lt_branches. + DATA ls_only_remote TYPE zif_abapgit_flow_logic=>ty_path_name. + DATA ls_result LIKE LINE OF lt_features. + DATA lt_all_transports TYPE ty_transports_tt. + DATA lv_filename TYPE string. + FIELD-SYMBOLS LIKE LINE OF lt_tadir. + + li_repo ?= ii_online. + +* find all that exists local, serialize these, skip if no changes or if in any branch + lt_branches = zcl_abapgit_git_factory=>get_v2_porcelain( )->list_branches( + iv_url = ii_online->get_url( ) + iv_prefix = zif_abapgit_git_definitions=>c_git_branch-heads_prefix )->get_all( ). + + CLEAR lt_features. + LOOP AT lt_branches INTO ls_branch WHERE display_name <> zif_abapgit_flow_logic=>c_main. + ls_result-repo = build_repo_data( ii_online ). + ls_result-branch-display_name = ls_branch-display_name. + ls_result-branch-sha1 = ls_branch-sha1. + INSERT ls_result INTO TABLE lt_features. + ENDLOOP. + + zcl_abapgit_flow_git=>find_changes_in_git( + EXPORTING + iv_url = ii_online->get_url( ) + io_dot = li_repo->get_dot_abapgit( ) + iv_package = li_repo->get_package( ) + it_branches = lt_branches + IMPORTING + et_main_expanded = lt_main_expanded + CHANGING + ct_features = lt_features ). + + lt_tadir = zcl_abapgit_factory=>get_tadir( )->read( + iv_package = li_repo->get_package( ) + io_dot = li_repo->get_dot_abapgit( ) + iv_check_exists = abap_true ). + + lt_all_transports = find_open_transports( ). + + LOOP AT lt_tadir ASSIGNING . +" skip the object is in any open transport + READ TABLE lt_all_transports WITH KEY object = -object obj_name = -obj_name TRANSPORTING NO FIELDS. + IF sy-subrc = 0 AND -object <> 'DEVC'. +* todo: this is not correct for AFF enabled objects + lv_filename = |{ to_lower( -obj_name ) }.{ to_lower( -object ) }*|. + DELETE lt_main_expanded WHERE name CP lv_filename. + CONTINUE. + ENDIF. + + INSERT INTO TABLE lt_filter. + + IF lines( lt_filter ) >= 500. + CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. + lt_local = li_repo->get_files_local_filtered( lo_filter ). + CLEAR lt_filter. + check_files( + EXPORTING + it_local = lt_local + it_features = lt_features + CHANGING + ct_main_expanded = lt_main_expanded + ct_missing_remote = cs_information-missing_remote ). + IF lines( cs_information-missing_remote ) > 1000. + INSERT `Only first 1000 missing files shown` INTO TABLE cs_information-warnings. + ENDIF. + ENDIF. + ENDLOOP. + + IF lines( lt_filter ) > 0. + CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. + lt_local = li_repo->get_files_local_filtered( lo_filter ). + CLEAR lt_filter. + check_files( + EXPORTING + it_local = lt_local + it_features = lt_features + CHANGING + ct_main_expanded = lt_main_expanded + ct_missing_remote = cs_information-missing_remote ). + ENDIF. + +* todo: double check, there might have been changes while consolidation is running +* or do smaller batches? + +* those left in lt_main_expanded are only in remote, not local + LOOP AT lt_main_expanded INTO ls_expanded. + CLEAR ls_only_remote. + ls_only_remote-path = ls_expanded-path. + ls_only_remote-filename = ls_expanded-name. + ls_only_remote-remote_sha1 = ls_expanded-sha1. + INSERT ls_only_remote INTO TABLE cs_information-only_remote. + ENDLOOP. + + ENDMETHOD. + METHOD errors_from_transports. + + DATA lv_message TYPE string. + DATA lt_transports LIKE it_all_transports. + DATA lv_index TYPE i. + DATA ls_next LIKE LINE OF lt_transports. + DATA ls_transport LIKE LINE OF lt_transports. + DATA ls_duplicate LIKE LINE OF cs_information-transport_duplicates. + DATA lv_found1 TYPE abap_bool. + DATA lv_found2 TYPE abap_bool. + + lt_transports = it_all_transports. + SORT lt_transports BY object obj_name trkorr. + + LOOP AT lt_transports INTO ls_transport. + lv_index = sy-tabix + 1. + READ TABLE lt_transports INTO ls_next INDEX lv_index. + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + + IF ls_next-object = ls_transport-object + AND ls_next-trkorr <> ls_transport-trkorr + AND ls_next-obj_name = ls_transport-obj_name. + + READ TABLE cs_information-features WITH KEY transport-trkorr = ls_transport-trkorr TRANSPORTING NO FIELDS. + lv_found1 = boolc( sy-subrc = 0 ). + READ TABLE cs_information-features WITH KEY transport-trkorr = ls_next-trkorr TRANSPORTING NO FIELDS. + lv_found2 = boolc( sy-subrc = 0 ). + IF lv_found1 = abap_false AND lv_found2 = abap_false. + " not in any favorite flow enabled repo + CONTINUE. + ENDIF. + + lv_message = |Object { ls_transport-object } { ls_transport-obj_name + } is in multiple transports: { ls_transport-trkorr } and { ls_next-trkorr }|. + INSERT lv_message INTO TABLE cs_information-errors. + + CLEAR ls_duplicate. + ls_duplicate-obj_type = ls_transport-object. + ls_duplicate-obj_name = ls_transport-obj_name. + INSERT ls_duplicate INTO TABLE cs_information-transport_duplicates. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD find_open_transports. + + DATA lt_trkorr TYPE zif_abapgit_cts_api=>ty_trkorr_tt. + DATA lv_trkorr LIKE LINE OF lt_trkorr. + DATA ls_result LIKE LINE OF rt_transports. + DATA lt_objects TYPE zif_abapgit_cts_api=>ty_transport_obj_tt. + DATA lv_obj_name TYPE tadir-obj_name. + DATA lt_date TYPE zif_abapgit_cts_api=>ty_date_range. + DATA ls_date LIKE LINE OF lt_date. + + FIELD-SYMBOLS LIKE LINE OF lt_objects. + +* only look for transports that are created/changed in the last two years + ls_date-sign = 'I'. + ls_date-option = 'GE'. + ls_date-low = sy-datum - 730. + INSERT ls_date INTO TABLE lt_date. + + lt_trkorr = zcl_abapgit_factory=>get_cts_api( )->list_open_requests( it_date = lt_date ). + + LOOP AT lt_trkorr INTO lv_trkorr. + ls_result-trkorr = lv_trkorr. + ls_result-title = zcl_abapgit_factory=>get_cts_api( )->read_description( lv_trkorr ). + + lt_objects = zcl_abapgit_factory=>get_cts_api( )->list_r3tr_by_request( lv_trkorr ). + LOOP AT lt_objects ASSIGNING . + ls_result-object = -object. + ls_result-obj_name = -obj_name. + + lv_obj_name = -obj_name. + ls_result-devclass = zcl_abapgit_factory=>get_tadir( )->read_single( + iv_object = ls_result-object + iv_obj_name = lv_obj_name )-devclass. + IF ls_result-devclass IS NOT INITIAL. + INSERT ls_result INTO TABLE rt_transports. + ENDIF. + ENDLOOP. + + ENDLOOP. + + ENDMETHOD. + METHOD find_prs. + + DATA lt_pulls TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests. + DATA ls_pull LIKE LINE OF lt_pulls. + + FIELD-SYMBOLS LIKE LINE OF ct_features. + IF lines( ct_features ) = 0. + " only main branch + RETURN. + ENDIF. + + lt_pulls = zcl_abapgit_pr_enumerator=>new( iv_url )->get_pulls( ). + + LOOP AT ct_features ASSIGNING . + READ TABLE lt_pulls INTO ls_pull WITH KEY head_branch = -branch-display_name. + IF sy-subrc = 0. + " remove markdown formatting, + REPLACE ALL OCCURRENCES OF '`' IN ls_pull-title WITH ''. + + -pr-title = |{ ls_pull-title } #{ ls_pull-number }|. + -pr-url = ls_pull-html_url. + -pr-number = ls_pull-number. + -pr-draft = ls_pull-draft. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD get. + + DATA lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. + DATA ls_branch LIKE LINE OF lt_branches. + DATA ls_result LIKE LINE OF rs_information-features. + DATA li_repo_online TYPE REF TO zif_abapgit_repo_online. + DATA lt_features LIKE rs_information-features. + DATA lt_all_transports TYPE ty_transports_tt. + DATA lt_relevant_transports TYPE ty_trkorr_tt. + DATA lt_repos TYPE ty_repos_tt. + DATA lt_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt. + DATA lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. + DATA lt_real_transports LIKE lt_all_transports. + + FIELD-SYMBOLS LIKE LINE OF lt_features. + FIELD-SYMBOLS LIKE LINE OF -changed_files. + + lt_all_transports = find_open_transports( ). + lt_real_transports = lt_all_transports. + +* list branches on favorite + flow enabled + transported repos + lt_repos = list_repos( ). + LOOP AT lt_repos INTO li_repo_online. + + lt_branches = zcl_abapgit_git_factory=>get_v2_porcelain( )->list_branches( + iv_url = li_repo_online->get_url( ) + iv_prefix = zif_abapgit_git_definitions=>c_git_branch-heads_prefix )->get_all( ). + + CLEAR lt_features. + LOOP AT lt_branches INTO ls_branch WHERE display_name <> zif_abapgit_flow_logic=>c_main. + ls_result-repo = build_repo_data( li_repo_online ). + ls_result-branch-display_name = ls_branch-display_name. + ls_result-branch-sha1 = ls_branch-sha1. + INSERT ls_result INTO TABLE lt_features. + ENDLOOP. + + zcl_abapgit_flow_git=>find_changes_in_git( + EXPORTING + iv_url = li_repo_online->get_url( ) + io_dot = li_repo_online->zif_abapgit_repo~get_dot_abapgit( ) + iv_package = li_repo_online->zif_abapgit_repo~get_package( ) + it_branches = lt_branches + IMPORTING + et_main_expanded = lt_main_expanded + CHANGING + ct_features = lt_features ). + + lt_relevant_transports = relevant_transports_via_devc( + ii_repo = li_repo_online + it_transports = lt_all_transports ). + + lt_local = serialize_filtered( + it_relevant_transports = lt_relevant_transports + ii_repo = li_repo_online + it_features = lt_features + it_all_transports = lt_all_transports ). + + try_matching_transports( + EXPORTING + ii_repo = li_repo_online + it_local = lt_local + it_main_expanded = lt_main_expanded + CHANGING + ct_transports = lt_all_transports + ct_features = lt_features ). + + find_prs( + EXPORTING + iv_url = li_repo_online->get_url( ) + CHANGING + ct_features = lt_features ). + + add_local_status( + EXPORTING + it_local = lt_local + CHANGING + ct_features = lt_features ). + + LOOP AT lt_features ASSIGNING . + -full_match = abap_true. + LOOP AT -changed_files ASSIGNING . + IF -remote_sha1 <> -local_sha1. + -full_match = abap_false. + ENDIF. + ENDLOOP. + ENDLOOP. + + INSERT LINES OF lt_features INTO TABLE rs_information-features. + ENDLOOP. + + errors_from_transports( + EXPORTING + it_all_transports = lt_real_transports + CHANGING + cs_information = rs_information ). + + SORT rs_information-features BY full_match transport-trkorr DESCENDING. + + ENDMETHOD. + METHOD list_repos. + + DATA lt_repos TYPE zif_abapgit_repo_srv=>ty_repo_list. + DATA li_repo LIKE LINE OF lt_repos. + DATA li_online TYPE REF TO zif_abapgit_repo_online. + + IF iv_favorites_only = abap_true. + lt_repos = zcl_abapgit_repo_srv=>get_instance( )->list_favorites( abap_false ). + ELSE. + lt_repos = zcl_abapgit_repo_srv=>get_instance( )->list( abap_false ). + ENDIF. + + LOOP AT lt_repos INTO li_repo. + IF li_repo->get_local_settings( )-flow = abap_false. + CONTINUE. + ELSEIF zcl_abapgit_factory=>get_sap_package( li_repo->get_package( ) + )->are_changes_recorded_in_tr_req( ) = abap_false. + CONTINUE. + ENDIF. + + li_online ?= li_repo. + INSERT li_online INTO TABLE rt_repos. + ENDLOOP. + ENDMETHOD. + METHOD relevant_transports_via_devc. + + DATA ls_trkorr LIKE LINE OF it_transports. + DATA lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. + DATA lv_found TYPE abap_bool. + DATA lv_package LIKE LINE OF lt_packages. + DATA lt_trkorr TYPE ty_transports_tt. + + FIELD-SYMBOLS LIKE LINE OF it_transports. + lt_trkorr = it_transports. + SORT lt_trkorr BY trkorr. + DELETE ADJACENT DUPLICATES FROM lt_trkorr COMPARING trkorr. + + lt_packages = zcl_abapgit_factory=>get_sap_package( ii_repo->get_package( ) )->list_subpackages( ). + INSERT ii_repo->get_package( ) INTO TABLE lt_packages. + + LOOP AT lt_trkorr INTO ls_trkorr. + lv_found = abap_false. + + LOOP AT lt_packages INTO lv_package. + READ TABLE it_transports ASSIGNING WITH KEY trkorr = ls_trkorr-trkorr devclass = lv_package. + IF sy-subrc = 0. + lv_found = abap_true. + EXIT. + ENDIF. + ENDLOOP. + IF lv_found = abap_false. + CONTINUE. + ENDIF. + + IF lv_found = abap_true. + INSERT ls_trkorr-trkorr INTO TABLE rt_transports. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD serialize_filtered. + + DATA lv_trkorr TYPE trkorr. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lo_filter TYPE REF TO zcl_abapgit_object_filter_obj. + DATA ls_feature LIKE LINE OF it_features. + DATA ls_changed_object LIKE LINE OF ls_feature-changed_objects. + + FIELD-SYMBOLS LIKE LINE OF it_all_transports. + FIELD-SYMBOLS LIKE LINE OF lt_filter. + +* from all relevant transports(matched via package) + LOOP AT it_relevant_transports INTO lv_trkorr. + LOOP AT it_all_transports ASSIGNING WHERE trkorr = lv_trkorr. + APPEND INITIAL LINE TO lt_filter ASSIGNING . + -object = -object. + -obj_name = -obj_name. + ENDLOOP. + ENDLOOP. + +* and from git + LOOP AT it_features INTO ls_feature. + LOOP AT ls_feature-changed_objects INTO ls_changed_object. + APPEND INITIAL LINE TO lt_filter ASSIGNING . + -object = ls_changed_object-obj_type. + -obj_name = ls_changed_object-obj_name. + ENDLOOP. + ENDLOOP. + + SORT lt_filter BY object obj_name. + DELETE ADJACENT DUPLICATES FROM lt_filter COMPARING object obj_name. + + CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. + rt_local = ii_repo->get_files_local_filtered( lo_filter ). + + ENDMETHOD. + METHOD try_matching_transports. + + DATA lt_trkorr LIKE ct_transports. + DATA ls_trkorr LIKE LINE OF lt_trkorr. + DATA ls_result LIKE LINE OF ct_features. + DATA lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. + DATA lv_package LIKE LINE OF lt_packages. + DATA lv_found TYPE abap_bool. + + FIELD-SYMBOLS LIKE LINE OF ct_features. + FIELD-SYMBOLS LIKE LINE OF ct_transports. + FIELD-SYMBOLS LIKE LINE OF -changed_objects. + SORT ct_transports BY object obj_name. + + LOOP AT ct_features ASSIGNING . + LOOP AT -changed_objects ASSIGNING . + READ TABLE ct_transports ASSIGNING + WITH KEY object = -obj_type obj_name = -obj_name BINARY SEARCH. + IF sy-subrc = 0. + -transport-trkorr = -trkorr. + -transport-title = -title. + + add_objects_and_files_from_tr( + EXPORTING + iv_trkorr = -trkorr + it_local = it_local + it_main_expanded = it_main_expanded + it_transports = ct_transports + CHANGING + cs_feature = ). + + DELETE ct_transports WHERE trkorr = -trkorr. + EXIT. + ENDIF. + ENDLOOP. + ENDLOOP. + +* unmatched transports + lt_trkorr = ct_transports. + SORT lt_trkorr BY trkorr. + DELETE ADJACENT DUPLICATES FROM lt_trkorr COMPARING trkorr. + + lt_packages = zcl_abapgit_factory=>get_sap_package( ii_repo->get_package( ) )->list_subpackages( ). + INSERT ii_repo->get_package( ) INTO TABLE lt_packages. + + LOOP AT lt_trkorr INTO ls_trkorr. + lv_found = abap_false. + LOOP AT lt_packages INTO lv_package. + READ TABLE ct_transports ASSIGNING WITH KEY trkorr = ls_trkorr-trkorr devclass = lv_package. + IF sy-subrc = 0. + lv_found = abap_true. + EXIT. + ENDIF. + ENDLOOP. + IF lv_found = abap_false. + CONTINUE. + ENDIF. + + CLEAR ls_result. + ls_result-repo = build_repo_data( ii_repo ). + ls_result-transport-trkorr = -trkorr. + ls_result-transport-title = -title. + + add_objects_and_files_from_tr( + EXPORTING + iv_trkorr = ls_trkorr-trkorr + it_local = it_local + it_main_expanded = it_main_expanded + it_transports = ct_transports + CHANGING + cs_feature = ls_result ). + + INSERT ls_result INTO TABLE ct_features. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlqeiVzSltVlvDZbkhPIfZcUzJG DEFINITION DEFERRED. +CLASS kHGwlqeiVzSltVlvDZbkInGePeKchD DEFINITION DEFERRED. +CLASS kHGwlqeiVzSltVlvDZbkLCHjJVYdTX DEFINITION DEFERRED. +CLASS kHGwlqeiVzSltVlvDZbkEBNMowNImG DEFINITION DEFERRED. +INTERFACE iUFTsqeiVzSltVlvDZbkdrJxKoXhDZ DEFERRED. +* renamed: zcl_abapgit_flow_git :: lif_find_changes +INTERFACE iUFTsqeiVzSltVlvDZbkdrJxKoXhDZ. + + METHODS find_changes + IMPORTING + iv_main TYPE zif_abapgit_git_definitions=>ty_sha1 + iv_branch TYPE zif_abapgit_git_definitions=>ty_sha1 + iv_first_commit TYPE zif_abapgit_git_definitions=>ty_sha1 + iv_starting_folder TYPE string + RETURNING + VALUE(rt_files) TYPE zif_abapgit_flow_logic=>ty_path_name_tt + RAISING + zcx_abapgit_exception. + +ENDINTERFACE. + +**************************************************************************** + +* renamed: zcl_abapgit_flow_git :: lcl_walker +CLASS kHGwlqeiVzSltVlvDZbkEBNMowNImG DEFINITION. + PUBLIC SECTION. + + METHODS constructor + IMPORTING + it_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + + METHODS walk + IMPORTING + iv_path TYPE string + iv_tree_main TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL + iv_tree_branch TYPE zif_abapgit_git_definitions=>ty_sha1 + RETURNING + VALUE(rt_files) TYPE zif_abapgit_flow_logic=>ty_path_name_tt + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + TYPES: BEGIN OF ty_tree_cache, + sha1 TYPE string, + nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt, + END OF ty_tree_cache. + DATA mt_tree_cache TYPE HASHED TABLE OF ty_tree_cache WITH UNIQUE KEY sha1. + DATA mt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + + METHODS decode_tree + IMPORTING + iv_tree TYPE zif_abapgit_git_definitions=>ty_sha1 + RETURNING + VALUE(rt_nodes) TYPE zcl_abapgit_git_pack=>ty_nodes_tt + RAISING + zcx_abapgit_exception. +ENDCLASS. + +CLASS kHGwlqeiVzSltVlvDZbkEBNMowNImG IMPLEMENTATION. + + METHOD constructor. + mt_objects = it_objects. + ENDMETHOD. + + METHOD walk. + + DATA lt_main TYPE zcl_abapgit_git_pack=>ty_nodes_tt. + DATA lt_branch TYPE zcl_abapgit_git_pack=>ty_nodes_tt. + DATA ls_node_main LIKE LINE OF lt_main. + DATA ls_node_branch LIKE LINE OF lt_branch. + DATA ls_file LIKE LINE OF rt_files. + DATA lt_files LIKE rt_files. + + IF iv_tree_main IS NOT INITIAL. + lt_main = decode_tree( iv_tree_main ). + ENDIF. + + IF iv_tree_branch IS NOT INITIAL. + lt_branch = decode_tree( iv_tree_branch ). + ENDIF. + + LOOP AT lt_main INTO ls_node_main. + CLEAR ls_node_branch. + READ TABLE lt_branch INTO ls_node_branch WITH KEY name = ls_node_main-name. + IF sy-subrc = 0. + DELETE lt_branch INDEX sy-tabix. + IF ls_node_branch-sha1 = ls_node_main-sha1. + CONTINUE. + ENDIF. + ENDIF. + + CASE ls_node_main-chmod. + WHEN zif_abapgit_git_definitions=>c_chmod-dir. + lt_files = walk( + iv_path = iv_path && ls_node_main-name && '/' + iv_tree_main = ls_node_main-sha1 + iv_tree_branch = ls_node_branch-sha1 ). + INSERT LINES OF lt_files INTO TABLE rt_files. + WHEN zif_abapgit_git_definitions=>c_chmod-file. + CLEAR ls_file. + ls_file-path = iv_path. + ls_file-filename = ls_node_main-name. + ls_file-remote_sha1 = ls_node_branch-sha1. + INSERT ls_file INTO TABLE rt_files. + WHEN OTHERS. + " ignore other types + ENDCASE. + ENDLOOP. + +* new in branch, not in main + LOOP AT lt_branch INTO ls_node_branch. + CASE ls_node_branch-chmod. + WHEN zif_abapgit_git_definitions=>c_chmod-dir. + lt_files = walk( + iv_path = iv_path && ls_node_branch-name && '/' + iv_tree_branch = ls_node_branch-sha1 ). + INSERT LINES OF lt_files INTO TABLE rt_files. + WHEN zif_abapgit_git_definitions=>c_chmod-file. + CLEAR ls_file. + ls_file-path = iv_path. + ls_file-filename = ls_node_branch-name. + ls_file-remote_sha1 = ls_node_branch-sha1. + INSERT ls_file INTO TABLE rt_files. + WHEN OTHERS. + " ignore other types + ENDCASE. + ENDLOOP. + + ENDMETHOD. + + METHOD decode_tree. + DATA ls_cache LIKE LINE OF mt_tree_cache. + DATA ls_object LIKE LINE OF mt_objects. + + FIELD-SYMBOLS LIKE LINE OF mt_tree_cache. + + READ TABLE mt_tree_cache ASSIGNING WITH KEY sha1 = iv_tree. + IF sy-subrc = 0. + rt_nodes = -nodes. + ELSE. + READ TABLE mt_objects INTO ls_object WITH TABLE KEY type + COMPONENTS sha1 = iv_tree type = zif_abapgit_git_definitions=>c_type-tree. + ASSERT sy-subrc = 0. + + rt_nodes = zcl_abapgit_git_pack=>decode_tree( ls_object-data ). + + ls_cache-sha1 = iv_tree. + ls_cache-nodes = rt_nodes. + INSERT ls_cache INTO TABLE mt_tree_cache. + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +**************************************************************************** + +* renamed: zcl_abapgit_flow_git :: lcl_find_changes_new +CLASS kHGwlqeiVzSltVlvDZbkLCHjJVYdTX DEFINITION. + PUBLIC SECTION. + METHODS constructor + IMPORTING + it_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + + INTERFACES iUFTsqeiVzSltVlvDZbkdrJxKoXhDZ. + PRIVATE SECTION. + DATA mt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + DATA mo_walker TYPE REF TO kHGwlqeiVzSltVlvDZbkEBNMowNImG. + + METHODS find_changed_in_commit + IMPORTING + is_commit TYPE zcl_abapgit_git_pack=>ty_commit + CHANGING + ct_files TYPE zif_abapgit_flow_logic=>ty_path_name_tt + RAISING + zcx_abapgit_exception. +ENDCLASS. + +CLASS kHGwlqeiVzSltVlvDZbkLCHjJVYdTX IMPLEMENTATION. + METHOD constructor. + mt_objects = it_objects. + CREATE OBJECT mo_walker EXPORTING it_objects = it_objects. + ENDMETHOD. + + METHOD find_changed_in_commit. + + DATA ls_parent_commit TYPE zcl_abapgit_git_pack=>ty_commit. + DATA lt_files LIKE ct_files. + DATA ls_file LIKE LINE OF lt_files. + + FIELD-SYMBOLS LIKE LINE OF mt_objects. + ASSERT is_commit-parent IS NOT INITIAL. +* as per calling logic, never called if there is a parent2 + ASSERT is_commit-parent2 IS INITIAL. + + READ TABLE mt_objects ASSIGNING WITH TABLE KEY sha COMPONENTS sha1 = is_commit-parent. + ASSERT sy-subrc = 0. + ls_parent_commit = zcl_abapgit_git_pack=>decode_commit( -data ). + + lt_files = mo_walker->walk( + iv_path = '/' + iv_tree_main = ls_parent_commit-tree + iv_tree_branch = is_commit-tree ). + + LOOP AT lt_files INTO ls_file. +* if its already there, then skip, we want the latest(top) change in the list + INSERT ls_file INTO TABLE ct_files. + ENDLOOP. + + ENDMETHOD. + + METHOD iUFTsqeiVzSltVlvDZbkdrJxKoXhDZ~find_changes. + DATA lv_current TYPE zif_abapgit_git_definitions=>ty_sha1. + DATA ls_commit TYPE zcl_abapgit_git_pack=>ty_commit. + + FIELD-SYMBOLS LIKE LINE OF mt_objects. + ASSERT iv_first_commit IS NOT INITIAL. + ASSERT iv_main IS NOT INITIAL. + ASSERT iv_branch IS NOT INITIAL. + + lv_current = iv_branch. + + DO. + READ TABLE mt_objects ASSIGNING WITH TABLE KEY sha COMPONENTS sha1 = lv_current. + ASSERT sy-subrc = 0. + + ls_commit = zcl_abapgit_git_pack=>decode_commit( -data ). + IF ls_commit-parent2 IS INITIAL. +* analyze changed files in commit + find_changed_in_commit( + EXPORTING is_commit = ls_commit + CHANGING ct_files = rt_files ). + ENDIF. + + IF lv_current = iv_first_commit. + EXIT. + ENDIF. + + lv_current = ls_commit-parent. + ENDDO. + + ENDMETHOD. +ENDCLASS. + +**************************************************************************** + +* renamed: zcl_abapgit_flow_git :: lcl_find_changes +CLASS kHGwlqeiVzSltVlvDZbkInGePeKchD DEFINITION. + PUBLIC SECTION. + METHODS constructor + IMPORTING + it_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + + INTERFACES iUFTsqeiVzSltVlvDZbkdrJxKoXhDZ. + + PRIVATE SECTION. + DATA mt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + DATA mo_walker TYPE REF TO kHGwlqeiVzSltVlvDZbkEBNMowNImG. + +ENDCLASS. + +CLASS kHGwlqeiVzSltVlvDZbkInGePeKchD IMPLEMENTATION. + + METHOD constructor. + mt_objects = it_objects. + CREATE OBJECT mo_walker EXPORTING it_objects = it_objects. + ENDMETHOD. + + METHOD iUFTsqeiVzSltVlvDZbkdrJxKoXhDZ~find_changes. +* don't care if its added or removed or changed, just remove identical +* also list identical moved files + DATA ls_object LIKE LINE OF mt_objects. + DATA lv_tree_main TYPE zif_abapgit_git_definitions=>ty_sha1. + DATA lv_tree_branch TYPE zif_abapgit_git_definitions=>ty_sha1. + + READ TABLE mt_objects WITH TABLE KEY type + COMPONENTS sha1 = iv_main type = zif_abapgit_git_definitions=>c_type-commit INTO ls_object. + ASSERT sy-subrc = 0. + lv_tree_main = zcl_abapgit_git_pack=>decode_commit( ls_object-data )-tree. + + READ TABLE mt_objects WITH TABLE KEY type + COMPONENTS sha1 = iv_branch type = zif_abapgit_git_definitions=>c_type-commit INTO ls_object. + ASSERT sy-subrc = 0. + lv_tree_branch = zcl_abapgit_git_pack=>decode_commit( ls_object-data )-tree. + + rt_files = mo_walker->walk( + iv_path = '/' + iv_tree_main = lv_tree_main + iv_tree_branch = lv_tree_branch ). + + DELETE rt_files WHERE path NP iv_starting_folder. + ENDMETHOD. +ENDCLASS. + +*************************************************************************** + +* renamed: zcl_abapgit_flow_git :: lcl_sha1_stack +CLASS kHGwlqeiVzSltVlvDZbkhPIfZcUzJG DEFINITION. + PUBLIC SECTION. + METHODS clear + RETURNING + VALUE(ro_stack) TYPE REF TO kHGwlqeiVzSltVlvDZbkhPIfZcUzJG. + + METHODS push + IMPORTING + iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1. + + METHODS pop + RETURNING + VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1. + + METHODS size + RETURNING + VALUE(rv_size) TYPE i. + PRIVATE SECTION. + DATA mt_list TYPE STANDARD TABLE OF zif_abapgit_git_definitions=>ty_sha1 WITH DEFAULT KEY. +ENDCLASS. + +CLASS kHGwlqeiVzSltVlvDZbkhPIfZcUzJG IMPLEMENTATION. + METHOD clear. + CLEAR mt_list. + ro_stack = me. + ENDMETHOD. + + METHOD push. + INSERT iv_sha1 INTO mt_list INDEX 1. + ENDMETHOD. + + METHOD pop. + READ TABLE mt_list INDEX 1 INTO rv_sha1. + ASSERT sy-subrc = 0. + DELETE mt_list INDEX 1. + ENDMETHOD. + + METHOD size. + rv_size = lines( mt_list ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_flow_git IMPLEMENTATION. + + METHOD find_changes_in_git. + + DATA ls_branch LIKE LINE OF it_branches. + DATA lt_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt. + DATA lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + DATA lv_starting_folder TYPE string. + DATA ls_main LIKE LINE OF it_branches. + DATA li_find TYPE REF TO iUFTsqeiVzSltVlvDZbkdrJxKoXhDZ. + DATA lv_previous TYPE zif_abapgit_persistence=>ty_repo-key. + DATA lt_commits TYPE zif_abapgit_definitions=>ty_objects_tt. + + FIELD-SYMBOLS LIKE LINE OF ct_features. + FIELD-SYMBOLS LIKE LINE OF lt_commits. + CLEAR et_main_expanded. + +******************************* + + LOOP AT it_branches INTO ls_branch WHERE is_head = abap_false. + APPEND ls_branch-sha1 TO lt_sha1. + ENDLOOP. + + lt_objects = zcl_abapgit_git_factory=>get_v2_porcelain( )->list_no_blobs_multi( + iv_url = iv_url + it_sha1 = lt_sha1 ). + + lt_commits = zcl_abapgit_git_factory=>get_v2_porcelain( )->commits_last_year( + iv_url = iv_url + it_sha1 = lt_sha1 ). + LOOP AT lt_commits ASSIGNING . + INSERT INTO TABLE lt_objects. +* ignore subrc, it might already be there + ENDLOOP. + +******************************** + + lv_starting_folder = io_dot->get_starting_folder( ) && '*'. + + READ TABLE it_branches INTO ls_main WITH KEY display_name = zif_abapgit_flow_logic=>c_main. + ASSERT sy-subrc = 0. + + et_main_expanded = zcl_abapgit_git_porcelain=>full_tree( + it_objects = lt_objects + iv_parent = ls_main-sha1 ). + DELETE et_main_expanded WHERE path NP lv_starting_folder. + + find_up_to_date( + EXPORTING + it_branches = it_branches + it_objects = lt_objects + CHANGING + ct_features = ct_features ). + + LOOP AT ct_features ASSIGNING WHERE branch-display_name <> zif_abapgit_flow_logic=>c_main. + IF lv_previous IS INITIAL OR lv_previous <> -repo-key. + IF zcl_abapgit_flow_exit=>get_instance( )->get_settings( -repo-key )-allow_not_up_to_date = abap_true. + CREATE OBJECT li_find TYPE kHGwlqeiVzSltVlvDZbkLCHjJVYdTX + EXPORTING + it_objects = lt_objects. + ELSE. + CREATE OBJECT li_find TYPE kHGwlqeiVzSltVlvDZbkInGePeKchD + EXPORTING + it_objects = lt_objects. + ENDIF. + lv_previous = -repo-key. + ENDIF. + + -changed_files = li_find->find_changes( + iv_main = ls_main-sha1 + iv_branch = -branch-sha1 + iv_first_commit = -branch-first_commit + iv_starting_folder = lv_starting_folder ). + + -changed_objects = map_files_to_objects( + io_dot = io_dot + iv_package = iv_package + it_files = -changed_files ). + ENDLOOP. + + ENDMETHOD. + + METHOD map_files_to_objects. + + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + + FIELD-SYMBOLS LIKE LINE OF it_files. + LOOP AT it_files ASSIGNING . + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = -filename + iv_path = -path + iv_devclass = iv_package + io_dot = io_dot + IMPORTING + es_item = ls_item ). + INSERT ls_item INTO TABLE rt_changed_objects. + ENDLOOP. + + ENDMETHOD. + + METHOD find_up_to_date. + + DATA ls_main LIKE LINE OF it_branches. + DATA lv_current TYPE zif_abapgit_git_definitions=>ty_sha1. + DATA lo_visit TYPE REF TO kHGwlqeiVzSltVlvDZbkhPIfZcUzJG. + DATA ls_commit TYPE zcl_abapgit_git_pack=>ty_commit. + + DATA lt_main_reachable TYPE HASHED TABLE OF zif_abapgit_git_definitions=>ty_sha1 WITH UNIQUE KEY table_line. + + FIELD-SYMBOLS LIKE LINE OF ct_features. + FIELD-SYMBOLS LIKE LINE OF it_objects. + IF lines( it_branches ) = 1. + " only main branch + RETURN. + ENDIF. + + READ TABLE it_branches INTO ls_main WITH KEY display_name = zif_abapgit_flow_logic=>c_main. + ASSERT sy-subrc = 0. + + CREATE OBJECT lo_visit. + lo_visit->clear( )->push( ls_main-sha1 ). + WHILE lo_visit->size( ) > 0. + lv_current = lo_visit->pop( ). + INSERT lv_current INTO TABLE lt_main_reachable. + READ TABLE it_objects ASSIGNING WITH TABLE KEY sha COMPONENTS sha1 = lv_current. + IF sy-subrc = 0. + ls_commit = zcl_abapgit_git_pack=>decode_commit( -data ). + lo_visit->push( ls_commit-parent ). + IF ls_commit-parent2 IS NOT INITIAL. + lo_visit->push( ls_commit-parent2 ). + ENDIF. + ENDIF. + ENDWHILE. + + LOOP AT ct_features ASSIGNING . + -branch-up_to_date = abap_undefined. + lo_visit->clear( )->push( -branch-sha1 ). + + " find up_to_date + WHILE lo_visit->size( ) > 0. + lv_current = lo_visit->pop( ). + IF lv_current = ls_main-sha1. + -branch-up_to_date = abap_true. + EXIT. + ENDIF. + + READ TABLE lt_main_reachable WITH KEY table_line = lv_current TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + -branch-up_to_date = abap_false. + EXIT. + ENDIF. + + READ TABLE it_objects ASSIGNING WITH TABLE KEY sha COMPONENTS sha1 = lv_current. + IF sy-subrc = 0. + ls_commit = zcl_abapgit_git_pack=>decode_commit( -data ). + lo_visit->push( ls_commit-parent ). + IF ls_commit-parent2 IS NOT INITIAL. + lo_visit->push( ls_commit-parent2 ). + ENDIF. + ENDIF. + ENDWHILE. + + " find first commit + lo_visit->clear( )->push( -branch-sha1 ). + WHILE lo_visit->size( ) > 0. + lv_current = lo_visit->pop( ). + + READ TABLE it_objects ASSIGNING WITH TABLE KEY sha COMPONENTS sha1 = lv_current. + IF sy-subrc = 0. + ls_commit = zcl_abapgit_git_pack=>decode_commit( -data ). + lo_visit->push( ls_commit-parent ). + + IF ls_commit-parent2 IS INITIAL. + READ TABLE lt_main_reachable WITH KEY table_line = ls_commit-parent TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + -branch-first_commit = lv_current. + EXIT. + ENDIF. + ENDIF. + ENDIF. + ENDWHILE. + + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_flow_exit IMPLEMENTATION. + + METHOD get_instance. +* this exit only works with global classes + + IF gi_global_exit IS NOT INITIAL. + ri_exit = gi_global_exit. + RETURN. + ENDIF. + + TRY. + CREATE OBJECT gi_exit TYPE ('ZCL_ABAPGIT_FLOW_USER_EXIT'). + CATCH cx_sy_create_object_error ##NO_HANDLER. + ENDTRY. + + CREATE OBJECT gi_global_exit TYPE zcl_abapgit_flow_exit. " this class + + ri_exit = gi_global_exit. + + ENDMETHOD. + + METHOD zif_abapgit_flow_exit~on_event. + + IF gi_exit IS NOT INITIAL. + TRY. + rs_result = gi_exit->on_event( + ii_event = ii_event + it_features = it_features ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + + METHOD zif_abapgit_flow_exit~get_settings. + + IF gi_exit IS NOT INITIAL. + TRY. + rs_settings = gi_exit->get_settings( iv_repo_key ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + + METHOD zif_abapgit_flow_exit~toolbar_extras. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->toolbar_extras( + io_toolbar = io_toolbar + iv_index = iv_index + is_feature = is_feature ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + + METHOD zif_abapgit_flow_exit~info_extras. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->info_extras( + ii_html = ii_html + is_feature = is_feature ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_ui_core_factory IMPLEMENTATION. + METHOD get_html_viewer. + + IF gi_html_viewer IS NOT BOUND. + CREATE OBJECT gi_html_viewer TYPE zcl_abapgit_html_viewer_gui + EXPORTING + io_container = io_container + iv_disable_query_table = iv_disable_query_table. + ENDIF. + + ri_viewer = gi_html_viewer. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_html_viewer_gui IMPLEMENTATION. + METHOD constructor. + + DATA: lt_events TYPE cntl_simple_events, + ls_event LIKE LINE OF lt_events. + + CREATE OBJECT mo_html_viewer + EXPORTING + query_table_disabled = iv_disable_query_table + parent = io_container. + + ls_event-eventid = zif_abapgit_html_viewer=>c_id_sapevent. + ls_event-appl_event = abap_true. + APPEND ls_event TO lt_events. + + mo_html_viewer->set_registered_events( lt_events ). + SET HANDLER on_event FOR mo_html_viewer. + + ENDMETHOD. + METHOD on_event. + + RAISE EVENT zif_abapgit_html_viewer~sapevent + EXPORTING + action = action + frame = frame + getdata = getdata + postdata = postdata + query_table = query_table. + + ENDMETHOD. + METHOD zif_abapgit_html_viewer~back. + + mo_html_viewer->go_back( ). + + ENDMETHOD. + METHOD zif_abapgit_html_viewer~close_document. + + mo_html_viewer->close_document( ). + + ENDMETHOD. + METHOD zif_abapgit_html_viewer~free. + + mo_html_viewer->free( ). + + ENDMETHOD. + METHOD zif_abapgit_html_viewer~get_url. + + DATA lv_url TYPE c LENGTH 250. + mo_html_viewer->get_current_url( IMPORTING url = lv_url ). + cl_gui_cfw=>flush( ). + rv_url = lv_url. + + ENDMETHOD. + METHOD zif_abapgit_html_viewer~load_data. + + DATA lv_url TYPE c LENGTH 250. + DATA lv_assigned TYPE c LENGTH 250. + + ASSERT strlen( iv_url ) <= 250. + lv_url = iv_url. + mo_html_viewer->load_data( + EXPORTING + url = lv_url + type = iv_type + subtype = iv_subtype + size = iv_size + IMPORTING + assigned_url = lv_assigned + CHANGING + data_table = ct_data_table + EXCEPTIONS + dp_invalid_parameter = 1 + dp_error_general = 2 + cntl_error = 3 + " html_syntax_notcorrect = 4 " not in lower releases + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error loading data for HTML viewer' ). + ENDIF. + ev_assigned_url = lv_assigned. + + ENDMETHOD. + METHOD zif_abapgit_html_viewer~set_focus. + cl_gui_control=>set_focus( + EXPORTING + control = mo_html_viewer + EXCEPTIONS + cntl_error = 1 + cntl_system_error = 2 + OTHERS = 3 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error in: cl_gui_control=>set_focus - SUBRC = { sy-subrc }| ). + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_html_viewer~set_registered_events. + + mo_html_viewer->set_registered_events( + EXPORTING + events = it_events + EXCEPTIONS + cntl_error = 1 + cntl_system_error = 2 + illegal_event_combination = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error registering events for HTML viewer' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_html_viewer~set_visiblity. + DATA: lv_visible TYPE c LENGTH 1. + + IF iv_visible = abap_true. + lv_visible = cl_gui_container=>visible_true. + ELSE. + lv_visible = cl_gui_container=>visible_false. + ENDIF. + + mo_html_viewer->set_visible( lv_visible ). + ENDMETHOD. + METHOD zif_abapgit_html_viewer~show_url. + + DATA lv_url TYPE c LENGTH 250. + lv_url = iv_url. + mo_html_viewer->show_url( + EXPORTING + url = lv_url + EXCEPTIONS + cntl_error = 1 + cnht_error_not_allowed = 2 + cnht_error_parameter = 3 + dp_error_general = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error showing URL in HTML viewer' ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_HTML_PARTS IMPLEMENTATION. + METHOD add_part. + + DATA lr_collection TYPE REF TO ty_named_collection. + lr_collection = get_collection( + iv_collection = iv_collection + iv_create_if_missing = abap_true ). + APPEND ii_part TO lr_collection->pile. + + ENDMETHOD. + METHOD clear. + CLEAR mt_part_collections. + ENDMETHOD. + METHOD get_collection. + + READ TABLE mt_part_collections REFERENCE INTO rr_collection WITH KEY name = iv_collection. + IF sy-subrc <> 0 AND iv_create_if_missing = abap_true. + APPEND INITIAL LINE TO mt_part_collections REFERENCE INTO rr_collection. + rr_collection->name = iv_collection. + ENDIF. + + ENDMETHOD. + METHOD get_collection_names. + + FIELD-SYMBOLS LIKE LINE OF mt_part_collections. + LOOP AT mt_part_collections ASSIGNING . + APPEND -name TO rt_list. + ENDLOOP. + + ENDMETHOD. + METHOD get_collection_size. + + DATA lr_collection TYPE REF TO ty_named_collection. + lr_collection = get_collection( iv_collection ). + IF lr_collection IS BOUND. + rv_size = lines( lr_collection->pile ). + ENDIF. + + ENDMETHOD. + METHOD get_parts. + + DATA lr_collection TYPE REF TO ty_named_collection. + lr_collection = get_collection( iv_collection ). + IF lr_collection IS BOUND. + rt_parts = lr_collection->pile. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_html IMPLEMENTATION. + METHOD checkbox. + + DATA: lv_checked TYPE string. + + IF iv_checked = abap_true. + lv_checked = |checked|. + ENDIF. + + rv_html = |`. + + ENDMETHOD. + METHOD class_constructor. + + CREATE OBJECT go_single_tags_re + EXPORTING + pattern = '<(AREA|BASE|BR|COL|COMMAND|EMBED|HR|IMG|INPUT|LINK|META|PARAM|SOURCE|!)' + ignore_case = abap_false. + + gv_spaces = repeat( + val = ` ` + occ = c_max_indent ). + + ENDMETHOD. + METHOD create. + CREATE OBJECT ri_instance TYPE zcl_abapgit_html. + IF iv_initial_chunk IS NOT INITIAL. + ri_instance->add( iv_initial_chunk ). + ENDIF. + ENDMETHOD. + METHOD icon. + + DATA: lv_hint TYPE string, + lv_name TYPE string, + lv_color TYPE string, + lv_class TYPE string, + lv_onclick TYPE string. + + SPLIT iv_name AT '/' INTO lv_name lv_color. + + IF iv_hint IS NOT INITIAL. + lv_hint = | title="{ iv_hint }"|. + ENDIF. + IF iv_onclick IS NOT INITIAL. + lv_onclick = | onclick="{ iv_onclick }"|. + ENDIF. + IF iv_class IS NOT INITIAL. + lv_class = | { iv_class }|. + ENDIF. + IF lv_color IS NOT INITIAL. + lv_color = | { lv_color }|. + ENDIF. + + rv_str = ||. + + ENDMETHOD. + METHOD indent_line. + + DATA: ls_study TYPE ty_study_result, + lv_spaces TYPE i. + + ls_study = study_line( + is_context = cs_context + iv_line = cv_line ). + + " No indent for textarea tags + IF ls_study-textarea_open = abap_true. + cs_context-within_textarea = abap_true. + RETURN. + ELSEIF ls_study-textarea_close = abap_true. + cs_context-within_textarea = abap_false. + RETURN. + ELSEIF cs_context-within_textarea = abap_true. + RETURN. + ENDIF. + + " No indent for pre tags + IF ls_study-pre_open = abap_true. + cs_context-within_pre = abap_true. + RETURN. + ELSEIF ls_study-pre_close = abap_true. + cs_context-within_pre = abap_false. + RETURN. + ELSEIF cs_context-within_pre = abap_true. + RETURN. + ENDIF. + + " First closing tag - shift back exceptionally + IF ( ls_study-script_close = abap_true + OR ls_study-style_close = abap_true + OR ls_study-curly_close = abap_true + OR ls_study-tag_close = abap_true ) + AND cs_context-indent > 0. + lv_spaces = ( cs_context-indent - 1 ) * c_indent_size. + IF lv_spaces <= c_max_indent. + cv_line = gv_spaces(lv_spaces) && cv_line. + ELSE. + cv_line = gv_spaces && cv_line. + ENDIF. + ELSE. + cv_line = cs_context-indent_str && cv_line. + ENDIF. + + " Context status update + CASE abap_true. + WHEN ls_study-script_open. + cs_context-within_js = abap_true. + cs_context-within_style = abap_false. + WHEN ls_study-style_open. + cs_context-within_js = abap_false. + cs_context-within_style = abap_true. + WHEN ls_study-script_close OR ls_study-style_close. + cs_context-within_js = abap_false. + cs_context-within_style = abap_false. + ls_study-closings = ls_study-closings + 1. + ENDCASE. + + " More-less logic chosen due to possible double tags in a line '' + IF ls_study-openings <> ls_study-closings. + IF ls_study-openings > ls_study-closings. + cs_context-indent = cs_context-indent + 1. + ELSEIF cs_context-indent > 0. " AND ls_study-openings < ls_study-closings + cs_context-indent = cs_context-indent - 1. + ENDIF. + lv_spaces = cs_context-indent * c_indent_size. + IF lv_spaces <= c_max_indent. + cs_context-indent_str = gv_spaces(lv_spaces). + ELSE. + cv_line = gv_spaces && cv_line. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD parse_data_attr. + + SPLIT iv_str AT '=' INTO rs_data_attr-name rs_data_attr-value. + IF rs_data_attr-name IS INITIAL. + CLEAR rs_data_attr. + ENDIF. + + ENDMETHOD. + METHOD set_debug_mode. + gv_debug_mode = iv_mode. + ENDMETHOD. + METHOD study_line. + + DATA: lv_line TYPE string, + lv_len TYPE i. + + lv_line = to_upper( shift_left( val = iv_line + sub = ` ` ) ). + lv_len = strlen( lv_line ). + + " Some assumptions for simplification and speed + " - style & scripts tag should be opened/closed in a separate line + " - style & scripts opening and closing in one line is possible but only once + + " TODO & Issues + " - What if the string IS a well formed html already not just single line ? + + IF is_context-within_js = abap_true OR is_context-within_style = abap_true. + + IF is_context-within_js = abap_true AND lv_len >= 8 AND lv_line(8) = '= 7 AND lv_line(7) = '= 1 AND lv_line(1) = '}'. + rs_result-curly_close = abap_true. + ENDIF. + + FIND ALL OCCURRENCES OF '{' IN lv_line MATCH COUNT rs_result-openings. + FIND ALL OCCURRENCES OF '}' IN lv_line MATCH COUNT rs_result-closings. + ENDIF. + + ELSE. + IF lv_len >= 7 AND lv_line(7) = ' 0. " Not found + rs_result-script_open = abap_true. + ENDIF. + ENDIF. + IF lv_len >= 6 AND lv_line(6) = ' 0. " Not found + rs_result-style_open = abap_true. + ENDIF. + ENDIF. + IF lv_len >= 2 AND lv_line(2) = ' rs_result-openings. +* if everything is closings, there are no single tags + FIND ALL OCCURRENCES OF REGEX go_single_tags_re IN lv_line MATCH COUNT rs_result-singles. + ENDIF. + rs_result-openings = rs_result-openings - rs_result-closings - rs_result-singles. + + ENDIF. + + " Textarea (same assumptions as above) + IF is_context-within_textarea = abap_true AND lv_len >= 10 AND lv_line(10) = '= 9 AND lv_line(9) = ' 0. " Not found + rs_result-textarea_open = abap_true. + ENDIF. + ENDIF. + + " Pre (same assumptions as above) + IF is_context-within_pre = abap_true AND lv_len >= 5 AND lv_line(5) = '= 4 AND lv_line(4) = ' 0. " Not found + rs_result-pre_open = abap_true. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_html~a. + + DATA: lv_class TYPE string, + lv_href TYPE string, + lv_click TYPE string, + lv_id TYPE string, + lv_act TYPE string, + lv_style TYPE string, + lv_title TYPE string. + + lv_class = iv_class. + + IF iv_opt CA zif_abapgit_html=>c_html_opt-strong. + lv_class = lv_class && ' emphasis'. + ENDIF. + IF iv_opt CA zif_abapgit_html=>c_html_opt-cancel. + lv_class = lv_class && ' attention'. + ENDIF. + IF iv_opt CA zif_abapgit_html=>c_html_opt-crossout. + lv_class = lv_class && ' crossout grey'. + ENDIF. + IF lv_class IS NOT INITIAL. + SHIFT lv_class LEFT DELETING LEADING space. + lv_class = | class="{ lv_class }"|. + ENDIF. + + lv_href = ' href="#"'. " Default, dummy + lv_act = iv_act. + IF ( iv_act IS NOT INITIAL OR iv_typ = zif_abapgit_html=>c_action_type-dummy ) + AND iv_opt NA zif_abapgit_html=>c_html_opt-crossout. + CASE iv_typ. + WHEN zif_abapgit_html=>c_action_type-url. + IF iv_query IS NOT INITIAL. + lv_act = lv_act && `?` && iv_query. + ENDIF. + lv_href = | href="{ lv_act }"|. + WHEN zif_abapgit_html=>c_action_type-sapevent. + IF iv_query IS NOT INITIAL. + lv_act = lv_act && `?` && iv_query. + ENDIF. + lv_href = | href="sapevent:{ lv_act }"|. + WHEN zif_abapgit_html=>c_action_type-onclick. + lv_href = ' href="#"'. + lv_click = | onclick="{ iv_act }"|. + WHEN zif_abapgit_html=>c_action_type-dummy. + lv_href = ' href="#"'. + ENDCASE. + ENDIF. + + IF iv_id IS NOT INITIAL. + lv_id = | id="{ iv_id }"|. + ENDIF. + + IF iv_style IS NOT INITIAL. + lv_style = | style="{ iv_style }"|. + ENDIF. + + IF iv_title IS NOT INITIAL. + lv_title = | title="{ iv_title }"|. + ENDIF. + + " Debug option to display href-link on hover + IF gv_debug_mode = abap_true. + lv_title = | title="{ escape( + val = lv_href + format = cl_abap_format=>e_html_attr ) }"|. + ENDIF. + + rv_str = || + && |{ iv_txt }|. + + ENDMETHOD. + METHOD zif_abapgit_html~add. + + DATA: lv_type TYPE c, + li_renderable TYPE REF TO zif_abapgit_gui_renderable, + lx_error TYPE REF TO zcx_abapgit_exception, + lo_html TYPE REF TO zcl_abapgit_html. + + FIELD-SYMBOLS: TYPE string_table. + + lv_type = cl_abap_typedescr=>describe_by_data( ig_chunk )->type_kind. + + CASE lv_type. + WHEN 'C' OR 'g'. " Char or string + APPEND ig_chunk TO mt_buffer. + WHEN 'h'. " Table + ASSIGN ig_chunk TO . " Assuming table of strings ! Will dump otherwise + APPEND LINES OF TO mt_buffer. + WHEN 'r'. " Object ref + ASSERT ig_chunk IS BOUND. " Dev mistake + TRY. + lo_html ?= ig_chunk. + CATCH cx_sy_move_cast_error. + TRY. + li_renderable ?= ig_chunk. + lo_html ?= li_renderable->render( ). + CATCH cx_sy_move_cast_error. + ASSERT 1 = 0. " Dev mistake + CATCH zcx_abapgit_exception INTO lx_error. + lo_html ?= create( |Render error: { lx_error->get_text( ) }| ). + ENDTRY. + ENDTRY. + APPEND LINES OF lo_html->mt_buffer TO mt_buffer. + WHEN OTHERS. + ASSERT 1 = 0. " Dev mistake + ENDCASE. + + ri_self = me. + + ENDMETHOD. + METHOD zif_abapgit_html~add_a. + + zif_abapgit_html~add( zif_abapgit_html~a( + iv_txt = iv_txt + iv_act = iv_act + iv_query = iv_query + iv_typ = iv_typ + iv_opt = iv_opt + iv_class = iv_class + iv_id = iv_id + iv_style = iv_style + iv_title = iv_title ) ). + + ri_self = me. + + ENDMETHOD. + METHOD zif_abapgit_html~add_checkbox. + + zif_abapgit_html~add( checkbox( + iv_id = iv_id + iv_checked = iv_checked ) ). + + ri_self = me. + + ENDMETHOD. + METHOD zif_abapgit_html~add_icon. + + zif_abapgit_html~add( icon( + iv_name = iv_name + iv_class = iv_class + iv_hint = iv_hint + iv_onclick = iv_onclick ) ). + + ri_self = me. + + ENDMETHOD. + METHOD zif_abapgit_html~div. + + zif_abapgit_html~wrap( + iv_tag = 'div' + iv_content = iv_content + ii_content = ii_content + is_data_attr = is_data_attr + it_data_attrs = it_data_attrs + iv_id = iv_id + iv_style = iv_style + iv_class = iv_class ). + + ri_self = me. + + ENDMETHOD. + METHOD zif_abapgit_html~icon. + + rv_str = icon( + iv_name = iv_name + iv_hint = iv_hint + iv_class = iv_class + iv_onclick = iv_onclick ). + + ENDMETHOD. + METHOD zif_abapgit_html~is_empty. + rv_yes = boolc( lines( mt_buffer ) = 0 ). + ENDMETHOD. + METHOD zif_abapgit_html~render. + + DATA: ls_context TYPE ty_indent_context, + lt_temp TYPE string_table. + + FIELD-SYMBOLS: LIKE LINE OF lt_temp, + LIKE LINE OF lt_temp. + + IF iv_no_line_breaks = abap_true. + CONCATENATE LINES OF mt_buffer INTO rv_html. + ELSE. + ls_context-no_indent_jscss = iv_no_indent_jscss. + + LOOP AT mt_buffer ASSIGNING . + APPEND TO lt_temp ASSIGNING . + indent_line( CHANGING cs_context = ls_context cv_line = ). + ENDLOOP. + + CONCATENATE LINES OF lt_temp INTO rv_html SEPARATED BY cl_abap_char_utilities=>newline. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_html~set_title. + zif_abapgit_html~mv_chunk_title = iv_title. + ri_self = me. + ENDMETHOD. + METHOD zif_abapgit_html~td. + + zif_abapgit_html~wrap( + iv_format_single_line = iv_format_single_line + iv_tag = 'td' + iv_content = iv_content + ii_content = ii_content + iv_id = iv_id + iv_class = iv_class + iv_style = iv_style + is_data_attr = is_data_attr + it_data_attrs = it_data_attrs + iv_hint = iv_hint ). + + ri_self = me. + + ENDMETHOD. + METHOD zif_abapgit_html~th. + + zif_abapgit_html~wrap( + iv_format_single_line = iv_format_single_line + iv_tag = 'th' + iv_content = iv_content + ii_content = ii_content + iv_id = iv_id + iv_class = iv_class + iv_style = iv_style + is_data_attr = is_data_attr + it_data_attrs = it_data_attrs + iv_hint = iv_hint ). + + ri_self = me. + + ENDMETHOD. + METHOD zif_abapgit_html~wrap. + + DATA lv_open_tag TYPE string. + DATA lv_close_tag TYPE string. + DATA ls_data_attr LIKE LINE OF it_data_attrs. + + DATA: lv_class TYPE string, + lv_style TYPE string, + lv_id TYPE string, + lv_data_attr TYPE string, + lv_title TYPE string. + + IF iv_id IS NOT INITIAL. + lv_id = | id="{ iv_id }"|. + ENDIF. + + IF iv_class IS NOT INITIAL. + lv_class = | class="{ iv_class }"|. + ENDIF. + + IF iv_style IS NOT INITIAL. + lv_style = | style="{ iv_style }"|. + ENDIF. + + IF iv_hint IS NOT INITIAL. + lv_title = | title="{ iv_hint }"|. + ENDIF. + + IF is_data_attr IS NOT INITIAL. + lv_data_attr = | data-{ is_data_attr-name }="{ is_data_attr-value }"|. + ENDIF. + + LOOP AT it_data_attrs INTO ls_data_attr. + lv_data_attr = lv_data_attr && | data-{ ls_data_attr-name }="{ ls_data_attr-value }"|. + ENDLOOP. + + lv_open_tag = |<{ iv_tag }{ lv_id }{ lv_class }{ lv_style }{ lv_data_attr }{ lv_title }>|. + lv_close_tag = ||. + + IF ii_content IS NOT BOUND AND iv_content IS INITIAL. + lv_open_tag = lv_open_tag && lv_close_tag. + CLEAR lv_close_tag. + ENDIF. + + IF iv_format_single_line = abap_true AND iv_content IS NOT INITIAL. + zif_abapgit_html~add( lv_open_tag && iv_content && lv_close_tag ). + ELSE. + zif_abapgit_html~add( lv_open_tag ). + IF ii_content IS BOUND. + zif_abapgit_html~add( ii_content ). + ELSEIF iv_content IS NOT INITIAL. + zif_abapgit_html~add( iv_content ). + ENDIF. + IF lv_close_tag IS NOT INITIAL. + zif_abapgit_html~add( lv_close_tag ). + ENDIF. + ENDIF. + + ri_self = me. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_UTILS IMPLEMENTATION. + METHOD is_event_handler. + DATA li_event_handler TYPE REF TO zif_abapgit_gui_event_handler. + TRY. + li_event_handler ?= io_obj. + rv_yes = abap_true. + CATCH cx_sy_move_cast_error. + rv_yes = abap_false. + ENDTRY. + ENDMETHOD. + METHOD is_renderable. + DATA li_renderable TYPE REF TO zif_abapgit_gui_renderable. + TRY. + li_renderable ?= io_obj. + rv_yes = abap_true. + CATCH cx_sy_move_cast_error. + rv_yes = abap_false. + ENDTRY. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_HTML_PROCESSOR IMPLEMENTATION. + METHOD constructor. + mi_asset_man = ii_asset_man. + ENDMETHOD. + METHOD is_preserved. + READ TABLE mt_preserve_css TRANSPORTING NO FIELDS WITH KEY table_line = iv_css_url. + rv_yes = boolc( sy-subrc = 0 ). + ENDMETHOD. + METHOD patch_html. + + CONSTANTS lc_css_re TYPE string VALUE ``. + + DATA lv_head_end TYPE i. + DATA lo_css_re TYPE REF TO cl_abap_regex. + DATA lo_matcher TYPE REF TO cl_abap_matcher. + DATA lv_css_path TYPE string. + DATA lv_marker TYPE string. + + DATA lv_off TYPE i. + DATA lv_len TYPE i. + DATA lv_cur TYPE i. + + DATA lv_css_build TYPE string VALUE ''. + REPLACE FIRST OCCURRENCE OF '$BUILD_NAME' IN lv_css_build WITH c_css_build_name. " Mmmm + + CLEAR: ev_html, et_css_urls. + + lv_head_end = find_head_offset( iv_html ). + + CREATE OBJECT lo_css_re + EXPORTING + ignore_case = abap_true + pattern = lc_css_re. + + lo_matcher = lo_css_re->create_matcher( text = substring( val = iv_html len = lv_head_end ) ). + WHILE lo_matcher->find_next( ) = abap_true. + lv_css_path = lo_matcher->get_submatch( 1 ). + IF abap_false = is_preserved( lv_css_path ). + lv_off = lo_matcher->get_offset( ). + lv_len = lo_matcher->get_length( ). + ev_html = ev_html && substring( val = iv_html + off = lv_cur + len = lv_off - lv_cur ). + ev_html = ev_html && c_comment_start && substring( val = iv_html + off = lv_off + len = lv_len ) && c_comment_end. + lv_cur = lv_off + lv_len. + APPEND lv_css_path TO et_css_urls. + ENDIF. + ENDWHILE. + + ev_html = ev_html && substring( val = iv_html + off = lv_cur + len = lv_head_end - lv_cur ). + IF lines( et_css_urls ) > 0. + lv_marker = cl_abap_char_utilities=>newline + && ` ` " Assume 4 space indent, maybe improve and detect ? + && c_preprocess_marker + && cl_abap_char_utilities=>newline + && ` `. + ev_html = ev_html && lv_marker && lv_css_build. + ENDIF. + ev_html = ev_html && substring( val = iv_html + off = lv_head_end ). + + ENDMETHOD. + METHOD preserve_css. + APPEND iv_css_url TO mt_preserve_css. + ENDMETHOD. + METHOD zif_abapgit_gui_html_processor~process. + + DATA lo_css_processor TYPE REF TO zcl_abapgit_gui_css_processor. + DATA lt_css_urls TYPE string_table. + DATA lv_css_build TYPE string. + + FIELD-SYMBOLS LIKE LINE OF lt_css_urls. + + patch_html( + EXPORTING + iv_html = iv_html + IMPORTING + ev_html = rv_html + et_css_urls = lt_css_urls ). + + IF lines( lt_css_urls ) > 0. + CREATE OBJECT lo_css_processor + EXPORTING + ii_asset_manager = mi_asset_man. + + LOOP AT lt_css_urls ASSIGNING . + lo_css_processor->add_file( ). + ENDLOOP. + + lv_css_build = lo_css_processor->process( ). + + ii_gui_services->cache_asset( + iv_url = |{ c_css_build_name }| + iv_type = 'text' + iv_subtype = 'css' + iv_text = lv_css_build ). + ENDIF. + + ENDMETHOD. + + METHOD find_head_offset. + + rv_head_end = find( val = iv_html + regex = |{ cl_abap_char_utilities=>newline }?\\s*| + case = abap_false ). + IF rv_head_end <= 0. + rv_head_end = find( val = iv_html + regex = || + case = abap_false ). + IF rv_head_end <= 0. + zcx_abapgit_exception=>raise( 'HTML preprocessor: not found' ). + ENDIF. + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_gui_event IMPLEMENTATION. + METHOD class_constructor. + + CONSTANTS lc_nbsp TYPE xstring VALUE 'C2A0'. "   + + TRY. + gv_non_breaking_space = zcl_abapgit_convert=>xstring_to_string_utf8( lc_nbsp ). + CATCH zcx_abapgit_exception. + " Fallback for non-Unicode systems + IF cl_abap_char_utilities=>charsize < 2. + gv_non_breaking_space = |X'A0'|. + ELSE. + ASSERT 0 = 1. + ENDIF. + ENDTRY. + + ENDMETHOD. + METHOD constructor. + + " Edge Webview control returns upper case action but abapGit requires lower case (#4841) + zif_abapgit_gui_event~mi_gui_services = ii_gui_services. + zif_abapgit_gui_event~mv_action = to_lower( iv_action ). + zif_abapgit_gui_event~mv_getdata = iv_getdata. + zif_abapgit_gui_event~mt_postdata = it_postdata. + + IF ii_gui_services IS BOUND. + zif_abapgit_gui_event~mv_current_page_name = ii_gui_services->get_current_page_name( ). + ENDIF. + + ENDMETHOD. + METHOD fields_to_map. + FIELD-SYMBOLS LIKE LINE OF it_fields. + + CREATE OBJECT ro_string_map EXPORTING iv_case_insensitive = abap_true. + LOOP AT it_fields ASSIGNING . + ro_string_map->set( + iv_key = -name + iv_val = -value ). + ENDLOOP. + ENDMETHOD. + METHOD field_keys_to_upper. + + FIELD-SYMBOLS LIKE LINE OF ct_fields. + + LOOP AT ct_fields ASSIGNING . + -name = to_upper( -name ). + ENDLOOP. + + ENDMETHOD. + METHOD new. + CREATE OBJECT ro_instance + EXPORTING + ii_gui_services = ii_gui_services + iv_action = iv_action + iv_getdata = iv_getdata + it_postdata = it_postdata. + ENDMETHOD. + METHOD parse_fields. + + DATA: + lt_substrings TYPE string_table, + ls_field LIKE LINE OF rt_fields. + + FIELD-SYMBOLS LIKE LINE OF lt_substrings. + + SPLIT iv_string AT '&' INTO TABLE lt_substrings. + + LOOP AT lt_substrings ASSIGNING . + + CLEAR ls_field. + " On attempt to change unescaping -> run unit tests to check ! + + " Unescape name and value separately + ls_field-name = unescape( substring_before( + val = + sub = '=' ) ). + + ls_field-value = unescape( substring_after( + val = + sub = '=' ) ). + + IF ls_field IS INITIAL. " Not a field with proper structure + CONTINUE. + ENDIF. + + APPEND ls_field TO rt_fields. + + ENDLOOP. + + IF iv_upper_cased = abap_true. + field_keys_to_upper( CHANGING ct_fields = rt_fields ). + ENDIF. + + ENDMETHOD. + METHOD parse_fields_upper_case_name. + + rt_fields = parse_fields( + iv_string = iv_string + iv_upper_cased = abap_true ). + + ENDMETHOD. + METHOD parse_post_form_data. + + DATA lv_serialized_post_data TYPE string. + + lv_serialized_post_data = translate_postdata( it_post_data ). + IF iv_upper_cased = abap_true. + rt_fields = parse_fields_upper_case_name( lv_serialized_post_data ). + ELSE. + rt_fields = parse_fields( lv_serialized_post_data ). + ENDIF. + + ENDMETHOD. + METHOD translate_postdata. + + DATA: lt_post_data TYPE zif_abapgit_html_viewer=>ty_post_data, + ls_last_line LIKE LINE OF it_postdata, + lv_last_line_index TYPE i. + + IF it_postdata IS INITIAL. + RETURN. "Nothing to do + ENDIF. + + lt_post_data = it_postdata. + + "Save the last line for separate merge, because we don't need its trailing spaces + WHILE ls_last_line IS INITIAL. + lv_last_line_index = lines( lt_post_data ). + READ TABLE lt_post_data INTO ls_last_line INDEX lv_last_line_index. + DELETE lt_post_data INDEX lv_last_line_index. + ENDWHILE. + + CONCATENATE LINES OF lt_post_data INTO rv_string + IN CHARACTER MODE RESPECTING BLANKS. + CONCATENATE rv_string ls_last_line INTO rv_string + IN CHARACTER MODE. + + ENDMETHOD. + METHOD unescape. + +* do not use cl_http_utility as it does strange things with the encoding + rv_string = iv_string. + +* todo, more to be added here + REPLACE ALL OCCURRENCES OF '%3A' IN rv_string WITH ':' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%3F' IN rv_string WITH '?' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%3D' IN rv_string WITH '=' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%2F' IN rv_string WITH '/' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%25' IN rv_string WITH '%' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%26' IN rv_string WITH '&' IGNORING CASE. + REPLACE ALL OCCURRENCES OF gv_non_breaking_space IN rv_string WITH ` `. + + ENDMETHOD. + METHOD zif_abapgit_gui_event~form_data. + + IF mo_form_data IS NOT BOUND. + mo_form_data = fields_to_map( parse_post_form_data( zif_abapgit_gui_event~mt_postdata ) ). + mo_form_data->freeze( ). + ENDIF. + ro_string_map = mo_form_data. + + ENDMETHOD. + METHOD zif_abapgit_gui_event~query. + + IF mo_query IS NOT BOUND. + mo_query = fields_to_map( parse_fields( zif_abapgit_gui_event~mv_getdata ) ). + mo_query->freeze( ). + ENDIF. + ro_string_map = mo_query. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GUI_CSS_PROCESSOR IMPLEMENTATION. + METHOD add_file. + APPEND iv_url TO mt_files. + ENDMETHOD. + METHOD constructor. + mi_asset_manager = ii_asset_manager. + ENDMETHOD. + METHOD get_css_vars_in_string. + CONSTANTS: lc_root_pattern TYPE string VALUE `:root\s*\{([^\}]*)\}`, + lc_variable_pattern TYPE string VALUE `\-\-([\w\d-]+)\s*:\s*([^\n\r;]*);`. + DATA: lv_root TYPE string, + lo_matcher TYPE REF TO cl_abap_matcher, + lo_regex TYPE REF TO cl_abap_regex, + ls_variable LIKE LINE OF rt_variables. + + " Only the :root element may define variables for now + + FIND FIRST OCCURRENCE OF REGEX lc_root_pattern IN iv_string SUBMATCHES lv_root. + IF sy-subrc = 0 AND lv_root IS NOT INITIAL. + CREATE OBJECT lo_regex + EXPORTING + pattern = lc_variable_pattern. + lo_matcher = lo_regex->create_matcher( text = lv_root ). + WHILE lo_matcher->find_next( ) = abap_true. + ls_variable-name = lo_matcher->get_submatch( 1 ). + ls_variable-value = lo_matcher->get_submatch( 2 ). + INSERT ls_variable INTO TABLE rt_variables. + IF sy-subrc <> 0. + MODIFY TABLE rt_variables FROM ls_variable. + ENDIF. + ENDWHILE. + ENDIF. + ENDMETHOD. + METHOD process. + DATA: + lt_contents TYPE STANDARD TABLE OF string, + lv_content TYPE string, + lt_css_variables TYPE ty_css_vars, + lt_css_vars_in_file TYPE ty_css_vars. + FIELD-SYMBOLS: TYPE string, + LIKE LINE OF lt_css_vars_in_file, + LIKE LINE OF lt_contents. + + " 1. Determine all variables and their values. Later definitions overwrite previous ones. + LOOP AT mt_files ASSIGNING . + lv_content = mi_asset_manager->get_text_asset( + iv_url = + iv_assert_subtype = 'css' ). + + lt_css_vars_in_file = get_css_vars_in_string( lv_content ). + + LOOP AT lt_css_vars_in_file ASSIGNING . + INSERT INTO TABLE lt_css_variables. + IF sy-subrc <> 0. + MODIFY TABLE lt_css_variables FROM . + ENDIF. + ENDLOOP. + + APPEND lv_content TO lt_contents. + ENDLOOP. + + " 2. Replace all variable usages in variables + LOOP AT lt_css_variables ASSIGNING WHERE value CS 'var(--'. + resolve_var_recursively( EXPORTING iv_variable_name = -name + CHANGING ct_variables = lt_css_variables ). + ENDLOOP. + + " 3. Replace all other variable usages by inlining the values. + LOOP AT lt_contents ASSIGNING . + LOOP AT lt_css_variables ASSIGNING . + REPLACE ALL OCCURRENCES OF |var(--{ -name })| + IN + WITH -value. + ENDLOOP. + ENDLOOP. + + rv_result = concat_lines_of( table = lt_contents + sep = cl_abap_char_utilities=>newline ). + ENDMETHOD. + METHOD resolve_var_recursively. + CONSTANTS: lc_variable_usage_pattern TYPE string VALUE `var\(\-\-([^\)]*)\)`. + DATA: lv_variable_name TYPE string. + FIELD-SYMBOLS: LIKE LINE OF ct_variables, + LIKE LINE OF ct_variables. + + READ TABLE ct_variables WITH TABLE KEY name = iv_variable_name ASSIGNING . + IF sy-subrc = 0. + DO. + FIND FIRST OCCURRENCE OF REGEX lc_variable_usage_pattern + IN -value + SUBMATCHES lv_variable_name. + IF sy-subrc = 0. + resolve_var_recursively( EXPORTING iv_variable_name = lv_variable_name + CHANGING ct_variables = ct_variables ). + READ TABLE ct_variables WITH TABLE KEY name = lv_variable_name ASSIGNING . + REPLACE FIRST OCCURRENCE OF |var(--{ lv_variable_name })| + IN -value + WITH -value. + ELSE. + EXIT. + ENDIF. + ENDDO. + ELSE. + zcx_abapgit_exception=>raise( |CSS variable { iv_variable_name } not resolvable| ). + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_asset_manager IMPLEMENTATION. + METHOD create. + CREATE OBJECT ri_asset_manager TYPE zcl_abapgit_gui_asset_manager. + ENDMETHOD. + METHOD get_mime_asset. + + DATA: ls_key TYPE wwwdatatab, + lv_size_c TYPE wwwparams-value, + lv_size TYPE i, + lt_w3mime TYPE STANDARD TABLE OF w3mime, + ls_w3mime LIKE LINE OF lt_w3mime. + + ls_key-relid = 'MI'. + ls_key-objid = iv_mime_name. + + " Get exact file size + CALL FUNCTION 'WWWPARAMS_READ' + EXPORTING + relid = ls_key-relid + objid = ls_key-objid + name = 'filesize' + IMPORTING + value = lv_size_c + EXCEPTIONS + entry_not_exists = 1. + + IF sy-subrc IS NOT INITIAL. + RETURN. + ENDIF. + + lv_size = lv_size_c. + + " Get binary data + CALL FUNCTION 'WWWDATA_IMPORT' + EXPORTING + key = ls_key + TABLES + mime = lt_w3mime + EXCEPTIONS + wrong_object_type = 1 + import_error = 2. + + IF sy-subrc IS NOT INITIAL. + RETURN. + ENDIF. + + LOOP AT lt_w3mime INTO ls_w3mime. + CONCATENATE rv_xdata ls_w3mime-line INTO rv_xdata IN BYTE MODE. + ENDLOOP. + rv_xdata = rv_xdata(lv_size). + + ENDMETHOD. + METHOD load_asset. + + MOVE-CORRESPONDING is_asset_entry TO rs_asset. + IF rs_asset-content IS INITIAL AND is_asset_entry-mime_name IS NOT INITIAL. + " inline content has the priority + rs_asset-content = get_mime_asset( is_asset_entry-mime_name ). + ENDIF. + IF rs_asset-content IS INITIAL. + zcx_abapgit_exception=>raise( |failed to load GUI asset: { is_asset_entry-url }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_asset_manager~get_all_assets. + + FIELD-SYMBOLS LIKE LINE OF mt_asset_register. + + LOOP AT mt_asset_register ASSIGNING . + APPEND load_asset( ) TO rt_assets. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_gui_asset_manager~get_asset. + + FIELD-SYMBOLS LIKE LINE OF mt_asset_register. + + READ TABLE mt_asset_register WITH KEY url = iv_url ASSIGNING . + IF IS NOT ASSIGNED. + zcx_abapgit_exception=>raise( |Cannot find GUI asset: { iv_url }| ). + ENDIF. + rs_asset = load_asset( ). + + ENDMETHOD. + METHOD zif_abapgit_gui_asset_manager~get_text_asset. + + DATA ls_asset TYPE zif_abapgit_gui_asset_manager~ty_web_asset. + ls_asset = zif_abapgit_gui_asset_manager~get_asset( iv_url ). + + IF ls_asset-type <> 'text'. + zcx_abapgit_exception=>raise( |Not a text asset: { iv_url }| ). + ENDIF. + + IF iv_assert_subtype IS NOT INITIAL AND ls_asset-subtype <> iv_assert_subtype. + zcx_abapgit_exception=>raise( |Wrong subtype ({ iv_assert_subtype }): { iv_url }| ). + ENDIF. + + rv_asset = zcl_abapgit_convert=>xstring_to_string_utf8( ls_asset-content ). + + ENDMETHOD. + METHOD zif_abapgit_gui_asset_manager~register_asset. + + DATA ls_asset LIKE LINE OF mt_asset_register. + + SPLIT iv_type AT '/' INTO ls_asset-type ls_asset-subtype. + ls_asset-url = iv_url. + ls_asset-mime_name = iv_mime_name. + ls_asset-is_cacheable = iv_cacheable. + IF iv_base64 IS NOT INITIAL. + ls_asset-content = zcl_abapgit_convert=>base64_to_xstring( iv_base64 ). + ELSEIF iv_inline IS NOT INITIAL. + ls_asset-content = zcl_abapgit_convert=>string_to_xstring( iv_inline ). + ENDIF. + + DELETE mt_asset_register WHERE url = iv_url. + " TODO: Maybe forbid overwriting cacheable assets as they were probably already cached ... arguable + APPEND ls_asset TO mt_asset_register. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui IMPLEMENTATION. + METHOD back. + + DATA lv_index TYPE i. + DATA ls_stack LIKE LINE OF mt_stack. + + " If viewer is showing Internet page, then use browser navigation + IF mi_html_viewer->get_url( ) CP 'http*'. + mi_html_viewer->back( ). + RETURN. + ENDIF. + + lv_index = lines( mt_stack ). + + IF lv_index = 0. + rv_exit = abap_true. + RETURN. + ENDIF. + + IF iv_graceful = abap_true AND back_graceful( ) = abap_true. + RETURN. + ENDIF. + + DO lv_index TIMES. + READ TABLE mt_stack INDEX lv_index INTO ls_stack. + ASSERT sy-subrc = 0. + + DELETE mt_stack INDEX lv_index. + ASSERT sy-subrc = 0. + + lv_index = lv_index - 1. + + IF iv_to_bookmark = abap_false OR ls_stack-bookmark = abap_true. + EXIT. + ENDIF. + ENDDO. + + mi_cur_page = ls_stack-page. " last page always stays + render( ). + + ENDMETHOD. + METHOD back_graceful. + + DATA li_handler TYPE REF TO zif_abapgit_gui_event_handler. + DATA ls_handled TYPE zif_abapgit_gui_event_handler=>ty_handling_result. + + " This code can be potentially improved + " Why send go_back to the topmost handler only ? It makes sense to notify the whole stack + " But than how to handle re-render ? render if at least one handler asks for it ? + " Probably that's the way but needs a relevant example. Postponed arch decision. + READ TABLE mt_event_handlers INTO li_handler INDEX 1. + IF sy-subrc = 0. + ls_handled = li_handler->on_event( zcl_abapgit_gui_event=>new( + iv_action = zif_abapgit_definitions=>c_action-go_back + ii_gui_services = me ) ). + IF ls_handled-state = c_event_state-re_render. " soft exit, probably popup + render( ). + rv_handled = abap_true. + ELSEIF ls_handled-state = c_event_state-no_more_act. " soft exit, probably GUI popup + rv_handled = abap_true. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD cache_html. + + rv_url = zif_abapgit_gui_services~cache_asset( + iv_text = iv_text + iv_type = 'text' + iv_subtype = 'html' ). + + ENDMETHOD. + METHOD call_page. + + DATA: ls_stack TYPE ty_page_stack. + + IF iv_replacing = abap_false AND NOT mi_cur_page IS INITIAL. + ls_stack-page = mi_cur_page. + ls_stack-bookmark = iv_with_bookmark. + APPEND ls_stack TO mt_stack. + ENDIF. + + mi_cur_page = ii_page. + render( ). + + ENDMETHOD. + METHOD constructor. + + IF io_component IS BOUND. + IF zcl_abapgit_gui_utils=>is_renderable( io_component ) = abap_true. + mi_cur_page ?= io_component. " direct page + ELSE. + IF zcl_abapgit_gui_utils=>is_event_handler( io_component ) = abap_false. + zcx_abapgit_exception=>raise( 'Component must be renderable or be an event handler' ). + ENDIF. + mi_router ?= io_component. + ENDIF. + ENDIF. + + CREATE OBJECT mo_html_parts. + + mv_rollback_on_error = iv_rollback_on_error. + mi_asset_man = ii_asset_man. + mi_hotkey_ctl = ii_hotkey_ctl. + mi_html_processor = ii_html_processor. " Maybe improve to middlewares stack ?? + startup( ). + + ENDMETHOD. + METHOD free. + + SET HANDLER on_event FOR mi_html_viewer ACTIVATION space. + mi_html_viewer->close_document( ). + mi_html_viewer->free( ). + FREE mi_html_viewer. + + ENDMETHOD. + METHOD go_home. + + DATA ls_stack LIKE LINE OF mt_stack. + + IF mi_router IS BOUND. + CLEAR: mt_stack, mt_event_handlers. + APPEND mi_router TO mt_event_handlers. + + on_event( action = |{ iv_action }| ). + ELSE. + IF lines( mt_stack ) > 0. + READ TABLE mt_stack INTO ls_stack INDEX 1. + mi_cur_page = ls_stack-page. + ENDIF. + render( ). + ENDIF. + + ENDMETHOD. + METHOD handle_action. + + DATA: + lx_exception TYPE REF TO zcx_abapgit_exception, + li_handler TYPE REF TO zif_abapgit_gui_event_handler, + li_event TYPE REF TO zif_abapgit_gui_event, + ls_handled TYPE zif_abapgit_gui_event_handler=>ty_handling_result. + + CREATE OBJECT li_event TYPE zcl_abapgit_gui_event + EXPORTING + ii_gui_services = me + iv_action = iv_action + iv_getdata = iv_getdata + it_postdata = it_postdata. + + TRY. + ls_handled = zcl_abapgit_exit=>get_instance( )->on_event( li_event ). + + IF ls_handled-state = c_event_state-not_handled. + LOOP AT mt_event_handlers INTO li_handler. + ls_handled = li_handler->on_event( li_event ). + IF ls_handled-state IS NOT INITIAL AND ls_handled-state <> c_event_state-not_handled. " is handled + EXIT. + ENDIF. + ENDLOOP. + ENDIF. + + IF is_page_modal( mi_cur_page ) = abap_true AND NOT ( + ls_handled-state = c_event_state-re_render OR + ls_handled-state = c_event_state-go_back OR + ls_handled-state = c_event_state-no_more_act ). + " Restrict new page switching from modals + ls_handled-state = c_event_state-no_more_act. + ENDIF. + + CASE ls_handled-state. + WHEN c_event_state-re_render. + render( ). + WHEN c_event_state-new_page. + call_page( ls_handled-page ). + WHEN c_event_state-new_page_w_bookmark. + call_page( + ii_page = ls_handled-page + iv_with_bookmark = abap_true ). + WHEN c_event_state-new_page_replacing. + call_page( + ii_page = ls_handled-page + iv_replacing = abap_true ). + WHEN c_event_state-go_back. + back( ). + WHEN c_event_state-go_back_to_bookmark. + back( iv_to_bookmark = abap_true ). + WHEN c_event_state-no_more_act. + " Do nothing, handling completed + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Unknown action: { iv_action }| ). + ENDCASE. + + CATCH zcx_abapgit_cancel ##NO_HANDLER. + " Do nothing = c_event_state-no_more_act + CATCH zcx_abapgit_exception INTO lx_exception. + handle_error( + iv_state = ls_handled-state + ix_exception = lx_exception ). + ENDTRY. + + ENDMETHOD. + METHOD handle_error. + + DATA: li_gui_error_handler TYPE REF TO zif_abapgit_gui_error_handler, + lx_exception TYPE REF TO cx_root. + + IF mv_rollback_on_error = abap_true. + ROLLBACK WORK. + ENDIF. + + TRY. + li_gui_error_handler ?= mi_cur_page. + + IF li_gui_error_handler IS BOUND AND li_gui_error_handler->handle_error( ix_exception ) = abap_true. + " If error happens when opening a new page, for example, the login to repo fails, + " then go back to previous page. + " Otherwise, re-render the current page to display the error box + IF is_new_page( iv_state ) = abap_true. + MESSAGE ix_exception TYPE 'S' DISPLAY LIKE 'E'. + back( ). + ELSE. + render( ). + ENDIF. + ELSEIF ix_exception->mi_log IS BOUND. + mi_common_log = ix_exception->mi_log. + IF mi_common_log->get_log_level( ) >= zif_abapgit_log=>c_log_level-warning. + zcl_abapgit_log_viewer=>show_log( mi_common_log ). + ENDIF. + ELSE. + MESSAGE ix_exception TYPE 'S' DISPLAY LIKE 'E'. + ENDIF. + + CATCH zcx_abapgit_exception cx_sy_move_cast_error INTO lx_exception. + " In case of fire we just fallback to plain old message + MESSAGE lx_exception TYPE 'S' DISPLAY LIKE 'E'. + ENDTRY. + + ENDMETHOD. + METHOD is_new_page. + + rv_new_page = boolc( + iv_state = c_event_state-new_page OR + iv_state = c_event_state-new_page_w_bookmark ). + + ENDMETHOD. + METHOD is_page_modal. + + DATA li_modal TYPE REF TO zif_abapgit_gui_modal. + + TRY. + IF ii_page IS BOUND. + li_modal ?= ii_page. + rv_yes = li_modal->is_modal( ). + ENDIF. + CATCH cx_sy_move_cast_error ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD on_event. + + handle_action( + iv_action = action + iv_getdata = getdata + it_postdata = postdata ). + + ENDMETHOD. + METHOD render. + + DATA: lv_url TYPE string, + lv_html TYPE string, + li_html TYPE REF TO zif_abapgit_html. + + IF mi_cur_page IS NOT BOUND. + zcx_abapgit_exception=>raise( 'GUI error: no current page' ). + ENDIF. + + CLEAR mt_event_handlers. + mo_html_parts->clear( ). + + IF mi_router IS BOUND AND is_page_modal( mi_cur_page ) = abap_false. + " No global commands in modals + APPEND mi_router TO mt_event_handlers. + ENDIF. + + IF mi_hotkey_ctl IS BOUND. + mi_hotkey_ctl->reset( ). + ENDIF. + + li_html = mi_cur_page->render( ). + lv_html = li_html->render( iv_no_indent_jscss = abap_true ). + + IF mi_html_processor IS BOUND. + lv_html = mi_html_processor->process( + iv_html = lv_html + ii_gui_services = me ). + ENDIF. + + lv_url = cache_html( lv_html ). + mi_html_viewer->show_url( lv_url ). + + ENDMETHOD. + METHOD set_focus. + mi_html_viewer->set_focus( ). + ENDMETHOD. + METHOD startup. + + DATA: lt_events TYPE cntl_simple_events, + ls_event LIKE LINE OF lt_events, + lt_assets TYPE zif_abapgit_gui_asset_manager=>ty_web_assets. + + FIELD-SYMBOLS LIKE LINE OF lt_assets. + mi_html_viewer = zcl_abapgit_ui_core_factory=>get_html_viewer( ). + + IF mi_asset_man IS BOUND. + lt_assets = mi_asset_man->get_all_assets( ). + LOOP AT lt_assets ASSIGNING WHERE is_cacheable = abap_true. + zif_abapgit_gui_services~cache_asset( + iv_xdata = -content + iv_url = -url + iv_type = -type + iv_subtype = -subtype ). + ENDLOOP. + ENDIF. + + ls_event-eventid = mi_html_viewer->c_id_sapevent. + ls_event-appl_event = abap_true. + APPEND ls_event TO lt_events. + + mi_html_viewer->set_registered_events( lt_events ). + SET HANDLER on_event FOR mi_html_viewer. + + ENDMETHOD. + METHOD zif_abapgit_gui_services~cache_asset. + + TYPES ty_hex TYPE x LENGTH 200. + TYPES ty_char TYPE c LENGTH 200. + + DATA: lt_xdata TYPE STANDARD TABLE OF ty_hex WITH DEFAULT KEY, + lv_size TYPE i, + lt_html TYPE STANDARD TABLE OF ty_char WITH DEFAULT KEY. + + ASSERT iv_text IS SUPPLIED OR iv_xdata IS SUPPLIED. + + IF iv_text IS SUPPLIED. " String input + zcl_abapgit_convert=>string_to_tab( + EXPORTING + iv_str = iv_text + IMPORTING + ev_size = lv_size + et_tab = lt_html ). + + mi_html_viewer->load_data( + EXPORTING + iv_type = iv_type + iv_subtype = iv_subtype + iv_size = lv_size + iv_url = iv_url + IMPORTING + ev_assigned_url = rv_url + CHANGING + ct_data_table = lt_html ). + ELSE. " Raw input + zcl_abapgit_convert=>xstring_to_bintab( + EXPORTING + iv_xstr = iv_xdata + IMPORTING + ev_size = lv_size + et_bintab = lt_xdata ). + + mi_html_viewer->load_data( + EXPORTING + iv_type = iv_type + iv_subtype = iv_subtype + iv_size = lv_size + iv_url = iv_url + IMPORTING + ev_assigned_url = rv_url + CHANGING + ct_data_table = lt_xdata ). + ENDIF. + + ASSERT sy-subrc = 0. " Image data error + + ENDMETHOD. + METHOD zif_abapgit_gui_services~get_current_page_name. + + DATA li_page_hoc TYPE REF TO zcl_abapgit_gui_page_hoc. + + IF mi_cur_page IS BOUND. + rv_page_name = cl_abap_classdescr=>describe_by_object_ref( mi_cur_page )->get_relative_name( ). + + " For HOC components return name of child component instead + IF rv_page_name = 'ZCL_ABAPGIT_GUI_PAGE_HOC'. + li_page_hoc ?= mi_cur_page. + IF li_page_hoc->get_child( ) IS BOUND. + rv_page_name = cl_abap_classdescr=>describe_by_object_ref( + li_page_hoc->get_child( ) )->get_relative_name( ). + ENDIF. + ENDIF. + ENDIF." ELSE - return is empty => initial page + + ENDMETHOD. + METHOD zif_abapgit_gui_services~get_hotkeys_ctl. + ri_hotkey_ctl = mi_hotkey_ctl. + ENDMETHOD. + METHOD zif_abapgit_gui_services~get_html_parts. + ro_parts = mo_html_parts. + ENDMETHOD. + METHOD zif_abapgit_gui_services~get_log. + + IF iv_create_new = abap_true OR mi_common_log IS NOT BOUND. + CREATE OBJECT mi_common_log TYPE zcl_abapgit_log. + ENDIF. + + ri_log = mi_common_log. + + ENDMETHOD. + METHOD zif_abapgit_gui_services~register_event_handler. + ASSERT ii_event_handler IS BOUND. + INSERT ii_event_handler INTO mt_event_handlers INDEX 1. + ENDMETHOD. + METHOD zif_abapgit_gui_services~register_page_asset. + + " Maybe forbid registering cacheable existing assets, maybe this is the right place (see also asset_man comments) + + mi_asset_man->register_asset( + iv_url = iv_url + iv_type = iv_type + iv_mime_name = iv_mime_name + iv_inline = iv_inline + " This registering will happen after initialization so all cacheable already cached + iv_cacheable = abap_false ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_page_template IMPLEMENTATION. + METHOD constructor. + super->constructor( ). + " ... + ENDMETHOD. + METHOD create. + + " TODO: replace with name of class (self) + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_template. + + CREATE OBJECT lo_component. + + ri_page = zcl_abapgit_gui_page_hoc=>create( lo_component ). + + ENDMETHOD. + METHOD zif_abapgit_gui_event_handler~on_event. + + CASE ii_event->mv_action. + " TODO: action handling, refresh is just an example + WHEN c_action-refresh. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN 'xyz'. + ASSERT 1 = 1. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + + DATA ls_hotkey_action LIKE LINE OF rt_hotkey_actions. + + ls_hotkey_action-ui_component = c_title. + + " TODO: define hotkeys + + ls_hotkey_action-description = 'Refresh'. + ls_hotkey_action-action = c_action-refresh. + ls_hotkey_action-hotkey = 'r'. + INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. + + ENDMETHOD. + METHOD zif_abapgit_gui_menu_provider~get_menu. + + " TODO: top level menu; use unique id + + ro_toolbar = zcl_abapgit_html_toolbar=>create( 'toolbar-template-id' )->add( + iv_txt = 'Refresh' + iv_act = c_action-refresh ). + + ENDMETHOD. + METHOD zif_abapgit_gui_page_title~get_page_title. + rv_title = c_title. " Fixed title + ENDMETHOD. + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + + ri_html = zcl_abapgit_html=>create( ). + + " TODO: do your rendering + + ri_html->div( + iv_class = 'template' + iv_content = 'Hello!' ). + + ENDMETHOD. + METHOD zif_abapgit_html_table~get_row_attrs. + " ... in case of table on the page, otherwise remove the interface at all + ENDMETHOD. + METHOD zif_abapgit_html_table~render_cell. + " ... in case of table on the page, otherwise remove the interface at all + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_syntax_xml IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + " Reset indicator for multi-line comments + CLEAR gv_comment. + + " Initialize instances of regular expressions + add_rule( iv_regex = c_regex-xml_tag + iv_token = c_token-xml_tag + iv_style = c_css-xml_tag + iv_submatch = 1 ). + + add_rule( iv_regex = c_regex-attr + iv_token = c_token-attr + iv_style = c_css-attr ). + + add_rule( iv_regex = c_regex-attr_val + iv_token = c_token-attr_val + iv_style = c_css-attr_val ). + + add_rule( iv_regex = c_regex-comment + iv_token = c_token-comment + iv_style = c_css-comment ). + + ENDMETHOD. + METHOD order_matches. + + DATA: + lv_match TYPE string, + lv_line_len TYPE i, + lv_cmmt_end TYPE i, + lv_index TYPE sy-tabix, + lv_prev_token TYPE c, + lv_state TYPE c VALUE 'O'. " O - for open tag; C - for closed tag; + + FIELD-SYMBOLS: + TYPE ty_match, + TYPE ty_match. + + SORT ct_matches BY offset. + + lv_line_len = strlen( iv_line ). + + " Check if this is part of multi-line comment and mark it accordingly + IF gv_comment = abap_true. + READ TABLE ct_matches WITH KEY token = c_token-comment TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + CLEAR ct_matches. + APPEND INITIAL LINE TO ct_matches ASSIGNING . + -token = c_token-comment. + -offset = 0. + -length = lv_line_len. + RETURN. + ENDIF. + ENDIF. + + LOOP AT ct_matches ASSIGNING . + lv_index = sy-tabix. + + lv_match = substring( val = iv_line + off = -offset + len = -length ). + + CASE -token. + WHEN c_token-xml_tag. + -text_tag = lv_match. + + " No other matches between two tags + IF -text_tag = '>' AND lv_prev_token = c_token-xml_tag. + lv_state = 'C'. + -length = -offset - -offset + -length. + DELETE ct_matches INDEX lv_index. + CONTINUE. + + " Adjust length and offset of closing tag + ELSEIF -text_tag = '>' AND lv_prev_token <> c_token-xml_tag. + lv_state = 'C'. + IF IS ASSIGNED. + -length = -offset - -offset - -length + -length. + -offset = -offset + -length. + ENDIF. + ELSE. + lv_state = 'O'. + ENDIF. + + WHEN c_token-comment. + IF lv_match = ''. + DELETE ct_matches WHERE offset < -offset. + -length = -offset + 3. + -offset = 0. + gv_comment = abap_false. + ELSE. + lv_cmmt_end = -offset + -length. + DELETE ct_matches WHERE offset > -offset AND offset <= lv_cmmt_end. + DELETE ct_matches WHERE offset = -offset AND token = c_token-xml_tag. + ENDIF. + + WHEN OTHERS. + IF lv_prev_token = c_token-xml_tag. + -length = -offset - -offset. " Extend length of the opening tag + ENDIF. + + IF lv_state = 'C'. " Delete all matches between tags + DELETE ct_matches INDEX lv_index. + CONTINUE. + ENDIF. + + ENDCASE. + + lv_prev_token = -token. + ASSIGN TO . + ENDLOOP. + + "if the last XML tag is not closed, extend it to the end of the tag + IF lv_prev_token = c_token-xml_tag + AND IS ASSIGNED + AND -length = 1 + AND -text_tag = '<'. + + FIND REGEX '<\s*[^\s]*' IN iv_line+-offset MATCH LENGTH -length. + IF sy-subrc <> 0. + -length = 1. + ENDIF. + + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_syntax_txt IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + " No rules for plain text files + + ENDMETHOD. + METHOD process_line. + + rv_line = apply_style( + iv_line = iv_line + iv_class = '' ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_SYNTAX_PO IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + add_rule( + iv_regex = c_regex-msgid + iv_token = c_token-msgid + iv_style = c_style-msgid ). + + add_rule( + iv_regex = c_regex-msgstr + iv_token = c_token-msgstr + iv_style = c_style-msgstr ). + + add_rule( + iv_regex = c_regex-comment + iv_token = c_token-comment + iv_style = c_style-comment ). + + " TODO maybe add rule to highlight empty msgstr with red + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_syntax_json IMPLEMENTATION. + METHOD constructor. + + super->constructor( ). + + " Initialize instances of regular expression + + add_rule( iv_regex = c_regex-keyword + iv_token = c_token-keyword + iv_style = c_css-keyword ). + + " Style for keys + add_rule( iv_regex = c_regex-text + iv_token = c_token-text + iv_style = c_css-text ). + + " Style for values + add_rule( iv_regex = '' + iv_token = c_token-values + iv_style = c_css-values ). + + " JSONC comments + add_rule( iv_regex = c_regex-comment + iv_token = c_token-comment + iv_style = c_css-comment ). + + ENDMETHOD. + METHOD order_matches. + + DATA: + lv_match TYPE string, + lv_count TYPE i, + lv_line_len TYPE i, + lv_prev_token TYPE c. + + FIELD-SYMBOLS: + TYPE ty_match, + TYPE ty_match. + + " Longest matches + SORT ct_matches BY offset length DESCENDING. + + lv_line_len = strlen( iv_line ). + + LOOP AT ct_matches ASSIGNING . + " Delete matches after open text match + IF lv_prev_token = c_token-text AND -token <> c_token-text. + CLEAR -token. + CONTINUE. + ENDIF. + + lv_match = substring( val = iv_line + off = -offset + len = -length ). + + IF -token = c_token-text. + -text_tag = lv_match. + IF lv_prev_token = c_token-text. + IF -text_tag = -text_tag. + -length = -offset + -length - -offset. + CLEAR lv_prev_token. + ENDIF. + CLEAR -token. + CONTINUE. + ENDIF. + ENDIF. + + lv_prev_token = -token. + ASSIGN TO . + ENDLOOP. + + DELETE ct_matches WHERE token IS INITIAL. + + " Switch style of second text match to values + LOOP AT ct_matches ASSIGNING WHERE token = c_token-text. + lv_count = lv_count + 1. + IF lv_count >= 2. + -token = c_token-values. + ENDIF. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_syntax_js IMPLEMENTATION. + METHOD class_constructor. + + init_keywords( ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + + " Reset indicator for multi-line comments + CLEAR gv_comment. + + " Initialize instances of regular expression + add_rule( iv_regex = c_regex-keyword + iv_token = c_token-keyword + iv_style = c_css-keyword ). + + add_rule( iv_regex = c_regex-comment + iv_token = c_token-comment + iv_style = c_css-comment ). + + add_rule( iv_regex = c_regex-text + iv_token = c_token-text + iv_style = c_css-text ). + + " Styles for keywords + add_rule( iv_regex = '' + iv_token = c_token-variables + iv_style = c_css-variables ). + + ENDMETHOD. + METHOD init_keywords. + + DATA: lv_keywords TYPE string. + + CLEAR gt_keywords. + + " 1) General keywords + lv_keywords = + 'alert|all|body|break|bytetostring|case|continue|default|delete|do|document|else|event|export|for|function|if|' && + 'import|in|innerhtml|isnan|item|mimetypes|navigator|new|onabort|onblur|onchange|onclick|ondblclick|ondragdrop|' && + 'onerror|onfocus|onkeydown|onkeypress|onkeyup|onload|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|' && + 'onmove|onreset|onselect|onsubmit|onunload|onresize|options|parsefloat|parseint|prototype|return|screen|switch|' && + 'unit|var|void|while|window|with|anchor|applet|area|button|checkbox|fileupload|form|frame|hidden|link|mimetype|' && + 'password|plugin|radio|reset|select|submit|text|textarea|abs|acos|alert|anchor|asin|atan|atan2|back|big|blink|' && + 'blur|bold|captureevents|ceil|charat|charcodeat|clearinterval|cleartimeout|click|close|concat|confirm|cos|' && + 'disableexternalcapture|enableexternalcapture|eval|exp|find|fixed|floor|focus|fontcolor|fontsize|forward|' && + 'fromcharcode|getdate|getday|getelementbyid|gethours|getminutes|getmonth|getoptionvalue|getoptionvaluecount|' && + 'getseconds|getselection|gettime|gettimezoneoffset|getyear|go|handleevent|home|indexof|italics|javaenabled|join|' && + 'lastindexof|link|load|log|match|max|min|moveabove|movebelow|moveby|moveto|movetoabsolute|open|parse|plugins|' && + 'pop|pow|preference|print|prompt|push|random|refresh|releaseevents|reload|replace|reset|resizeby|resizeto|' && + 'reverse|round|routeevent|scroll|scrollby|scrollto|search|select|setdate|sethours|setinterval|setminutes|' && + 'setmonth|setseconds|settime|settimeout|setyear|shift|sin|slice|small|sort|splice|split|sqrt|stop|strike|sub|' && + 'submit|substr|substring|sup|taintenabled|tan|togmtstring|tolocalestring|tolowercase|tostring|touppercase|' && + 'unshift|unwatch|utc|valueof|watch|write|writeln|e|ln10|ln2|log10e|log2e|max_value|min_value|negative_infinity|' && + 'nan|pi|positive_infinity|url|above|action|alinkcolor|anchors|appcodename|appname|appversion|applets|arguments|' && + 'arity|availheight|availwidth|background|backgroundcolor|below|bgcolor|border|bottom|caller|cancelbubble|' && + 'checked|clientheight|clientwidth|clientx|clienty|clip|closed|color|colordepth|complete|constructor|cookie|' && + 'count|current|defaultchecked|defaultselected|defaultstatus|defaultvalue|description|display|document|domain|' && + 'elements|embeds|enabledplugin|encoding|false|fgcolor|filename|form|formname|forms|frames|hash|height|history|' && + 'host|hostname|href|hspace|images|innerheight|innerwidth|language|lastmodified|layers|left|length|linkcolor|' && + 'links|location|locationbar|lowsrc|menubar|method|mimetypes|name|next|null|offsetheight|offsetleft|offsetparent|' && + 'offsetwidth|opener|outerheight|outerwidth|pagex|pagexoffset|pagey|pageyoffset|parent|parentlayer|pathname|' && + 'personalbar|pixeldepth|platform|plugins|port|poswidth|previous|protocol|prototype|referrer|right|scrolltop|' && + 'scrollbars|search|selected|selectedindex|self|siblingabove|siblingbelow|src|srcelement|status|statusbar|style|' && + 'suffixes|tags|target|text|this|title|toolbar|top|true|type|useragent|value|visibility|vlinkcolor|vspace|width|' && + 'window|zindex'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-keyword ). + + " 2) Variable types + lv_keywords = + 'array|boolean|date|function|image|layer|math|number|object|option|regexp|string'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-variables ). + + ENDMETHOD. + METHOD insert_keywords. + + DATA: lt_keywords TYPE STANDARD TABLE OF string, + ls_keyword TYPE ty_keyword. + + FIELD-SYMBOLS: TYPE any. + + SPLIT iv_keywords AT '|' INTO TABLE lt_keywords. + + LOOP AT lt_keywords ASSIGNING . + CLEAR ls_keyword. + ls_keyword-keyword = . + ls_keyword-token = iv_token. + INSERT ls_keyword INTO TABLE gt_keywords. + ENDLOOP. + + ENDMETHOD. + METHOD is_keyword. + + DATA lv_str TYPE string. + + lv_str = to_lower( iv_chunk ). + READ TABLE gt_keywords WITH TABLE KEY keyword = lv_str TRANSPORTING NO FIELDS. + rv_yes = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD order_matches. + + DATA: + lv_match TYPE string, + lv_line_len TYPE i, + lv_cmmt_end TYPE i, + lv_prev_end TYPE i, + lv_prev_token TYPE c. + + FIELD-SYMBOLS: + TYPE ty_match, + TYPE ty_match, + TYPE ty_keyword. + + " Longest matches + SORT ct_matches BY offset length DESCENDING. + + lv_line_len = strlen( iv_line ). + + " Check if this is part of multi-line comment and mark it accordingly + IF gv_comment = abap_true. + READ TABLE ct_matches WITH KEY token = c_token-comment TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + CLEAR ct_matches. + APPEND INITIAL LINE TO ct_matches ASSIGNING . + -token = c_token-comment. + -offset = 0. + -length = lv_line_len. + RETURN. + ENDIF. + ENDIF. + + LOOP AT ct_matches ASSIGNING . + " Delete matches after open text match + IF lv_prev_token = c_token-text AND -token <> c_token-text. + CLEAR -token. + CONTINUE. + ENDIF. + + lv_match = substring( val = iv_line + off = -offset + len = -length ). + + CASE -token. + WHEN c_token-keyword. + " Skip keyword that's part of previous (longer) keyword + IF -offset < lv_prev_end. + CLEAR -token. + CONTINUE. + ENDIF. + + " Map generic keyword to specific token + lv_match = to_lower( lv_match ). + READ TABLE gt_keywords ASSIGNING WITH TABLE KEY keyword = lv_match. + IF sy-subrc = 0. + -token = -token. + ENDIF. + + WHEN c_token-comment. + IF lv_match = '/*'. + DELETE ct_matches WHERE offset > -offset. + -length = lv_line_len - -offset. + gv_comment = abap_true. + ELSEIF lv_match = '//'. + DELETE ct_matches WHERE offset > -offset. + -length = lv_line_len - -offset. + ELSEIF lv_match = '*/'. + DELETE ct_matches WHERE offset < -offset. + -length = -offset + 2. + -offset = 0. + gv_comment = abap_false. + ELSE. + lv_cmmt_end = -offset + -length. + DELETE ct_matches WHERE offset > -offset AND offset <= lv_cmmt_end. + ENDIF. + + WHEN c_token-text. + -text_tag = lv_match. + IF lv_prev_token = c_token-text. + IF -text_tag = -text_tag. + -length = -offset + -length - -offset. + CLEAR lv_prev_token. + ENDIF. + CLEAR -token. + CONTINUE. + ENDIF. + + ENDCASE. + + lv_prev_token = -token. + lv_prev_end = -offset + -length. + ASSIGN TO . + ENDLOOP. + + DELETE ct_matches WHERE token IS INITIAL. + + ENDMETHOD. + METHOD parse_line. "REDEFINITION + + DATA lv_index TYPE i. + + FIELD-SYMBOLS LIKE LINE OF rt_matches. + + rt_matches = super->parse_line( iv_line ). + + " Remove non-keywords + LOOP AT rt_matches ASSIGNING WHERE token = c_token-keyword. + lv_index = sy-tabix. + IF abap_false = is_keyword( substring( val = iv_line + off = -offset + len = -length ) ). + CLEAR -token. + ENDIF. + ENDLOOP. + + DELETE rt_matches WHERE token IS INITIAL. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_syntax_highlighter IMPLEMENTATION. + METHOD add_rule. + + DATA ls_rule LIKE LINE OF mt_rules. + + IF NOT iv_regex IS INITIAL. + CREATE OBJECT ls_rule-regex + EXPORTING + pattern = iv_regex + ignore_case = abap_true. + ENDIF. + + ls_rule-token = iv_token. + ls_rule-style = iv_style. + ls_rule-relevant_submatch = iv_submatch. + APPEND ls_rule TO mt_rules. + + ENDMETHOD. + METHOD apply_style. + + DATA lv_escaped TYPE string. + + lv_escaped = escape( val = iv_line + format = cl_abap_format=>e_html_text ). + + lv_escaped = show_hidden_chars( lv_escaped ). + + IF iv_class IS NOT INITIAL. + rv_line = |{ lv_escaped }|. + ELSE. + rv_line = lv_escaped. + ENDIF. + + ENDMETHOD. + METHOD extend_matches. + + DATA: lv_line_len TYPE i, + lv_last_pos TYPE i VALUE 0, + lv_length TYPE i, + ls_match TYPE ty_match. + + FIELD-SYMBOLS TYPE ty_match. + + lv_line_len = strlen( iv_line ). + + SORT ct_matches BY offset. + + " Add entries referring to parts of text that should not be formatted + LOOP AT ct_matches ASSIGNING . + IF -offset > lv_last_pos. + lv_length = -offset - lv_last_pos. + ls_match-token = c_token_none. + ls_match-offset = lv_last_pos. + ls_match-length = lv_length. + INSERT ls_match INTO ct_matches INDEX sy-tabix. + ENDIF. + lv_last_pos = -offset + -length. + ENDLOOP. + + " Add remainder of the string + IF lv_line_len > lv_last_pos. + lv_length = lv_line_len - lv_last_pos. + ls_match-token = c_token_none. + ls_match-offset = lv_last_pos. + ls_match-length = lv_length. + APPEND ls_match TO ct_matches. + ENDIF. + + ENDMETHOD. + METHOD format_line. + + DATA: + lv_chunk TYPE string, + ls_rule LIKE LINE OF mt_rules. + + FIELD-SYMBOLS TYPE ty_match. + + LOOP AT it_matches ASSIGNING . + lv_chunk = substring( val = iv_line + off = -offset + len = -length ). + + CLEAR ls_rule. " Failed read equals no style + READ TABLE mt_rules INTO ls_rule WITH KEY token = -token. + + lv_chunk = apply_style( iv_line = lv_chunk + iv_class = ls_rule-style ). + + rv_line = rv_line && lv_chunk. + ENDLOOP. + + ENDMETHOD. + METHOD is_whitespace. + + DATA: lv_whitespace TYPE string. + + "/^\s+$/ + lv_whitespace = ` ` && cl_abap_char_utilities=>horizontal_tab && cl_abap_char_utilities=>cr_lf. + + rv_result = boolc( iv_string CO lv_whitespace ). + + ENDMETHOD. + METHOD order_matches. + ENDMETHOD. + METHOD parse_line. + + DATA: + lo_regex TYPE REF TO cl_abap_regex, + lo_matcher TYPE REF TO cl_abap_matcher, + lt_result TYPE match_result_tab, + ls_match TYPE ty_match. + + FIELD-SYMBOLS: + LIKE LINE OF mt_rules, + TYPE match_result, + LIKE LINE OF -submatches. + " Process syntax-dependent regex table and find all matches + LOOP AT mt_rules ASSIGNING WHERE regex IS BOUND. + lo_regex = -regex. + lo_matcher = lo_regex->create_matcher( text = iv_line ). + lt_result = lo_matcher->find_all( ). + + " Save matches into custom table with predefined tokens + LOOP AT lt_result ASSIGNING . + CLEAR: ls_match. + IF -relevant_submatch = 0. + ls_match-token = -token. + ls_match-offset = -offset. + ls_match-length = -length. + APPEND ls_match TO rt_matches. + ELSE. + READ TABLE -submatches ASSIGNING INDEX -relevant_submatch. + "submatch might be empty if only discarded parts matched + IF sy-subrc = 0 AND -offset >= 0 AND -length > 0. + ls_match-token = -token. + ls_match-offset = -offset. + ls_match-length = -length. + APPEND ls_match TO rt_matches. + ENDIF. + ENDIF. + ENDLOOP. + ENDLOOP. + + ENDMETHOD. + METHOD process_line. + + DATA: lt_matches TYPE ty_match_tt. + + IF iv_line IS INITIAL OR is_whitespace( iv_line ) = abap_true. + rv_line = show_hidden_chars( iv_line ). + RETURN. + ENDIF. + + lt_matches = parse_line( iv_line ). + + order_matches( EXPORTING iv_line = iv_line + CHANGING ct_matches = lt_matches ). + + extend_matches( EXPORTING iv_line = iv_line + CHANGING ct_matches = lt_matches ). + + rv_line = format_line( iv_line = iv_line + it_matches = lt_matches ). + + ENDMETHOD. + METHOD set_hidden_chars. + mv_hidden_chars = iv_hidden_chars. + ENDMETHOD. + METHOD show_hidden_chars. + + DATA lv_bom TYPE x LENGTH 3. + + rv_line = iv_line. + + IF mv_hidden_chars = abap_true. + " The order of these replacements matters to properly show CR, LF, and CRLF + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>horizontal_tab IN rv_line WITH ' → '. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN rv_line WITH '¶'. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN rv_line WITH '↵'. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf(1) IN rv_line WITH '¶'. + REPLACE ALL OCCURRENCES OF ` ` IN rv_line WITH '·'. + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>form_feed IN rv_line + WITH ''. + + IF strlen( rv_line ) BETWEEN 1 AND 2. + TRY. + lv_bom = zcl_abapgit_convert=>string_to_xstring( rv_line ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + IF lv_bom(2) = cl_abap_char_utilities=>byte_order_mark_big. + rv_line = ''. " UTF-16 big-endian (FE FF) + ENDIF. + IF lv_bom(2) = cl_abap_char_utilities=>byte_order_mark_little. + rv_line = ''. " UTF-16 little-endian (FF FE) + ENDIF. + IF lv_bom(3) = cl_abap_char_utilities=>byte_order_mark_utf8. + rv_line = '¤'. " UTF-8 (EF BB BF) + ENDIF. + ENDIF. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_SYNTAX_FACTORY IMPLEMENTATION. + METHOD create. + + " Create instance of highlighter dynamically dependent on syntax type + IF iv_filename CP '*.abap'. + CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_abap. + ELSEIF iv_filename CP '*.xml' OR iv_filename CP '*.html' OR iv_filename CP '*.xdp'. + CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_xml. + ELSEIF iv_filename CP '*.css'. + CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_css. + ELSEIF iv_filename CP '*.js'. + CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_js. + ELSEIF iv_filename CP '*.json' OR iv_filename CP '*.jsonc'. + CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_json. + ELSEIF iv_filename CP '*.txt' OR iv_filename CP '*.ini' OR iv_filename CP '*.text'. + CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_txt. + ELSEIF iv_filename CP '*.po'. + CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_po. + ELSE. + CLEAR ro_instance. + ENDIF. + + IF ro_instance IS BOUND. + ro_instance->set_hidden_chars( iv_hidden_chars ). + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_syntax_css IMPLEMENTATION. + METHOD class_constructor. + + init_keywords( ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + + " Reset indicator for multi-line comments + CLEAR gv_comment. + + " Initialize instances of regular expression + add_rule( iv_regex = c_regex-keyword + iv_token = c_token-keyword + iv_style = c_css-keyword ). + + add_rule( iv_regex = c_regex-comment + iv_token = c_token-comment + iv_style = c_css-comment ). + + add_rule( iv_regex = c_regex-text + iv_token = c_token-text + iv_style = c_css-text ). + + add_rule( iv_regex = c_regex-selectors + iv_token = c_token-selectors + iv_style = c_css-selectors ). + + add_rule( iv_regex = c_regex-units + iv_token = c_token-units + iv_style = c_css-units ). + + " Styles for keywords + add_rule( iv_regex = '' + iv_token = c_token-html + iv_style = c_css-html ). + + add_rule( iv_regex = '' + iv_token = c_token-properties + iv_style = c_css-properties ). + + add_rule( iv_regex = '' + iv_token = c_token-values + iv_style = c_css-values ). + + add_rule( iv_regex = '' + iv_token = c_token-functions + iv_style = c_css-functions ). + + add_rule( iv_regex = '' + iv_token = c_token-colors + iv_style = c_css-colors ). + + add_rule( iv_regex = '' + iv_token = c_token-extensions + iv_style = c_css-extensions ). + + add_rule( iv_regex = '' + iv_token = c_token-at_rules + iv_style = c_css-at_rules ). + + ENDMETHOD. + METHOD init_keywords. + + DATA: lv_keywords TYPE string. + + CLEAR gt_keywords. + + " 1) CSS Properties + lv_keywords = + 'align-content|align-items|align-self|animation|animation-delay|animation-direction|animation-duration|' && + 'animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|' && + 'backface-visibility|background|background-attachment|background-blend-mode|background-clip|background-color|' && + 'background-image|background-origin|background-position|background-repeat|background-size|border|' && + 'border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|' && + 'border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|' && + 'border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|' && + 'border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|' && + 'border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|' && + 'border-top-style|border-top-width|border-width|box-decoration-break|box-shadow|box-sizing|caption-side|' && + 'caret-color|clear|clip|color|column-count|column-fill|column-gap|column-rule|column-rule-color|' && + 'column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|' && + 'counter-reset|cursor|direction|display|empty-cells|filter|flex|flex-basis|flex-direction|flex-flow|' && + 'flex-grow|flex-shrink|flex-wrap|float|font|font-family|font-kerning|font-size|font-size-adjust|' && + 'font-stretch|font-style|font-variant|font-weight|grid|grid-area|grid-auto-columns|grid-auto-flow|' && + 'grid-auto-rows|grid-column|grid-column-end|grid-column-gap|grid-column-start|grid-gap|grid-row|' && + 'grid-row-end|grid-row-gap|grid-row-start|grid-template|grid-template-areas|grid-template-columns|' && + 'grid-template-rows|hanging-punctuation|height|hyphens|isolation|justify-content|' && + 'letter-spacing|line-height|list-style|list-style-image|list-style-position|list-style-type|margin|' && + 'margin-bottom|margin-left|margin-right|margin-top|max-height|max-width|media|min-height|min-width|' && + 'mix-blend-mode|object-fit|object-position|opacity|order|outline|outline-color|outline-offset|' && + 'outline-style|outline-width|overflow|overflow-x|overflow-y|padding|padding-bottom|padding-left|' && + 'padding-right|padding-top|page-break-after|page-break-before|page-break-inside|perspective|' && + 'perspective-origin|pointer-events|position|quotes|resize|scroll-behavior|tab-size|table-layout|' && + 'text-align|text-align-last|text-decoration|text-decoration-color|text-decoration-line|' && + 'text-decoration-style|text-indent|text-justify|text-overflow|text-rendering|text-shadow|text-transform|' && + 'transform|transform-origin|transform-style|transition|transition-delay|transition-duration|' && + 'transition-property|transition-timing-function|unicode-bidi|user-select|vertical-align|visibility|' && + 'white-space|width|word-break|word-spacing|word-wrap|writing-mode|z-index'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-properties ). + + " 2) CSS Values + lv_keywords = + 'absolute|all|auto|block|bold|border-box|both|bottom|center|counter|cover|dashed|fixed|hidden|important|' && + 'inherit|initial|inline-block|italic|left|max-content|middle|min-content|no-repeat|none|normal|pointer|' && + 'relative|rem|right|solid|table-cell|text|top|transparent|underline|url'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-values ). + + " 3) CSS Selectors + lv_keywords = + ':active|::after|::before|:checked|:disabled|:empty|:enabled|:first-child|::first-letter|::first-line|' && + ':first-of-type|:focus|:hover|:lang|:last-child|:last-of-type|:link|:not|:nth-child|:nth-last-child|' && + ':nth-last-of-type|:nth-of-type|:only-child|:only-of-type|:root|:target|:visited'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-selectors ). + + " 4) CSS Functions + lv_keywords = + 'attr|calc|cubic-bezier|hsl|hsla|linear-gradient|radial-gradient|repeating-linear-gradient|' && + 'repeating-radial-gradient|rgb|rgba|rotate|scale|translateX|translateY|var'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-functions ). + + " 5) CSS Colors + lv_keywords = + '#|aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|' && + 'burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|' && + 'darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|' && + 'darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|' && + 'deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|' && + 'ghostwhite|gold|goldenrod|gray|green|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|' && + 'lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|' && + 'lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|' && + 'lightslategrey|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|' && + 'mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|' && + 'mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|' && + 'orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|' && + 'peru|pink|plum|powderblue|purple|rebeccapurple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|' && + 'seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|' && + 'tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-colors ). + + " 6) CSS Extensions + lv_keywords = + 'moz|moz-binding|moz-border-bottom-colors|moz-border-left-colors|moz-border-right-colors|' && + 'moz-border-top-colors|moz-box-align|moz-box-direction|moz-box-flex|moz-box-ordinal-group|' && + 'moz-box-orient|moz-box-pack|moz-box-shadow|moz-context-properties|moz-float-edge|' && + 'moz-force-broken-image-icon|moz-image-region|moz-orient|moz-osx-font-smoothing|' && + 'moz-outline-radius|moz-outline-radius-bottomleft|moz-outline-radius-bottomright|' && + 'moz-outline-radius-topleft|moz-outline-radius-topright|moz-stack-sizing|moz-system-metric|' && + 'moz-transform|moz-transform-origin|moz-transition|moz-transition-delay|moz-user-focus|' && + 'moz-user-input|moz-user-modify|moz-window-dragging|moz-window-shadow|ms|ms-accelerator|' && + 'ms-block-progression|ms-content-zoom-chaining|ms-content-zoom-limit|' && + 'ms-content-zoom-limit-max|ms-content-zoom-limit-min|ms-content-zoom-snap|' && + 'ms-content-zoom-snap-points|ms-content-zoom-snap-type|ms-content-zooming|ms-filter|' && + 'ms-flow-from|ms-flow-into|ms-high-contrast-adjust|ms-hyphenate-limit-chars|' && + 'ms-hyphenate-limit-lines|ms-hyphenate-limit-zone|ms-ime-align|ms-overflow-style|' && + 'ms-scroll-chaining|ms-scroll-limit|ms-scroll-limit-x-max|ms-scroll-limit-x-min|' && + 'ms-scroll-limit-y-max|ms-scroll-limit-y-min|ms-scroll-rails|ms-scroll-snap-points-x|' && + 'ms-scroll-snap-points-y|ms-scroll-snap-x|ms-scroll-snap-y|ms-scroll-translation|' && + 'ms-scrollbar-3dlight-color|ms-scrollbar-arrow-color|ms-scrollbar-base-color|' && + 'ms-scrollbar-darkshadow-color|ms-scrollbar-face-color|ms-scrollbar-highlight-color|' && + 'ms-scrollbar-shadow-color|ms-scrollbar-track-color|ms-transform|ms-text-autospace|' && + 'ms-touch-select|ms-wrap-flow|ms-wrap-margin|ms-wrap-through|o|o-transform|webkit|' && + 'webkit-animation-trigger|webkit-app-region|webkit-appearance|webkit-aspect-ratio|' && + 'webkit-backdrop-filter|webkit-background-composite|webkit-border-after|' && + 'webkit-border-after-color|webkit-border-after-style|webkit-border-after-width|' && + 'webkit-border-before|webkit-border-before-color|webkit-border-before-style|' && + 'webkit-border-before-width|webkit-border-end|webkit-border-end-color|' && + 'webkit-border-end-style|webkit-border-end-width|webkit-border-fit|' && + 'webkit-border-horizontal-spacing|webkit-border-radius|webkit-border-start|' && + 'webkit-border-start-color|webkit-border-start-style|webkit-border-start-width|' && + 'webkit-border-vertical-spacing|webkit-box-align|webkit-box-direction|webkit-box-flex|' && + 'webkit-box-flex-group|webkit-box-lines|webkit-box-ordinal-group|webkit-box-orient|' && + 'webkit-box-pack|webkit-box-reflect|webkit-box-shadow|webkit-column-axis|' && + 'webkit-column-break-after|webkit-column-break-before|webkit-column-break-inside|' && + 'webkit-column-progression|webkit-cursor-visibility|webkit-dashboard-region|' && + 'webkit-font-size-delta|webkit-font-smoothing|webkit-highlight|webkit-hyphenate-character|' && + 'webkit-hyphenate-limit-after|webkit-hyphenate-limit-before|webkit-hyphenate-limit-lines|' && + 'webkit-initial-letter|webkit-line-align|webkit-line-box-contain|webkit-line-clamp|' && + 'webkit-line-grid|webkit-line-snap|webkit-locale|webkit-logical-height|' && + 'webkit-logical-width|webkit-margin-after|webkit-margin-after-collapse|' && + 'webkit-margin-before|webkit-margin-before-collapse|webkit-margin-bottom-collapse|' && + 'webkit-margin-collapse|webkit-margin-end|webkit-margin-start|webkit-margin-top-collapse|' && + 'webkit-marquee|webkit-marquee-direction|webkit-marquee-increment|' && + 'webkit-marquee-repetition|webkit-marquee-speed|webkit-marquee-style|webkit-mask-box-image|' && + 'webkit-mask-box-image-outset|webkit-mask-box-image-repeat|webkit-mask-box-image-slice|' && + 'webkit-mask-box-image-source|webkit-mask-box-image-width|webkit-mask-repeat-x|' && + 'webkit-mask-repeat-y|webkit-mask-source-type|webkit-max-logical-height|' && + 'webkit-max-logical-width|webkit-min-logical-height|webkit-min-logical-width|' && + 'webkit-nbsp-mode|webkit-padding-after|webkit-padding-before|webkit-padding-end|' && + 'webkit-padding-start|webkit-perspective-origin-x|webkit-perspective-origin-y|' && + 'webkit-print-color-adjust|webkit-rtl-ordering|webkit-svg-shadow|' && + 'webkit-tap-highlight-color|webkit-text-combine|webkit-text-decoration-skip|' && + 'webkit-text-decorations-in-effect|webkit-text-fill-color|webkit-text-security|' && + 'webkit-text-stroke|webkit-text-stroke-color|webkit-text-stroke-width|webkit-text-zoom|' && + 'webkit-transform|webkit-transform-origin|webkit-transform-origin-x|' && + 'webkit-transform-origin-y|webkit-transform-origin-z|webkit-transition|' && + 'webkit-transition-delay|webkit-user-drag|webkit-user-modify|overflow-clip-box|' && + 'overflow-clip-box-block|overflow-clip-box-inline|zoom'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-extensions ). + + " 6) CSS At-Rules + lv_keywords = + '@|charset|counter-style|font-face|import|keyframes'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-at_rules ). + + " 7) HTML tag + lv_keywords = + 'doctyype|a|abbr|acronym|address|applet|area|b|base|basefont|bdo|bgsound|big|blink|blockquote|' && + 'body|br|button|caption|center|cite|code|col|colgroup|dd|del|dfn|dir|div|dl|dt|em|embed|fieldset|' && + 'font|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|hr|html|i|iframe|ilayer|img|input|ins|isindex|' && + 'kbd|keygen|label|layer|legend|li|link|listing|map|menu|meta|multicol|nobr|noembed|noframes|' && + 'nolayer|noscript|object|ol|optgroup|option|p|param|plaintext|pre|q|s|samp|script|select|server|' && + 'small|sound|spacer|span|strike|strong|style|sub|sup|tbody|textarea|title|tt|u|ul|var|wbr|xmp|' && + 'xsl|xml|accesskey|action|align|alink|alt|background|balance|behavior|bgcolor|bgproperties|' && + 'border|bordercolor|bordercolordark|bordercolorlight|bottommargin|checked|class|classid|clear|' && + 'code|codebase|codetype|color|cols|colspan|compact|content|controls|coords|data|datafld|' && + 'dataformatas|datasrc|direction|disabled|dynsrc|enctype|event|face|for|frame|frameborder|' && + 'framespacing|height|hidden|href|hspace|http-equiv|id|ismap|lang|language|leftmargin|link|loop|' && + 'lowsrc|marginheight|marginwidth|maxlength|mayscript|method|methods|multiple|name|nohref|' && + 'noresize|noshade|nowrap|palette|pluginspage|public|readonly|rel|rev|rightmargin|rows|rowspan|' && + 'rules|scroll|scrollamount|scrolldelay|scrolling|selected|shape|size|span|src|start|style|' && + 'tabindex|target|text|title|topmargin|truespeed|type|url|urn|usemap|valign|value|vlink|volume|' && + 'vrml|vspace|width|wrap|apply-templates|attribute|choose|comment|define-template-set|' && + 'entity-ref|eval|expr|for-each|if|match|no-entities|node-name|order-by|otherwise|select|' && + 'stylesheet|template|test|value-of|version|when|xmlns|xsl|cellpadding|cellspacing|table|td|' && + 'tfoot|th|thead|tr'. + insert_keywords( iv_keywords = lv_keywords + iv_token = c_token-html ). + + ENDMETHOD. + METHOD insert_keywords. + + DATA: lt_keywords TYPE STANDARD TABLE OF string, + ls_keyword TYPE ty_keyword. + + FIELD-SYMBOLS: TYPE any. + + SPLIT iv_keywords AT '|' INTO TABLE lt_keywords. + + LOOP AT lt_keywords ASSIGNING . + CLEAR ls_keyword. + ls_keyword-keyword = . + ls_keyword-token = iv_token. + INSERT ls_keyword INTO TABLE gt_keywords. + ENDLOOP. + + ENDMETHOD. + METHOD is_keyword. + + DATA lv_str TYPE string. + + lv_str = to_lower( iv_chunk ). + READ TABLE gt_keywords WITH TABLE KEY keyword = lv_str TRANSPORTING NO FIELDS. + rv_yes = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD order_matches. + + DATA: + lv_match TYPE string, + lv_line_len TYPE i, + lv_cmmt_end TYPE i, + lv_prev_end TYPE i, + lv_prev_token TYPE c. + + FIELD-SYMBOLS: + TYPE ty_match, + TYPE ty_match, + TYPE ty_keyword. + + " Longest matches + SORT ct_matches BY offset length DESCENDING. + + lv_line_len = strlen( iv_line ). + + " Check if this is part of multi-line comment and mark it accordingly + IF gv_comment = abap_true. + READ TABLE ct_matches WITH KEY token = c_token-comment TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + CLEAR ct_matches. + APPEND INITIAL LINE TO ct_matches ASSIGNING . + -token = c_token-comment. + -offset = 0. + -length = lv_line_len. + RETURN. + ENDIF. + ENDIF. + + LOOP AT ct_matches ASSIGNING . + " Delete matches after open text match + IF lv_prev_token = c_token-text AND -token <> c_token-text. + CLEAR -token. + CONTINUE. + ENDIF. + + lv_match = substring( val = iv_line + off = -offset + len = -length ). + + CASE -token. + WHEN c_token-keyword. + " Skip keyword that's part of previous (longer) keyword + IF -offset < lv_prev_end. + CLEAR -token. + CONTINUE. + ENDIF. + + " Map generic keyword to specific CSS token + lv_match = to_lower( lv_match ). + READ TABLE gt_keywords ASSIGNING WITH TABLE KEY keyword = lv_match. + IF sy-subrc = 0. + -token = -token. + ENDIF. + + WHEN c_token-comment. + IF lv_match = '/*'. + DELETE ct_matches WHERE offset > -offset. + -length = lv_line_len - -offset. + gv_comment = abap_true. + ELSEIF lv_match = '*/'. + DELETE ct_matches WHERE offset < -offset. + -length = -offset + 2. + -offset = 0. + gv_comment = abap_false. + ELSE. + lv_cmmt_end = -offset + -length. + DELETE ct_matches WHERE offset > -offset AND offset <= lv_cmmt_end. + ENDIF. + + WHEN c_token-text. + -text_tag = lv_match. + IF lv_prev_token = c_token-text. + IF -text_tag = -text_tag. + -length = -offset + -length - -offset. + CLEAR lv_prev_token. + ENDIF. + CLEAR -token. + CONTINUE. + ENDIF. + + ENDCASE. + + lv_prev_token = -token. + lv_prev_end = -offset + -length. + ASSIGN TO . + ENDLOOP. + + DELETE ct_matches WHERE token IS INITIAL. + + ENDMETHOD. + METHOD parse_line. "REDEFINITION + + DATA lv_index TYPE i. + + FIELD-SYMBOLS LIKE LINE OF rt_matches. + + rt_matches = super->parse_line( iv_line ). + + " Remove non-keywords + LOOP AT rt_matches ASSIGNING WHERE token = c_token-keyword. + lv_index = sy-tabix. + IF abap_false = is_keyword( substring( val = iv_line + off = -offset + len = -length ) ). + CLEAR -token. + ENDIF. + ENDLOOP. + + DELETE rt_matches WHERE token IS INITIAL. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_SYNTAX_ABAP IMPLEMENTATION. + METHOD class_constructor. + + init_keywords( ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( ). + + " Initialize instances of regular expression + add_rule( iv_regex = c_regex-keyword + iv_token = c_token-keyword + iv_style = c_css-keyword ). + + add_rule( iv_regex = c_regex-comment + iv_token = c_token-comment + iv_style = c_css-comment ). + + add_rule( iv_regex = c_regex-text + iv_token = c_token-text + iv_style = c_css-text ). + + ENDMETHOD. + METHOD init_keywords. + + DATA: lv_keywords TYPE string, + lt_keywords TYPE STANDARD TABLE OF string. + + lv_keywords = + '&&|?TO|ABAP-SOURCE|ABBREVIATED|ABS|ABSTRACT|ACCEPT|ACCEPTING' && + '|ACCORDING|ACOS|ACTIVATION|ACTUAL|ADD|ADD-CORRESPONDING|ADJACENT|AFTER|ALIAS' && + '|ALIASES|ALIGN|ALL|ALLOCATE|ALPHA|ANALYSIS|ANALYZER|AND|ANY|APPEND|APPENDAGE' && + '|APPENDING|APPLICATION|ARCHIVE|AREA|ARITHMETIC|AS|ASCENDING|ASIN|ASPECT|ASSERT' && + '|ASSIGN|ASSIGNED|ASSIGNING|ASSOCIATION|ASYNCHRONOUS|AT|ATAN|ATTRIBUTES|AUTHORITY' && + '|AUTHORITY-CHECK|AVG|BACK|BACKGROUND|BACKUP|BACKWARD|BADI|BASE|BEFORE|BEGIN' && + '|BETWEEN|BIG|BINARY|BIT|BIT-AND|BIT-NOT|BIT-OR|BIT-XOR|BLACK|BLANK' && + '|BLANKS|BLOB|BLOCK|BLOCKS|BLUE|BOUND|BOUNDARIES|BOUNDS|BOXED|BREAK-POINT|BT' && + '|BUFFER|BY|BYPASSING|BYTE|BYTE-CA|BYTE-CN|BYTE-CO|BYTE-CS|BYTE-NA|BYTE-NS' && + '|BYTE-ORDER|C|CA|CALL|CALLING|CASE|CAST|CASTING|CATCH|CEIL|CENTER|CENTERED' && + '|CHAIN|CHAIN-INPUT|CHAIN-REQUEST|CHANGE|CHANGING|CHANNELS|CHARACTER|CHARLEN' && + '|CHAR-TO-HEX|CHECK|CHECKBOX|CI_|CIRCULAR|CLASS|CLASS-CODING|CLASS-DATA' && + '|CLASS-EVENTS|CLASS-METHODS|CLASS-POOL|CLEANUP|CLEAR|CLIENT|CLOB|CLOCK|CLOSE' && + '|CN|CO|COALESCE|CODE|CODING|COL_BACKGROUND|COL_GROUP|COL_HEADING|COL_KEY' && + '|COL_NEGATIVE|COL_NORMAL|COL_POSITIVE|COL_TOTAL|COLLECT|COLOR|COLUMN|COLUMNS' && + '|COMMENT|COMMENTS|COMMIT|COMMON|COMMUNICATION|COMPARING|COMPONENT|COMPONENTS' && + '|COMPRESSION|COMPUTE|CONCAT|CONCATENATE|COND|CONDENSE|CONDITION|CONNECT' && + '|CONNECTION|CONSTANTS|CONTEXT|CONTEXTS|CONTINUE|CONTROL|CONTROLS|CONV|CONVERSION' && + '|CONVERT|COPIES|COPY|CORRESPONDING|COS|COSH|COUNT|COUNTRY|COVER|CP|CPI|CREATE' && + '|CREATING|CRITICAL|CS|CURRENCY|CURRENCY_CONVERSION|CURRENT|CURSOR|CURSOR-SELECTION' && + '|CUSTOMER|CUSTOMER-FUNCTION|DANGEROUS|DATA|DATABASE|DATAINFO|DATASET|DATE' && + '|DAYLIGHT|DBMAXLEN|DD/MM/YY|DD/MM/YYYY|DDMMYY|DEALLOCATE|DECIMAL_SHIFT|DECIMALS' && + '|DECLARATIONS|DEEP|DEFAULT|DEFERRED|DEFINE|DEFINING|DEFINITION|DELETE|DELETING' && + '|DEMAND|DEPARTMENT|DESCENDING|DESCRIBE|DESTINATION|DETAIL|DIALOG|DIRECTORY' && + '|DISCONNECT|DISPLAY|DISPLAY-MODE|DISTANCE|DISTINCT|DIV|DIVIDE|DIVIDE-CORRESPONDING' && + '|DIVISION|DO|DUMMY|DUPLICATE|DUPLICATES|DURATION|DURING|DYNAMIC|DYNPRO' && + '|EDIT|EDITOR-CALL|ELSE|ELSEIF|EMPTY|ENABLED|ENABLING|ENCODING|END|ENDAT|ENDCASE' && + '|ENDCATCH|ENDCHAIN|ENDCLASS|ENDDO|ENDENHANCEMENT|END-ENHANCEMENT-SECTION' && + '|ENDEXEC|ENDFORM|ENDFUNCTION|ENDIAN|ENDIF|ENDING|ENDINTERFACE' && + '|END-LINES|ENDLOOP|ENDMETHOD|ENDMODULE|END-OF-DEFINITION|END-OF-FILE' && + '|END-OF-PAGE|END-OF-SELECTION|ENDON|ENDPROVIDE|ENDSELECT|ENDTRY|ENDWHILE' && + '|ENGINEERING|ENHANCEMENT|ENHANCEMENT-POINT|ENHANCEMENTS|ENHANCEMENT-SECTION' && + '|ENTRIES|ENTRY|ENVIRONMENT|EQ|EQUIV|ERRORMESSAGE|ERRORS|ESCAPE|ESCAPING' && + '|EVENT|EVENTS|EXACT|EXCEPT|EXCEPTION|EXCEPTIONS|EXCEPTION-TABLE|EXCLUDE|EXCLUDING' && + '|EXEC|EXECUTE|EXISTS|EXIT|EXIT-COMMAND|EXP|EXPAND|EXPANDING|EXPIRATION|EXPLICIT' && + '|EXPONENT|EXPORT|EXPORTING|EXTEND|EXTENDED|EXTENSION|EXTRACT|FAIL|FETCH|FIELD' && + '|FIELD-GROUPS|FIELDS|FIELD-SYMBOL|FIELD-SYMBOLS|FILE|FILTER|FILTERS|FILTER-TABLE' && + '|FINAL|FIND|FIRST|FIRST-LINE|FIXED-POINT|FKEQ|FKGE|FLOOR|FLUSH|FONT|FOR|FORM' && + '|FORMAT|FORWARD|FOUND|FRAC|FRAME|FRAMES|FREE|FRIENDS|FROM|FUNCTION|FUNCTIONALITY' && + '|FUNCTION-POOL|FURTHER|GAPS|GE|GENERATE|GET|GIVING|GKEQ|GKGE|GLOBAL|GRANT' && + '|GREEN|GROUP|GROUPS|GT|HANDLE|HANDLER|HARMLESS|HASHED|HAVING|HDB|HEADER|HEADERS' && + '|HEADING|HEAD-LINES|HELP-ID|HELP-REQUEST|HIDE|HIGH|HINT|HOLD|HOTSPOT|I|ICON|ID' && + '|IDENTIFICATION|IDENTIFIER|IDS|IF|IGNORE|IGNORING|IMMEDIATELY|IMPLEMENTATION' && + '|IMPLEMENTATIONS|IMPLEMENTED|IMPLICIT|IMPORT|IMPORTING|IN|INACTIVE|INCL|INCLUDE' && + '|INCLUDES|INCLUDING|INCREMENT|INDEX|INDEX-LINE|INFOTYPES|INHERITING|INIT|INITIAL' && + '|INITIALIZATION|INNER|INOUT|INPUT|INSERT|INSTANCES|INTENSIFIED|INTERFACE' && + '|INTERFACE-POOL|INTERFACES|INTERNAL|INTERVALS|INTO|INVERSE|INVERTED-DATE|IS' && + '|ISO|JOB|JOIN|KEEP|KEEPING|KERNEL|KEY|KEYS|KEYWORDS|KIND' && + '|LANGUAGE|LAST|LATE|LAYOUT|LE|LEADING|LEAVE|LEFT|LEFT-JUSTIFIED|LEFTPLUS' && + '|LEFTSPACE|LEGACY|LENGTH|LET|LEVEL|LEVELS|LIKE|LINE|LINE-COUNT|LINEFEED' && + '|LINES|LINE-SELECTION|LINE-SIZE|LIST|LISTBOX|LIST-PROCESSING|LITTLE|LLANG' && + '|LOAD|LOAD-OF-PROGRAM|LOB|LOCAL|LOCALE|LOCATOR|LOG|LOG10|LOGFILE|LOGICAL' && + '|LOG-POINT|LONG|LOOP|LOW|LOWER|LPAD|LPI|LT|M|MAIL|MAIN|MAJOR-ID|MAPPING|MARGIN' && + '|MARK|MASK|MATCH|MATCHCODE|MAX|MAXIMUM|MEDIUM|MEMBERS|MEMORY|MESH|MESSAGE' && + '|MESSAGE-ID|MESSAGES|MESSAGING|METHOD|METHODS|MIN|MINIMUM|MINOR-ID|MM/DD/YY' && + '|MM/DD/YYYY|MMDDYY|MOD|MODE|MODIF|MODIFIER|MODIFY|MODULE|MOVE|MOVE-CORRESPONDING' && + '|MULTIPLY|MULTIPLY-CORRESPONDING|NA|NAME|NAMETAB|NATIVE|NB|NE|NESTED|NESTING' && + '|NEW|NEW-LINE|NEW-PAGE|NEW-SECTION|NEXT|NO|NODE|NODES|NO-DISPLAY' && + '|NO-EXTENSION|NO-GAP|NO-GAPS|NO-GROUPING|NO-HEADING|NON-UNICODE|NON-UNIQUE' && + '|NO-SCROLLING|NO-SIGN|NOT|NO-TITLE|NO-TOPOFPAGE|NO-ZERO|NP|NS|NULL|NUMBER' && + '|NUMOFCHAR|O|OBJECT|OBJECTS|OBLIGATORY|OCCURRENCE|OCCURRENCES|OCCURS|OF|OFF' && + '|OFFSET|OLE|ON|ONLY|OPEN|OPTION|OPTIONAL|OPTIONS|OR|ORDER|OTHER|OTHERS|OUT' && + '|OUTER|OUTPUT|OUTPUT-LENGTH|OVERFLOW|OVERLAY|PACK|PACKAGE|PAD|PADDING|PAGE' && + '|PAGES|PARAMETER|PARAMETERS|PARAMETER-TABLE|PART|PARTIALLY|PATTERN|PERCENTAGE' && + '|PERFORM|PERFORMING|PERSON|PF1|PF2|PF3|PF4|PF5|PF6|PF7|PF8|PF9|PF10|PF11|PF12' && + '|PF13|PF14|PF15|PF-STATUS|PINK|PLACES|POOL|POS_HIGH|POS_LOW' && + '|POSITION|PRAGMAS|PRECOMPILED|PREFERRED|PRESERVING|PRIMARY|PRINT|PRINT-CONTROL' && + '|PRIORITY|PRIVATE|PROCEDURE|PROCESS|PROGRAM|PROPERTY|PROTECTED|PROVIDE|PUBLIC' && + '|PUSHBUTTON|PUT|QUEUE-ONLY|QUICKINFO|RADIOBUTTON|RAISE|RAISING|RANGE|RANGES' && + '|RAW|READ|READER|READ-ONLY|RECEIVE|RECEIVED|RECEIVER|RECEIVING|RED|REDEFINITION' && + '|REDUCE|REDUCED|REF|REFERENCE|REFRESH|REGEX|REJECT|REMOTE|RENAMING|REPLACE' && + '|REPLACEMENT|REPLACING|REPORT|REQUEST|REQUESTED|RESERVE|RESET|RESOLUTION' && + '|RESPECTING|RESPONSIBLE|RESULT|RESULTS|RESUMABLE|RESUME|RETRY|RETURN|RETURNCODE' && + '|RETURNING|RIGHT|RIGHT-JUSTIFIED|RIGHTPLUS|RIGHTSPACE|RISK|RMC_COMMUNICATION_FAILURE' && + '|RMC_INVALID_STATUS|RMC_SYSTEM_FAILURE|ROLE|ROLLBACK|ROUND|ROWS|RUN|SAP' && + '|SAP-SPOOL|SAVING|SCALE_PRESERVING|SCALE_PRESERVING_SCIENTIFIC|SCAN|SCIENTIFIC' && + '|SCIENTIFIC_WITH_LEADING_ZERO|SCREEN|SCROLL|SCROLL-BOUNDARY|SCROLLING|SEARCH' && + '|SECONDARY|SECONDS|SECTION|SELECT|SELECTION|SELECTIONS|SELECTION-SCREEN|SELECTION-SET' && + '|SELECTION-SETS|SELECTION-TABLE|SELECT-OPTIONS|SEND|SEPARATE|SEPARATED|SET' && + '|SHARED|SHIFT|SHORT|SHORTDUMP-ID|SIGN|SIGN_AS_POSTFIX|SIMPLE|SIN|SINGLE|SINH|SIZE' && + '|SKIP|SKIPPING|SMART|SOME|SORT|SORTABLE|SORTED|SOURCE|SPACE|SPECIFIED|SPLIT|SPOOL' && + '|SPOTS|SQL|SQLSCRIPT|SQRT|STABLE|STAMP|STANDARD|STARTING|START-OF-SELECTION|STATE' && + '|STATEMENT|STATEMENTS|STATIC|STATICS|STATUSINFO|STEP-LOOP|STOP|STRLEN|STRUCTURE' && + '|STRUCTURES|STYLE|SUBKEY|SUBMATCHES|SUBMIT|SUBROUTINE|SUBSCREEN|SUBSTRING|SUBTRACT' && + '|SUBTRACT-CORRESPONDING|SUFFIX|SUM|SUMMARY|SUMMING|SUPPLIED|SUPPLY|SUPPRESS|SWITCH' && + '|SWITCHSTATES|SYMBOL|SYNCPOINTS|SYNTAX|SYNTAX-CHECK|SYNTAX-TRACE' && + '|SYSTEM-CALL|SYSTEM-EXCEPTIONS|SYSTEM-EXIT|TAB|TABBED|TABLE|TABLES|TABLEVIEW|TABSTRIP' && + '|TAN|TANH|TARGET|TASK|TASKS|TEST|TESTING|TEXT|TEXTPOOL|THEN|THROW|TIME|TIMES|TIMESTAMP' && + '|TIMEZONE|TITLE|TITLEBAR|TITLE-LINES|TO|TOKENIZATION|TOKENS|TOP-LINES|TOP-OF-PAGE' && + '|TRACE-FILE|TRACE-TABLE|TRAILING|TRANSACTION|TRANSFER|TRANSFORMATION|TRANSLATE' && + '|TRANSPORTING|TRMAC|TRUNC|TRUNCATE|TRUNCATION|TRY|TYPE|TYPE-POOL|TYPE-POOLS|TYPES' && + '|ULINE|UNASSIGN|UNDER|UNICODE|UNION|UNIQUE|UNIT|UNIT_CONVERSION|UNIX|UNPACK|UNTIL' && + '|UNWIND|UP|UPDATE|UPPER|USER|USER-COMMAND|USING|UTF-8|VALID|VALUE|VALUE-REQUEST|VALUES' && + '|VARY|VARYING|VERIFICATION-MESSAGE|VERSION|VIA|VIEW|VISIBLE|WAIT|WARNING|WHEN|WHENEVER' && + '|WHERE|WHILE|WIDTH|WINDOW|WINDOWS|WITH|WITH-HEADING|WITHOUT|WITH-TITLE|WORD|WORK' && + '|WRITE|WRITER|X|XML|XSD|XSTRLEN|YELLOW|YES|YYMMDD|Z|ZERO|ZONE' && + '|BINTOHEX|CHAR|CLNT|CONCAT_WITH_SPACE|CURR|DATS|DATS_ADD_DAYS|DATS_ADD_MONTHS' && + '|DATS_DAYS_BETWEEN|DATS_IS_VALID|DEC|END-OF-EDITING|END-TEST-INJECTION|END-TEST-SEAM' && + '|ENDWITH|ENUM|HEXTOBIN|INSTANCE|INSTR|LANG|LTRIM|NUMC|PUSH' && + '|QUAN|RETURNS|RPAD|RTRIM|SSTRING|START-OF-EDITING|TEST-INJECTION|TEST-SEAM|TIMS' && + '|TIMS_IS_VALID|TSTMP_ADD_SECONDS|TSTMP_CURRENT_UTCTIMESTAMP|TSTMP_IS_VALID' && + '|TSTMP_SECONDS_BETWEEN|B|D|DECFLOAT16|DECFLOAT34|F|INT8|N|P|S|STRING|T|UTCLONG|XSTRING' && + '|ABAP_BOOL|ACCP|CUKY|DF16_DEC|DF16_RAW|DF34_DEC|DF34_RAW|FLTP' && + '|INT1|INT2|INT4|LCHR|LRAW|RAWSTRING|DF16_SCL|DF34_SCL' && + '|PREC|VARC|CLIKE|CSEQUENCE|DECFLOAT|NUMERIC|XSEQUENCE|ME|SYST|SY' && + '|BIT-SET|BOOLC|BOOLX|CHAR_OFF|CMAX|CMIN|CONCAT_LINES_OF|CONTAINS|CONTAINS_ANY_NOT_OF' && + '|CONTAINS_ANY_OF|COUNT_ANY_NOT_OF|COUNT_ANY_OF|FIND_ANY_NOT_OF|FIND_ANY_OF|FIND_END' && + '|FROM_MIXED|IPOW|LINE_EXISTS|LINE_INDEX|MATCHES|NMAX|NMIN|REPEAT|RESCALE|REVERSE' && + '|SEGMENT|SHIFT_LEFT|SHIFT_RIGHT|SUBSTRING_AFTER|SUBSTRING_BEFORE|SUBSTRING_FROM|SUBSTRING_TO' && + '|TO_LOWER|TO_MIXED|TO_UPPER|UTCLONG_ADD|UTCLONG_CURRENT|UTCLONG_DIFF|XSDBOOL'. + SPLIT lv_keywords AT '|' INTO TABLE lt_keywords. + " remove duplicates to avoid dumps when converting to a hash table + SORT lt_keywords BY table_line ASCENDING. + DELETE ADJACENT DUPLICATES FROM lt_keywords. + gt_keywords = lt_keywords. " Hash table + + ENDMETHOD. + METHOD is_keyword. + + DATA lv_str TYPE string. + + lv_str = to_upper( iv_chunk ). + READ TABLE gt_keywords WITH KEY table_line = lv_str TRANSPORTING NO FIELDS. + rv_yes = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD order_matches. + + DATA: + lv_index TYPE sy-tabix, + lv_line_len TYPE i, + lv_prev_token TYPE c. + + FIELD-SYMBOLS: + TYPE ty_match, + TYPE ty_match. + + SORT ct_matches BY offset. + + lv_line_len = strlen( iv_line ). + + LOOP AT ct_matches ASSIGNING . + lv_index = sy-tabix. + + " Delete matches after open text match + IF lv_prev_token = c_token-text AND -token <> c_token-text. + DELETE ct_matches INDEX lv_index. + CONTINUE. + ENDIF. + + CASE -token. + WHEN c_token-keyword. + IF -offset > 0 + AND substring( val = iv_line + off = ( -offset - 1 ) + len = 1 ) CA '-<'. + " Delete match if keyword is part of structure or field symbol + DELETE ct_matches INDEX lv_index. + CONTINUE. + ENDIF. + + WHEN c_token-comment. + -length = lv_line_len - -offset. + DELETE ct_matches FROM lv_index + 1. + CONTINUE. + + WHEN c_token-text. + -text_tag = substring( val = iv_line + off = -offset + len = -length ). + IF lv_prev_token = c_token-text. + IF -text_tag = -text_tag. + -length = -offset + -length - -offset. + CLEAR lv_prev_token. + ELSEIF -text_tag = '}' AND -text_tag = '{'. + -length = -offset - -offset - 1. " Shift } out of scope + -offset = -offset + 1. " Shift { out of scope + CLEAR lv_prev_token. + ELSEIF -text_tag = '{'. + -length = -offset - -offset. + CLEAR lv_prev_token. + ELSEIF -text_tag = '}'. + -length = -offset - -offset. + -offset = -offset + 1. " Shift } out of scope + CLEAR lv_prev_token. + ENDIF. + DELETE ct_matches INDEX lv_index. + CONTINUE. + ENDIF. + + ENDCASE. + + lv_prev_token = -token. + ASSIGN TO . + ENDLOOP. + + ENDMETHOD. + METHOD parse_line. "REDEFINITION + + DATA lv_index TYPE i. + + FIELD-SYMBOLS LIKE LINE OF rt_matches. + + rt_matches = super->parse_line( iv_line ). + + " Remove non-keywords + LOOP AT rt_matches ASSIGNING WHERE token = c_token-keyword. + lv_index = sy-tabix. + IF abap_false = is_keyword( substring( val = iv_line + off = -offset + len = -length ) ). + DELETE rt_matches INDEX lv_index. + ENDIF. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlVCHrsAtuwxHoXzuQzYvAOqpyr DEFINITION DEFERRED. +* renamed: zcl_abapgit_repo_status :: lcl_status_consistency_checks +CLASS kHGwlVCHrsAtuwxHoXzuQzYvAOqpyr DEFINITION FINAL. + PUBLIC SECTION. + + METHODS constructor + IMPORTING + iv_root_package TYPE devclass + io_dot TYPE REF TO zcl_abapgit_dot_abapgit. + + METHODS run_checks + IMPORTING + it_results TYPE zif_abapgit_definitions=>ty_results_tt + RETURNING + VALUE(ri_log) TYPE REF TO zif_abapgit_log + RAISING + zcx_abapgit_exception . + + PRIVATE SECTION. + + DATA mv_root_package TYPE devclass. + DATA mo_dot TYPE REF TO zcl_abapgit_dot_abapgit. + DATA mi_log TYPE REF TO zif_abapgit_log. + + METHODS check_package_move + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception . + METHODS check_files_folder + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception . + METHODS check_package_sub_package + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + !iv_top TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS check_package_folder + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !iv_top TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS check_multiple_files + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception . + METHODS check_namespace + IMPORTING + !it_results TYPE zif_abapgit_definitions=>ty_results_tt + RAISING + zcx_abapgit_exception . + +ENDCLASS. + +CLASS kHGwlVCHrsAtuwxHoXzuQzYvAOqpyr IMPLEMENTATION. + + METHOD constructor. + mv_root_package = iv_root_package. + mo_dot = io_dot. + ENDMETHOD. + + METHOD run_checks. + + CREATE OBJECT mi_log TYPE zcl_abapgit_log. + + " Find all objects which were assigned to a different package + check_package_move( it_results ). + + " Check files for one object is in the same folder + check_files_folder( it_results ). + + " Check that sub packages are included in the package hierarchy + check_package_sub_package( + it_results = it_results + iv_top = mv_root_package ). + + " Check that objects are created in package corresponding to folder + check_package_folder( + it_results = it_results + io_dot = mo_dot + iv_top = mv_root_package ). + + " Check for multiple files with same filename + check_multiple_files( it_results ). + + " Check if namespaces exist already + check_namespace( it_results ). + + ri_log = mi_log. + + ENDMETHOD. + + METHOD check_files_folder. + + DATA: + ls_item TYPE zif_abapgit_definitions=>ty_item, + lt_res_sort LIKE it_results, + lt_item_idx LIKE it_results. + + FIELD-SYMBOLS: + LIKE LINE OF it_results, + LIKE LINE OF it_results. + + " TODO optimize ? + " sort by obj, path + " loop, and compare to first object record + + " Collect object index + lt_res_sort = it_results. + SORT lt_res_sort BY obj_type ASCENDING obj_name ASCENDING. + + LOOP AT it_results ASSIGNING WHERE NOT obj_type IS INITIAL AND packmove = abap_false. + + IF NOT ( -obj_type = ls_item-obj_type + AND -obj_name = ls_item-obj_name ). + APPEND INITIAL LINE TO lt_item_idx ASSIGNING . + -obj_type = -obj_type. + -obj_name = -obj_name. + -path = -path. + MOVE-CORRESPONDING TO ls_item. + ENDIF. + + ENDLOOP. + + LOOP AT it_results ASSIGNING + WHERE NOT obj_type IS INITIAL AND obj_type <> 'DEVC' AND packmove = abap_false. + + READ TABLE lt_item_idx ASSIGNING + WITH KEY obj_type = -obj_type obj_name = -obj_name + BINARY SEARCH. " Sorted above + + IF sy-subrc <> 0 OR -path <> -path. " All paths are same + mi_log->add_warning( |Files for object { -obj_type } { -obj_name }| + && | are not placed in the same folder| ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + + METHOD check_multiple_files. + + DATA: + lt_res_sort LIKE it_results, + ls_file TYPE zif_abapgit_git_definitions=>ty_file_signature. + + FIELD-SYMBOLS LIKE LINE OF it_results. + + lt_res_sort = it_results. + SORT lt_res_sort BY filename ASCENDING. + + LOOP AT lt_res_sort ASSIGNING WHERE obj_type <> 'DEVC' AND packmove = abap_false. + IF -filename IS NOT INITIAL AND -filename = ls_file-filename. + mi_log->add_warning( |Multiple files with same filename, { -filename }| ). + ENDIF. + + IF -filename IS INITIAL. + mi_log->add_warning( |Filename is empty for object { -obj_type } { -obj_name }| ). + ENDIF. + + MOVE-CORRESPONDING TO ls_file. + ENDLOOP. + + ENDMETHOD. + METHOD check_namespace. + + DATA: + li_namespace TYPE REF TO zif_abapgit_sap_namespace, + lv_namespace TYPE namespace, + lt_namespace TYPE TABLE OF namespace. + + FIELD-SYMBOLS LIKE LINE OF it_results. + + " Collect all namespaces based on name of xml- and json-files + LOOP AT it_results ASSIGNING . + FIND REGEX '^#([a-zA-Z0-9]+)#.*\..*\.xml$' IN -filename SUBMATCHES lv_namespace. + IF sy-subrc = 0. + lv_namespace = '/' && to_upper( lv_namespace ) && '/'. + COLLECT lv_namespace INTO lt_namespace. + ENDIF. + FIND REGEX '^\(([a-zA-Z0-9]+)\).*\..*\.json$' IN -filename SUBMATCHES lv_namespace. + IF sy-subrc = 0. + lv_namespace = '/' && to_upper( lv_namespace ) && '/'. + COLLECT lv_namespace INTO lt_namespace. + ENDIF. + ENDLOOP. + + li_namespace = zcl_abapgit_factory=>get_sap_namespace( ). + + LOOP AT lt_namespace INTO lv_namespace. + IF li_namespace->exists( lv_namespace ) = abap_false. + mi_log->add_warning( |Namespace { lv_namespace } does not exist.| + && | Pull it first (or create it in transaction SE03)| ). + ELSEIF li_namespace->is_editable( lv_namespace ) = abap_false. + mi_log->add_warning( |Namespace { lv_namespace } is not modifiable. Check it in transaction SE03| ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD check_package_folder. + + DATA: + lv_path TYPE string, + lv_object TYPE string, + lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic. + + FIELD-SYMBOLS LIKE LINE OF it_results. + + lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). + + LOOP AT it_results ASSIGNING + WHERE NOT package IS INITIAL AND NOT path IS INITIAL AND packmove = abap_false. + + lv_path = lo_folder_logic->package_to_path( + iv_top = iv_top + io_dot = io_dot + iv_package = -package ). + + lv_object = |{ -obj_type } { -obj_name }|. + + IF lv_path IS INITIAL. + IF -package(1) = '$'. + mi_log->add_warning( |{ lv_object } exists but package { -package } is missing| + && | (might have been lost during an upgrade, SAP Note 2478895)| ). + ELSE. + mi_log->add_error( |{ lv_object } already exists outside of { iv_top } package hierarchy| ). + ENDIF. + ELSEIF lv_path <> -path. + mi_log->add_warning( |Package and path do not match for object { lv_object }| ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD check_package_move. + + DATA lt_move_idx LIKE it_results. + + FIELD-SYMBOLS: + LIKE LINE OF it_results, + LIKE LINE OF it_results. + + " TODO: optimize ? + " delete where packmove = false, delete adj duplicates and fire messages ? + LOOP AT it_results ASSIGNING + WHERE lstate = zif_abapgit_definitions=>c_state-added AND packmove = abap_true. + + READ TABLE lt_move_idx TRANSPORTING NO FIELDS + WITH KEY + obj_type = -obj_type + obj_name = -obj_name + BINARY SEARCH. " Sorted since it_result is sorted + IF sy-subrc <> 0. + mi_log->add_warning( |Changed package assignment for object| + && | { -obj_type } { -obj_name }| ). + APPEND INITIAL LINE TO lt_move_idx ASSIGNING . + -obj_type = -obj_type. + -obj_name = -obj_name. + -path = -path. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD check_package_sub_package. + + DATA lv_msg TYPE string. + + FIELD-SYMBOLS LIKE LINE OF it_results. + + LOOP AT it_results ASSIGNING USING KEY sec_key + WHERE package IS INITIAL AND obj_type = 'DEVC'. + + IF zcl_abapgit_factory=>get_sap_package( |{ -obj_name }| )->exists( ) = abap_true. + " If package already exist but is not included in the package hierarchy of + " the package assigned to the repository, then a manual change of the package + " is required i.e. setting a parent package to the repo package (or one of its + " subpackages). We don't do this automatically since it's not clear where in the + " hierarchy the new package should be located or whether the sub package shall be + " removed from the repo. + lv_msg = |Package { -obj_name } already exists but is not a sub-package of { iv_top }. | + && |Check your package and folder logic, and either assign { -obj_name } | + && |to the package hierarchy of { iv_top } or remove package { -obj_name } | + && |from the repository.|. + mi_log->add_warning( lv_msg ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_repo_status IMPLEMENTATION. + METHOD calculate. + + DATA lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. + DATA lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt. + DATA li_exit TYPE REF TO zif_abapgit_exit. + DATA li_instance TYPE REF TO zif_abapgit_status_calc. + DATA lo_consistency_checks TYPE REF TO kHGwlVCHrsAtuwxHoXzuQzYvAOqpyr. + + IF ii_obj_filter IS INITIAL. + lt_local = ii_repo->get_files_local( ii_log ). + ELSE. + lt_local = ii_repo->get_files_local_filtered( + ii_log = ii_log + ii_obj_filter = ii_obj_filter ). + ENDIF. + + IF lines( lt_local ) <= 2 AND ii_obj_filter IS INITIAL. + " Less equal two means that we have only the .abapgit.xml and the package in + " our local repository. In this case we have to update our local .abapgit.xml + " from the remote one. Otherwise we get errors when e.g. the folder starting + " folder is different. + ii_repo->find_remote_dot_abapgit( ). + ENDIF. + + lt_remote = ii_repo->get_files_remote( ii_obj_filter = ii_obj_filter + iv_ignore_files = abap_true ). + + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->pre_calculate_repo_status( + EXPORTING + is_repo_meta = ii_repo->ms_data + CHANGING + ct_local = lt_local + ct_remote = lt_remote ). + + li_instance = zcl_abapgit_status_calc=>get_instance( + iv_root_package = ii_repo->get_package( ) + io_dot = ii_repo->get_dot_abapgit( ) ). + + rt_results = li_instance->calculate_status( + it_local = lt_local + it_remote = lt_remote + it_cur_state = ii_repo->checksums( )->get_checksums_per_file( ) ). + + IF ii_log IS BOUND. + " This method just adds messages to the log. No log, nothing to do here + CREATE OBJECT lo_consistency_checks + EXPORTING + iv_root_package = ii_repo->get_package( ) + io_dot = ii_repo->get_dot_abapgit( ). + ii_log->merge_with( lo_consistency_checks->run_checks( rt_results ) ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_srv IMPLEMENTATION. + METHOD add. + + DATA li_repo LIKE LINE OF mt_list. + + LOOP AT mt_list INTO li_repo. + IF li_repo->ms_data-key = ii_repo->ms_data-key. + IF li_repo = ii_repo. + RETURN. + ENDIF. + zcx_abapgit_exception=>raise( 'identical keys' ). + ENDIF. + ENDLOOP. + + ii_repo->bind_listener( me ). + APPEND ii_repo TO mt_list. + + ENDMETHOD. + METHOD create_initial_branch. + + rv_name = zcl_abapgit_pr_enumerator=>new( iv_url )->create_initial_branch( + iv_readme = iv_readme + iv_branch_name = iv_branch_name ). + + ENDMETHOD. + METHOD determine_branch_name. + + DATA lo_branch_list TYPE REF TO zif_abapgit_git_branch_list. + + rv_name = iv_name. + IF rv_name IS INITIAL. + ASSERT NOT iv_url IS INITIAL. + lo_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). + rv_name = lo_branch_list->get_head_symref( ). + ELSEIF -1 = find( + val = rv_name + sub = zif_abapgit_git_definitions=>c_git_branch-heads_prefix ). + " Assume short branch name was received + rv_name = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && rv_name. + ENDIF. + + ENDMETHOD. + METHOD get_instance. + IF gi_ref IS INITIAL. + CREATE OBJECT gi_ref TYPE zcl_abapgit_repo_srv. + ENDIF. + ri_srv = gi_ref. + ENDMETHOD. + METHOD inject_instance. + gi_ref = ii_srv. + ENDMETHOD. + METHOD instantiate_and_add. + + IF is_repo_meta-offline = abap_false. + CREATE OBJECT ri_repo TYPE zcl_abapgit_repo_online + EXPORTING + is_data = is_repo_meta. + ELSE. + CREATE OBJECT ri_repo TYPE zcl_abapgit_repo_offline + EXPORTING + is_data = is_repo_meta. + ENDIF. + add( ri_repo ). + + ENDMETHOD. + METHOD refresh_all. + + DATA: lt_list TYPE zif_abapgit_persistence=>ty_repos. + + FIELD-SYMBOLS: LIKE LINE OF lt_list. + + CLEAR mt_list. + + lt_list = zcl_abapgit_persist_factory=>get_repo( )->list( ). + LOOP AT lt_list ASSIGNING . + instantiate_and_add( ). + ENDLOOP. + + mv_init = abap_true. + mv_only_favorites = abap_false. + + ENDMETHOD. + METHOD refresh_favorites. + + DATA: lt_list TYPE zif_abapgit_persistence=>ty_repos, + lt_user_favorites TYPE zif_abapgit_persist_user=>ty_favorites. + + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA lv_repo_index TYPE i. + DATA lo_repo_db TYPE REF TO zif_abapgit_persist_repo. + + FIELD-SYMBOLS: LIKE LINE OF lt_list. + + lo_repo_db = zcl_abapgit_persist_factory=>get_repo( ). + lt_user_favorites = zcl_abapgit_persist_factory=>get_user( )->get_favorites( ). + lt_list = lo_repo_db->list_by_keys( lt_user_favorites ). + + SORT lt_list BY package. + + LOOP AT mt_list INTO li_repo. + lv_repo_index = sy-tabix. + + READ TABLE lt_list TRANSPORTING NO FIELDS WITH KEY package = li_repo->get_package( ). + IF sy-subrc = 0. + DELETE lt_list INDEX sy-tabix. + CONTINUE. " Leave the repo be + ELSEIF lo_repo_db->exists( li_repo->get_key( ) ) = abap_false. + " Not a fav, and also does not exist, probably uninstalled + DELETE mt_list INDEX lv_repo_index. + ENDIF. + + ENDLOOP. + + " Create remaining (new) favs + LOOP AT lt_list ASSIGNING . + instantiate_and_add( ). + ENDLOOP. + + mv_init = abap_true. + mv_only_favorites = abap_true. + + ENDMETHOD. + METHOD reinstantiate_repo. + + DATA li_repo TYPE REF TO zif_abapgit_repo. + DATA ls_full_meta TYPE zif_abapgit_persistence=>ty_repo. + + li_repo = zif_abapgit_repo_srv~get( iv_key ). + DELETE TABLE mt_list FROM li_repo. + ASSERT sy-subrc IS INITIAL. + + MOVE-CORRESPONDING is_meta TO ls_full_meta. + ls_full_meta-key = iv_key. + + instantiate_and_add( ls_full_meta ). + + ENDMETHOD. + METHOD validate_package_korrflag. + + DATA: + li_package TYPE REF TO zif_abapgit_sap_package, + lv_korrflag TYPE abap_bool, + lv_package TYPE devclass, + lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. + + li_package = zcl_abapgit_factory=>get_sap_package( iv_package ). + IF li_package->exists( ) = abap_false. + " Skip dangling repository + RETURN. + ENDIF. + + lv_korrflag = li_package->are_changes_recorded_in_tr_req( ). + + IF iv_ign_subpkg = abap_false. + lt_packages = li_package->list_subpackages( ). + LOOP AT lt_packages INTO lv_package. + li_package = zcl_abapgit_factory=>get_sap_package( lv_package ). + IF li_package->exists( ) = abap_true AND li_package->are_changes_recorded_in_tr_req( ) <> lv_korrflag. + zcx_abapgit_exception=>raise( 'Mix of transportable and non-transportable packages is not supported' ). + ENDIF. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD validate_sub_super_packages. + + DATA: + ls_repo LIKE LINE OF it_repos, + li_package TYPE REF TO zif_abapgit_sap_package, + lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt, + li_repo TYPE REF TO zif_abapgit_repo. + + LOOP AT it_repos INTO ls_repo. + li_repo = zif_abapgit_repo_srv~get( ls_repo-key ). + + li_package = zcl_abapgit_factory=>get_sap_package( ls_repo-package ). + IF li_package->exists( ) = abap_false. + " Skip dangling repository + CONTINUE. + ENDIF. + + CLEAR lt_packages. + IF li_repo->get_local_settings( )-ignore_subpackages = abap_false. + APPEND LINES OF li_package->list_subpackages( ) TO lt_packages. + READ TABLE lt_packages TRANSPORTING NO FIELDS + WITH KEY table_line = iv_package. + IF sy-subrc = 0. + ei_repo = li_repo. + ev_reason = |Repository { li_repo->get_name( ) } already contains { iv_package } |. + RETURN. + ENDIF. + ENDIF. + + IF iv_ign_subpkg = abap_false. + APPEND LINES OF li_package->list_superpackages( ) TO lt_packages. + READ TABLE lt_packages TRANSPORTING NO FIELDS + WITH KEY table_line = iv_package. + IF sy-subrc = 0. + ei_repo = li_repo. + ev_reason = |Repository { li_repo->get_name( ) } already contains subpackage of { iv_package } |. + RETURN. + ENDIF. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_repo_listener~on_meta_change. + + DATA li_persistence TYPE REF TO zif_abapgit_persist_repo. + + li_persistence = zcl_abapgit_persist_factory=>get_repo( ). + li_persistence->update_metadata( + iv_key = iv_key + is_meta = is_meta + is_change_mask = is_change_mask ). + " Recreate repo instance if type changed + " Instances in mt_list are of *_online and *_offline type + " If type is changed object should be recreated from the proper class + " TODO refactor, e.g. unify repo logic in one class + IF is_change_mask-offline = abap_true. + reinstantiate_repo( + iv_key = iv_key + is_meta = is_meta ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~delete. + + zcl_abapgit_persist_factory=>get_repo( )->delete( ii_repo->get_key( ) ). + zcl_abapgit_persist_factory=>get_repo_cs( )->delete( ii_repo->get_key( ) ). + + " If favorite, remove it + IF zcl_abapgit_persist_factory=>get_user( )->is_favorite_repo( ii_repo->get_key( ) ) = abap_true. + zcl_abapgit_persist_factory=>get_user( )->toggle_favorite( ii_repo->get_key( ) ). + ENDIF. + + DELETE TABLE mt_list FROM ii_repo. + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~get. + + FIELD-SYMBOLS: LIKE LINE OF mt_list. + + ASSERT iv_key IS NOT INITIAL. + + IF mv_init = abap_false. + refresh_all( ). + ENDIF. + + DO 2 TIMES. + " Repo might have been created in another session. Try again after refresh + IF sy-index = 2. + refresh_all( ). + ENDIF. + LOOP AT mt_list ASSIGNING . + IF ->ms_data-key = iv_key. + ri_repo = . + RETURN. + ENDIF. + ENDLOOP. + ENDDO. + + zcx_abapgit_exception=>raise( |Repository not found in database. Key: REPO, { iv_key }| ). + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~get_label_list. + + DATA: + lt_repo TYPE zif_abapgit_repo_srv=>ty_repo_list, + ls_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings, + lt_labels TYPE string_table, + ls_label LIKE LINE OF rt_labels. + + FIELD-SYMBOLS: + TYPE REF TO zif_abapgit_repo, + TYPE LINE OF string_table. + + lt_repo = zif_abapgit_repo_srv~list( ). + + LOOP AT lt_repo ASSIGNING . + + ls_local_settings = ->get_local_settings( ). + lt_labels = zcl_abapgit_repo_labels=>split( ls_local_settings-labels ). + + LOOP AT lt_labels ASSIGNING . + ls_label-label = . + INSERT ls_label INTO TABLE rt_labels. + ENDLOOP. + + ENDLOOP. + + SORT rt_labels. + DELETE ADJACENT DUPLICATES FROM rt_labels. + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~get_repo_from_package. + + DATA: + lt_repos TYPE zif_abapgit_persistence=>ty_repos, + lv_name TYPE zif_abapgit_persistence=>ty_local_settings-display_name, + lv_owner TYPE zif_abapgit_persistence=>ty_local_settings-display_name. + + FIELD-SYMBOLS: + LIKE LINE OF lt_repos. + + " check if package is already in use for a different repository + lt_repos = zcl_abapgit_persist_factory=>get_repo( )->list( ). + READ TABLE lt_repos WITH KEY package = iv_package ASSIGNING . + IF sy-subrc = 0. + ei_repo = get_instance( )->get( -key ). + lv_name = ei_repo->get_name( ). + lv_owner = -created_by. + ev_reason = |Package { iv_package } already versioned as { lv_name } by { lv_owner }|. + ELSE. + " check if package is include as sub-package in a different repo + validate_sub_super_packages( + EXPORTING + iv_package = iv_package + it_repos = lt_repos + iv_ign_subpkg = iv_ign_subpkg + IMPORTING + ei_repo = ei_repo + ev_reason = ev_reason ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~get_repo_from_url. + + DATA: + lt_repos TYPE zif_abapgit_persistence=>ty_repos, + lv_current_repo_address TYPE string, + lv_check_repo_address TYPE string, + lv_repo_path TYPE string, + lv_name TYPE zif_abapgit_persistence=>ty_local_settings-display_name, + lv_owner TYPE zif_abapgit_persistence=>ty_local_settings-display_name. + + FIELD-SYMBOLS: + LIKE LINE OF lt_repos. + + CLEAR: + ei_repo, ev_reason. + + lv_current_repo_address = zcl_abapgit_url=>url_address( iv_url ). + + " check if url is already in use for a different package + lt_repos = zcl_abapgit_persist_factory=>get_repo( )->list( ). + LOOP AT lt_repos ASSIGNING WHERE offline = abap_false. + + lv_check_repo_address = zcl_abapgit_url=>url_address( -url ). + + IF lv_current_repo_address = lv_check_repo_address. + ei_repo = get_instance( )->get( -key ). + lv_repo_path = zcl_abapgit_url=>path_name( iv_url ). + lv_name = ei_repo->get_name( ). + lv_owner = -created_by. + ev_reason = |Repository { lv_repo_path } already versioned as { lv_name } by { lv_owner }|. + RETURN. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~init. + CLEAR mv_init. + ENDMETHOD. + METHOD zif_abapgit_repo_srv~is_repo_installed. + + DATA: lt_repo TYPE zif_abapgit_repo_srv=>ty_repo_list, + li_repo TYPE REF TO zif_abapgit_repo, + lv_url TYPE string, + lv_package TYPE devclass, + li_repo_online TYPE REF TO zif_abapgit_repo_online, + lv_err TYPE string. + + lt_repo = zif_abapgit_repo_srv~list( ). + + LOOP AT lt_repo INTO li_repo. + CHECK li_repo->is_offline( ) = abap_false. + li_repo_online ?= li_repo. + + lv_url = li_repo_online->get_url( ). + lv_package = li_repo->get_package( ). + CHECK to_upper( lv_url ) = to_upper( iv_url ). + + " Validate bindings + "TODO refactor: move this message out of this method + IF iv_target_package IS NOT INITIAL AND iv_target_package <> lv_package. + lv_err = |Installation to package { lv_package } detected. | + && |Cancelling installation|. + zcx_abapgit_exception=>raise( lv_err ). + ENDIF. + + rv_installed = abap_true. + EXIT. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~list. + + DATA li_repo TYPE REF TO zif_abapgit_repo. + + IF mv_init = abap_false OR mv_only_favorites = abap_true. + refresh_all( ). + ENDIF. + + LOOP AT mt_list INTO li_repo. + IF iv_offline = abap_undefined OR li_repo->is_offline( ) = iv_offline. + INSERT li_repo INTO TABLE rt_list. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~list_favorites. + + DATA lt_user_favorites TYPE zif_abapgit_persist_user=>ty_favorites. + DATA li_repo TYPE REF TO zif_abapgit_repo. + + lt_user_favorites = zcl_abapgit_persist_factory=>get_user( )->get_favorites( ). + SORT lt_user_favorites BY table_line. + + IF mv_init = abap_false OR mv_only_favorites = abap_false. + refresh_favorites( ). + ENDIF. + + LOOP AT mt_list INTO li_repo. + READ TABLE lt_user_favorites + TRANSPORTING NO FIELDS + WITH KEY table_line = li_repo->get_key( ). + IF sy-subrc = 0 AND ( iv_offline = abap_undefined OR li_repo->is_offline( ) = iv_offline ). + APPEND li_repo TO rt_list. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~new_offline. + + DATA: ls_repo TYPE zif_abapgit_persistence=>ty_repo, + lv_key TYPE zif_abapgit_persistence=>ty_repo-key, + lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit. + IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-create_repo ) = abap_false. + zcx_abapgit_exception=>raise( 'Not authorized' ). + ENDIF. + + zif_abapgit_repo_srv~validate_package( + iv_package = iv_package + iv_ign_subpkg = iv_ign_subpkg ). + + IF iv_name IS INITIAL. + zcx_abapgit_exception=>raise( 'Missing name for repository' ). + ENDIF. + + " Repo Settings + lo_dot_abapgit = zcl_abapgit_dot_abapgit=>build_default( ). + lo_dot_abapgit->set_folder_logic( iv_folder_logic ). + lo_dot_abapgit->set_name( iv_name ). + lo_dot_abapgit->set_abap_language_version( iv_abap_lang_vers ). + + lv_key = zcl_abapgit_persist_factory=>get_repo( )->add( + iv_package = iv_package + iv_offline = abap_true + is_dot_abapgit = lo_dot_abapgit->get_data( ) ). + + TRY. + ls_repo = zcl_abapgit_persist_factory=>get_repo( )->read( lv_key ). + CATCH zcx_abapgit_not_found. + zcx_abapgit_exception=>raise( 'new_offline not found' ). + ENDTRY. + + ri_repo = instantiate_and_add( ls_repo ). + + " Local Settings + IF ls_repo-local_settings-ignore_subpackages <> iv_ign_subpkg. + ls_repo-local_settings-ignore_subpackages = iv_ign_subpkg. + ENDIF. + ls_repo-local_settings-main_language_only = iv_main_lang_only. + ls_repo-local_settings-labels = iv_labels. + + ri_repo->set_local_settings( ls_repo-local_settings ). + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~new_online. + + DATA: ls_repo TYPE zif_abapgit_persistence=>ty_repo, + lv_branch_name LIKE iv_branch_name, + lv_key TYPE zif_abapgit_persistence=>ty_repo-key, + lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit, + lv_url TYPE string. + ASSERT NOT iv_url IS INITIAL + AND NOT iv_package IS INITIAL. + + lv_url = condense( iv_url ). + + IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-create_repo ) = abap_false. + zcx_abapgit_exception=>raise( 'Not authorized' ). + ENDIF. + + zif_abapgit_repo_srv~validate_package( + iv_package = iv_package + iv_ign_subpkg = iv_ign_subpkg ). + + zif_abapgit_repo_srv~validate_url( lv_url ). + + lv_branch_name = determine_branch_name( + iv_name = iv_branch_name + iv_url = lv_url ). + + " New repos without any commits do not have a branch yet + IF lv_branch_name IS INITIAL. + lv_branch_name = create_initial_branch( lv_url ). + + lv_branch_name = determine_branch_name( + iv_name = lv_branch_name + iv_url = lv_url ). + ENDIF. + + " Repo Settings + lo_dot_abapgit = zcl_abapgit_dot_abapgit=>build_default( ). + lo_dot_abapgit->set_folder_logic( iv_folder_logic ). + lo_dot_abapgit->set_name( iv_name ). + lo_dot_abapgit->set_abap_language_version( iv_abap_lang_vers ). + + lv_key = zcl_abapgit_persist_factory=>get_repo( )->add( + iv_url = lv_url + iv_branch_name = lv_branch_name " local ! + iv_display_name = iv_display_name + iv_package = iv_package + iv_offline = abap_false + is_dot_abapgit = lo_dot_abapgit->get_data( ) ). + + TRY. + ls_repo = zcl_abapgit_persist_factory=>get_repo( )->read( lv_key ). + CATCH zcx_abapgit_not_found. + zcx_abapgit_exception=>raise( 'new_online not found' ). + ENDTRY. + + ri_repo = instantiate_and_add( ls_repo ). + + " Local Settings + IF ls_repo-local_settings-ignore_subpackages <> iv_ign_subpkg. + ls_repo-local_settings-ignore_subpackages = iv_ign_subpkg. + ENDIF. + ls_repo-local_settings-main_language_only = iv_main_lang_only. + ls_repo-local_settings-labels = iv_labels. + + ri_repo->set_local_settings( ls_repo-local_settings ). + + ri_repo->refresh( ). + ri_repo->find_remote_dot_abapgit( ). + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~purge. + +* uninstalls all objects, no UI or popups in this class + +* todo, this should be a method on the repo instead? + + DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA: lx_error TYPE REF TO zcx_abapgit_exception. + + ri_log = ii_repo->create_new_log( 'Uninstall Log' ). + + IF ii_repo->get_local_settings( )-write_protected = abap_true. + zcx_abapgit_exception=>raise( 'Cannot purge. Local code is write-protected by repo config' ). + ELSEIF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-uninstall ) = abap_false. + zcx_abapgit_exception=>raise( 'Not authorized' ). + ENDIF. + + lt_tadir = ii_repo->get_tadir_objects( ). + + TRY. + zcl_abapgit_objects=>delete( it_tadir = lt_tadir + is_checks = is_checks + ii_log = ri_log ). + CATCH zcx_abapgit_exception INTO lx_error. + " If uninstall fails, repo needs a refresh to show which objects where deleted and which not + ii_repo->refresh( iv_drop_log = abap_false ). + RAISE EXCEPTION lx_error. + ENDTRY. + + IF iv_keep_repo = abap_true. + ii_repo->refresh( ). + ii_repo->checksums( )->rebuild( ). + ELSE. + zif_abapgit_repo_srv~delete( ii_repo ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~validate_package. + + DATA: lv_as4user TYPE usnam, + li_repo TYPE REF TO zif_abapgit_repo, + lv_reason TYPE string. + + zcl_abapgit_factory=>get_sap_package( iv_package )->validate_name( ). + + " Check if package owned by SAP is allowed (new packages are ok, since they are created automatically) + lv_as4user = zcl_abapgit_factory=>get_sap_package( iv_package )->read_responsible( ). + + IF sy-subrc = 0 AND lv_as4user = 'SAP' AND + zcl_abapgit_factory=>get_environment( )->is_sap_object_allowed( ) = abap_false. + zcx_abapgit_exception=>raise( |Package { iv_package } not allowed, responsible user = 'SAP'| ). + ENDIF. + + " Check if package is already used in another repo + IF iv_chk_exists = abap_true. + zif_abapgit_repo_srv~get_repo_from_package( + EXPORTING + iv_package = iv_package + iv_ign_subpkg = iv_ign_subpkg + IMPORTING + ei_repo = li_repo + ev_reason = lv_reason ). + + IF li_repo IS BOUND. + zcx_abapgit_exception=>raise( lv_reason ). + ENDIF. + ENDIF. + + " Check if package hierarchy is a mix of transportable and local packages + validate_package_korrflag( + iv_package = iv_package + iv_ign_subpkg = iv_ign_subpkg ). + + ENDMETHOD. + METHOD zif_abapgit_repo_srv~validate_url. + + DATA: + li_repo TYPE REF TO zif_abapgit_repo, + lv_reason TYPE string. + + zcl_abapgit_url=>validate( iv_url ). + + IF iv_chk_exists = abap_true. + zif_abapgit_repo_srv~get_repo_from_url( + EXPORTING + iv_url = iv_url + IMPORTING + ei_repo = li_repo + ev_reason = lv_reason ). + IF li_repo IS BOUND. + zcx_abapgit_exception=>raise( lv_reason ). + ENDIF. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_online IMPLEMENTATION. + METHOD constructor. + + super->constructor( is_data ). + + ENDMETHOD. + METHOD fetch_remote. + + DATA: li_progress TYPE REF TO zif_abapgit_progress, + ls_pull TYPE zcl_abapgit_git_porcelain=>ty_pull_result. + + IF mv_request_remote_refresh = abap_false. + RETURN. + ENDIF. + + li_progress = zcl_abapgit_progress=>get_instance( 1 ). + + li_progress->show( iv_current = 1 + iv_text = 'Fetch remote files' ). + + IF get_selected_commit( ) IS INITIAL. + ls_pull = zcl_abapgit_git_porcelain=>pull_by_branch( iv_url = get_url( ) + iv_branch_name = get_selected_branch( ) ). + ELSE. + ls_pull = zcl_abapgit_git_porcelain=>pull_by_commit( iv_url = get_url( ) + iv_commit_hash = get_selected_commit( ) ). + ENDIF. + + set_files_remote( ls_pull-files ). + set_objects( ls_pull-objects ). + mv_current_commit = ls_pull-commit. + + ENDMETHOD. + METHOD get_objects. + fetch_remote( ). + rt_objects = mt_objects. + ENDMETHOD. + METHOD handle_stage_ignore. + + DATA: lv_add TYPE abap_bool, + lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit, + lt_stage TYPE zif_abapgit_definitions=>ty_stage_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_stage. + lo_dot_abapgit = get_dot_abapgit( ). + lt_stage = io_stage->get_all( ). + LOOP AT lt_stage ASSIGNING WHERE method = zif_abapgit_definitions=>c_method-ignore. + + lo_dot_abapgit->add_ignore( + iv_path = -file-path + iv_filename = -file-filename ). + + " remove it from the staging object, as the action is handled here + io_stage->reset( iv_path = -file-path + iv_filename = -file-filename ). + + lv_add = abap_true. + + ENDLOOP. + + IF lv_add = abap_true. + io_stage->add( + iv_path = zif_abapgit_definitions=>c_root_dir + iv_filename = zif_abapgit_definitions=>c_dot_abapgit + iv_data = lo_dot_abapgit->serialize( ) ). + + set_dot_abapgit( lo_dot_abapgit ). + ENDIF. + + ENDMETHOD. + METHOD raise_error_if_branch_exists. + + DATA: + lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, + lv_display_name TYPE string. + + lt_branches = zcl_abapgit_git_factory=>get_git_transport( + )->branches( get_url( ) + )->get_branches_only( ). + + READ TABLE lt_branches WITH TABLE KEY name_key + COMPONENTS name = iv_name + TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + lv_display_name = zcl_abapgit_git_branch_utils=>get_display_name( iv_name ). + zcx_abapgit_exception=>raise( |Branch '{ lv_display_name }' already exists| ). + ENDIF. + + ENDMETHOD. + METHOD set_objects. + mt_objects = it_objects. + ENDMETHOD. + METHOD zif_abapgit_repo_online~check_for_valid_branch. + + DATA: + li_branch_list TYPE REF TO zif_abapgit_git_branch_list, + lx_error TYPE REF TO zcx_abapgit_exception, + lv_branch TYPE string, + lv_head TYPE string, + lv_msg TYPE string. + + lv_branch = get_selected_branch( ). + + IF lv_branch IS NOT INITIAL. + li_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( get_url( ) ). + + TRY. + li_branch_list->find_by_name( lv_branch ). + CATCH zcx_abapgit_exception INTO lx_error. + " branch does not exist, fallback to head + lv_head = li_branch_list->get_head_symref( ). + lv_msg = |{ lx_error->get_text( ) }. Switched to { zcl_abapgit_git_branch_utils=>get_display_name( lv_head ) }|. + MESSAGE lv_msg TYPE 'S'. + select_branch( lv_head ). + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo_online~create_branch. + + DATA: lv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1. + + ASSERT iv_name CP zif_abapgit_git_definitions=>c_git_branch-heads. + + IF iv_from IS INITIAL. + lv_sha1 = get_current_remote( ). + ELSE. + lv_sha1 = iv_from. + ENDIF. + + raise_error_if_branch_exists( iv_name ). + + zcl_abapgit_git_porcelain=>create_branch( + iv_url = get_url( ) + iv_name = iv_name + iv_from = lv_sha1 ). + + " automatically switch to new branch + select_branch( iv_name ). + + ENDMETHOD. + METHOD zif_abapgit_repo_online~get_current_remote. + fetch_remote( ). + rv_sha1 = mv_current_commit. + ENDMETHOD. + METHOD zif_abapgit_repo_online~get_remote_settings. + + DATA lv_branch TYPE string. + + rs_settings-url = get_url( ). + rs_settings-offline = abap_false. + rs_settings-switched_origin = get_switched_origin( ). + + IF get_selected_commit( ) IS NOT INITIAL. + rs_settings-commit = get_selected_commit( ). + rs_settings-branch = get_selected_branch( ). + rs_settings-head_type = zif_abapgit_git_definitions=>c_head_types-commit. + ELSEIF get_switched_origin( ) IS NOT INITIAL. + " get_switched_origin( ) returns the original repo url + HEAD concatenated with @ + " get_branch( ) returns the branch of the PR in the source repo + " get_url( ) returns the source repo of the PR branch + + rs_settings-switched_origin = get_switched_origin( ). + SPLIT rs_settings-switched_origin AT '@' INTO rs_settings-url rs_settings-branch. + IF rs_settings-branch CP zif_abapgit_git_definitions=>c_git_branch-tags. + rs_settings-tag = rs_settings-branch. + CLEAR rs_settings-branch. + ENDIF. + + lv_branch = get_selected_branch( ). + REPLACE FIRST OCCURRENCE OF zif_abapgit_git_definitions=>c_git_branch-heads_prefix IN lv_branch WITH space. + CONDENSE lv_branch. + rs_settings-pull_request = |{ get_url( ) }@{ lv_branch }|. + rs_settings-head_type = zif_abapgit_git_definitions=>c_head_types-pull_request. + ELSE. + rs_settings-branch = get_selected_branch( ). + rs_settings-head_type = zif_abapgit_git_definitions=>c_head_types-branch. + + IF rs_settings-branch CP zif_abapgit_git_definitions=>c_git_branch-tags. + rs_settings-head_type = zif_abapgit_git_definitions=>c_head_types-tag. + rs_settings-tag = rs_settings-branch. + CLEAR rs_settings-branch. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo_online~get_selected_branch. + rv_name = ms_data-branch_name. + ENDMETHOD. + METHOD zif_abapgit_repo_online~get_selected_commit. + rv_selected_commit = ms_data-selected_commit. + ENDMETHOD. + METHOD zif_abapgit_repo_online~get_switched_origin. + rv_switched_origin = ms_data-switched_origin. + ENDMETHOD. + METHOD zif_abapgit_repo_online~get_url. + rv_url = ms_data-url. + ENDMETHOD. + METHOD zif_abapgit_repo_online~push. + +* assumption: PUSH is done on top of the currently selected branch + + DATA: ls_push TYPE zcl_abapgit_git_porcelain=>ty_push_result, + lv_text TYPE string, + lv_parent TYPE zif_abapgit_git_definitions=>ty_sha1. + IF ms_data-branch_name CP zif_abapgit_git_definitions=>c_git_branch-tags. + lv_text = |You're working on a tag. Currently it's not | + && |possible to push on tags. Consider creating a branch instead|. + zcx_abapgit_exception=>raise( lv_text ). + ENDIF. + + IF ms_data-selected_commit IS NOT INITIAL. + lv_text = 'You are currently checked out in a commit.'. + lv_text = |{ lv_text } You must be on a branch to push|. + zcx_abapgit_exception=>raise( lv_text ). + ENDIF. + + IF ms_data-local_settings-block_commit = abap_true + AND zcl_abapgit_code_inspector=>get_code_inspector( get_package( ) + )->is_successful( ) = abap_false. + zcx_abapgit_exception=>raise( |A successful code inspection is required| ). + ENDIF. + + handle_stage_ignore( io_stage ). + + IF get_selected_commit( ) IS INITIAL. + lv_parent = get_current_remote( ). + ELSE. + lv_parent = get_selected_commit( ). + ENDIF. + + ls_push = zcl_abapgit_git_porcelain=>push( + is_comment = is_comment + io_stage = io_stage + iv_branch_name = get_selected_branch( ) + iv_url = get_url( ) + iv_parent = lv_parent + it_old_objects = get_objects( ) ). + + set_objects( ls_push-new_objects ). + set_files_remote( ls_push-new_files ). + + mv_current_commit = ls_push-branch. + + checksums( )->update( ls_push-updated_files ). + + ENDMETHOD. + METHOD zif_abapgit_repo_online~select_branch. + + reset_remote( ). + set( iv_branch_name = iv_branch_name + iv_selected_commit = space ). + + ENDMETHOD. + METHOD zif_abapgit_repo_online~select_commit. + + reset_remote( ). + set( iv_selected_commit = iv_selected_commit ). + + ENDMETHOD. + METHOD zif_abapgit_repo_online~set_url. + + reset_remote( ). + set( iv_url = iv_url ). + + ENDMETHOD. + METHOD zif_abapgit_repo_online~switch_origin. + + DATA lv_offs TYPE i. + + " For repo settings page + IF iv_overwrite = abap_true. + set( iv_switched_origin = iv_url ). + RETURN. + ENDIF. + + IF iv_url IS INITIAL. + IF ms_data-switched_origin IS INITIAL. + RETURN. + ELSE. + lv_offs = find( + val = reverse( ms_data-switched_origin ) + sub = '@' ). + IF lv_offs = -1. + zcx_abapgit_exception=>raise( 'Incorrect format of switched origin' ). + ENDIF. + lv_offs = strlen( ms_data-switched_origin ) - lv_offs - 1. + set_url( substring( + val = ms_data-switched_origin + len = lv_offs ) ). + select_branch( substring( + val = ms_data-switched_origin + off = lv_offs + 1 ) ). + set( iv_switched_origin = '' ). + ENDIF. + ELSEIF ms_data-switched_origin IS INITIAL. + set( iv_switched_origin = ms_data-url && '@' && ms_data-branch_name ). + set_url( iv_url ). + select_branch( iv_branch ). + ELSE. + zcx_abapgit_exception=>raise( 'Cannot switch origin twice' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo~get_files_remote. + fetch_remote( ). + rt_files = super->get_files_remote( + ii_obj_filter = ii_obj_filter + iv_ignore_files = iv_ignore_files ). + ENDMETHOD. + METHOD zif_abapgit_repo~get_name. + rv_name = super->get_name( ). + IF rv_name IS INITIAL. + TRY. + rv_name = zcl_abapgit_url=>name( ms_data-url ). + rv_name = cl_http_utility=>unescape_url( rv_name ). + CATCH zcx_abapgit_exception. + rv_name = 'New online repo'. "unlikely fallback + ENDTRY. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_repo~has_remote_source. + rv_yes = abap_true. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_offline IMPLEMENTATION. + METHOD reset_remote. + + DATA lt_backup LIKE mt_remote. + + " online repo has online source to renew data from, offline does not + " so offline repo preserves the remote + " in case of partial pull failure the user will immediately see the new difference + " UI will detect "pullable" content based on mt_status + " in the uniform way both for online and offline repos + " for more details see discussion in 2096 and 1953 + + lt_backup = mt_remote. + super->reset_remote( ). + set_files_remote( lt_backup ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_REPO_CS_MIGRATION IMPLEMENTATION. + METHOD clear_repo_metadata. + + DATA lo_repo_persistence TYPE REF TO zcl_abapgit_persistence_repo. + + lo_repo_persistence ?= zcl_abapgit_persist_factory=>get_repo( ). + lo_repo_persistence->rewrite_repo_meta( iv_repo_key ). + + ENDMETHOD. + METHOD convert_checksums. + + DATA lo_cs TYPE REF TO zcl_abapgit_repo_checksums. + DATA lv_xml TYPE zif_abapgit_persistence=>ty_content-data_str. + DATA: + BEGIN OF ls_repo_extract, + local_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt, + END OF ls_repo_extract. + + lv_xml = zcl_abapgit_persistence_db=>get_instance( )->read( + iv_type = zcl_abapgit_persistence_db=>c_type_repo + iv_value = iv_repo_key ). + + REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_REPO_--29>' IN lv_xml WITH ''. + REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. + + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML lv_xml + RESULT repo = ls_repo_extract. + + IF lines( ls_repo_extract-local_checksums ) = 0. + RETURN. + ENDIF. + + CREATE OBJECT lo_cs EXPORTING iv_repo_key = iv_repo_key. + lo_cs->force_write( ls_repo_extract-local_checksums ). + + ENDMETHOD. + METHOD get_unconverted_repo_ids. + + DATA lt_cs_ids TYPE ty_repo_ids. + DATA lv_repo_id LIKE LINE OF rt_repo_ids. + DATA lv_index TYPE i. + + SELECT value FROM (zcl_abapgit_persistence_db=>c_tabname) + INTO TABLE rt_repo_ids + WHERE type = zcl_abapgit_persistence_db=>c_type_repo. + SELECT value FROM (zcl_abapgit_persistence_db=>c_tabname) + INTO TABLE lt_cs_ids + WHERE type = zcl_abapgit_persistence_db=>c_type_repo_csum. + + LOOP AT rt_repo_ids INTO lv_repo_id. + lv_index = sy-tabix. + READ TABLE lt_cs_ids TRANSPORTING NO FIELDS WITH KEY table_line = lv_repo_id. + IF sy-subrc = 0. " Already converted + DELETE rt_repo_ids INDEX lv_index. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD run. + + DATA lt_repo_ids TYPE ty_repo_ids. + DATA lv_repo_id LIKE LINE OF lt_repo_ids. + + lt_repo_ids = get_unconverted_repo_ids( ). + + LOOP AT lt_repo_ids INTO lv_repo_id. + convert_checksums( lv_repo_id ). + clear_repo_metadata( lv_repo_id ). + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_content_list IMPLEMENTATION. + METHOD build_folders. + + DATA: lv_index TYPE i, + lt_subitems LIKE ct_repo_items, + ls_subitem LIKE LINE OF ct_repo_items, + ls_folder LIKE LINE OF ct_repo_items. + + DATA lo_state TYPE REF TO zcl_abapgit_repo_item_state. + + FIELD-SYMBOLS LIKE LINE OF ct_repo_items. + LOOP AT ct_repo_items ASSIGNING . + lv_index = sy-tabix. + CHECK -path <> iv_cur_dir. " files in target dir - just leave them be + + IF zcl_abapgit_path=>is_subdir( iv_path = -path + iv_parent = iv_cur_dir ) = abap_true. + ls_subitem-changes = -changes. + ls_subitem-path = -path. + ls_subitem-lstate = -lstate. + ls_subitem-rstate = -rstate. + APPEND ls_subitem TO lt_subitems. + ENDIF. + + DELETE ct_repo_items INDEX lv_index. + ENDLOOP. + + SORT lt_subitems BY path ASCENDING. + + LOOP AT lt_subitems ASSIGNING . + AT NEW path. + CLEAR ls_folder. + ls_folder-path = -path. + ls_folder-sortkey = c_sortkey-dir. " Directory + ls_folder-is_dir = abap_true. + CREATE OBJECT lo_state. + ENDAT. + + ls_folder-changes = ls_folder-changes + -changes. + lo_state->sum_with_repo_item( ). + + AT END OF path. + ls_folder-lstate = lo_state->local( ). + ls_folder-rstate = lo_state->remote( ). + APPEND ls_folder TO ct_repo_items. + ENDAT. + ENDLOOP. + + ENDMETHOD. + METHOD build_repo_items. + + DATA: + lo_state TYPE REF TO zcl_abapgit_repo_item_state, + ls_file TYPE zif_abapgit_definitions=>ty_repo_file, + lt_status TYPE zif_abapgit_definitions=>ty_results_tt, + ls_item TYPE zif_abapgit_definitions=>ty_item, + ls_previous LIKE ls_item, + lv_changed_by TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF lt_status, + LIKE LINE OF rt_repo_items. + lt_status = zcl_abapgit_repo_status=>calculate( + ii_repo = mi_repo + ii_log = mi_log ). + + LOOP AT lt_status ASSIGNING . + AT NEW obj_name. "obj_type + obj_name + APPEND INITIAL LINE TO rt_repo_items ASSIGNING . + -obj_type = -obj_type. + -obj_name = -obj_name. + -inactive = -inactive. + -sortkey = c_sortkey-default. " Default sort key + -changes = 0. + -path = -path. + -srcsystem = -srcsystem. + CREATE OBJECT lo_state. + ENDAT. + + IF -filename IS NOT INITIAL. + MOVE-CORRESPONDING TO ls_file. + ls_file-is_changed = boolc( -match = abap_false ). " TODO refactor + APPEND ls_file TO -files. + + IF -inactive = abap_true AND -sortkey > c_sortkey-changed. + -sortkey = c_sortkey-inactive. + ENDIF. + + IF ls_file-is_changed = abap_true. + -sortkey = c_sortkey-changed. " Changed files + -changes = -changes + 1. + lo_state->sum_with_status_item( ). + ENDIF. + ENDIF. + + IF -changes > 0 AND -obj_type IS NOT INITIAL. + MOVE-CORRESPONDING TO ls_item. + IF ls_previous = ls_item. + -changed_by = lv_changed_by. + ELSEIF zcl_abapgit_objects=>exists( ls_item ) = abap_true. + -changed_by = zcl_abapgit_objects=>changed_by( ls_item ). + ls_previous = ls_item. + lv_changed_by = -changed_by. + ENDIF. + CLEAR ls_item. + ENDIF. + + AT END OF obj_name. "obj_type + obj_name + IF -obj_type IS INITIAL. + -sortkey = c_sortkey-orphan. "Virtual objects + ENDIF. + -lstate = lo_state->local( ). + -rstate = lo_state->remote( ). + -packmove = lo_state->is_reassigned( ). + ENDAT. + ENDLOOP. + + ENDMETHOD. + METHOD check_repo_size. + + CONSTANTS lc_new_repo_size TYPE i VALUE 10. + + DATA lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt. + + lt_remote = mi_repo->get_files_remote( ). + + IF lines( lt_remote ) > lc_new_repo_size. + " Less files means it's a new repo (with just readme and license, for example) which is ok + READ TABLE lt_remote TRANSPORTING NO FIELDS + WITH KEY file_path + COMPONENTS path = zif_abapgit_definitions=>c_root_dir + filename = zif_abapgit_definitions=>c_dot_abapgit. + IF sy-subrc <> 0. + mi_log->add_warning( |Cannot find .abapgit.xml - Is this an abapGit repository?| ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD constructor. + mi_repo = ii_repo. + CREATE OBJECT mi_log TYPE zcl_abapgit_log. + ENDMETHOD. + METHOD determine_transports. + + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + + FIELD-SYMBOLS LIKE LINE OF ct_repo_items. + + LOOP AT ct_repo_items ASSIGNING . + ls_item-obj_type = -obj_type. + ls_item-obj_name = -obj_name. + TRY. + -transport = zcl_abapgit_factory=>get_cts_api( )->get_transport_for_object( ls_item ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + " Ignore errors related to object check when trying to get transport + ENDTRY. + ENDLOOP. + + ENDMETHOD. + METHOD filter_changes. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_repo_item. + + DELETE ct_repo_items WHERE changes = 0 AND inactive = abap_false. + LOOP AT ct_repo_items ASSIGNING WHERE inactive = abap_false. + DELETE -files WHERE is_changed = abap_false. + ENDLOOP. + ENDMETHOD. + METHOD get_log. + DATA li_repo_log TYPE REF TO zif_abapgit_log. + DATA lt_repo_msg TYPE zif_abapgit_log=>ty_log_outs. + DATA lr_repo_msg TYPE REF TO zif_abapgit_log=>ty_log_out. + + ri_log = mi_log. + + "add warning and error messages from repo log + li_repo_log = mi_repo->get_log( ). + IF li_repo_log IS BOUND. + lt_repo_msg = li_repo_log->get_messages( ). + LOOP AT lt_repo_msg REFERENCE INTO lr_repo_msg WHERE type CA 'EW'. + CASE lr_repo_msg->type. + WHEN 'E'. + ri_log->add_error( lr_repo_msg->text ). + WHEN 'W'. + ri_log->add_warning( lr_repo_msg->text ). + WHEN OTHERS. + CONTINUE. + ENDCASE. + ENDLOOP. + ENDIF. + ENDMETHOD. + METHOD list. + + FIELD-SYMBOLS LIKE LINE OF rt_repo_items. + + mi_log->clear( ). + + rt_repo_items = build_repo_items( ). + check_repo_size( ). + + IF mi_repo->has_remote_source( ) = abap_false. + " If there's no remote source, ignore the item state + LOOP AT rt_repo_items ASSIGNING . + CLEAR: -changes, -lstate, -rstate. + ENDLOOP. + ENDIF. + + IF iv_by_folders = abap_true. + build_folders( + EXPORTING iv_cur_dir = iv_path + CHANGING ct_repo_items = rt_repo_items ). + ENDIF. + + IF iv_changes_only = abap_true. + " There are never changes for offline repositories + filter_changes( CHANGING ct_repo_items = rt_repo_items ). + ENDIF. + + IF iv_transports = abap_true. + determine_transports( CHANGING ct_repo_items = rt_repo_items ). + ENDIF. + + SORT rt_repo_items BY + sortkey ASCENDING + path ASCENDING + obj_name ASCENDING. + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlIAZUQfihQNtbCZJmgPrpXDFKn DEFINITION DEFERRED. +CLASS kHGwlIAZUQfihQNtbCZJXaTWQDiHod DEFINITION DEFERRED. +CLASS kHGwlIAZUQfihQNtbCZJprVxXPzzzh DEFINITION DEFERRED. +* renamed: zcl_abapgit_repo_checksums :: lcl_checksum_serializer +CLASS kHGwlIAZUQfihQNtbCZJprVxXPzzzh DEFINITION + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + CONSTANTS c_splitter TYPE string VALUE `|`. + CONSTANTS c_root TYPE string VALUE `@`. + + CLASS-METHODS serialize + IMPORTING + it_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt + RETURNING + VALUE(rv_string) TYPE string. + + CLASS-METHODS deserialize + IMPORTING + iv_string TYPE string + RETURNING + VALUE(rt_checksums) TYPE zif_abapgit_persistence=>ty_local_checksum_tt. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. + +CLASS kHGwlIAZUQfihQNtbCZJprVxXPzzzh IMPLEMENTATION. + METHOD deserialize. + + DATA lt_buf_tab TYPE string_table. + DATA lv_buf TYPE string. + DATA lt_checksums LIKE rt_checksums. + + FIELD-SYMBOLS LIKE LINE OF lt_checksums. + FIELD-SYMBOLS LIKE LINE OF -files. + + SPLIT iv_string AT |\n| INTO TABLE lt_buf_tab. + + LOOP AT lt_buf_tab INTO lv_buf. + CHECK lv_buf IS NOT INITIAL. " In fact this is a bug ... it cannot be empty, maybe raise + + IF lv_buf+0(1) = '/'. + IF IS NOT ASSIGNED. + " Incorrect checksums structure, maybe raise, though it is not critical for execution + RETURN. + ENDIF. + + APPEND INITIAL LINE TO -files ASSIGNING . + SPLIT lv_buf AT c_splitter INTO -path -filename -sha1. + + IF -path IS INITIAL OR -filename IS INITIAL OR -sha1 IS INITIAL. + " Incorrect checksums structure, maybe raise, though it is not critical for execution + RETURN. + ENDIF. + ELSEIF lv_buf = c_root. " Root + APPEND INITIAL LINE TO lt_checksums ASSIGNING . " Empty item + ELSE. + APPEND INITIAL LINE TO lt_checksums ASSIGNING . + SPLIT lv_buf AT c_splitter INTO -item-obj_type -item-obj_name -item-devclass. + + IF -item-obj_type IS INITIAL OR -item-obj_name IS INITIAL OR -item-devclass IS INITIAL. + " Incorrect checksums structure, maybe raise, though it is not critical for execution + RETURN. + ENDIF. + + ENDIF. + ENDLOOP. + + rt_checksums = lt_checksums. + + ENDMETHOD. + METHOD serialize. + + DATA lt_buf_tab TYPE string_table. + DATA lv_buf TYPE string. + DATA lt_checksums_sorted TYPE zif_abapgit_persistence=>ty_local_checksum_by_item_tt. + + FIELD-SYMBOLS LIKE LINE OF it_checksums. + FIELD-SYMBOLS LIKE LINE OF -files. + + lt_checksums_sorted = it_checksums. + + LOOP AT lt_checksums_sorted ASSIGNING . + + IF lines( -files ) = 0. + CONTINUE. + ENDIF. + + IF -item-obj_type IS NOT INITIAL. + CONCATENATE -item-obj_type -item-obj_name -item-devclass + INTO lv_buf + SEPARATED BY c_splitter. + ELSE. + lv_buf = c_root. + ENDIF. + APPEND lv_buf TO lt_buf_tab. + + LOOP AT -files ASSIGNING . + + CONCATENATE -path -filename -sha1 + INTO lv_buf + SEPARATED BY c_splitter. + APPEND lv_buf TO lt_buf_tab. + + ENDLOOP. + + ENDLOOP. + + rv_string = concat_lines_of( + table = lt_buf_tab + sep = |\n| ). + + ENDMETHOD. +ENDCLASS. + +********************************************************************** +* UPDATE CALCULATOR +********************************************************************** + +* renamed: zcl_abapgit_repo_checksums :: lcl_update_calculator +CLASS kHGwlIAZUQfihQNtbCZJXaTWQDiHod DEFINITION + FINAL + CREATE PUBLIC. + PUBLIC SECTION. + + CLASS-METHODS calculate_updated + IMPORTING + it_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt + it_current_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt + it_local_files TYPE zif_abapgit_definitions=>ty_files_item_tt + RETURNING + VALUE(rt_checksums) TYPE zif_abapgit_persistence=>ty_local_checksum_tt. + + PRIVATE SECTION. + + CLASS-METHODS process_updated_files + CHANGING + ct_update_index TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts + ct_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_by_item_tt. + + CLASS-METHODS add_new_files + IMPORTING + it_local TYPE zif_abapgit_definitions=>ty_files_item_tt + it_update_index TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts + CHANGING + ct_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_by_item_tt. + +ENDCLASS. + +CLASS kHGwlIAZUQfihQNtbCZJXaTWQDiHod IMPLEMENTATION. + + METHOD calculate_updated. + + DATA lt_update_index TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts. + DATA lt_checksums_sorted TYPE zif_abapgit_persistence=>ty_local_checksum_by_item_tt. + + lt_checksums_sorted = it_current_checksums. + lt_update_index = it_updated_files. + + process_updated_files( + CHANGING + ct_update_index = lt_update_index + ct_checksums = lt_checksums_sorted ). + + add_new_files( + EXPORTING + it_update_index = lt_update_index + it_local = it_local_files + CHANGING + ct_checksums = lt_checksums_sorted ). + + rt_checksums = lt_checksums_sorted. + + ENDMETHOD. + + METHOD process_updated_files. + + DATA lv_cs_row TYPE i. + DATA lv_file_row TYPE i. + + FIELD-SYMBOLS LIKE LINE OF ct_checksums. + FIELD-SYMBOLS LIKE LINE OF -files. + FIELD-SYMBOLS LIKE LINE OF ct_update_index. + + " Loop through current checksum state, update sha1 for common files + + LOOP AT ct_checksums ASSIGNING . + lv_cs_row = sy-tabix. + + LOOP AT -files ASSIGNING . + lv_file_row = sy-tabix. + + READ TABLE ct_update_index ASSIGNING + WITH KEY + path = -path + filename = -filename. + IF sy-subrc <> 0. + CONTINUE. " Missing in updated files -> nothing to update, skip + ENDIF. + + IF -sha1 IS INITIAL. " Empty input sha1 is a deletion marker + DELETE -files INDEX lv_file_row. + ELSE. + -sha1 = -sha1. " Update sha1 + CLEAR -sha1. " Mark as processed + ENDIF. + ENDLOOP. + + IF lines( -files ) = 0. " Remove empty objects + DELETE ct_checksums INDEX lv_cs_row. + ENDIF. + ENDLOOP. + + DELETE ct_update_index WHERE sha1 IS INITIAL. " Remove processed + + ENDMETHOD. + + METHOD add_new_files. + + DATA lt_local_sorted TYPE zif_abapgit_definitions=>ty_files_item_by_file_tt. + DATA ls_checksum LIKE LINE OF ct_checksums. + FIELD-SYMBOLS LIKE LINE OF ct_checksums. + FIELD-SYMBOLS LIKE LINE OF it_update_index. + FIELD-SYMBOLS LIKE LINE OF lt_local_sorted. + + lt_local_sorted = it_local. + + " Add new files - not deleted and not marked as processed + LOOP AT it_update_index ASSIGNING . + + READ TABLE lt_local_sorted ASSIGNING + WITH KEY + file-path = -path + file-filename = -filename. + IF sy-subrc <> 0. + " The file should be in locals, however: + " if the deserialization fails, the local file might not be there + " in this case no new CS added, and the file will appear to be remote+new + CONTINUE. + ENDIF. + + READ TABLE ct_checksums ASSIGNING + WITH KEY + item-obj_type = -item-obj_type + item-obj_name = -item-obj_name. + IF sy-subrc <> 0. + MOVE-CORRESPONDING -item TO ls_checksum-item. + INSERT ls_checksum INTO TABLE ct_checksums ASSIGNING . + ENDIF. + + APPEND TO -files. + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. +* renamed: zcl_abapgit_repo_checksums :: lcl_filter +CLASS kHGwlIAZUQfihQNtbCZJmgPrpXDFKn DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_object_filter. + + METHODS constructor + IMPORTING + it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + + PRIVATE SECTION. + DATA mt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. +ENDCLASS. + +CLASS kHGwlIAZUQfihQNtbCZJmgPrpXDFKn IMPLEMENTATION. + METHOD constructor. + mt_filter = it_filter. + SORT mt_filter. + DELETE ADJACENT DUPLICATES FROM mt_filter. + ENDMETHOD. + + METHOD zif_abapgit_object_filter~get_filter. + rt_filter = mt_filter. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_checksums IMPLEMENTATION. + METHOD add_meta. + + DATA lv_meta_str TYPE string. + + lv_meta_str = |#repo_name#{ mi_repo->get_name( ) }|. + + cv_cs_blob = lv_meta_str && |\n| && cv_cs_blob. + + ENDMETHOD. + METHOD build_checksums_from_files. + + DATA ls_last_item TYPE zif_abapgit_definitions=>ty_item. + + FIELD-SYMBOLS: + LIKE LINE OF rt_checksums, + LIKE LINE OF it_local, + LIKE LINE OF -files. + + " This method is run at repo creation moment or manually by user + " In the first case it assumes that the local state is the CURRENT state + " Thus the idea is to copy local state to checksums + " The second case is an exception, when we acknowledge that the state is unknown + " Thus copying the local to checksums is the "best guess" + + LOOP AT it_local ASSIGNING . + IF ls_last_item <> -item OR sy-tabix = 1. " First or New item reached ? + APPEND INITIAL LINE TO rt_checksums ASSIGNING . + MOVE-CORRESPONDING -item TO -item. + ls_last_item = -item. + ENDIF. + + APPEND INITIAL LINE TO -files ASSIGNING . + MOVE-CORRESPONDING -file TO . + + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + ASSERT iv_repo_key IS NOT INITIAL. + mv_repo_key = iv_repo_key. + mi_repo = zcl_abapgit_repo_srv=>get_instance( )->get( mv_repo_key ). + " Should be safe as repo_srv is supposed to be single source of repo instances + ENDMETHOD. + METHOD extract_meta. + + DATA lv_meta_str TYPE string. + + IF cv_cs_blob+0(1) <> '#'. + RETURN. " No meta ? just ignore it + ENDIF. + + SPLIT cv_cs_blob AT |\n| INTO lv_meta_str cv_cs_blob. + " Just remove the header meta string - this is OK for now. + " There is just repo name for the moment - needed to for DB util and potential debug + + ENDMETHOD. + METHOD force_write. + + " for migration only for the moment + + save_checksums( it_checksums ). + + ENDMETHOD. + METHOD get_latest_local_files. + + DATA: + lv_package TYPE devclass, + lo_dot TYPE REF TO zcl_abapgit_dot_abapgit, + ls_item TYPE zif_abapgit_definitions=>ty_item, + lo_filter TYPE REF TO kHGwlIAZUQfihQNtbCZJmgPrpXDFKn, + lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + + FIELD-SYMBOLS: + LIKE LINE OF it_updated_files, + LIKE LINE OF lt_filter. + + lo_dot = mi_repo->get_dot_abapgit( ). + lv_package = mi_repo->get_package( ). + + LOOP AT it_updated_files ASSIGNING . + + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = -filename + iv_path = -path + io_dot = lo_dot + iv_devclass = lv_package + IMPORTING + es_item = ls_item ). + + APPEND INITIAL LINE TO lt_filter ASSIGNING . + -object = ls_item-obj_type. + -obj_name = ls_item-obj_name. + ENDLOOP. + + CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. + + rt_files = mi_repo->get_files_local_filtered( lo_filter ). + + ENDMETHOD. + METHOD remove_non_code_related_files. + + DELETE ct_local_files + WHERE item IS INITIAL + AND NOT ( file-path = zif_abapgit_definitions=>c_root_dir + AND file-filename = zif_abapgit_definitions=>c_dot_abapgit ). + + ENDMETHOD. + METHOD save_checksums. + + DATA lv_cs_blob TYPE string. + + lv_cs_blob = kHGwlIAZUQfihQNtbCZJprVxXPzzzh=>serialize( it_checksums ). + add_meta( CHANGING cv_cs_blob = lv_cs_blob ). + zcl_abapgit_persist_factory=>get_repo_cs( )->update( + iv_key = mv_repo_key + iv_cs_blob = lv_cs_blob ). + + ENDMETHOD. + METHOD zif_abapgit_repo_checksums~get. + + DATA lv_cs_blob TYPE string. + + TRY. + lv_cs_blob = zcl_abapgit_persist_factory=>get_repo_cs( )->read( mv_repo_key ). + CATCH zcx_abapgit_exception zcx_abapgit_not_found. + " Ignore currently, it's not critical for execution, just return empty + RETURN. + ENDTRY. + + IF lv_cs_blob IS NOT INITIAL. + extract_meta( CHANGING cv_cs_blob = lv_cs_blob ). + rt_checksums = kHGwlIAZUQfihQNtbCZJprVxXPzzzh=>deserialize( lv_cs_blob ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo_checksums~get_checksums_per_file. + + DATA lt_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt. + FIELD-SYMBOLS LIKE LINE OF lt_checksums. + + lt_checksums = zif_abapgit_repo_checksums~get( ). + + LOOP AT lt_checksums ASSIGNING . + APPEND LINES OF -files TO rt_checksums. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_repo_checksums~rebuild. + + DATA lt_local TYPE ty_local_files_by_item_tt. + DATA lt_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt. + + lt_local = mi_repo->get_files_local( ). + remove_non_code_related_files( CHANGING ct_local_files = lt_local ). + + lt_checksums = build_checksums_from_files( lt_local ). + save_checksums( lt_checksums ). + + ENDMETHOD. + METHOD zif_abapgit_repo_checksums~update. + + DATA lt_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt. + DATA lt_local_files TYPE zif_abapgit_definitions=>ty_files_item_tt. + + lt_checksums = zif_abapgit_repo_checksums~get( ). + + " Checksum update does not need full repo serialized + " Getting the latest files of objects that changed is sufficient + lt_local_files = get_latest_local_files( it_updated_files ). + + lt_checksums = kHGwlIAZUQfihQNtbCZJXaTWQDiHod=>calculate_updated( + it_current_checksums = lt_checksums + it_local_files = lt_local_files + it_updated_files = it_updated_files ). + + save_checksums( lt_checksums ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_REPO IMPLEMENTATION. + METHOD zif_abapgit_repo~bind_listener. + mi_listener = ii_listener. + ENDMETHOD. + METHOD check_abap_language_version. + + DATA lo_abapgit_abap_language_vers TYPE REF TO zcl_abapgit_abap_language_vers. + DATA lv_text TYPE string. + + CREATE OBJECT lo_abapgit_abap_language_vers + EXPORTING + io_dot_abapgit = get_dot_abapgit( ). + + IF lo_abapgit_abap_language_vers->is_import_allowed( ms_data-package ) = abap_false. + lv_text = |Repository cannot be imported. | && + |ABAP Language Version of linked package is not compatible with repository settings.|. + zcx_abapgit_exception=>raise( lv_text ). + ENDIF. + ENDMETHOD. + METHOD check_language. + + DATA: + lv_main_language TYPE spras, + lv_error_message TYPE string, + lv_error_longtext TYPE string. + + " for deserialize, assumes find_remote_dot_abapgit has been called before (or language won't be defined) + lv_main_language = get_dot_abapgit( )->get_main_language( ). + + IF lv_main_language <> sy-langu. + + lv_error_message = |Current login language | + && |'{ zcl_abapgit_convert=>conversion_exit_isola_output( sy-langu ) }'| + && | does not match main language | + && |'{ zcl_abapgit_convert=>conversion_exit_isola_output( lv_main_language ) }'.|. + + " Feature open in main language only exists if abapGit tcode is present + IF zcl_abapgit_services_abapgit=>get_abapgit_tcode( ) IS INITIAL. + lv_error_message = lv_error_message && | Please logon in main language and retry.|. + lv_error_longtext = |For the Advanced menu option 'Open in Main Language' to be available a transaction code| && + | must be assigned to report { sy-cprog }.|. + ELSE. + lv_error_message = lv_error_message && | Select 'Advanced' > 'Open in Main Language'|. + ENDIF. + + zcx_abapgit_exception=>raise( iv_text = lv_error_message + iv_longtext = lv_error_longtext ). + + ENDIF. + + ENDMETHOD. + METHOD check_write_protect. + + IF get_local_settings( )-write_protected = abap_true. + zcx_abapgit_exception=>raise( 'Cannot deserialize. Local code is write-protected by repo config' ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + ASSERT NOT is_data-key IS INITIAL. + + ms_data = is_data. + mv_request_remote_refresh = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_repo~create_new_log. + + CREATE OBJECT mi_log TYPE zcl_abapgit_log. + mi_log->set_title( iv_title ). + + ri_log = mi_log. + + ENDMETHOD. + METHOD zif_abapgit_repo~delete_checks. + + DATA: li_package TYPE REF TO zif_abapgit_sap_package. + + check_write_protect( ). + check_language( ). + + li_package = zcl_abapgit_factory=>get_sap_package( get_package( ) ). + rs_checks-transport-required = li_package->are_changes_recorded_in_tr_req( ). + + ENDMETHOD. + METHOD deserialize_data. + + DATA: + lt_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt, + lt_result TYPE zif_abapgit_data_deserializer=>ty_results. + + "Deserialize data + lt_result = zcl_abapgit_data_factory=>get_deserializer( )->deserialize( + iv_package = get_package( ) + ii_config = get_data_config( ) + it_files = get_files_remote( ) ). + + "Save deserialized data to DB and add entries to transport requests + lt_updated_files = zcl_abapgit_data_factory=>get_deserializer( )->actualize( + it_result = lt_result + is_checks = is_checks ). + + INSERT LINES OF lt_updated_files INTO TABLE ct_files. + + ENDMETHOD. + METHOD deserialize_dot_abapgit. + INSERT get_dot_abapgit( )->get_signature( ) INTO TABLE ct_files. + ENDMETHOD. + METHOD deserialize_objects. + + DATA: + lt_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt, + lx_error TYPE REF TO zcx_abapgit_exception. + + TRY. + lt_updated_files = zcl_abapgit_objects=>deserialize( + ii_repo = me + is_checks = is_checks + ii_log = ii_log ). + CATCH zcx_abapgit_exception INTO lx_error. + " Ensure to reset default transport request task + zcl_abapgit_factory=>get_default_transport( )->reset( ). + refresh( iv_drop_log = abap_false ). + RAISE EXCEPTION lx_error. + ENDTRY. + + INSERT LINES OF lt_updated_files INTO TABLE ct_files. + + ENDMETHOD. + METHOD find_remote_dot_apack. + + FIELD-SYMBOLS: LIKE LINE OF mt_remote. + + get_files_remote( ). + + READ TABLE mt_remote ASSIGNING + WITH KEY file_path + COMPONENTS path = zif_abapgit_definitions=>c_root_dir + filename = zif_abapgit_apack_definitions=>c_dot_apack_manifest. + IF sy-subrc = 0. + ro_dot = zcl_abapgit_apack_reader=>deserialize( iv_package_name = ms_data-package + iv_xstr = -data ). + set_dot_apack( ro_dot ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo~get_data_config. + + FIELD-SYMBOLS: LIKE LINE OF mt_remote. + + IF mi_data_config IS BOUND. + ri_config = mi_data_config. + RETURN. + ENDIF. + + CREATE OBJECT ri_config TYPE zcl_abapgit_data_config. + + READ TABLE mt_remote ASSIGNING + WITH KEY file_path + COMPONENTS path = zif_abapgit_data_config=>c_default_path. + IF sy-subrc = 0. + ri_config->from_json( mt_remote ). + ENDIF. + +* offline repos does not have the remote files before the zip is choosen +* so make sure the json is read after zip file is loaded + IF lines( mt_remote ) > 0. + mi_data_config = ri_config. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo~get_dot_apack. + IF mo_apack_reader IS NOT BOUND. + mo_apack_reader = zcl_abapgit_apack_reader=>create_instance( ms_data-package ). + ENDIF. + + ro_dot_apack = mo_apack_reader. + + ENDMETHOD. + METHOD zif_abapgit_repo~get_log. + ri_log = mi_log. + ENDMETHOD. + METHOD zif_abapgit_repo~get_unsupported_objects_local. + + DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, + lt_supported_types TYPE zif_abapgit_objects=>ty_types_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_tadir, + LIKE LINE OF rt_objects. + + lt_tadir = get_tadir_objects( ). + + lt_supported_types = zcl_abapgit_objects=>supported_list( ). + LOOP AT lt_tadir ASSIGNING . + READ TABLE lt_supported_types WITH KEY table_line = -object TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO rt_objects ASSIGNING . + MOVE-CORRESPONDING TO . + -obj_type = -object. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD normalize_local_settings. + + cs_local_settings-labels = zcl_abapgit_repo_labels=>normalize( cs_local_settings-labels ). + + " TODO: more validation and normalization ? + + ENDMETHOD. + METHOD notify_listener. + + DATA ls_meta_slug TYPE zif_abapgit_persistence=>ty_repo_xml. + + IF mi_listener IS BOUND. + MOVE-CORRESPONDING ms_data TO ls_meta_slug. + mi_listener->on_meta_change( + iv_key = ms_data-key + is_meta = ls_meta_slug + is_change_mask = is_change_mask ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo~refresh_local_object. + + DATA: + ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, + lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, + lt_new_local_files TYPE zif_abapgit_definitions=>ty_files_item_tt, + lo_serialize TYPE REF TO zcl_abapgit_serialize. + + lt_tadir = get_tadir_objects( ). + + DELETE mt_local WHERE item-obj_type = iv_obj_type + AND item-obj_name = iv_obj_name. + + READ TABLE lt_tadir INTO ls_tadir + WITH KEY object = iv_obj_type + obj_name = iv_obj_name. + IF sy-subrc <> 0 OR ls_tadir-delflag = abap_true. + " object doesn't exist anymore, nothing todo here + RETURN. + ENDIF. + + CLEAR lt_tadir. + INSERT ls_tadir INTO TABLE lt_tadir. + + CREATE OBJECT lo_serialize + EXPORTING + io_dot_abapgit = get_dot_abapgit( ) + is_local_settings = get_local_settings( ). + + lt_new_local_files = lo_serialize->serialize( + iv_package = ms_data-package + it_tadir = lt_tadir ). + + INSERT LINES OF lt_new_local_files INTO TABLE mt_local. + + ENDMETHOD. + METHOD zif_abapgit_repo~refresh_local_objects. + + mv_request_local_refresh = abap_true. + get_files_local( ). + + ENDMETHOD. + METHOD zif_abapgit_repo~remove_ignored_files. + + DATA lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. + DATA lv_index TYPE sy-index. + + FIELD-SYMBOLS LIKE LINE OF ct_files. + + lo_dot = get_dot_abapgit( ). + + " Skip ignored files + LOOP AT ct_files ASSIGNING . + lv_index = sy-tabix. + IF lo_dot->is_ignored( iv_path = -path + iv_filename = -filename ) = abap_true. + DELETE ct_files INDEX lv_index. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD remove_locally_excluded_files. + + DATA ls_ls TYPE zif_abapgit_persistence=>ty_repo-local_settings. + DATA lv_excl TYPE string. + DATA lv_full_path TYPE string. + + FIELD-SYMBOLS LIKE LINE OF ct_rem_files. + FIELD-SYMBOLS LIKE LINE OF ct_loc_files. + + ls_ls = get_local_settings( ). + + LOOP AT ls_ls-exclude_remote_paths INTO lv_excl. + CHECK lv_excl IS NOT INITIAL. + + IF ct_rem_files IS SUPPLIED. + LOOP AT ct_rem_files ASSIGNING . + lv_full_path = -path && -filename. + IF lv_full_path CP lv_excl. + DELETE ct_rem_files INDEX sy-tabix. + ENDIF. + ENDLOOP. + + ELSEIF ct_loc_files IS SUPPLIED. + LOOP AT ct_loc_files ASSIGNING . + lv_full_path = -file-path && -file-filename. + IF lv_full_path CP lv_excl. + DELETE ct_loc_files INDEX sy-tabix. + ENDIF. + ENDLOOP. + + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD reset_remote. + CLEAR mt_remote. + mv_request_remote_refresh = abap_true. + ENDMETHOD. + METHOD set. + +* TODO: refactor, maybe use zcl_abapgit_string_map ? + + DATA: ls_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask. + ASSERT iv_url IS SUPPLIED + OR iv_branch_name IS SUPPLIED + OR iv_selected_commit IS SUPPLIED + OR iv_head_branch IS SUPPLIED + OR iv_offline IS SUPPLIED + OR is_dot_abapgit IS SUPPLIED + OR is_local_settings IS SUPPLIED + OR iv_deserialized_by IS SUPPLIED + OR iv_deserialized_at IS SUPPLIED + OR iv_switched_origin IS SUPPLIED. + IF iv_url IS SUPPLIED. + ms_data-url = iv_url. + ls_mask-url = abap_true. + ENDIF. + + IF iv_branch_name IS SUPPLIED. + ms_data-branch_name = iv_branch_name. + ls_mask-branch_name = abap_true. + ENDIF. + + IF iv_selected_commit IS SUPPLIED. + ms_data-selected_commit = iv_selected_commit. + ls_mask-selected_commit = abap_true. + ENDIF. + + IF iv_head_branch IS SUPPLIED. + ms_data-head_branch = iv_head_branch. + ls_mask-head_branch = abap_true. + ENDIF. + + IF iv_offline IS SUPPLIED. + ms_data-offline = iv_offline. + ls_mask-offline = abap_true. + ENDIF. + + IF is_dot_abapgit IS SUPPLIED. + ms_data-dot_abapgit = is_dot_abapgit. + ls_mask-dot_abapgit = abap_true. + ENDIF. + + IF is_local_settings IS SUPPLIED. + ms_data-local_settings = is_local_settings. + ls_mask-local_settings = abap_true. + normalize_local_settings( CHANGING cs_local_settings = ms_data-local_settings ). + ENDIF. + + IF iv_deserialized_at IS SUPPLIED OR iv_deserialized_by IS SUPPLIED. + ms_data-deserialized_at = iv_deserialized_at. + ms_data-deserialized_by = iv_deserialized_by. + ls_mask-deserialized_at = abap_true. + ls_mask-deserialized_by = abap_true. + ENDIF. + + IF iv_switched_origin IS SUPPLIED. + ms_data-switched_origin = iv_switched_origin. + ls_mask-switched_origin = abap_true. + ENDIF. + + notify_listener( ls_mask ). + + ENDMETHOD. + METHOD set_dot_apack. + get_dot_apack( ). + mo_apack_reader->set_manifest_descriptor( io_dot_apack->get_manifest_descriptor( ) ). + ENDMETHOD. + METHOD zif_abapgit_repo~set_files_remote. + + mt_remote = it_files. + mv_request_remote_refresh = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_repo~set_local_settings. + + set( is_local_settings = is_settings ). + + ENDMETHOD. + METHOD zif_abapgit_repo~switch_repo_type. + + IF iv_offline = ms_data-offline. + zcx_abapgit_exception=>raise( |Cannot switch_repo_type, offline already = "{ ms_data-offline }"| ). + ENDIF. + + IF iv_offline = abap_true. " On-line -> OFFline + set( iv_url = zcl_abapgit_url=>name( ms_data-url ) + iv_branch_name = '' + iv_selected_commit = '' + iv_head_branch = '' + iv_offline = abap_true ). + ELSE. " OFFline -> On-line + set( iv_offline = abap_false ). + ENDIF. + + ENDMETHOD. + METHOD update_last_deserialize. + + DATA: lv_deserialized_at TYPE zif_abapgit_persistence=>ty_repo-deserialized_at, + lv_deserialized_by TYPE zif_abapgit_persistence=>ty_repo-deserialized_by. + + GET TIME STAMP FIELD lv_deserialized_at. + lv_deserialized_by = sy-uname. + + set( iv_deserialized_at = lv_deserialized_at + iv_deserialized_by = lv_deserialized_by ). + + ENDMETHOD. + METHOD zif_abapgit_repo~checksums. + + CREATE OBJECT ri_checksums TYPE zcl_abapgit_repo_checksums + EXPORTING + iv_repo_key = ms_data-key. + + ENDMETHOD. + METHOD zif_abapgit_repo~deserialize. + + DATA lt_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt. + + find_remote_dot_abapgit( ). + find_remote_dot_apack( ). + + check_write_protect( ). + check_language( ). + + IF is_checks-requirements-met = zif_abapgit_definitions=>c_no AND is_checks-requirements-decision IS INITIAL. + zcx_abapgit_exception=>raise( 'Requirements not met and undecided' ). + ENDIF. + + IF is_checks-dependencies-met = zif_abapgit_definitions=>c_no AND is_checks-dependencies-decision IS INITIAL. + zcx_abapgit_exception=>raise( 'APACK dependencies not met and undecided' ). + ENDIF. + + IF is_checks-transport-required = abap_true AND is_checks-transport-transport IS INITIAL. + zcx_abapgit_exception=>raise( |No transport request was supplied| ). + ENDIF. + + deserialize_dot_abapgit( CHANGING ct_files = lt_updated_files ). + + deserialize_objects( + EXPORTING + is_checks = is_checks + ii_log = ii_log + CHANGING + ct_files = lt_updated_files ). + + deserialize_data( + EXPORTING + is_checks = is_checks + CHANGING + ct_files = lt_updated_files ). + + CLEAR mt_local. " Should be before CS update which uses NEW local + + checksums( )->update( lt_updated_files ). + + update_last_deserialize( ). + + COMMIT WORK AND WAIT. + + ENDMETHOD. + METHOD zif_abapgit_repo~deserialize_checks. + + DATA: lt_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt, + lt_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies. + + find_remote_dot_abapgit( ). + find_remote_dot_apack( ). + + check_write_protect( ). + check_language( ). + check_abap_language_version( ). + + rs_checks = zcl_abapgit_objects=>deserialize_checks( me ). + + lt_requirements = get_dot_abapgit( )->get_data( )-requirements. + rs_checks-requirements-met = zcl_abapgit_repo_requirements=>is_requirements_met( lt_requirements ). + + lt_dependencies = get_dot_apack( )->get_manifest_descriptor( )-dependencies. + rs_checks-dependencies-met = zcl_abapgit_apack_helper=>are_dependencies_met( lt_dependencies ). + + rs_checks-customizing = zcl_abapgit_data_factory=>get_deserializer( )->deserialize_check( + ii_repo = me + ii_config = get_data_config( ) ). + + ENDMETHOD. + METHOD zif_abapgit_repo~find_remote_dot_abapgit. + + FIELD-SYMBOLS: LIKE LINE OF mt_remote. + + get_files_remote( ). + + READ TABLE mt_remote ASSIGNING + WITH KEY file_path + COMPONENTS path = zif_abapgit_definitions=>c_root_dir + filename = zif_abapgit_definitions=>c_dot_abapgit. + IF sy-subrc = 0. + ro_dot = zcl_abapgit_dot_abapgit=>deserialize( -data ). + set_dot_abapgit( ro_dot ). + COMMIT WORK AND WAIT. " to release lock + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo~get_dot_abapgit. + CREATE OBJECT ro_dot_abapgit + EXPORTING + is_data = ms_data-dot_abapgit. + ENDMETHOD. + METHOD zif_abapgit_repo~get_files_local. + + DATA lo_serialize TYPE REF TO zcl_abapgit_serialize. + + " Serialization happened before and no refresh request + IF lines( mt_local ) > 0 AND mv_request_local_refresh = abap_false. + rt_files = mt_local. + RETURN. + ENDIF. + + CREATE OBJECT lo_serialize + EXPORTING + io_dot_abapgit = get_dot_abapgit( ) + is_local_settings = get_local_settings( ). + + rt_files = lo_serialize->files_local( + iv_package = get_package( ) + ii_data_config = get_data_config( ) + ii_log = ii_log ). + + remove_locally_excluded_files( CHANGING ct_loc_files = rt_files ). + + mt_local = rt_files. + mv_request_local_refresh = abap_false. " Fulfill refresh + + ENDMETHOD. + METHOD zif_abapgit_repo~get_files_local_filtered. + + DATA lo_serialize TYPE REF TO zcl_abapgit_serialize. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + CREATE OBJECT lo_serialize + EXPORTING + io_dot_abapgit = get_dot_abapgit( ) + is_local_settings = get_local_settings( ). + + lt_filter = ii_obj_filter->get_filter( ). + + rt_files = lo_serialize->files_local( + iv_package = get_package( ) + ii_data_config = get_data_config( ) + ii_log = ii_log + it_filter = lt_filter ). + + ENDMETHOD. + METHOD zif_abapgit_repo~get_files_remote. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lr_filter TYPE REF TO zcl_abapgit_repo_filter. + + rt_files = mt_remote. + + "Filter Ignored Files prior to Applying a Filter + IF iv_ignore_files = abap_true. + remove_ignored_files( CHANGING ct_files = rt_files ). + ENDIF. + + remove_locally_excluded_files( CHANGING ct_rem_files = rt_files ). + + IF ii_obj_filter IS NOT INITIAL. + lt_filter = ii_obj_filter->get_filter( ). + + CREATE OBJECT lr_filter. + lr_filter->apply_object_filter( + EXPORTING + it_filter = lt_filter + io_dot = get_dot_abapgit( ) + iv_devclass = get_package( ) + CHANGING + ct_files = rt_files ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo~get_key. + rv_key = ms_data-key. + ENDMETHOD. + METHOD zif_abapgit_repo~get_local_settings. + + rs_settings = ms_data-local_settings. + + ENDMETHOD. + METHOD zif_abapgit_repo~get_name. + + " Local display name has priority over official name + rv_name = ms_data-local_settings-display_name. + IF rv_name IS INITIAL. + rv_name = ms_data-dot_abapgit-name. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_repo~get_package. + rv_package = ms_data-package. + ENDMETHOD. + METHOD zif_abapgit_repo~get_tadir_objects. + + rt_tadir = zcl_abapgit_factory=>get_tadir( )->read( + iv_package = get_package( ) + iv_ignore_subpackages = get_local_settings( )-ignore_subpackages + iv_only_local_objects = get_local_settings( )-only_local_objects + io_dot = get_dot_abapgit( ) ). + + ENDMETHOD. + METHOD zif_abapgit_repo~has_remote_source. + rv_yes = boolc( lines( mt_remote ) > 0 ). + ENDMETHOD. + METHOD zif_abapgit_repo~is_offline. + rv_offline = ms_data-offline. + ENDMETHOD. + METHOD zif_abapgit_repo~refresh. + + mv_request_local_refresh = abap_true. + reset_remote( ). + + IF iv_drop_log = abap_true. + CLEAR mi_log. + ENDIF. + + IF iv_drop_cache = abap_true. + CLEAR mt_local. + ENDIF. + + get_dot_apack( )->refresh( ). + + ENDMETHOD. + METHOD zif_abapgit_repo~set_dot_abapgit. + set( is_dot_abapgit = io_dot_abapgit->get_data( ) ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_dot_abapgit IMPLEMENTATION. + METHOD add_ignore. + + DATA: lv_name TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF ms_data-ignore. + lv_name = iv_path && iv_filename. + + READ TABLE ms_data-ignore FROM lv_name TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + RETURN. + ENDIF. + + APPEND INITIAL LINE TO ms_data-ignore ASSIGNING . + = lv_name. + + ENDMETHOD. + METHOD build_default. + + DATA: ls_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit. + ls_data-master_language = sy-langu. + ls_data-starting_folder = '/src/'. + ls_data-folder_logic = zif_abapgit_dot_abapgit=>c_folder_logic-prefix. + + CREATE OBJECT ro_dot_abapgit + EXPORTING + is_data = ls_data. + + ENDMETHOD. + METHOD constructor. + ms_data = is_data. + ENDMETHOD. + METHOD deserialize. + + DATA: lv_xml TYPE string, + ls_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit. + lv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( iv_xstr ). + + ls_data = from_xml( lv_xml ). + + CREATE OBJECT ro_dot_abapgit + EXPORTING + is_data = ls_data. + + ENDMETHOD. + METHOD determine_i18n_parameters. + + rs_i18n_params-main_language = get_main_language( ). + rs_i18n_params-use_lxe = use_lxe( ). + rs_i18n_params-main_language_only = iv_main_language_only. + rs_i18n_params-translation_languages = zcl_abapgit_lxe_texts=>get_translation_languages( + iv_main_language = get_main_language( ) + it_i18n_languages = get_i18n_languages( ) ). + + ENDMETHOD. + METHOD from_xml. + + DATA: lv_xml TYPE string. + + lv_xml = iv_xml. + + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML lv_xml + RESULT data = rs_data. + +* downward compatibility + IF rs_data-folder_logic IS INITIAL. + rs_data-folder_logic = zif_abapgit_dot_abapgit=>c_folder_logic-prefix. + ENDIF. + + ENDMETHOD. + METHOD get_abap_language_version. + rv_abap_language_version = ms_data-abap_language_version. + ENDMETHOD. + METHOD get_data. + rs_data = ms_data. + ENDMETHOD. + METHOD get_folder_logic. + rv_logic = ms_data-folder_logic. + ENDMETHOD. + METHOD get_i18n_languages. + rt_languages = ms_data-i18n_languages. + ENDMETHOD. + METHOD get_main_language. + rv_language = ms_data-master_language. + IF rv_language IS INITIAL. + rv_language = sy-langu. + ENDIF. + ENDMETHOD. + METHOD get_name. + rv_name = ms_data-name. + ENDMETHOD. + METHOD get_objs_without_translation. + rt_list = ms_data-without_translation. + ENDMETHOD. + METHOD get_original_system. + rv_original_system = ms_data-original_system. + ENDMETHOD. + METHOD get_requirements. + rt_requirements = ms_data-requirements. + ENDMETHOD. + METHOD get_signature. + + rs_signature-path = zif_abapgit_definitions=>c_root_dir. + rs_signature-filename = zif_abapgit_definitions=>c_dot_abapgit. + rs_signature-sha1 = zcl_abapgit_hash=>sha1_blob( serialize( ) ). + + ENDMETHOD. + METHOD get_starting_folder. + rv_path = ms_data-starting_folder. + ENDMETHOD. + METHOD get_version_constant. + rv_version_constant = ms_data-version_constant. + ENDMETHOD. + METHOD is_ignored. + + DATA: lv_name TYPE string, + lv_starting TYPE string, + lv_dot TYPE string, + lv_ignore TYPE string. + lv_name = iv_path && iv_filename. + + CONCATENATE ms_data-starting_folder '*' INTO lv_starting. + + " Always allow .abapgit.xml and .apack-manifest.xml + CONCATENATE '/' zif_abapgit_definitions=>c_dot_abapgit INTO lv_dot. + IF lv_name = lv_dot. + RETURN. + ENDIF. + CONCATENATE '/' zif_abapgit_apack_definitions=>c_dot_apack_manifest INTO lv_dot. + IF lv_name = lv_dot. + RETURN. + ENDIF. + + " Ignore all files matching pattern in ignore list + LOOP AT ms_data-ignore INTO lv_ignore. + " # needs to be escaped since it's the escape character + " and used as namespace separator in filenames, for example + lv_ignore = replace( + val = lv_ignore + sub = '#' + with = '##' + occ = 0 ). + IF lv_name CP lv_ignore. + rv_ignored = abap_true. + RETURN. + ENDIF. + ENDLOOP. + + " Ignore all files outside of starting folder tree + IF ms_data-starting_folder <> '/' AND NOT lv_name CP lv_starting. + rv_ignored = abap_true. + ENDIF. + + IF iv_path = zif_abapgit_data_config=>c_default_path. + rv_ignored = abap_false. + ENDIF. + + ENDMETHOD. + METHOD remove_ignore. + + DATA: lv_name TYPE string. + lv_name = iv_path && iv_filename. + + DELETE TABLE ms_data-ignore FROM lv_name. + + ENDMETHOD. + METHOD serialize. + + DATA lv_xml TYPE string. + + lv_xml = to_xml( ms_data ). + + rv_xstr = zcl_abapgit_convert=>string_to_xstring_utf8_bom( lv_xml ). + + ENDMETHOD. + METHOD set_abap_language_version. + ms_data-abap_language_version = iv_abap_language_version. + ENDMETHOD. + METHOD set_folder_logic. + ms_data-folder_logic = iv_logic. + ENDMETHOD. + METHOD set_i18n_languages. + ms_data-i18n_languages = it_languages. + ENDMETHOD. + METHOD set_name. + ms_data-name = iv_name. + ENDMETHOD. + METHOD set_objs_without_translation. + ms_data-without_translation = it_list. + ENDMETHOD. + METHOD set_original_system. + ms_data-original_system = iv_original_system. + ENDMETHOD. + METHOD set_requirements. + ms_data-requirements = it_requirements. + ENDMETHOD. + METHOD set_starting_folder. + ms_data-starting_folder = iv_path. + ENDMETHOD. + METHOD set_version_constant. + ms_data-version_constant = iv_version_constant. + ENDMETHOD. + METHOD to_file. + rs_file-path = zif_abapgit_definitions=>c_root_dir. + rs_file-filename = zif_abapgit_definitions=>c_dot_abapgit. + rs_file-data = serialize( ). + rs_file-sha1 = zcl_abapgit_hash=>sha1_blob( rs_file-data ). + ENDMETHOD. + METHOD to_xml. + + CALL TRANSFORMATION id + OPTIONS initial_components = 'suppress' + SOURCE data = is_data + RESULT XML rv_xml. + + rv_xml = zcl_abapgit_xml_pretty=>print( rv_xml ). + + REPLACE FIRST OCCURRENCE + OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' + IN rv_xml + WITH ''. + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD use_lxe. + + IF iv_yes <> abap_undefined. + ms_data-use_lxe = iv_yes. + ENDIF. + + rv_yes = ms_data-use_lxe. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ZIP IMPLEMENTATION. + METHOD encode_files. + + DATA: lo_zip TYPE REF TO cl_abap_zip, + lv_filename TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF it_files. + CREATE OBJECT lo_zip. + + LOOP AT it_files ASSIGNING . + CONCATENATE -file-path+1 -file-filename INTO lv_filename. + lo_zip->add( name = lv_filename + content = -file-data ). + ENDLOOP. + + rv_xstr = lo_zip->save( ). + + ENDMETHOD. + METHOD export. + + DATA li_log TYPE REF TO zif_abapgit_log. + DATA lt_zip TYPE zif_abapgit_definitions=>ty_files_item_tt. + DATA lo_serialize TYPE REF TO zcl_abapgit_serialize. + + CREATE OBJECT li_log TYPE zcl_abapgit_log. + li_log->set_title( 'Zip Export Log' ). + + IF zcl_abapgit_factory=>get_sap_package( iv_package )->exists( ) = abap_false. + zcx_abapgit_exception=>raise( |Package { iv_package } doesn't exist| ). + ENDIF. + + CREATE OBJECT lo_serialize + EXPORTING + io_dot_abapgit = io_dot_abapgit + is_local_settings = is_local_settings. + + lt_zip = lo_serialize->files_local( + iv_package = iv_package + ii_log = li_log + it_filter = it_filter ). + + FREE lo_serialize. + + IF li_log->count( ) > 0 AND iv_show_log = abap_true. + zcl_abapgit_log_viewer=>show_log( li_log ). + ENDIF. + + rv_xstr = encode_files( lt_zip ). + + ENDMETHOD. + METHOD export_object. + + DATA: ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, + lv_folder TYPE string, + lv_fullpath TYPE string, + lv_sep TYPE c LENGTH 1, + ls_files_item TYPE zif_abapgit_objects=>ty_serialization, + lo_frontend_serv TYPE REF TO zif_abapgit_frontend_services. + + FIELD-SYMBOLS: LIKE LINE OF ls_files_item-files. + + ls_tadir = zcl_abapgit_factory=>get_tadir( )->read_single( + iv_object = iv_object_type + iv_obj_name = iv_object_name ). + + IF ls_tadir IS INITIAL. + zcx_abapgit_exception=>raise( 'Object could not be found' ). + ENDIF. + + ls_files_item-item-obj_type = ls_tadir-object. + ls_files_item-item-obj_name = ls_tadir-obj_name. + ls_files_item-item-abap_language_version = '*'. "any + + ls_files_item = zcl_abapgit_objects=>serialize( + is_item = ls_files_item-item + io_i18n_params = zcl_abapgit_i18n_params=>new( + iv_use_lxe = iv_use_lxe + it_translation_langs = it_translation_langs + iv_main_language_only = iv_main_language_only + iv_main_language = sy-langu ) ). + + IF lines( ls_files_item-files ) = 0. + zcx_abapgit_exception=>raise( 'Empty' ). + ENDIF. + + lo_frontend_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + lo_frontend_serv->directory_browse( CHANGING cv_selected_folder = lv_folder ). + IF lv_folder IS INITIAL. + RAISE EXCEPTION TYPE zcx_abapgit_cancel. + ENDIF. + + lo_frontend_serv->get_file_separator( CHANGING cv_file_separator = lv_sep ). + + LOOP AT ls_files_item-files ASSIGNING . + lv_fullpath = |{ lv_folder }{ lv_sep }{ -filename }|. + save_binstring_to_localfile( iv_filename = lv_fullpath + iv_binstring = -data ). + + ENDLOOP. + + ENDMETHOD. + METHOD export_package. + + DATA: ls_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings, + lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit, + lo_frontend_serv TYPE REF TO zif_abapgit_frontend_services, + lv_default TYPE string, + lv_package_escaped TYPE string, + lv_path TYPE string, + lv_zip_xstring TYPE xstring. + + ls_local_settings-main_language_only = iv_main_lang_only. + ls_local_settings-ignore_subpackages = iv_ign_subpkg. + + lo_dot_abapgit = zcl_abapgit_dot_abapgit=>build_default( ). + lo_dot_abapgit->set_folder_logic( iv_folder_logic ). + + lo_frontend_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + + lv_package_escaped = iv_package. + REPLACE ALL OCCURRENCES OF '/' IN lv_package_escaped WITH '#'. + lv_default = |{ lv_package_escaped }_{ sy-datlo }_{ sy-timlo }.zip|. + + lv_zip_xstring = export( + is_local_settings = ls_local_settings + iv_package = iv_package + io_dot_abapgit = lo_dot_abapgit ). + + lv_path = lo_frontend_serv->show_file_save_dialog( + iv_title = 'Package Export' + iv_extension = 'zip' + iv_default_filename = lv_default ). + + lo_frontend_serv->file_download( + iv_path = lv_path + iv_xstr = lv_zip_xstring ). + + ENDMETHOD. + METHOD filename. + + IF iv_str CA '/'. + FIND REGEX '(.*/)(.*)' IN iv_str + SUBMATCHES ev_path ev_filename. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Malformed path' ). + ENDIF. + IF ev_path <> '/'. + CONCATENATE '/' ev_path INTO ev_path. + ENDIF. + ELSE. + ev_path = '/'. + ev_filename = iv_str. + ENDIF. + TRANSLATE ev_filename TO LOWER CASE. + + ENDMETHOD. + METHOD load. + + rt_files = unzip_file( iv_xstr ). + + ENDMETHOD. + METHOD normalize_path. +* removes first folder from path if needed + + DATA: lt_split TYPE TABLE OF string, + lv_needed TYPE abap_bool, + lv_length TYPE i, + lv_split LIKE LINE OF lt_split. + + FIELD-SYMBOLS: LIKE LINE OF ct_files. + READ TABLE ct_files INDEX 1 ASSIGNING . + IF sy-subrc <> 0. + RETURN. + ENDIF. + + SPLIT -path AT '/' INTO TABLE lt_split. + IF sy-subrc <> 0. + RETURN. + ENDIF. + READ TABLE lt_split INDEX 2 INTO lv_split. + IF sy-subrc <> 0 OR strlen( lv_split ) = 0. + RETURN. + ENDIF. + + CONCATENATE '/' lv_split '/*' INTO lv_split. + + lv_needed = abap_true. + LOOP AT ct_files ASSIGNING . + IF NOT -path CP lv_split. + lv_needed = abap_false. + EXIT. " current loop + ENDIF. + ENDLOOP. + + IF lv_needed = abap_true. + lv_length = strlen( lv_split ) - 2. + LOOP AT ct_files ASSIGNING . + -path = -path+lv_length. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD save_binstring_to_localfile. + + zcl_abapgit_ui_factory=>get_frontend_services( )->file_download( + iv_path = iv_filename + iv_xstr = iv_binstring ). + + ENDMETHOD. + METHOD unzip_file. + + DATA: lo_zip TYPE REF TO cl_abap_zip, + lv_data TYPE xstring. + + FIELD-SYMBOLS: LIKE LINE OF lo_zip->files, + LIKE LINE OF rt_files. + CREATE OBJECT lo_zip. + lo_zip->load( EXPORTING + zip = iv_xstr + EXCEPTIONS + zip_parse_error = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from zip' ). + ENDIF. + + LOOP AT lo_zip->files ASSIGNING . + + lo_zip->get( + EXPORTING + name = -name + IMPORTING + content = lv_data + EXCEPTIONS + zip_index_error = 1 + zip_decompression_error = 2 + OTHERS = 3 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from zip get' ). + ENDIF. + + APPEND INITIAL LINE TO rt_files ASSIGNING . + + filename( + EXPORTING + iv_str = -name + IMPORTING + ev_path = -path + ev_filename = -filename ). + + -data = lv_data. + + -sha1 = zcl_abapgit_hash=>sha1_blob( -data ). + + ENDLOOP. + + DELETE rt_files WHERE filename IS INITIAL. + + normalize_path( CHANGING ct_files = rt_files ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_version IMPLEMENTATION. + METHOD check_dependant_version. + + CONSTANTS: lc_message TYPE string VALUE 'Current version is older than required'. + + IF is_dependant-major > is_current-major. + zcx_abapgit_exception=>raise( lc_message ). + ELSEIF is_dependant-major < is_current-major. + RETURN. + ENDIF. + + IF is_dependant-minor > is_current-minor. + zcx_abapgit_exception=>raise( lc_message ). + ELSEIF is_dependant-minor < is_current-minor. + RETURN. + ENDIF. + + IF is_dependant-patch > is_current-patch. + zcx_abapgit_exception=>raise( lc_message ). + ELSEIF is_dependant-patch < is_current-patch. + RETURN. + ENDIF. + + IF is_current-prerelase IS INITIAL. + RETURN. + ENDIF. + + CASE is_current-prerelase. + WHEN 'rc'. + IF is_dependant-prerelase = ''. + zcx_abapgit_exception=>raise( lc_message ). + ENDIF. + + WHEN 'beta'. + IF is_dependant-prerelase = '' OR is_dependant-prerelase = 'rc'. + zcx_abapgit_exception=>raise( lc_message ). + ENDIF. + + WHEN 'alpha'. + IF is_dependant-prerelase = '' OR is_dependant-prerelase = 'rc' OR is_dependant-prerelase = 'beta'. + zcx_abapgit_exception=>raise( lc_message ). + ENDIF. + + ENDCASE. + + IF is_dependant-prerelase = is_current-prerelase AND is_dependant-prerelase_patch > is_current-prerelase_patch. + zcx_abapgit_exception=>raise( lc_message ). + ENDIF. + + ENDMETHOD. + METHOD compare. + + DATA: ls_version_a TYPE zif_abapgit_definitions=>ty_version, + ls_version_b TYPE zif_abapgit_definitions=>ty_version. + + TRY. + IF is_a IS NOT INITIAL. + ls_version_a = is_a. + ELSE. + ls_version_a = conv_str_to_version( iv_a ). + ENDIF. + + IF is_b IS NOT INITIAL. + ls_version_b = is_b. + ELSE. + ls_version_b = conv_str_to_version( iv_b ). + ENDIF. + CATCH zcx_abapgit_exception. + rv_result = 0. + RETURN. + ENDTRY. + + IF ls_version_a = ls_version_b. + rv_result = 0. + ELSE. + TRY. + check_dependant_version( is_current = ls_version_a + is_dependant = ls_version_b ). + rv_result = 1. + CATCH zcx_abapgit_exception. + rv_result = -1. + RETURN. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD conv_str_to_version. + + DATA: lt_segments TYPE STANDARD TABLE OF string, + lt_parts TYPE STANDARD TABLE OF string, + lv_segment TYPE string. + + SPLIT iv_version AT '-' INTO TABLE lt_segments. + + READ TABLE lt_segments INTO lv_segment INDEX 1. " Version + IF sy-subrc <> 0. " No version + RETURN. + ENDIF. + + SPLIT lv_segment AT '.' INTO TABLE lt_parts. + + LOOP AT lt_parts INTO lv_segment. + + TRY. + CASE sy-tabix. + WHEN 1. + rs_version-major = lv_segment. + WHEN 2. + rs_version-minor = lv_segment. + WHEN 3. + rs_version-patch = lv_segment. + ENDCASE. + CATCH cx_sy_conversion_no_number. + zcx_abapgit_exception=>raise( 'Incorrect format for Semantic Version' ). + ENDTRY. + + ENDLOOP. + + READ TABLE lt_segments INTO lv_segment INDEX 2. " Pre-release Version + IF sy-subrc <> 0. " No version + RETURN. + ENDIF. + + SPLIT lv_segment AT '.' INTO TABLE lt_parts. + + LOOP AT lt_parts INTO lv_segment. + + CASE sy-tabix. + WHEN 1. + rs_version-prerelase = lv_segment. + TRANSLATE rs_version-prerelase TO LOWER CASE. + WHEN 2. + rs_version-prerelase_patch = lv_segment. + ENDCASE. + + ENDLOOP. + + IF rs_version-prerelase <> 'rc' AND rs_version-prerelase <> 'beta' AND rs_version-prerelase <> 'alpha'. + zcx_abapgit_exception=>raise( 'Incorrect format for Semantic Version' ). + ENDIF. + + ENDMETHOD. + METHOD get_version_constant_value. + DATA: lv_version_class TYPE seoclsname, + lv_version_component TYPE string. + FIELD-SYMBOLS: TYPE simple. + + IF iv_version_constant NP '*=>*'. + zcx_abapgit_exception=>raise( 'Version constant needs to use the format CLASS/INTERFACE=>CONSTANT' ). + ENDIF. + + SPLIT iv_version_constant AT '=>' INTO lv_version_class lv_version_component. + IF sy-subrc <> 0 OR lv_version_class IS INITIAL OR lv_version_component IS INITIAL. + zcx_abapgit_exception=>raise( 'Version constant cannot be parsed' ). + ENDIF. + + " You should remember that accessing a class or an interface with syntax errors + " gives us a shortdump. Therefore we do a syntax check here. + zcl_abapgit_oo_factory=>get_by_name( lv_version_class )->syntax_check( lv_version_class ). + + ASSIGN (lv_version_class)=>(lv_version_component) TO . + IF sy-subrc = 0. + rv_version = . + ELSE. + zcx_abapgit_exception=>raise( |Could not access version at class { lv_version_class } component | && + |{ lv_version_component }| ). + ENDIF. + ENDMETHOD. + METHOD normalize. + + " Internal program version should be in format "XXX.XXX.XXX" or "vXXX.XXX.XXX" + CONSTANTS: + lc_version_pattern TYPE string VALUE '^v?(\d{1,3}\.\d{1,3}\.\d{1,3})\s*$', + lc_prerelease_pattern TYPE string VALUE '^((rc|beta|alpha)\.\d{1,3})\s*$'. + + DATA: lv_version TYPE string, + lv_prerelease TYPE string, + lv_version_n TYPE string, + lv_prerelease_n TYPE string. + + SPLIT iv_version AT '-' INTO lv_version lv_prerelease. + + FIND FIRST OCCURRENCE OF REGEX lc_version_pattern + IN lv_version SUBMATCHES lv_version_n. + + IF lv_prerelease IS NOT INITIAL. + + FIND FIRST OCCURRENCE OF REGEX lc_prerelease_pattern + IN lv_prerelease SUBMATCHES lv_prerelease_n. + + ENDIF. + + IF lv_version_n IS INITIAL. + RETURN. + ENDIF. + + rv_version = lv_version_n. + + IF lv_prerelease_n IS NOT INITIAL. + CONCATENATE rv_version '-' lv_prerelease_n INTO rv_version. + ENDIF. + + ENDMETHOD. + METHOD version_to_numeric. + + DATA: lv_major TYPE n LENGTH 4, + lv_minor TYPE n LENGTH 4, + lv_release TYPE n LENGTH 4. + + SPLIT iv_version AT '.' INTO lv_major lv_minor lv_release. + + " Calculated value of version number, empty version will become 0 which is OK + rv_version = lv_major * 1000000 + lv_minor * 1000 + lv_release. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_requirements IMPLEMENTATION. + METHOD get_cvers. + IF gt_cvers IS NOT INITIAL. + rt_cvers = gt_cvers. + RETURN. + ENDIF. + + SELECT * FROM cvers INTO TABLE rt_cvers ORDER BY PRIMARY KEY. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error reading installed components| ). + ENDIF. + ENDMETHOD. + METHOD get_requirement_met_status. + + DATA: lt_installed TYPE ty_cvers. + + FIELD-SYMBOLS: TYPE zif_abapgit_dot_abapgit=>ty_requirement, + TYPE ty_requirement_status, + TYPE cvers. + lt_installed = get_cvers( ). + + LOOP AT it_requirements ASSIGNING . + APPEND INITIAL LINE TO rt_status ASSIGNING . + -component = -component. + -required_release = -min_release. + -required_patch = -min_patch. + + READ TABLE lt_installed WITH KEY component = -component + ASSIGNING . + IF sy-subrc = 0. + " Component is installed, requirement is met if the installed version is greater or equal + " to the required one. + -installed_release = -release. + -installed_patch = -extrelease. + + SELECT SINGLE desc_text FROM cvers_ref INTO -description + WHERE component = -component AND langu = sy-langu ##SUBRC_OK. + + -met = is_version_greater_or_equal( ). + ELSE. + " Component is not installed at all + -met = abap_false. + ENDIF. + + UNASSIGN . + ENDLOOP. + + ENDMETHOD. + METHOD inject_cvers. + " For testing only + gt_cvers = it_cvers. + ENDMETHOD. + METHOD is_requirements_met. + + DATA: lt_met_status TYPE ty_requirement_status_tt. + + lt_met_status = get_requirement_met_status( it_requirements ). + + READ TABLE lt_met_status TRANSPORTING NO FIELDS WITH KEY met = abap_false. + IF sy-subrc = 0. + rv_status = zif_abapgit_definitions=>c_no. + ELSE. + rv_status = zif_abapgit_definitions=>c_yes. + ENDIF. + + ENDMETHOD. + METHOD is_version_greater_or_equal. + + DATA: + lv_installed_release TYPE n LENGTH 4, + lv_installed_patch TYPE n LENGTH 4, + lv_required_release TYPE n LENGTH 4, + lv_required_patch TYPE n LENGTH 4. + + TRY. + MOVE EXACT: is_status-installed_release TO lv_installed_release, + is_status-installed_patch TO lv_installed_patch, + is_status-required_release TO lv_required_release, + is_status-required_patch TO lv_required_patch. + CATCH cx_sy_conversion_error. + " Cannot compare by number, assume requirement not fulfilled (user can force install + " anyways if this was an error) + rv_true = abap_false. + RETURN. + ENDTRY. + + " Versions are comparable by number, compare release and if necessary patch level + IF lv_installed_release > lv_required_release + OR ( lv_installed_release = lv_required_release + AND ( lv_required_patch = 0 + OR lv_installed_patch >= lv_required_patch ) ). + + rv_true = abap_true. + + ENDIF. + + ENDMETHOD. + METHOD requirements_popup. + + DATA: lt_met_status TYPE ty_requirement_status_tt, + lv_answer TYPE c LENGTH 1. + lt_met_status = get_requirement_met_status( it_requirements ). + + show_requirement_popup( lt_met_status ). + + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_titlebar = 'Warning' + iv_text_question = 'The project has unmet requirements. Do you want to continue?' ). + + IF lv_answer <> '1'. + zcx_abapgit_exception=>raise( 'Cancelling because of unmet requirements.' ). + ENDIF. + + ENDMETHOD. + METHOD show_requirement_popup. + + TYPES: BEGIN OF ty_color_line, + color TYPE lvc_t_scol. + INCLUDE TYPE ty_requirement_status. + TYPES: END OF ty_color_line. + + TYPES: ty_color_tab TYPE STANDARD TABLE OF ty_color_line WITH DEFAULT KEY. + + DATA: lo_alv TYPE REF TO cl_salv_table, + lo_column TYPE REF TO cl_salv_column, + lo_columns TYPE REF TO cl_salv_columns_table, + lt_color_table TYPE ty_color_tab, + lt_color_negative TYPE lvc_t_scol, + lt_color_positive TYPE lvc_t_scol, + ls_color TYPE lvc_s_scol, + ls_position TYPE zif_abapgit_popups=>ty_popup_position, + lx_ex TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE ty_color_line, + LIKE LINE OF it_requirements. + ls_color-color-col = col_negative. + APPEND ls_color TO lt_color_negative. + + ls_color-color-col = col_positive. + APPEND ls_color TO lt_color_positive. + + CLEAR ls_color. + + LOOP AT it_requirements ASSIGNING . + APPEND INITIAL LINE TO lt_color_table ASSIGNING . + MOVE-CORRESPONDING TO . + ENDLOOP. + + LOOP AT lt_color_table ASSIGNING . + IF -met = abap_false. + -color = lt_color_negative. + ELSE. + -color = lt_color_positive. + ENDIF. + ENDLOOP. + UNASSIGN . + + TRY. + cl_salv_table=>factory( IMPORTING r_salv_table = lo_alv + CHANGING t_table = lt_color_table ). + + lo_columns = lo_alv->get_columns( ). + lo_columns->get_column( 'MET' )->set_short_text( 'Met' ). + lo_columns->set_color_column( 'COLOR' ). + lo_columns->set_optimize( ). + + lo_column = lo_columns->get_column( 'REQUIRED_RELEASE' ). + lo_column->set_short_text( 'Req. Rel.' ). + + lo_column = lo_columns->get_column( 'REQUIRED_PATCH' ). + lo_column->set_short_text( 'Req. SP L.' ). + + ls_position = zcl_abapgit_popups=>center( + iv_width = 70 + iv_height = 10 ). + + lo_alv->set_screen_popup( start_column = ls_position-start_column + end_column = ls_position-end_column + start_line = ls_position-start_row + end_line = ls_position-end_row ). + + lo_alv->get_display_settings( )->set_list_header( 'Requirements' ). + lo_alv->display( ). + + CATCH cx_salv_msg cx_salv_not_found cx_salv_data_error INTO lx_ex. + zcx_abapgit_exception=>raise( lx_ex->get_text( ) ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_news IMPLEMENTATION. + METHOD constructor. + + DATA: lt_lines TYPE string_table, + lv_string TYPE string, + ls_log_line LIKE LINE OF mt_log. + + " Validate params + mv_current_version = zcl_abapgit_version=>normalize( iv_current_version ). + mv_lastseen_version = zcl_abapgit_version=>normalize( iv_lastseen_version ). + IF mv_current_version IS INITIAL. + RETURN. " Internal format of program version is not correct -> abort parsing + ENDIF. + + lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( iv_rawdata ). + lt_lines = zcl_abapgit_convert=>split_string( lv_string ). + mt_log = parse( it_lines = lt_lines + iv_current_version = mv_current_version ). + + READ TABLE mt_log INTO ls_log_line INDEX 1. + mv_latest_version = ls_log_line-version. " Empty if not found + + ENDMETHOD. + METHOD create. + + CONSTANTS: " TODO refactor + lc_log_path TYPE string VALUE '/', + lc_log_filename TYPE string VALUE 'changelog*', + lc_log_filename_up TYPE string VALUE 'CHANGELOG*'. + + DATA: lo_apack TYPE REF TO zcl_abapgit_apack_reader, + lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt, + lv_version TYPE string, + lv_last_seen TYPE string, + lv_url TYPE string, + li_repo_online TYPE REF TO zif_abapgit_repo_online, + lv_version_constant TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit-version_constant. + + FIELD-SYMBOLS LIKE LINE OF lt_remote. + IF ii_repo->is_offline( ) = abap_true. + RETURN. + ENDIF. + + li_repo_online ?= ii_repo. + lv_url = li_repo_online->get_url( ). + + lo_apack = ii_repo->get_dot_apack( ). + IF lo_apack IS BOUND. + lv_version = lo_apack->get_manifest_descriptor( )-version. + ENDIF. + + IF lv_version IS INITIAL. + TRY. + lv_version_constant = ii_repo->get_dot_abapgit( )->get_version_constant( ). + IF lv_version_constant IS NOT INITIAL. + lv_version = zcl_abapgit_version=>get_version_constant_value( lv_version_constant ). + ENDIF. + CATCH zcx_abapgit_exception. + CLEAR lv_version. + ENDTRY. + ENDIF. + + IF lv_version IS INITIAL. + RETURN. + ENDIF. + + lv_last_seen = zcl_abapgit_persist_factory=>get_user( )->get_repo_last_change_seen( lv_url ). + + TRY. " Find changelog + lt_remote = ii_repo->get_files_remote( ). + CATCH zcx_abapgit_exception. + RETURN. + ENDTRY. + + LOOP AT lt_remote ASSIGNING + " USING KEY file_path " syntax error in 754 + WHERE path = lc_log_path + AND ( filename CP lc_log_filename OR filename CP lc_log_filename_up ) ##PRIMKEY[FILE_PATH]. + + CREATE OBJECT ro_instance + EXPORTING + iv_rawdata = -data + iv_current_version = lv_version + iv_lastseen_version = zcl_abapgit_version=>normalize( lv_last_seen ). + + EXIT. + + ENDLOOP. + + IF ro_instance IS BOUND AND lv_last_seen <> ro_instance->latest_version( ). + zcl_abapgit_persist_factory=>get_user( )->set_repo_last_change_seen( + iv_url = lv_url + iv_version = ro_instance->latest_version( ) ). + ENDIF. + + ENDMETHOD. + METHOD get_log. + rt_log = mt_log. + ENDMETHOD. + METHOD has_important. + READ TABLE mt_log WITH KEY is_important = abap_true TRANSPORTING NO FIELDS. + rv_boolean = boolc( sy-subrc IS INITIAL ). + ENDMETHOD. + METHOD has_news. + rv_boolean = boolc( lines( mt_log ) > 0 ). + ENDMETHOD. + METHOD has_unseen. + rv_boolean = boolc( zcl_abapgit_version=>compare( + iv_a = mv_latest_version + iv_b = mv_lastseen_version ) > 0 ). + ENDMETHOD. + METHOD has_updates. + rv_boolean = boolc( zcl_abapgit_version=>compare( + iv_a = mv_latest_version + iv_b = mv_current_version ) > 0 ). + ENDMETHOD. + METHOD latest_version. + rv_version = mv_latest_version. + ENDMETHOD. + METHOD parse. + + DATA: lv_tail TYPE i, + lv_first_version_found TYPE abap_bool, + lv_version TYPE string, + ls_log LIKE LINE OF rt_log. + + FIELD-SYMBOLS: LIKE LINE OF it_lines. + LOOP AT it_lines ASSIGNING . + ls_log = parse_line( iv_line = + iv_current_version = iv_current_version ). + + " Skip until first version head and Skip empty lines + CHECK ls_log IS NOT INITIAL AND + ( lv_first_version_found = abap_true OR ls_log-version IS NOT INITIAL ). + + IF lv_first_version_found = abap_false. + lv_first_version_found = abap_true. + IF zcl_abapgit_version=>compare( iv_a = ls_log-version + iv_b = iv_current_version ) <= 0. + lv_tail = c_tail_length. " Display some last versions if no updates + ENDIF. + ENDIF. + + IF ls_log-is_header = abap_true. + "Skip everything below current version or show tail news + IF zcl_abapgit_version=>compare( iv_a = ls_log-version + iv_b = iv_current_version ) <= 0. + IF lv_tail > 0. + lv_tail = lv_tail - 1. + ELSE. + EXIT. + ENDIF. + ENDIF. + lv_version = ls_log-version. " Save to fill news lines + ELSE. + ls_log-version = lv_version. + ENDIF. + + APPEND ls_log TO rt_log. + ENDLOOP. + + ENDMETHOD. + METHOD parse_line. + + CONSTANTS: lc_header_pattern TYPE string + VALUE '^\d{4}-\d{2}-\d{2}\s+v(\d{1,3}\.\d{1,3}\.\d{1,3})\s*$'. + + DATA: lv_version TYPE string. + + IF iv_line IS INITIAL OR iv_line CO ' -='. + RETURN. " Skip empty and markup lines + ENDIF. + + " Check if line is a header line + FIND FIRST OCCURRENCE OF REGEX lc_header_pattern IN iv_line SUBMATCHES lv_version. + IF sy-subrc IS INITIAL. + lv_version = zcl_abapgit_version=>normalize( lv_version ). + rs_log-version = lv_version. + rs_log-is_header = abap_true. + rs_log-pos_to_cur = zcl_abapgit_version=>compare( iv_a = lv_version + iv_b = iv_current_version ). + ELSE. + FIND FIRST OCCURRENCE OF REGEX '^\s*!' IN iv_line. + rs_log-is_important = boolc( sy-subrc IS INITIAL ). " Change is important + ENDIF. + + rs_log-text = iv_line. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_labels IMPLEMENTATION. + METHOD class_constructor. + gv_regex = |^[{ c_allowed_chars }]*$|. " Must start with - + ENDMETHOD. + METHOD normalize. + + DATA lt_labels TYPE string_table. + DATA lt_normalized TYPE string_table. + FIELD-SYMBOLS LIKE LINE OF lt_labels. + + lt_labels = split( iv_labels ). + + LOOP AT lt_labels ASSIGNING . + FIND REGEX gv_regex IN . + IF sy-subrc = 0. + APPEND TO lt_normalized. + ENDIF. + ENDLOOP. + + SORT lt_normalized. + DELETE ADJACENT DUPLICATES FROM lt_normalized. + + rv_labels = concat_lines_of( + table = lt_normalized + sep = `, ` ). + + ENDMETHOD. + METHOD normalize_colors. + + DATA lt_colors TYPE ty_label_colors. + DATA lt_normalized TYPE ty_label_colors. + DATA lt_pairs TYPE string_table. + DATA lv_pair TYPE string. + FIELD-SYMBOLS LIKE LINE OF lt_colors. + + lt_colors = split_colors( iv_config ). + + LOOP AT lt_colors ASSIGNING . + TRY. + validate_one_label_color( ). + APPEND TO lt_normalized. + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + ENDLOOP. + + SORT lt_normalized BY label. + DELETE ADJACENT DUPLICATES FROM lt_normalized COMPARING label. + + LOOP AT lt_normalized ASSIGNING . + lv_pair = -label && `:` && -color. + APPEND lv_pair TO lt_pairs. + ENDLOOP. + + rv_config = concat_lines_of( + table = lt_pairs + sep = `, ` ). + + ENDMETHOD. + METHOD parse_color. + + DATA lv_tmp TYPE string. + + IF iv_color IS INITIAL. + RETURN. + ENDIF. + + IF iv_color+0(1) = '#'. + lv_tmp = iv_color+1. + SPLIT lv_tmp AT '/' INTO rs_parsed-fg rs_parsed-bg rs_parsed-border. + ELSE. + rs_parsed-cls = iv_color. + ENDIF. + + ENDMETHOD. + METHOD split. + + FIELD-SYMBOLS LIKE LINE OF rt_labels. + + SPLIT iv_labels AT ',' INTO TABLE rt_labels. + LOOP AT rt_labels ASSIGNING . + CONDENSE . + ENDLOOP. + DELETE rt_labels WHERE table_line IS INITIAL. + + ENDMETHOD. + METHOD split_colors. + + DATA lt_pairs TYPE string_table. + DATA lv_clean_config LIKE iv_config. + DATA ls_c LIKE LINE OF rt_label_colors. + FIELD-SYMBOLS LIKE LINE OF lt_pairs. + + lv_clean_config = replace( + val = iv_config + sub = cl_abap_char_utilities=>newline + with = ` ` ). " text area ends with LF + + SPLIT lv_clean_config AT ',' INTO TABLE lt_pairs. + LOOP AT lt_pairs ASSIGNING . + CONDENSE . + IF IS NOT INITIAL. + SPLIT AT ':' INTO ls_c-label ls_c-color. + CONDENSE ls_c-label. + CONDENSE ls_c-color. + APPEND ls_c TO rt_label_colors. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD split_colors_into_map. + + DATA lt_colors TYPE ty_label_colors. + FIELD-SYMBOLS LIKE LINE OF lt_colors. + + lt_colors = split_colors( iv_config ). + + ro_map = zcl_abapgit_string_map=>create( ). + LOOP AT lt_colors ASSIGNING . + TRY. + ro_map->set( + iv_key = -label + iv_val = -color ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + ENDLOOP. + + ENDMETHOD. + METHOD validate. + + DATA lt_labels TYPE string_table. + FIELD-SYMBOLS LIKE LINE OF lt_labels. + + lt_labels = split( iv_labels ). + + LOOP AT lt_labels ASSIGNING . + FIND REGEX gv_regex IN . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Disallowed chars in label #{ sy-tabix }| ). + ENDIF. + " TODO: maybe also limit length ? + ENDLOOP. + + ENDMETHOD. + METHOD validate_colors. + + DATA lt_colors TYPE ty_label_colors. + FIELD-SYMBOLS LIKE LINE OF lt_colors. + + lt_colors = split_colors( iv_config ). + + LOOP AT lt_colors ASSIGNING . + validate_one_label_color( + is_lc = + iv_index = sy-tabix ). + ENDLOOP. + + ENDMETHOD. + METHOD validate_one_label_color. + + DATA ls_parsed_color TYPE ty_color. + + IF is_lc-label IS INITIAL. + zcx_abapgit_exception=>raise( |Label is empty in pair #{ iv_index }| ). + ENDIF. + + IF is_lc-color IS INITIAL. + zcx_abapgit_exception=>raise( |Color is empty in pair #{ iv_index }| ). + ENDIF. + + FIND REGEX gv_regex IN is_lc-label. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Disallowed chars in label in pair #{ iv_index }| ). + ENDIF. + + ls_parsed_color = parse_color( is_lc-color ). + IF ls_parsed_color-cls IS NOT INITIAL. + FIND REGEX '^[-_A-Za-z]+$' IN ls_parsed_color-cls. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Disallowed chars in color in pair #{ iv_index }| ). + ENDIF. + ENDIF. + IF ls_parsed_color-fg IS NOT INITIAL. + validate_rgb_color( ls_parsed_color-fg ). + ENDIF. + IF ls_parsed_color-bg IS NOT INITIAL. + validate_rgb_color( ls_parsed_color-bg ). + ENDIF. + IF ls_parsed_color-border IS NOT INITIAL. + validate_rgb_color( ls_parsed_color-border ). + ENDIF. + + ENDMETHOD. + METHOD validate_rgb_color. + + DATA lv_len TYPE i. + + IF iv_color IS NOT INITIAL. + FIND REGEX '^[0-9A-Fa-f]+$' IN iv_color. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Disallowed chars in color in pair #{ iv_index }| ). + ENDIF. + lv_len = strlen( iv_color ). + IF NOT ( lv_len = 3 OR lv_len = 6 ). + zcx_abapgit_exception=>raise( |Incorrect color in pair #{ iv_index }| ). + ENDIF. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_item_state IMPLEMENTATION. + METHOD is_reassigned. + rv_is_reassigned = mv_is_reassigned. + ENDMETHOD. + METHOD is_unchanged. + rv_is_unchanged = boolc( mv_is_reassigned = abap_false + AND mv_lstate = zif_abapgit_definitions=>c_state-unchanged + AND mv_rstate = zif_abapgit_definitions=>c_state-unchanged ). + ENDMETHOD. + METHOD local. + rv_state = mv_lstate. + ENDMETHOD. + METHOD reduce. + + rv_new = iv_prev. + IF rv_new = iv_cur OR iv_cur IS INITIAL. + RETURN. " No change + ELSEIF rv_new IS INITIAL. + rv_new = iv_cur. + ELSE. + rv_new = zif_abapgit_definitions=>c_state-mixed. + ENDIF. + + ENDMETHOD. + METHOD remote. + rv_state = mv_rstate. + ENDMETHOD. + METHOD sum_with_repo_item. + + mv_lstate = reduce( + iv_prev = mv_lstate + iv_cur = is_repo_item-lstate ). + mv_rstate = reduce( + iv_prev = mv_rstate + iv_cur = is_repo_item-rstate ). + mv_is_reassigned = boolc( mv_is_reassigned = abap_true OR is_repo_item-packmove = abap_true ). + + ENDMETHOD. + METHOD sum_with_status_item. + + mv_lstate = reduce( + iv_prev = mv_lstate + iv_cur = is_status_item-lstate ). + mv_rstate = reduce( + iv_prev = mv_rstate + iv_cur = is_status_item-rstate ). + mv_is_reassigned = boolc( mv_is_reassigned = abap_true OR is_status_item-packmove = abap_true ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_status_calc IMPLEMENTATION. + METHOD build_existing. + + DATA ls_file_sig LIKE LINE OF it_state. + + " Item + rs_result-obj_type = is_local-item-obj_type. + rs_result-obj_name = is_local-item-obj_name. + rs_result-package = is_local-item-devclass. + rs_result-srcsystem = is_local-item-srcsystem. + rs_result-origlang = is_local-item-origlang. + rs_result-inactive = is_local-item-inactive. + + " File + rs_result-path = is_local-file-path. + rs_result-filename = is_local-file-filename. + + rs_result-match = boolc( is_local-file-sha1 = is_remote-sha1 ). + IF rs_result-match = abap_true. + RETURN. + ENDIF. + + " Match against current state + READ TABLE it_state INTO ls_file_sig + WITH KEY + path = is_local-file-path + filename = is_local-file-filename + BINARY SEARCH. + + IF sy-subrc = 0. + IF ls_file_sig-sha1 <> is_local-file-sha1. + rs_result-lstate = zif_abapgit_definitions=>c_state-modified. + ENDIF. + IF ls_file_sig-sha1 <> is_remote-sha1. + rs_result-rstate = zif_abapgit_definitions=>c_state-modified. + ENDIF. + ELSE. + " This is a strange situation. As both local and remote exist + " the state should also be present. Maybe this is a first run of the code. + " In this case just compare hashes directly and mark both changed + " the user will presumably decide what to do after checking the actual diff + rs_result-lstate = zif_abapgit_definitions=>c_state-modified. + rs_result-rstate = zif_abapgit_definitions=>c_state-modified. + ENDIF. + + ENDMETHOD. + METHOD build_new_local. + + " Item + rs_result-obj_type = is_local-item-obj_type. + rs_result-obj_name = is_local-item-obj_name. + rs_result-package = is_local-item-devclass. + rs_result-srcsystem = is_local-item-srcsystem. + rs_result-origlang = is_local-item-origlang. + rs_result-inactive = is_local-item-inactive. + + " File + rs_result-path = is_local-file-path. + rs_result-filename = is_local-file-filename. + + " Match + rs_result-match = abap_false. + rs_result-lstate = zif_abapgit_definitions=>c_state-added. + + ENDMETHOD. + METHOD build_new_remote. + + DATA ls_item LIKE LINE OF it_items_idx. + DATA ls_file_sig LIKE LINE OF it_state_idx. + + " Common and default part + rs_result-path = is_remote-path. + rs_result-filename = is_remote-filename. + rs_result-match = abap_false. + rs_result-rstate = zif_abapgit_definitions=>c_state-added. + + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = is_remote-filename + iv_path = is_remote-path + iv_devclass = mv_root_package + io_dot = mo_dot + IMPORTING + es_item = ls_item ). + + " Check if in item index + get package + READ TABLE it_items_idx INTO ls_item + WITH KEY + obj_type = ls_item-obj_type + obj_name = ls_item-obj_name. + + IF sy-subrc = 0. + + " Completely new (xml, abap) and new file in an existing object + rs_result-obj_type = ls_item-obj_type. + rs_result-obj_name = ls_item-obj_name. + rs_result-package = ls_item-devclass. + rs_result-srcsystem = ''. + rs_result-origlang = ''. + + READ TABLE it_state_idx INTO ls_file_sig + WITH KEY + path = is_remote-path + filename = is_remote-filename. + + " Existing file but from another package + " was not added during local file proc as was not in tadir for repo package + IF sy-subrc = 0. + IF ls_file_sig-sha1 = is_remote-sha1. + rs_result-match = abap_true. + CLEAR rs_result-rstate. + ELSE. + rs_result-rstate = zif_abapgit_definitions=>c_state-modified. + ENDIF. + + " Item is in state and in cache but with no package - it was deleted + " OR devclass is the same as repo package (see #532) + IF ls_item-devclass IS INITIAL OR ls_item-devclass = mv_root_package. + rs_result-match = abap_false. + rs_result-lstate = zif_abapgit_definitions=>c_state-deleted. + ENDIF. + ENDIF. + + ELSE. " Completely unknown file, probably non-abapgit + ASSERT 1 = 1. " No action, just follow defaults + ENDIF. + + ENDMETHOD. + METHOD check_local_remote_consistency. + IF is_remote-sha1 IS INITIAL. + IF is_local-file-filename = zcl_abapgit_filename_logic=>c_package_file. + zcx_abapgit_exception=>raise( + |Package name conflict { is_local-item-obj_type } { is_local-item-obj_name }. | && + |Rename package or use FULL folder logic| ). + ELSE. + zcx_abapgit_exception=>raise( + |Checksum conflict { is_local-item-obj_type } { is_local-item-obj_name }. | && + |Please create an issue on Github| ). + ENDIF. + ENDIF. + ENDMETHOD. + METHOD constructor. + mv_root_package = iv_root_package. + mo_dot = io_dot. + ENDMETHOD. + METHOD ensure_state. + + FIELD-SYMBOLS LIKE LINE OF rt_state. + FIELD-SYMBOLS LIKE LINE OF it_local. + + IF lines( it_cur_state ) = 0. + " Empty state is usually not expected. Maybe for new repos. + " In this case suppose the local state is unchanged + LOOP AT it_local ASSIGNING . + APPEND INITIAL LINE TO rt_state ASSIGNING . + MOVE-CORRESPONDING -file TO . + ENDLOOP. + ELSE. + rt_state = it_cur_state. + ENDIF. + + ENDMETHOD. + METHOD get_instance. + + CREATE OBJECT ri_instance TYPE zcl_abapgit_status_calc + EXPORTING + iv_root_package = iv_root_package + io_dot = io_dot. + + ENDMETHOD. + METHOD get_object_package. + DATA: lv_name TYPE devclass, + li_package TYPE REF TO zif_abapgit_sap_package. + + rv_devclass = zcl_abapgit_factory=>get_tadir( )->get_object_package( + iv_object = iv_object + iv_obj_name = iv_obj_name ). + IF rv_devclass IS INITIAL AND iv_object = 'DEVC' AND iv_obj_name(1) = '$'. + " local packages usually have no tadir entry + lv_name = iv_obj_name. + li_package = zcl_abapgit_factory=>get_sap_package( lv_name ). + IF li_package->exists( ) = abap_true. + rv_devclass = lv_name. + ENDIF. + ENDIF. + ENDMETHOD. + METHOD process_items. + + DATA: + ls_item LIKE LINE OF ct_items, + lv_is_xml TYPE abap_bool, + lv_is_json TYPE abap_bool, + lv_sub_fetched TYPE abap_bool, + lt_sub_packages TYPE SORTED TABLE OF devclass WITH UNIQUE KEY table_line. + + FIELD-SYMBOLS LIKE LINE OF it_unprocessed_remote. + + LOOP AT it_unprocessed_remote ASSIGNING . + + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = -filename + iv_path = -path + io_dot = mo_dot + iv_devclass = mv_root_package + IMPORTING + es_item = ls_item + ev_is_xml = lv_is_xml + ev_is_json = lv_is_json ). + + CHECK lv_is_xml = abap_true OR lv_is_json = abap_true. " only object definitions + + ls_item-devclass = get_object_package( + iv_object = ls_item-obj_type + iv_obj_name = ls_item-obj_name ). + + IF ls_item-devclass IS NOT INITIAL AND mv_root_package <> ls_item-devclass. + IF lv_sub_fetched = abap_false. + lt_sub_packages = zcl_abapgit_factory=>get_sap_package( mv_root_package )->list_subpackages( ). + lv_sub_fetched = abap_true. + ENDIF. + + " Make sure the package is under the repo main package + READ TABLE lt_sub_packages TRANSPORTING NO FIELDS + WITH KEY table_line = ls_item-devclass. + IF sy-subrc <> 0 AND ls_item-obj_type = 'DEVC'. + CLEAR ls_item-devclass. + ENDIF. + ENDIF. + + APPEND ls_item TO ct_items. + ENDLOOP. + + ENDMETHOD. + METHOD process_local. + + FIELD-SYMBOLS: + LIKE LINE OF ct_remote, + LIKE LINE OF ct_results, + LIKE LINE OF it_state_idx, + LIKE LINE OF it_local. + + LOOP AT it_local ASSIGNING . + " Skip ignored files + CHECK mo_dot->is_ignored( + iv_path = -file-path + iv_filename = -file-filename ) = abap_false. + + IF -item IS NOT INITIAL + AND zcl_abapgit_filename_logic=>is_obj_definition_file( -file-filename ) = abap_true. + " Collect for item index + APPEND -item TO ct_items. + ENDIF. + + APPEND INITIAL LINE TO ct_results ASSIGNING . + + " Find a match in remote + READ TABLE ct_remote ASSIGNING + WITH KEY file_path + COMPONENTS + path = -file-path + filename = -file-filename. + IF sy-subrc = 0. " Both local and remote exist + check_local_remote_consistency( + is_local = + is_remote = ). + = build_existing( + is_local = + is_remote = + it_state = it_state_idx ). + CLEAR -sha1. " Mark as processed + ELSE. " Only local exists + = build_new_local( ). + " Check if same file exists in different location + READ TABLE ct_remote ASSIGNING + WITH KEY file + COMPONENTS filename = -file-filename. + IF sy-subrc = 0 AND -file-sha1 = -sha1. + " If yes, then it was probably moved + -packmove = abap_true. + ELSEIF sy-subrc = 4. + " Check if file existed before and was deleted remotely + READ TABLE it_state_idx ASSIGNING + WITH KEY + path = -file-path + filename = -file-filename. + IF sy-subrc = 0. + IF -file-sha1 = -sha1. + -lstate = zif_abapgit_definitions=>c_state-unchanged. + ELSE. + -lstate = zif_abapgit_definitions=>c_state-modified. + ENDIF. + -rstate = zif_abapgit_definitions=>c_state-deleted. " ?? + ENDIF. + ENDIF. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD process_remote. + + FIELD-SYMBOLS: + LIKE LINE OF it_unprocessed_remote, + LIKE LINE OF ct_results, + LIKE LINE OF it_local. + + LOOP AT it_unprocessed_remote ASSIGNING . + + APPEND INITIAL LINE TO ct_results ASSIGNING . + + = build_new_remote( + is_remote = + it_items_idx = it_items_idx + it_state_idx = it_state_idx ). + + " Check if same file exists in different location (not for generic package files) + READ TABLE it_local ASSIGNING + WITH KEY file-filename = -filename. + IF sy-subrc = 0 AND -filename <> zcl_abapgit_filename_logic=>c_package_file. + -match = abap_false. + -lstate = zif_abapgit_definitions=>c_state-deleted. + -rstate = zif_abapgit_definitions=>c_state-unchanged. + IF -file-sha1 = -sha1. + -packmove = abap_true. + ENDIF. + ELSE. + " Check if file existed before and was deleted locally + READ TABLE it_state_idx TRANSPORTING NO FIELDS + WITH KEY + path = -path + filename = -filename. + IF sy-subrc = 0. + -match = abap_false. + -lstate = zif_abapgit_definitions=>c_state-deleted. + ENDIF. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_status_calc~calculate_status. + + DATA: + lt_remote LIKE it_remote, + lt_items TYPE zif_abapgit_definitions=>ty_items_tt, + lt_items_by_obj TYPE zif_abapgit_definitions=>ty_items_ts, " Sorted by obj_type+obj_name + lt_state_by_file TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts. " Sorted by path+filename + + lt_state_by_file = ensure_state( " Index by file + it_cur_state = it_cur_state + it_local = it_local ). + lt_remote = it_remote. + + " Process local files and new local files + process_local( + EXPORTING + it_local = it_local + it_state_idx = lt_state_by_file + CHANGING + ct_remote = lt_remote + ct_items = lt_items + ct_results = rt_results ). + + " Remove processed remotes (with cleared SHA1) + DELETE lt_remote WHERE sha1 IS INITIAL. + + " Complete item index for unmarked remote files + process_items( " TODO: rename ? + EXPORTING + it_unprocessed_remote = lt_remote + CHANGING + ct_items = lt_items ). + + " The item list was not unique by now, just collected as "mention" list + SORT lt_items DESCENDING. " Default key - type, name, pkg, ... + DELETE ADJACENT DUPLICATES FROM lt_items COMPARING obj_type obj_name. + lt_items_by_obj = lt_items. + + " Process new remote files (marked above with empty SHA1) + process_remote( + EXPORTING + it_local = it_local + it_unprocessed_remote = lt_remote + it_state_idx = lt_state_by_file + it_items_idx = lt_items_by_obj + CHANGING + ct_results = rt_results ). + + SORT rt_results BY + obj_type ASCENDING + obj_name ASCENDING + filename ASCENDING + path ASCENDING. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_stage_logic IMPLEMENTATION. + METHOD get_stage_logic. + + IF gi_stage_logic IS INITIAL. + CREATE OBJECT gi_stage_logic TYPE zcl_abapgit_stage_logic. + ENDIF. + + ri_logic = gi_stage_logic. + + ENDMETHOD. + METHOD remove_identical. + + DATA: lv_index TYPE i, + ls_remote LIKE LINE OF cs_files-remote. + + FIELD-SYMBOLS: LIKE LINE OF cs_files-local. + + SORT cs_files-remote BY path filename. + + LOOP AT cs_files-local ASSIGNING . + lv_index = sy-tabix. + + READ TABLE cs_files-remote INTO ls_remote + WITH KEY path = -file-path filename = -file-filename + BINARY SEARCH. + IF sy-subrc = 0. + DELETE cs_files-remote INDEX sy-tabix. + IF ls_remote-sha1 = -file-sha1. + DELETE cs_files-local INDEX lv_index. + ENDIF. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD remove_ignored. + + DATA: lv_index TYPE i. + + FIELD-SYMBOLS: LIKE LINE OF cs_files-remote, + LIKE LINE OF cs_files-local. + LOOP AT cs_files-remote ASSIGNING . + lv_index = sy-tabix. + + IF ii_repo->get_dot_abapgit( )->is_ignored( + iv_path = -path + iv_filename = -filename ) = abap_true. + DELETE cs_files-remote INDEX lv_index. + ELSEIF -path = zif_abapgit_definitions=>c_root_dir + AND -filename = zif_abapgit_definitions=>c_dot_abapgit. + " Remove .abapgit from remotes - it cannot be removed or ignored + DELETE cs_files-remote INDEX lv_index. + ENDIF. + + ENDLOOP. + + LOOP AT cs_files-local ASSIGNING . + lv_index = sy-tabix. + + IF ii_repo->get_dot_abapgit( )->is_ignored( + iv_path = -file-path + iv_filename = -file-filename ) = abap_true. + DELETE cs_files-local INDEX lv_index. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD set_stage_logic. + gi_stage_logic = ii_logic. + ENDMETHOD. + METHOD zif_abapgit_stage_logic~get. + + " Getting REMOTE before LOCAL is critical to ensure that DATA config is loaded first + rs_files-remote = ii_repo_online->get_files_remote( ii_obj_filter ). + + IF ii_obj_filter IS INITIAL. + rs_files-local = ii_repo_online->get_files_local( ). + ELSE. + rs_files-local = ii_repo_online->get_files_local_filtered( ii_obj_filter ). + ENDIF. + + rs_files-status = zcl_abapgit_repo_status=>calculate( ii_repo = ii_repo_online + ii_obj_filter = ii_obj_filter ). + + remove_identical( CHANGING cs_files = rs_files ). + remove_ignored( EXPORTING ii_repo = ii_repo_online + CHANGING cs_files = rs_files ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_stage IMPLEMENTATION. + METHOD add. + + append( iv_path = iv_path + iv_filename = iv_filename + iv_method = zif_abapgit_definitions=>c_method-add + is_status = is_status + iv_data = iv_data ). + + ENDMETHOD. + METHOD append. + + DATA: ls_stage LIKE LINE OF mt_stage. + + FIELD-SYMBOLS: LIKE LINE OF mt_stage. + READ TABLE mt_stage WITH KEY + file-path = iv_path + file-filename = iv_filename + ASSIGNING . + IF sy-subrc = 0. + -file-data = iv_data. + -method = iv_method. + ELSE. + ls_stage-file-path = iv_path. + ls_stage-file-filename = iv_filename. + ls_stage-file-data = iv_data. + ls_stage-method = iv_method. + ls_stage-status = is_status. + INSERT ls_stage INTO TABLE mt_stage. + ENDIF. + + ENDMETHOD. + METHOD constructor. + mv_merge_source = iv_merge_source. + ENDMETHOD. + METHOD count. + rv_count = lines( mt_stage ). + ENDMETHOD. + METHOD get_all. + rt_stage = mt_stage. + ENDMETHOD. + METHOD get_merge_source. + rv_source = mv_merge_source. + ENDMETHOD. + METHOD ignore. + append( iv_path = iv_path + iv_filename = iv_filename + iv_method = zif_abapgit_definitions=>c_method-ignore ). + ENDMETHOD. + METHOD method_description. + + CASE iv_method. + WHEN zif_abapgit_definitions=>c_method-add. + rv_description = 'add'. + WHEN zif_abapgit_definitions=>c_method-rm. + rv_description = 'remove'. + WHEN zif_abapgit_definitions=>c_method-ignore. + rv_description = 'ignore'. + WHEN OTHERS. + zcx_abapgit_exception=>raise( 'unknown staging method type' ). + ENDCASE. + + ENDMETHOD. + METHOD reset. + DELETE mt_stage WHERE file-path = iv_path AND file-filename = iv_filename. + ASSERT sy-subrc = 0. + ENDMETHOD. + METHOD rm. + append( iv_path = iv_path + iv_filename = iv_filename + is_status = is_status + iv_method = zif_abapgit_definitions=>c_method-rm ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_merge IMPLEMENTATION. + METHOD all_files. + + APPEND LINES OF ms_merge-stree TO rt_files. + APPEND LINES OF ms_merge-ttree TO rt_files. + APPEND LINES OF ms_merge-ctree TO rt_files. + SORT rt_files BY path DESCENDING name ASCENDING. + DELETE ADJACENT DUPLICATES FROM rt_files COMPARING path name. + + ENDMETHOD. + METHOD calculate_result. + + DATA: lt_files TYPE zif_abapgit_git_definitions=>ty_expanded_tt, + lv_found_source TYPE abap_bool, + lv_found_target TYPE abap_bool, + lv_found_common TYPE abap_bool. + + FIELD-SYMBOLS: LIKE LINE OF lt_files, + LIKE LINE OF lt_files, + LIKE LINE OF lt_files, + LIKE LINE OF lt_files, + LIKE LINE OF ms_merge-result, + LIKE LINE OF mt_objects, + LIKE LINE OF mt_conflicts. + + lt_files = all_files( ). + + CREATE OBJECT ms_merge-stage + EXPORTING + iv_merge_source = ms_merge-source-sha1. + + LOOP AT lt_files ASSIGNING . + + UNASSIGN . + UNASSIGN . + UNASSIGN . + + READ TABLE ms_merge-stree ASSIGNING + WITH KEY path_name + COMPONENTS path = -path name = -name. "#EC CI_SUBRC + READ TABLE ms_merge-ttree ASSIGNING + WITH KEY path_name + COMPONENTS path = -path name = -name. "#EC CI_SUBRC + READ TABLE ms_merge-ctree ASSIGNING + WITH KEY path_name + COMPONENTS path = -path name = -name. "#EC CI_SUBRC + + lv_found_source = boolc( IS ASSIGNED ). + lv_found_target = boolc( IS ASSIGNED ). + lv_found_common = boolc( IS ASSIGNED ). + + IF lv_found_source = abap_false + AND lv_found_target = abap_false. +* deleted in source and target, skip + CONTINUE. + ELSEIF lv_found_source = abap_false + AND lv_found_common = abap_true + AND -sha1 = -sha1. +* deleted in source, skip + ms_merge-stage->rm( iv_path = -path + iv_filename = -name ). + CONTINUE. + ELSEIF lv_found_target = abap_false + AND lv_found_common = abap_true + AND -sha1 = -sha1. +* deleted in target, skip + CONTINUE. + ENDIF. + + APPEND INITIAL LINE TO ms_merge-result ASSIGNING . + -path = -path. + -name = -name. + + IF lv_found_target = abap_false. +* added in source + READ TABLE mt_objects ASSIGNING + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-blob + sha1 = -sha1. + ASSERT sy-subrc = 0. + + ms_merge-stage->add( iv_path = -path + iv_filename = -name + iv_data = -data ). + -sha1 = -sha1. + CONTINUE. + ELSEIF lv_found_source = abap_false. +* added in target + -sha1 = -sha1. + ELSEIF lv_found_common = abap_false + AND -sha1 = -sha1. +* added in source and target + -sha1 = -sha1. + ELSEIF lv_found_common = abap_false + AND -sha1 <> -sha1. + + INSERT INITIAL LINE INTO TABLE mt_conflicts ASSIGNING . + -path = -path. + -filename = -name. + -source_sha1 = -sha1. + READ TABLE mt_objects ASSIGNING + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-blob + sha1 = -sha1. + -source_data = -data. + + -target_sha1 = -sha1. + READ TABLE mt_objects ASSIGNING + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-blob + sha1 = -sha1. + -target_data = -data. + +* added in source and target, but different, merge conflict must be resolved + ms_merge-conflict = |{ -name } merge conflict|. + CONTINUE. + ENDIF. + + IF lv_found_source = abap_false + OR lv_found_target = abap_false + OR lv_found_common = abap_false. + ms_merge-conflict = |{ -name } merge conflict, not found anywhere|. + CONTINUE. + ENDIF. + + IF -sha1 = -sha1. +* target and source match + -sha1 = -sha1. + ELSEIF -sha1 = -sha1. +* changed in source + READ TABLE mt_objects ASSIGNING + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-blob + sha1 = -sha1. + ASSERT sy-subrc = 0. + + ms_merge-stage->add( iv_path = -path + iv_filename = -name + iv_data = -data ). + -sha1 = -sha1. + ELSEIF -sha1 = -sha1. +* changed in target + -sha1 = -sha1. + ELSE. +* changed in source and target, conflict +* conflict must be resolved before merge + INSERT INITIAL LINE INTO TABLE mt_conflicts ASSIGNING . + -path = -path. + -filename = -name. + -source_sha1 = -sha1. + READ TABLE mt_objects ASSIGNING + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-blob + sha1 = -sha1. + -source_data = -data. + + -target_sha1 = -sha1. + READ TABLE mt_objects ASSIGNING + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-blob + sha1 = -sha1. + -target_data = -data. + + ms_merge-conflict = |{ -name } merge conflict, changed in source and target branch|. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + + IF iv_source_branch = ii_repo_online->get_selected_branch( ). + zcx_abapgit_exception=>raise( 'source = target' ). + ENDIF. + + mi_repo_online = ii_repo_online. + mv_source_branch = iv_source_branch. + + ENDMETHOD. + METHOD fetch_git. + + DATA: li_branch_list TYPE REF TO zif_abapgit_git_branch_list, + lt_upload TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. + + li_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( ms_merge-repo_online->get_url( ) ). + + ms_merge-source = li_branch_list->find_by_name( + zcl_abapgit_git_branch_utils=>complete_heads_branch_name( mv_source_branch ) ). + + ms_merge-target = li_branch_list->find_by_name( + zcl_abapgit_git_branch_utils=>complete_heads_branch_name( mi_repo_online->get_selected_branch( ) ) ). + + APPEND ms_merge-source TO lt_upload. + APPEND ms_merge-target TO lt_upload. + + zcl_abapgit_git_transport=>upload_pack_by_branch( + EXPORTING + iv_url = ms_merge-repo_online->get_url( ) + iv_branch_name = ms_merge-repo_online->get_selected_branch( ) + iv_deepen_level = 0 + it_branches = lt_upload + IMPORTING + et_objects = rt_objects ). + + ENDMETHOD. + METHOD find_ancestors. + + DATA: ls_commit TYPE zcl_abapgit_git_pack=>ty_commit, + lt_visit TYPE ty_visit_tt, + lv_commit LIKE LINE OF lt_visit. + + FIELD-SYMBOLS: LIKE LINE OF rt_ancestors, + LIKE LINE OF mt_objects. + APPEND iv_commit TO lt_visit. + + LOOP AT lt_visit INTO lv_commit. + READ TABLE mt_objects ASSIGNING + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-commit + sha1 = lv_commit. + ASSERT sy-subrc = 0. + + ls_commit = zcl_abapgit_git_pack=>decode_commit( -data ). + + visit( EXPORTING iv_parent = ls_commit-parent + CHANGING ct_visit = lt_visit ). + visit( EXPORTING iv_parent = ls_commit-parent2 + CHANGING ct_visit = lt_visit ). + + APPEND INITIAL LINE TO rt_ancestors ASSIGNING . + -commit = lv_commit. + -tree = ls_commit-tree. + -body = ls_commit-body. + -time = ls_commit-author. + + "Strip Author entry of all but the time component + REPLACE ALL OCCURRENCES OF REGEX '[a-zA-Z<>@.-]*' IN -time WITH ''. + CONDENSE -time. + ENDLOOP. + + SORT rt_ancestors BY time DESCENDING. + + ENDMETHOD. + METHOD find_first_common. + + FIELD-SYMBOLS: LIKE LINE OF it_list1, + LIKE LINE OF it_list2. + + LOOP AT it_list1 ASSIGNING . + LOOP AT it_list2 ASSIGNING . + IF -tree = -tree. + rs_common = . + RETURN. + ENDIF. + ENDLOOP. + ENDLOOP. + + zcx_abapgit_exception=>raise( 'error finding common ancestor' ). + + ENDMETHOD. + METHOD visit. + + IF NOT iv_parent IS INITIAL. + READ TABLE ct_visit FROM iv_parent TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + APPEND iv_parent TO ct_visit. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_merge~get_conflicts. + + rt_conflicts = mt_conflicts. + + ENDMETHOD. + METHOD zif_abapgit_merge~get_result. + + rs_merge = ms_merge. + + ENDMETHOD. + METHOD zif_abapgit_merge~get_source_branch. + + rv_source_branch = mv_source_branch. + + ENDMETHOD. + METHOD zif_abapgit_merge~has_conflicts. + + rv_conflicts_exists = boolc( lines( mt_conflicts ) > 0 ). + + ENDMETHOD. + METHOD zif_abapgit_merge~resolve_conflict. + + FIELD-SYMBOLS: TYPE zif_abapgit_merge=>ty_merge_conflict, + LIKE LINE OF ms_merge-result. + + IF is_conflict-result_sha1 IS NOT INITIAL + AND is_conflict-result_data IS NOT INITIAL. + READ TABLE mt_conflicts ASSIGNING WITH KEY path = is_conflict-path + filename = is_conflict-filename. + IF sy-subrc = 0. + READ TABLE ms_merge-result ASSIGNING + WITH KEY path_name + COMPONENTS path = is_conflict-path name = is_conflict-filename. + IF sy-subrc = 0. + -sha1 = is_conflict-result_sha1. + + ms_merge-stage->add( iv_path = -path + iv_filename = -filename + iv_data = is_conflict-result_data ). + + DELETE mt_conflicts WHERE path = is_conflict-path + AND filename = is_conflict-filename. + ENDIF. + + READ TABLE ms_merge-result ASSIGNING WITH KEY sha1 = space. + IF sy-subrc = 0. + ms_merge-conflict = |{ -name } merge conflict, changed in source and target branch|. + ELSE. + CLEAR ms_merge-conflict. + ENDIF. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_merge~run. + + DATA: lt_asource TYPE ty_ancestor_tt, + lt_atarget TYPE ty_ancestor_tt. + + CLEAR: ms_merge, mt_objects, mt_conflicts. + + ms_merge-repo_online = mi_repo_online. + mt_objects = fetch_git( ). + + lt_asource = find_ancestors( ms_merge-source-sha1 ). + lt_atarget = find_ancestors( ms_merge-target-sha1 ). + + ms_merge-common = find_first_common( it_list1 = lt_asource + it_list2 = lt_atarget ). + + ms_merge-stree = zcl_abapgit_git_porcelain=>full_tree( + it_objects = mt_objects + iv_parent = ms_merge-source-sha1 ). + ms_merge-ttree = zcl_abapgit_git_porcelain=>full_tree( + it_objects = mt_objects + iv_parent = ms_merge-target-sha1 ). + ms_merge-ctree = zcl_abapgit_git_porcelain=>full_tree( + it_objects = mt_objects + iv_parent = ms_merge-common-commit ). + + calculate_result( ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_repo_filter IMPLEMENTATION. + METHOD apply. + + DATA: lt_filter TYPE SORTED TABLE OF zif_abapgit_definitions=>ty_tadir + WITH NON-UNIQUE KEY object obj_name, + lv_index TYPE i. + + FIELD-SYMBOLS: LIKE LINE OF ct_tadir. + + IF lines( it_filter ) = 0. + RETURN. + ENDIF. + + lt_filter = it_filter. + +* this is another loop at TADIR, but typically the filter is blank + LOOP AT ct_tadir ASSIGNING . + lv_index = sy-tabix. + READ TABLE lt_filter TRANSPORTING NO FIELDS WITH KEY object = -object + obj_name = -obj_name + BINARY SEARCH. + IF sy-subrc <> 0. + DELETE ct_tadir INDEX lv_index. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD apply_object_filter. + DATA lr_file TYPE REF TO zif_abapgit_git_definitions=>ty_file. + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + DATA ls_tadir TYPE zif_abapgit_definitions=>ty_tadir. + DATA lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lt_filter TYPE SORTED TABLE OF zif_abapgit_definitions=>ty_tadir + WITH NON-UNIQUE KEY object obj_name. + + lt_filter = it_filter. + + LOOP AT ct_files REFERENCE INTO lr_file. + IF lr_file->filename = zif_abapgit_definitions=>c_dot_abapgit. + CONTINUE. + ENDIF. + + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = lr_file->filename + iv_path = lr_file->path + iv_devclass = iv_devclass + io_dot = io_dot + IMPORTING + es_item = ls_item ). + + CLEAR lt_tadir. + CLEAR ls_tadir. + + ls_tadir-object = ls_item-obj_type. + ls_tadir-obj_name = ls_item-obj_name. + ls_tadir-devclass = ls_item-devclass. + + INSERT ls_tadir INTO TABLE lt_tadir. + + READ TABLE lt_filter TRANSPORTING NO FIELDS + WITH KEY object = ls_tadir-object + obj_name = ls_tadir-obj_name + BINARY SEARCH. + + IF sy-subrc <> 0. + DELETE ct_files. + ENDIF. + + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_filter_tran IMPLEMENTATION. + METHOD adjust_local_filter. + + DATA lt_e071_filter TYPE ty_e071_filter_tt. + DATA lr_e071_filter TYPE REF TO ty_e071_filter. + DATA ls_filter TYPE zif_abapgit_definitions=>ty_tadir. + DATA lv_trobj_name_new TYPE trobj_name. + DATA lv_trobj_type_new TYPE tadir-object. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lr_cts_api TYPE REF TO zif_abapgit_cts_api. + + lt_e071_filter = it_e071_filter. + + LOOP AT lt_e071_filter REFERENCE INTO lr_e071_filter. + + IF lr_e071_filter->pgmid = 'LIMU'. + "Get Main Object from LIMU Object (Example the Class (R3TR) of a Method (LIMU)) + + lr_cts_api = zcl_abapgit_factory=>get_cts_api( ). + + TRY. + lr_cts_api->get_r3tr_obj_for_limu_obj( + EXPORTING + iv_object = lr_e071_filter->object + iv_obj_name = lr_e071_filter->obj_name + IMPORTING + ev_object = lv_trobj_type_new + ev_obj_name = lv_trobj_name_new ). + CATCH zcx_abapgit_exception. + CONTINUE. + ENDTRY. + + CLEAR ls_filter. + ls_filter-pgmid = 'R3TR'. + ls_filter-object = lv_trobj_type_new. + ls_filter-obj_name = lv_trobj_name_new. + ELSE. + ls_filter-pgmid = lr_e071_filter->pgmid. + ls_filter-object = lr_e071_filter->object. + ls_filter-obj_name = lr_e071_filter->obj_name. + ENDIF. + INSERT ls_filter INTO TABLE rt_filter. + ENDLOOP. + + IF iv_package IS NOT INITIAL. + ls_filter-pgmid = 'R3TR'. + ls_filter-object = 'DEVC'. + ls_filter-obj_name = iv_package. + INSERT ls_filter INTO TABLE rt_filter. + + lt_filter = get_all_sub_packages( iv_package ). + INSERT LINES OF lt_filter INTO TABLE rt_filter. + + ENDIF. + + SORT rt_filter. + DELETE ADJACENT DUPLICATES FROM rt_filter. + + IF rt_filter IS INITIAL. + + zcx_abapgit_exception=>raise( 'No objects found for transport filter' ). + + ENDIF. + + ENDMETHOD. + METHOD generate_local_filter. + DATA lt_e071_filter TYPE ty_e071_filter_tt. + + SELECT DISTINCT pgmid object obj_name + INTO CORRESPONDING FIELDS OF TABLE lt_e071_filter + FROM e071 + WHERE trkorr IN it_r_trkorr + ORDER BY pgmid object obj_name. + IF sy-subrc <> 0. + CLEAR lt_e071_filter. + ENDIF. + rt_filter = adjust_local_filter( + iv_package = iv_package + it_e071_filter = lt_e071_filter ). + ENDMETHOD. + METHOD get_all_sub_packages. + + DATA li_package TYPE REF TO zif_abapgit_sap_package. + DATA lt_list TYPE zif_abapgit_sap_package=>ty_devclass_tt. + DATA lr_list TYPE REF TO devclass. + DATA ls_filter TYPE zif_abapgit_definitions=>ty_tadir. + + li_package = zcl_abapgit_factory=>get_sap_package( iv_package ). + lt_list = li_package->list_subpackages( ). + LOOP AT lt_list REFERENCE INTO lr_list. + ls_filter-pgmid = 'R3TR'. + ls_filter-object = 'DEVC'. + ls_filter-obj_name = lr_list->*. + INSERT ls_filter INTO TABLE rt_filter. + ENDLOOP. + + ENDMETHOD. + METHOD get_filter_values. + et_r_trkorr = mt_r_trkorr. + ev_package = mv_package. + ENDMETHOD. + METHOD init. + CLEAR mt_filter. + CLEAR mt_r_trkorr. + CLEAR mv_package. + ENDMETHOD. + METHOD set_filter_values. + init( ). + mt_r_trkorr = it_r_trkorr. + mv_package = iv_package. + IF it_r_trkorr IS NOT INITIAL. + mt_filter = generate_local_filter( + iv_package = mv_package + it_r_trkorr = mt_r_trkorr ). + + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object_filter~get_filter. + rt_filter = mt_filter. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_filter_obj IMPLEMENTATION. + METHOD constructor. + mt_filter = it_filter. + ENDMETHOD. + + METHOD zif_abapgit_object_filter~get_filter. + rt_filter = mt_filter. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_persistence_user IMPLEMENTATION. + METHOD constructor. + mv_user = iv_user. + read( ). + ENDMETHOD. + METHOD from_xml. + + DATA: lv_xml TYPE string. + + lv_xml = iv_xml. + +* fix downward compatibility + REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_USER_--29>' IN lv_xml WITH ''. + REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. + + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML lv_xml + RESULT user = rs_user. + ENDMETHOD. + METHOD read. + + DATA: lv_xml TYPE string. + + TRY. + lv_xml = zcl_abapgit_persistence_db=>get_instance( )->read( + iv_type = zcl_abapgit_persistence_db=>c_type_user + iv_value = mv_user ). + CATCH zcx_abapgit_not_found. + RETURN. + ENDTRY. + + ms_user = from_xml( lv_xml ). + + ENDMETHOD. + METHOD read_repo_config. + DATA lv_url TYPE string. + lv_url = to_lower( iv_url ). + READ TABLE ms_user-repo_config INTO rs_repo_config WITH KEY url = lv_url. + ENDMETHOD. + METHOD to_xml. + CALL TRANSFORMATION id + SOURCE user = is_user + RESULT XML rv_xml. + ENDMETHOD. + METHOD update. + + DATA: lv_xml TYPE string. + + lv_xml = to_xml( ms_user ). + + zcl_abapgit_persistence_db=>get_instance( )->modify( + iv_type = zcl_abapgit_persistence_db=>c_type_user + iv_value = mv_user + iv_data = lv_xml ). + + COMMIT WORK AND WAIT. + + ENDMETHOD. + METHOD update_repo_config. + + DATA: lv_key TYPE string. + + FIELD-SYMBOLS TYPE ty_repo_config. + + lv_key = to_lower( iv_url ). + + READ TABLE ms_user-repo_config ASSIGNING WITH KEY url = lv_key. + IF sy-subrc IS NOT INITIAL. + APPEND INITIAL LINE TO ms_user-repo_config ASSIGNING . + ENDIF. + = is_repo_config. + -url = lv_key. + + update( ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_changes_only. + + rv_changes_only = ms_user-changes_only. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_default_git_user_email. + + rv_email = ms_user-settings-default_git_email. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_default_git_user_name. + + rv_username = ms_user-settings-default_git_uname. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_diff_first. + rv_diff_first = ms_user-diff_first. + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_diff_unified. + + rv_diff_unified = ms_user-diff_unified. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_favorites. + + rt_favorites = ms_user-favorites. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_hide_files. + + rv_hide = ms_user-hide_files. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_list_settings. + + rs_list_settings = ms_user-list_settings. + + IF rs_list_settings IS INITIAL. + " for performance reasons, set "only favorites" as a default + IF zcl_abapgit_repo_srv=>get_instance( )->list_favorites( ) IS NOT INITIAL. + rs_list_settings-only_favorites = abap_true. + ENDIF. + + rs_list_settings-order_by = |NAME|. + ENDIF. + + ENDMETHOD. + + METHOD zif_abapgit_persist_user~get_flow_settings. + rs_flow_settings = ms_user-flow_settings. + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_order_by. + rv_order_by = ms_user-order_by. + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_order_descending. + rv_order_descending = ms_user-order_descending. + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_repo_git_user_email. + + rv_email = read_repo_config( iv_url )-git_user-email. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_repo_git_user_name. + + rv_username = read_repo_config( iv_url )-git_user-name. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_repo_last_change_seen. + + rv_version = read_repo_config( iv_url )-last_change_seen. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_repo_login. + + rv_login = read_repo_config( iv_url )-login. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_repo_show. + + rv_key = ms_user-repo_show. + + IF rv_key IS INITIAL. + RETURN. + ENDIF. + + " Check if repo exists + TRY. + zcl_abapgit_persistence_db=>get_instance( )->read( + iv_type = zcl_abapgit_persistence_db=>c_type_repo + iv_value = rv_key ). + CATCH zcx_abapgit_not_found. + " remove invalid key + CLEAR rv_key. + zif_abapgit_persist_user~set_repo_show( rv_key ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_settings. + + rs_user_settings = ms_user-settings. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~get_show_folders. + + rv_folders = ms_user-show_folders. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~is_favorite_repo. + + READ TABLE ms_user-favorites TRANSPORTING NO FIELDS + WITH KEY table_line = iv_repo_key. + + rv_yes = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_default_git_user_email. + + ms_user-settings-default_git_email = iv_email. + update( ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_default_git_user_name. + + ms_user-settings-default_git_uname = iv_username. + update( ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_diff_first. + ms_user-diff_first = iv_diff_first. + update( ). + rv_diff_first = ms_user-diff_first. + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_list_settings. + ms_user-list_settings = is_list_settings. + update( ). + ENDMETHOD. + + METHOD zif_abapgit_persist_user~set_flow_settings. + ms_user-flow_settings = is_flow_settings. + update( ). + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_order_by. + ms_user-order_by = iv_order_by. + update( ). + rv_order_by = ms_user-order_by. + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_order_descending. + ms_user-order_descending = iv_order_descending. + update( ). + rv_order_descending = ms_user-order_descending. + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_repo_git_user_email. + + DATA: ls_repo_config TYPE ty_repo_config. + + ls_repo_config = read_repo_config( iv_url ). + ls_repo_config-git_user-email = iv_email. + update_repo_config( iv_url = iv_url + is_repo_config = ls_repo_config ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_repo_git_user_name. + + DATA: ls_repo_config TYPE ty_repo_config. + + ls_repo_config = read_repo_config( iv_url ). + ls_repo_config-git_user-name = iv_username. + update_repo_config( iv_url = iv_url + is_repo_config = ls_repo_config ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_repo_last_change_seen. + + DATA: ls_repo_config TYPE ty_repo_config. + + ls_repo_config = read_repo_config( iv_url ). + ls_repo_config-last_change_seen = iv_version. + update_repo_config( iv_url = iv_url + is_repo_config = ls_repo_config ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_repo_login. + + DATA: ls_repo_config TYPE ty_repo_config. + + ls_repo_config = read_repo_config( iv_url ). + ls_repo_config-login = iv_login. + update_repo_config( iv_url = iv_url + is_repo_config = ls_repo_config ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_repo_show. + + ms_user-repo_show = iv_key. + update( ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~set_settings. + + ms_user-settings = is_user_settings. + update( ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~toggle_changes_only. + + ms_user-changes_only = boolc( ms_user-changes_only = abap_false ). + update( ). + + rv_changes_only = ms_user-changes_only. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~toggle_diff_unified. + + ms_user-diff_unified = boolc( ms_user-diff_unified = abap_false ). + update( ). + + rv_diff_unified = ms_user-diff_unified. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~toggle_favorite. + + READ TABLE ms_user-favorites TRANSPORTING NO FIELDS + WITH KEY table_line = iv_repo_key. + + IF sy-subrc = 0. + DELETE ms_user-favorites INDEX sy-tabix. + ELSE. + APPEND iv_repo_key TO ms_user-favorites. + ENDIF. + + update( ). + + ENDMETHOD. + METHOD zif_abapgit_persist_user~toggle_hide_files. + + ms_user-hide_files = boolc( ms_user-hide_files = abap_false ). + update( ). + + rv_hide = ms_user-hide_files. + + ENDMETHOD. + METHOD zif_abapgit_persist_user~toggle_show_folders. + ms_user-show_folders = boolc( ms_user-show_folders = abap_false ). + update( ). + + rv_folders = ms_user-show_folders. + ENDMETHOD. +ENDCLASS. +CLASS zcl_abapgit_persistence_repo IMPLEMENTATION. + METHOD constructor. + + DATA ls_dummy_meta_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask. + DATA ls_dummy_meta TYPE zif_abapgit_persistence=>ty_repo_xml. + DATA lo_type_meta_mask TYPE REF TO cl_abap_structdescr. + DATA lo_type_meta TYPE REF TO cl_abap_structdescr. + FIELD-SYMBOLS LIKE LINE OF lo_type_meta_mask->components. + + " Collect actual list of fields in repo meta data (used in update_meta) + lo_type_meta_mask ?= cl_abap_structdescr=>describe_by_data( ls_dummy_meta_mask ). + lo_type_meta ?= cl_abap_structdescr=>describe_by_data( ls_dummy_meta ). + LOOP AT lo_type_meta_mask->components ASSIGNING . + APPEND -name TO mt_meta_fields. + ENDLOOP. + + mo_db = zcl_abapgit_persistence_db=>get_instance( ). + + ENDMETHOD. + METHOD from_xml. + + DATA: lv_xml TYPE string. + + lv_xml = iv_repo_xml_string. + +* fix downward compatibility + REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_REPO_--29>' IN lv_xml WITH ''. + REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. + + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML lv_xml + RESULT repo = rs_repo. + +* automatic migration of old fields +* todo, keep for transition period until 2022-12-31, then remove all of these + FIND FIRST OCCURRENCE OF 'X' IN lv_xml. + IF sy-subrc = 0. + rs_repo-local_settings-write_protected = abap_true. + ENDIF. + FIND FIRST OCCURRENCE OF 'X' IN lv_xml. + IF sy-subrc = 0. + rs_repo-local_settings-ignore_subpackages = abap_true. + ENDIF. + FIND FIRST OCCURRENCE OF 'X' IN lv_xml. + IF sy-subrc = 0. + rs_repo-local_settings-main_language_only = abap_true. + ENDIF. + + IF rs_repo IS INITIAL. + zcx_abapgit_exception=>raise( 'Inconsistent repo metadata' ). + ENDIF. + + ENDMETHOD. + METHOD get_next_id. + +* todo: Lock the complete persistence in order to prevent concurrent repo-creation +* however the current approach will most likely work in almost all cases + + DATA: lt_content TYPE zif_abapgit_persistence=>ty_contents. + + FIELD-SYMBOLS: LIKE LINE OF lt_content. + rv_next_repo_id = 1. + + lt_content = mo_db->list_by_type( zcl_abapgit_persistence_db=>c_type_repo ). + LOOP AT lt_content ASSIGNING . + IF -value >= rv_next_repo_id. + rv_next_repo_id = -value + 1. + ENDIF. + ENDLOOP. + + SHIFT rv_next_repo_id RIGHT DELETING TRAILING space. + TRANSLATE rv_next_repo_id USING ' 0'. + + ENDMETHOD. + METHOD get_repo_from_content. + MOVE-CORRESPONDING from_xml( is_content-data_str ) TO rs_result. + IF rs_result-local_settings-write_protected = abap_false + AND zcl_abapgit_factory=>get_environment( )->is_repo_object_changes_allowed( ) = abap_false. + rs_result-local_settings-write_protected = abap_true. + ENDIF. + rs_result-key = is_content-value. + ENDMETHOD. + METHOD rewrite_repo_meta. + + DATA lv_old_blob TYPE string. + DATA lv_new_blob TYPE string. + DATA ls_repo_meta TYPE zif_abapgit_persistence=>ty_repo. + + lv_old_blob = mo_db->read( + iv_type = zcl_abapgit_persistence_db=>c_type_repo + iv_value = iv_repo_key ). + + MOVE-CORRESPONDING from_xml( lv_old_blob ) TO ls_repo_meta. + lv_new_blob = to_xml( ls_repo_meta ). + + IF lv_new_blob <> lv_old_blob. + mo_db->update( + iv_type = zcl_abapgit_persistence_db=>c_type_repo + iv_value = iv_repo_key + iv_data = lv_new_blob ). + + COMMIT WORK. + ENDIF. + + ENDMETHOD. + METHOD to_xml. + + DATA: ls_xml TYPE zif_abapgit_persistence=>ty_repo_xml. + MOVE-CORRESPONDING is_repo TO ls_xml. + + CALL TRANSFORMATION id + SOURCE repo = ls_xml + RESULT XML rv_repo_xml_string. + ENDMETHOD. + METHOD zif_abapgit_persist_repo_cs~delete. + + mo_db->delete( + iv_type = zcl_abapgit_persistence_db=>c_type_repo_csum + iv_value = iv_key ). + + ENDMETHOD. + METHOD zif_abapgit_persist_repo_cs~read. + + rv_cs_blob = mo_db->read( + iv_type = zcl_abapgit_persistence_db=>c_type_repo_csum + iv_value = iv_key ). + + ENDMETHOD. + METHOD zif_abapgit_persist_repo_cs~update. + + mo_db->modify( + iv_type = zcl_abapgit_persistence_db=>c_type_repo_csum + iv_value = iv_key + iv_data = iv_cs_blob ). + + ENDMETHOD. + METHOD zif_abapgit_persist_repo~add. + + DATA: ls_repo TYPE zif_abapgit_persistence=>ty_repo, + lv_repo_as_xml TYPE string. + ls_repo-url = iv_url. + ls_repo-branch_name = iv_branch_name. + ls_repo-package = iv_package. + ls_repo-offline = iv_offline. + ls_repo-created_by = sy-uname. + GET TIME STAMP FIELD ls_repo-created_at. + ls_repo-dot_abapgit = is_dot_abapgit. + + ls_repo-local_settings-display_name = iv_display_name. + + lv_repo_as_xml = to_xml( ls_repo ). + + rv_key = get_next_id( ). + + mo_db->add( iv_type = zcl_abapgit_persistence_db=>c_type_repo + iv_value = rv_key + iv_data = lv_repo_as_xml ). + + ENDMETHOD. + METHOD zif_abapgit_persist_repo~delete. + + zcl_abapgit_persist_factory=>get_background( )->delete( iv_key ). + + mo_db->delete( iv_type = zcl_abapgit_persistence_db=>c_type_repo + iv_value = iv_key ). + + ENDMETHOD. + METHOD zif_abapgit_persist_repo~exists. + + DATA lt_keys TYPE zif_abapgit_persistence=>ty_repo_keys. + DATA lt_content TYPE zif_abapgit_persistence=>ty_contents. + + APPEND iv_key TO lt_keys. + + lt_content = mo_db->list_by_keys( + it_keys = lt_keys + iv_type = zcl_abapgit_persistence_db=>c_type_repo ). + + rv_yes = boolc( lines( lt_content ) > 0 ). + + ENDMETHOD. + METHOD zif_abapgit_persist_repo~list. + + DATA: lt_content TYPE zif_abapgit_persistence=>ty_contents, + ls_content LIKE LINE OF lt_content, + ls_repo LIKE LINE OF rt_repos. + + lt_content = mo_db->list_by_type( zcl_abapgit_persistence_db=>c_type_repo ). + + LOOP AT lt_content INTO ls_content. + ls_repo = get_repo_from_content( ls_content ). + INSERT ls_repo INTO TABLE rt_repos. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_persist_repo~list_by_keys. + DATA: lt_content TYPE zif_abapgit_persistence=>ty_contents, + ls_content LIKE LINE OF lt_content, + ls_repo LIKE LINE OF rt_repos. + + lt_content = mo_db->list_by_keys( + it_keys = it_keys + iv_type = zcl_abapgit_persistence_db=>c_type_repo ). + + LOOP AT lt_content INTO ls_content. + ls_repo = get_repo_from_content( ls_content ). + INSERT ls_repo INTO TABLE rt_repos. + ENDLOOP. + ENDMETHOD. + METHOD zif_abapgit_persist_repo~lock. + + mo_db->lock( iv_mode = iv_mode + iv_type = zcl_abapgit_persistence_db=>c_type_repo + iv_value = iv_key ). + + ENDMETHOD. + METHOD zif_abapgit_persist_repo~read. + + DATA lt_repo TYPE zif_abapgit_persistence=>ty_repos. + + lt_repo = zif_abapgit_persist_repo~list( ). + + READ TABLE lt_repo INTO rs_repo WITH KEY key = iv_key. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_abapgit_not_found. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_persist_repo~update_metadata. + + DATA: + lv_blob TYPE zif_abapgit_persistence=>ty_content-data_str, + ls_persistent_meta TYPE zif_abapgit_persistence=>ty_repo. + + FIELD-SYMBOLS LIKE LINE OF mt_meta_fields. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE abap_bool. + + ASSERT NOT iv_key IS INITIAL. + + IF is_change_mask IS INITIAL. + RETURN. + ENDIF. + + " Validations + IF is_change_mask-url = abap_true AND is_meta-url IS INITIAL. + zcx_abapgit_exception=>raise( 'update, url empty' ). + ENDIF. + + ls_persistent_meta = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key )->ms_data. + + " Update + LOOP AT mt_meta_fields ASSIGNING . + ASSIGN COMPONENT OF STRUCTURE is_change_mask TO . + ASSERT sy-subrc = 0. + CHECK = abap_true. + ASSIGN COMPONENT OF STRUCTURE ls_persistent_meta TO . + ASSERT sy-subrc = 0. + ASSIGN COMPONENT OF STRUCTURE is_meta TO . + ASSERT sy-subrc = 0. + = . + ENDLOOP. + + lv_blob = to_xml( ls_persistent_meta ). + + mo_db->update( iv_type = zcl_abapgit_persistence_db=>c_type_repo + iv_value = iv_key + iv_data = lv_blob ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_PERSISTENCE_DB IMPLEMENTATION. + METHOD add. + + DATA ls_table TYPE zif_abapgit_persistence=>ty_content. + + validate_entry_type( iv_type ). + ls_table-type = iv_type. + ls_table-value = iv_value. + ls_table-data_str = iv_data. + + INSERT (c_tabname) FROM ls_table. "#EC CI_SUBRC + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD delete. + + lock( iv_type = iv_type + iv_value = iv_value ). + + " Ignore errors since record might not exist + DELETE FROM (c_tabname) + WHERE type = iv_type + AND value = iv_value. + + ENDMETHOD. + METHOD get_instance. + + IF go_db IS NOT BOUND. + CREATE OBJECT go_db. + ENDIF. + ro_db = go_db. + + ENDMETHOD. + METHOD get_update_function. + IF mv_update_function IS INITIAL. + mv_update_function = 'CALL_V1_PING'. + IF zcl_abapgit_factory=>get_function_module( )->function_exists( mv_update_function ) = abap_false. + mv_update_function = 'BANK_OBJ_WORKL_RELEASE_LOCKS'. + ENDIF. + ENDIF. + rv_funcname = mv_update_function. + + ENDMETHOD. + METHOD list. + SELECT * FROM (c_tabname) + INTO TABLE rt_content. "#EC CI_SUBRC + ENDMETHOD. + METHOD list_by_keys. + FIELD-SYMBOLS: LIKE LINE OF it_keys. + LOOP AT it_keys ASSIGNING . + SELECT * FROM (c_tabname) + APPENDING TABLE rt_contents + WHERE value = AND + type = iv_type. + ENDLOOP. + ENDMETHOD. + METHOD list_by_type. + SELECT * FROM (c_tabname) + INTO TABLE rt_content + WHERE type = iv_type + ORDER BY PRIMARY KEY. "#EC CI_SUBRC + ENDMETHOD. + METHOD lock. + DATA: lv_dummy_update_function TYPE funcname. + + CALL FUNCTION 'ENQUEUE_EZABAPGIT' + EXPORTING + mode_zabapgit = iv_mode + type = iv_type + value = iv_value + EXCEPTIONS + foreign_lock = 1 + system_failure = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + lv_dummy_update_function = get_update_function( ). + +* trigger dummy update task to automatically release locks at commit + CALL FUNCTION lv_dummy_update_function + IN UPDATE TASK. + + ENDMETHOD. + METHOD modify. + + DATA: ls_content TYPE zif_abapgit_persistence=>ty_content. + + lock( iv_type = iv_type + iv_value = iv_value ). + + ls_content-type = iv_type. + ls_content-value = iv_value. + ls_content-data_str = iv_data. + + MODIFY (c_tabname) FROM ls_content. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'DB modify failed' ). + ENDIF. + + ENDMETHOD. + METHOD read. + + SELECT SINGLE data_str FROM (c_tabname) INTO rv_data + WHERE type = iv_type + AND value = iv_value. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_abapgit_not_found. + ENDIF. + + ENDMETHOD. + METHOD update. + + DATA lv_data LIKE iv_data. + + IF iv_data CS ' 0. + zcx_abapgit_exception=>raise( 'DB update failed' ). + ENDIF. + + ENDMETHOD. + METHOD validate_and_unprettify_xml. + + rv_xml = zcl_abapgit_xml_pretty=>print( + iv_xml = iv_xml + iv_unpretty = abap_true + iv_ignore_errors = abap_false ). + + ENDMETHOD. + METHOD validate_entry_type. + + IF NOT ( + iv_type = c_type_repo OR + iv_type = c_type_repo_csum OR + iv_type = c_type_user OR + iv_type = c_type_settings OR + iv_type = c_type_background OR + iv_type = c_type_packages ). + zcx_abapgit_exception=>raise( |Invalid DB entry type [{ iv_type }]| ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_persist_settings IMPLEMENTATION. + METHOD zif_abapgit_persist_settings~modify. + + DATA: lv_settings TYPE string, + ls_user_settings TYPE zif_abapgit_persist_user=>ty_s_user_settings. + lv_settings = io_settings->get_settings_xml( ). + + zcl_abapgit_persistence_db=>get_instance( )->modify( + iv_type = zcl_abapgit_persistence_db=>c_type_settings + iv_value = '' + iv_data = lv_settings ). + + ls_user_settings = io_settings->get_user_settings( ). + + zcl_abapgit_persist_factory=>get_user( )->set_settings( ls_user_settings ). + + " Settings have been modified: Update Buffered Settings + IF mo_settings IS BOUND. + mo_settings->set_xml_settings( lv_settings ). + mo_settings->set_user_settings( ls_user_settings ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_persist_settings~read. + + IF mo_settings IS BOUND. + " Return Buffered Settings + ro_settings = mo_settings. + RETURN. + ENDIF. + + " Settings have changed or have not yet been loaded + CREATE OBJECT ro_settings. + + TRY. + + ro_settings->set_xml_settings( + zcl_abapgit_persistence_db=>get_instance( )->read( + iv_type = zcl_abapgit_persistence_db=>c_type_settings + iv_value = '' ) ). + + ro_settings->set_user_settings( zcl_abapgit_persist_factory=>get_user( )->get_settings( ) ). + + CATCH zcx_abapgit_not_found zcx_abapgit_exception. + + ro_settings->set_defaults( ). + + ENDTRY. + + mo_settings = ro_settings. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_persist_packages IMPLEMENTATION. + METHOD from_xml. + + DATA lo_input TYPE REF TO zif_abapgit_xml_input. + + CREATE OBJECT lo_input TYPE zcl_abapgit_xml_input EXPORTING iv_xml = iv_xml. + + lo_input->read( + EXPORTING + iv_name = zcl_abapgit_persistence_db=>c_type_packages + CHANGING + cg_data = rt_packages ). + + ENDMETHOD. + METHOD init. + + TRY. + " Might have changed in another session so always get latest + mt_packages = from_xml( zcl_abapgit_persistence_db=>get_instance( )->read( + iv_type = zcl_abapgit_persistence_db=>c_type_packages + iv_value = '' ) ). + CATCH zcx_abapgit_exception zcx_abapgit_not_found ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD to_xml. + + DATA li_output TYPE REF TO zif_abapgit_xml_output. + + CREATE OBJECT li_output TYPE zcl_abapgit_xml_output. + + li_output->add( + iv_name = zcl_abapgit_persistence_db=>c_type_packages + ig_data = it_packages ). + + rv_xml = li_output->render( ). + + ENDMETHOD. + METHOD zif_abapgit_persist_packages~modify. + + DATA ls_package LIKE LINE OF mt_packages. + + FIELD-SYMBOLS LIKE LINE OF mt_packages. + + init( ). + + IF iv_component IS INITIAL AND iv_comp_posid IS INITIAL. + DELETE mt_packages WHERE devclass = iv_package. + ELSE. + READ TABLE mt_packages ASSIGNING WITH TABLE KEY devclass = iv_package. + IF sy-subrc = 0. + -component = iv_component. + -comp_posid = iv_comp_posid. + ELSE. + ls_package-devclass = iv_package. + ls_package-component = iv_component. + ls_package-comp_posid = iv_comp_posid. + INSERT ls_package INTO TABLE mt_packages. + ENDIF. + ENDIF. + + zcl_abapgit_persistence_db=>get_instance( )->modify( + iv_type = zcl_abapgit_persistence_db=>c_type_packages + iv_value = '' + iv_data = to_xml( mt_packages ) ). + + COMMIT WORK AND WAIT. + + ENDMETHOD. + METHOD zif_abapgit_persist_packages~read. + + init( ). + + READ TABLE mt_packages INTO rs_package WITH TABLE KEY devclass = iv_package. + IF sy-subrc <> 0. + rs_package-devclass = iv_package. " no component + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlIgZqNOMnmtzWUhGXxcERFBDQR DEFINITION DEFERRED. +CLASS kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ DEFINITION DEFERRED. +* renamed: zcl_abapgit_persist_migrate :: lcl_cua_interface +CLASS kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ DEFINITION INHERITING FROM zcl_abapgit_objects_program FINAL. + PUBLIC SECTION. + CLASS-METHODS new + RETURNING + VALUE(ro_instance) TYPE REF TO kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ. + METHODS get_own_cua + RETURNING + VALUE(rs_cua) TYPE ty_cua + RAISING + zcx_abapgit_exception. + METHODS put_own_cua + IMPORTING + is_cua TYPE ty_cua + RAISING + zcx_abapgit_exception. +ENDCLASS. + +CLASS kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ IMPLEMENTATION. + + METHOD new. + + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + + SELECT SINGLE devclass object obj_name INTO (ls_item-devclass, ls_item-obj_type, ls_item-obj_name) + FROM tadir + WHERE pgmid = 'R3TR' + AND object = 'PROG' + AND obj_name = sy-cprog. + + CREATE OBJECT ro_instance + EXPORTING + iv_language = 'E' + is_item = ls_item. + + ENDMETHOD. + + METHOD get_own_cua. + + rs_cua = serialize_cua( sy-cprog ). + + ENDMETHOD. + + METHOD put_own_cua. + + DATA li_log TYPE REF TO zif_abapgit_log. + + deserialize_cua( + is_cua = is_cua + iv_program_name = ms_item-obj_name ). + + CREATE OBJECT li_log TYPE zcl_abapgit_log. + zcl_abapgit_objects_activation=>activate( li_log ). + zcl_abapgit_objects_activation=>clear( ). + + ENDMETHOD. + +ENDCLASS. + +* renamed: zcl_abapgit_persist_migrate :: lcl_own_cua_provider +CLASS kHGwlIgZqNOMnmtzWUhGXxcERFBDQR DEFINITION FINAL. + PUBLIC SECTION. + CLASS-METHODS get + RETURNING + VALUE(rs_cua) TYPE zcl_abapgit_objects_program=>ty_cua ##NEEDED. +ENDCLASS. + +CLASS kHGwlIgZqNOMnmtzWUhGXxcERFBDQR IMPLEMENTATION. + METHOD get. +**************************************************** +* abapmerge Pragma [include-cua] - ZABAPGIT.PROG.XML +**************************************************** + DATA ls_sta LIKE LINE OF rs_cua-sta. + DATA ls_fun LIKE LINE OF rs_cua-fun. + DATA ls_but LIKE LINE OF rs_cua-but. + DATA ls_pfk LIKE LINE OF rs_cua-pfk. + DATA ls_set LIKE LINE OF rs_cua-set. + DATA ls_doc LIKE LINE OF rs_cua-doc. + rs_cua-adm-pfkcode = '000001'. + CLEAR ls_sta. + ls_sta-code = 'DECIDE_DIALOG'. + ls_sta-modal = 'P'. + ls_sta-pfkcode = '000001'. + ls_sta-butcode = '0001'. + ls_sta-int_note = 'Object list decide dialog toolbar'. + APPEND ls_sta TO rs_cua-sta. + CLEAR ls_fun. + ls_fun-code = '&ILD'. + ls_fun-textno = '001'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_FILTER_UNDO'. + ls_fun-icon_id = '@GD@'. + ls_fun-fun_text = 'Reset filter'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_fun. + ls_fun-code = '&ILT'. + ls_fun-textno = '001'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_FILTER'. + ls_fun-icon_id = '@4G@'. + ls_fun-fun_text = 'Set Filter'. + ls_fun-path = 'F'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_fun. + ls_fun-code = '&ODN'. + ls_fun-textno = '001'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_SORT_DOWN'. + ls_fun-icon_id = '@3F@'. + ls_fun-fun_text = 'Sort in Descending Order'. + ls_fun-path = 'O'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_fun. + ls_fun-code = '&OUP'. + ls_fun-textno = '001'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_SORT_UP'. + ls_fun-icon_id = '@3E@'. + ls_fun-fun_text = 'Sort in Ascending Order'. + ls_fun-path = 'I'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_fun. + ls_fun-code = 'CANCEL'. + ls_fun-textno = '001'. + ls_fun-type = 'E'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_CANCEL'. + ls_fun-icon_id = '@0W@'. + ls_fun-fun_text = 'Cancel'. + ls_fun-icon_text = 'Cancel'. + ls_fun-path = 'A'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_fun. + ls_fun-code = 'OK'. + ls_fun-textno = '001'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_OKAY'. + ls_fun-icon_id = '@0V@'. + ls_fun-fun_text = 'Continue'. + ls_fun-icon_text = 'Continue'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_fun. + ls_fun-code = 'SEL_ALL'. + ls_fun-textno = '001'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_SELECT_ALL'. + ls_fun-icon_id = '@4B@'. + ls_fun-fun_text = 'Select All Visible'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_fun. + ls_fun-code = 'SEL_CAT'. + ls_fun-textno = '001'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_WD_TOOLBAR'. + ls_fun-icon_id = '@TF@'. + ls_fun-fun_text = 'Select category'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_fun. + ls_fun-code = 'SEL_DEL'. + ls_fun-textno = '001'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_DESELECT_ALL'. + ls_fun-icon_id = '@4D@'. + ls_fun-fun_text = 'Deselect All Visible'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_fun. + ls_fun-code = 'SEL_KEY'. + ls_fun-textno = '001'. + ls_fun-text_type = 'S'. + ls_fun-text_name = 'ICON_SELECT_BLOCK'. + ls_fun-icon_id = '@4C@'. + ls_fun-fun_text = 'Mark/Toggle Selected'. + APPEND ls_fun TO rs_cua-fun. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '01'. + ls_but-pfno = '00'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '02'. + ls_but-pfno = 'S'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '03'. + ls_but-pfno = '13'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '04'. + ls_but-pfno = '17'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '05'. + ls_but-pfno = '14'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '06'. + ls_but-pfno = '16'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '07'. + ls_but-pfno = 'S'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '08'. + ls_but-pfno = '05'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '09'. + ls_but-pfno = '06'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '10'. + ls_but-pfno = '07'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '11'. + ls_but-pfno = '08'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '12'. + ls_but-pfno = 'S'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_but. + ls_but-pfk_code = '000001'. + ls_but-code = '0001'. + ls_but-no = '13'. + ls_but-pfno = '12'. + APPEND ls_but TO rs_cua-but. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '00'. + ls_pfk-funcode = 'OK'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '05'. + ls_pfk-funcode = 'SEL_ALL'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '06'. + ls_pfk-funcode = 'SEL_DEL'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '07'. + ls_pfk-funcode = 'SEL_KEY'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '08'. + ls_pfk-funcode = 'SEL_CAT'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '11'. + ls_pfk-funcode = 'OK'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '12'. + ls_pfk-funcode = 'CANCEL'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '13'. + ls_pfk-funcode = '&ILT'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '14'. + ls_pfk-funcode = '&OUP'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '16'. + ls_pfk-funcode = '&ODN'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_pfk. + ls_pfk-code = '000001'. + ls_pfk-pfno = '17'. + ls_pfk-funcode = '&ILD'. + ls_pfk-funno = '001'. + APPEND ls_pfk TO rs_cua-pfk. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = '&ILD'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = '&ILT'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = '&ODN'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = '&OUP'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = 'CANCEL'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = 'OK'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = 'SEL_ALL'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = 'SEL_CAT'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = 'SEL_DEL'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_set. + ls_set-status = 'DECIDE_DIALOG'. + ls_set-function = 'SEL_KEY'. + APPEND ls_set TO rs_cua-set. + CLEAR ls_doc. + ls_doc-obj_type = 'P'. + ls_doc-obj_code = '000001'. + ls_doc-modal = 'P'. + ls_doc-int_note = 'Object list decide dialog FK settings'. + APPEND ls_doc TO rs_cua-doc. + CLEAR ls_doc. + ls_doc-obj_type = 'B'. + ls_doc-obj_code = '000001'. + ls_doc-sub_code = '0001'. + ls_doc-modal = 'P'. + ls_doc-int_note = 'Object list decide dialog PB settings'. + APPEND ls_doc TO rs_cua-doc. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_persist_migrate IMPLEMENTATION. + METHOD gui_status_create. + + DATA ls_cua TYPE zcl_abapgit_objects_program=>ty_cua. + + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. + RETURN. " No autocreation for full version + ENDIF. + + IF gui_status_exists( ) = abap_true. + RETURN. + ENDIF. + + ls_cua = kHGwlIgZqNOMnmtzWUhGXxcERFBDQR=>get( ). + + IF ls_cua IS INITIAL. " Full version or something wrong with abapmerged version + RETURN. + ENDIF. + + TRY. + kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ=>new( )->put_own_cua( ls_cua ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD gui_status_exists. + + DATA ls_own_cua TYPE zcl_abapgit_objects_program=>ty_cua. + DATA ls_new_cua TYPE zcl_abapgit_objects_program=>ty_cua. + DATA lv_x_own TYPE xstring. + DATA lv_x_new TYPE xstring. + DATA lv_h_own TYPE zif_abapgit_git_definitions=>ty_sha1. + DATA lv_h_new TYPE zif_abapgit_git_definitions=>ty_sha1. + + TRY. + ls_own_cua = kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ=>new( )->get_own_cua( ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + IF ls_own_cua IS INITIAL. + rv_exists = abap_false. + RETURN. + ENDIF. + + ls_new_cua = kHGwlIgZqNOMnmtzWUhGXxcERFBDQR=>get( ). + IF ls_new_cua IS INITIAL. + rv_exists = abap_true. " own exists and new is not - nothing to compare with + RETURN. + ENDIF. + + EXPORT data = ls_own_cua TO DATA BUFFER lv_x_own. + EXPORT data = ls_new_cua TO DATA BUFFER lv_x_new. + + TRY. + lv_h_own = zcl_abapgit_hash=>sha1_raw( lv_x_own ). + lv_h_new = zcl_abapgit_hash=>sha1_raw( lv_x_new ). + CATCH zcx_abapgit_exception. + rv_exists = abap_true. " own exists and some issue with calculating hash ... assume own is OK + RETURN. + ENDTRY. + + " New exists and differs from own - then it is really new, needs to be installed + rv_exists = boolc( lv_h_own = lv_h_new ). + + ENDMETHOD. + METHOD lock_create. + + DATA: + ls_dd25v TYPE dd25v, + lt_dd26e TYPE STANDARD TABLE OF dd26e WITH DEFAULT KEY, + lt_dd27p TYPE STANDARD TABLE OF dd27p WITH DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF lt_dd26e, + LIKE LINE OF lt_dd27p. + ls_dd25v-viewname = zcl_abapgit_persistence_db=>c_lock. + ls_dd25v-aggtype = 'E'. + ls_dd25v-roottab = zcl_abapgit_persistence_db=>c_tabname. + ls_dd25v-ddlanguage = zif_abapgit_definitions=>c_english. + ls_dd25v-ddtext = c_text. + + APPEND INITIAL LINE TO lt_dd26e ASSIGNING . + -viewname = zcl_abapgit_persistence_db=>c_lock. + -tabname = zcl_abapgit_persistence_db=>c_tabname. + -tabpos = '0001'. + -fortabname = zcl_abapgit_persistence_db=>c_tabname. + -enqmode = 'E'. + + APPEND INITIAL LINE TO lt_dd27p ASSIGNING . + -viewname = zcl_abapgit_persistence_db=>c_lock. + -objpos = '0001'. + -viewfield = 'TYPE'. + -tabname = zcl_abapgit_persistence_db=>c_tabname. + -fieldname = 'TYPE'. + -keyflag = abap_true. + + APPEND INITIAL LINE TO lt_dd27p ASSIGNING . + -viewname = zcl_abapgit_persistence_db=>c_lock. + -objpos = '0002'. + -viewfield = 'VALUE'. + -tabname = zcl_abapgit_persistence_db=>c_tabname. + -fieldname = 'VALUE'. + -keyflag = abap_true. + + CALL FUNCTION 'DDIF_ENQU_PUT' + EXPORTING + name = zcl_abapgit_persistence_db=>c_lock + dd25v_wa = ls_dd25v + TABLES + dd26e_tab = lt_dd26e + dd27p_tab = lt_dd27p + EXCEPTIONS + enqu_not_found = 1 + name_inconsistent = 2 + enqu_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + zcl_abapgit_factory=>get_tadir( )->insert_single( + iv_object = 'ENQU' + iv_obj_name = zcl_abapgit_persistence_db=>c_lock + iv_package = '$TMP' + iv_set_genflag = abap_true ). + + CALL FUNCTION 'DDIF_ENQU_ACTIVATE' + EXPORTING + name = zcl_abapgit_persistence_db=>c_lock + EXCEPTIONS + not_found = 1 + put_failure = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'migrate, error from DDIF_ENQU_ACTIVATE' ). + ENDIF. + + ENDMETHOD. + METHOD lock_exists. + + DATA: lv_viewname TYPE dd25l-viewname. + + SELECT SINGLE viewname FROM dd25l INTO lv_viewname + WHERE viewname = zcl_abapgit_persistence_db=>c_lock. + rv_exists = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD run. + + IF table_exists( ) = abap_false. + table_create( ). + ENDIF. + + IF lock_exists( ) = abap_false. + lock_create( ). + ENDIF. + + gui_status_create( ). + + ENDMETHOD. + METHOD table_create. + + DATA: lv_rc LIKE sy-subrc, + ls_dd02v TYPE dd02v, + ls_dd09l TYPE dd09l, + lt_dd03p TYPE STANDARD TABLE OF dd03p WITH DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF lt_dd03p. + + ls_dd02v-tabname = zcl_abapgit_persistence_db=>c_tabname. + ls_dd02v-ddlanguage = zif_abapgit_definitions=>c_english. + ls_dd02v-tabclass = 'TRANSP'. + ls_dd02v-ddtext = c_text. + ls_dd02v-contflag = 'L'. + ls_dd02v-exclass = '1'. + + ls_dd09l-tabname = zcl_abapgit_persistence_db=>c_tabname. + ls_dd09l-as4local = 'A'. + ls_dd09l-tabkat = '1'. + ls_dd09l-tabart = 'APPL1'. + ls_dd09l-bufallow = 'N'. + + APPEND INITIAL LINE TO lt_dd03p ASSIGNING . + -tabname = zcl_abapgit_persistence_db=>c_tabname. + -fieldname = 'TYPE'. + -position = '0001'. + -keyflag = 'X'. + -datatype = 'CHAR'. + -leng = '000012'. + + APPEND INITIAL LINE TO lt_dd03p ASSIGNING . + -tabname = zcl_abapgit_persistence_db=>c_tabname. + -fieldname = 'VALUE'. + -position = '0002'. + -keyflag = 'X'. + -datatype = 'CHAR'. + -leng = '000012'. + + APPEND INITIAL LINE TO lt_dd03p ASSIGNING . + -tabname = zcl_abapgit_persistence_db=>c_tabname. + -fieldname = 'DATA_STR'. + -position = '0003'. + -datatype = 'STRG'. + + CALL FUNCTION 'DDIF_TABL_PUT' + EXPORTING + name = zcl_abapgit_persistence_db=>c_tabname + dd02v_wa = ls_dd02v + dd09l_wa = ls_dd09l + TABLES + dd03p_tab = lt_dd03p + EXCEPTIONS + tabl_not_found = 1 + name_inconsistent = 2 + tabl_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + zcl_abapgit_factory=>get_tadir( )->insert_single( + iv_object = 'TABL' + iv_obj_name = zcl_abapgit_persistence_db=>c_tabname + iv_package = '$TMP' + iv_set_genflag = abap_true ). + + CALL FUNCTION 'DDIF_TABL_ACTIVATE' + EXPORTING + name = zcl_abapgit_persistence_db=>c_tabname + auth_chk = abap_false + IMPORTING + rc = lv_rc + EXCEPTIONS + not_found = 1 + put_failure = 2 + OTHERS = 3. + IF sy-subrc <> 0 OR lv_rc <> 0. + zcx_abapgit_exception=>raise( 'migrate, error from DDIF_TABL_ACTIVATE' ). + ENDIF. + + ENDMETHOD. + METHOD table_exists. + + DATA: lv_tabname TYPE dd02l-tabname. + + SELECT SINGLE tabname FROM dd02l INTO lv_tabname + WHERE tabname = zcl_abapgit_persistence_db=>c_tabname. "#EC CI_NOORDER + rv_exists = boolc( sy-subrc = 0 ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_persist_factory IMPLEMENTATION. + METHOD get_background. + + IF gi_background IS INITIAL. + CREATE OBJECT gi_background TYPE zcl_abapgit_persist_background. + ENDIF. + + ri_background = gi_background. + + ENDMETHOD. + METHOD get_packages. + + IF gi_packages IS INITIAL. + CREATE OBJECT gi_packages TYPE zcl_abapgit_persist_packages. + ENDIF. + + ri_packages = gi_packages. + + ENDMETHOD. + METHOD get_repo. + + IF gi_repo IS INITIAL. + CREATE OBJECT gi_repo TYPE zcl_abapgit_persistence_repo. + ENDIF. + + ri_repo = gi_repo. + + ENDMETHOD. + METHOD get_repo_cs. + + IF gi_repo_cs IS INITIAL. + CREATE OBJECT gi_repo_cs TYPE zcl_abapgit_persistence_repo. + ENDIF. + + ri_repo_cs = gi_repo_cs. + + ENDMETHOD. + METHOD get_settings. + + IF gi_settings IS INITIAL. + CREATE OBJECT gi_settings TYPE zcl_abapgit_persist_settings. + ENDIF. + + ri_settings = gi_settings. + + ENDMETHOD. + METHOD get_user. + + IF iv_user = sy-uname ##USER_OK. + IF gi_current_user IS NOT BOUND. + CREATE OBJECT gi_current_user TYPE zcl_abapgit_persistence_user. + ENDIF. + ri_user = gi_current_user. + ELSE. + CREATE OBJECT ri_user TYPE zcl_abapgit_persistence_user + EXPORTING + iv_user = iv_user. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_persist_background IMPLEMENTATION. + METHOD constructor. + mo_db = zcl_abapgit_persistence_db=>get_instance( ). + ENDMETHOD. + METHOD from_xml. + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML iv_string + RESULT data = rs_xml. + ENDMETHOD. + METHOD to_xml. + DATA ls_xml TYPE zif_abapgit_persist_background=>ty_xml. + + MOVE-CORRESPONDING is_background TO ls_xml. + + CALL TRANSFORMATION id + SOURCE data = ls_xml + RESULT XML rv_string. + ENDMETHOD. + METHOD zif_abapgit_persist_background~delete. + + TRY. + mo_db->read( iv_type = zcl_abapgit_persistence_db=>c_type_background + iv_value = iv_key ). + CATCH zcx_abapgit_not_found. + RETURN. + ENDTRY. + + mo_db->delete( iv_type = zcl_abapgit_persistence_db=>c_type_background + iv_value = iv_key ). + + ENDMETHOD. + METHOD zif_abapgit_persist_background~exists. + + TRY. + mo_db->read( iv_type = zcl_abapgit_persistence_db=>c_type_background + iv_value = iv_key ). + rv_yes = abap_true. + CATCH zcx_abapgit_not_found. + rv_yes = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_persist_background~get_by_key. + + DATA: lt_list TYPE zif_abapgit_persist_background=>ty_background_keys. + + lt_list = zif_abapgit_persist_background~list( ). + + READ TABLE lt_list WITH KEY key = iv_key INTO rs_data. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_abapgit_not_found. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_persist_background~list. + + DATA: lt_list TYPE zif_abapgit_persistence=>ty_contents, + ls_xml TYPE zif_abapgit_persist_background=>ty_xml. + + FIELD-SYMBOLS: LIKE LINE OF lt_list, + LIKE LINE OF rt_list. + lt_list = mo_db->list_by_type( zcl_abapgit_persistence_db=>c_type_background ). + + LOOP AT lt_list ASSIGNING . + ls_xml = from_xml( -data_str ). + + APPEND INITIAL LINE TO rt_list ASSIGNING . + MOVE-CORRESPONDING ls_xml TO . + -key = -value. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_persist_background~modify. + + ASSERT NOT is_data-key IS INITIAL. + + mo_db->modify( + iv_type = zcl_abapgit_persistence_db=>c_type_background + iv_value = is_data-key + iv_data = to_xml( is_data ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_migrations IMPLEMENTATION. + METHOD migrate_offline_repos. + + DATA: + lt_repos TYPE zif_abapgit_repo_srv=>ty_repo_list, + li_repo LIKE LINE OF lt_repos, + lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. + + TRY. + " Get offline repos only + lt_repos = zcl_abapgit_repo_srv=>get_instance( )->list( abap_true ). + + LOOP AT lt_repos INTO li_repo. + lo_dot = li_repo->get_dot_abapgit( ). + " Move repo name from URL fields to .abapGit.xml + IF li_repo->ms_data-url IS NOT INITIAL AND lo_dot->get_name( ) IS INITIAL. + lo_dot->set_name( li_repo->ms_data-url ). + li_repo->set_dot_abapgit( lo_dot ). + ENDIF. + ENDLOOP. + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD run. + + " Migrate STDTEXT to TABLE + zcl_abapgit_persist_migrate=>run( ). + + " Create ZIF_APACK_MANIFEST interface + zcl_abapgit_apack_migration=>run( ). + + " Migrate checksums from repo metadata to separate DB object + zcl_abapgit_repo_cs_migration=>run( ). + + " Migrate offline repo metadata + migrate_offline_repos( ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_objects_super IMPLEMENTATION. + METHOD clear_abap_language_version. + + " Used during serializing of objects + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + " Ignore ABAP language version + CLEAR cv_abap_language_version. + ELSEIF ms_item-abap_language_version <> zcl_abapgit_abap_language_vers=>c_any_abap_language_version. + " Check if ABAP language version matches repository setting + zcl_abapgit_abap_language_vers=>check_abap_language_version( + iv_abap_language_version = cv_abap_language_version + is_item = ms_item ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + ms_item = is_item. + ASSERT NOT ms_item IS INITIAL. + mv_language = iv_language. + ASSERT NOT mv_language IS INITIAL. + + IF io_files IS NOT INITIAL. + mo_files = io_files. + ELSE. + mo_files = zcl_abapgit_objects_files=>new( is_item ). " New file collection + ENDIF. + + IF io_i18n_params IS NOT INITIAL. + mo_i18n_params = io_i18n_params. + ELSE. + mo_i18n_params = zcl_abapgit_i18n_params=>new( ). " All defaults + ENDIF. + + ENDMETHOD. + METHOD corr_insert. + + DATA: lv_object TYPE trobj_name, + lv_object_class TYPE tadir-object. + + IF ig_object_class IS NOT INITIAL. + lv_object_class = ig_object_class. + IF ig_object_class = 'DICT'. + CONCATENATE ms_item-obj_type ms_item-obj_name INTO lv_object. + ELSE. + lv_object = ms_item-obj_name. + ENDIF. + ELSE. + lv_object_class = ms_item-obj_type. + lv_object = ms_item-obj_name. + ENDIF. + + zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( + iv_object = lv_object_class + iv_obj_name = lv_object + iv_package = iv_package + iv_language = mv_language ). + + ENDMETHOD. + METHOD delete_ddic. + + DATA: lv_objname TYPE rsedd0-ddobjname, + lv_objtype TYPE rsedd0-ddobjtype. + + lv_objname = ms_item-obj_name. + lv_objtype = iv_objtype. + + TRY. + CALL FUNCTION 'RS_DD_DELETE_OBJ' + EXPORTING + no_ask = iv_no_ask + objname = lv_objname + objtype = lv_objtype + no_ask_delete_append = iv_no_ask_delete_append + EXCEPTIONS + not_executed = 1 + object_not_found = 2 + object_not_specified = 3 + permission_failure = 4 + dialog_needed = 5 + OTHERS = 6 ##FM_SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. + TRY. + " try to force deletion for APPENDs + CALL FUNCTION 'RS_DD_DELETE_OBJ' + EXPORTING + no_ask = iv_no_ask + objname = lv_objname + objtype = lv_objtype + aie_force_deletion = iv_no_ask_delete_append + EXCEPTIONS + not_executed = 1 + object_not_found = 2 + object_not_specified = 3 + permission_failure = 4 + dialog_needed = 5 + OTHERS = 6 ##FM_SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. + " no_ask_delete_append and aie_force_deletion not available in lower releases + CALL FUNCTION 'RS_DD_DELETE_OBJ' + EXPORTING + no_ask = iv_no_ask + objname = lv_objname + objtype = lv_objtype + EXCEPTIONS + not_executed = 1 + object_not_found = 2 + object_not_specified = 3 + permission_failure = 4 + dialog_needed = 5 + OTHERS = 6 ##FM_SUBRC_OK. + ENDTRY. + ENDTRY. + + IF sy-subrc = 5. + zcx_abapgit_exception=>raise( |Object { ms_item-obj_type } { ms_item-obj_name + } has dependencies and must be deleted manually| ). + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error deleting { ms_item-obj_type } { ms_item-obj_name }| ). + ENDIF. + + ENDMETHOD. + METHOD delete_longtexts. + + zcl_abapgit_factory=>get_longtexts( )->delete( + iv_longtext_id = iv_longtext_id + iv_object_name = ms_item-obj_name ). + + ENDMETHOD. + METHOD deserialize_longtexts. + + zcl_abapgit_factory=>get_longtexts( )->deserialize( + ii_xml = ii_xml + iv_longtext_name = iv_longtext_name + iv_object_name = ms_item-obj_name + iv_longtext_id = iv_longtext_id + iv_main_language = mv_language ). + + ENDMETHOD. + METHOD exists_a_lock_entry_for. + + DATA: lt_lock_entries TYPE STANDARD TABLE OF seqg3. + DATA: lv_argument TYPE seqg3-garg. + + IF iv_prefix IS INITIAL. + lv_argument = iv_argument. + ELSE. + lv_argument = |{ iv_prefix }{ iv_argument }|. + OVERLAY lv_argument WITH ' '. + lv_argument = lv_argument && '*'. + ENDIF. + + CALL FUNCTION 'ENQUEUE_READ' + EXPORTING + guname = '*' + garg = lv_argument + TABLES + enq = lt_lock_entries + EXCEPTIONS + communication_failure = 1 + system_failure = 2 + OTHERS = 3. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + READ TABLE lt_lock_entries TRANSPORTING NO FIELDS + WITH KEY gobj = iv_lock_object. + IF sy-subrc = 0. + rv_exists_a_lock_entry = abap_true. + ENDIF. + + ENDMETHOD. + METHOD get_abap_language_version. + + " This is limited to DDIC objects + TRY. + CALL METHOD ('CL_DD_ABAP_LANGUAGE_VERSION')=>get_abap_language_version + EXPORTING + iv_object_type = ms_item-obj_type + iv_object_name = ms_item-obj_name + RECEIVING + rv_abap_language_version = rv_abap_language_version. + CATCH cx_root. + " does not exist in lower releases + RETURN. + ENDTRY. + + clear_abap_language_version( CHANGING cv_abap_language_version = rv_abap_language_version ). + + ENDMETHOD. + METHOD get_accessed_files. + rt_files = mo_files->get_accessed_files( ). + ENDMETHOD. + METHOD get_metadata. + + DATA: lv_class TYPE string. + + lv_class = cl_abap_classdescr=>describe_by_object_ref( me )->get_relative_name( ). + + REPLACE FIRST OCCURRENCE OF 'ZCL_ABAPGIT' IN lv_class WITH 'LCL'. + + rs_metadata-class = lv_class. + rs_metadata-version = 'v1.0.0'. + + ENDMETHOD. + METHOD is_active. + + rv_active = zcl_abapgit_objects_activation=>is_active( ms_item ). + + ENDMETHOD. + METHOD serialize_longtexts. + + zcl_abapgit_factory=>get_longtexts( )->serialize( + iv_object_name = ms_item-obj_name + iv_longtext_name = iv_longtext_name + iv_longtext_id = iv_longtext_id + it_dokil = it_dokil + io_i18n_params = mo_i18n_params + ii_xml = ii_xml ). + + ENDMETHOD. + METHOD set_abap_language_version. + + " Used during deserializing of objects + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + " ABAP language version is derived from object type and target package (see zcl_abapgit_objects->deserialize) + cv_abap_language_version = ms_item-abap_language_version. + ELSEIF ms_item-abap_language_version <> zcl_abapgit_abap_language_vers=>c_any_abap_language_version. + " Check if ABAP language version matches repository setting + zcl_abapgit_abap_language_vers=>check_abap_language_version( + iv_abap_language_version = cv_abap_language_version + is_item = ms_item ). + ENDIF. + + ENDMETHOD. + METHOD set_default_package. + + " In certain cases we need to set the package via ABAP memory + " because we can't supply it via the APIs. + " + " Set default package, see function module RS_CORR_INSERT FORM get_current_devclass. + " + " We use ABAP memory instead the SET parameter because it is + " more reliable. SET parameter doesn't work when multiple objects + " are deserialized which uses the ABAP memory mechanism. + " We don't need to reset the memory as it is done in above mentioned form routine. + + EXPORT current_devclass FROM iv_package TO MEMORY ID 'EUK'. + + ENDMETHOD. + METHOD set_default_transport. + + " In certain cases we need to set the transport via ABAP memory + " because we can't supply it via the APIs. + " + " See function module RS_CORR_INSERT + + EXPORT tasknr FROM iv_transport TO MEMORY ID 'EUT'. + + ENDMETHOD. + METHOD tadir_delete. + + zcl_abapgit_factory=>get_tadir( )->delete_single( + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name ). + + ENDMETHOD. + METHOD tadir_insert. + + zcl_abapgit_factory=>get_tadir( )->insert_single( + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + iv_package = iv_package + iv_language = mv_language ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_objects_program IMPLEMENTATION. + METHOD add_tpool. + + FIELD-SYMBOLS: LIKE LINE OF it_tpool, + LIKE LINE OF rt_tpool. + LOOP AT it_tpool ASSIGNING . + APPEND INITIAL LINE TO rt_tpool ASSIGNING . + MOVE-CORRESPONDING TO . + IF -id = 'S'. + -split = -entry. + -entry = -entry+8. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD auto_correct_cua_adm. + " issue #1807 automatic correction of CUA interfaces saved incorrectly in the past (ADM was not saved in the XML) + + CONSTANTS: + lc_num_n_space TYPE string VALUE ' 0123456789', + lc_num_only TYPE string VALUE '0123456789'. + + FIELD-SYMBOLS: + TYPE rsmpe_pfk, + TYPE rsmpe_act, + TYPE rsmpe_men. + + IF cs_adm IS NOT INITIAL + AND cs_adm-actcode CO lc_num_n_space + AND cs_adm-mencode CO lc_num_n_space + AND cs_adm-pfkcode CO lc_num_n_space. "Check performed in form check_adm of include LSMPIF03 + RETURN. + ENDIF. + + LOOP AT is_cua-act ASSIGNING . + IF -code+6(14) IS INITIAL AND -code(6) CO lc_num_only. + cs_adm-actcode = -code. + ENDIF. + ENDLOOP. + + LOOP AT is_cua-men ASSIGNING . + IF -code+6(14) IS INITIAL AND -code(6) CO lc_num_only. + cs_adm-mencode = -code. + ENDIF. + ENDLOOP. + + LOOP AT is_cua-pfk ASSIGNING . + IF -code+6(14) IS INITIAL AND -code(6) CO lc_num_only. + cs_adm-pfkcode = -code. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_cua. + + DATA: ls_tr_key TYPE trkey, + ls_adm TYPE rsmpe_adm. + IF lines( is_cua-sta ) = 0 + AND lines( is_cua-fun ) = 0 + AND lines( is_cua-men ) = 0 + AND lines( is_cua-mtx ) = 0 + AND lines( is_cua-act ) = 0 + AND lines( is_cua-but ) = 0 + AND lines( is_cua-pfk ) = 0 + AND lines( is_cua-set ) = 0 + AND lines( is_cua-doc ) = 0 + AND lines( is_cua-tit ) = 0 + AND lines( is_cua-biv ) = 0. + RETURN. + ENDIF. + + SELECT SINGLE devclass INTO ls_tr_key-devclass + FROM tadir + WHERE pgmid = 'R3TR' + AND object = ms_item-obj_type + AND obj_name = ms_item-obj_name. "#EC CI_GENBUFF + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'not found in tadir' ). + ENDIF. + + ls_tr_key-obj_type = ms_item-obj_type. + ls_tr_key-obj_name = ms_item-obj_name. + ls_tr_key-sub_type = 'CUAD'. + ls_tr_key-sub_name = iv_program_name. + + ls_adm = is_cua-adm. + auto_correct_cua_adm( EXPORTING is_cua = is_cua CHANGING cs_adm = ls_adm ). + + sy-tcode = 'SE41' ##WRITE_OK. " evil hack, workaround to handle fixes in note 2159455 + CALL FUNCTION 'RS_CUA_INTERNAL_WRITE' + EXPORTING + program = iv_program_name + language = mv_language + tr_key = ls_tr_key + adm = ls_adm + state = c_state-inactive + TABLES + sta = is_cua-sta + fun = is_cua-fun + men = is_cua-men + mtx = is_cua-mtx + act = is_cua-act + but = is_cua-but + pfk = is_cua-pfk + set = is_cua-set + doc = is_cua-doc + tit = is_cua-tit + biv = is_cua-biv + EXCEPTIONS + not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. +* if moving code from SAPlink, see https://github.com/abapGit/abapGit/issues/562 + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + zcl_abapgit_objects_activation=>add( + iv_type = 'CUAD' + iv_name = iv_program_name ). + + ENDMETHOD. + METHOD deserialize_dynpros. + + CONSTANTS lc_rpyty_force_off TYPE c LENGTH 1 VALUE '/'. + + DATA: lv_name TYPE dwinactiv-obj_name, + lt_d020s_to_delete TYPE TABLE OF d020s, + ls_d020s LIKE LINE OF lt_d020s_to_delete, + lt_params TYPE TABLE OF d023s, + ls_dynpro LIKE LINE OF it_dynpros. + + FIELD-SYMBOLS: TYPE rpy_dyfatc. + + " Delete DYNPROs which are not in the list + CALL FUNCTION 'RS_SCREEN_LIST' + EXPORTING + dynnr = '' + progname = ms_item-obj_name + TABLES + dynpros = lt_d020s_to_delete + EXCEPTIONS + not_found = 1 + OTHERS = 2. + IF sy-subrc = 2. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + SORT lt_d020s_to_delete BY dnum ASCENDING. + +* ls_dynpro is changed by the function module, a field-symbol will cause +* the program to dump since it_dynpros cannot be changed + LOOP AT it_dynpros INTO ls_dynpro. + + READ TABLE lt_d020s_to_delete WITH KEY dnum = ls_dynpro-header-screen + TRANSPORTING NO FIELDS + BINARY SEARCH. + IF sy-subrc = 0. + DELETE lt_d020s_to_delete INDEX sy-tabix. + ENDIF. + + " todo: kept for compatibility, remove after grace period #3680 + ls_dynpro-flow_logic = uncondense_flow( + it_flow = ls_dynpro-flow_logic + it_spaces = ls_dynpro-spaces ). + + IF ls_dynpro-flow_logic IS INITIAL. + ls_dynpro-flow_logic = mo_files->read_abap( iv_extra = 'screen_' && ls_dynpro-header-screen ). + ENDIF. + + LOOP AT ls_dynpro-fields ASSIGNING . +* if the DDIC element has a PARAMETER_ID and the flag "from_dict" is active +* the import will enable the SET-/GET_PARAM flag. In this case: "force off" + IF -param_id IS NOT INITIAL + AND -from_dict = abap_true. + IF -set_param IS INITIAL. + -set_param = lc_rpyty_force_off. + ENDIF. + IF -get_param IS INITIAL. + -get_param = lc_rpyty_force_off. + ENDIF. + ENDIF. + +* If the previous conditions are met the value 'F' will be taken over +* during de-serialization potentially overlapping other fields in the screen, +* we set the tag to the correct value 'X' + IF -type = 'CHECK' + AND -from_dict = abap_true + AND -text IS INITIAL + AND -modific IS INITIAL. + -modific = 'X'. + ENDIF. + + "fix for issue #2747: + IF -foreignkey IS INITIAL. + -foreignkey = lc_rpyty_force_off. + ENDIF. + + ENDLOOP. + + IF ls_dynpro-header-type CA c_native_dynpro AND ls_dynpro-nat_header IS NOT INITIAL. + DELETE FROM d021t WHERE prog = ls_dynpro-header-program AND dynr = ls_dynpro-header-screen ##SUBRC_OK. + INSERT d021t FROM TABLE ls_dynpro-nat_texts ##SUBRC_OK. + + ls_dynpro-nat_header-dgen = sy-datum. + ls_dynpro-nat_header-tgen = sy-uzeit. + + CALL FUNCTION 'RPY_DYNPRO_INSERT_NATIVE' + EXPORTING + header = ls_dynpro-nat_header + dynprotext = ls_dynpro-header-descript + TABLES + fieldlist = ls_dynpro-nat_fields + flowlogic = ls_dynpro-flow_logic + params = lt_params + EXCEPTIONS + cancelled = 1 + already_exists = 2 + program_not_exists = 3 + not_executed = 4 + OTHERS = 5. + ELSE. + CALL FUNCTION 'RPY_DYNPRO_INSERT' + EXPORTING + header = ls_dynpro-header + suppress_exist_checks = abap_true + suppress_generate = ls_dynpro-header-no_execute + TABLES + containers = ls_dynpro-containers + fields_to_containers = ls_dynpro-fields + flow_logic = ls_dynpro-flow_logic + EXCEPTIONS + cancelled = 1 + already_exists = 2 + program_not_exists = 3 + not_executed = 4 + missing_required_field = 5 + illegal_field_value = 6 + field_not_allowed = 7 + not_generated = 8 + illegal_field_position = 9 + OTHERS = 10. + ENDIF. + IF sy-subrc <> 2 AND sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CONCATENATE ls_dynpro-header-program ls_dynpro-header-screen + INTO lv_name RESPECTING BLANKS. + ASSERT NOT lv_name IS INITIAL. + + zcl_abapgit_objects_activation=>add( + iv_type = 'DYNP' + iv_name = lv_name ). + + ENDLOOP. + + " Delete obsolete screens + LOOP AT lt_d020s_to_delete INTO ls_d020s. + + CALL FUNCTION 'RS_SCRP_DELETE' + EXPORTING + dynnr = ls_d020s-dnum + progname = ms_item-obj_name + with_popup = abap_false + EXCEPTIONS + enqueued_by_user = 1 + enqueue_system_failure = 2 + not_executed = 3 + not_exists = 4 + no_modify_permission = 5 + popup_canceled = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_exit_include. + + DATA: + lv_progname TYPE reposrc-progname, + lv_title TYPE rglif-title. + + " Includes in SAP exit function groups must be processed in active state only + " (check in RS_INSERT_INTO_WORKING_AREA) + lv_title = get_program_title( it_tpool ). + + SELECT SINGLE progname FROM reposrc INTO lv_progname + WHERE progname = is_progdir-name + AND r3state = c_state-active. + + IF sy-subrc = 0. + update_program( + is_progdir = is_progdir + it_source = it_source + iv_title = lv_title + iv_state = '' ). + ELSE. + insert_program( + is_progdir = is_progdir + it_source = it_source + iv_title = lv_title + iv_package = iv_package + iv_state = '' ). + ENDIF. + + ENDMETHOD. + METHOD deserialize_program. + + DATA: + lv_progname TYPE reposrc-progname, + lv_title TYPE rglif-title. + + IF is_exit_include( is_progdir-name ) = abap_true. + deserialize_exit_include( + is_progdir = is_progdir + it_source = it_source + it_tpool = it_tpool + iv_package = iv_package ). + RETURN. + ENDIF. + + zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( + iv_object = 'ABAP' + iv_obj_name = is_progdir-name + iv_package = iv_package + iv_language = mv_language ). + + lv_title = get_program_title( it_tpool ). + + " Check if program already exists + SELECT SINGLE progname FROM reposrc INTO lv_progname + WHERE progname = is_progdir-name + AND r3state = c_state-active. + + IF sy-subrc = 0. + update_program( + is_progdir = is_progdir + it_source = it_source + iv_title = lv_title ). + ELSE. + insert_program( + is_progdir = is_progdir + it_source = it_source + iv_title = lv_title + iv_package = iv_package ). + ENDIF. + + zcl_abapgit_factory=>get_sap_report( )->update_progdir( + is_progdir = is_progdir + iv_package = iv_package ). + + zcl_abapgit_objects_activation=>add( + iv_type = 'REPS' + iv_name = is_progdir-name ). + + ENDMETHOD. + METHOD deserialize_textpool. + + DATA lv_language TYPE sy-langu. + DATA lv_state TYPE c. + DATA lv_delete TYPE abap_bool. + + IF iv_language IS INITIAL. + lv_language = mv_language. + ELSE. + lv_language = iv_language. + ENDIF. + + IF lv_language = mv_language. + lv_state = c_state-inactive. "Textpool in main language needs to be activated + ELSE. + lv_state = c_state-active. "Translations are always active + ENDIF. + + IF it_tpool IS INITIAL. + IF iv_is_include = abap_false OR lv_state = c_state-active. + DELETE TEXTPOOL iv_program "Remove initial description from textpool if + LANGUAGE lv_language "original program does not have a textpool + STATE lv_state. + + lv_delete = abap_true. + ELSE. + INSERT TEXTPOOL iv_program "In case of includes: Deletion of textpool in + FROM it_tpool "main language cannot be activated because + LANGUAGE lv_language "this would activate the deletion of the textpool + STATE lv_state. "of the mail program -> insert empty textpool + ENDIF. + ELSE. + INSERT TEXTPOOL iv_program + FROM it_tpool + LANGUAGE lv_language + STATE lv_state. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from INSERT TEXTPOOL' ). + ENDIF. + ENDIF. + + "Textpool in main language needs to be activated (not for FUGS/FUGX) + IF lv_state = c_state-inactive AND iv_program NP 'SAPLX*'. + zcl_abapgit_objects_activation=>add( + iv_type = 'REPT' + iv_name = iv_program + iv_delete = lv_delete ). + ENDIF. + ENDMETHOD. + METHOD get_program_title. + + DATA ls_tpool LIKE LINE OF it_tpool. + + FIELD-SYMBOLS TYPE any. + + READ TABLE it_tpool INTO ls_tpool WITH KEY id = 'R'. + IF sy-subrc = 0. + " there is a bug in RPY_PROGRAM_UPDATE, the header line of TTAB is not + " cleared, so the title length might be inherited from a different program. + ASSIGN ('(SAPLSIFP)TTAB') TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + rv_title = ls_tpool-entry. + ENDIF. + + ENDMETHOD. + METHOD insert_program. + + TRY. + CALL FUNCTION 'RPY_PROGRAM_INSERT' + EXPORTING + development_class = iv_package + program_name = is_progdir-name + program_type = is_progdir-subc + title_string = iv_title + save_inactive = iv_state + suppress_dialog = abap_true + uccheck = is_progdir-uccheck " does not exist on lower releases + TABLES + source_extended = it_source + EXCEPTIONS + already_exists = 1 + cancelled = 2 + name_not_allowed = 3 + permission_error = 4 + OTHERS = 5 ##FM_SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. + CALL FUNCTION 'RPY_PROGRAM_INSERT' + EXPORTING + development_class = iv_package + program_name = is_progdir-name + program_type = is_progdir-subc + title_string = iv_title + save_inactive = iv_state + suppress_dialog = abap_true + TABLES + source_extended = it_source + EXCEPTIONS + already_exists = 1 + cancelled = 2 + name_not_allowed = 3 + permission_error = 4 + OTHERS = 5 ##FM_SUBRC_OK. + ENDTRY. + IF sy-subrc = 3. + + " For cases that standard function does not handle (like FUGR), + " we save active and inactive version of source with the given PROGRAM TYPE. + " Without the active version, the code will not be visible in case of activation errors. + zcl_abapgit_factory=>get_sap_report( )->insert_report( + iv_name = is_progdir-name + iv_package = iv_package + it_source = it_source + iv_state = c_state-active + iv_version = is_progdir-uccheck + iv_program_type = is_progdir-subc ). + + zcl_abapgit_factory=>get_sap_report( )->insert_report( + iv_name = is_progdir-name + iv_package = iv_package + it_source = it_source + iv_state = c_state-inactive + iv_version = is_progdir-uccheck + iv_program_type = is_progdir-subc ). + + ELSEIF sy-subrc > 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD is_any_dynpro_locked. + + DATA: lt_dynpros TYPE ty_dynpro_tt, + lv_object TYPE seqg3-garg. + + FIELD-SYMBOLS: TYPE ty_dynpro. + + lt_dynpros = serialize_dynpros( iv_program ). + + LOOP AT lt_dynpros ASSIGNING . + + lv_object = |{ -header-screen }{ -header-program }|. + + IF exists_a_lock_entry_for( iv_lock_object = 'ESCRP' + iv_argument = lv_object ) = abap_true. + rv_is_any_dynpro_locked = abap_true. + EXIT. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD is_cua_locked. + + DATA: lv_object TYPE eqegraarg. + + lv_object = |CU{ iv_program }|. + OVERLAY lv_object WITH ' '. + lv_object = lv_object && '*'. + + rv_is_cua_locked = exists_a_lock_entry_for( iv_lock_object = 'ESCUAPAINT' + iv_argument = lv_object ). + + ENDMETHOD. + METHOD is_exit_include. + rv_is_exit_include = boolc( + iv_program CP 'LX*' OR iv_program CP 'SAPLX*' OR + iv_program+1 CP '/LX*' OR iv_program+1 CP '/SAPLX*' ). + ENDMETHOD. + METHOD is_text_locked. + + DATA: lv_object TYPE eqegraarg. + + lv_object = |*{ iv_program }|. + + rv_is_text_locked = exists_a_lock_entry_for( iv_lock_object = 'EABAPTEXTE' + iv_argument = lv_object ). + + ENDMETHOD. + METHOD read_tpool. + + FIELD-SYMBOLS: LIKE LINE OF it_tpool, + LIKE LINE OF rt_tpool. + LOOP AT it_tpool ASSIGNING . + APPEND INITIAL LINE TO rt_tpool ASSIGNING . + MOVE-CORRESPONDING TO . + IF -id = 'S'. + CONCATENATE -split -entry + INTO -entry + RESPECTING BLANKS. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD serialize_cua. + + CALL FUNCTION 'RS_CUA_INTERNAL_FETCH' + EXPORTING + program = iv_program_name + language = mv_language + state = c_state-active + IMPORTING + adm = rs_cua-adm + TABLES + sta = rs_cua-sta + fun = rs_cua-fun + men = rs_cua-men + mtx = rs_cua-mtx + act = rs_cua-act + but = rs_cua-but + pfk = rs_cua-pfk + set = rs_cua-set + doc = rs_cua-doc + tit = rs_cua-tit + biv = rs_cua-biv + EXCEPTIONS + not_found = 1 + unknown_version = 2 + OTHERS = 3. + IF sy-subrc > 1. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD serialize_dynpros. + DATA: ls_header TYPE rpy_dyhead, + lt_containers TYPE dycatt_tab, + lt_fields_to_containers TYPE dyfatc_tab, + lt_flow_logic TYPE swydyflow, + lt_d020s TYPE TABLE OF d020s, + lt_texts TYPE TABLE OF d021t, + lt_fieldlist_int TYPE TABLE OF d021s. "internal format + + FIELD-SYMBOLS: LIKE LINE OF lt_d020s, + TYPE scrpostyle, + LIKE LINE OF lt_containers, + LIKE LINE OF lt_fields_to_containers, + LIKE LINE OF rt_dynpro, + LIKE LINE OF lt_fieldlist_int. + + "#2746: relevant flag values (taken from include MSEUSBIT) + CONSTANTS: lc_flg1ddf TYPE x VALUE '20', + lc_flg3fku TYPE x VALUE '08', + lc_flg3for TYPE x VALUE '04', + lc_flg3fdu TYPE x VALUE '02'. + CALL FUNCTION 'RS_SCREEN_LIST' + EXPORTING + dynnr = '' + progname = iv_program_name + TABLES + dynpros = lt_d020s + EXCEPTIONS + not_found = 1 + OTHERS = 2. + IF sy-subrc = 2. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + SORT lt_d020s BY dnum ASCENDING. + +* loop dynpros and skip generated selection screens + LOOP AT lt_d020s ASSIGNING + WHERE type <> 'S' AND type <> 'W' AND type <> 'J' + AND NOT dnum IS INITIAL. + + CALL FUNCTION 'RPY_DYNPRO_READ' + EXPORTING + progname = iv_program_name + dynnr = -dnum + IMPORTING + header = ls_header + TABLES + containers = lt_containers + fields_to_containers = lt_fields_to_containers + flow_logic = lt_flow_logic + EXCEPTIONS + cancelled = 1 + not_found = 2 + permission_error = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + "#2746: we need the dynpro fields in internal format: + FREE lt_fieldlist_int. + + CALL FUNCTION 'RPY_DYNPRO_READ_NATIVE' + EXPORTING + progname = iv_program_name + dynnr = -dnum + TABLES + fieldlist = lt_fieldlist_int + fieldtexts = lt_texts. + + LOOP AT lt_fields_to_containers ASSIGNING . +* output style is a NUMC field, the XML conversion will fail if it contains invalid value +* field does not exist in all versions + ASSIGN COMPONENT 'OUTPUTSTYLE' OF STRUCTURE TO . + IF sy-subrc = 0 AND = ' '. + CLEAR . + ENDIF. + + "2746: we apply the same logic as in SAPLWBSCREEN + "for setting or unsetting the foreignkey field: + UNASSIGN . + READ TABLE lt_fieldlist_int ASSIGNING WITH KEY fnam = -name. + IF IS ASSIGNED. + IF -flg1 O lc_flg1ddf AND + -flg3 O lc_flg3for AND + -flg3 Z lc_flg3fdu AND + -flg3 Z lc_flg3fku. + -foreignkey = 'X'. + ELSE. + CLEAR -foreignkey. + ENDIF. + ENDIF. + + IF -from_dict = abap_true AND + -modific <> 'F' AND + -modific <> 'X'. + CLEAR -text. + ENDIF. + ENDLOOP. + + LOOP AT lt_containers ASSIGNING . + IF -c_resize_v = abap_false. + CLEAR -c_line_min. + ENDIF. + IF -c_resize_h = abap_false. + CLEAR -c_coln_min. + ENDIF. + ENDLOOP. + + APPEND INITIAL LINE TO rt_dynpro ASSIGNING . + -header = ls_header. + + " Store flow logic as separate ABAP files instead of XML + mo_files->add_abap( + iv_extra = 'screen_' && ls_header-screen + it_abap = lt_flow_logic ). + + READ TABLE lt_fieldlist_int TRANSPORTING NO FIELDS WITH KEY fill = 'X'. + IF ls_header-type CA c_native_dynpro AND sy-subrc = 0. + " In particular for dynpros with splitter + -nat_header = . + CLEAR: -nat_header-dgen, -nat_header-tgen. + -nat_fields = lt_fieldlist_int. + -nat_texts = lt_texts. + ELSE. + -containers = lt_containers. + -fields = lt_fields_to_containers. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD serialize_program. + + DATA: ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, + lv_program_name TYPE syrepid, + lt_dynpros TYPE ty_dynpro_tt, + ls_cua TYPE ty_cua, + li_report TYPE REF TO zif_abapgit_sap_report, + lt_source TYPE TABLE OF abaptxt255, + lt_tpool TYPE textpool_table, + ls_tpool LIKE LINE OF lt_tpool, + li_xml TYPE REF TO zif_abapgit_xml_output. + + IF iv_program IS INITIAL. + lv_program_name = is_item-obj_name. + ELSE. + lv_program_name = iv_program. + ENDIF. + + zcl_abapgit_language=>set_current_language( mv_language ). + + CALL FUNCTION 'RPY_PROGRAM_READ' + EXPORTING + program_name = lv_program_name + with_includelist = abap_false + with_lowercase = abap_true + TABLES + source_extended = lt_source + textelements = lt_tpool + EXCEPTIONS + cancelled = 1 + not_found = 2 + permission_error = 3 + OTHERS = 4. + + IF sy-subrc = 2. + zcl_abapgit_language=>restore_login_language( ). + RETURN. + ELSEIF sy-subrc <> 0. + zcl_abapgit_language=>restore_login_language( ). + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + zcl_abapgit_language=>restore_login_language( ). + + " If inactive version exists, then RPY_PROGRAM_READ does not return the active code + li_report = zcl_abapgit_factory=>get_sap_report( ). + + TRY. + " Raises exception if inactive version does not exist + ls_progdir = li_report->read_progdir( + iv_name = lv_program_name + iv_state = c_state-inactive ). + + " Explicitly request active source code + lt_source = li_report->read_report( + iv_name = lv_program_name + iv_state = c_state-active ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + ls_progdir = li_report->read_progdir( + iv_name = lv_program_name + iv_state = c_state-active ). + + clear_abap_language_version( CHANGING cv_abap_language_version = ls_progdir-uccheck ). + + IF io_xml IS BOUND. + li_xml = io_xml. + ELSE. + CREATE OBJECT li_xml TYPE zcl_abapgit_xml_output. + ENDIF. + + li_xml->add( iv_name = 'PROGDIR' + ig_data = ls_progdir ). + IF ls_progdir-subc = '1' OR ls_progdir-subc = 'M'. + lt_dynpros = serialize_dynpros( lv_program_name ). + li_xml->add( iv_name = 'DYNPROS' + ig_data = lt_dynpros ). + + ls_cua = serialize_cua( lv_program_name ). + IF NOT ls_cua IS INITIAL. + li_xml->add( iv_name = 'CUA' + ig_data = ls_cua ). + ENDIF. + ENDIF. + + READ TABLE lt_tpool WITH KEY id = 'R' INTO ls_tpool. + IF sy-subrc = 0 AND ls_tpool-key = '' AND ls_tpool-length = 0. + DELETE lt_tpool INDEX sy-tabix. + ENDIF. + + li_xml->add( iv_name = 'TPOOL' + ig_data = add_tpool( lt_tpool ) ). + + IF NOT io_xml IS BOUND. + io_files->add_xml( iv_extra = iv_extra + ii_xml = li_xml ). + ENDIF. + + strip_generation_comments( CHANGING ct_source = lt_source ). + + io_files->add_abap( iv_extra = iv_extra + it_abap = lt_source ). + + ENDMETHOD. + METHOD strip_generation_comments. + + FIELD-SYMBOLS TYPE any. " Assuming CHAR (e.g. abaptxt255_tab) or string (FUGR) + + IF ms_item-obj_type <> 'FUGR'. + RETURN. + ENDIF. + + " Case 1: MV FM main prog and TOPs + READ TABLE ct_source INDEX 1 ASSIGNING . + IF sy-subrc = 0 AND CP '#**regenerated at *'. + DELETE ct_source INDEX 1. + RETURN. + ENDIF. + + " Case 2: MV FM includes + IF lines( ct_source ) < 5. " Generation header length + RETURN. + ENDIF. + + READ TABLE ct_source INDEX 1 ASSIGNING . + ASSERT sy-subrc = 0. + IF NOT CP '#*---*'. + RETURN. + ENDIF. + + READ TABLE ct_source INDEX 2 ASSIGNING . + ASSERT sy-subrc = 0. + IF NOT CP '#**'. + RETURN. + ENDIF. + + READ TABLE ct_source INDEX 3 ASSIGNING . + ASSERT sy-subrc = 0. + IF NOT CP '#**generation date:*'. + RETURN. + ENDIF. + + READ TABLE ct_source INDEX 4 ASSIGNING . + ASSERT sy-subrc = 0. + IF NOT CP '#**generator version:*'. + RETURN. + ENDIF. + + READ TABLE ct_source INDEX 5 ASSIGNING . + ASSERT sy-subrc = 0. + IF NOT CP '#*---*'. + RETURN. + ENDIF. + + DELETE ct_source INDEX 4. + DELETE ct_source INDEX 3. + + ENDMETHOD. + METHOD uncondense_flow. + + DATA: lv_spaces LIKE LINE OF it_spaces. + + FIELD-SYMBOLS: LIKE LINE OF it_flow, + LIKE LINE OF rt_flow. + LOOP AT it_flow ASSIGNING . + APPEND INITIAL LINE TO rt_flow ASSIGNING . + -line = -line. + + READ TABLE it_spaces INDEX sy-tabix INTO lv_spaces. + IF sy-subrc = 0. + SHIFT -line RIGHT BY lv_spaces PLACES IN CHARACTER MODE. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD update_program. + + zcl_abapgit_language=>set_current_language( mv_language ). + + CALL FUNCTION 'RPY_PROGRAM_UPDATE' + EXPORTING + program_name = is_progdir-name + title_string = iv_title + save_inactive = iv_state + TABLES + source_extended = it_source + EXCEPTIONS + cancelled = 1 + permission_error = 2 + not_found = 3 + OTHERS = 4. + + IF sy-subrc <> 0. + zcl_abapgit_language=>restore_login_language( ). + + IF sy-msgid = 'EU' AND sy-msgno = '510'. + zcx_abapgit_exception=>raise( 'User is currently editing program' ). + ELSEIF sy-msgid = 'EU' AND sy-msgno = '522'. + " for generated table maintenance function groups, the author is set to SAP* instead of the user which + " generates the function group. This hits some standard checks, pulling new code again sets the author + " to the current user which avoids the check + IF is_exit_include( is_progdir-name ) = abap_false. + zcx_abapgit_exception=>raise( |Delete function group and pull again, { is_progdir-name } (EU522)| ). + ENDIF. + ELSE. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + zcl_abapgit_language=>restore_login_language( ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_objects_generic IMPLEMENTATION. + METHOD after_import. + + DATA: lt_cts_object_entry TYPE STANDARD TABLE OF e071 WITH DEFAULT KEY, + ls_cts_object_entry LIKE LINE OF lt_cts_object_entry, + lt_cts_key TYPE STANDARD TABLE OF e071k WITH DEFAULT KEY. + + FIELD-SYMBOLS LIKE LINE OF mt_object_method. + ls_cts_object_entry-pgmid = 'R3TR'. + ls_cts_object_entry-object = ms_item-obj_type. + ls_cts_object_entry-obj_name = ms_item-obj_name. + INSERT ls_cts_object_entry INTO TABLE lt_cts_object_entry. + + READ TABLE mt_object_method ASSIGNING + WITH KEY + objectname = ms_item-obj_type + objecttype = 'L' + method = 'AFTER_IMP'. + IF sy-subrc = 0. +* client is actually optional for most AIM, but let's supply it and hope +* that those client-independent-ones just ignore it + CALL FUNCTION -methodname + EXPORTING + iv_tarclient = sy-mandt + iv_is_upgrade = abap_false + TABLES + tt_e071 = lt_cts_object_entry + tt_e071k = lt_cts_key. + ENDIF. + + ENDMETHOD. + METHOD apply_clear_logic. + IF mo_field_rules IS BOUND. + mo_field_rules->apply_clear_logic( EXPORTING iv_table = |{ iv_table }| + CHANGING ct_data = ct_data ). + ENDIF. + ENDMETHOD. + METHOD apply_fill_logic. + IF mo_field_rules IS BOUND. + mo_field_rules->apply_fill_logic( + EXPORTING + iv_table = |{ iv_table }| + iv_package = iv_package + CHANGING + ct_data = ct_data ). + ENDIF. + ENDMETHOD. + METHOD before_export. + + DATA: lt_cts_object_entry TYPE STANDARD TABLE OF e071 WITH DEFAULT KEY, + ls_cts_object_entry LIKE LINE OF lt_cts_object_entry, + lt_cts_key TYPE STANDARD TABLE OF e071k WITH DEFAULT KEY, + lv_client TYPE trclient. + + FIELD-SYMBOLS LIKE LINE OF mt_object_method. + READ TABLE mt_object_method ASSIGNING + WITH KEY + objectname = ms_item-obj_type + objecttype = 'L' + method = 'BEFORE_EXP'. + IF sy-subrc = 0. + lv_client = sy-mandt. + + ls_cts_object_entry-pgmid = 'R3TR'. + ls_cts_object_entry-object = ms_item-obj_type. + ls_cts_object_entry-obj_name = ms_item-obj_name. + INSERT ls_cts_object_entry INTO TABLE lt_cts_object_entry. + + CALL FUNCTION -methodname + EXPORTING + iv_client = lv_client + TABLES + tt_e071 = lt_cts_object_entry + tt_e071k = lt_cts_key. + ENDIF. + + ENDMETHOD. + METHOD constructor. + + CONSTANTS lc_logical_transport_object TYPE c LENGTH 1 VALUE 'L'. + SELECT SINGLE * FROM objh INTO ms_object_header + WHERE objectname = is_item-obj_type + AND objecttype = lc_logical_transport_object. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDIF. + + " object tables + SELECT * FROM objsl INTO CORRESPONDING FIELDS OF TABLE mt_object_table + WHERE objectname = is_item-obj_type + AND objecttype = lc_logical_transport_object + AND tobject = 'TABU' + ORDER BY PRIMARY KEY. + IF mt_object_table IS INITIAL. + zcx_abapgit_exception=>raise( |Obviously corrupted object-type { is_item-obj_type }: No tables defined| ). + ENDIF. + + " remove duplicate table/table-key entries + " same table with different keys is ok + SORT mt_object_table BY tobj_name tobjkey. + DELETE ADJACENT DUPLICATES FROM mt_object_table COMPARING tobj_name tobjkey. + + " object methods + SELECT * FROM objm INTO TABLE mt_object_method + WHERE objectname = is_item-obj_type + AND objecttype = lc_logical_transport_object + ORDER BY PRIMARY KEY. + + ms_item = is_item. + mv_language = iv_language. + mo_field_rules = io_field_rules. + + ENDMETHOD. + METHOD corr_insert. + +* this will also insert into TADIR + zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + iv_package = iv_package + iv_language = mv_language ). + + ENDMETHOD. + METHOD delete. + + DATA: lv_where TYPE string, + lv_primary TYPE objsl-tobj_name. + + FIELD-SYMBOLS LIKE LINE OF mt_object_table. + lv_primary = get_primary_table( ). + + LOOP AT mt_object_table ASSIGNING . + lv_where = get_where_clause( -tobj_name ). + ASSERT NOT lv_where IS INITIAL. + + DELETE FROM (-tobj_name) WHERE (lv_where). + + IF -tobj_name = lv_primary. + ASSERT sy-dbcnt <= 1. "Just to be on the very safe side + ENDIF. + ENDLOOP. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD deserialize. + + validate( io_xml ). + + delete( iv_package ). + + deserialize_data( + io_xml = io_xml + iv_package = iv_package ). + + after_import( ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD deserialize_data. + + DATA: lr_ref TYPE REF TO data. + + FIELD-SYMBOLS: TYPE STANDARD TABLE, + LIKE LINE OF mt_object_table. + LOOP AT mt_object_table ASSIGNING . + + CREATE DATA lr_ref TYPE STANDARD TABLE OF (-tobj_name). + ASSIGN lr_ref->* TO . + + io_xml->read( + EXPORTING + iv_name = -tobj_name + CHANGING + cg_data = ). + apply_fill_logic( + EXPORTING + iv_table = -tobj_name + iv_package = iv_package + CHANGING + ct_data = ). + + INSERT (-tobj_name) FROM TABLE . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error inserting data, { -tobj_name }| ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD distribute_name_to_components. + + DATA: lt_key_component_uncovered LIKE it_key_component, + ls_key_component_uncovered LIKE LINE OF lt_key_component_uncovered, + ls_objkey_sub LIKE cs_objkey, + lv_objkey_sub_pos TYPE i, + lv_remaining_length TYPE i, + lv_count_components_covered LIKE ls_objkey_sub-num. + + DATA lv_len LIKE ls_key_component_uncovered-leng. + lt_key_component_uncovered = it_key_component. + ls_objkey_sub-num = cs_objkey-num. + lv_objkey_sub_pos = 0. + +* we want to fill the attribute values which are not covered by explicit key components yet + lv_count_components_covered = ls_objkey_sub-num - 1. + DO lv_count_components_covered TIMES. + DELETE lt_key_component_uncovered INDEX 1. + ENDDO. + + LOOP AT lt_key_component_uncovered INTO ls_key_component_uncovered. + CLEAR ls_objkey_sub-value. + +* Some datatype used in the key might exceed the total remaining characters length (e. g. SICF) + TRY. + lv_remaining_length = strlen( |{ substring( val = cs_objkey-value + off = lv_objkey_sub_pos ) }| ). + CATCH cx_sy_range_out_of_bounds. + lv_remaining_length = 0. + RETURN. ">>>>>>>>>>>>>>>>>>>>>>>>>>> + ENDTRY. + IF ls_key_component_uncovered-leng <= lv_remaining_length. + lv_len = ls_key_component_uncovered-leng. + ELSE. + lv_len = lv_remaining_length. + ENDIF. + + ls_objkey_sub-value = |{ substring( val = cs_objkey-value + off = lv_objkey_sub_pos + len = lv_len ) }|. + ls_objkey_sub-num = cv_non_value_pos. + + INSERT ls_objkey_sub INTO TABLE ct_objkey. + + lv_objkey_sub_pos = lv_objkey_sub_pos + ls_key_component_uncovered-leng. + cv_non_value_pos = cv_non_value_pos + 1. + CLEAR ls_objkey_sub. + + IF lv_objkey_sub_pos = strlen( cs_objkey-value ). + cs_objkey-num = cv_non_value_pos. + EXIT. "end splitting - all characters captured + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD exists. + + DATA: lv_where_clause TYPE string, + lv_primary TYPE objsl-tobj_name, + lr_table_line TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any. + lv_primary = get_primary_table( ). + + lv_where_clause = get_where_clause( lv_primary ). + + CREATE DATA lr_table_line TYPE (lv_primary). + ASSIGN lr_table_line->* TO . + + SELECT SINGLE * FROM (lv_primary) INTO WHERE (lv_where_clause). + rv_bool = boolc( sy-dbcnt > 0 ). + + ENDMETHOD. + METHOD get_key_fields. + + DATA: lv_table TYPE ddobjname. + lv_table = iv_table. + + CALL FUNCTION 'DDIF_NAMETAB_GET' + EXPORTING + tabname = lv_table + TABLES + dfies_tab = rt_keys + EXCEPTIONS + not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + DELETE rt_keys WHERE keyflag = abap_false. + + ENDMETHOD. + METHOD get_primary_table. + + DATA: ls_object_table LIKE LINE OF mt_object_table. + DATA: lt_object_table LIKE mt_object_table. + + " There might be several tables marked as "primary" + " Sort by DB key so we get first one in the list + lt_object_table = mt_object_table. + SORT lt_object_table. + + READ TABLE lt_object_table INTO ls_object_table WITH KEY prim_table = abap_true. + IF sy-subrc <> 0. + " Fallback. For some objects, no primary table is explicitly flagged + " Then, the one with only one key field shall be chosen + READ TABLE lt_object_table INTO ls_object_table WITH KEY tobjkey = '/&'. "#EC CI_SUBRC + ENDIF. + IF ls_object_table IS INITIAL. + zcx_abapgit_exception=>raise( |Object { ms_item-obj_type } has got no defined primary table| ). + ENDIF. + + rv_table = ls_object_table-tobj_name. + + ENDMETHOD. + METHOD get_where_clause. + + DATA: lv_objkey_pos TYPE i, + lv_next_objkey_pos TYPE i, + lv_value_pos TYPE i, + lv_objkey_length TYPE i, + lt_objkey TYPE ty_t_objkey, + ls_objkey LIKE LINE OF lt_objkey, + lv_non_value_pos TYPE numc3, + lt_key_fields TYPE ddfields. + + DATA: lv_is_asterix TYPE abap_bool, + lv_where_statement TYPE string, + lv_key_pos TYPE i, + lv_value128 TYPE string. + + FIELD-SYMBOLS LIKE LINE OF mt_object_table. + + FIELD-SYMBOLS LIKE LINE OF lt_key_fields. + READ TABLE mt_object_table ASSIGNING WITH KEY tobj_name = iv_tobj_name. + ASSERT sy-subrc = 0. + + lt_key_fields = get_key_fields( iv_tobj_name ). + +* analyze the object key and compose the key (table) + CLEAR lt_objkey. + CLEAR ls_objkey. + lv_objkey_pos = 0. + lv_non_value_pos = 1. + lv_value_pos = 0. + lv_objkey_length = strlen( -tobjkey ). + + WHILE lv_objkey_pos <= lv_objkey_length. + ls_objkey-num = lv_non_value_pos. +* command + IF -tobjkey+lv_objkey_pos(1) = '/'. + IF NOT ls_objkey-value IS INITIAL. +* We reached the end of a key-definition. +* this key part may address multiple fields. +* E. g. six characters may address one boolean field and a five-digit version field. +* Thus, we need to analyze the remaining key components which have not been covered yet. + split_value_to_keys( + EXPORTING + it_key_component = lt_key_fields + CHANGING + ct_objkey = lt_objkey + cs_objkey = ls_objkey + cv_non_value_pos = lv_non_value_pos ). + ENDIF. + lv_next_objkey_pos = lv_objkey_pos + 1. +* '*' means all further key values + IF -tobjkey+lv_next_objkey_pos(1) = '*'. + ls_objkey-value = '*'. + INSERT ls_objkey INTO TABLE lt_objkey. + CLEAR ls_objkey. + lv_non_value_pos = lv_non_value_pos + 1. + lv_objkey_pos = lv_objkey_pos + 1. +* object name + ELSEIF -tobjkey+lv_next_objkey_pos(1) = '&'. + ls_objkey-value = ms_item-obj_name. +* The object name might comprise multiple key components (e. g. WDCC) +* This string needs to be split + distribute_name_to_components( + EXPORTING + it_key_component = lt_key_fields + CHANGING + ct_objkey = lt_objkey + cs_objkey = ls_objkey + cv_non_value_pos = lv_non_value_pos ). + CLEAR ls_objkey. + lv_objkey_pos = lv_objkey_pos + 1. +* language + ELSEIF -tobjkey+lv_next_objkey_pos(1) = 'L'. + ls_objkey-value = mv_language. + INSERT ls_objkey INTO TABLE lt_objkey. + CLEAR ls_objkey. + lv_non_value_pos = lv_non_value_pos + 1. + lv_objkey_pos = lv_objkey_pos + 1. +* Client + ELSEIF -tobjkey+lv_next_objkey_pos(1) = 'C'. + ls_objkey-value = sy-mandt. + INSERT ls_objkey INTO TABLE lt_objkey. + CLEAR ls_objkey. + lv_non_value_pos = lv_non_value_pos + 1. + lv_objkey_pos = lv_objkey_pos + 1. + ENDIF. + lv_value_pos = 0. +* value + ELSE. + ls_objkey-value+lv_value_pos(1) = -tobjkey+lv_objkey_pos(1). + lv_value_pos = lv_value_pos + 1. + ENDIF. + + lv_objkey_pos = lv_objkey_pos + 1. + ENDWHILE. + +* Similarly to that, fixed values might be supplied in the object key which actually make up key components + IF NOT ls_objkey-value IS INITIAL. + split_value_to_keys( + EXPORTING + it_key_component = lt_key_fields + CHANGING + ct_objkey = lt_objkey + cs_objkey = ls_objkey + cv_non_value_pos = lv_non_value_pos ). + ENDIF. + +* compose the where clause + lv_is_asterix = abap_false. + lv_key_pos = 1. + + LOOP AT lt_key_fields ASSIGNING . + READ TABLE lt_objkey INTO ls_objkey + WITH TABLE KEY num = lv_key_pos. + IF sy-subrc <> 0 OR -fieldname = 'LANGU'. + CLEAR ls_objkey. + lv_key_pos = lv_key_pos + 1. + CONTINUE. + ENDIF. + IF ls_objkey-value = '*'. + lv_is_asterix = abap_true. + ENDIF. + IF lv_is_asterix = abap_true. + CONTINUE. + ENDIF. + IF NOT lv_where_statement IS INITIAL. + CONCATENATE lv_where_statement 'AND' INTO lv_where_statement + SEPARATED BY space. + ENDIF. + lv_value128 = cl_abap_dyn_prg=>quote( ls_objkey-value ). + CONCATENATE lv_where_statement -fieldname '=' + lv_value128 INTO lv_where_statement SEPARATED BY space. + lv_key_pos = lv_key_pos + 1. + ENDLOOP. + + rv_where = condense( lv_where_statement ). + + ENDMETHOD. + METHOD serialize. + + before_export( ). + + serialize_data( io_xml ). + + ENDMETHOD. + METHOD serialize_data. + + DATA: lr_ref TYPE REF TO data, + lv_where TYPE string. + + FIELD-SYMBOLS: TYPE STANDARD TABLE, + LIKE LINE OF mt_object_table. + LOOP AT mt_object_table ASSIGNING . + + CREATE DATA lr_ref TYPE STANDARD TABLE OF (-tobj_name). + ASSIGN lr_ref->* TO . + + lv_where = get_where_clause( -tobj_name ). + + SELECT * FROM (-tobj_name) + INTO TABLE + WHERE (lv_where) + ORDER BY PRIMARY KEY. + + apply_clear_logic( EXPORTING iv_table = -tobj_name + CHANGING ct_data = ). + + io_xml->add( + iv_name = -tobj_name + ig_data = ). + + ENDLOOP. + + ENDMETHOD. + METHOD split_value_to_keys. + + DATA: lt_key_component_uncovered LIKE it_key_component, + ls_dummy LIKE LINE OF ct_objkey, + ls_key_component_uncovered LIKE LINE OF lt_key_component_uncovered, + ls_objkey_sub LIKE cs_objkey, + lv_objkey_sub_pos TYPE i. + lt_key_component_uncovered = it_key_component. + +* we want to fill the attribute values which are not covered by explicit key components yet + LOOP AT ct_objkey INTO ls_dummy. + DELETE lt_key_component_uncovered INDEX 1. + ENDLOOP. + + ls_objkey_sub-num = cs_objkey-num. + lv_objkey_sub_pos = 0. + LOOP AT lt_key_component_uncovered INTO ls_key_component_uncovered. + CLEAR ls_objkey_sub-value. + ls_objkey_sub-value = cs_objkey-value+lv_objkey_sub_pos(ls_key_component_uncovered-leng). + ls_objkey_sub-num = cv_non_value_pos. + + INSERT ls_objkey_sub INTO TABLE ct_objkey. + + lv_objkey_sub_pos = lv_objkey_sub_pos + ls_key_component_uncovered-leng. + cv_non_value_pos = cv_non_value_pos + 1. + CLEAR ls_objkey_sub. + + IF lv_objkey_sub_pos = strlen( cs_objkey-value ). + cs_objkey-num = cv_non_value_pos. + EXIT. "end splitting - all characters captured + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD validate. + + DATA: lv_where TYPE string, + lv_primary TYPE objsl-tobj_name, + lr_ref TYPE REF TO data. + + FIELD-SYMBOLS: TYPE STANDARD TABLE. + lv_primary = get_primary_table( ). + + CREATE DATA lr_ref TYPE STANDARD TABLE OF (lv_primary). + ASSIGN lr_ref->* TO . + + io_xml->read( + EXPORTING + iv_name = lv_primary + CHANGING + cg_data = ). + + IF lines( ) = 0. + zcx_abapgit_exception=>raise( |Primary table { lv_primary } not found in imported container| ). + ELSEIF lines( ) <> 1. + zcx_abapgit_exception=>raise( |Primary table { lv_primary } contains more than one instance!| ). + ENDIF. + + lv_where = get_where_clause( lv_primary ). + +* validate that max one local instance was affected by the import + SELECT COUNT(*) FROM (lv_primary) WHERE (lv_where). + IF sy-dbcnt > 1. + zcx_abapgit_exception=>raise( |More than one instance exists locally in primary table { lv_primary }| ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECTS_FACTORY IMPLEMENTATION. + METHOD get_gui_jumper. + + IF gi_gui_jumper IS INITIAL. + CREATE OBJECT gi_gui_jumper TYPE zcl_abapgit_gui_jumper. + ENDIF. + + ri_gui_jumper = gi_gui_jumper. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_objects_bridge IMPLEMENTATION. + METHOD constructor. + + DATA ls_objtype_map LIKE LINE OF gt_objtype_map. + + super->constructor( + is_item = is_item + iv_language = zif_abapgit_definitions=>c_english + io_files = io_files + io_i18n_params = io_i18n_params ). + + initialize( ). + +* determine the responsible plugin + READ TABLE gt_objtype_map INTO ls_objtype_map + WITH TABLE KEY obj_typ = is_item-obj_type. + IF sy-subrc = 0. + CREATE OBJECT mo_plugin TYPE (ls_objtype_map-plugin_class). + + CALL METHOD mo_plugin->('SET_ITEM') + EXPORTING + iv_obj_type = is_item-obj_type + iv_obj_name = is_item-obj_name. + ELSE. + RAISE EXCEPTION TYPE cx_sy_create_object_error + EXPORTING + classname = 'LCL_OBJECTS_BRIDGE'. + ENDIF. + ENDMETHOD. + METHOD initialize. + + DATA lt_plugin_class TYPE STANDARD TABLE OF seoclsname WITH DEFAULT KEY. + DATA lv_plugin_class LIKE LINE OF lt_plugin_class. + DATA lo_plugin TYPE REF TO object. + DATA lt_plugin_obj_type TYPE STANDARD TABLE OF tadir-object WITH DEFAULT KEY. + DATA ls_objtype_map LIKE LINE OF gt_objtype_map. + + IF gv_init = abap_true. + RETURN. + ENDIF. + gv_init = abap_true. + + SELECT clsname + FROM seometarel + INTO TABLE lt_plugin_class + WHERE refclsname LIKE 'ZCL_ABAPGITP_OBJECT%' + AND version = '1' + ORDER BY clsname. "#EC CI_SUBRC + + CLEAR gt_objtype_map. + LOOP AT lt_plugin_class INTO lv_plugin_class + WHERE table_line <> 'ZCL_ABAPGITP_OBJECT_BY_SOBJ'. +* have the generic plugin only as fallback + TRY. + CREATE OBJECT lo_plugin TYPE (lv_plugin_class). + CATCH cx_sy_create_object_error. + CONTINUE. ">>>>>>>>>>>>>> + ENDTRY. + + CALL METHOD lo_plugin->('GET_SUPPORTED_OBJ_TYPES') + IMPORTING + rt_obj_type = lt_plugin_obj_type. + + ls_objtype_map-plugin_class = lv_plugin_class. + LOOP AT lt_plugin_obj_type INTO ls_objtype_map-obj_typ. + INSERT ls_objtype_map INTO TABLE gt_objtype_map. + IF sy-subrc <> 0. +* No exception in class-constructor possible. +* Anyway, a shortdump is more appropriate in this case + ASSERT 'There must not be' = + |multiple abapGit-Plugins for the same object type { + ls_objtype_map-obj_typ }|. + ENDIF. + ENDLOOP. + ENDLOOP. "at plugins + +* and the same for the generic plugin if exists +* have the generic plugin only as fallback + LOOP AT lt_plugin_class INTO lv_plugin_class + WHERE table_line = 'ZCL_ABAPGITP_OBJECT_BY_SOBJ'. + CREATE OBJECT lo_plugin TYPE (lv_plugin_class). + + CALL METHOD lo_plugin->('GET_SUPPORTED_OBJ_TYPES') + RECEIVING + rt_obj_type = lt_plugin_obj_type. + + ls_objtype_map-plugin_class = lv_plugin_class. + LOOP AT lt_plugin_obj_type INTO ls_objtype_map-obj_typ. + INSERT ls_objtype_map INTO TABLE gt_objtype_map. "knowingly ignore the subrc + ENDLOOP. + ENDLOOP. "at plugins + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " todo + ENDMETHOD. + METHOD zif_abapgit_object~delete. + DATA lx_plugin TYPE REF TO cx_static_check. + + TRY. + CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~DELETE'). + CATCH cx_static_check INTO lx_plugin. + zcx_abapgit_exception=>raise( lx_plugin->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lx_plugin TYPE REF TO cx_static_check. + + TRY. + CALL METHOD mo_plugin->('WRAP_DESERIALIZE') + EXPORTING + iv_package = iv_package + io_xml = io_xml. + CATCH cx_static_check INTO lx_plugin. + zcx_abapgit_exception=>raise( lx_plugin->get_text( ) ). + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~EXISTS') + RECEIVING + rv_bool = rv_bool. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + + DATA ls_meta TYPE ty_metadata. + + CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~GET_METADATA') + RECEIVING + rs_metadata = ls_meta. + + IF ls_meta-late_deser = abap_true. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ELSEIF ls_meta-ddic = abap_true. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + ELSE. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + + DATA ls_meta TYPE ty_metadata. + + CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~GET_METADATA') + RECEIVING + rs_metadata = ls_meta. + + MOVE-CORRESPONDING ls_meta TO rs_metadata. + + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = abap_true. + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~JUMP'). + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + CALL METHOD mo_plugin->('WRAP_SERIALIZE') + EXPORTING + io_xml = io_xml. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_objects IMPLEMENTATION. + METHOD changed_by. + + DATA: li_obj TYPE REF TO zif_abapgit_object. + + " For unsupported objects, return empty string + IF is_type_supported( is_item-obj_type ) = abap_false. + RETURN. + ENDIF. + + TRY. + li_obj = create_object( is_item ). + rv_user = li_obj->changed_by( get_extra_from_filename( iv_filename ) ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + " Ignore errors + ENDTRY. + + IF rv_user IS INITIAL. + " Eg. ".abapgit.xml" file + rv_user = zcl_abapgit_objects_super=>c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD change_package_assignments. + + TRY. + zcl_abapgit_factory=>get_tadir( )->insert_single( + iv_object = is_item-obj_type + iv_obj_name = is_item-obj_name + iv_package = is_item-devclass ). + + ii_log->add_success( iv_msg = |Object { is_item-obj_name } assigned to package { is_item-devclass }| + is_item = is_item ). + CATCH zcx_abapgit_exception. + ii_log->add_error( iv_msg = |Package change of object { is_item-obj_name } failed| + is_item = is_item ). + ENDTRY. + + ENDMETHOD. + METHOD check_duplicates. + + DATA: lt_files TYPE zif_abapgit_git_definitions=>ty_files_tt, + lv_path TYPE string, + lv_filename TYPE string, + lt_duplicates TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + lv_duplicates LIKE LINE OF lt_duplicates, + lv_all_duplicates TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF it_files. + + lt_files = it_files. + SORT lt_files BY path ASCENDING filename ASCENDING. + + LOOP AT lt_files ASSIGNING . + IF lv_path = -path AND lv_filename = -filename. + CONCATENATE -path -filename INTO lv_duplicates. + APPEND lv_duplicates TO lt_duplicates. + ENDIF. + lv_path = -path. + lv_filename = -filename. + ENDLOOP. + + IF lt_duplicates IS NOT INITIAL. + CONCATENATE LINES OF lt_duplicates INTO lv_all_duplicates SEPARATED BY `, `. + zcx_abapgit_exception=>raise( |Duplicates: { lv_all_duplicates }| ). + ENDIF. + + ENDMETHOD. + METHOD check_objects_locked. + + DATA: li_obj TYPE REF TO zif_abapgit_object. + + FIELD-SYMBOLS: LIKE LINE OF it_items. + + LOOP AT it_items ASSIGNING . + + " You should remember that we ignore not supported objects here, + " because otherwise the process aborts which is not desired + IF is_type_supported( -obj_type ) = abap_false. + CONTINUE. + ENDIF. + + li_obj = create_object( ). + + IF li_obj->is_locked( ) = abap_true. + zcx_abapgit_exception=>raise( |Object { -obj_type } { -obj_name } | + && |is locked. Action not possible.| ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD check_original_system. + + DATA: + lv_srcsystem TYPE tadir-srcsystem, + lv_error TYPE abap_bool. + + FIELD-SYMBOLS LIKE LINE OF it_items. + + lv_srcsystem = io_dot->get_original_system( ). + IF lv_srcsystem IS INITIAL. + RETURN. + ENDIF. + + ii_log->add_info( |>> Checking original system| ). + + LOOP AT it_items ASSIGNING WHERE srcsystem <> lv_srcsystem AND srcsystem IS NOT INITIAL. + ii_log->add_error( + iv_msg = |Object belongs to system { -srcsystem }. Can't overwrite it from system { lv_srcsystem }| + is_item = ). + lv_error = abap_true. + ENDLOOP. + + IF lv_error = abap_true. + zcx_abapgit_exception=>raise( 'Error trying to overwrite object from different system' ). + ENDIF. + + ENDMETHOD. + METHOD class_name. + + CONCATENATE 'ZCL_ABAPGIT_OBJECT_' is_item-obj_type INTO rv_class_name. + + ENDMETHOD. + METHOD create_object. + + DATA: lv_class_name TYPE string, + ls_obj_serializer_map LIKE LINE OF gt_obj_serializer_map. + + " serialize & deserialize require files and i18n parameters, + " other calls are good without them + ASSERT io_files IS BOUND AND io_i18n_params IS BOUND OR + io_files IS NOT BOUND AND io_i18n_params IS NOT BOUND. + + READ TABLE gt_obj_serializer_map + INTO ls_obj_serializer_map WITH KEY item = is_item. + IF sy-subrc = 0. + lv_class_name = ls_obj_serializer_map-metadata-class. + ELSEIF is_metadata IS NOT INITIAL. +* Metadata is provided only on deserialization +* Once this has been triggered, the same deserializer shall be used +* for subsequent processes. +* Thus, buffer the metadata afterwards + ls_obj_serializer_map-item = is_item. + ls_obj_serializer_map-metadata = is_metadata. + INSERT ls_obj_serializer_map INTO TABLE gt_obj_serializer_map. + lv_class_name = is_metadata-class. + ELSE. + lv_class_name = class_name( is_item ). + ENDIF. + + REPLACE FIRST OCCURRENCE OF 'LCL' IN lv_class_name WITH 'ZCL_ABAPGIT'. + + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. + " Prevent accidental usage of object handlers in the developer version + lv_class_name = |\\PROGRAM={ sy-repid }\\CLASS={ lv_class_name }|. + ENDIF. + + TRY. + IF io_files IS BOUND AND io_i18n_params IS BOUND. + CREATE OBJECT ri_obj TYPE (lv_class_name) + EXPORTING + is_item = is_item + iv_language = io_i18n_params->ms_params-main_language + io_files = io_files + io_i18n_params = io_i18n_params. + ELSE. + CREATE OBJECT ri_obj TYPE (lv_class_name) + EXPORTING + is_item = is_item + iv_language = zif_abapgit_definitions=>c_english. + ENDIF. + CATCH cx_sy_create_object_error. + IF iv_native_only = abap_true. + " No native support? -> fail + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDIF. + + TRY. " 2nd step, try looking for plugins + IF io_files IS BOUND AND io_i18n_params IS BOUND. + CREATE OBJECT ri_obj TYPE zcl_abapgit_objects_bridge + EXPORTING + is_item = is_item + io_files = io_files + io_i18n_params = io_i18n_params. + ELSE. + CREATE OBJECT ri_obj TYPE zcl_abapgit_objects_bridge + EXPORTING + is_item = is_item. + ENDIF. + CATCH cx_sy_create_object_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + ENDTRY. + + ENDMETHOD. + METHOD delete. + + DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, + li_progress TYPE REF TO zif_abapgit_progress, + lt_tadir LIKE it_tadir, + lt_deleted LIKE it_tadir, + lt_items TYPE zif_abapgit_definitions=>ty_items_tt, + lx_error TYPE REF TO zcx_abapgit_exception, + lv_count TYPE i. + + FIELD-SYMBOLS: LIKE LINE OF it_tadir. + + IF it_tadir IS INITIAL. + RETURN. + ENDIF. + + lt_tadir = it_tadir. + + IF ii_log IS BOUND. + IF lines( lt_tadir ) = 1. + ii_log->add_info( |>>> Deleting 1 object| ). + ELSE. + ii_log->add_info( |>>> Deleting { lines( lt_tadir ) } objects| ). + ENDIF. + ENDIF. + + IF is_checks-transport-required = abap_true. + zcl_abapgit_factory=>get_default_transport( )->set( is_checks-transport-transport ). + ENDIF. + + TRY. + zcl_abapgit_dependencies=>resolve( CHANGING ct_tadir = lt_tadir ). + + li_progress = zcl_abapgit_progress=>get_instance( lines( lt_tadir ) ). + + lt_items = map_tadir_to_items( lt_tadir ). + + check_objects_locked( lt_items ). + + CATCH zcx_abapgit_exception INTO lx_error. + zcl_abapgit_factory=>get_default_transport( )->reset( ). + RAISE EXCEPTION lx_error. + ENDTRY. + + lv_count = 1. + DO. + CLEAR lt_deleted. + LOOP AT lt_tadir ASSIGNING . + li_progress->show( iv_current = lv_count + iv_text = |Delete { -obj_name }| ). + + CLEAR ls_item. + ls_item-obj_type = -object. + ls_item-obj_name = -obj_name. + + TRY. + delete_object( + iv_package = -devclass + is_item = ls_item + iv_transport = is_checks-transport-transport ). + + INSERT INTO TABLE lt_deleted. + DELETE lt_tadir. + lv_count = lv_count + 1. + + " make sure to save object deletions + COMMIT WORK. + + IF ii_log IS BOUND. + ii_log->add_info( iv_msg = |Object { ls_item-obj_type } { ls_item-obj_name } deleted| + is_item = ls_item ). + ENDIF. + + CATCH zcx_abapgit_exception INTO lx_error. + IF ii_log IS BOUND. + ii_log->add_exception( ix_exc = lx_error + is_item = ls_item ). + ii_log->add_error( iv_msg = |Deletion of object { ls_item-obj_name } failed| + is_item = ls_item ). + ENDIF. + ENDTRY. + + ENDLOOP. + + " Exit if done or nothing else was deleted + IF lines( lt_tadir ) = 0 OR lines( lt_deleted ) = 0. + EXIT. + ENDIF. + ENDDO. + + zcl_abapgit_factory=>get_default_transport( )->reset( ). + + IF lx_error IS BOUND AND lines( lt_tadir ) > 0. + zcx_abapgit_exception=>raise( 'Error during uninstall. Check the log.' ). + ENDIF. + + li_progress->off( ). + + ENDMETHOD. + METHOD delete_object. + + DATA: li_obj TYPE REF TO zif_abapgit_object. + + " Nothing to do for unsupported objects + IF is_type_supported( is_item-obj_type ) = abap_false. + RETURN. + ENDIF. + + li_obj = create_object( is_item ). + li_obj->delete( iv_package = iv_package + iv_transport = iv_transport ). + + ENDMETHOD. + METHOD deserialize. + + DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, + lo_dot TYPE REF TO zcl_abapgit_dot_abapgit, + li_obj TYPE REF TO zif_abapgit_object, + lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt, + lv_package TYPE devclass, + lo_files TYPE REF TO zcl_abapgit_objects_files, + ls_metadata TYPE zif_abapgit_definitions=>ty_metadata, + lo_xml TYPE REF TO zif_abapgit_xml_input, + lt_results TYPE zif_abapgit_definitions=>ty_results_tt, + li_progress TYPE REF TO zif_abapgit_progress, + lv_path TYPE string, + lt_items TYPE zif_abapgit_definitions=>ty_items_tt, + lt_steps_id TYPE zif_abapgit_objects=>ty_deserialization_step_tt, + lt_steps TYPE zif_abapgit_objects=>ty_step_data_tt, + lx_exc TYPE REF TO zcx_abapgit_exception. + DATA lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic. + DATA lo_i18n_params TYPE REF TO zcl_abapgit_i18n_params. + DATA lo_timer TYPE REF TO zcl_abapgit_timer. + DATA lo_abap_language_vers TYPE REF TO zcl_abapgit_abap_language_vers. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_result, + TYPE LINE OF zif_abapgit_objects=>ty_deserialization_step_tt, + TYPE LINE OF zif_abapgit_objects=>ty_step_data_tt, + TYPE LINE OF zif_abapgit_objects=>ty_deserialization_tt. + + lt_steps = get_deserialize_steps( ). + + lv_package = ii_repo->get_package( ). + lo_dot = ii_repo->get_dot_abapgit( ). + + IF is_checks-transport-required = abap_true. + zcl_abapgit_factory=>get_default_transport( )->set( is_checks-transport-transport ). + ENDIF. + + zcl_abapgit_objects_activation=>clear( ). + + lt_remote = ii_repo->get_files_remote( iv_ignore_files = abap_true ). + + lt_results = zcl_abapgit_file_deserialize=>get_results( + ii_repo = ii_repo + ii_log = ii_log ). + + IF lt_results IS INITIAL. + RETURN. + ENDIF. + + zcl_abapgit_objects_check=>checks_adjust( + EXPORTING + ii_repo = ii_repo + is_checks = is_checks + CHANGING + ct_results = lt_results ). + + li_progress = zcl_abapgit_progress=>get_instance( lines( lt_results ) ). + + lt_items = map_results_to_items( lt_results ). + + lo_timer = zcl_abapgit_timer=>create( + iv_text = 'Deserialize:' + iv_count = lines( lt_items ) )->start( ). + + zcl_abapgit_factory=>get_cts_api( )->confirm_transport_messages( ). + + check_objects_locked( lt_items ). + + " Check the original system of all objects to prevent overwriting + check_original_system( + it_items = lt_items + ii_log = ii_log + io_dot = ii_repo->get_dot_abapgit( ) ). + + lo_i18n_params = zcl_abapgit_i18n_params=>new( is_params = + lo_dot->determine_i18n_parameters( ii_repo->get_local_settings( )-main_language_only ) ). + + IF lines( lt_items ) = 1. + ii_log->add_info( |>>> Deserializing 1 object| ). + ELSE. + ii_log->add_info( |>>> Deserializing { lines( lt_items ) } objects| ). + ENDIF. + + CREATE OBJECT lo_abap_language_vers + EXPORTING + io_dot_abapgit = lo_dot. + + lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). + LOOP AT lt_results ASSIGNING . + li_progress->show( iv_current = sy-tabix + iv_text = |Prepare Deserialize: { -obj_type } { -obj_name }| ). + + CLEAR ls_item. + CLEAR: lv_path, lv_package. + + ls_item-obj_type = -obj_type. + ls_item-obj_name = -obj_name. + + "error handling & logging added + TRY. + IF ls_item-obj_type <> 'NSPC'. + " If package does not exist yet, it will be created with this call + lv_package = lo_folder_logic->path_to_package( + iv_top = ii_repo->get_package( ) + io_dot = lo_dot + iv_path = -path ). + + zcl_abapgit_factory=>get_sap_package( lv_package )->check_object_type( ls_item-obj_type ). + ENDIF. + + IF ls_item-obj_type = 'DEVC'. + " Packages have the same filename across different folders. The path needs to be supplied + " to find the correct file. + lv_path = -path. + ENDIF. + + ls_item-devclass = lv_package. + ls_item-abap_language_version = lo_abap_language_vers->get_abap_language_vers_by_objt( + iv_object_type = ls_item-obj_type + iv_package = lv_package ). + + IF -packmove = abap_true. + " Move object to new package + change_package_assignments( is_item = ls_item + ii_log = ii_log ). + " No other changes required + CONTINUE. + ENDIF. + + " Create or update object + lo_files = zcl_abapgit_objects_files=>new( + is_item = ls_item + iv_path = lv_path ). + + lo_files->set_files( lt_remote ). + + IF lo_files->is_json_metadata( ) = abap_false. + "analyze XML in order to instantiate the proper serializer + lo_xml = lo_files->read_xml( ). + ls_metadata = lo_xml->get_metadata( ). + ELSE. + " there's no XML and metadata for JSON format + CLEAR: lo_xml, ls_metadata. + ENDIF. + + li_obj = create_object( + is_item = ls_item + is_metadata = ls_metadata + io_files = lo_files + io_i18n_params = lo_i18n_params ). + + "get required steps for deserialize the object + lt_steps_id = li_obj->get_deserialize_steps( ). + + LOOP AT lt_steps_id ASSIGNING . + READ TABLE lt_steps WITH KEY step_id = ASSIGNING . + ASSERT sy-subrc = 0. + IF = zif_abapgit_object=>gc_step_id-ddic AND + zcl_abapgit_objects_activation=>is_ddic_type( ls_item-obj_type ) = abap_false. + " DDIC only for DDIC objects + zcx_abapgit_exception=>raise( |Step { } is only for DDIC objects| ). + ENDIF. + APPEND INITIAL LINE TO -objects ASSIGNING . + -item = ls_item. + -files = lo_files. + -obj = li_obj. + -xml = lo_xml. + -package = lv_package. + ENDLOOP. + + CATCH zcx_abapgit_exception INTO lx_exc. + ii_log->add_exception( ix_exc = lx_exc + is_item = ls_item ). + ii_log->add_error( iv_msg = |Import of object { ls_item-obj_name } failed| + is_item = ls_item ). + "object should not be part of any deserialization step + CONTINUE. + ENDTRY. + + ENDLOOP. + + li_progress->off( ). + + "run deserialize for all steps and its objects + deserialize_steps( + EXPORTING + it_steps = lt_steps + ii_log = ii_log + io_i18n_params = lo_i18n_params + iv_transport = is_checks-transport-transport + CHANGING + ct_files = rt_accessed_files ). + + update_package_tree( ii_repo->get_package( ) ). + + " Set the original system for all updated objects to what's defined in repo settings + update_original_system( + it_items = lt_items + ii_log = ii_log + io_dot = lo_dot + iv_transport = is_checks-transport-transport ). + + zcl_abapgit_factory=>get_default_transport( )->reset( ). + + lo_timer->end( abap_true ). + + ENDMETHOD. + METHOD deserialize_checks. + + rs_checks = zcl_abapgit_objects_check=>deserialize_checks( ii_repo ). + + ENDMETHOD. + METHOD deserialize_lxe. + + DATA: + lo_base TYPE REF TO zcl_abapgit_objects_super, + lx_exc TYPE REF TO zcx_abapgit_exception. + + FIELD-SYMBOLS LIKE LINE OF is_step-objects. + + ii_log->add_success( |>> Step { is_step-order } - { is_step-descr }| ). + + LOOP AT is_step-objects ASSIGNING . + + TRY. + zcl_abapgit_factory=>get_lxe_texts( )->deserialize( + iv_object_type = -item-obj_type + iv_object_name = -item-obj_name + iv_package = -item-devclass + ii_xml = -xml + io_files = -files + io_i18n_params = io_i18n_params ). + + lo_base ?= -obj. + APPEND LINES OF lo_base->get_accessed_files( ) TO ct_files. + + ii_log->add_success( iv_msg = |Translations for { -item-obj_name } imported| + is_item = -item ). + + CATCH zcx_abapgit_exception INTO lx_exc. + ii_log->add_exception( ix_exc = lx_exc + is_item = -item ). + ii_log->add_error( iv_msg = |Import of translations for { -item-obj_name } failed| + is_item = -item ). + ENDTRY. + + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_step. + + DATA: li_progress TYPE REF TO zif_abapgit_progress, + li_exit TYPE REF TO zif_abapgit_exit, + lo_base TYPE REF TO zcl_abapgit_objects_super, + lx_exc TYPE REF TO zcx_abapgit_exception. + + FIELD-SYMBOLS: LIKE LINE OF is_step-objects. + zcl_abapgit_objects_activation=>clear( ). + + ii_log->add_success( |>> Step { is_step-order } - { is_step-descr }| ). + + li_progress = zcl_abapgit_progress=>get_instance( lines( is_step-objects ) ). + + LOOP AT is_step-objects ASSIGNING . + li_progress->show( + iv_current = sy-tabix + iv_text = |Step { is_step-order } - { is_step-descr }:| && + | { -item-obj_type } { -item-obj_name }| ). + + TRY. + -obj->deserialize( iv_package = -package + io_xml = -xml + iv_step = is_step-step_id + ii_log = ii_log + iv_transport = iv_transport ). + + lo_base ?= -obj. + APPEND LINES OF lo_base->get_accessed_files( ) TO ct_files. + + ii_log->add_success( iv_msg = |Object { -item-obj_name } imported| + is_item = -item ). + + CATCH zcx_abapgit_exception INTO lx_exc. + ii_log->add_exception( ix_exc = lx_exc + is_item = -item ). + ii_log->add_error( iv_msg = |Import of object { -item-obj_name } failed| + is_item = -item ). + ENDTRY. + + ENDLOOP. + + li_progress->show( iv_current = lines( is_step-objects ) + iv_text = |Step { is_step-order } - Activating Objects| ). + + CASE is_step-step_id. + WHEN zif_abapgit_object=>gc_step_id-ddic. + zcl_abapgit_objects_activation=>activate( + iv_ddic = abap_true + ii_log = ii_log ). + WHEN zif_abapgit_object=>gc_step_id-abap. + zcl_abapgit_objects_activation=>activate( + iv_ddic = abap_false + ii_log = ii_log ). + WHEN zif_abapgit_object=>gc_step_id-late. + " late can have both DDIC (like TABL with REF TO) and non-DDIC objects + zcl_abapgit_objects_activation=>activate( + iv_ddic = abap_true + ii_log = ii_log ). + zcl_abapgit_objects_activation=>activate( + iv_ddic = abap_false + ii_log = ii_log ). + ENDCASE. + + li_progress->off( ). + +* Call postprocessing + li_exit = zcl_abapgit_exit=>get_instance( ). + + li_exit->deserialize_postprocess( is_step = is_step + ii_log = ii_log ). + + ENDMETHOD. + METHOD deserialize_steps. + + FIELD-SYMBOLS LIKE LINE OF it_steps. + + LOOP AT it_steps ASSIGNING . + IF -step_id <> zif_abapgit_object=>gc_step_id-lxe. + deserialize_step( + EXPORTING + is_step = + ii_log = ii_log + iv_transport = iv_transport + CHANGING + ct_files = ct_files ). + ELSEIF io_i18n_params->is_lxe_applicable( ) = abap_true. + deserialize_lxe( + EXPORTING + is_step = + ii_log = ii_log + io_i18n_params = io_i18n_params + CHANGING + ct_files = ct_files ). + ENDIF. + ENDLOOP. + + SORT ct_files BY path ASCENDING filename ASCENDING. + DELETE ADJACENT DUPLICATES FROM ct_files. " Just in case + + ENDMETHOD. + METHOD exists. + + DATA: li_obj TYPE REF TO zif_abapgit_object. + + " Might be called for objects without tadir entry + IF is_item IS INITIAL. + RETURN. + ENDIF. + + " We want the object list of a repository to show unsupported object (without serializing them) + " This is why the follow check and the caught exception return true. + + " For unsupported objects, assume object exists + IF is_type_supported( is_item-obj_type ) = abap_false. + rv_bool = abap_true. + RETURN. + ENDIF. + + TRY. + li_obj = create_object( is_item ). + rv_bool = li_obj->exists( ). + CATCH zcx_abapgit_exception. + " Ignore errors and assume the object exists + rv_bool = abap_true. + ENDTRY. + + ENDMETHOD. + METHOD get_deserialize_steps. + FIELD-SYMBOLS: TYPE LINE OF zif_abapgit_objects=>ty_step_data_tt. + + APPEND INITIAL LINE TO rt_steps ASSIGNING . + -step_id = zif_abapgit_object=>gc_step_id-early. + -descr = 'Pre-process Objects'. + -syntax_check = abap_false. + -order = 1. + + APPEND INITIAL LINE TO rt_steps ASSIGNING . + -step_id = zif_abapgit_object=>gc_step_id-ddic. + -descr = 'Deserialize DDIC Objects'. + -syntax_check = abap_false. + -order = 2. + + APPEND INITIAL LINE TO rt_steps ASSIGNING . + -step_id = zif_abapgit_object=>gc_step_id-abap. + -descr = 'Deserialize non-DDIC Objects'. + -syntax_check = abap_false. + -order = 3. + + APPEND INITIAL LINE TO rt_steps ASSIGNING . + -step_id = zif_abapgit_object=>gc_step_id-late. + -descr = 'Post-process Objects'. + -syntax_check = abap_true. + -order = 4. + + APPEND INITIAL LINE TO rt_steps ASSIGNING . + -step_id = zif_abapgit_object=>gc_step_id-lxe. + -descr = 'Translations (LXE)'. + -syntax_check = abap_false. + -order = 5. + + SORT rt_steps BY order. " ensure correct processing order + ENDMETHOD. + METHOD get_extra_from_filename. + + IF iv_filename IS NOT INITIAL. + FIND REGEX '\..*\.([\-a-z0-9_%]*)\.' IN iv_filename SUBMATCHES rv_extra. + IF sy-subrc = 0. + rv_extra = cl_http_utility=>unescape_url( rv_extra ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD is_active. + + DATA: li_obj TYPE REF TO zif_abapgit_object. + + " For unsupported objects, assume active state + IF is_type_supported( is_item-obj_type ) = abap_false. + rv_active = abap_true. + RETURN. + ENDIF. + + TRY. + li_obj = create_object( is_item ). + rv_active = li_obj->is_active( ). + CATCH cx_sy_dyn_call_illegal_method + cx_sy_ref_is_initial + zcx_abapgit_exception. + " Ignore errors and assume active state + rv_active = abap_true. + ENDTRY. + + ENDMETHOD. + METHOD is_supported. + + TRY. + create_object( + is_item = is_item + iv_native_only = iv_native_only ). + rv_bool = abap_true. + CATCH zcx_abapgit_type_not_supported. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD is_type_supported. + + DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, + ls_supported_obj_type TYPE ty_supported_types. + + FIELD-SYMBOLS TYPE ty_supported_types. + + IF iv_obj_type IS INITIAL. + " empty object type should never exist + RETURN. + ENDIF. + + READ TABLE gt_supported_obj_types + ASSIGNING + WITH KEY obj_type = iv_obj_type. + + IF sy-subrc <> 0. + + ls_item-obj_type = iv_obj_type. + + ls_supported_obj_type-obj_type = iv_obj_type. + + IF is_type_supported_exit( iv_obj_type ) = abap_true. + ls_supported_obj_type-supported = is_supported( ls_item ). + ENDIF. + + INSERT ls_supported_obj_type INTO TABLE gt_supported_obj_types. + + rv_bool = ls_supported_obj_type-supported. + RETURN. + + ENDIF. + + rv_bool = -supported. + + ENDMETHOD. + METHOD is_type_supported_exit. + + DATA: + lt_types TYPE zif_abapgit_exit=>ty_object_types, + li_exit TYPE REF TO zif_abapgit_exit. + + INSERT iv_obj_type INTO TABLE lt_types. + + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->change_supported_object_types( CHANGING ct_types = lt_types ). + + READ TABLE lt_types TRANSPORTING NO FIELDS WITH TABLE KEY table_line = iv_obj_type. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD jump. + + DATA: li_obj TYPE REF TO zif_abapgit_object, + lv_exit TYPE abap_bool. + + " Nothing to do for unsupported objects + IF is_type_supported( is_item-obj_type ) = abap_false. + zcx_abapgit_exception=>raise( |Object type { is_item-obj_type } is not supported by this system| ). + ENDIF. + + " Nothing to do if object does not exist + li_obj = create_object( is_item ). + + IF li_obj->exists( ) = abap_false. + zcx_abapgit_exception=>raise( |Object { is_item-obj_type } { is_item-obj_name } doesn't exist| ). + ENDIF. + + " First priority object-specific handler + lv_exit = li_obj->jump( get_extra_from_filename( iv_filename ) ). + + IF lv_exit = abap_false. + " Open object in new window with generic jumper + lv_exit = zcl_abapgit_objects_factory=>get_gui_jumper( )->jump( + is_item = is_item + is_sub_item = is_sub_item + iv_line_number = iv_line_number + iv_new_window = iv_new_window ). + ENDIF. + + IF lv_exit = abap_false. + zcx_abapgit_exception=>raise( |Jump to { is_item-obj_type } { is_item-obj_name } not possible| ). + ENDIF. + + ENDMETHOD. + METHOD map_results_to_items. + + DATA: ls_item LIKE LINE OF rt_items. + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_result. + + LOOP AT it_results ASSIGNING . + + ls_item-devclass = -package. + ls_item-obj_type = -obj_type. + ls_item-obj_name = -obj_name. + ls_item-srcsystem = -srcsystem. + ls_item-origlang = -origlang. + INSERT ls_item INTO TABLE rt_items. + + ENDLOOP. + + ENDMETHOD. + METHOD map_tadir_to_items. + + DATA: ls_item LIKE LINE OF rt_items. + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_tadir. + + LOOP AT it_tadir ASSIGNING . + + ls_item-devclass = -devclass. + ls_item-obj_type = -object. + ls_item-obj_name = -obj_name. + ls_item-srcsystem = -srcsystem. + ls_item-origlang = -masterlang. + INSERT ls_item INTO TABLE rt_items. + + ENDLOOP. + + ENDMETHOD. + METHOD serialize. + + DATA: li_obj TYPE REF TO zif_abapgit_object, + lx_error TYPE REF TO zcx_abapgit_exception, + li_xml TYPE REF TO zif_abapgit_xml_output, + lo_files TYPE REF TO zcl_abapgit_objects_files. + + FIELD-SYMBOLS LIKE LINE OF rs_files_and_item-files. + + IF is_type_supported( is_item-obj_type ) = abap_false. + zcx_abapgit_exception=>raise( |Object type ignored, not supported: { + is_item-obj_type }-{ + is_item-obj_name }| ). + ENDIF. + + lo_files = zcl_abapgit_objects_files=>new( is_item ). + + li_obj = create_object( + is_item = is_item + io_files = lo_files + io_i18n_params = io_i18n_params ). + + CREATE OBJECT li_xml TYPE zcl_abapgit_xml_output. + + rs_files_and_item-item = is_item. + + TRY. + li_obj->serialize( li_xml ). + CATCH zcx_abapgit_exception INTO lx_error. + rs_files_and_item-item-inactive = boolc( li_obj->is_active( ) = abap_false ). + RAISE EXCEPTION lx_error. + ENDTRY. + + IF io_i18n_params->is_lxe_applicable( ) = abap_true. + zcl_abapgit_factory=>get_lxe_texts( )->serialize( + iv_object_type = is_item-obj_type + iv_object_name = is_item-obj_name + io_i18n_params = io_i18n_params + io_files = lo_files + ii_xml = li_xml ). + ENDIF. + + IF lo_files->is_json_metadata( ) = abap_false. + lo_files->add_xml( + ii_xml = li_xml + is_metadata = li_obj->get_metadata( ) ). + ENDIF. + + rs_files_and_item-files = lo_files->get_files( ). + + check_duplicates( rs_files_and_item-files ). + + rs_files_and_item-item-inactive = boolc( li_obj->is_active( ) = abap_false ). + + LOOP AT rs_files_and_item-files ASSIGNING . + -sha1 = zcl_abapgit_hash=>sha1_blob( -data ). + ENDLOOP. + + ENDMETHOD. + METHOD supported_list. + + DATA lt_objects TYPE STANDARD TABLE OF ko100. + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + DATA ls_supported_obj_type TYPE ty_supported_types. + DATA lt_types TYPE zif_abapgit_exit=>ty_object_types. + DATA lv_type LIKE LINE OF lt_types. + DATA li_exit TYPE REF TO zif_abapgit_exit. + + FIELD-SYMBOLS LIKE LINE OF lt_objects. + FIELD-SYMBOLS TYPE ty_supported_types. + + IF gv_supported_obj_types_loaded = abap_true. + LOOP AT gt_supported_obj_types ASSIGNING WHERE supported = abap_true. + INSERT -obj_type INTO TABLE rt_types. + ENDLOOP. + RETURN. + ENDIF. + + " delete content because it might be filled already by method IS_TYPE_SUPPORTED + CLEAR gt_supported_obj_types. + + CALL FUNCTION 'TR_OBJECT_TABLE' + TABLES + wt_object_text = lt_objects + EXCEPTIONS + OTHERS = 1 ##FM_SUBRC_OK. + + LOOP AT lt_objects ASSIGNING WHERE pgmid = 'R3TR'. + INSERT -object INTO TABLE lt_types. + ENDLOOP. + + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->change_supported_object_types( CHANGING ct_types = lt_types ). + + LOOP AT lt_types INTO lv_type. + ls_item-obj_type = lv_type. + + ls_supported_obj_type-obj_type = lv_type. + ls_supported_obj_type-supported = is_supported( ls_item ). + + INSERT ls_supported_obj_type INTO TABLE gt_supported_obj_types. + + IF ls_supported_obj_type-supported = abap_true. + INSERT ls_supported_obj_type-obj_type INTO TABLE rt_types. + ENDIF. + ENDLOOP. + + gv_supported_obj_types_loaded = abap_true. + + ENDMETHOD. + METHOD update_original_system. + + DATA: + lv_srcsystem TYPE tadir-srcsystem, + lv_transport_type_from TYPE trfunction, + lv_transport_type_to TYPE trfunction, + lv_errors TYPE abap_bool, + lx_error TYPE REF TO zcx_abapgit_exception. + + FIELD-SYMBOLS LIKE LINE OF it_items. + + lv_srcsystem = io_dot->get_original_system( ). + + IF lv_srcsystem IS INITIAL. + RETURN. + ELSEIF lv_srcsystem = 'SID'. + " Change objects to local system and switch repairs to development requests + lv_srcsystem = sy-sysid. + lv_transport_type_from = zif_abapgit_cts_api=>c_transport_type-wb_repair. + lv_transport_type_to = zif_abapgit_cts_api=>c_transport_type-wb_task. + ELSE. + " Change objects to external system and switch development requests to repairs + lv_transport_type_from = zif_abapgit_cts_api=>c_transport_type-wb_task. + lv_transport_type_to = zif_abapgit_cts_api=>c_transport_type-wb_repair. + ENDIF. + + ii_log->add_info( |>> Setting original system| ). + + LOOP AT it_items ASSIGNING . + " Local packages are not stored in TADIR + IF -obj_type = 'DEVC' AND -obj_name(1) = '$'. + CONTINUE. + ENDIF. + IF exists( ) = abap_true. + TRY. + zcl_abapgit_factory=>get_tadir( )->insert_single( + iv_object = -obj_type + iv_obj_name = -obj_name + iv_srcsystem = lv_srcsystem ). + CATCH zcx_abapgit_exception INTO lx_error. + ii_log->add_error( + iv_msg = lx_error->get_text( ) + is_item = ). + lv_errors = abap_true. + ENDTRY. + ENDIF. + ENDLOOP. + + IF lv_errors IS INITIAL. + " Since original system has changed, the type of transport request needs to be adjusted + zcl_abapgit_factory=>get_cts_api( )->change_transport_type( + iv_transport_request = iv_transport + iv_transport_type_from = lv_transport_type_from + iv_transport_type_to = lv_transport_type_to ). + ENDIF. + + ENDMETHOD. + METHOD update_package_tree. + + DATA: lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt, + lv_package LIKE LINE OF lt_packages, + lv_tree TYPE string. + lt_packages = zcl_abapgit_factory=>get_sap_package( iv_package )->list_subpackages( ). + APPEND iv_package TO lt_packages. + + LOOP AT lt_packages INTO lv_package. +* update package tree for SE80 + lv_tree = 'EU_' && lv_package. + CALL FUNCTION 'WB_TREE_ACTUALIZE' + EXPORTING + tree_name = lv_tree + without_crossreference = abap_true + with_tcode_index = abap_true. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_xslt IMPLEMENTATION. + METHOD get. + + DATA: lv_name TYPE cxsltdesc. + lv_name = ms_item-obj_name. + + cl_o2_api_xsltdesc=>load( + EXPORTING + p_xslt_desc = lv_name + IMPORTING + p_obj = ro_xslt + EXCEPTIONS + not_existing = 1 + permission_failure = 2 + OTHERS = 3 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from cl_o2_api_xsltdesc=>load' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_xslt TYPE REF TO cl_o2_api_xsltdesc, + ls_attributes TYPE o2xsltattr. + + lo_xslt = get( ). + lo_xslt->get_attributes( + RECEIVING + p_attributes = ls_attributes + EXCEPTIONS + object_invalid = 1 + xsltdesc_deleted = 2 + OTHERS = 3 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + rv_user = ls_attributes-changedby. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_xslt TYPE REF TO cl_o2_api_xsltdesc, + lv_name TYPE cxsltdesc. + lv_name = ms_item-obj_name. + + cl_o2_api_xsltdesc=>load( + EXPORTING + p_xslt_desc = lv_name + IMPORTING + p_obj = lo_xslt + EXCEPTIONS + error_occured = 1 + not_existing = 2 + permission_failure = 3 + version_not_found = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from cl_o2_api_xsltdesc=>load' ). + ENDIF. + + lo_xslt->set_changeable( abap_true ). + lo_xslt->delete( ). + lo_xslt->save( ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_source TYPE string, + lo_xslt TYPE REF TO cl_o2_api_xsltdesc, + ls_extra TYPE ty_extra, + lv_len TYPE i, + ls_attributes TYPE o2xsltattr. + + " Transformation might depend on other objects like a class + " We attempt to activate it in late step + IF iv_step = zif_abapgit_object=>gc_step_id-late. + IF zif_abapgit_object~is_active( ) = abap_false. + zcl_abapgit_objects_activation=>add_item( ms_item ). + ENDIF. + RETURN. + ENDIF. + + IF zif_abapgit_object~exists( ) = abap_true. + zif_abapgit_object~delete( iv_package = iv_package + iv_transport = iv_transport ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'ATTRIBUTES' + CHANGING cg_data = ls_attributes ). + + ls_attributes-devclass = iv_package. + + lv_source = mo_files->read_string( + iv_extra = 'source' + iv_ext = 'xml' ). + + zcl_abapgit_utils=>check_eol( lv_source ). + +* workaround: somewhere additional linefeeds are added + lv_len = strlen( lv_source ) - 2. + IF lv_source+lv_len(2) = cl_abap_char_utilities=>cr_lf. + lv_source = lv_source(lv_len). + ENDIF. + + cl_o2_api_xsltdesc=>create_new_from_string( + EXPORTING + p_source = lv_source + p_attr = ls_attributes + IMPORTING + p_obj = lo_xslt + EXCEPTIONS + action_cancelled = 1 + error_occured = 2 + not_authorized = 3 + object_already_existing = 4 + undefined_name = 5 + OTHERS = 6 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from XSLT new, { sy-subrc }| ). + ENDIF. + + lo_xslt->save( + EXCEPTIONS + action_cancelled = 1 + error_occured = 2 + object_invalid = 3 + object_not_changeable = 4 + permission_failure = 5 + OTHERS = 6 ). + IF sy-subrc <> 0. + lo_xslt->set_changeable( abap_false ). " unlock + zcx_abapgit_exception=>raise( |Error from XSLT save, { sy-subrc }| ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'EXTRA' + CHANGING cg_data = ls_extra ). + + TRY. + set_abap_language_version( CHANGING cv_abap_language_version = ls_extra-abap_language_version ). + + UPDATE ('O2XSLTDESC') SET abap_language_version = ls_extra-abap_language_version + WHERE relid = 'TR' AND xsltdesc = ms_item-obj_name. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + + lo_xslt->set_changeable( abap_false ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_name TYPE cxsltdesc. + + lv_name = ms_item-obj_name. + + rv_bool = cl_o2_api_xsltdesc=>exists( lv_name ). + rv_bool = boolc( rv_bool = '1' ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_xslt TYPE REF TO cl_o2_api_xsltdesc, + ls_extra TYPE ty_extra, + lv_source TYPE string, + ls_attributes TYPE o2xsltattr. + + lo_xslt = get( ). + + ls_attributes = lo_xslt->get_attributes( ). + + CLEAR: ls_attributes-author, + ls_attributes-createdon, + ls_attributes-changedby, + ls_attributes-changedon, + ls_attributes-devclass. + + io_xml->add( iv_name = 'ATTRIBUTES' + ig_data = ls_attributes ). + + lv_source = lo_xslt->get_source_string( ). + + mo_files->add_string( + iv_extra = 'source' + iv_ext = 'xml' + iv_string = lv_source ). + + TRY. + SELECT SINGLE abap_language_version FROM ('O2XSLTDESC') INTO CORRESPONDING FIELDS OF ls_extra + WHERE relid = 'TR' AND xsltdesc = ms_item-obj_name AND state = 'A'. + IF sy-subrc = 0. + clear_abap_language_version( CHANGING cv_abap_language_version = ls_extra-abap_language_version ). + ENDIF. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + + io_xml->add( iv_name = 'EXTRA' + ig_data = ls_extra ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_xinx IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + cl_wb_object_type=>get_key_components_from_id( + EXPORTING + p_key = |{ ms_item-obj_name }| + p_external_id = swbm_c_type_ddic_db_tabxinx + IMPORTING + p_key_component1 = mv_name + p_key_component2 = mv_id + EXCEPTIONS + too_many_key_components = 1 + objecttype_not_existing = 2 + OTHERS = 3 ). + + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD xinx_delete_docu. + + DATA: lv_docuid TYPE dokhl-id, + lv_doctype TYPE dokhl-typ, + lv_docname TYPE dokhl-object. + + lv_docname = iv_objname. + lv_docname+30 = iv_id. + CALL FUNCTION 'INTERN_DD_DOCU_ID_MATCH' + EXPORTING + p_trobjtype = c_objtype_extension_index + IMPORTING + p_docu_id = lv_docuid + p_doctype = lv_doctype + EXCEPTIONS + illegal_type = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + RETURN. + ENDIF. + + CALL FUNCTION 'DOKU_DELETE_ALL' + EXPORTING + doku_id = lv_docuid + doku_object = lv_docname + doku_typ = lv_doctype + suppress_authority = 'X' + suppress_enqueue = 'X' + suppress_transport = 'X' + EXCEPTIONS + no_docu_found = 1 + OTHERS = 2 ##FM_SUBRC_OK. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + SELECT SINGLE as4user FROM dd12l INTO rv_user + WHERE sqltab = mv_name AND indexname = mv_id. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + " Reimplement FM RS_DD_INDX_DELETE as it calls the UI + + DATA: ls_enqueue TYPE ddenqs, + lv_protname TYPE tstrf01-file, + lv_del_concname LIKE ls_enqueue-objname, + lv_concname TYPE rsdxx-objname, + ls_transp_key TYPE trkey, + ls_e071 TYPE e071, + lv_clm_corrnum TYPE e070-trkorr. + + CONCATENATE mv_name '-' mv_id INTO lv_concname. + ls_enqueue-objtype = c_objtype_extension_index. + + CALL FUNCTION 'INT_INDX_DEL_LOCK' + EXPORTING + i_trobjtype = ls_enqueue-objtype + i_tabname = mv_name + i_indexname = mv_id + EXCEPTIONS + not_executed = 1 + error_occured = 2 + permission_failure = 3 + OTHERS = 4. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ls_enqueue-objname = mv_name. + ls_enqueue-secname = mv_id. + CALL FUNCTION 'RS_CORR_INSERT' + EXPORTING + object = ls_enqueue + object_class = 'DICT' + mode = 'DELETE' + IMPORTING + transport_key = ls_transp_key + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc <> 0. + " & was not deleted (correction entry not possible or canceled) + MESSAGE s015(e2) WITH lv_concname INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'DD_LOGNPROT_NAME_GET' + EXPORTING + task = 'DEL' + obj_type = ls_enqueue-objtype + obj_name = ls_enqueue-objname + ind_name = ls_enqueue-secname + IMPORTING + protname = lv_protname + EXCEPTIONS + input_error = 0. + + PERFORM logdelete IN PROGRAM rddu0001 USING lv_protname. + + lv_del_concname = ls_enqueue-objname. + lv_del_concname+16 = ls_enqueue-secname. + + CALL FUNCTION 'DD_OBJ_DEL' + EXPORTING + object_name = lv_del_concname + object_type = ls_enqueue-objtype + del_state = 'M' + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc <> 0. + RETURN. + ENDIF. + + CALL FUNCTION 'DD_DD_TO_E071' + EXPORTING + type = ls_enqueue-objtype + name = ls_enqueue-objname + id = ls_enqueue-secname + IMPORTING + obj_name = ls_e071-obj_name + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + " Internal error & in & (contact person in charge) + MESSAGE i008(e2) WITH 'DD_DD_TO_E071' 'RS_DD_INDX_DELETE' INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ls_e071-object = ls_enqueue-objtype. + + CALL FUNCTION 'RS_DELETE_FROM_WORKING_AREA' + EXPORTING + object = ls_e071-object + obj_name = ls_e071-obj_name + immediate = 'X' + actualize_working_area = 'X'. + + xinx_delete_docu( + iv_objname = mv_name + iv_id = mv_id ). + + CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' + EXPORTING + object = ls_e071-obj_name + operation = 'DELETE' + type = c_objtype_extension_index. + + IF mv_id(1) CA 'YZ'. + CALL FUNCTION 'CLM_INDX_MODIFICATION_DELETE' + EXPORTING + idxobj_name = ls_enqueue-objname + idx_type = ls_enqueue-objtype + idx_name = mv_id + transport_key = ls_transp_key + corrnum = lv_clm_corrnum. + ENDIF. + + CALL FUNCTION 'RS_DD_DEQUEUE' + EXPORTING + objtype = ls_enqueue-objtype + objname = ls_enqueue-objname + secname = ls_enqueue-secname. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_extension_index TYPE ty_extension_index, + lv_rc TYPE sy-subrc. + + io_xml->read( + EXPORTING + iv_name = 'XINX' + CHANGING + cg_data = ls_extension_index ). + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + CALL FUNCTION 'DDIF_INDX_PUT' + EXPORTING + name = mv_name + id = mv_id + dd12v_wa = ls_extension_index-dd12v + TABLES + dd17v_tab = ls_extension_index-t_dd17v + EXCEPTIONS + indx_not_found = 1 + name_inconsistent = 2 + indx_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from DDIF_INDX_PUT { sy-subrc }| ). + ENDIF. + + CALL FUNCTION 'DDIF_INDX_ACTIVATE' + EXPORTING + name = mv_name + id = mv_id + IMPORTING + rc = lv_rc + EXCEPTIONS + not_found = 1 + put_failure = 2 + OTHERS = 3. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from DDIF_INDX_ACTIVATE { sy-subrc }| ). + ENDIF. + + IF lv_rc <> 0. + zcx_abapgit_exception=>raise( |Cannot activate extension index { mv_id } of table { mv_name }| ). + ENDIF. + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_xinx ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_dd12v TYPE dd12v. + + CALL FUNCTION 'DDIF_INDX_GET' + EXPORTING + name = mv_name + id = mv_id + IMPORTING + dd12v_wa = ls_dd12v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error reading index' ). + ENDIF. + + rv_bool = boolc( ls_dd12v IS NOT INITIAL ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_extension_index TYPE ty_extension_index. + + CALL FUNCTION 'DDIF_INDX_GET' + EXPORTING + name = mv_name + id = mv_id + langu = mv_language + IMPORTING + dd12v_wa = ls_extension_index-dd12v + TABLES + dd17v_tab = ls_extension_index-t_dd17v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from DDIF_INDX_GET { sy-subrc }| ). + ENDIF. + + CLEAR: ls_extension_index-dd12v-as4user, + ls_extension_index-dd12v-as4date, + ls_extension_index-dd12v-as4time. + + io_xml->add( iv_name = 'XINX' + ig_data = ls_extension_index ). + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_xinx ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_WEBI IMPLEMENTATION. + METHOD handle_endpoint. + + DATA: ls_endpoint LIKE LINE OF is_webi-pvependpoint, + li_endpoint TYPE REF TO if_ws_md_vif_endpoint_ref. + + FIELD-SYMBOLS: LIKE LINE OF is_webi-pvepfunction. + READ TABLE is_webi-pvependpoint INDEX 1 INTO ls_endpoint. + ASSERT sy-subrc = 0. + + IF mi_vi->has_endpoint_reference( sews_c_vif_version-all ) = abap_true. + RETURN. + ENDIF. + + li_endpoint = mi_vi->create_endpoint_reference( + endpoint_type = ls_endpoint-endpointtype + service_def_startpoint = ls_endpoint-def_start_pt + auto_generated = ls_endpoint-auto_generated + i_is_srvv = ls_endpoint-is_srvv ). + + IF ls_endpoint-endpointtype = 'BAPI'. +* it looks like some special handling is needed when calling +* set_data, and looking at the cluster data LS_ENDPOINT-CLUSTD + zcx_abapgit_exception=>raise( 'todo, WEBI BAPI' ). + ENDIF. + +* field ls_endpoint-endpointname does not exist in 702 + READ TABLE is_webi-pvepfunction INDEX 1 ASSIGNING . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |WEBI { ms_item-obj_name }: couldn't detect endpoint name| ). + ENDIF. + + li_endpoint->set_data( + data_version = '1' + data = -function ). + + ENDMETHOD. + METHOD handle_function. + + DATA: li_parameter TYPE REF TO if_ws_md_vif_param, + li_soap TYPE REF TO if_ws_md_soap_ext_func, + li_fault TYPE REF TO if_ws_md_vif_fault, + li_function TYPE REF TO if_ws_md_vif_func. + + FIELD-SYMBOLS: LIKE LINE OF is_webi-pvepfunction, + LIKE LINE OF is_webi-pvepfuncsoapext, + LIKE LINE OF is_webi-pvepfault, + LIKE LINE OF is_webi-pvepparameter. + LOOP AT is_webi-pvepfunction ASSIGNING . + + IF mi_vi->has_function( funcname = -function + version = sews_c_vif_version-active ) = abap_true. + CONTINUE. + ENDIF. + + IF mi_vi->has_function( funcname = -function + version = sews_c_vif_version-inactive ) = abap_true. + + li_function = mi_vi->get_function( funcname = -function + version = sews_c_vif_version-inactive ). + + ELSE. + + li_function = mi_vi->create_function( funcname = -function + mapped_name = -mappedname ). + + ENDIF. + + li_function->set_is_exposed( -is_exposed ). + + LOOP AT is_webi-pvepparameter ASSIGNING + WHERE function = -function. + + li_parameter = handle_single_parameter( iv_name = -vepparam + ii_function = li_function + iv_parameter_type = -vepparamtype ). + + li_parameter->set_name_mapped_to( -mappedname ). + li_parameter->set_is_exposed( -is_exposed ). + li_parameter->set_is_optional( -is_optional ). + li_parameter->set_default_value( -default_value ). + li_parameter->set_initial( -is_initial ). + li_parameter->set_type( -typename ). + ENDLOOP. + + LOOP AT is_webi-pvepfuncsoapext ASSIGNING + WHERE function = -function. + IF li_function->has_soap_extension_function( 'I' ) = abap_true. + li_function->delete_soap_extension_function( ). + ENDIF. + li_soap = li_function->create_soap_extension_function( ). + li_soap->set_soap_request_name( -requestname ). + li_soap->set_soap_response_name( -responsename ). + li_soap->set_namespace( -namespace ). + ENDLOOP. + + LOOP AT is_webi-pvepfault ASSIGNING + WHERE function = -function. + li_fault = li_function->create_fault( -fault ). + li_fault->set_name_mapped_to( -mappedname ). + li_fault->set_detail( -detail ). + ENDLOOP. + + ENDLOOP. + + ENDMETHOD. + METHOD handle_single_parameter. + CONSTANTS: + BEGIN OF lc_parameter_type, + import TYPE vepparamtype VALUE 'I', + export TYPE vepparamtype VALUE 'O', + END OF lc_parameter_type. + + CASE iv_parameter_type. + WHEN lc_parameter_type-import. + ri_parameter = ii_function->get_incoming_parameter( parameter_name = iv_name + version = 'I' ). + IF ri_parameter IS BOUND. + ii_function->delete_incoming_parameter( ri_parameter ). + ENDIF. + ri_parameter = ii_function->create_incoming_parameter( iv_name ). + + WHEN lc_parameter_type-export. + + ri_parameter = ii_function->get_outgoing_parameter( parameter_name = iv_name + version = 'I' ). + IF ri_parameter IS BOUND. + ii_function->delete_outgoing_parameter( parameter = ri_parameter ). + ENDIF. + + ri_parameter = ii_function->create_outgoing_parameter( iv_name ). + + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + + ENDMETHOD. + METHOD handle_soap. + + DATA: li_soap TYPE REF TO if_ws_md_soap_ext_virtinfc, + ls_soap LIKE LINE OF is_webi-pvepvisoapext. + READ TABLE is_webi-pvepvisoapext INDEX 1 INTO ls_soap. + ASSERT sy-subrc = 0. + + IF mi_vi->has_soap_extension_virtinfc( sews_c_vif_version-active ) = abap_true. + RETURN. + ENDIF. + + IF mi_vi->has_soap_extension_virtinfc( sews_c_vif_version-inactive ) = abap_true. + li_soap = mi_vi->get_soap_extension_virtinfc( sews_c_vif_version-inactive ). + ELSE. + li_soap = mi_vi->create_soap_extension_virtinfc( ls_soap-soap_appl_uri ). + ENDIF. + + li_soap->set_namespace( ls_soap-namespace ). + + ENDMETHOD. + METHOD handle_types. + + DATA: lv_index TYPE i, + li_soap TYPE REF TO if_ws_md_soap_extension_type, + li_struc TYPE REF TO if_ws_md_vif_struc_type, + li_field TYPE REF TO if_ws_md_vif_field, + li_table TYPE REF TO if_ws_md_vif_table_type, + li_elem TYPE REF TO if_ws_md_vif_elem_type. + + FIELD-SYMBOLS: LIKE LINE OF is_webi-pvepelemtype, + LIKE LINE OF is_webi-pveptabletype, + LIKE LINE OF is_webi-pveptypesoapext, + LIKE LINE OF is_webi-pvepstrutype. + LOOP AT is_webi-pvepelemtype ASSIGNING . + li_elem = mi_vi->create_type_as_elementary( -typename ). + li_elem->set_built_in_type( -build_in_type ). + li_elem->set_decimals( -decimals ). + li_elem->set_kind( -kind ). + li_elem->set_length( -length ). + li_elem->set_signed( -signed ). + li_elem->set_abaptype( -abaptype ). + + IF li_elem->if_ws_md_vif_type~has_soap_extension_type( sews_c_vif_version-all ) = abap_false. + READ TABLE is_webi-pveptypesoapext ASSIGNING + WITH KEY typename = -typename. + IF sy-subrc = 0. + li_soap = li_elem->if_ws_md_vif_type~create_soap_extension_type( ). + li_soap->set_namespace( -namespace ). + ENDIF. + ENDIF. + ENDLOOP. + + LOOP AT is_webi-pvepstrutype ASSIGNING . + lv_index = sy-tabix. + + li_struc = mi_vi->create_type_as_structure( -typename ). + + IF li_struc->has_field( field_pos = -fieldpos + version = sews_c_vif_version-active ) = abap_true. + CONTINUE. + ENDIF. + + li_field = li_struc->create_field( + field_name = -fieldname + fieldpos = -fieldpos ). + li_field->set_type( mi_vi->get_type( typename = -typeref + version = sews_c_vif_version-inactive ) ). + + IF lv_index = 1 + AND li_struc->if_ws_md_vif_type~has_soap_extension_type( + sews_c_vif_version-all ) = abap_false. + READ TABLE is_webi-pveptypesoapext ASSIGNING + WITH KEY typename = -typename. + IF sy-subrc = 0. + li_soap = li_struc->if_ws_md_vif_type~create_soap_extension_type( ). + li_soap->set_namespace( -namespace ). + ENDIF. + ENDIF. + ENDLOOP. + + LOOP AT is_webi-pveptabletype ASSIGNING . + li_table = mi_vi->create_type_as_table( -typename ). + li_table->set_line_type( mi_vi->get_type( typename = -typeref + version = sews_c_vif_version-inactive ) ). + + IF li_table->if_ws_md_vif_type~has_soap_extension_type( sews_c_vif_version-all ) = abap_false. + READ TABLE is_webi-pveptypesoapext ASSIGNING + WITH KEY typename = -typename. + IF sy-subrc = 0. + li_soap = li_table->if_ws_md_vif_type~create_soap_extension_type( ). + li_soap->set_namespace( -namespace ). + ENDIF. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD sort. + SORT cs_webi-pvepheader BY vepname version. + SORT cs_webi-pvepfunction BY vepname version function. + SORT cs_webi-pvepfault BY vepname version function fault. + SORT cs_webi-pvepparameter BY vepname version function vepparam vepparamtype. + SORT cs_webi-pveptype BY vepname version typename. + SORT cs_webi-pvepelemtype BY vepname version typename. + SORT cs_webi-pveptabletype BY vepname version typename. + SORT cs_webi-pvepstrutype BY vepname version typename fieldpos. + SORT cs_webi-pveptypesoapext BY vepname version typename. + SORT cs_webi-pvepeletypsoap BY vepname version typename assign_type assign_data1 assign_data2. + SORT cs_webi-pveptabtypsoap BY vepname version typename. + SORT cs_webi-pvepfuncsoapext BY vepname version function. + SORT cs_webi-pvepfieldref BY vepname version function vepparam vepparamtype strucid fieldname. + SORT cs_webi-pvependpoint BY relid vepname version sortfield. + SORT cs_webi-pvepvisoapext BY vepname version. + SORT cs_webi-pvepparasoapext BY vepname version function vepparam vepparamtype. + SORT cs_webi-pwsheader BY wsname version. + SORT cs_webi-pwssoapprop BY wsname version feature soapapp funcref propnum. + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE changedby FROM vepheader INTO rv_user + WHERE vepname = ms_item-obj_name AND version = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_name TYPE vepname, + lo_vif TYPE REF TO cl_ws_md_vif_root. + lv_name = ms_item-obj_name. + + CREATE OBJECT lo_vif. + TRY. + lo_vif->if_ws_md_vif_root~delete_virtual_interface( lv_name ). + CATCH cx_ws_md_exception. + zcx_abapgit_exception=>raise( 'error deleting WEBI' ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_webi TYPE ty_webi, + lv_name TYPE vepname, + ls_header LIKE LINE OF ls_webi-pvepheader, + lx_root TYPE REF TO cx_root, + lv_exists TYPE abap_bool, + li_root TYPE REF TO if_ws_md_vif_root, + ls_endpoint LIKE LINE OF ls_webi-pvependpoint. + + io_xml->read( EXPORTING iv_name = 'WEBI' + CHANGING cg_data = ls_webi ). + + lv_name = ms_item-obj_name. + + READ TABLE ls_webi-pvependpoint INDEX 1 INTO ls_endpoint. + ASSERT sy-subrc = 0. + IF ls_endpoint-auto_generated = abap_true. + " handled by SPRX. + RETURN. + ENDIF. + + READ TABLE ls_webi-pvepheader INDEX 1 INTO ls_header. + ASSERT sy-subrc = 0. + + lv_exists = cl_ws_md_vif_root=>check_existence_by_vif_name( + name = lv_name + i_version = sews_c_vif_version-all ). + + li_root = cl_ws_md_factory=>get_vif_root( ). + TRY. + IF lv_exists = abap_false. + mi_vi = li_root->create_virtual_interface( + name = lv_name + nameext = ls_header-vepnameext ). + ELSE. + mi_vi = li_root->get_virtual_interface( lv_name ). + mi_vi->if_ws_md_lockable_object~lock( ). + ENDIF. + + mi_vi->set_short_text( ls_webi-veptext ). + + handle_endpoint( ls_webi ). + handle_types( ls_webi ). + handle_function( ls_webi ). + handle_soap( ls_webi ). + + tadir_insert( iv_package ). + + mi_vi->if_ws_md_lockable_object~save( ). + mi_vi->if_ws_md_lockable_object~unlock( ). + CATCH cx_ws_md_exception INTO lx_root. + TRY. + mi_vi->if_ws_md_lockable_object~unlock( ). + CATCH cx_ws_md_exception ##NO_HANDLER. + ENDTRY. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + zcl_abapgit_sotr_handler=>create_sotr( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_name TYPE vepname. + DATA lv_generated TYPE abap_bool. + + lv_name = ms_item-obj_name. + + " Check if service is generated by proxy + SELECT SINGLE auto_generated FROM vependpoint INTO lv_generated + WHERE vepname = lv_name AND version = sews_c_vif_version-active. + IF sy-subrc = 0 AND lv_generated = abap_true. + RETURN. + ENDIF. + + rv_bool = cl_ws_md_vif_root=>check_existence_by_vif_name( + name = lv_name + i_version = sews_c_vif_version-all ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_webi TYPE ty_webi, + lx_error TYPE REF TO cx_ws_md_exception, + lt_modilog TYPE STANDARD TABLE OF smodilog WITH DEFAULT KEY, + li_vi TYPE REF TO if_ws_md_vif, + lv_name TYPE vepname. + + FIELD-SYMBOLS: LIKE LINE OF ls_webi-pvepheader, + LIKE LINE OF ls_webi-pvependpoint, + TYPE wsheader. + + CALL FUNCTION 'WEBI_GET_OBJECT' + EXPORTING + webiname = ms_item-obj_name + TABLES + psmodilog = lt_modilog + pvepheader = ls_webi-pvepheader + pvepfunction = ls_webi-pvepfunction + pvepfault = ls_webi-pvepfault + pvepparameter = ls_webi-pvepparameter + pveptype = ls_webi-pveptype + pvepelemtype = ls_webi-pvepelemtype + pveptabletype = ls_webi-pveptabletype + pvepstrutype = ls_webi-pvepstrutype + pveptypesoapext = ls_webi-pveptypesoapext + pvepeletypsoap = ls_webi-pvepeletypsoap + pveptabtypsoap = ls_webi-pveptabtypsoap + pvepfuncsoapext = ls_webi-pvepfuncsoapext + pvepfieldref = ls_webi-pvepfieldref + pvependpoint = ls_webi-pvependpoint + pvepvisoapext = ls_webi-pvepvisoapext + pvepparasoapext = ls_webi-pvepparasoapext + pwsheader = ls_webi-pwsheader + pwssoapprop = ls_webi-pwssoapprop + EXCEPTIONS + version_not_found = 1 + webi_not_exist = 2 + OTHERS = 3. + IF sy-subrc = 1. + " no active version + RETURN. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + sort( CHANGING cs_webi = ls_webi ). + + lv_name = ms_item-obj_name. + TRY. + li_vi = cl_ws_md_factory=>get_vif_root( )->get_virtual_interface( lv_name ). + ls_webi-veptext = li_vi->get_short_text( sews_c_vif_version-active ). + CATCH cx_ws_md_exception INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + LOOP AT ls_webi-pvepheader ASSIGNING . + CLEAR -author. + CLEAR -createdon. + CLEAR -changedby. + CLEAR -changedon. + CLEAR -ctime. + CLEAR -text_id. + CLEAR -utime. + CLEAR -wsint_version. + ENDLOOP. + + LOOP AT ls_webi-pvependpoint ASSIGNING . + CLEAR -clustd. + ENDLOOP. + + LOOP AT ls_webi-pwsheader ASSIGNING . + + CLEAR: + -author, + -createdon, + -changedby, + -changedon, + -ctime, + -utime. + + ENDLOOP. + + io_xml->add( iv_name = 'WEBI' + ig_data = ls_webi ). + + zcl_abapgit_sotr_handler=>read_sotr( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + io_xml = io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_wdyn IMPLEMENTATION. + METHOD add_fm_exception. + + DATA: ls_exception LIKE LINE OF ct_exception. + + ls_exception-name = iv_name. + ls_exception-value = iv_value. + + INSERT ls_exception INTO TABLE ct_exception. + + ENDMETHOD. + METHOD add_fm_param_exporting. + + DATA: ls_param LIKE LINE OF ct_param. + + ls_param-kind = abap_func_exporting. + ls_param-name = iv_name. + GET REFERENCE OF ig_value INTO ls_param-value. + + INSERT ls_param INTO TABLE ct_param. + + ENDMETHOD. + METHOD add_fm_param_tables. + + DATA: ls_param LIKE LINE OF ct_param. + + ls_param-kind = abap_func_tables. + ls_param-name = iv_name. + GET REFERENCE OF ct_value INTO ls_param-value. + + INSERT ls_param INTO TABLE ct_param. + + ENDMETHOD. + METHOD add_with_inactive_parts. + + DATA: + lv_obj_name TYPE trobj_name, + lv_object TYPE trobjtype, + lt_objects TYPE dwinactiv_tab. + + FIELD-SYMBOLS: LIKE LINE OF lt_objects. + + lv_obj_name = ms_item-obj_name. + lv_object = ms_item-obj_type. + + CALL FUNCTION 'RS_INACTIVE_OBJECTS_IN_OBJECT' + EXPORTING + obj_name = lv_obj_name + object = lv_object + TABLES + inactive_objects = lt_objects + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + LOOP AT lt_objects ASSIGNING . + zcl_abapgit_objects_activation=>add( iv_type = -object + iv_name = -obj_name ). + ENDLOOP. + + ENDMETHOD. + METHOD delta_controller. + + DATA: li_controller TYPE REF TO if_wdy_md_controller, + lx_error TYPE REF TO cx_wdy_md_exception, + lv_found TYPE abap_bool, + ls_key TYPE wdy_md_controller_key, + ls_obj_new TYPE svrs2_versionable_object, + ls_obj_old TYPE svrs2_versionable_object. + + FIELD-SYMBOLS: LIKE LINE OF mt_components, + LIKE LINE OF mt_sources, + TYPE ANY TABLE, + TYPE ANY TABLE, + TYPE ANY TABLE, + TYPE ANY TABLE. + ls_key-component_name = is_controller-definition-component_name. + ls_key-controller_name = is_controller-definition-controller_name. + + lv_found = cl_wdy_md_controller=>check_existency( + component_name = ls_key-component_name + controller_name = ls_key-controller_name ). + IF lv_found = abap_false. + TRY. + li_controller ?= cl_wdy_md_controller=>create_complete( + component_name = ls_key-component_name + controller_name = ls_key-controller_name + controller_type = is_controller-definition-controller_type ). + li_controller->save_to_database( ). + li_controller->unlock( ). + CATCH cx_wdy_md_exception INTO lx_error. + zcx_abapgit_exception=>raise( |Error creating dummy controller: { lx_error->get_text( ) }| ). + ENDTRY. + ENDIF. + + ls_obj_new-objtype = wdyn_limu_component_controller. + ls_obj_new-objname = ls_key. + + ls_obj_old-objtype = wdyn_limu_component_controller. + ls_obj_old-objname = ls_key. + + APPEND is_controller-definition TO ls_obj_old-wdyc-defin. + + LOOP AT mt_components ASSIGNING + WHERE component_name = ls_key-component_name + AND controller_name = ls_key-controller_name. + APPEND TO ls_obj_old-wdyc-ccomp. + ENDLOOP. + LOOP AT mt_sources ASSIGNING + WHERE component_name = ls_key-component_name + AND controller_name = ls_key-controller_name. + APPEND TO ls_obj_old-wdyc-ccoms. + ENDLOOP. + + ls_obj_old-wdyc-descr = is_controller-descriptions. + ls_obj_old-wdyc-cusag = is_controller-controller_usages. + ls_obj_old-wdyc-ccomt = is_controller-controller_component_texts. + ls_obj_old-wdyc-cpara = is_controller-controller_parameters. + ls_obj_old-wdyc-cpart = is_controller-controller_parameter_texts. + ls_obj_old-wdyc-cnode = is_controller-context_nodes. + ls_obj_old-wdyc-cattr = is_controller-context_attributes. + ls_obj_old-wdyc-cmapp = is_controller-context_mappings. +* Version 702 doesn't have these two attributes so we +* use them dynamically for downward compatibility + ASSIGN COMPONENT 'CONTROLLER_EXCEPTIONS' OF STRUCTURE is_controller + TO . + IF sy-subrc = 0. + ASSIGN COMPONENT 'EXCP' OF STRUCTURE ls_obj_old-wdyc TO . + IF sy-subrc = 0. + = . + ENDIF. + ENDIF. + ASSIGN COMPONENT 'CONTROLLER_EXCEPTIONS_TEXTS' OF STRUCTURE is_controller + TO . + IF sy-subrc = 0. + ASSIGN COMPONENT 'EXCPT' OF STRUCTURE ls_obj_old-wdyc TO . + IF sy-subrc = 0. + = . + ENDIF. + ENDIF. + ls_obj_old-wdyc-fgrps = is_controller-fieldgroups. + + CALL FUNCTION 'SVRS_MAKE_OBJECT_DELTA' + EXPORTING + obj_old = ls_obj_new + obj_new = ls_obj_old + CHANGING + delta = rs_delta + EXCEPTIONS + inconsistent_objects = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from SVRS_MAKE_OBJECT_DELTA' ). + ENDIF. + + ENDMETHOD. + METHOD delta_definition. + + DATA: ls_key TYPE wdy_md_component_key, + lv_found TYPE abap_bool, + ls_obj_new TYPE svrs2_versionable_object, + li_component TYPE REF TO if_wdy_md_component, + lx_error TYPE REF TO cx_wdy_md_exception, + ls_obj_old TYPE svrs2_versionable_object. + ls_key-component_name = is_definition-definition-component_name. + + lv_found = cl_wdy_md_component=>check_existency( ls_key-component_name ). + IF lv_found = abap_false. + TRY. + cl_wdy_md_component=>create_complete( + EXPORTING + name = ls_key-component_name + IMPORTING + component = li_component + CHANGING + devclass = iv_package ). + li_component->save_to_database( ). + li_component->unlock( ). + CATCH cx_wdy_md_exception INTO lx_error. + zcx_abapgit_exception=>raise( |Error creating dummy component: { lx_error->get_text( ) }| ). + ENDTRY. + ENDIF. + + ls_obj_new-objtype = wdyn_limu_component_definition. + ls_obj_new-objname = ls_key-component_name. + + ls_obj_old-objtype = wdyn_limu_component_definition. + ls_obj_old-objname = ls_key-component_name. + + APPEND is_definition-definition TO ls_obj_old-wdyd-defin. + ls_obj_old-wdyd-descr = is_definition-descriptions. + ls_obj_old-wdyd-cusag = is_definition-component_usages. + ls_obj_old-wdyd-intrf = is_definition-interface_implementings. + ls_obj_old-wdyd-libra = is_definition-library_usages. + ls_obj_old-wdyd-ctuse = is_definition-ext_ctlr_usages. + ls_obj_old-wdyd-ctmap = is_definition-ext_ctx_mappings. + + CALL FUNCTION 'SVRS_MAKE_OBJECT_DELTA' + EXPORTING + obj_old = ls_obj_new + obj_new = ls_obj_old + CHANGING + delta = rs_delta + EXCEPTIONS + inconsistent_objects = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from SVRS_MAKE_OBJECT_DELTA' ). + ENDIF. + + ENDMETHOD. + METHOD delta_view. + + DATA: ls_key TYPE wdy_md_view_key, + ls_obj_new TYPE svrs2_versionable_object, + ls_obj_old TYPE svrs2_versionable_object, + lv_found TYPE abap_bool, + lx_error TYPE REF TO cx_wdy_md_exception, + li_view TYPE REF TO if_wdy_md_abstract_view. + + FIELD-SYMBOLS: LIKE LINE OF ls_obj_old-wdyv-defin. + ls_key-component_name = is_view-definition-component_name. + ls_key-view_name = is_view-definition-view_name. + + lv_found = cl_wdy_md_abstract_view=>check_existency( + component_name = ls_key-component_name + name = ls_key-view_name ). + IF lv_found = abap_false. + TRY. + li_view = cl_wdy_md_abstract_view=>create( + component_name = is_view-definition-component_name + view_name = is_view-definition-view_name + type = is_view-definition-type ). + li_view->save_to_database( ). + li_view->unlock( ). + CATCH cx_wdy_md_exception INTO lx_error. + zcx_abapgit_exception=>raise( |Error creating dummy view: { lx_error->get_text( ) }| ). + ENDTRY. + ENDIF. + + ls_obj_new-objtype = wdyn_limu_component_view. + ls_obj_new-objname = ls_key. + + ls_obj_old-objtype = wdyn_limu_component_view. + ls_obj_old-objname = ls_key. + + APPEND INITIAL LINE TO ls_obj_old-wdyv-defin ASSIGNING . + MOVE-CORRESPONDING is_view-definition TO . + + ls_obj_old-wdyv-descr = is_view-descriptions. + ls_obj_old-wdyv-vcont = is_view-view_containers. + ls_obj_old-wdyv-vcntt = is_view-view_container_texts. + ls_obj_old-wdyv-ibplg = is_view-iobound_plugs. + ls_obj_old-wdyv-ibplt = is_view-iobound_plug_texts. + ls_obj_old-wdyv-plpar = is_view-plug_parameters. + ls_obj_old-wdyv-plprt = is_view-plug_parameter_texts. + ls_obj_old-wdyv-uiele = is_view-ui_elements. + ls_obj_old-wdyv-uicon = is_view-ui_context_bindings. + ls_obj_old-wdyv-uievt = is_view-ui_event_bindings. + ls_obj_old-wdyv-uiddc = is_view-ui_ddic_bindings. + ls_obj_old-wdyv-uiprp = is_view-ui_properties. + ls_obj_old-wdyv-navil = is_view-navigation_links. + ls_obj_old-wdyv-navit = is_view-navigation_target_refs. + ls_obj_old-wdyv-vshno = is_view-vsh_nodes. + ls_obj_old-wdyv-vshpl = is_view-vsh_placeholders. + ls_obj_old-wdyv-views = is_view-viewset_properties. + + CALL FUNCTION 'SVRS_MAKE_OBJECT_DELTA' + EXPORTING + obj_old = ls_obj_new + obj_new = ls_obj_old + CHANGING + delta = rs_delta + EXCEPTIONS + inconsistent_objects = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from SVRS_MAKE_OBJECT_DELTA' ). + ENDIF. + + ENDMETHOD. + METHOD deserialize_sources. + + DATA: + lv_extra TYPE string, + lt_extra TYPE string_table, + ls_abap TYPE abaptxt255, + lt_abap TYPE abaptxt255_tab, + lv_line TYPE wdy_ctlr_compo_source_vrs-line_number, + lv_cmpname TYPE wdy_ctlr_compo_source_vrs-cmpname, + ls_sources LIKE LINE OF mt_sources. + + " Old format + ii_xml->read( EXPORTING iv_name = 'SOURCES' + CHANGING cg_data = mt_sources ). + + IF mt_sources IS NOT INITIAL. + RETURN. + ENDIF. + + " New format + ii_xml->read( EXPORTING iv_name = 'FILES' + CHANGING cg_data = lt_extra ). + + LOOP AT lt_extra INTO lv_extra. + lv_line = 0. + lt_abap = mo_files->read_abap( iv_extra = lv_extra ). + LOOP AT lt_abap INTO ls_abap. + " Start of method + FIND REGEX '\s*method\s+(.*)\s*\.' IN ls_abap-line IGNORING CASE SUBMATCHES lv_cmpname. + IF sy-subrc = 0. + lv_line = 1. + ENDIF. + + IF lv_cmpname IS NOT INITIAL AND lv_line > 0. + CLEAR ls_sources. + ls_sources-component_name = ms_item-obj_name. + ls_sources-controller_name = to_upper( lv_extra ). + ls_sources-cmpname = to_upper( lv_cmpname ). + ls_sources-line_number = lv_line. + ls_sources-source_line = ls_abap-line. + INSERT ls_sources INTO TABLE mt_sources. + lv_line = lv_line + 1. + ENDIF. + + " End of method + FIND REGEX '\s*endmethod\s*\.' IN ls_abap-line IGNORING CASE. + IF sy-subrc = 0. + lv_line = 0. + ENDIF. + ENDLOOP. + ENDLOOP. + + ENDMETHOD. + METHOD get_limu_objects. + + DATA: lv_name TYPE wdy_component_name. + lv_name = ms_item-obj_name. + CALL FUNCTION 'WDYN_GET_LIMU_OBJECTS' + EXPORTING + component_name = lv_name + IMPORTING + limu_objects = rt_objects. + + ENDMETHOD. + METHOD read. + + DATA: lt_objects TYPE wdy_md_transport_keys, + ls_controller_key TYPE wdy_md_controller_key, + ls_component_key TYPE wdy_md_component_key, + ls_view_key TYPE wdy_md_view_key. + + FIELD-SYMBOLS: LIKE LINE OF lt_objects, + LIKE LINE OF rs_component-ctlr_metadata, + LIKE LINE OF rs_component-view_metadata, + TYPE ANY TABLE, + TYPE ANY TABLE. + + CLEAR mt_components. + CLEAR mt_sources. + + lt_objects = get_limu_objects( ). + + LOOP AT lt_objects ASSIGNING . + CASE -sub_type. + WHEN wdyn_limu_component_controller. + ls_controller_key = -sub_name. + APPEND read_controller( ls_controller_key ) TO rs_component-ctlr_metadata. + WHEN wdyn_limu_component_definition. + ls_component_key = -sub_name. + rs_component-comp_metadata = read_definition( ls_component_key ). + WHEN wdyn_limu_component_view. + ls_view_key = -sub_name. + APPEND read_view( ls_view_key ) TO rs_component-view_metadata. + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + ENDLOOP. + + SORT rs_component-ctlr_metadata BY + definition-component_name ASCENDING + definition-controller_name ASCENDING. + + LOOP AT rs_component-ctlr_metadata ASSIGNING . + SORT -descriptions. + SORT -controller_usages. + SORT -controller_components. + SORT -controller_component_texts. + SORT -controller_parameters. + SORT -controller_parameter_texts. + SORT -context_nodes. + SORT -context_attributes. + SORT -context_mappings. + SORT -fieldgroups. +* Version 702 doesn't have these two attributes so we +* use them dynamically for downward compatibility + ASSIGN COMPONENT 'CONTROLLER_EXCEPTIONS' OF STRUCTURE TO . + IF sy-subrc = 0. + SORT . + ENDIF. + ASSIGN COMPONENT 'CONTROLLER_EXCEPTION_TEXTS' OF STRUCTURE TO . + IF sy-subrc = 0. + SORT . + ENDIF. + ENDLOOP. + + SORT rs_component-view_metadata BY + definition-component_name ASCENDING + definition-view_name ASCENDING. + + LOOP AT rs_component-view_metadata ASSIGNING . + SORT -descriptions. + SORT -view_containers. + SORT -view_container_texts. + SORT -iobound_plugs. + SORT -iobound_plug_texts. + SORT -plug_parameters. + SORT -plug_parameter_texts. + SORT -ui_elements. + SORT -ui_context_bindings. + SORT -ui_event_bindings. + SORT -ui_ddic_bindings. + SORT -ui_properties. + SORT -navigation_links. + SORT -navigation_target_refs. + SORT -vsh_nodes. + SORT -vsh_placeholders. + SORT -viewset_properties. + ENDLOOP. + + SORT mt_components BY + component_name ASCENDING + controller_name ASCENDING + cmpname ASCENDING. + + SORT mt_sources BY + component_name ASCENDING + controller_name ASCENDING + cmpname ASCENDING + line_number ASCENDING. + + ENDMETHOD. + METHOD read_controller. + + DATA: lt_components TYPE TABLE OF wdy_ctlr_compo_vrs, + lt_sources TYPE TABLE OF wdy_ctlr_compo_source_vrs, + lt_definition TYPE TABLE OF wdy_controller, + lt_psmodilog TYPE TABLE OF smodilog, + lt_psmodisrc TYPE TABLE OF smodisrc, + lt_fm_param TYPE abap_func_parmbind_tab, + lt_fm_exception TYPE abap_func_excpbind_tab. + + FIELD-SYMBOLS: TYPE ANY TABLE, + TYPE ANY TABLE. + +* Calling FM dynamically because version 702 has less parameters + +* FM parameters + add_fm_param_exporting( EXPORTING iv_name = 'CONTROLLER_KEY' + ig_value = is_key + CHANGING ct_param = lt_fm_param ). + add_fm_param_exporting( EXPORTING iv_name = 'GET_ALL_TRANSLATIONS' + ig_value = abap_false + CHANGING ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'DEFINITION' + CHANGING ct_value = lt_definition + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'DESCRIPTIONS' + CHANGING ct_value = rs_controller-descriptions + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_USAGES' + CHANGING ct_value = rs_controller-controller_usages + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_COMPONENTS' + CHANGING ct_value = lt_components + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_COMPONENT_SOURCES' + CHANGING ct_value = lt_sources + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_COMPONENT_TEXTS' + CHANGING ct_value = rs_controller-controller_component_texts + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_PARAMETERS' + CHANGING ct_value = rs_controller-controller_parameters + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_PARAMETER_TEXTS' + CHANGING ct_value = rs_controller-controller_parameter_texts + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'CONTEXT_NODES' + CHANGING ct_value = rs_controller-context_nodes + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'CONTEXT_ATTRIBUTES' + CHANGING ct_value = rs_controller-context_attributes + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'CONTEXT_MAPPINGS' + CHANGING ct_value = rs_controller-context_mappings + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'FIELDGROUPS' + CHANGING ct_value = rs_controller-fieldgroups + ct_param = lt_fm_param ). +* Version 702 doesn't have these two attributes so we +* use them dynamically for downward compatibility + ASSIGN COMPONENT 'CONTROLLER_EXCEPTIONS' OF STRUCTURE rs_controller TO . + IF sy-subrc = 0. + add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_EXCEPTIONS' + CHANGING ct_value = + ct_param = lt_fm_param ). + ENDIF. + ASSIGN COMPONENT 'CONTROLLER_EXCEPTION_TEXTS' OF STRUCTURE rs_controller TO . + IF sy-subrc = 0. + add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_EXCEPTION_TEXTS' + CHANGING ct_value = + ct_param = lt_fm_param ). + ENDIF. + add_fm_param_tables( EXPORTING iv_name = 'PSMODILOG' + CHANGING ct_value = lt_psmodilog + ct_param = lt_fm_param ). + add_fm_param_tables( EXPORTING iv_name = 'PSMODISRC' + CHANGING ct_value = lt_psmodisrc + ct_param = lt_fm_param ). + +* FM exceptions + add_fm_exception( EXPORTING iv_name = 'NOT_EXISTING' + iv_value = 1 + CHANGING ct_exception = lt_fm_exception ). + add_fm_exception( EXPORTING iv_name = 'OTHERS' + iv_value = 2 + CHANGING ct_exception = lt_fm_exception ). + + CALL FUNCTION 'WDYC_GET_OBJECT' + PARAMETER-TABLE + lt_fm_param + EXCEPTION-TABLE + lt_fm_exception. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from WDYC_GET_OBJECT' ). + ENDIF. + + APPEND LINES OF lt_components TO mt_components. + APPEND LINES OF lt_sources TO mt_sources. + + READ TABLE lt_definition INDEX 1 INTO rs_controller-definition. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'WDYC, definition not found' ). + ENDIF. + + CLEAR: rs_controller-definition-author, + rs_controller-definition-createdon, + rs_controller-definition-changedby, + rs_controller-definition-changedon. + + ENDMETHOD. + METHOD read_definition. + + DATA: lt_definition TYPE TABLE OF wdy_component, + lt_psmodilog TYPE TABLE OF smodilog, + lt_psmodisrc TYPE TABLE OF smodisrc. + CALL FUNCTION 'WDYD_GET_OBJECT' + EXPORTING + component_key = is_key + get_all_translations = abap_false + TABLES + definition = lt_definition + descriptions = rs_definition-descriptions + component_usages = rs_definition-component_usages + interface_implementings = rs_definition-interface_implementings + library_usages = rs_definition-library_usages + ext_ctlr_usages = rs_definition-ext_ctlr_usages + ext_ctx_mappings = rs_definition-ext_ctx_mappings + psmodilog = lt_psmodilog " not optional in all versions + psmodisrc = lt_psmodisrc " not optional in all versions + EXCEPTIONS + not_existing = 1 + OTHERS = 2. + IF sy-subrc = 1. + RETURN. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from WDYD_GET_OBJECT' ). + ENDIF. + + READ TABLE lt_definition INDEX 1 INTO rs_definition-definition. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'WDYD, definition not found' ). + ENDIF. + + CLEAR: rs_definition-definition-author, + rs_definition-definition-createdon, + rs_definition-definition-changedby, + rs_definition-definition-changedon, + rs_definition-definition-gendate, + rs_definition-definition-gentime. + + ENDMETHOD. + METHOD read_view. + + DATA: lt_definition TYPE TABLE OF wdy_view_vrs, + lt_psmodilog TYPE TABLE OF smodilog, + lt_psmodisrc TYPE TABLE OF smodisrc. + + FIELD-SYMBOLS: LIKE LINE OF lt_definition. + CALL FUNCTION 'WDYV_GET_OBJECT' + EXPORTING + view_key = is_key + get_all_translations = abap_false + TABLES + definition = lt_definition + descriptions = rs_view-descriptions + view_containers = rs_view-view_containers + view_container_texts = rs_view-view_container_texts + iobound_plugs = rs_view-iobound_plugs + iobound_plug_texts = rs_view-iobound_plug_texts + plug_parameters = rs_view-plug_parameters + plug_parameter_texts = rs_view-plug_parameter_texts + ui_elements = rs_view-ui_elements + ui_context_bindings = rs_view-ui_context_bindings + ui_event_bindings = rs_view-ui_event_bindings + ui_ddic_bindings = rs_view-ui_ddic_bindings + ui_properties = rs_view-ui_properties + navigation_links = rs_view-navigation_links + navigation_target_refs = rs_view-navigation_target_refs + vsh_nodes = rs_view-vsh_nodes + vsh_placeholders = rs_view-vsh_placeholders + viewset_properties = rs_view-viewset_properties + psmodilog = lt_psmodilog + psmodisrc = lt_psmodisrc + EXCEPTIONS + not_existing = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from WDYV_GET_OBJECT' ). + ENDIF. + + READ TABLE lt_definition INDEX 1 ASSIGNING . + ASSERT sy-subrc = 0. + MOVE-CORRESPONDING TO rs_view-definition. + + CLEAR: rs_view-definition-author, + rs_view-definition-createdon, + rs_view-definition-changedby, + rs_view-definition-changedon. + + ENDMETHOD. + METHOD recover_controller. + + DATA: ls_key TYPE wdy_controller_key, + lv_corrnr TYPE trkorr, + lx_error TYPE REF TO cx_wdy_md_exception, + ls_delta TYPE svrs2_xversionable_object. + ls_delta = delta_controller( is_controller ). + ls_key-component_name = is_controller-definition-component_name. + ls_key-controller_name = is_controller-definition-controller_name. + + TRY. + cl_wdy_md_controller=>recover_version( + EXPORTING + controller_key = ls_key + delta = ls_delta-wdyc + CHANGING + corrnr = lv_corrnr ). + CATCH cx_wdy_md_exception INTO lx_error. + zcx_abapgit_exception=>raise( |Error recovering version of controller: { lx_error->get_text( ) }| ). + ENDTRY. + + unlock_controller( ls_key ). + + ENDMETHOD. + METHOD recover_definition. + + DATA: ls_key TYPE wdy_md_component_key, + lv_corrnr TYPE trkorr, + lx_error TYPE REF TO cx_wdy_md_exception, + ls_delta TYPE svrs2_xversionable_object. + ls_delta = delta_definition( + is_definition = is_definition + iv_package = iv_package ). + + ls_key-component_name = is_definition-definition-component_name. + + TRY. + cl_wdy_md_component=>recover_version( + EXPORTING + component_key = ls_key + delta = ls_delta-wdyd + CHANGING + corrnr = lv_corrnr ). + CATCH cx_wdy_md_exception INTO lx_error. + zcx_abapgit_exception=>raise( |Error recovering version of component: { lx_error->get_text( ) }| ). + ENDTRY. + + unlock_definition( ls_key ). + + ENDMETHOD. + METHOD recover_view. + + DATA: ls_key TYPE wdy_md_view_key, + lv_corrnr TYPE trkorr, + lx_error TYPE REF TO cx_wdy_md_exception, + ls_delta TYPE svrs2_xversionable_object. + ls_delta = delta_view( is_view ). + ls_key-component_name = is_view-definition-component_name. + ls_key-view_name = is_view-definition-view_name. + + TRY. + cl_wdy_md_abstract_view=>recover_version( + EXPORTING + view_key = ls_key + delta = ls_delta-wdyv + CHANGING + corrnr = lv_corrnr ). + CATCH cx_wdy_md_exception INTO lx_error. + zcx_abapgit_exception=>raise( |Error recovering version of abstract view: { lx_error->get_text( ) }| ). + ENDTRY. + + unlock_view( ls_key ). + + ENDMETHOD. + METHOD unlock_controller. + + DATA lo_controller TYPE REF TO cl_wdy_md_controller. + + TRY. + lo_controller ?= cl_wdy_md_controller=>get_object_by_key( + component_name = is_controller_key-component_name + controller_name = is_controller_key-controller_name ). + lo_controller->if_wdy_md_lockable_object~unlock( ). + CATCH cx_wdy_md_permission_failure cx_wdy_md_not_existing ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD unlock_definition. + + DATA: lo_component TYPE REF TO cl_wdy_md_component, + lo_comp_intf_def TYPE REF TO cl_wdy_md_component_intf_def. + + TRY. + lo_component ?= cl_wdy_md_component=>get_object_by_key( name = is_component_key-component_name ). + lo_component->if_wdy_md_component~unlock( ). + CATCH cx_wdy_md_not_existing. + TRY. + lo_comp_intf_def ?= cl_wdy_md_component_intf_def=>get_object_by_key( name = is_component_key-component_name ). + lo_comp_intf_def->if_wdy_md_component_intf_def~unlock( ). + CATCH cx_wdy_md_permission_failure cx_wdy_md_not_existing ##NO_HANDLER. + ENDTRY. + CATCH cx_wdy_md_permission_failure ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD unlock_view. + + DATA lo_view TYPE REF TO cl_wdy_md_abstract_view. + + TRY. + lo_view ?= cl_wdy_md_abstract_view=>get_object_by_key( + component_name = is_view_key-component_name + view_name = is_view_key-view_name ). + lo_view->if_wdy_md_lockable_object~unlock( ). + CATCH cx_wdy_md_permission_failure cx_wdy_md_not_existing ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD serialize_sources. + + DATA: + lv_extra TYPE string, + lt_extra TYPE string_table, + ls_abap TYPE abaptxt255, + lt_abap TYPE abaptxt255_tab. + + FIELD-SYMBOLS LIKE LINE OF mt_sources. + + " Store code as separate ABAP files instead of XML (assumes sorted data, see "read") + LOOP AT mt_sources ASSIGNING . + AT NEW controller_name. + CLEAR lt_abap. + lv_extra = to_lower( -controller_name ). + ENDAT. + + ls_abap-line = -source_line. + INSERT ls_abap INTO TABLE lt_abap. + + AT END OF cmpname. + CLEAR ls_abap. + INSERT ls_abap INTO TABLE lt_abap. + ENDAT. + AT END OF controller_name. + IF lt_abap IS NOT INITIAL. + mo_files->add_abap( + iv_extra = lv_extra + it_abap = lt_abap ). + INSERT lv_extra INTO TABLE lt_extra. + ENDIF. + ENDAT. + ENDLOOP. + + ii_xml->add( + iv_name = 'FILES' + ig_data = lt_extra ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + SELECT SINGLE changedby FROM wdy_component INTO rv_user + WHERE component_name = ms_item-obj_name AND version = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_component TYPE REF TO cl_wdy_wb_component, + lo_request TYPE REF TO cl_wb_request, + li_state TYPE REF TO if_wb_program_state, + lv_object_name TYPE seu_objkey. + CREATE OBJECT lo_component. + + lv_object_name = ms_item-obj_name. + CREATE OBJECT lo_request + EXPORTING + p_object_type = 'YC' + p_object_name = lv_object_name + p_operation = swbm_c_op_delete_no_dialog. + + lo_component->if_wb_program~process_wb_request( + p_wb_request = lo_request + p_wb_program_state = li_state ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_component TYPE wdy_component_metadata, + ls_description TYPE wdy_ext_ctx_map. + + FIELD-SYMBOLS: LIKE LINE OF ls_component-view_metadata, + LIKE LINE OF ls_component-ctlr_metadata. + + io_xml->read( EXPORTING iv_name = 'COMPONENT' + CHANGING cg_data = ls_component ). + io_xml->read( EXPORTING iv_name = 'COMPONENTS' + CHANGING cg_data = mt_components ). + + deserialize_sources( io_xml ). + + ls_component-comp_metadata-definition-author = sy-uname. + ls_component-comp_metadata-definition-createdon = sy-datum. + recover_definition( is_definition = ls_component-comp_metadata + iv_package = iv_package ). + + LOOP AT ls_component-ctlr_metadata ASSIGNING . + -definition-author = sy-uname. + -definition-createdon = sy-datum. + recover_controller( ). + ENDLOOP. + LOOP AT ls_component-view_metadata ASSIGNING . + -definition-author = sy-uname. + -definition-createdon = sy-datum. + recover_view( ). + ENDLOOP. + + READ TABLE ls_component-comp_metadata-descriptions INTO ls_description INDEX 1. + IF sy-subrc = 0. + zcl_abapgit_sotr_handler=>create_sotr( + iv_package = iv_package + io_xml = io_xml ). + ENDIF. + + add_with_inactive_parts( ). + + deserialize_longtexts( + ii_xml = io_xml + iv_longtext_id = c_longtext_id_wd ). + + deserialize_longtexts( + ii_xml = io_xml + iv_longtext_id = c_longtext_id_wc + iv_longtext_name = c_longtext_name_wc ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_component_name TYPE wdy_component-component_name. + SELECT SINGLE component_name FROM wdy_component + INTO lv_component_name + WHERE component_name = ms_item-obj_name. "#EC CI_GENBUFF + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_component TYPE wdy_component_metadata, + ls_comp TYPE wdy_ctlr_compo_vrs, + lv_object TYPE dokil-object, + lt_object TYPE STANDARD TABLE OF dokil-object WITH DEFAULT KEY, + lt_dokil TYPE STANDARD TABLE OF dokil WITH DEFAULT KEY, + ls_description TYPE wdy_ext_ctx_map. + + ls_component = read( ). + + io_xml->add( iv_name = 'COMPONENT' + ig_data = ls_component ). + io_xml->add( ig_data = mt_components + iv_name = 'COMPONENTS' ). + + serialize_sources( io_xml ). + + READ TABLE ls_component-comp_metadata-descriptions INTO ls_description INDEX 1. + IF sy-subrc = 0. + zcl_abapgit_sotr_handler=>read_sotr( + iv_pgmid = 'LIMU' + iv_object = 'WDYV' + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + io_xml = io_xml ). + ENDIF. + + serialize_longtexts( + ii_xml = io_xml + iv_longtext_id = c_longtext_id_wd ). + + LOOP AT mt_components INTO ls_comp. + lv_object = ls_comp-component_name. + lv_object+30 = ls_comp-controller_name. + COLLECT lv_object INTO lt_object. + ENDLOOP. + + IF lt_object IS NOT INITIAL. + IF mo_i18n_params->ms_params-main_language_only = abap_true. + SELECT * FROM dokil INTO TABLE lt_dokil + FOR ALL ENTRIES IN lt_object + WHERE id = c_longtext_id_wc AND object = lt_object-table_line AND masterlang = abap_true + ORDER BY PRIMARY KEY. + ELSE. + SELECT * FROM dokil INTO TABLE lt_dokil + FOR ALL ENTRIES IN lt_object + WHERE id = c_longtext_id_wc AND object = lt_object-table_line + ORDER BY PRIMARY KEY. + ENDIF. + + serialize_longtexts( + ii_xml = io_xml + it_dokil = lt_dokil + iv_longtext_id = c_longtext_id_wc + iv_longtext_name = c_longtext_name_wc ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_wdya IMPLEMENTATION. + METHOD read. + + DATA: li_app TYPE REF TO if_wdy_md_application, + li_map TYPE REF TO if_object_map, + lo_prop TYPE REF TO cl_wdy_md_application_property, + ls_prop LIKE LINE OF et_properties, + lv_name TYPE wdy_application_name. + CLEAR es_app. + CLEAR et_properties. + + lv_name = ms_item-obj_name. + TRY. + li_app = cl_wdy_md_application=>get_object_by_key( + name = lv_name + version = 'A' ). + CATCH cx_wdy_md_not_existing. + RETURN. + CATCH cx_wdy_md_permission_failure. + zcx_abapgit_exception=>raise( 'WDYA, permission failure' ). + ENDTRY. + + li_app->if_wdy_md_object~get_definition( IMPORTING definition = es_app ). + CLEAR: es_app-author, + es_app-createdon, + es_app-changedby, + es_app-changedon. + + li_map = li_app->get_properties( ). + DO li_map->size( ) TIMES. + lo_prop ?= li_map->get_by_position( sy-index ). + lo_prop->get_definition( IMPORTING definition = ls_prop ). + APPEND ls_prop TO et_properties. + ENDDO. + + ENDMETHOD. + METHOD save. + + DATA: li_prop TYPE REF TO if_wdy_md_application_property, + lo_app TYPE REF TO cl_wdy_md_application. + + FIELD-SYMBOLS: LIKE LINE OF it_properties. + TRY. + CREATE OBJECT lo_app + EXPORTING + name = is_app-application_name + definition = is_app + devclass = iv_package. + + LOOP AT it_properties ASSIGNING . + li_prop = lo_app->if_wdy_md_application~create_property( -name ). + li_prop->set_value( -value ). + ENDLOOP. + + tadir_insert( iv_package ). + + lo_app->if_wdy_md_lockable_object~save_to_database( ). + + lo_app->if_wdy_md_lockable_object~unlock( ). + CATCH cx_wdy_md_exception. + IF lo_app IS NOT INITIAL. + lo_app->if_wdy_md_lockable_object~unlock( ). + ENDIF. + zcx_abapgit_exception=>raise( 'error saving WDYA' ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: li_app TYPE REF TO if_wdy_md_application, + ls_app TYPE wdy_application, + lv_name TYPE wdy_application_name. + lv_name = ms_item-obj_name. + TRY. + li_app = cl_wdy_md_application=>get_object_by_key( + name = lv_name + version = 'A' ). + + li_app->if_wdy_md_object~get_definition( IMPORTING definition = ls_app ). + + IF ls_app-changedby IS INITIAL. + rv_user = ls_app-author. + ELSE. + rv_user = ls_app-changedby. + ENDIF. + CATCH cx_root. + rv_user = c_user_unknown. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: li_app TYPE REF TO if_wdy_md_application, + lv_objkey TYPE wdy_wb_appl_name, + lv_type TYPE seu_type, + lv_name TYPE wdy_application_name. + lv_name = ms_item-obj_name. + TRY. + li_app = cl_wdy_md_application=>get_object_by_key( + name = lv_name + version = 'A' ). + li_app->if_wdy_md_object~delete( ). + li_app->if_wdy_md_lockable_object~save_to_database( ). + +* method save_to_database calls function module TR_TADIR_INTERFACE +* with test mode = X, so it does not delete the TADIR entry. +* Instead the standard code uses RS_TREE_OBJECT_PLACEMENT to delete +* the TADIR entry + lv_objkey = ms_item-obj_name. + CONCATENATE 'O' swbm_c_type_wdy_application INTO lv_type. + CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' + EXPORTING + object = lv_objkey + type = lv_type + operation = 'DELETE'. + + CATCH cx_wdy_md_not_existing. + RETURN. + CATCH cx_wdy_md_exception. + zcx_abapgit_exception=>raise( 'WDYA, error deleting' ). + ENDTRY. + + delete_longtexts( c_longtext_id_wdya ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_app TYPE wdy_application, + lt_properties TYPE wdy_app_property_table. + + io_xml->read( EXPORTING iv_name = 'APP' + CHANGING cg_data = ls_app ). + io_xml->read( EXPORTING iv_name = 'PROPERTIES' + CHANGING cg_data = lt_properties ). + + save( is_app = ls_app + it_properties = lt_properties + iv_package = iv_package ). + + zcl_abapgit_sotr_handler=>create_sotr( + iv_package = iv_package + io_xml = io_xml ). + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_wdya ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_name TYPE wdy_application_name. + lv_name = ms_item-obj_name. + + TRY. + cl_wdy_md_application=>get_object_by_key( + name = lv_name + version = 'A' ). + rv_bool = abap_true. + CATCH cx_wdy_md_not_existing. + rv_bool = abap_false. + CATCH cx_wdy_md_permission_failure. + zcx_abapgit_exception=>raise( 'WDYA, permission failure' ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_app TYPE wdy_application, + lt_properties TYPE wdy_app_property_table. + + read( IMPORTING es_app = ls_app + et_properties = lt_properties ). + + io_xml->add( iv_name = 'APP' + ig_data = ls_app ). + io_xml->add( iv_name = 'PROPERTIES' + ig_data = lt_properties ). + + zcl_abapgit_sotr_handler=>read_sotr( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + io_xml = io_xml ). + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_wdya ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_wdcc IMPLEMENTATION. + + METHOD constructor. + + DATA: + ls_orig_config TYPE wdy_config_data. + + FIELD-SYMBOLS: + TYPE data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + ASSIGN COMPONENT 'CONFIG_IDPAR' OF STRUCTURE ls_orig_config TO . + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_outline TYPE wdy_cfg_outline_data, + ls_config_key TYPE wdy_config_key. + + ls_config_key-config_id = ms_item-obj_name+0(32). + ls_config_key-config_type = ms_item-obj_name+32(2). + ls_config_key-config_var = ms_item-obj_name+34(6). + + TRY. + cl_wdr_cfg_persistence_utils=>read_comp_config_from_db( + EXPORTING + config_key = ls_config_key + IMPORTING + outline_data = ls_outline ). + CATCH cx_static_check. + zcx_abapgit_exception=>raise( 'Error Reading Component Config from DB: ' && ms_item-obj_name ). + ENDTRY. + + rv_user = ls_outline-changedby. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + DATA: ls_config_key TYPE wdy_config_key, + lv_subrc TYPE sysubrc. + + ls_config_key-config_id = ms_item-obj_name+0(32). + ls_config_key-config_type = ms_item-obj_name+32(2). + ls_config_key-config_var = ms_item-obj_name+34(6). + + " does not exist in 702 + CALL METHOD cl_wdr_cfg_persistence_utils=>('DELETE_CONFIGURATION') + EXPORTING + config_key = ls_config_key + RECEIVING + subrc = lv_subrc. + IF lv_subrc <> 0. + zcx_abapgit_exception=>raise( 'Error deleting WDCC: ' && ms_item-obj_name ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_config_id TYPE c LENGTH 32, + lv_config_type TYPE n LENGTH 2, + lv_config_var TYPE c LENGTH 6, + lt_otr_texts TYPE TABLE OF wdy_config_compt, + ls_orig_config TYPE wdy_config_data, + lt_config_datt TYPE TABLE OF wdy_config_datt, + lv_xml_string TYPE string, + lv_xml_xstring TYPE xstring. + + FIELD-SYMBOLS: TYPE any. + + io_xml->read( EXPORTING iv_name = 'CONFIG_ID' + CHANGING cg_data = ls_orig_config-config_id ). + + io_xml->read( EXPORTING iv_name = 'CONFIG_TYPE' + CHANGING cg_data = ls_orig_config-config_type ). + + io_xml->read( EXPORTING iv_name = 'CONFIG_VAR' + CHANGING cg_data = ls_orig_config-config_var ). + + lv_config_id = ls_orig_config-config_id. + lv_config_type = ls_orig_config-config_type. + lv_config_var = ls_orig_config-config_var. + + ASSIGN COMPONENT 'CONFIG_IDPAR' OF STRUCTURE ls_orig_config TO . + IF sy-subrc = 0. + io_xml->read( EXPORTING iv_name = 'CONFIG_IDPAR' + CHANGING cg_data = ). + ENDIF. + + ASSIGN COMPONENT 'CONFIG_TYPEPAR' OF STRUCTURE ls_orig_config TO . + IF sy-subrc = 0. + io_xml->read( EXPORTING iv_name = 'CONFIG_TYPEPAR' + CHANGING cg_data = ). + ENDIF. + + ASSIGN COMPONENT 'CONFIG_VARPAR' OF STRUCTURE ls_orig_config TO . + IF sy-subrc = 0. + io_xml->read( EXPORTING iv_name = 'CONFIG_VARPAR' + CHANGING cg_data = ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'WDA_COMPONENT' + CHANGING cg_data = ls_orig_config-component ). + + lv_xml_string = mo_files->read_string( + iv_extra = 'comp_config' + iv_ext = 'xml' ). + + TRY. + lv_xml_string = zcl_abapgit_xml_pretty=>print( iv_xml = lv_xml_string + iv_ignore_errors = abap_false + iv_unpretty = abap_true ). + CATCH zcx_abapgit_exception. + zcx_abapgit_exception=>raise( 'Error Un-Pretty Printing WDCC XML Content: ' && ms_item-obj_name ). + ENDTRY. + + REPLACE FIRST OCCURRENCE + OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' + IN lv_xml_string + WITH ''. + ASSERT sy-subrc = 0. + + lv_xml_xstring = zcl_abapgit_convert=>string_to_xstring( lv_xml_string ). + ls_orig_config-xcontent = lv_xml_xstring. + + ASSIGN COMPONENT 'PARENT' OF STRUCTURE ls_orig_config TO . + IF sy-subrc = 0. + io_xml->read( EXPORTING iv_name = 'PARENT' + CHANGING cg_data = ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'RELID' + CHANGING cg_data = ls_orig_config-relid ). + + SELECT SINGLE author createdon FROM wdy_config_data INTO (ls_orig_config-author, ls_orig_config-createdon) + WHERE config_id = lv_config_id AND + config_type = lv_config_type AND + config_var = lv_config_var. + + IF ls_orig_config-author IS INITIAL. + ls_orig_config-author = sy-uname. + ENDIF. + ls_orig_config-changedby = sy-uname. + ls_orig_config-changedon = sy-datum. + + IF ls_orig_config-createdon IS INITIAL. + ls_orig_config-createdon = sy-datum. + ENDIF. + + CALL FUNCTION 'ENQUEUE_E_WDY_CONFCOMP' + EXPORTING + mode_wdy_config_data = 'E' "if_wdr_cfg_constants=>c_lock_mode_exclusive + config_id = lv_config_id + config_type = lv_config_type + config_var = lv_config_var + x_config_id = 'X' + x_config_type = 'X' + x_config_var = 'X' + EXCEPTIONS + foreign_lock = 1 + system_failure = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error Enqueueing Component Config: ' && ms_item-obj_name ). + ENDIF. + + " CL_WDR_CFG_PERSISTENCE_UTILS=>SAVE_COMP_CONFIG_TO_DB does not exist in 702 so we save directly to DB + DELETE FROM wdy_config_data + WHERE config_id = ls_orig_config-config_id + AND config_type = ls_orig_config-config_type + AND config_var = ls_orig_config-config_var. + MODIFY wdy_config_data FROM ls_orig_config. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error Updating WDY_CONFIG_DATA for Component Config ' && ms_item-obj_name ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'OTR_TEXT' + CHANGING cg_data = lt_otr_texts ). + + IF lt_otr_texts IS NOT INITIAL. + DELETE FROM wdy_config_compt + WHERE config_id = ls_orig_config-config_id + AND config_type = ls_orig_config-config_type + AND config_var = ls_orig_config-config_var. + MODIFY wdy_config_compt FROM TABLE lt_otr_texts. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error Updating WDY_CONFIG_COMPT for Component Config ' && ms_item-obj_name ). + ENDIF. + ENDIF. + + io_xml->read( EXPORTING iv_name = 'DESCR_LANG' + CHANGING cg_data = lt_config_datt ). + + IF lt_config_datt IS NOT INITIAL. + DELETE FROM wdy_config_datt + WHERE config_id = ls_orig_config-config_id + AND config_type = ls_orig_config-config_type + AND config_var = ls_orig_config-config_var. + MODIFY wdy_config_datt FROM TABLE lt_config_datt. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error Updating WDY_CONFIG_DATT for Component Config ' && ms_item-obj_name ). + ENDIF. + ENDIF. + + CALL FUNCTION 'DEQUEUE_E_WDY_CONFCOMP' + EXPORTING + mode_wdy_config_data = 'E' "if_wdr_cfg_constants=>c_lock_mode_exclusive + config_id = lv_config_id + config_type = lv_config_type + config_var = lv_config_var + x_config_id = 'X' + x_config_type = 'X' + x_config_var = 'X'. + + tadir_insert( iv_package ). + + after_import( ). + + corr_insert( iv_package ). + + ENDMETHOD. + + METHOD after_import. + + DATA: lt_cts_object_entry TYPE STANDARD TABLE OF e071 WITH DEFAULT KEY, + ls_cts_object_entry LIKE LINE OF lt_cts_object_entry, + lt_cts_key TYPE STANDARD TABLE OF e071k WITH DEFAULT KEY. + + ls_cts_object_entry-pgmid = 'R3TR'. + ls_cts_object_entry-object = ms_item-obj_type. + ls_cts_object_entry-obj_name = ms_item-obj_name. + INSERT ls_cts_object_entry INTO TABLE lt_cts_object_entry. + + CALL FUNCTION 'WDR_CFG_AFTER_IMPORT' + EXPORTING + iv_tarclient = sy-mandt + iv_is_upgrade = abap_false + TABLES + tt_e071 = lt_cts_object_entry + tt_e071k = lt_cts_key. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_outline TYPE wdy_cfg_outline_data, + ls_config_key TYPE wdy_config_key. + + ls_config_key-config_id = ms_item-obj_name+0(32). + ls_config_key-config_type = ms_item-obj_name+32(2). + ls_config_key-config_var = ms_item-obj_name+34(6). + + TRY. + cl_wdr_cfg_persistence_utils=>read_comp_config_from_db( + EXPORTING + config_key = ls_config_key + IMPORTING + outline_data = ls_outline ). + CATCH cx_static_check. + rv_bool = abap_false. + RETURN. + ENDTRY. + + rv_bool = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = abap_true. + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lt_enq TYPE STANDARD TABLE OF seqg3, + lv_subrc TYPE sysubrc, + lv_garg TYPE eqegraarg. + + lv_garg = ms_item-obj_name. + + CALL FUNCTION 'ENQUEUE_READ' + EXPORTING + gclient = sy-mandt + gname = 'WDY_CONFIG_DATA' + garg = lv_garg + IMPORTING + subrc = lv_subrc + TABLES + enq = lt_enq + EXCEPTIONS + communication_failure = 2 + OTHERS = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error check object lock WDCC: ' && ms_item-obj_name ). + ENDIF. + + rv_is_locked = boolc( lines( lt_enq ) > 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_xml_xstring TYPE xstring, + lt_otr_texts TYPE TABLE OF wdy_config_compt, + lt_cc_text TYPE TABLE OF wdy_config_datt, + ls_orig_config TYPE wdy_config_data, + ls_outline TYPE wdy_cfg_outline_data, + ls_config_key TYPE wdy_config_key, + lv_xml_string TYPE string. + + FIELD-SYMBOLS: TYPE any. + + io_xml->add( iv_name = 'OBJECT_NAME' + ig_data = ms_item-obj_name ). + + ls_config_key-config_id = ms_item-obj_name+0(32). + ls_config_key-config_type = ms_item-obj_name+32(2). + ls_config_key-config_var = ms_item-obj_name+34(6). + + TRY. + " original_config_data does not exist in 702 + CALL METHOD cl_wdr_cfg_persistence_utils=>('READ_COMP_CONFIG_FROM_DB') + EXPORTING + config_key = ls_config_key + IMPORTING + xml_xcontent = lv_xml_xstring + original_config_data = ls_orig_config + outline_data = ls_outline. + + CATCH cx_static_check. + zcx_abapgit_exception=>raise( 'Error Reading Component Config from DB: ' && ms_item-obj_name ). + ENDTRY. + + io_xml->add( iv_name = 'CONFIG_ID' + ig_data = ls_orig_config-config_id ). + + io_xml->add( iv_name = 'CONFIG_TYPE' + ig_data = ls_orig_config-config_type ). + + io_xml->add( iv_name = 'CONFIG_VAR' + ig_data = ls_orig_config-config_var ). + + io_xml->add( iv_name = 'WDA_COMPONENT' + ig_data = ls_orig_config-component ). + + ASSIGN COMPONENT 'CONFIG_IDPAR' OF STRUCTURE ls_orig_config TO . + IF sy-subrc = 0. + io_xml->add( iv_name = 'CONFIG_IDPAR' + ig_data = ). + ENDIF. + + ASSIGN COMPONENT 'CONFIG_TYPEPAR' OF STRUCTURE ls_orig_config TO . + IF sy-subrc = 0. + io_xml->add( iv_name = 'CONFIG_TYPEPAR' + ig_data = ). + ENDIF. + + ASSIGN COMPONENT 'CONFIG_VARPAR' OF STRUCTURE ls_orig_config TO . + IF sy-subrc = 0. + io_xml->add( iv_name = 'CONFIG_VARPAR' + ig_data = ). + ENDIF. + + ASSIGN COMPONENT 'PARENT' OF STRUCTURE ls_orig_config TO . + IF sy-subrc = 0. + io_xml->add( iv_name = 'PARENT' + ig_data = ). + ENDIF. + + io_xml->add( iv_name = 'RELID' + ig_data = ls_orig_config-relid ). + + lv_xml_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xml_xstring ). + IF lv_xml_string IS NOT INITIAL. + TRY. + lv_xml_string = zcl_abapgit_xml_pretty=>print( + iv_xml = lv_xml_string + iv_ignore_errors = abap_false ). + CATCH zcx_abapgit_exception. + zcx_abapgit_exception=>raise( 'Error Pretty Printing WDCC XML Content: ' && ms_item-obj_name ). + ENDTRY. + + REPLACE FIRST OCCURRENCE + OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' + IN lv_xml_string + WITH ''. + ASSERT sy-subrc = 0. + ENDIF. + + mo_files->add_string( + iv_extra = 'comp_config' + iv_ext = 'xml' + iv_string = lv_xml_string ). + + SELECT * FROM wdy_config_compt INTO TABLE lt_otr_texts + WHERE config_id = ls_orig_config-config_id + AND config_type = ls_orig_config-config_type + AND config_var = ls_orig_config-config_var + ORDER BY PRIMARY KEY. + IF lt_otr_texts IS NOT INITIAL. + io_xml->add( iv_name = 'OTR_TEXT' + ig_data = lt_otr_texts ). + ENDIF. + + SELECT * FROM wdy_config_datt INTO TABLE lt_cc_text + WHERE config_id = ls_orig_config-config_id + AND config_type = ls_orig_config-config_type + AND config_var = ls_orig_config-config_var + ORDER BY PRIMARY KEY. + IF lt_cc_text IS NOT INITIAL. + io_xml->add( iv_name = 'DESCR_LANG' + ig_data = lt_cc_text ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_wdca IMPLEMENTATION. + METHOD check. + + FIELD-SYMBOLS: TYPE LINE OF cts_messages. + + LOOP AT it_messages ASSIGNING WHERE severity = 'E'. + zcx_abapgit_exception=>raise( -text ). + ENDLOOP. + + ENDMETHOD. + METHOD delete. + + DATA: + lo_cfg TYPE REF TO cl_wdr_cfg_persistence_appl, + lx_err TYPE REF TO cx_wd_configuration, + lt_messages TYPE cts_messages, + ls_key TYPE wdy_config_key, + ls_outline TYPE wdy_cfg_outline_data, + lv_operation TYPE i, + lv_name TYPE wdy_md_object_name, + lv_exists TYPE wdy_boolean. + + ls_key = ms_item-obj_name. + + TRY. + CREATE OBJECT lo_cfg + EXPORTING + config_key = ls_key + object_name = lv_name. + + MOVE-CORRESPONDING ls_key TO ls_outline. + + lo_cfg->check_config_existent( + EXPORTING + i_outline_data = ls_outline + i_only_current_layer = abap_false + i_is_original = abap_true + IMPORTING + e_is_existent = lv_exists ). + + IF lv_exists = abap_false. + RETURN. + ENDIF. + + lo_cfg->set_transport( trkorr = iv_transport + devclass = iv_package ). + + lv_operation = if_wdr_cfg_constants=>c_cts_operation-e_delete. + " First call, check, second call, delete + DO 2 TIMES. + lo_cfg->do_next_step( + IMPORTING + e_messages = lt_messages + CHANGING + c_operation = lv_operation ). + check( lt_messages ). + ENDDO. + + CATCH cx_wd_configuration INTO lx_err. + IF lx_err->textid = cx_wd_configuration=>conf_config_not_exist. + RETURN. + ELSE. + zcx_abapgit_exception=>raise( 'WDCA, delete error:' && lx_err->get_text( ) ). + ENDIF. + ENDTRY. + + ENDMETHOD. + METHOD read. + + DATA: + lo_cfg TYPE REF TO cl_wdr_cfg_persistence_appl, + ls_key TYPE wdy_config_key, + lv_exists TYPE abap_bool, + lx_err TYPE REF TO cx_wd_configuration, + lv_name TYPE wdy_md_object_name. + + FIELD-SYMBOLS: + LIKE LINE OF et_data, + LIKE LINE OF -appl_params. + + CLEAR: es_outline, et_data. + + ls_key = ms_item-obj_name. + + TRY. + CREATE OBJECT lo_cfg + EXPORTING + config_key = ls_key + object_name = lv_name. + + MOVE-CORRESPONDING ls_key TO es_outline. + + lo_cfg->check_config_existent( + EXPORTING + i_outline_data = es_outline + i_only_current_layer = abap_false + i_is_original = abap_true + IMPORTING + e_is_existent = lv_exists ). + + IF lv_exists = abap_false. + RETURN. + ENDIF. + + es_outline = lo_cfg->read_outline_data( ). + + CLEAR: es_outline-devclass, + es_outline-author, + es_outline-createdon, + es_outline-changedby, + es_outline-changedon. + + et_data = lo_cfg->read_data( ). + + " Clear descriptions since they are release and language-specific + LOOP AT et_data ASSIGNING . + LOOP AT -appl_params ASSIGNING . + CLEAR -description. + ENDLOOP. + ENDLOOP. + + CATCH cx_wd_configuration INTO lx_err. + zcx_abapgit_exception=>raise( 'WDCA, read error:' && lx_err->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD save. + + DATA: + lo_cfg TYPE REF TO cl_wdr_cfg_persistence_appl, + lx_err TYPE REF TO cx_wd_configuration, + lt_messages TYPE cts_messages, + ls_key TYPE wdy_config_key, + ls_data LIKE LINE OF it_data, + lv_operation TYPE i, + lv_name TYPE wdy_md_object_name, + lv_exists TYPE wdy_boolean. + + MOVE-CORRESPONDING is_outline TO ls_key. + + TRY. + CREATE OBJECT lo_cfg + EXPORTING + config_key = ls_key + object_name = lv_name. + + READ TABLE it_data INDEX 1 INTO ls_data. + ASSERT sy-subrc = 0. + + lo_cfg->check_config_existent( + EXPORTING + i_outline_data = is_outline + i_only_current_layer = abap_false + i_is_original = abap_true + IMPORTING + e_is_existent = lv_exists ). + + CATCH cx_wd_configuration ##NO_HANDLER. + " Ignore + ENDTRY. + + TRY. + lo_cfg->set_transport( trkorr = iv_transport + devclass = iv_package ). + lo_cfg->set_save_data( ls_data ). + lo_cfg->set_config_description( is_outline ). + + IF lv_exists = abap_false. + lv_operation = if_wdr_cfg_constants=>c_cts_operation-e_create. + ELSE. + lv_operation = if_wdr_cfg_constants=>c_cts_operation-e_save. + ENDIF. + + " First call, check, second call, create/save + DO 2 TIMES. + lo_cfg->do_next_step( + IMPORTING + e_messages = lt_messages + CHANGING + c_operation = lv_operation ). + check( lt_messages ). + ENDDO. + + CATCH cx_wd_configuration INTO lx_err. + zcx_abapgit_exception=>raise( 'WDCA, save error:' && lx_err->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA ls_key TYPE wdy_config_key. + + ls_key = ms_item-obj_name. + + SELECT SINGLE changedby FROM wdy_config_appl INTO rv_user + WHERE config_id = ls_key-config_id AND config_type = ls_key-config_type AND config_var = ls_key-config_var. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + delete( iv_package = iv_package + iv_transport = iv_transport ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_outline TYPE wdy_cfg_outline_data, + lt_data TYPE wdy_cfg_persist_data_appl_tab, + lt_config_appt TYPE TABLE OF wdy_config_appt, + lv_xml_string TYPE string, + lv_xml_xstring TYPE xstring. + + io_xml->read( EXPORTING iv_name = 'OUTLINE' + CHANGING cg_data = ls_outline ). + io_xml->read( EXPORTING iv_name = 'DATA' + CHANGING cg_data = lt_data ). + + save( is_outline = ls_outline + it_data = lt_data + iv_package = iv_package + iv_transport = iv_transport ). + + TRY. + lv_xml_string = mo_files->read_string( + iv_extra = 'appl_config' + iv_ext = 'xml' ). + + TRY. + lv_xml_string = zcl_abapgit_xml_pretty=>print( iv_xml = lv_xml_string + iv_ignore_errors = abap_false + iv_unpretty = abap_true ). + CATCH zcx_abapgit_exception. + zcx_abapgit_exception=>raise( 'Error Un-Pretty Printing WDCA XML Content: ' && ms_item-obj_name ). + ENDTRY. + + REPLACE FIRST OCCURRENCE + OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' + IN lv_xml_string + WITH ''. + ASSERT sy-subrc = 0. + + lv_xml_xstring = zcl_abapgit_convert=>string_to_xstring( lv_xml_string ). + UPDATE wdy_config_appl + SET xcontent = lv_xml_xstring + WHERE config_id = ls_outline-config_id + AND config_type = ls_outline-config_type + AND config_var = ls_outline-config_var. + CATCH zcx_abapgit_exception ##NO_HANDLER. + " File not found + ENDTRY. + io_xml->read( EXPORTING iv_name = 'DESCR_LANG' + CHANGING cg_data = lt_config_appt ). + + IF lt_config_appt IS NOT INITIAL. + DELETE FROM wdy_config_appt + WHERE config_id = ls_outline-config_id + AND config_type = ls_outline-config_type + AND config_var = ls_outline-config_var. + MODIFY wdy_config_appt FROM TABLE lt_config_appt. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error Updating WDY_CONFIG_APPT for Component Config ' && ms_item-obj_name ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + DATA: ls_wdy_config_appl TYPE wdy_config_appl. + DATA: ls_wdy_config_key TYPE wdy_config_key. + + ls_wdy_config_key = ms_item-obj_name. + SELECT SINGLE * FROM wdy_config_appl + INTO ls_wdy_config_appl + WHERE config_id = ls_wdy_config_key-config_id + AND config_type = ls_wdy_config_key-config_type + AND config_var = ls_wdy_config_key-config_var. "#EC CI_GENBUFF + rv_bool = boolc( sy-subrc = 0 ). + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_outline TYPE wdy_cfg_outline_data, + lt_data TYPE wdy_cfg_persist_data_appl_tab, + lt_cc_text TYPE TABLE OF wdy_config_appt, + lv_xml_xstring TYPE xstring, + lv_xml_string TYPE string. + + read( IMPORTING es_outline = ls_outline + et_data = lt_data ). + + IF ls_outline IS INITIAL. + RETURN. + ENDIF. + + io_xml->add( iv_name = 'OUTLINE' + ig_data = ls_outline ). + io_xml->add( iv_name = 'DATA' + ig_data = lt_data ). + SELECT SINGLE xcontent + INTO lv_xml_xstring + FROM wdy_config_appl + WHERE config_id = ls_outline-config_id + AND config_type = ls_outline-config_type + AND config_var = ls_outline-config_var. + lv_xml_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xml_xstring ). + IF lv_xml_string IS NOT INITIAL. + TRY. + lv_xml_string = zcl_abapgit_xml_pretty=>print( + iv_xml = lv_xml_string + iv_ignore_errors = abap_false ). + CATCH zcx_abapgit_exception. + zcx_abapgit_exception=>raise( 'Error Pretty Printing WDCA XML Content: ' && ms_item-obj_name ). + ENDTRY. + + REPLACE FIRST OCCURRENCE + OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' + IN lv_xml_string + WITH ''. + ASSERT sy-subrc = 0. + ENDIF. + + mo_files->add_string( + iv_extra = 'appl_config' + iv_ext = 'xml' + iv_string = lv_xml_string ). + + SELECT * FROM wdy_config_appt INTO TABLE lt_cc_text + WHERE config_id = ls_outline-config_id + AND config_type = ls_outline-config_type + AND config_var = ls_outline-config_var + ORDER BY PRIMARY KEY. + IF lt_cc_text IS NOT INITIAL. + io_xml->add( iv_name = 'DESCR_LANG' + ig_data = lt_cc_text ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_wapa IMPLEMENTATION. + METHOD create_new_application. + + DATA: ls_item LIKE ms_item, + lv_objkey TYPE seu_objkey. + + cl_o2_api_application=>create_new( + EXPORTING + p_application_data = is_attributes + p_nodes = it_nodes + p_navgraph = it_navgraph + IMPORTING + p_application = ro_bsp + EXCEPTIONS + object_already_existing = 1 + object_just_created = 2 + not_authorized = 3 + undefined_name = 4 + author_not_existing = 5 + action_cancelled = 6 + error_occured = 7 + invalid_parameter = 8 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |WAPA - error from create_new: { sy-subrc }| ). + ENDIF. + + ro_bsp->save( ). + + ro_bsp->set_changeable( + p_changeable = abap_false + p_complete_application = abap_true ). + + ls_item-obj_type = 'WAPD'. + ls_item-obj_name = ms_item-obj_name. + zcl_abapgit_objects_activation=>add_item( ls_item ). + + lv_objkey = ls_item-obj_name. +* todo, hmm, the WAPD is not added to the worklist during activation + cl_o2_api_application=>activate( lv_objkey ). + ENDMETHOD. + METHOD create_new_page. + + cl_o2_api_pages=>create_new_page( + EXPORTING + p_pageattrs = is_page_attributes + IMPORTING + p_page = ro_page + EXCEPTIONS + object_already_exists = 1 + invalid_name = 2 + error_occured = 3 + o2appl_not_existing = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error { sy-subrc } from CL_O2_API_PAGES=>CREATE_NEW_PAGE| ). + ENDIF. + + ENDMETHOD. + METHOD delete_superfluous_pages. + + DATA: ls_pagekey TYPE o2pagkey. + FIELD-SYMBOLS: LIKE LINE OF it_local_pages. + + " delete local pages which doesn't exist remotely + LOOP AT it_local_pages ASSIGNING . + + READ TABLE it_remote_pages WITH KEY attributes-pagekey = -pagekey + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + " page exists locally but not remotely -> delete + + ls_pagekey-applname = -applname. + ls_pagekey-pagekey = -pagekey. + + cl_o2_page=>delete_page_for_application( + EXPORTING + p_pagekey = ls_pagekey + EXCEPTIONS + object_not_existing = 1 + error_occured = 2 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error { sy-subrc } from CL_O2_PAGE=>DELETE_PAGE_FOR_APPLICATION| ). + ENDIF. + + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD get_page_content. + + DATA: lt_content TYPE o2pageline_table, + lv_string TYPE string. + + io_page->get_page( + IMPORTING + p_content = lt_content + EXCEPTIONS + invalid_call = 1 + page_deleted = 2 + OTHERS = 3 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |WAPA - error from get_page_content| ). + ENDIF. + + CONCATENATE LINES OF lt_content INTO lv_string SEPARATED BY cl_abap_char_utilities=>newline RESPECTING BLANKS. + + rv_content = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). + + ENDMETHOD. + METHOD read_page. + + DATA: lv_name TYPE o2applname, + ls_pagekey TYPE o2pagkey, + lv_content TYPE xstring, + lv_extra TYPE string, + lv_ext TYPE string, + lo_page TYPE REF TO cl_o2_api_pages. + lv_name = ms_item-obj_name. + + ls_pagekey-applname = lv_name. + ls_pagekey-pagekey = is_page-pagekey. + + cl_o2_api_pages=>load( + EXPORTING + p_pagekey = ls_pagekey + IMPORTING + p_page = lo_page ). + + lo_page->get_attrs( IMPORTING p_attrs = rs_page-attributes ). + + IF rs_page-attributes-pagetype <> so2_controller. + + lo_page->get_event_handlers( + IMPORTING + p_ev_handler = rs_page-event_handlers + EXCEPTIONS + page_deleted = 1 + invalid_call = 2 ). + ASSERT sy-subrc = 0. + + lo_page->get_parameters( + IMPORTING + p_parameters = rs_page-parameters + EXCEPTIONS + page_deleted = 1 + invalid_call = 2 + OTHERS = 3 ). + ASSERT sy-subrc = 0. + + lo_page->get_type_source( + IMPORTING + p_source = rs_page-types + EXCEPTIONS + page_deleted = 1 + invalid_call = 2 + OTHERS = 3 ). + ASSERT sy-subrc = 0. + + lv_content = get_page_content( lo_page ). + SPLIT is_page-pagename AT '.' INTO lv_extra lv_ext. + REPLACE ALL OCCURRENCES OF '/' IN lv_ext WITH '_-'. + REPLACE ALL OCCURRENCES OF '/' IN lv_extra WITH '_-'. + IF iv_no_files_add = abap_false. + mo_files->add_raw( + iv_extra = lv_extra + iv_ext = lv_ext + iv_data = lv_content ). + ENDIF. + + CLEAR: rs_page-attributes-implclass. + + ENDIF. + + CLEAR: rs_page-attributes-author, + rs_page-attributes-createdon, + rs_page-attributes-changedby, + rs_page-attributes-changedon, + rs_page-attributes-changetime, + rs_page-attributes-gendate, + rs_page-attributes-gentime, + rs_page-attributes-devclass. + + ENDMETHOD. + METHOD to_page_content. + + DATA: lv_string TYPE string. + lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( iv_content ). + + SPLIT lv_string AT cl_abap_char_utilities=>newline INTO TABLE rt_content. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_name TYPE o2applname, + lt_pages TYPE STANDARD TABLE OF o2pagdir WITH DEFAULT KEY, + ls_latest LIKE LINE OF lt_pages. + lv_name = ms_item-obj_name. + + SELECT * FROM o2pagdir INTO TABLE lt_pages WHERE applname = lv_name + ORDER BY changedon DESCENDING changetime DESCENDING. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + RETURN. + ENDIF. + + READ TABLE lt_pages INDEX 1 INTO ls_latest. + ASSERT sy-subrc = 0. + + rv_user = ls_latest-changedby. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_name TYPE o2applname, + lo_bsp TYPE REF TO cl_o2_api_application, + ls_pagekey TYPE o2pagkey, + lv_object TYPE seu_objkey, + lt_pages TYPE o2pagelist, + lt_local_mimes TYPE o2pagename_table. + + FIELD-SYMBOLS: LIKE LINE OF lt_pages, + TYPE o2pagename. + + lv_name = ms_item-obj_name. + + cl_o2_api_application=>load( + EXPORTING + p_application_name = lv_name + IMPORTING + p_application = lo_bsp + EXCEPTIONS + object_not_existing = 1 + permission_failure = 2 + error_occured = 3 ). + ASSERT sy-subrc = 0. + + lo_bsp->set_changeable( + p_changeable = abap_true + p_complete_application = abap_true ). + + cl_o2_api_pages=>get_all_pages( + EXPORTING + p_applname = lv_name + p_version = c_active + IMPORTING + p_pages = lt_pages ). + + LOOP AT lt_pages ASSIGNING . + CLEAR ls_pagekey. + ls_pagekey-applname = lv_name. + ls_pagekey-pagekey = -pagekey. + + cl_o2_page=>delete_page_for_application( + EXPORTING + p_pagekey = ls_pagekey + EXCEPTIONS + object_not_existing = 1 + error_occured = 2 ). + ASSERT sy-subrc = 0. + ENDLOOP. + + lo_bsp->get_local_mimes( + IMPORTING + p_local_mimes = lt_local_mimes + EXCEPTIONS + object_invalid = 1 + object_deleted = 2 + error_occured = 3 + OTHERS = 4 ). + + LOOP AT lt_local_mimes ASSIGNING . + CLEAR ls_pagekey. + ls_pagekey-applname = -applname. + ls_pagekey-pagekey = -pagekey. + + cl_o2_page=>delete_page_for_application( + EXPORTING + p_pagekey = ls_pagekey + EXCEPTIONS + object_not_existing = 1 + error_occured = 2 ). + ASSERT sy-subrc = 0. + ENDLOOP. + + lo_bsp->delete( + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + action_cancelled = 4 + permission_failure = 5 + error_occured = 6 + OTHERS = 7 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |WAPA - error from delete: { sy-subrc }| ). + ENDIF. + +* release lock + lv_object = lv_name. + cl_o2_api_application=>call_access_permission( + p_mode = 'FREE' + p_object = lv_object + p_complete_application = abap_true ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lo_bsp TYPE REF TO cl_o2_api_application, + ls_attributes TYPE o2applattr, + lt_nodes TYPE o2applnode_table, + lt_navgraph TYPE o2applgrap_table, + lv_obj_name TYPE string, + lv_extra TYPE string, + lv_ext TYPE string, + lo_page TYPE REF TO cl_o2_api_pages, + lt_pages_info TYPE ty_pages_tt, + ls_pagekey TYPE o2pagkey, + ls_local_page TYPE ty_page, + lt_remote_content TYPE o2pageline_table, + lt_local_content TYPE o2pageline_table, + lt_local_pages TYPE o2pagelist. + + FIELD-SYMBOLS: LIKE LINE OF lt_pages_info. + + io_xml->read( EXPORTING iv_name = 'ATTRIBUTES' + CHANGING cg_data = ls_attributes ). + io_xml->read( EXPORTING iv_name = 'NAVGRAPH' + CHANGING cg_data = lt_navgraph ). + io_xml->read( EXPORTING iv_name = 'PAGES' + CHANGING cg_data = lt_pages_info ). + + ls_attributes-devclass = iv_package. + + cl_o2_api_application=>load( + EXPORTING + p_application_name = ls_attributes-applname " Application Name + IMPORTING + p_application = lo_bsp " Instance Created + EXCEPTIONS + object_not_existing = 1 + permission_failure = 2 + error_occured = 3 + OTHERS = 4 ). + + CASE sy-subrc. + WHEN 0. + + cl_o2_api_pages=>get_all_pages( + EXPORTING + p_applname = ls_attributes-applname + p_version = c_active + IMPORTING + p_pages = lt_local_pages ). + + WHEN 1. + + lo_bsp = create_new_application( is_attributes = ls_attributes + it_nodes = lt_nodes + it_navgraph = lt_navgraph ). + + WHEN OTHERS. + + zcx_abapgit_exception=>raise( |Error { sy-subrc } from CL_O2_API_APPLICATION=>LOAD| ). + + ENDCASE. + + LOOP AT lt_pages_info ASSIGNING . + + ls_pagekey-applname = -attributes-applname. + ls_pagekey-pagekey = -attributes-pagekey. + + cl_o2_api_pages=>load( + EXPORTING + p_pagekey = ls_pagekey + IMPORTING + p_page = lo_page + EXCEPTIONS + object_not_existing = 1 + version_not_existing = 2 + OTHERS = 3 ). + + CASE sy-subrc. + WHEN 0. + + ls_local_page = read_page( is_page = -attributes + iv_no_files_add = abap_true ). + + WHEN 1. + + lo_page = create_new_page( -attributes ). + + WHEN 2. + + " Do nothing... + + WHEN OTHERS. + + zcx_abapgit_exception=>raise( |Error { sy-subrc } from CL_O2_API_PAGES=>LOAD| ). + + ENDCASE. + + SPLIT -attributes-pagename AT '.' INTO lv_extra lv_ext. + REPLACE ALL OCCURRENCES OF '/' IN lv_extra WITH '_-'. + REPLACE ALL OCCURRENCES OF '/' IN lv_ext WITH '_-'. + + lt_remote_content = to_page_content( mo_files->read_raw( iv_extra = lv_extra + iv_ext = lv_ext ) ). + lt_local_content = to_page_content( get_page_content( lo_page ) ). + + IF ls_local_page = AND lt_local_content = lt_remote_content. + " no changes -> nothing to do + CONTINUE. + ENDIF. + + IF -attributes-pagetype <> so2_controller. + + lo_page->set_page( lt_remote_content ). + + lo_page->set_event_handlers( -event_handlers ). + lo_page->set_parameters( -parameters ). + lo_page->set_type_source( -types ). + + ENDIF. + + lo_page->save( p_with_all_texts = abap_true ). + + lv_obj_name = cl_wb_object_type=>get_concatenated_key_from_id( + p_key_component1 = -attributes-applname + p_key_component2 = -attributes-pagekey + p_external_id = 'WG ' ). + + zcl_abapgit_objects_activation=>add( iv_type = 'WAPP' + iv_name = lv_obj_name ). + + ENDLOOP. + + delete_superfluous_pages( it_local_pages = lt_local_pages + it_remote_pages = lt_pages_info ). + + zcl_abapgit_sotr_handler=>create_sotr( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_name TYPE o2applname. + lv_name = ms_item-obj_name. + + cl_o2_api_application=>load( + EXPORTING + p_application_name = lv_name + EXCEPTIONS + object_not_existing = 1 + permission_failure = 2 + error_occured = 3 ). + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_name TYPE o2applname, + ls_attributes TYPE o2applattr, + lt_navgraph TYPE o2applgrap_table, + lt_pages TYPE o2pagelist, + lt_pages_info TYPE ty_pages_tt, + lo_bsp TYPE REF TO cl_o2_api_application. + + FIELD-SYMBOLS: LIKE LINE OF lt_pages. + + lv_name = ms_item-obj_name. + + cl_o2_api_application=>load( + EXPORTING + p_application_name = lv_name + IMPORTING + p_application = lo_bsp + EXCEPTIONS + object_not_existing = 1 + permission_failure = 2 + error_occured = 3 ). + IF sy-subrc <> 0. + RETURN. + ENDIF. + + lo_bsp->get_attributes( + EXPORTING + p_version = c_active + IMPORTING + p_attributes = ls_attributes ). + + CLEAR: ls_attributes-author, + ls_attributes-createdon, + ls_attributes-changedby, + ls_attributes-changedon, + ls_attributes-devclass. + + io_xml->add( iv_name = 'ATTRIBUTES' + ig_data = ls_attributes ). + + lo_bsp->get_navgraph( + EXPORTING + p_version = c_active + IMPORTING + p_navgraph = lt_navgraph ). + + io_xml->add( iv_name = 'NAVGRAPH' + ig_data = lt_navgraph ). + + cl_o2_api_pages=>get_all_pages( + EXPORTING + p_applname = lv_name + p_version = c_active + IMPORTING + p_pages = lt_pages ). + + LOOP AT lt_pages ASSIGNING . + APPEND read_page( ) TO lt_pages_info. + ENDLOOP. + + io_xml->add( iv_name = 'PAGES' + ig_data = lt_pages_info ). + + zcl_abapgit_sotr_handler=>read_sotr( + iv_pgmid = 'LIMU' + iv_object = 'WAPP' + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + io_xml = io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_w3xx_super IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + ms_key-relid = ms_item-obj_type+2(2). + ms_key-objid = ms_item-obj_name. + + ENDMETHOD. + METHOD find_param. + + FIELD-SYMBOLS LIKE LINE OF it_params. + READ TABLE it_params ASSIGNING WITH KEY name = iv_name. + IF sy-subrc > 0. + zcx_abapgit_exception=>raise( |W3xx: Cannot find { iv_name } for { ms_key-objid }| ). + ENDIF. + + rv_value = -value. + + ENDMETHOD. + METHOD get_ext. + + rv_ext = find_param( it_params = it_params + iv_name = c_param_names-fileext ). + SHIFT rv_ext LEFT DELETING LEADING '.'. + + ENDMETHOD. + METHOD normalize_params. + + FIELD-SYMBOLS LIKE LINE OF ct_params. + + " Ensure filesize param exists + READ TABLE ct_params ASSIGNING WITH KEY name = c_param_names-filesize. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO ct_params ASSIGNING . + -name = c_param_names-filesize. + ENDIF. + + LOOP AT ct_params ASSIGNING . + -relid = ms_key-relid. " Ensure param key = object key + -objid = ms_key-objid. + IF -name = c_param_names-filesize. " Patch filesize = real file size + -value = iv_size. + CONDENSE -value. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD strip_params. + + FIELD-SYMBOLS LIKE LINE OF ct_params. + + " Remove path from filename + find_param( it_params = ct_params + iv_name = c_param_names-filename ). " Check exists + READ TABLE ct_params ASSIGNING WITH KEY name = c_param_names-filename. + -value = zcl_abapgit_path=>get_filename_from_syspath( |{ -value }| ). + + " Clear id and object name + LOOP AT ct_params ASSIGNING . + CLEAR: -relid, -objid. + ENDLOOP. + + " Clear version & filesize + DELETE ct_params WHERE name = c_param_names-version. + DELETE ct_params WHERE name = c_param_names-filesize. + + " Avoid diffs due to different order + SORT ct_params. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE chname INTO rv_user + FROM wwwdata + WHERE relid = ms_key-relid + AND objid = ms_key-objid + AND srtf2 = 0. + + IF sy-subrc IS NOT INITIAL OR rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + CALL FUNCTION 'WWWDATA_DELETE' + EXPORTING + key = ms_key + EXCEPTIONS + wrong_object_type = 1 + delete_error = 2. + + IF sy-subrc IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'Cannot delete W3xx data' ). + ENDIF. + + CALL FUNCTION 'WWWPARAMS_DELETE_ALL' + EXPORTING + key = ms_key + EXCEPTIONS + delete_error = 1. + + IF sy-subrc IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'Cannot delete W3xx params' ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA lv_base64str TYPE string. + DATA lt_w3params TYPE STANDARD TABLE OF wwwparams. + DATA lv_xstring TYPE xstring. + DATA lt_w3mime TYPE STANDARD TABLE OF w3mime. + DATA lt_w3html TYPE STANDARD TABLE OF w3html. + DATA lv_size TYPE i. + io_xml->read( EXPORTING iv_name = 'TEXT' + CHANGING cg_data = ms_key-text ). + + io_xml->read( EXPORTING iv_name = 'PARAMS' + CHANGING cg_data = lt_w3params ). + + CASE io_xml->get_metadata( )-version. + WHEN 'v1.0.0'. + io_xml->read( EXPORTING iv_name = 'DATA' + CHANGING cg_data = lv_base64str ). + lv_xstring = cl_http_utility=>decode_x_base64( lv_base64str ). + WHEN 'v2.0.0'. + lv_xstring = mo_files->read_raw( iv_extra = 'data' + iv_ext = get_ext( lt_w3params ) ). + WHEN OTHERS. + zcx_abapgit_exception=>raise( 'W3xx: Unknown serializer version' ). + ENDCASE. + + CASE ms_key-relid. + WHEN 'MI'. + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_xstring + IMPORTING + output_length = lv_size + TABLES + binary_tab = lt_w3mime. + WHEN 'HT'. + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_xstring + IMPORTING + output_length = lv_size + TABLES + binary_tab = lt_w3mime. + + CALL FUNCTION 'SCMS_BINARY_TO_TEXT' + EXPORTING + input_length = lv_size + IMPORTING + output_length = lv_size + TABLES + binary_tab = lt_w3mime + text_tab = lt_w3html + EXCEPTIONS + failed = 1. + IF sy-subrc IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'Cannot update W3xx params' ). + ENDIF. + + CLEAR lt_w3mime. + WHEN OTHERS. + zcx_abapgit_exception=>raise( 'Wrong W3xx type' ). + ENDCASE. + + " Update size of file based on actual data file size, prove param object name + normalize_params( EXPORTING iv_size = lv_size + CHANGING ct_params = lt_w3params ). + + CALL FUNCTION 'WWWPARAMS_UPDATE' + TABLES + params = lt_w3params + EXCEPTIONS + update_error = 1. + + IF sy-subrc IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'Cannot update W3xx params' ). + ENDIF. + + ms_key-tdate = sy-datum. + ms_key-ttime = sy-uzeit. + ms_key-chname = sy-uname. + ms_key-devclass = iv_package. + + CALL FUNCTION 'WWWDATA_EXPORT' + EXPORTING + key = ms_key + TABLES + mime = lt_w3mime + html = lt_w3html + EXCEPTIONS + wrong_object_type = 1 + export_error = 2. + + IF sy-subrc IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'Cannot upload W3xx data' ). + ENDIF. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + SELECT SINGLE objid INTO ms_key-objid + FROM wwwdata + WHERE relid = ms_key-relid + AND objid = ms_key-objid + AND srtf2 = 0. + + IF sy-subrc IS NOT INITIAL. + RETURN. + ENDIF. + + rv_bool = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + rs_metadata-version = 'v2.0.0'. " Serialization v2, separate data file + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_object TYPE eqegraarg. + + lv_object = |{ ms_item-obj_type+2(2) }{ ms_item-obj_name }|. + OVERLAY lv_object WITH ' '. + lv_object = lv_object && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_WWW_HTML' + iv_argument = lv_object ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_bdcdata TYPE bdcdata, + lt_bdcdata TYPE ty_bdcdata. + + ls_bdcdata-program = 'SAPMWWW0'. + ls_bdcdata-dynpro = '0100'. + ls_bdcdata-dynbegin = 'X'. + APPEND ls_bdcdata TO lt_bdcdata. + + change_bdc_jump_data( CHANGING ct_bdcdata = lt_bdcdata ). + + CLEAR ls_bdcdata. + ls_bdcdata-fnam = 'BDC_OKCODE'. + ls_bdcdata-fval = '=CRO1'. + APPEND ls_bdcdata TO lt_bdcdata. + + ls_bdcdata-program = 'RSWWWSHW'. + ls_bdcdata-dynpro = '1000'. + ls_bdcdata-dynbegin = 'X'. + APPEND ls_bdcdata TO lt_bdcdata. + + CLEAR ls_bdcdata. + ls_bdcdata-fnam = 'SO_OBJID-LOW'. + ls_bdcdata-fval = ms_item-obj_name. + APPEND ls_bdcdata TO lt_bdcdata. + + CLEAR ls_bdcdata. + ls_bdcdata-fnam = 'BDC_OKCODE'. + ls_bdcdata-fval = '=ONLI'. + APPEND ls_bdcdata TO lt_bdcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SMW0' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA lt_w3mime TYPE STANDARD TABLE OF w3mime. + DATA lt_w3html TYPE STANDARD TABLE OF w3html. + DATA lt_w3params TYPE STANDARD TABLE OF wwwparams. + DATA lv_xstring TYPE xstring. + DATA lv_size TYPE i. + + SELECT SINGLE * INTO CORRESPONDING FIELDS OF ms_key + FROM wwwdata + WHERE relid = ms_key-relid + AND objid = ms_key-objid + AND srtf2 = 0. + + IF sy-subrc IS NOT INITIAL. + RETURN. + ENDIF. + + CALL FUNCTION 'WWWDATA_IMPORT' + EXPORTING + key = ms_key + TABLES + mime = lt_w3mime + html = lt_w3html + EXCEPTIONS + wrong_object_type = 1 + import_error = 2. + + IF sy-subrc IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'Cannot read W3xx data' ). + ENDIF. + + CALL FUNCTION 'WWWPARAMS_READ_ALL' + EXPORTING + type = ms_key-relid + objid = ms_key-objid + TABLES + params = lt_w3params + EXCEPTIONS + entry_not_exists = 1. + + IF sy-subrc IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'Cannot read W3xx data' ). + ENDIF. + + lv_size = find_param( it_params = lt_w3params + iv_name = c_param_names-filesize ). + " Clean params (remove version, filesize & clear filename from path) + strip_params( CHANGING ct_params = lt_w3params ). + + CASE ms_key-relid. + WHEN 'MI'. + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_size + IMPORTING + buffer = lv_xstring + TABLES + binary_tab = lt_w3mime + EXCEPTIONS + failed = 1. + WHEN 'HT'. + CALL FUNCTION 'SCMS_TEXT_TO_XSTRING' + IMPORTING + buffer = lv_xstring + TABLES + text_tab = lt_w3html + EXCEPTIONS + failed = 1. + WHEN OTHERS. + zcx_abapgit_exception=>raise( 'Wrong W3xx type' ). + ENDCASE. + + IF sy-subrc IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'Cannot convert W3xx to xstring' ). + ENDIF. + + io_xml->add( iv_name = 'NAME' + ig_data = ms_key-objid ). + + io_xml->add( iv_name = 'TEXT' + ig_data = ms_key-text ). + + SORT lt_w3params. + + io_xml->add( iv_name = 'PARAMS' + ig_data = lt_w3params ). + + " Serialization v2, separate data file. 'extra' added to prevent conflict with .xml + mo_files->add_raw( iv_data = lv_xstring + iv_extra = 'data' + iv_ext = get_ext( lt_w3params ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_w3mi IMPLEMENTATION. + METHOD change_bdc_jump_data. + + DATA: ls_bdcdata LIKE LINE OF ct_bdcdata. + + ls_bdcdata-fnam = 'RADIO_HT'. + ls_bdcdata-fval = ' '. + APPEND ls_bdcdata TO ct_bdcdata. + + CLEAR ls_bdcdata. + ls_bdcdata-fnam = 'RADIO_MI'. + ls_bdcdata-fval = 'X'. + APPEND ls_bdcdata TO ct_bdcdata. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_w3ht IMPLEMENTATION. + METHOD change_bdc_jump_data. + + DATA: ls_bdcdata LIKE LINE OF ct_bdcdata. + + ls_bdcdata-fnam = 'RADIO_HT'. + ls_bdcdata-fval = 'X'. + APPEND ls_bdcdata TO ct_bdcdata. + + CLEAR ls_bdcdata. + ls_bdcdata-fnam = 'RADIO_MI'. + ls_bdcdata-fval = ' '. + APPEND ls_bdcdata TO ct_bdcdata. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_view IMPLEMENTATION. + METHOD delete_extras. + + DELETE FROM tddat WHERE tabname = iv_name. + + insert_transport( + iv_name = iv_name + iv_transport = iv_transport ). + + ENDMETHOD. + METHOD deserialize_texts. + + DATA: + lv_name TYPE ddobjname, + lt_i18n_langs TYPE TABLE OF langu, + lt_dd25_texts TYPE ty_dd25_texts, + ls_dd25v_tmp TYPE dd25v. + + FIELD-SYMBOLS: + TYPE langu, + LIKE LINE OF lt_dd25_texts. + + lv_name = ms_item-obj_name. + + ii_xml->read( EXPORTING iv_name = 'I18N_LANGS' + CHANGING cg_data = lt_i18n_langs ). + + ii_xml->read( EXPORTING iv_name = 'DD25_TEXTS' + CHANGING cg_data = lt_dd25_texts ). + + mo_i18n_params->trim_saplang_list( CHANGING ct_sap_langs = lt_i18n_langs ). + + SORT lt_i18n_langs. + SORT lt_dd25_texts BY ddlanguage. + + LOOP AT lt_i18n_langs ASSIGNING . + + " View description + ls_dd25v_tmp = is_dd25v. + READ TABLE lt_dd25_texts ASSIGNING WITH KEY ddlanguage = . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |DD25_TEXTS cannot find lang { } in XML| ). + ENDIF. + MOVE-CORRESPONDING TO ls_dd25v_tmp. + CALL FUNCTION 'DDIF_VIEW_PUT' + EXPORTING + name = lv_name + dd25v_wa = ls_dd25v_tmp + EXCEPTIONS + view_not_found = 1 + name_inconsistent = 2 + view_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD insert_transport. + + DATA: + ls_key TYPE tddat, + lt_keys TYPE TABLE OF tddat. + + IF iv_transport IS INITIAL. + RETURN. + ENDIF. + + ls_key-tabname = iv_name. + INSERT ls_key INTO TABLE lt_keys. + + zcl_abapgit_factory=>get_cts_api( )->create_transport_entries( + iv_transport = iv_transport + it_table_ins = lt_keys + iv_tabname = 'TDDAT' ). + + ENDMETHOD. + METHOD read_extras. + + SELECT SINGLE * FROM tddat INTO rs_tabl_extras-tddat WHERE tabname = iv_name. + + " Fields that are not part of dd25v + TRY. + SELECT SINGLE abap_language_version FROM ('DD25L') INTO CORRESPONDING FIELDS OF rs_tabl_extras + WHERE viewname = iv_name AND as4local = 'A' AND as4vers = '0000'. + IF sy-subrc = 0. + clear_abap_language_version( CHANGING cv_abap_language_version = rs_tabl_extras-abap_language_version ). + ENDIF. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD read_view. + + DATA: lv_name TYPE ddobjname. + + lv_name = ms_item-obj_name. + + CALL FUNCTION 'DDIF_VIEW_GET' + EXPORTING + name = lv_name + state = 'A' + langu = iv_language + IMPORTING + gotstate = ev_state + dd25v_wa = es_dd25v + dd09l_wa = es_dd09l + TABLES + dd26v_tab = et_dd26v + dd27p_tab = et_dd27p + dd28j_tab = et_dd28j + dd28v_tab = et_dd28v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + es_extras = read_extras( lv_name ). + + ENDMETHOD. + METHOD serialize_texts. + + DATA: + lv_index TYPE i, + ls_dd25v TYPE dd25v, + lt_dd25_texts TYPE ty_dd25_texts, + lt_i18n_langs TYPE TABLE OF langu, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + FIELD-SYMBOLS: + LIKE LINE OF lt_i18n_langs, + LIKE LINE OF lt_dd25_texts. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + " Collect additional languages, skip main lang - it was serialized already + lt_language_filter = mo_i18n_params->build_language_filter( ). + + SELECT DISTINCT ddlanguage AS langu INTO TABLE lt_i18n_langs + FROM dd25v + WHERE viewname = ms_item-obj_name + AND ddlanguage IN lt_language_filter + AND ddlanguage <> mv_language + ORDER BY langu. "#EC CI_SUBRC + + LOOP AT lt_i18n_langs ASSIGNING . + lv_index = sy-tabix. + CLEAR: ls_dd25v. + + TRY. + read_view( + EXPORTING + iv_language = + IMPORTING + es_dd25v = ls_dd25v ). + + CATCH zcx_abapgit_exception. + CONTINUE. + ENDTRY. + + IF ls_dd25v-ddlanguage IS INITIAL. + DELETE lt_i18n_langs INDEX lv_index. " Don't save this lang + CONTINUE. + ENDIF. + + APPEND INITIAL LINE TO lt_dd25_texts ASSIGNING . + MOVE-CORRESPONDING ls_dd25v TO . + + ENDLOOP. + + SORT lt_i18n_langs ASCENDING. + SORT lt_dd25_texts BY ddlanguage ASCENDING. + + IF lines( lt_i18n_langs ) > 0. + ii_xml->add( iv_name = 'I18N_LANGS' + ig_data = lt_i18n_langs ). + + ii_xml->add( iv_name = 'DD25_TEXTS' + ig_data = lt_dd25_texts ). + ENDIF. + + ENDMETHOD. + METHOD update_extras. + + DATA lv_abap_language_version TYPE uccheck. + + IF is_tabl_extras-tddat IS INITIAL. + delete_extras( + iv_name = iv_name + iv_transport = iv_transport ). + ELSE. + MODIFY tddat FROM is_tabl_extras-tddat. + + insert_transport( + iv_name = iv_name + iv_transport = iv_transport ). + ENDIF. + + " Fields that are not part of dd25v + TRY. + lv_abap_language_version = is_tabl_extras-abap_language_version. + + set_abap_language_version( CHANGING cv_abap_language_version = lv_abap_language_version ). + + UPDATE ('DD25L') SET abap_language_version = lv_abap_language_version WHERE viewname = iv_name. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE as4user FROM dd25l INTO rv_user + WHERE viewname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA lv_objname TYPE rsedd0-ddobjname. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + lv_objname = ms_item-obj_name. + delete_ddic( 'V' ). + + delete_extras( + iv_name = lv_objname + iv_transport = iv_transport ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_name TYPE ddobjname, + ls_dd25v TYPE dd25v, + ls_dd09l TYPE dd09l, + lt_dd26v TYPE TABLE OF dd26v, + lt_dd27p TYPE TABLE OF dd27p, + lt_dd28j TYPE TABLE OF dd28j, + lt_dd28v TYPE TABLE OF dd28v, + ls_extras TYPE zif_abapgit_object_tabl=>ty_internal-extras. + + FIELD-SYMBOLS: LIKE LINE OF lt_dd27p. + + io_xml->read( EXPORTING iv_name = 'DD25V' + CHANGING cg_data = ls_dd25v ). + io_xml->read( EXPORTING iv_name = 'DD09L' + CHANGING cg_data = ls_dd09l ). + io_xml->read( EXPORTING iv_name = 'DD26V_TABLE' + CHANGING cg_data = lt_dd26v ). + io_xml->read( EXPORTING iv_name = 'DD27P_TABLE' + CHANGING cg_data = lt_dd27p ). + io_xml->read( EXPORTING iv_name = 'DD28J_TABLE' + CHANGING cg_data = lt_dd28j ). + io_xml->read( EXPORTING iv_name = 'DD28V_TABLE' + CHANGING cg_data = lt_dd28v ). + io_xml->read( EXPORTING iv_name = zif_abapgit_object_tabl=>c_s_dataname-tabl_extras + CHANGING cg_data = ls_extras ). + + lv_name = ms_item-obj_name. " type conversion + + IF iv_step = zif_abapgit_object=>gc_step_id-ddic. + + LOOP AT lt_dd27p ASSIGNING . + -objpos = sy-tabix. + -viewname = lv_name. + " rollname seems to be mandatory in the API, but is typically not defined in the VIEW + SELECT SINGLE rollname FROM dd03l INTO -rollname + WHERE tabname = -tabname + AND fieldname = -fieldname. + IF -rollnamevi IS INITIAL. + -rollnamevi = -rollname. + ENDIF. + ENDLOOP. + + corr_insert( iv_package = iv_package + ig_object_class = 'DICT' ). + + CALL FUNCTION 'DDIF_VIEW_PUT' + EXPORTING + name = lv_name + dd25v_wa = ls_dd25v + dd09l_wa = ls_dd09l + TABLES + dd26v_tab = lt_dd26v + dd27p_tab = lt_dd27p + dd28j_tab = lt_dd28j + dd28v_tab = lt_dd28v + EXCEPTIONS + view_not_found = 1 + name_inconsistent = 2 + view_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + deserialize_texts( + ii_xml = io_xml + is_dd25v = ls_dd25v ). + ENDIF. + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_view ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ELSE. + " Late update after activation because activation removes ABAP Language Version (in lower releases?) + update_extras( iv_name = lv_name + iv_transport = iv_transport + is_tabl_extras = ls_extras ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_viewname TYPE dd25l-viewname, + lv_ddl_view TYPE abap_bool. + + SELECT SINGLE viewname FROM dd25l INTO lv_viewname + WHERE viewname = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + IF rv_bool = abap_true. + TRY. + CALL METHOD ('CL_DD_DDL_UTILITIES')=>('CHECK_FOR_DDL_VIEW') + EXPORTING + objname = lv_viewname + RECEIVING + is_ddl_view = lv_ddl_view. + + IF lv_ddl_view = abap_true. + rv_bool = abap_false. + ENDIF. + CATCH cx_root ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECT=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_dd25v TYPE dd25v, + lv_state TYPE ddgotstate, + ls_dd09l TYPE dd09l, + lt_dd26v TYPE ty_dd26v, + lt_dd27p TYPE ty_dd27p, + lt_dd28j TYPE ty_dd28j, + lt_dd28v TYPE ty_dd28v, + ls_extras TYPE zif_abapgit_object_tabl=>ty_tabl_extras. + + FIELD-SYMBOLS: LIKE LINE OF lt_dd27p. + FIELD-SYMBOLS TYPE any. + + read_view( + EXPORTING + iv_language = mv_language + IMPORTING + ev_state = lv_state + es_dd25v = ls_dd25v + es_dd09l = ls_dd09l + et_dd26v = lt_dd26v + et_dd27p = lt_dd27p + et_dd28j = lt_dd28j + et_dd28v = lt_dd28v + es_extras = ls_extras ). + + IF ls_dd25v IS INITIAL OR lv_state <> 'A'. + RETURN. + ENDIF. + + CLEAR: ls_dd25v-as4user, + ls_dd25v-as4date, + ls_dd25v-as4time. + + ASSIGN COMPONENT 'ACTFLAG' OF STRUCTURE ls_dd25v TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + CLEAR: ls_dd09l-as4user, + ls_dd09l-as4date, + ls_dd09l-as4time. + + LOOP AT lt_dd27p ASSIGNING . + CLEAR: -ddtext, + -reptext, + -scrtext_s, + -scrtext_m, + -scrtext_l, + -outputlen, + -decimals, + -lowercase, + -convexit, + -signflag, + -flength, + -domname, + -datatype, + -entitytab, + -inttype, + -intlen, + -headlen, + -scrlen1, + -scrlen2, + -scrlen3, + -memoryid. + IF -rollchange = abap_false. + CLEAR -rollnamevi. + ENDIF. + CLEAR -ddlanguage. + CLEAR -rollname. + CLEAR -viewname. + CLEAR -objpos. + ENDLOOP. + + io_xml->add( iv_name = 'DD25V' + ig_data = ls_dd25v ). + io_xml->add( iv_name = 'DD09L' + ig_data = ls_dd09l ). + io_xml->add( ig_data = lt_dd26v + iv_name = 'DD26V_TABLE' ). + io_xml->add( ig_data = lt_dd27p + iv_name = 'DD27P_TABLE' ). + io_xml->add( ig_data = lt_dd28j + iv_name = 'DD28J_TABLE' ). + io_xml->add( ig_data = lt_dd28v + iv_name = 'DD28V_TABLE' ). + io_xml->add( iv_name = zif_abapgit_object_tabl=>c_s_dataname-tabl_extras + ig_data = ls_extras ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + serialize_texts( io_xml ). + ENDIF. + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_view ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_vcls IMPLEMENTATION. + METHOD is_locked. + + DATA: + ls_rstable_key TYPE rstable, " Lock argument for table RSTABLE + lv_argument TYPE eqegraarg. + + " Set Values for generic table lock + ls_rstable_key-tabname = iv_tabname. + ls_rstable_key-varkey = iv_argument. + + " include all sub keys + lv_argument = ls_rstable_key. + lv_argument = lv_argument && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_TABLEE' + iv_argument = lv_argument ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + SELECT SINGLE author FROM vcldir INTO rv_user + WHERE vclname = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. +* Do the same as in VIEWCLUSTER_SAVE_DEFINITION + DATA: lv_vclname TYPE vcl_name. + lv_vclname = ms_item-obj_name. + + DELETE FROM vcldir WHERE vclname = lv_vclname. "#EC CI_SUBRC + DELETE FROM vcldirt WHERE vclname = lv_vclname. "#EC CI_NOFIRST "#EC CI_SUBRC + DELETE FROM vclstruc WHERE vclname = lv_vclname. "#EC CI_SUBRC + DELETE FROM vclstruct WHERE vclname = lv_vclname. "#EC CI_NOFIRST "#EC CI_SUBRC + DELETE FROM vclstrudep WHERE vclname = lv_vclname. "#EC CI_SUBRC + DELETE FROM vclmf WHERE vclname = lv_vclname. "#EC CI_SUBRC + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_vcldir_entry TYPE v_vcldir, + lt_vclstruc TYPE TABLE OF v_vclstruc, + lt_vclstrudep TYPE TABLE OF v_vclstdep, + lt_vclmf TYPE TABLE OF v_vclmf, + lv_objectname TYPE ob_object. + io_xml->read( EXPORTING iv_name = 'VCLDIR' + CHANGING cg_data = ls_vcldir_entry ). + io_xml->read( EXPORTING iv_name = 'VLCSTRUC_TAB' + CHANGING cg_data = lt_vclstruc ). + io_xml->read( EXPORTING iv_name = 'VCLSTRUDEP_TAB' + CHANGING cg_data = lt_vclstrudep ). + io_xml->read( EXPORTING iv_name = 'lt_vclstrudep' + CHANGING cg_data = lt_vclmf ). + + ls_vcldir_entry-author = sy-uname. + ls_vcldir_entry-changedate = sy-datum. + + CALL FUNCTION 'VIEWCLUSTER_SAVE_DEFINITION' + EXPORTING + vcldir_entry = ls_vcldir_entry + TABLES + vclstruc_tab = lt_vclstruc + vclstrudep_tab = lt_vclstrudep + vclmf_tab = lt_vclmf. + + corr_insert( iv_package ). + + lv_objectname = ls_vcldir_entry-vclname. + + CALL FUNCTION 'OBJ_GENERATE' + EXPORTING + iv_objectname = lv_objectname + iv_objecttype = c_cluster_type + iv_maint_mode = c_mode_insert + iv_devclass = iv_package + EXCEPTIONS + illegal_call = 1 + object_not_found = 2 + generate_error = 3 + transport_error = 4 + object_enqueue_failed = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA lv_changedate TYPE vcldir-changedate. + + SELECT SINGLE changedate INTO lv_changedate FROM vcldir + WHERE vclname = ms_item-obj_name. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + + DATA lv_changedate TYPE vcldir-changedate. + + SELECT SINGLE changedate INTO lv_changedate FROM vcldir + WHERE vclname = ms_item-obj_name. + +* see logic in function module VIEWCLUSTER_GET_DEFINITION + rv_active = boolc( lv_changedate IS NOT INITIAL ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: + lv_argument TYPE seqg3-garg, + lv_argument_langu TYPE seqg3-garg. + + lv_argument = ms_item-obj_name. + lv_argument_langu = |@{ ms_item-obj_name }|. + + "Check all relevant maintain tables for view clusters + IF is_locked( iv_tabname = 'VCLDIR' + iv_argument = lv_argument ) = abap_true + OR is_locked( iv_tabname = 'VCLDIRT' + iv_argument = lv_argument_langu ) = abap_true + OR is_locked( iv_tabname = 'VCLSTRUC' + iv_argument = lv_argument ) = abap_true + OR is_locked( iv_tabname = 'VCLSTRUCT' + iv_argument = lv_argument_langu ) = abap_true + OR is_locked( iv_tabname = 'VCLMF' + iv_argument = lv_argument ) = abap_true. + + rv_is_locked = abap_true. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_bcdata TYPE bdcdata, + lt_bcdata TYPE STANDARD TABLE OF bdcdata. + + ls_bcdata-program = 'SAPMSVIM'. + ls_bcdata-dynpro = '0050'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'VIMDYNFLDS-VIEWNAME'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'VIMDYNFLDS-STRUCT_MNT'. + ls_bcdata-fval = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=CLUS'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-program = 'SAPMSVIM'. + ls_bcdata-dynpro = '0052 '. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'VIMDYNFLDS-VCLNAME'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=CLSH'. + APPEND ls_bcdata TO lt_bcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SE54' + it_bdcdata = lt_bcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_vclname TYPE vcl_name, + ls_vcldir_entry TYPE v_vcldir, + lt_vclstruc TYPE TABLE OF v_vclstruc, + lt_vclstrudep TYPE TABLE OF v_vclstdep, + lt_vclmf TYPE TABLE OF v_vclmf. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + lv_vclname = ms_item-obj_name. + + CALL FUNCTION 'VIEWCLUSTER_GET_DEFINITION' + EXPORTING + vclname = lv_vclname + IMPORTING + vcldir_entry = ls_vcldir_entry + TABLES + vclstruc_tab = lt_vclstruc + vclstrudep_tab = lt_vclstrudep + vclmf_tab = lt_vclmf + EXCEPTIONS + viewcluster_not_found = 1 + incomplete_viewcluster = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + SORT lt_vclstrudep BY vclname object objfield. + + CLEAR ls_vcldir_entry-author. + CLEAR ls_vcldir_entry-changedate. + + io_xml->add( iv_name = 'VCLDIR' + ig_data = ls_vcldir_entry ). + io_xml->add( iv_name = 'VLCSTRUC_TAB' + ig_data = lt_vclstruc ). + io_xml->add( iv_name = 'VCLSTRUDEP_TAB' + ig_data = lt_vclstrudep ). + io_xml->add( iv_name = 'VCLMF_TAB' + ig_data = lt_vclmf ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ueno IMPLEMENTATION. + METHOD build_text_name. + + TYPES BEGIN OF ty_text_name. + TYPES id TYPE c LENGTH 4. + TYPES entity TYPE c LENGTH 26. + TYPES modifier TYPE c LENGTH 2. + TYPES END OF ty_text_name. + + DATA ls_text_name TYPE ty_text_name. + + ls_text_name-id = iv_id. + ls_text_name-entity = mv_entity_id. + ls_text_name-modifier = 'A%'. + + rv_result = ls_text_name. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_entity_id = is_item-obj_name. + + ENDMETHOD. + METHOD delete_docu_uen. + + DATA lt_dm02l TYPE STANDARD TABLE OF dm02l WITH DEFAULT KEY. + DATA ls_dm02l TYPE dm02l. + + SELECT * + FROM dm02l + INTO TABLE lt_dm02l + WHERE entid = mv_entity_id + ORDER BY PRIMARY KEY. + + LOOP AT lt_dm02l INTO ls_dm02l. + + CALL FUNCTION 'SDU_DOCU_DELETE' + EXPORTING + key1 = ls_dm02l-entid + key2 = ls_dm02l-as4local + key3 = '00' + langu = mv_language + obj_id = 'UENC' "Entity Comments + EXCEPTIONS + ret_code = 0. + + CALL FUNCTION 'SDU_DOCU_DELETE' + EXPORTING + key1 = ls_dm02l-entid + key2 = ls_dm02l-as4local + key3 = '00' + langu = mv_language + obj_id = 'UEND' "Entity Definition + EXCEPTIONS + ret_code = 0. + + CALL FUNCTION 'SDU_DOCU_DELETE' + EXPORTING + key1 = ls_dm02l-entid + key2 = ls_dm02l-as4local + key3 = '00' + langu = mv_language + obj_id = 'UENE' "Entity Example + EXCEPTIONS + ret_code = 0. + + ENDLOOP. + + ENDMETHOD. + METHOD delete_docu_url. + + DATA lt_dm42s TYPE STANDARD TABLE OF dm42s WITH DEFAULT KEY. + DATA ls_dm42s LIKE LINE OF lt_dm42s. + + SELECT * + FROM dm42s + INTO TABLE lt_dm42s + WHERE entidto = mv_entity_id + ORDER BY PRIMARY KEY. + + LOOP AT lt_dm42s INTO ls_dm42s. + + CALL FUNCTION 'SDU_DOCU_DELETE' + EXPORTING + langu = mv_language + obj_id = 'URL1' + key1 = ls_dm42s-entidto + key2 = ls_dm42s-as4local + key3 = ls_dm42s-entidfrom + key4 = ls_dm42s-ebrolnr + EXCEPTIONS + ret_code = 0. + + CALL FUNCTION 'SDU_DOCU_DELETE' + EXPORTING + langu = mv_language + obj_id = 'URL2' + key1 = ls_dm42s-entidto + key2 = ls_dm42s-as4local + key3 = ls_dm42s-entidfrom + key4 = ls_dm42s-ebrolnr + EXCEPTIONS + ret_code = 0. + + CALL FUNCTION 'SDU_DOCU_DELETE' + EXPORTING + langu = mv_language + obj_id = 'URLC' + key1 = ls_dm42s-entidto + key2 = ls_dm42s-as4local + key3 = ls_dm42s-entidfrom + key4 = ls_dm42s-ebrolnr + EXCEPTIONS + ret_code = 0. + + ENDLOOP. + ENDMETHOD. + METHOD delete_docu_usp. + + DATA lt_dm45l TYPE STANDARD TABLE OF dm45l WITH DEFAULT KEY. + DATA ls_dm45l LIKE LINE OF lt_dm45l. + + SELECT * + FROM dm45l + INTO TABLE lt_dm45l + WHERE entid = ms_item-obj_name + ORDER BY PRIMARY KEY. + + LOOP AT lt_dm45l INTO ls_dm45l. + + CALL FUNCTION 'SDU_DOCU_DELETE' + EXPORTING + langu = mv_language + obj_id = 'USPD' + key1 = ls_dm45l-entid + key2 = ls_dm45l-as4local + key3 = ls_dm45l-spezid + EXCEPTIONS + ret_code = 0. + + ENDLOOP. + ENDMETHOD. + METHOD deserialize_docu_uen. + + DATA lt_docu TYPE ty_docu_lines. + + io_xml->read( EXPORTING iv_name = 'DOCU_UENC' + CHANGING cg_data = lt_docu ). + deserialize_docu_xxxx( lt_docu ). + CLEAR lt_docu. + io_xml->read( EXPORTING iv_name = 'DOCU_UEND' + CHANGING cg_data = lt_docu ). + deserialize_docu_xxxx( lt_docu ). + CLEAR lt_docu. + io_xml->read( EXPORTING iv_name = 'DOCU_UENE' + CHANGING cg_data = lt_docu ). + deserialize_docu_xxxx( lt_docu ). + + ENDMETHOD. + METHOD deserialize_docu_url. + + DATA lt_docu TYPE ty_docu_lines. + + io_xml->read( EXPORTING iv_name = 'DOCU_URL1' + CHANGING cg_data = lt_docu ). + + deserialize_docu_xxxx( lt_docu ). + + CLEAR lt_docu. + io_xml->read( EXPORTING iv_name = 'DOCU_URL2' + CHANGING cg_data = lt_docu ). + + deserialize_docu_xxxx( lt_docu ). + + CLEAR lt_docu. + io_xml->read( EXPORTING iv_name = 'DOCU_URLC' + CHANGING cg_data = lt_docu ). + + deserialize_docu_xxxx( lt_docu ). + + ENDMETHOD. + METHOD deserialize_docu_usp. + + DATA lt_docu TYPE ty_docu_lines. + + io_xml->read( EXPORTING iv_name = 'DOCU_USPD' + CHANGING cg_data = lt_docu ). + + deserialize_docu_xxxx( lt_docu ). + + ENDMETHOD. + METHOD deserialize_docu_xxxx. + + DATA ls_docu LIKE LINE OF it_docu. + DATA lv_objname TYPE lxeobjname. + DATA lv_change_flag TYPE char1. + DATA lv_error_status TYPE lxestatprc. + + LOOP AT it_docu INTO ls_docu. + + ls_docu-header-tdfuser = sy-uname. + ls_docu-header-tdfdate = sy-datum. + ls_docu-header-tdftime = sy-uzeit. + ls_docu-header-tdfreles = sy-saprl. + + ls_docu-header-tdluser = sy-uname. + ls_docu-header-tdldate = sy-datum. + ls_docu-header-tdltime = sy-uzeit. + ls_docu-header-tdlreles = sy-saprl. + + lv_objname = ls_docu-header-tdname. + + CALL FUNCTION 'LXE_OBJ_DOKU_PUT_XSTRING' + EXPORTING + slang = mv_language + tlang = ls_docu-language + objtype = ls_docu-header-tdid + objname = lv_objname + header = ls_docu-header + content = ls_docu-content + IMPORTING + change_flag = lv_change_flag + pstatus = lv_error_status. + + ENDLOOP. + ENDMETHOD. + METHOD get_field_rules. + + DATA: + lt_fields TYPE TABLE OF string, + lv_fields TYPE string, + lv_table TYPE tabname, + lv_field TYPE string, + lv_rule TYPE string, + lv_rule_iter TYPE string, + lv_fill_rule TYPE zif_abapgit_field_rules=>ty_fill_rule, + lv_prefix TYPE fieldname, + lv_suffix TYPE fieldname. + + ro_result = zcl_abapgit_field_rules=>create( ). + + " Many tables and fields with date,time,user so we encode them + APPEND 'DM02L,FL,DTU' TO lt_fields. + APPEND 'DM02T,L,DTU' TO lt_fields. + APPEND 'DM03S,FL,DTU' TO lt_fields. + APPEND 'DM25L,FL,DTU' TO lt_fields. + APPEND 'DM26L,FL,DTU' TO lt_fields. + APPEND 'DM42S,FL,DTU' TO lt_fields. + APPEND 'DM42T,L,DTU' TO lt_fields. + APPEND 'DM43T,L,DU' TO lt_fields. + APPEND 'DM45L,FL,DTU' TO lt_fields. + APPEND 'DM45T,L,DTU' TO lt_fields. + APPEND 'DM46S,FL,DTU' TO lt_fields. + + LOOP AT lt_fields INTO lv_fields. + SPLIT lv_fields AT ',' INTO lv_table lv_field lv_rule_iter. + + DO strlen( lv_field ) TIMES. + CASE lv_field(1). + WHEN 'F'. + lv_prefix = 'FST'. + WHEN 'L'. + lv_prefix = 'LST'. + ENDCASE. + + lv_rule = lv_rule_iter. + DO strlen( lv_rule ) TIMES. + CASE lv_rule(1). + WHEN 'D'. + lv_suffix = 'DATE'. + lv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date. + WHEN 'T'. + lv_suffix = 'TIME'. + lv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time. + WHEN 'U'. + lv_suffix = 'USER'. + lv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user. + ENDCASE. + + ro_result->add( + iv_table = lv_table + iv_field = lv_prefix && lv_suffix + iv_fill_rule = lv_fill_rule ). + + SHIFT lv_rule LEFT. + ENDDO. + + SHIFT lv_field LEFT. + ENDDO. + + ENDLOOP. + + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD is_name_permitted. + + " It is unlikely that a serialized entity will have a name that is not permitted. However + " there may be reservations in TRESE which could prohibit the entity name. + " So to be safe, we check. Tx SD11 does this check. + + CALL FUNCTION 'SDU_SAA_CHECK' + EXPORTING + obj_name = ms_item-obj_name + obj_type = ms_item-obj_type + EXCEPTIONS + wrong_type = 1. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD serialize_docu_uen. + + DATA lt_docu TYPE ty_docu_lines. + + lt_docu = serialize_docu_xxxx( 'UENC' ). + + io_xml->add( iv_name = 'DOCU_UENC' + ig_data = lt_docu ). + lt_docu = serialize_docu_xxxx( 'UEND' ). + + io_xml->add( iv_name = 'DOCU_UEND' + ig_data = lt_docu ). + + lt_docu = serialize_docu_xxxx( 'UENE' ). + + io_xml->add( iv_name = 'DOCU_UENE' + ig_data = lt_docu ). + ENDMETHOD. + METHOD serialize_docu_url. + DATA lt_docu TYPE ty_docu_lines. + + lt_docu = serialize_docu_xxxx( 'URL1' ). + io_xml->add( iv_name = 'DOCU_URL1' + ig_data = lt_docu ). + lt_docu = serialize_docu_xxxx( 'URL2' ). + io_xml->add( iv_name = 'DOCU_URL2' + ig_data = lt_docu ). + + lt_docu = serialize_docu_xxxx( 'URLC' ). + io_xml->add( iv_name = 'DOCU_URLC' + ig_data = lt_docu ). + + ENDMETHOD. + METHOD serialize_docu_usp. + + DATA lt_docu TYPE ty_docu_lines. + + lt_docu = serialize_docu_xxxx( 'USPD' ). + + io_xml->add( iv_name = 'DOCU_USPD' + ig_data = lt_docu ). + ENDMETHOD. + METHOD serialize_docu_xxxx. + + DATA ls_docu TYPE ty_docu. + DATA ls_dokvl TYPE dokvl. + DATA lt_dokvl TYPE STANDARD TABLE OF dokvl. + DATA lv_error_status TYPE lxestatprc. + DATA lv_objname TYPE lxeobjname. + ls_dokvl-object = build_text_name( iv_id ). + + SELECT id object langu + FROM dokvl + INTO CORRESPONDING FIELDS OF TABLE lt_dokvl + WHERE id = c_text_object_type + AND object LIKE ls_dokvl-object + ORDER BY id object langu ##TOO_MANY_ITAB_FIELDS. + + LOOP AT lt_dokvl INTO ls_dokvl. + + ls_docu-language = ls_dokvl-langu. + lv_objname = ls_dokvl-object. + + " You are reminded that this function gets the most recent version of the texts. + CALL FUNCTION 'LXE_OBJ_DOKU_GET_XSTRING' + EXPORTING + lang = ls_docu-language + objtype = c_text_object_type + objname = lv_objname + IMPORTING + header = ls_docu-header + content = ls_docu-content + itf = ls_docu-itf + pstatus = lv_error_status ##ARG_OK. + + CHECK lv_error_status = 'S'. "Success + + " Administrative information is not + CLEAR ls_docu-header-tdfuser. + CLEAR ls_docu-header-tdfdate. + CLEAR ls_docu-header-tdftime. + CLEAR ls_docu-header-tdfreles. + + CLEAR ls_docu-header-tdluser. + CLEAR ls_docu-header-tdldate. + CLEAR ls_docu-header-tdltime. + CLEAR ls_docu-header-tdlreles. + + APPEND ls_docu TO rt_result. + + ENDLOOP. + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE lstuser INTO rv_user + FROM dm02l + WHERE entid = mv_entity_id + AND as4local = c_active_state. + + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + " The deletion of the documentation occurs before the deletion of + " the associated tables - otherwise we don't know what + " documentation needs deletion + delete_docu_uen( ). + delete_docu_url( ). + delete_docu_usp( ). + + " the deletion of the tables of the entity + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + " Is the entity type name compliant with naming conventions? + " Entity Type have their own conventions. + is_name_permitted( ). + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + deserialize_docu_uen( io_xml ). + deserialize_docu_url( io_xml ). + deserialize_docu_usp( io_xml ). + + " You are reminded that entity types are not relevant for activation. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( + iv_lock_object = 'ESDUM' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + " The function module listed below do not open a new window - so we revert to BDC. + " CALL FUNCTION 'SDU_MODEL_SHOW' + " CALL FUNCTION 'RS_TOOL_ACCESS' + + DATA lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMUD00'. + -dynpro = '0100'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=SHOW'. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'RSUD3-ENTI'. + -fval = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'RSUD3-OBJ_KEY'. + -fval = ms_item-obj_name. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SD11' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + serialize_docu_uen( io_xml ). + serialize_docu_url( io_xml ). + serialize_docu_usp( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_udmo IMPLEMENTATION. + METHOD access_free. + + " Release the lock on the object. + + CALL FUNCTION 'RS_ACCESS_PERMISSION' + EXPORTING + mode = 'FREE' + object = ms_object_type + object_class = c_transport_object_class + EXCEPTIONS + canceled_in_corr = 1 + enqueued_by_user = 2 + enqueue_system_failure = 3 + illegal_parameter_values = 4 + locked_by_author = 5 + no_modify_permission = 6 + no_show_permission = 7 + permission_failure = 8 + request_language_denied = 9 + OTHERS = 10. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ELSE. + rv_result = abap_true. + ENDIF. + + ENDMETHOD. + METHOD access_modify. + +* You are reminded that mode modify is the same as insert, with one important difference: + +* Mode INSERT is intended for newly created objects, for which a TADIR entry does not yet +* exist. In that case, the system shows a pop-up for the entry of the package, which isn't +* desirable when the SAPGUI is not available. + +* In the context of abapGit, the package is known. + + CALL FUNCTION 'RS_ACCESS_PERMISSION' + EXPORTING + authority_check = abap_true + global_lock = abap_true + mode = 'MODIFY' + object = ms_object_type + object_class = c_transport_object_class + EXCEPTIONS + canceled_in_corr = 1 + enqueued_by_user = 2 + enqueue_system_failure = 3 + illegal_parameter_values = 4 + locked_by_author = 5 + no_modify_permission = 6 + no_show_permission = 7 + permission_failure = 8 + request_language_denied = 9 + OTHERS = 10. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ELSE. + rv_result = abap_true. + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + " Conversion to Data model + mv_data_model = is_item-obj_name. + " Default activation state is active + mv_activation_state = c_active_state. + " Derive the data model's text object + mv_text_object = 'UDMD' && is_item-obj_name. + " And set the text object to active + mv_text_object+30(1) = mv_activation_state. + mv_lxe_text_name = mv_text_object. + + " Correction and Transport System object + ms_object_type-objtype = c_correction_object_type. + ms_object_type-objname = is_item-obj_name. + ENDMETHOD. + METHOD corr_insert. + + DATA lv_obj_name TYPE tadir-obj_name. + + " You are reminded that SUDM - Data Model has no part objects e.g. no LIMU + " Therefore global lock is always appropriate + + " You are reminded that the main language (in TADIR) is taken from MV_LANGUAGE. + lv_obj_name = ms_object_type. + + zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( + iv_object = c_transport_object_class + iv_obj_name = lv_obj_name + iv_package = iv_package + iv_language = mv_language ). + + ENDMETHOD. + METHOD deserialize_entities. + + DATA lt_udmo_entities TYPE STANDARD TABLE OF dm41s WITH DEFAULT KEY. + DATA ls_udmo_entity LIKE LINE OF lt_udmo_entities. + io_xml->read( EXPORTING iv_name = 'UDMO_ENTITIES' + CHANGING cg_data = lt_udmo_entities ). + + LOOP AT lt_udmo_entities INTO ls_udmo_entity. + + CALL FUNCTION 'SDU_DMO_ENT_PUT' + EXPORTING + object = ls_udmo_entity + EXCEPTIONS + OTHERS = 0. + + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_long_texts. + + DATA BEGIN OF ls_udmo_long_text. + DATA language TYPE dm40t-sprache. + DATA header TYPE thead. + DATA content TYPE xstring. + DATA END OF ls_udmo_long_text. + + DATA lt_udmo_long_texts LIKE STANDARD TABLE OF ls_udmo_long_text. + DATA ls_header TYPE thead. + + io_xml->read( EXPORTING iv_name = 'UDMO_LONG_TEXTS' + CHANGING cg_data = lt_udmo_long_texts ). + + LOOP AT lt_udmo_long_texts INTO ls_udmo_long_text. + + ls_udmo_long_text-header-tdfuser = sy-uname. + ls_udmo_long_text-header-tdfdate = sy-datum. + ls_udmo_long_text-header-tdftime = sy-uzeit. + + " You are reminded that the target system may already have some texts in + " existence. So we determine the highest existent version. + + CLEAR ls_header-tdversion. + + SELECT MAX( dokversion ) + INTO ls_header-tdversion + FROM dokhl + WHERE id = c_lxe_text_type + AND object = mv_text_object + AND langu = ls_udmo_long_text-language. + + " Increment the version + ls_header-tdversion = ls_header-tdversion + 1. + ls_udmo_long_text-header-tdversion = ls_header-tdversion. + + " This function module takes care of the variation in text processing between various objects. + CALL FUNCTION 'LXE_OBJ_DOKU_PUT_XSTRING' + EXPORTING + slang = mv_language + tlang = ls_udmo_long_text-language + objtype = c_lxe_text_type + objname = mv_lxe_text_name + header = ls_udmo_long_text-header + content = ls_udmo_long_text-content. + ENDLOOP. + ENDMETHOD. + METHOD deserialize_model. + + DATA ls_dm40l TYPE dm40l. + io_xml->read( EXPORTING iv_name = 'DM40L' + CHANGING cg_data = ls_dm40l ). + " See SDU_MODEL_PUT + GET TIME. + + ls_dm40l-flg_frame = abap_true. + ls_dm40l-fstdate = sy-datum. + ls_dm40l-fsttime = sy-uzeit. + ls_dm40l-fstuser = sy-uname. + ls_dm40l-lstdate = sy-datum. + ls_dm40l-lsttime = sy-uzeit. + ls_dm40l-lstuser = sy-uname. + + MODIFY dm40l FROM ls_dm40l. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from SDU_MODEL_PUT' ). + ENDIF. + + ENDMETHOD. + METHOD deserialize_short_texts. + + DATA lt_udmo_texts TYPE STANDARD TABLE OF ty_udmo_text_type WITH DEFAULT KEY. + DATA ls_udmo_text TYPE ty_udmo_text_type. + DATA ls_dm40t TYPE dm40t. + " Deserialize the XML + io_xml->read( EXPORTING iv_name = 'UDMO_TEXTS' + CHANGING cg_data = lt_udmo_texts ). + + " For every text provided + LOOP AT lt_udmo_texts INTO ls_udmo_text. + + " Does the text already exist? This is the same logic as used + " in the FM SDU_MODEL_PUT + SELECT SINGLE * + FROM dm40t + INTO ls_dm40t + WHERE sprache = ls_udmo_text-sprache + AND dmoid = ls_udmo_text-dmoid + AND as4local = mv_activation_state. + + IF sy-subrc = 0. + " There is already an active description for this language + " but the provided description differs + IF ls_dm40t-langbez <> ls_udmo_text-langbez. + + ls_dm40t-langbez = ls_udmo_text-langbez. + ls_dm40t-lstdate = sy-datum. + ls_dm40t-lsttime = sy-uzeit. + ls_dm40t-lstuser = sy-uname. + + MODIFY dm40t FROM ls_dm40t. + + ENDIF. + ELSE. + + " There is no EXISTING active description in this language + + ls_dm40t-as4local = ls_udmo_text-as4local. + ls_dm40t-dmoid = ls_udmo_text-dmoid. + ls_dm40t-langbez = ls_udmo_text-langbez. + ls_dm40t-lstdate = sy-datum. + ls_dm40t-lsttime = sy-uzeit. + ls_dm40t-lstuser = sy-uname. + ls_dm40t-sprache = ls_udmo_text-sprache. + INSERT dm40t FROM ls_dm40t. + + ENDIF. + + ENDLOOP. + ENDMETHOD. + METHOD is_name_permitted. + + " It is unlikely that a serialized data model will have a name that is not permitted. However + " there may be reservations in TRESE which could prohibit the data model name. + " So to be safe, we check. Tx SD11 does this check. + CALL FUNCTION 'SDU_SAA_CHECK' + EXPORTING + obj_name = ms_object_type-objname + obj_type = ms_object_type-objtype + EXCEPTIONS + wrong_type = 1. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD serialize_entities. + + DATA lt_udmo_entities TYPE STANDARD TABLE OF dm41s WITH DEFAULT KEY. + FIELD-SYMBOLS TYPE dm41s. + + SELECT * FROM dm41s + INTO TABLE lt_udmo_entities + WHERE dmoid = mv_data_model + AND as4local = mv_activation_state + ORDER BY PRIMARY KEY. + + LOOP AT lt_udmo_entities ASSIGNING . + " You are reminded that administrative information, such as last changed by user, date, time is not serialized. + CLEAR -lstuser. + CLEAR -lstdate. + CLEAR -lsttime. + CLEAR -fstuser. + CLEAR -fstdate. + CLEAR -fsttime. + ENDLOOP. + + " You are reminded that descriptions in other languages do not have to be in existence, although they may. + IF lines( lt_udmo_entities ) > 0. + io_xml->add( iv_name = 'UDMO_ENTITIES' + ig_data = lt_udmo_entities ). + ENDIF. + + ENDMETHOD. + METHOD serialize_long_texts. + + " The model has short texts in multiple languages. These are held in DM40T. + + " The model has a long description also in a main language, with other long descriptions + " maintained as translations using SE63 Translation Editor. All of these long texts are held in DOK* + + TYPES BEGIN OF ty_language_type. + TYPES language TYPE dm40t-sprache. + TYPES END OF ty_language_type. + + DATA BEGIN OF ls_udmo_long_text. + DATA language TYPE dm40t-sprache. + DATA header TYPE thead. + DATA content TYPE xstring. + DATA END OF ls_udmo_long_text. + + DATA lt_udmo_long_texts LIKE STANDARD TABLE OF ls_udmo_long_text. + DATA lt_udmo_languages TYPE STANDARD TABLE OF ty_language_type. + DATA ls_udmo_language LIKE LINE OF lt_udmo_languages. + DATA: lv_error_status TYPE lxestatprc. + " In which languages are the short texts are maintained. + SELECT sprache AS language + FROM dm40t + INTO TABLE lt_udmo_languages + WHERE dmoid = mv_data_model + AND as4local = mv_activation_state + ORDER BY sprache ASCENDING. "#EC CI_NOFIRST + + " For every language for which a short text is maintained, + LOOP AT lt_udmo_languages INTO ls_udmo_language. + + CLEAR ls_udmo_long_text. + CLEAR lv_error_status. + + ls_udmo_long_text-language = ls_udmo_language-language. + + " You are reminded that this function gets the most recent version of the texts. + CALL FUNCTION 'LXE_OBJ_DOKU_GET_XSTRING' + EXPORTING + lang = ls_udmo_language-language + objtype = c_lxe_text_type + objname = mv_lxe_text_name + IMPORTING + header = ls_udmo_long_text-header + content = ls_udmo_long_text-content + pstatus = lv_error_status. + + CHECK lv_error_status = 'S'. "Success + + " Administrative information is not serialized + CLEAR ls_udmo_long_text-header-tdfuser. + CLEAR ls_udmo_long_text-header-tdfdate. + CLEAR ls_udmo_long_text-header-tdftime. + + CLEAR ls_udmo_long_text-header-tdluser. + CLEAR ls_udmo_long_text-header-tdldate. + CLEAR ls_udmo_long_text-header-tdltime. + + APPEND ls_udmo_long_text TO lt_udmo_long_texts. + + ENDLOOP. + + " You are reminded that long texts do not have to be in existence + IF lines( lt_udmo_long_texts ) > 0. + io_xml->add( iv_name = 'UDMO_LONG_TEXTS' + ig_data = lt_udmo_long_texts ). + ENDIF. + ENDMETHOD. + METHOD serialize_model. + + DATA ls_dm40l TYPE dm40l. + + " See SDU_MODEL_GET. + SELECT SINGLE * + FROM dm40l + INTO ls_dm40l + WHERE dmoid = mv_data_model + AND as4local = mv_activation_state. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from UDMO - model serialisation' ). + ENDIF. + + " You are reminded that administrative data is not serialized. + CLEAR ls_dm40l-lstdate. + CLEAR ls_dm40l-lsttime. + CLEAR ls_dm40l-lstuser. + CLEAR ls_dm40l-fstdate. + CLEAR ls_dm40l-fsttime. + CLEAR ls_dm40l-fstuser. + + io_xml->add( iv_name = 'DM40L' + ig_data = ls_dm40l ). + + ENDMETHOD. + METHOD serialize_short_texts. + + DATA lt_udmo_texts TYPE STANDARD TABLE OF ty_udmo_text_type WITH DEFAULT KEY. + " You are reminded that administrative information, such as last changed by user, date, time is not serialized. + + " You are reminded that active short texts of all (existent) languages are serialized. + + SELECT sprache dmoid as4local langbez + FROM dm40t + INTO CORRESPONDING FIELDS OF TABLE lt_udmo_texts + WHERE dmoid = mv_data_model + AND as4local = mv_activation_state + ORDER BY sprache ASCENDING. "#EC CI_NOFIRST + + " You are reminded that descriptions in other languages do not have to be in existence. + IF lines( lt_udmo_texts ) > 0. + io_xml->add( iv_name = 'UDMO_TEXTS' + ig_data = lt_udmo_texts ). + ENDIF. + ENDMETHOD. + METHOD update_tree. + + CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' + EXPORTING + object = mv_data_model + operation = 'INSERT' + type = c_correction_object_type. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE lstuser INTO rv_user + FROM dm40l + WHERE dmoid = mv_data_model + AND as4local = mv_activation_state. + + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + +* You are reminded that this function model checks for +* - permissions +* - locks +* - connection to transport and correction system +* - deletion of data model, model relations and all documentation +* - update of object tree +* - releasing of lock + + CALL FUNCTION 'RPY_DATAMODEL_DELETE' + EXPORTING + model_name = mv_data_model + EXCEPTIONS + cancelled = 1 + permission_error = 2 + not_found = 3 + is_used = 4 + OTHERS = 5. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + +* You are reminded that this method checks for +* - validity of data model name with regard to naming conventions +* - permissions and locks +* - connection to transport and correction system +* - insert of data model, model relations and all documentation +* - update of object tree +* - releasing of lock +* Is the data model name compliant with naming conventions? + is_name_permitted( ). + +* Access Permission granted? + access_modify( ). + +* Connection to transport and correction system + corr_insert( iv_package ). + +* Insert the data model, relations and documentation + TRY. + deserialize_model( io_xml ). + deserialize_entities( io_xml ). + deserialize_short_texts( io_xml ). + deserialize_long_texts( io_xml ). + update_tree( ). + access_free( ). + + CATCH zcx_abapgit_exception. + + access_free( ). + + zcx_abapgit_exception=>raise( 'Error in deserialization of UDMO' ). + ENDTRY. + + " You are reminded that data models are not relevant for activation. + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + " See Function Module SDU_MODEL_EXISTS + + SELECT COUNT( * ) FROM dm40l + WHERE dmoid = mv_data_model AND as4local = mv_activation_state. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( + iv_lock_object = 'ESDUM' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + " The function module listed below do not open a new window - so we revert to BDC. + " CALL FUNCTION 'SDU_MODEL_SHOW' + " CALL FUNCTION 'RS_TOOL_ACCESS' + + DATA lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMUD00'. + -dynpro = '0100'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=SHOW'. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'RSUD3-DATM'. + -fval = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'RSUD3-OBJ_KEY'. + -fval = ms_item-obj_name. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SD11' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + serialize_model( io_xml ). + serialize_entities( io_xml ). + serialize_short_texts( io_xml ). + serialize_long_texts( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ucsa IMPLEMENTATION. + METHOD clear_dynamic_fields. + + FIELD-SYMBOLS: TYPE any. + ASSIGN COMPONENT 'HEADER' OF STRUCTURE cg_complete_comm_assembly + TO . + ASSERT sy-subrc = 0. + + clear_field( + EXPORTING iv_fieldname = 'CREATEDBY' + CHANGING cg_header = ). + + clear_field( + EXPORTING iv_fieldname = 'CREATEDON' + CHANGING cg_header = ). + + clear_field( + EXPORTING iv_fieldname = 'CREATEDAT' + CHANGING cg_header = ). + + clear_field( + EXPORTING iv_fieldname = 'CHANGEDBY' + CHANGING cg_header = ). + + clear_field( + EXPORTING iv_fieldname = 'CHANGEDON' + CHANGING cg_header = ). + + clear_field( + EXPORTING iv_fieldname = 'CHANGEDAT' + CHANGING cg_header = ). + + ENDMETHOD. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE any. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cg_header + TO . + ASSERT sy-subrc = 0. + CLEAR . + + ENDMETHOD. + METHOD get_persistence. + + CALL METHOD ('CL_UCON_SA_DB_PERSIST')=>('IF_UCON_SA_PERSIST~GET_INSTANCE') + EXPORTING + id = iv_id + RECEIVING + instance = ro_persistence. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_id TYPE ty_id, + lx_root TYPE REF TO cx_root, + lo_persistence TYPE REF TO object, + lr_complete_comm_assembly TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + lv_id = ms_item-obj_name. + + TRY. + CREATE DATA lr_complete_comm_assembly TYPE ('UCONSERVASCOMPLETE'). + ASSIGN lr_complete_comm_assembly->* TO . + ASSERT sy-subrc = 0. + + lo_persistence = get_persistence( lv_id ). + + CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~LOAD') + EXPORTING + version = c_version-active + language = mv_language + IMPORTING + sa = . + + ASSIGN COMPONENT 'CHANGEDBY' OF STRUCTURE TO . + IF sy-subrc = 0. + rv_user = . + ENDIF. + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_id TYPE ty_id, + lx_root TYPE REF TO cx_root, + lv_text TYPE string, + lo_persistence TYPE REF TO object. + + TRY. + lv_id = ms_item-obj_name. + + lo_persistence = get_persistence( lv_id ). + + CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~DELETE') + EXPORTING + version = c_version-active. + + CATCH cx_root INTO lx_root. + lv_text = lx_root->get_text( ). + zcx_abapgit_exception=>raise( lv_text ). + ENDTRY. + + tadir_delete( ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_id TYPE ty_id, + lx_root TYPE REF TO cx_root, + lv_text TYPE string, + lo_persistence TYPE REF TO object, + lr_complete_comm_assembly TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any. + + TRY. + CREATE DATA lr_complete_comm_assembly TYPE ('UCONSERVASCOMPLETE'). + ASSIGN lr_complete_comm_assembly->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'UCSA' + CHANGING + cg_data = ). + + lv_id = ms_item-obj_name. + + lo_persistence = get_persistence( lv_id ). + + CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~CREATE'). + + CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~SAVE') + EXPORTING + sa = + version = c_version-active. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + CATCH cx_root INTO lx_root. + lv_text = lx_root->get_text( ). + zcx_abapgit_exception=>raise( lv_text ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_id TYPE ty_id, + lo_persistence TYPE REF TO object. + + lv_id = ms_item-obj_name. + + TRY. + lo_persistence = get_persistence( lv_id ). + + " Interface IF_UCON_SA_PERSIST and other objects are not present + " in lower NetWeaver releases. Therefore we have to call them + " dynamically to be downward compatible. + + CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~LOAD') + EXPORTING + version = c_version-active + language = mv_language. + + CATCH cx_root. + rv_bool = abap_false. + RETURN. + ENDTRY. + + rv_bool = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_id TYPE ty_id, + lx_root TYPE REF TO cx_root, + lo_persistence TYPE REF TO object, + lr_complete_comm_assembly TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any. + lv_id = ms_item-obj_name. + + TRY. + CREATE DATA lr_complete_comm_assembly TYPE ('UCONSERVASCOMPLETE'). + ASSIGN lr_complete_comm_assembly->* TO . + ASSERT sy-subrc = 0. + + lo_persistence = get_persistence( lv_id ). + + CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~LOAD') + EXPORTING + version = c_version-active + language = mv_language + IMPORTING + sa = . + + clear_dynamic_fields( CHANGING cg_complete_comm_assembly = ). + + io_xml->add( iv_name = 'UCSA' + ig_data = ). + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_type IMPLEMENTATION. + METHOD create. + + DATA: lv_progname TYPE reposrc-progname, + lv_typegroup TYPE rsedd0-typegroup. + lv_typegroup = ms_item-obj_name. + + CALL FUNCTION 'RS_DD_TYGR_INSERT_SOURCES' + EXPORTING + typegroupname = lv_typegroup + ddtext = iv_ddtext + corrnum = '' + devclass = iv_devclass + TABLES + source = it_source + EXCEPTIONS + already_exists = 1 + not_executed = 2 + permission_failure = 3 + object_not_specified = 4 + illegal_name = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CONCATENATE c_prefix lv_typegroup INTO lv_progname. + UPDATE progdir SET uccheck = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard + WHERE name = lv_progname. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error setting uccheck' ). + ENDIF. + + ENDMETHOD. + METHOD read. + + DATA: lv_typdname TYPE rsedd0-typegroup, + lt_psmodisrc TYPE TABLE OF smodisrc, + lt_psmodilog TYPE TABLE OF smodilog, + lt_ptrdir TYPE TABLE OF trdir. + SELECT SINGLE ddtext FROM ddtypet + INTO ev_ddtext + WHERE typegroup = ms_item-obj_name + AND ddlanguage = mv_language. + + lv_typdname = ms_item-obj_name. + + " Get active version, ignore errors if not found + CALL FUNCTION 'TYPD_GET_OBJECT' + EXPORTING + typdname = lv_typdname + TABLES + psmodisrc = lt_psmodisrc + psmodilog = lt_psmodilog + psource = et_source + ptrdir = lt_ptrdir + EXCEPTIONS + version_not_found = 1 + reps_not_exist = 2 + OTHERS = 3 ##FM_SUBRC_OK. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + DATA lv_prog TYPE progname. + + CONCATENATE '%_C' ms_item-obj_name INTO lv_prog. + + SELECT SINGLE unam FROM reposrc INTO rv_user + WHERE progname = lv_prog AND r3state = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + delete_ddic( 'G' ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_ddtext TYPE ddtypet-ddtext, + lt_source TYPE abaptxt255_tab, + lv_progname TYPE reposrc-progname, + lv_typegroup TYPE rsedd0-typegroup. + lv_typegroup = ms_item-obj_name. + io_xml->read( EXPORTING iv_name = 'DDTEXT' + CHANGING cg_data = lv_ddtext ). + + lt_source = mo_files->read_abap( ). + + IF zif_abapgit_object~exists( ) = abap_false. + create( iv_ddtext = lv_ddtext + it_source = lt_source + iv_devclass = iv_package ). + ELSE. + CONCATENATE c_prefix lv_typegroup INTO lv_progname. + + zcl_abapgit_factory=>get_sap_report( )->insert_report( + iv_name = lv_progname + iv_package = iv_package + iv_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard + it_source = lt_source ). + ENDIF. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_progname TYPE progname, + lv_state TYPE r3state. + + lv_progname = |%_C{ ms_item-obj_name }|. + SELECT SINGLE state + FROM progdir + INTO lv_state + WHERE name = lv_progname. "#EC CI_NOORDER + IF lv_state IS NOT INITIAL. + rv_bool = abap_true. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECT=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_ddtext TYPE ddtypet-ddtext, + lt_source TYPE abaptxt255_tab. + read( IMPORTING ev_ddtext = lv_ddtext + et_source = lt_source ). + + IF lt_source IS INITIAL. + RETURN. + ENDIF. + + io_xml->add( iv_name = 'DDTEXT' + ig_data = lv_ddtext ). + + mo_files->add_abap( lt_source ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ttyp IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE as4user FROM dd40l INTO rv_user + WHERE typename = ms_item-obj_name + AND as4local = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + delete_ddic( 'A' ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_name TYPE ddobjname, + lt_dd42v TYPE dd42v_tab, + lt_dd43v TYPE dd43v_tab, + ls_dd40v TYPE dd40v, + ls_extra TYPE ty_extra, + lv_msg TYPE string. + + io_xml->read( EXPORTING iv_name = 'DD40V' + CHANGING cg_data = ls_dd40v ). + + io_xml->read( EXPORTING iv_name = 'DD42V' + CHANGING cg_data = lt_dd42v ). + io_xml->read( EXPORTING iv_name = 'DD43V' + CHANGING cg_data = lt_dd43v ). + + corr_insert( iv_package = iv_package + ig_object_class = 'DICT' ). + + lv_name = ms_item-obj_name. " type conversion + + CALL FUNCTION 'DDIF_TTYP_PUT' + EXPORTING + name = lv_name + dd40v_wa = ls_dd40v + TABLES + dd42v_tab = lt_dd42v + dd43v_tab = lt_dd43v + EXCEPTIONS + ttyp_not_found = 1 + name_inconsistent = 2 + ttyp_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + + IF sy-subrc <> 0. + lv_msg = |Error in DDIF_TTYP_PUT on object { lv_name }|. + + CASE sy-subrc. + WHEN 1. + lv_msg = lv_msg && | (TTYP_NOT_FOUND)|. + WHEN 2. + lv_msg = lv_msg && | (NAME_INCONSISTENT)|. + WHEN 3. + lv_msg = lv_msg && | (TTYP_INCONSISTENT)|. + WHEN 4. + lv_msg = lv_msg && | (PUT_FAILURE)|. + WHEN 5. + lv_msg = lv_msg && | (PUT_REFUSED)|. + WHEN OTHERS. + ENDCASE. + + zcx_abapgit_exception=>raise( lv_msg ). + ENDIF. + + " Fields that are not part of dd40v + io_xml->read( EXPORTING iv_name = 'DD40L_EXTRA' + CHANGING cg_data = ls_extra ). + + TRY. + set_abap_language_version( CHANGING cv_abap_language_version = ls_extra-abap_language_version ). + + UPDATE ('DD40L') SET abap_language_version = ls_extra-abap_language_version WHERE typename = lv_name. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_ttyp ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_typename TYPE dd40l-typename. + + SELECT SINGLE typename FROM dd40l INTO lv_typename + WHERE typename = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECT=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_name TYPE ddobjname, + lv_state TYPE ddgotstate, + lt_dd42v TYPE dd42v_tab, + lt_dd43v TYPE dd43v_tab, + ls_extra TYPE ty_extra, + ls_dd40v TYPE dd40v. + + FIELD-SYMBOLS TYPE any. + + lv_name = ms_item-obj_name. + + CALL FUNCTION 'DDIF_TTYP_GET' + EXPORTING + name = lv_name + state = 'A' + langu = mv_language + IMPORTING + gotstate = lv_state + dd40v_wa = ls_dd40v + TABLES + dd42v_tab = lt_dd42v + dd43v_tab = lt_dd43v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF ls_dd40v IS INITIAL OR lv_state <> 'A'. + RETURN. + ENDIF. + + CLEAR: ls_dd40v-as4user, + ls_dd40v-as4date, + ls_dd40v-as4time. + + IF NOT ls_dd40v-rowkind IS INITIAL. + CLEAR ls_dd40v-typelen. + ENDIF. + + ASSIGN COMPONENT 'ACTFLAG' OF STRUCTURE ls_dd40v TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + io_xml->add( iv_name = 'DD40V' + ig_data = ls_dd40v ). + io_xml->add( iv_name = 'DD42V' + ig_data = lt_dd42v ). + io_xml->add( iv_name = 'DD43V' + ig_data = lt_dd43v ). + + ls_extra-abap_language_version = get_abap_language_version( ). + + io_xml->add( iv_name = 'DD40L_EXTRA' + ig_data = ls_extra ). + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_ttyp ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_tran IMPLEMENTATION. + METHOD add_data. + + DATA: ls_bcdata LIKE LINE OF mt_bcdata. + + ls_bcdata-fnam = iv_fnam. + ls_bcdata-fval = iv_fval. + APPEND ls_bcdata TO mt_bcdata. + + ENDMETHOD. + METHOD call_se93. + + DATA: lt_message TYPE STANDARD TABLE OF bdcmsgcoll. + DATA lv_msg TYPE string. + + FIELD-SYMBOLS: TYPE bdcmsgcoll. + CALL FUNCTION 'ABAP4_CALL_TRANSACTION' + EXPORTING + tcode = 'SE93' + mode_val = 'N' + TABLES + using_tab = mt_bcdata + mess_tab = lt_message + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error deserializing { ms_item-obj_type } { ms_item-obj_name }| ). + ENDIF. + + LOOP AT lt_message ASSIGNING WHERE msgtyp CA 'EAX'. + MESSAGE ID -msgid + TYPE -msgtyp + NUMBER -msgnr + WITH -msgv1 -msgv2 -msgv3 -msgv4 + INTO lv_msg. + zcx_abapgit_exception=>raise_t100( ). + ENDLOOP. + + ENDMETHOD. + METHOD clear_functiongroup_globals. + TYPES ty_param_vari TYPE abap_bool. + + DATA lt_error_list TYPE STANDARD TABLE OF rsmp_check WITH DEFAULT KEY. + FIELD-SYMBOLS TYPE ty_param_vari. + + " only way to clear global fields in function group + CALL FUNCTION 'RS_TRANSACTION_INCONSISTENCIES' + EXPORTING + transaction_code = 'ZTHISTCODENEVEREXIST' + TABLES + error_list = lt_error_list + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + "Expected - fine + + " but there is no other way to clear this field + ASSIGN ('(SAPLSEUK)PARAM_VARI') TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD deserialize_oo_transaction. + + " You should remember that we don't use batch input just for fun, + " but because FM RPY_TRANSACTION_INSERT doesn't support OO transactions. + + DATA: ls_bcdata TYPE bdcdata. + CLEAR mt_bcdata. + + ls_bcdata-program = 'SAPLSEUK'. + ls_bcdata-dynpro = '0390'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO mt_bcdata. + + add_data( iv_fnam = 'TSTC-TCODE' + iv_fval = is_tstc-tcode ). + + IF zif_abapgit_object~exists( ) = abap_true. + + add_data( iv_fnam = 'BDC_OKCODE' + iv_fval = '=CHNG' ). + + ELSE. + + add_data( iv_fnam = 'BDC_OKCODE' + iv_fval = '=ADD' ). + + ENDIF. + + ls_bcdata-program = 'SAPLSEUK'. + ls_bcdata-dynpro = '0300'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO mt_bcdata. + + add_data( iv_fnam = 'TSTCT-TTEXT' + iv_fval = is_tstct-ttext ). + + add_data( iv_fnam = 'RSSTCD-S_CLASS' + iv_fval = 'X' ). + + add_data( iv_fnam = 'BDC_OKCODE' + iv_fval = '=ENTR' ). + + ls_bcdata-program = 'SAPLSEUK'. + ls_bcdata-dynpro = '0360'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO mt_bcdata. + + add_data( iv_fnam = 'RSSTCD-S_TRFRAME' + iv_fval = is_rsstcd-s_trframe ). + + add_data( iv_fnam = 'RSSTCD-S_UPDTASK' + iv_fval = is_rsstcd-s_updtask ). + + add_data( iv_fnam = 'BDC_OKCODE' + iv_fval = '=TR_FRAMEWORK' ). + + ls_bcdata-program = 'SAPLSEUK'. + ls_bcdata-dynpro = '0360'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO mt_bcdata. + + add_data( iv_fnam = 'RSSTCD-CLASSNAME' + iv_fval = is_rsstcd-classname ). + + add_data( iv_fnam = 'RSSTCD-METHOD' + iv_fval = is_rsstcd-method ). + + IF is_rsstcd-s_local IS NOT INITIAL. + add_data( iv_fnam = 'RSSTCD-S_LOCAL' + iv_fval = is_rsstcd-s_local ). + ENDIF. + + IF is_rsstcd-s_updlok IS NOT INITIAL. + add_data( iv_fnam = 'RSSTCD-S_UPDLOK' + iv_fval = is_rsstcd-s_updlok ). + ENDIF. + + add_data( iv_fnam = 'TSTC-PGMNA' + iv_fval = is_tstc-pgmna ). + + IF is_tstcc-s_webgui = '2'. + + add_data( iv_fnam = 'G_IAC_EWT' + iv_fval = abap_true ). + + add_data( iv_fnam = 'BDC_OKCODE' + iv_fval = 'MAKE_PROFI' ). + + ls_bcdata-program = 'SAPLSEUK'. + ls_bcdata-dynpro = '0360'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO mt_bcdata. + + ELSEIF is_tstcc-s_webgui IS NOT INITIAL. + + add_data( iv_fnam = 'TSTCC-S_WEBGUI' + iv_fval = is_tstcc-s_webgui ). + + ENDIF. + + IF is_tstcc-s_pervas IS NOT INITIAL. + add_data( iv_fnam = 'TSTCC-S_PERVAS' + iv_fval = is_tstcc-s_pervas ). + ENDIF. + + IF is_tstcc-s_service IS NOT INITIAL. + add_data( iv_fnam = 'TSTCC-S_SERVICE' + iv_fval = is_tstcc-s_service ). + ENDIF. + + IF is_tstcc-s_platin IS NOT INITIAL. + add_data( iv_fnam = 'TSTCC-S_PLATIN' + iv_fval = is_tstcc-s_platin ). + ENDIF. + + IF is_tstcc-s_win32 IS NOT INITIAL. + add_data( iv_fnam = 'TSTCC-S_WIN32' + iv_fval = is_tstcc-s_win32 ). + ENDIF. + + add_data( iv_fnam = 'BDC_OKCODE' + iv_fval = '=WB_SAVE' ). + + ls_bcdata-program = 'SAPLSTRD'. + ls_bcdata-dynpro = '0100'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO mt_bcdata. + + add_data( iv_fnam = 'KO007-L_DEVCLASS' + iv_fval = iv_package ). + + add_data( iv_fnam = 'BDC_OKCODE' + iv_fval = '=ADD' ). + + ls_bcdata-program = 'BDC_OKCODE'. + ls_bcdata-dynpro = '0360'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO mt_bcdata. + + add_data( iv_fnam = 'BDC_OKCODE' + iv_fval = '=WB_BACK' ). + + ls_bcdata-program = 'BDC_OKCODE'. + ls_bcdata-dynpro = '0360'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO mt_bcdata. + + add_data( iv_fnam = 'BDC_OKCODE' + iv_fval = '=WB_BACK' ). + + call_se93( ). + + ENDMETHOD. + METHOD deserialize_texts. + + DATA lt_tpool_i18n TYPE TABLE OF tstct. + + FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. + + " Read XML-files data + ii_xml->read( EXPORTING iv_name = 'I18N_TPOOL' + CHANGING cg_data = lt_tpool_i18n ). + + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'SPRSL' + CHANGING + ct_tab = lt_tpool_i18n ). + + " Force t-code name (security reasons) + LOOP AT lt_tpool_i18n ASSIGNING . + -tcode = ms_item-obj_name. + ENDLOOP. + + IF lines( lt_tpool_i18n ) > 0. + MODIFY tstct FROM TABLE lt_tpool_i18n. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Update of t-code translations failed' ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD is_variant_transaction. + + rv_variant_transaction = boolc( is_tstcp-param(1) = '@' ). + + ENDMETHOD. + METHOD save_authorizations. + + CONSTANTS: lc_hex_chk TYPE x VALUE '04'. + DATA: ls_transaction TYPE tstc. + + transaction_read( EXPORTING iv_transaction = iv_transaction + IMPORTING es_transaction = ls_transaction ). + + DELETE FROM tstca WHERE tcode = iv_transaction. + + IF ls_transaction IS NOT INITIAL. + INSERT tstca FROM TABLE it_authorizations. + ls_transaction-cinfo = ls_transaction-cinfo + lc_hex_chk. + UPDATE tstc SET cinfo = ls_transaction-cinfo WHERE tcode = ls_transaction-tcode. + ENDIF. + + ENDMETHOD. + METHOD serialize_texts. + + DATA lt_tpool_i18n TYPE TABLE OF tstct. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + " Skip main language - it was already serialized + " Don't serialize t-code itself + SELECT sprsl ttext + INTO CORRESPONDING FIELDS OF TABLE lt_tpool_i18n + FROM tstct + WHERE sprsl <> mv_language + AND tcode = ms_item-obj_name + ORDER BY sprsl ##TOO_MANY_ITAB_FIELDS. "#EC CI_GENBUFF + + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'SPRSL' + CHANGING + ct_tab = lt_tpool_i18n ). + + IF lines( lt_tpool_i18n ) > 0. + SORT lt_tpool_i18n BY sprsl ASCENDING. + ii_xml->add( iv_name = 'I18N_TPOOL' + ig_data = lt_tpool_i18n ). + ENDIF. + + ENDMETHOD. + METHOD set_oo_parameters. + + DATA: ls_param LIKE LINE OF it_rsparam. + + IF cs_rsstcd-call_tcode = c_oo_tcode. + cs_rsstcd-s_trframe = c_true. + LOOP AT it_rsparam INTO ls_param. + CASE ls_param-field. + WHEN c_oo_frclass. + cs_rsstcd-classname = ls_param-value. + WHEN c_oo_frmethod. + cs_rsstcd-method = ls_param-value. + WHEN c_oo_frupdtask. + IF ls_param-value = c_oo_synchron. + cs_rsstcd-s_upddir = c_true. + cs_rsstcd-s_updtask = c_false. + cs_rsstcd-s_updlok = c_false. + ELSEIF ls_param-value = c_oo_asynchron. + cs_rsstcd-s_upddir = c_false. + cs_rsstcd-s_updtask = c_true. + cs_rsstcd-s_updlok = c_false. + ELSE. + cs_rsstcd-s_upddir = c_false. + cs_rsstcd-s_updtask = c_false. + cs_rsstcd-s_updlok = c_true. + ENDIF. + ENDCASE. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD shift_param. + + DATA: ls_param LIKE LINE OF ct_rsparam, + lv_fdpos TYPE sy-fdpos, + lv_length TYPE i. + + FIELD-SYMBOLS TYPE any. + DO 254 TIMES. + IF cs_tstcp-param = space. + EXIT. + ENDIF. + CLEAR ls_param. + IF cs_tstcp-param CA '='. + CHECK sy-fdpos <> 0. + ASSIGN cs_tstcp-param(sy-fdpos) TO . + ls_param-field = . + IF ls_param-field(1) = space. + SHIFT ls_param-field. + ENDIF. + lv_fdpos = sy-fdpos + 1. + SHIFT cs_tstcp-param BY lv_fdpos PLACES. + IF cs_tstcp-param CA ';'. + IF sy-fdpos <> 0. + ASSIGN cs_tstcp-param(sy-fdpos) TO . + ls_param-value = . + IF ls_param-value(1) = space. + SHIFT ls_param-value. + ENDIF. + ENDIF. + lv_fdpos = sy-fdpos + 1. + SHIFT cs_tstcp-param BY lv_fdpos PLACES. + APPEND ls_param TO ct_rsparam. + ELSE. + lv_length = strlen( cs_tstcp-param ). + CHECK lv_length > 0. + ASSIGN cs_tstcp-param(lv_length) TO . + ls_param-value = . + IF ls_param-value(1) = space. + SHIFT ls_param-value. + ENDIF. + lv_length = lv_length + 1. + SHIFT cs_tstcp-param BY lv_length PLACES. + APPEND ls_param TO ct_rsparam. + ENDIF. + ENDIF. + ENDDO. + + ENDMETHOD. + METHOD split_parameters. +* see subroutine split_parameters in include LSEUKF01 + + DATA: lv_off TYPE i, + lv_fdpos TYPE sy-fdpos, + lv_param_beg TYPE i. + CLEAR cs_rsstcd-s_vari. + + IF cs_tstcp-param(1) = '\'. " OO-Transaction without FR + split_parameters_comp( EXPORTING ig_type = c_oo_program + ig_param = cs_tstcp-param + CHANGING cg_value = cs_tstc-pgmna ). + split_parameters_comp( EXPORTING ig_type = c_oo_class + ig_param = cs_tstcp-param + CHANGING cg_value = cs_rsstcd-classname ). + split_parameters_comp( EXPORTING ig_type = c_oo_method + ig_param = cs_tstcp-param + CHANGING cg_value = cs_rsstcd-method ). + + IF NOT cs_tstc-pgmna IS INITIAL. + cs_rsstcd-s_local = c_true. + ENDIF. + RETURN. + ELSEIF cs_tstcp-param(1) = '@'. " Transaction variant + cs_rsstcd-s_vari = c_true. + IF cs_tstcp-param(2) = '@@'. + cs_rsstcd-s_ind_vari = c_true. + lv_off = 2. + ELSE. + CLEAR cs_rsstcd-s_ind_vari. + lv_off = 1. + ENDIF. + IF cs_tstcp-param CA ' '. + ENDIF. + lv_fdpos = sy-fdpos - lv_off. + IF lv_fdpos > 0. + cs_rsstcd-call_tcode = cs_tstcp-param+lv_off(sy-fdpos). + lv_fdpos = lv_fdpos + 1 + lv_off. + cs_rsstcd-variant = cs_tstcp-param+lv_fdpos. + ENDIF. + ELSEIF cs_tstcp-param(1) = '/'. + cs_rsstcd-st_tcode = c_true. + cs_rsstcd-st_prog = space. + IF cs_tstcp-param+1(1) = '*'. + cs_rsstcd-st_skip_1 = c_true. + ELSE. + CLEAR cs_rsstcd-st_skip_1. + ENDIF. + IF cs_tstcp-param CA ' '. + ENDIF. + lv_param_beg = sy-fdpos + 1. + lv_fdpos = sy-fdpos - 2. + IF lv_fdpos > 0. + cs_rsstcd-call_tcode = cs_tstcp-param+2(lv_fdpos). + ENDIF. + SHIFT cs_tstcp-param BY lv_param_beg PLACES. + ELSE. + cs_rsstcd-st_tcode = space. + cs_rsstcd-st_prog = c_true. + ENDIF. + + shift_param( + CHANGING ct_rsparam = ct_rsparam + cs_tstcp = cs_tstcp ). + + set_oo_parameters( + EXPORTING it_rsparam = ct_rsparam + CHANGING cs_rsstcd = cs_rsstcd ). + + ENDMETHOD. + METHOD split_parameters_comp. + DATA: lv_off TYPE i. + + IF ig_param CS ig_type. + lv_off = sy-fdpos + strlen( ig_type ). + cg_value = ig_param+lv_off. + IF cg_value CA '\'. + CLEAR cg_value+sy-fdpos. + ENDIF. + ENDIF. + ENDMETHOD. + METHOD transaction_read. + + DATA: lt_tcodes TYPE TABLE OF tstc, + lt_gui_attr TYPE TABLE OF tstcc. + + CLEAR: es_transaction, es_gui_attr. + + CALL FUNCTION 'RPY_TRANSACTION_READ' + EXPORTING + transaction = iv_transaction + TABLES + tcodes = lt_tcodes + gui_attributes = lt_gui_attr + EXCEPTIONS + permission_error = 1 + cancelled = 2 + not_found = 3 + object_not_found = 4 + OTHERS = 5. + IF sy-subrc = 4 OR sy-subrc = 3. + RETURN. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + READ TABLE lt_tcodes INDEX 1 INTO es_transaction. + ASSERT sy-subrc = 0. + READ TABLE lt_gui_attr INDEX 1 INTO es_gui_attr. + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + " Changed-by-user is not stored in transaction metadata + " Instead, use owner of last transport or object directory + + DATA lv_transport TYPE trkorr. + + lv_transport = zcl_abapgit_factory=>get_cts_api( )->get_transport_for_object( ms_item ). + + IF lv_transport IS NOT INITIAL. + SELECT SINGLE as4user FROM e070 INTO rv_user WHERE trkorr = lv_transport. + ELSE. + SELECT SINGLE author FROM tadir INTO rv_user + WHERE pgmid = 'R3TR' AND object = ms_item-obj_type AND obj_name = ms_item-obj_name. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_transaction TYPE tstc-tcode. + lv_transaction = ms_item-obj_name. + + CALL FUNCTION 'RPY_TRANSACTION_DELETE' + EXPORTING + transaction = lv_transaction + EXCEPTIONS + not_excecuted = 1 + object_not_found = 0 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + CONSTANTS: lc_hex_tra TYPE x VALUE '00', +* lc_hex_men TYPE x VALUE '01', + lc_hex_par TYPE x VALUE '02', + lc_hex_rep TYPE x VALUE '80', +* lc_hex_rpv TYPE x VALUE '10', + lc_hex_obj TYPE x VALUE '08'. + + DATA: lv_dynpro TYPE d020s-dnum, + ls_tstc TYPE tstc, + lv_type TYPE rglif-docutype, + ls_tstct TYPE tstct, + ls_tstcc TYPE tstcc, + ls_tstcp TYPE tstcp, + lt_tstca TYPE ty_tstca, + lt_param_values TYPE ty_param_values, + ls_rsstcd TYPE rsstcd. + IF zif_abapgit_object~exists( ) = abap_true. + zif_abapgit_object~delete( iv_package = iv_package + iv_transport = iv_transport ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'TSTC' + CHANGING cg_data = ls_tstc ). + io_xml->read( EXPORTING iv_name = 'TSTCC' + CHANGING cg_data = ls_tstcc ). + io_xml->read( EXPORTING iv_name = 'TSTCT' + CHANGING cg_data = ls_tstct ). + io_xml->read( EXPORTING iv_name = 'TSTCP' + CHANGING cg_data = ls_tstcp ). + io_xml->read( EXPORTING iv_name = 'AUTHORIZATIONS' + CHANGING cg_data = lt_tstca ). + + lv_dynpro = ls_tstc-dypno. + + IF ls_tstc-cinfo O lc_hex_rep. + lv_type = c_variant_type-report. + ELSEIF ls_tstc-cinfo O lc_hex_obj. + lv_type = c_variant_type-object. + ELSEIF ls_tstc-cinfo O lc_hex_par. + IF is_variant_transaction( ls_tstcp ) = abap_true. + lv_type = c_variant_type-variant. + ELSE. + lv_type = c_variant_type-parameters. + ENDIF. + ELSEIF ls_tstc-cinfo O lc_hex_tra. + lv_type = c_variant_type-dialog. + ELSE. + zcx_abapgit_exception=>raise( 'Transaction, unknown CINFO' ). + ENDIF. + + IF ls_tstcp IS NOT INITIAL. + split_parameters( CHANGING ct_rsparam = lt_param_values + cs_rsstcd = ls_rsstcd + cs_tstcp = ls_tstcp + cs_tstc = ls_tstc ). + ENDIF. + + CASE lv_type. + WHEN c_variant_type-object. + + deserialize_oo_transaction( iv_package = iv_package + is_tstc = ls_tstc + is_tstcc = ls_tstcc + is_tstct = ls_tstct + is_rsstcd = ls_rsstcd ). + + WHEN OTHERS. + + clear_functiongroup_globals( ). + + corr_insert( iv_package ). + + CALL FUNCTION 'RPY_TRANSACTION_INSERT' + EXPORTING + transaction = ls_tstc-tcode + program = ls_tstc-pgmna + dynpro = lv_dynpro + language = mv_language + development_class = iv_package + transaction_type = lv_type + shorttext = ls_tstct-ttext + called_transaction = ls_rsstcd-call_tcode + called_transaction_skip = ls_rsstcd-st_skip_1 + variant = ls_rsstcd-variant + cl_independend = ls_rsstcd-s_ind_vari + html_enabled = ls_tstcc-s_webgui + java_enabled = ls_tstcc-s_platin + wingui_enabled = ls_tstcc-s_win32 + suppress_corr_insert = abap_true + TABLES + param_values = lt_param_values + EXCEPTIONS + cancelled = 1 + already_exist = 2 + permission_error = 3 + name_not_allowed = 4 + name_conflict = 5 + illegal_type = 6 + object_inconsistent = 7 + db_access_error = 8 + OTHERS = 9. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDCASE. + + IF lt_tstca IS NOT INITIAL. + save_authorizations( iv_transaction = ls_tstc-tcode + it_authorizations = lt_tstca ). + ENDIF. + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + deserialize_texts( io_xml ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_tcode TYPE tstc-tcode. + SELECT SINGLE tcode FROM tstc INTO lv_tcode + WHERE tcode = ms_item-obj_name. "#EC CI_GENBUFF + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' + iv_argument = ms_item-obj_name + iv_prefix = 'TN' ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPLSEUK'. + -dynpro = '0390'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=SHOW'. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'TSTC-TCODE'. + -fval = ms_item-obj_name. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SE93' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_transaction TYPE tstc-tcode, + ls_tcode TYPE tstc, + ls_tstct TYPE tstct, + ls_tstcp TYPE tstcp, + lt_tstca TYPE ty_tstca, + ls_gui_attr TYPE tstcc. + lv_transaction = ms_item-obj_name. + + transaction_read( EXPORTING iv_transaction = lv_transaction + IMPORTING es_transaction = ls_tcode + es_gui_attr = ls_gui_attr ). + IF ls_tcode IS INITIAL. + RETURN. + ENDIF. + + SELECT SINGLE * FROM tstct INTO ls_tstct + WHERE sprsl = mv_language + AND tcode = lv_transaction. "#EC CI_SUBRC "#EC CI_GENBUFF + + SELECT SINGLE * FROM tstcp INTO ls_tstcp + WHERE tcode = lv_transaction. "#EC CI_SUBRC "#EC CI_GENBUFF + + SELECT * FROM tstca INTO TABLE lt_tstca + WHERE tcode = lv_transaction + ORDER BY PRIMARY KEY. + IF sy-subrc <> 0. + CLEAR: lt_tstca. + ENDIF. + + io_xml->add( iv_name = 'TSTC' + ig_data = ls_tcode ). + io_xml->add( iv_name = 'TSTCC' + ig_data = ls_gui_attr ). + io_xml->add( iv_name = 'TSTCT' + ig_data = ls_tstct ). + IF ls_tstcp IS NOT INITIAL. + io_xml->add( iv_name = 'TSTCP' + ig_data = ls_tstcp ). + ENDIF. + io_xml->add( iv_name = 'AUTHORIZATIONS' + ig_data = lt_tstca ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + serialize_texts( io_xml ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_tobj IMPLEMENTATION. + METHOD delete_extra. + + DELETE FROM tddat WHERE tabname = iv_tabname. + DELETE FROM tvdir WHERE tabname = iv_tabname. + DELETE FROM tvimf WHERE tabname = iv_tabname. + + ENDMETHOD. + METHOD read_extra. + + SELECT SINGLE * FROM tddat INTO rs_tobj-tddat WHERE tabname = iv_tabname. + + SELECT SINGLE * FROM tvdir INTO rs_tobj-tvdir WHERE tabname = iv_tabname. + CLEAR: rs_tobj-tvdir-gendate, rs_tobj-tvdir-gentime, rs_tobj-tvdir-devclass. + + SELECT * FROM tvimf INTO TABLE rs_tobj-tvimf WHERE tabname = iv_tabname + ORDER BY PRIMARY KEY. + + ENDMETHOD. + METHOD update_extra. + DATA: lt_current_tvimf TYPE STANDARD TABLE OF tvimf. + FIELD-SYMBOLS: TYPE tvimf. + + MODIFY tddat FROM is_tobj-tddat. + MODIFY tvdir FROM is_tobj-tvdir. + + SELECT * INTO TABLE lt_current_tvimf + FROM tvimf + WHERE tabname = is_tobj-tddat-tabname + ORDER BY PRIMARY KEY. + + LOOP AT lt_current_tvimf ASSIGNING . + READ TABLE is_tobj-tvimf WITH KEY tabname = -tabname + event = -event + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + DELETE FROM tvimf + WHERE tabname = -tabname + AND event = -event. + ENDIF. + ENDLOOP. + + MODIFY tvimf FROM TABLE is_tobj-tvimf. + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_type_pos TYPE i. + + lv_type_pos = strlen( ms_item-obj_name ) - 1. + + SELECT SINGLE luser FROM objh INTO rv_user + WHERE objectname = ms_item-obj_name(lv_type_pos) + AND objecttype = ms_item-obj_name+lv_type_pos. "#EC CI_GENBUFF + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: ls_objh TYPE objh, + lv_type_pos TYPE i. + + lv_type_pos = strlen( ms_item-obj_name ) - 1. + + ls_objh-objectname = ms_item-obj_name(lv_type_pos). + ls_objh-objecttype = ms_item-obj_name+lv_type_pos. + + IF ls_objh-objecttype = 'L'. + zcx_abapgit_exception=>raise( |Use transaction SOBJ to delete transport objects { ls_objh-objectname }| ). + ENDIF. + + CALL FUNCTION 'OBJ_GENERATE' + EXPORTING + iv_korrnum = iv_transport + iv_objectname = ls_objh-objectname + iv_objecttype = ls_objh-objecttype + iv_maint_mode = 'D' + EXCEPTIONS + illegal_call = 1 + object_not_found = 2 + generate_error = 3 + transport_error = 4 + object_enqueue_failed = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + delete_extra( ls_objh-objectname ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_objh TYPE objh, + ls_objt TYPE objt, + lt_objs TYPE tt_objs, + lt_objsl TYPE tt_objsl, + lt_objm TYPE tt_objm, + ls_tobj TYPE ty_tobj. + io_xml->read( EXPORTING iv_name = 'OBJH' + CHANGING cg_data = ls_objh ). + io_xml->read( EXPORTING iv_name = 'OBJT' + CHANGING cg_data = ls_objt ). + io_xml->read( EXPORTING iv_name = 'OBJS' + CHANGING cg_data = lt_objs ). + io_xml->read( EXPORTING iv_name = 'OBJSL' + CHANGING cg_data = lt_objsl ). + io_xml->read( EXPORTING iv_name = 'OBJM' + CHANGING cg_data = lt_objm ). + + CALL FUNCTION 'OBJ_GENERATE' + EXPORTING + iv_korrnum = iv_transport + iv_objectname = ls_objh-objectname + iv_objecttype = ls_objh-objecttype + iv_maint_mode = 'I' + iv_objecttext = ls_objt-ddtext + iv_objcateg = ls_objh-objcateg + iv_objtransp = ls_objh-objtransp + iv_devclass = iv_package + TABLES + tt_v_obj_s = lt_objs + tt_objm = lt_objm + EXCEPTIONS + illegal_call = 1 + object_not_found = 2 + generate_error = 3 + transport_error = 4 + object_enqueue_failed = 5 + OTHERS = 6. + IF sy-subrc <> 0. +* TOBJ has to be saved/generated after the DDIC tables have been +* activated - fixed with late deserialization + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'OBJ_SET_IMPORTABLE' + EXPORTING + iv_objectname = ls_objh-objectname + iv_objecttype = ls_objh-objecttype + iv_importable = ls_objh-importable + EXCEPTIONS + object_not_defined = 1 + invalid = 2 + transport_error = 3 + object_enqueue_failed = 4 + OTHERS = 5. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + +* fm OBJ_GENERATE takes the defaults from the DDIC object +* set OBJTRANSP directly, should be okay looking at the code in OBJ_SET_IMPORTABLE +* locking has been done in OBJ_SET_IMPORTABLE plus recording of transport + UPDATE objh SET objtransp = ls_objh-objtransp + WHERE objectname = ls_objh-objectname + AND objecttype = ls_objh-objecttype. + + io_xml->read( EXPORTING iv_name = 'TOBJ' + CHANGING cg_data = ls_tobj ). + ls_tobj-tvdir-gendate = sy-datum. + ls_tobj-tvdir-gentime = sy-uzeit. + ls_tobj-tvdir-devclass = iv_package. + + update_extra( ls_tobj ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_objectname TYPE objh-objectname, + lv_type_pos TYPE i. + + lv_type_pos = strlen( ms_item-obj_name ) - 1. + + SELECT SINGLE objectname FROM objh INTO lv_objectname + WHERE objectname = ms_item-obj_name(lv_type_pos) + AND objecttype = ms_item-obj_name+lv_type_pos. "#EC CI_GENBUFF + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lv_object_name TYPE e071-obj_name. + + lv_object_name = ms_item-obj_name. + + CALL FUNCTION 'TR_OBJECT_JUMP_TO_TOOL' + EXPORTING + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = lv_object_name + EXCEPTIONS + jump_not_possible = 1 + OTHERS = 2. + + rv_exit = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_objh TYPE objh, + ls_objt TYPE objt, + lt_objs TYPE tt_objs, + lt_objsl TYPE tt_objsl, + lt_objm TYPE tt_objm, + ls_tobj TYPE ty_tobj, + lv_type_pos TYPE i. + + lv_type_pos = strlen( ms_item-obj_name ) - 1. + + ls_objh-objectname = ms_item-obj_name(lv_type_pos). + ls_objh-objecttype = ms_item-obj_name+lv_type_pos. + + CALL FUNCTION 'CTO_OBJECT_GET' + EXPORTING + iv_objectname = ls_objh-objectname + iv_objecttype = ls_objh-objecttype + iv_language = mv_language + iv_sel_objt = abap_true + iv_sel_objs = abap_true + iv_sel_objsl = abap_true + iv_sel_objm = abap_true + IMPORTING + es_objh = ls_objh + es_objt = ls_objt + TABLES + tt_objs = lt_objs + tt_objsl = lt_objsl + tt_objm = lt_objm + EXCEPTIONS + object_not_defined = 1 + OTHERS = 2. + IF sy-subrc = 1. + RETURN. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CLEAR: ls_objh-luser, + ls_objh-ldate. + + SORT lt_objs BY objectname objecttype tabname. + SORT lt_objsl BY objectname objecttype trwcount. + SORT lt_objm BY objectname objecttype method. + + io_xml->add( iv_name = 'OBJH' + ig_data = ls_objh ). + io_xml->add( iv_name = 'OBJT' + ig_data = ls_objt ). + io_xml->add( iv_name = 'OBJS' + ig_data = lt_objs ). + io_xml->add( iv_name = 'OBJSL' + ig_data = lt_objsl ). + io_xml->add( iv_name = 'OBJM' + ig_data = lt_objm ). + + ls_tobj = read_extra( ls_objh-objectname ). + + IF ls_tobj-tvdir-detail = ``. + " to prevent xslt serialization error, + " force clear if numc field is empty + CLEAR ls_tobj-tvdir-detail. + ENDIF. + + io_xml->add( iv_name = 'TOBJ' + ig_data = ls_tobj ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sxsd IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + SELECT SINGLE * FROM sxc_attr INTO ms_badi_attr WHERE imp_name = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + IF ms_badi_attr-uname IS NOT INITIAL. + rv_user = ms_badi_attr-uname. + ELSE. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + "Not allowed, SAP Object + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + " Not allowed, SAP Object + " Can't create Z-BADIs since at least 7.0 + zcx_abapgit_exception=>raise_t100( + iv_msgid = 'ENHANCEMENT' + iv_msgno = '269' ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + rv_bool = boolc( ms_badi_attr IS NOT INITIAL ). + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + "Not allowed, SAP Object + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + "Serialize only, irrelevant + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA lv_exit_name TYPE rsexscrn-exit_name. + + lv_exit_name = ms_item-obj_name. + + CALL FUNCTION 'SXO_BADI_SHOW' + EXPORTING + exit_name = lv_exit_name + EXCEPTIONS + action_canceled = 1 + access_failure = 2 + badi_not_exixting = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( + iv_msgid = sy-msgid + iv_msgno = sy-msgno + iv_msgv1 = sy-msgv1 + iv_msgv2 = sy-msgv2 + iv_msgv3 = sy-msgv3 + iv_msgv4 = sy-msgv4 ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + TYPES: BEGIN OF ty_badi_definition, + badi TYPE badi_data, + mast_langu TYPE sy-langu, + ext_clname TYPE seoclsname, + fcodes TYPE seex_fcode_table, + cocos TYPE seex_coco_table, + intas TYPE seex_table_table, + scrns TYPE seex_screen_table, + methods TYPE seex_mtd_table, + inactive_tabstrips TYPE seex_inactive_tabstrips, + END OF ty_badi_definition. + + DATA ls_badi_definition TYPE ty_badi_definition. + DATA lv_exit_name TYPE rsexscrn-exit_name. + + lv_exit_name = ms_item-obj_name. + + CALL FUNCTION 'SXO_BADI_READ' + EXPORTING + exit_name = lv_exit_name + IMPORTING + badi = ls_badi_definition-badi + mast_langu = ls_badi_definition-mast_langu + ext_clname = ls_badi_definition-ext_clname + TABLES + fcodes = ls_badi_definition-fcodes + cocos = ls_badi_definition-cocos + intas = ls_badi_definition-intas + scrns = ls_badi_definition-scrns + methods = ls_badi_definition-methods + inactive_tabstrips = ls_badi_definition-inactive_tabstrips + EXCEPTIONS + read_failure = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Could not read definition for BAdI { lv_exit_name }| ). + ENDIF. + + CLEAR: ls_badi_definition-badi-uname, + ls_badi_definition-badi-udate, + ls_badi_definition-badi-utime. + + io_xml->add( + iv_name = 'SXSD' + ig_data = ls_badi_definition ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sxci IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE uname FROM sxc_attr INTO rv_user WHERE imp_name = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_implementation_name TYPE rsexscrn-imp_name. + + lv_implementation_name = ms_item-obj_name. + + CALL FUNCTION 'SXO_IMPL_DELETE' + EXPORTING + imp_name = lv_implementation_name + no_dialog = abap_true + EXCEPTIONS + imp_not_existing = 1 + action_canceled = 2 + access_failure = 3 + data_inconsistency = 4 + OTHERS = 5. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_badi_definition TYPE badi_data, + lo_filter_object TYPE REF TO cl_badi_flt_struct, + lo_filter_values_object TYPE REF TO cl_badi_flt_values_alv, + lv_korrnum TYPE trkorr, + lv_filter_type_enhanceability TYPE rsexscrn-flt_ext, + lv_package TYPE devclass, + ls_classic_badi_implementation TYPE ty_classic_badi_implementation. + + io_xml->read( + EXPORTING + iv_name = 'SXCI' + CHANGING + cg_data = ls_classic_badi_implementation ). + + CALL FUNCTION 'SXO_BADI_READ' + EXPORTING + exit_name = ls_classic_badi_implementation-implementation_data-exit_name + IMPORTING + badi = ls_badi_definition + filter_obj = lo_filter_object + EXCEPTIONS + read_failure = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + lv_package = iv_package. + + CREATE OBJECT lo_filter_values_object + EXPORTING + filter_object = lo_filter_object + filter_values = ls_classic_badi_implementation-filters. + + CALL FUNCTION 'SXO_IMPL_SAVE' + EXPORTING + impl = ls_classic_badi_implementation-implementation_data + flt_ext = lv_filter_type_enhanceability + filter_val_obj = lo_filter_values_object + genflag = abap_true + no_dialog = abap_true + TABLES + fcodes_to_insert = ls_classic_badi_implementation-function_codes + cocos_to_insert = ls_classic_badi_implementation-control_composites + intas_to_insert = ls_classic_badi_implementation-customer_includes + sscrs_to_insert = ls_classic_badi_implementation-screens + CHANGING + korrnum = lv_korrnum + devclass = lv_package + EXCEPTIONS + save_failure = 1 + action_canceled = 2 + OTHERS = 3. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'SXO_IMPL_ACTIVE' + EXPORTING + imp_name = ls_classic_badi_implementation-implementation_data-imp_name + no_dialog = abap_true + EXCEPTIONS + badi_not_existing = 1 + imp_not_existing = 2 + already_active = 3 + data_inconsistency = 4 + activation_not_admissable = 5 + action_canceled = 6 + access_failure = 7 + OTHERS = 8. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_implementation_name TYPE rsexscrn-imp_name. + + lv_implementation_name = ms_item-obj_name. + + CALL FUNCTION 'SXV_IMP_EXISTS' + EXPORTING + imp_name = lv_implementation_name + EXCEPTIONS + not_existing = 1 + data_inconsistency = 2 + OTHERS = 3. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + + rs_metadata = get_metadata( ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + + "Note: SAP does not show inactive classic BAdIs as "Inactive objects" in SE80 + "Therefore, rv_active will always be true. The implementation state (runtime + "behaviour of the BAdI) will be serialized as part of the XML + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_implementation_name TYPE rsexscrn-imp_name, + lv_exit_name TYPE rsexscrn-exit_name, + lo_filter_object TYPE REF TO cl_badi_flt_struct, + ls_badi_definition TYPE badi_data, + lo_filter_values_object TYPE REF TO cl_badi_flt_values_alv, + lt_methods TYPE seex_mtd_table, + ls_classic_badi_implementation TYPE ty_classic_badi_implementation. + + lv_implementation_name = ms_item-obj_name. + + CALL FUNCTION 'SXV_EXIT_FOR_IMP' + EXPORTING + imp_name = lv_implementation_name + IMPORTING + exit_name = lv_exit_name + TABLES + filters = ls_classic_badi_implementation-filters + EXCEPTIONS + data_inconsistency = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'SXO_BADI_READ' + EXPORTING + exit_name = lv_exit_name + IMPORTING + badi = ls_badi_definition + filter_obj = lo_filter_object + TABLES + fcodes = ls_classic_badi_implementation-function_codes + cocos = ls_classic_badi_implementation-control_composites + intas = ls_classic_badi_implementation-customer_includes + scrns = ls_classic_badi_implementation-screens + methods = lt_methods + EXCEPTIONS + read_failure = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'SXO_IMPL_FOR_BADI_READ' + EXPORTING + imp_name = lv_implementation_name + exit_name = lv_exit_name + inter_name = ls_badi_definition-inter_name + filter_obj = lo_filter_object + no_create_filter_values_obj = abap_true + IMPORTING + impl = ls_classic_badi_implementation-implementation_data + filter_values_obj = lo_filter_values_object + TABLES + fcodes = ls_classic_badi_implementation-function_codes + cocos = ls_classic_badi_implementation-control_composites + intas = ls_classic_badi_implementation-customer_includes + scrns = ls_classic_badi_implementation-screens + CHANGING + methods = lt_methods + EXCEPTIONS + read_failure = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CLEAR: ls_classic_badi_implementation-implementation_data-aname, + ls_classic_badi_implementation-implementation_data-adate, + ls_classic_badi_implementation-implementation_data-atime, + ls_classic_badi_implementation-implementation_data-uname, + ls_classic_badi_implementation-implementation_data-udate, + ls_classic_badi_implementation-implementation_data-utime. + + io_xml->add( iv_name = 'SXCI' + ig_data = ls_classic_badi_implementation ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_suso IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_objectname = ms_item-obj_name. + + ENDMETHOD. + METHOD delete_documentation. + + DATA: + lv_docu_obj TYPE dokhl-object, + lv_dummy TYPE sy-langu. + + lv_docu_obj = mv_objectname. + + SELECT SINGLE langu + FROM dokil INTO lv_dummy + WHERE id = 'UO' "#EC CI_GENBUFF + AND object = lv_docu_obj. "#EC CI_NOORDER + + IF sy-subrc = 0. + + CALL FUNCTION 'DOKU_DELETE_ALL' + EXPORTING + doku_id = 'UO' + doku_object = lv_docu_obj + suppress_transport = space + EXCEPTIONS + header_without_text = 1 + index_without_header = 2 + no_authority_for_devclass_xxxx = 3 + no_docu_found = 4 + object_is_already_enqueued = 5 + object_is_enqueued_by_corr = 6 + techn_enqueue_problem = 7 + user_break = 8 + OTHERS = 9. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD pre_check. + + CONSTANTS: + lc_act_delete TYPE activ_auth VALUE '06'. + + DATA: + lv_act_head TYPE activ_auth, + lo_suso TYPE REF TO object, + lv_failed TYPE abap_bool, + lv_suso_collect_in_cts TYPE i, + ls_clskey TYPE seoclskey. + + " Downport: CL_SUSO_GEN doesn't exist in 702 + ls_clskey-clsname = |CL_SUSO_GEN|. + + CALL FUNCTION 'SEO_CLASS_EXISTENCE_CHECK' + EXPORTING + clskey = ls_clskey + EXCEPTIONS + not_specified = 1 + not_existing = 2 + is_interface = 3 + no_text = 4 + inconsistent = 5 + OTHERS = 6. + + IF sy-subrc = 0. + + " so these checks are not executed in 702 + + CREATE OBJECT lo_suso + TYPE + ('CL_SUSO_GEN'). + + CALL METHOD lo_suso->('SUSO_LOAD_FROM_DB') + EXPORTING + id_object = mv_objectname + RECEIVING + ed_failed = lv_failed. + + IF lv_failed = abap_true. + " Object & does not exist; choose an existing object + MESSAGE s111(01) WITH mv_objectname INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL METHOD lo_suso->('GET_SUSO_EDIT_MODE') + EXPORTING + id_object = mv_objectname + id_planed_act = lc_act_delete + IMPORTING + ed_mode_head = lv_act_head. + + IF lv_act_head <> lc_act_delete. + zcx_abapgit_exception=>raise( |SUSO { mv_objectname }: Delete not allowed. Check where-used in SU21| ). + ENDIF. + + CALL METHOD lo_suso->('SUSO_COLLECT_IN_CTS') + EXPORTING + id_object = mv_objectname + RECEIVING + ed_result = lv_suso_collect_in_cts. + + IF lv_suso_collect_in_cts IS NOT INITIAL. + zcx_abapgit_exception=>raise( |SUSO { mv_objectname }: Cannot delete| ). + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD regenerate_sap_all. + + DATA: ls_e071 TYPE e071, + lt_e071 TYPE STANDARD TABLE OF e071, + lt_e071k TYPE STANDARD TABLE OF e071k. + + ls_e071-pgmid = 'R3TR'. + ls_e071-object = ms_item-obj_type. + ls_e071-obj_name = ms_item-obj_name. + INSERT ls_e071 INTO TABLE lt_e071. + + CALL FUNCTION 'PRGN_AFTER_IMP_SUSO_SAP_ALL' + EXPORTING + iv_tarclient = '000' + iv_is_upgrade = space + TABLES + tt_e071 = lt_e071 + tt_e071k = lt_e071k. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + SELECT SINGLE modifier FROM tobjvor INTO rv_user + WHERE objct = mv_objectname. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + " FM SUSR_DELETE_OBJECT calls the UI. Therefore we reimplement it here. + " As the class CL_SUSO_GEN isn't present in 702, we call dynamically and + " skip the pre checks on 702 system. That seems ok. + + pre_check( ). + + delete_documentation( ). + + DELETE FROM tobj WHERE objct = mv_objectname. + DELETE FROM tobjt WHERE object = mv_objectname. + DELETE FROM tactz WHERE brobj = mv_objectname. + + CALL FUNCTION 'SUPV_DELETE_OBJECT_ASSIGNMENTS' + EXPORTING + object_name = mv_objectname + all_releases = abap_true. + + CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' + EXPORTING + object = mv_objectname + type = 'SUSO' + operation = 'DELETE'. + + regenerate_sap_all( ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. +* see function group SUSA + + DATA: lv_objectname TYPE trobj_name, + ls_tobj TYPE tobj, + ls_tobjt TYPE tobjt, + ls_tobjvorflg TYPE tobjvorflg, + lt_tactz TYPE TABLE OF tactz, + lt_tobjvordat TYPE TABLE OF tobjvordat, + lt_tobjvor TYPE TABLE OF tobjvor. + ASSERT NOT ms_item-obj_name IS INITIAL. + + io_xml->read( EXPORTING iv_name = 'TOBJ' + CHANGING cg_data = ls_tobj ). + ls_tobj-bname = sy-uname. + io_xml->read( EXPORTING iv_name = 'TOBJT' + CHANGING cg_data = ls_tobjt ). + io_xml->read( EXPORTING iv_name = 'TOBJVORFLG' + CHANGING cg_data = ls_tobjvorflg ). + io_xml->read( EXPORTING iv_name = 'TACTZ' + CHANGING cg_data = lt_tactz ). + io_xml->read( EXPORTING iv_name = 'TOBJVORDAT' + CHANGING cg_data = lt_tobjvordat ). + io_xml->read( EXPORTING iv_name = 'TOBJVOR' + CHANGING cg_data = lt_tobjvor ). + + tadir_insert( iv_package ). + + lv_objectname = mv_objectname. + + CALL FUNCTION 'SUSR_COMMEDITCHECK' + EXPORTING + objectname = lv_objectname + transobjecttype = 'O'. + + MODIFY tobj FROM ls_tobj. "#EC CI_SUBRC + MODIFY tobjt FROM ls_tobjt. "#EC CI_SUBRC + MODIFY tobjvorflg FROM ls_tobjvorflg. "#EC CI_SUBRC + DELETE FROM tactz WHERE brobj = ms_item-obj_name. "#EC CI_SUBRC + INSERT tactz FROM TABLE lt_tactz. "#EC CI_SUBRC + DELETE FROM tobjvordat WHERE objct = ms_item-obj_name. "#EC CI_SUBRC + INSERT tobjvordat FROM TABLE lt_tobjvordat. "#EC CI_SUBRC + DELETE FROM tobjvor WHERE objct = ms_item-obj_name. "#EC CI_SUBRC + INSERT tobjvor FROM TABLE lt_tobjvor. "#EC CI_SUBRC + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_suso ). + + regenerate_sap_all( ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_objct TYPE tobj-objct. + SELECT SINGLE objct FROM tobj INTO lv_objct + WHERE objct = ms_item-obj_name. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + CALL FUNCTION 'SUSR_SHOW_OBJECT' + EXPORTING + object = mv_objectname. + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_tobj TYPE tobj, + ls_tobjt TYPE tobjt, + ls_tobjvorflg TYPE tobjvorflg, + lt_tactz TYPE TABLE OF tactz, + lt_tobjvordat TYPE TABLE OF tobjvordat, + lt_tobjvor TYPE TABLE OF tobjvor. + SELECT SINGLE * FROM tobj INTO ls_tobj + WHERE objct = ms_item-obj_name. + IF sy-subrc <> 0. + RETURN. + ENDIF. + CLEAR ls_tobj-bname. + + SELECT SINGLE * FROM tobjt INTO ls_tobjt + WHERE object = ms_item-obj_name + AND langu = mv_language. "#EC CI_GENBUFF + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'TOBJT no English description' + && ' for object (' && ms_item-obj_name && ')' ). + ENDIF. + + SELECT SINGLE * FROM tobjvorflg INTO ls_tobjvorflg + WHERE objct = ms_item-obj_name. "#EC CI_SUBRC + + SELECT * FROM tactz INTO TABLE lt_tactz + WHERE brobj = ms_item-obj_name + ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF + + SELECT * FROM tobjvordat INTO TABLE lt_tobjvordat + WHERE objct = ms_item-obj_name + ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF + + SELECT * FROM tobjvor INTO TABLE lt_tobjvor + WHERE objct = ms_item-obj_name + ORDER BY PRIMARY KEY. "#EC CI_SUBRC + + io_xml->add( iv_name = 'TOBJ' + ig_data = ls_tobj ). + io_xml->add( iv_name = 'TOBJT' + ig_data = ls_tobjt ). + io_xml->add( iv_name = 'TOBJVORFLG' + ig_data = ls_tobjvorflg ). + io_xml->add( ig_data = lt_tactz + iv_name = 'TACTZ' ). + io_xml->add( ig_data = lt_tobjvordat + iv_name = 'TOBJVORDAT' ). + io_xml->add( ig_data = lt_tobjvor + iv_name = 'TOBJVOR' ). + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_suso ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sush IMPLEMENTATION. + METHOD clear_metadata. + + DATA: + BEGIN OF ls_empty_metadata, + modifier TYPE c LENGTH 12, " usob_sm-modifier + moddate TYPE d, " usob_sm-moddate, + modtime TYPE t, " usob_sm-modtime, + srcsystem TYPE tadir-srcsystem, + author TYPE tadir-author, + devclass TYPE tadir-devclass, + END OF ls_empty_metadata. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE any, + TYPE any. + + MOVE-CORRESPONDING ls_empty_metadata TO cs_data_head. + + LOOP AT ct_usobx ASSIGNING . + MOVE-CORRESPONDING ls_empty_metadata TO . + ENDLOOP. + + LOOP AT ct_usobt ASSIGNING . + MOVE-CORRESPONDING ls_empty_metadata TO . + ENDLOOP. + + LOOP AT ct_usobt_ext ASSIGNING . + MOVE-CORRESPONDING ls_empty_metadata TO . + ENDLOOP. + + LOOP AT ct_usobx_ext ASSIGNING . + MOVE-CORRESPONDING ls_empty_metadata TO . + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + + DATA: lr_data_head TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE DATA lr_data_head TYPE ('IF_SU22_ADT_OBJECT=>TS_SU2X_HEAD'). + + CATCH cx_sy_create_data_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + DATA ls_key TYPE usobkey. + + ls_key = ms_item-obj_name. + + SELECT SINGLE modifier FROM usob_sm INTO rv_user + WHERE name = ls_key-name AND type = ls_key-type. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + DATA: + lo_su22 TYPE REF TO object, + ls_key TYPE usobkey, + lx_err TYPE REF TO cx_static_check. + + ASSERT NOT ms_item-obj_name IS INITIAL. + + ls_key = ms_item-obj_name. + + TRY. + CREATE OBJECT lo_su22 TYPE ('CL_SU22_ADT_OBJECT'). + + CALL METHOD lo_su22->('IF_SU22_ADT_OBJECT~DELETE') + EXPORTING + iv_key = ls_key + iv_cleanup = abap_true. + CATCH cx_static_check INTO lx_err. + zcx_abapgit_exception=>raise_with_text( lx_err ). + ENDTRY. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + ls_key TYPE usobkey, + lo_su22 TYPE REF TO object, + lo_appl TYPE REF TO object, + lt_usobx TYPE usobx_t, + lt_usobt TYPE usobt_t, + lr_appl_head TYPE REF TO data, + lr_data_head TYPE REF TO data, + lr_data_usobx_ext TYPE REF TO data, + lr_data_usobt_ext TYPE REF TO data, + lx_err TYPE REF TO cx_static_check, + lv_text TYPE string. + + FIELD-SYMBOLS: TYPE any, + TYPE any, + TYPE ANY TABLE, + TYPE ANY TABLE, + TYPE any. + + ASSERT NOT ms_item-obj_name IS INITIAL. + + TRY. + CREATE DATA lr_data_head TYPE ('IF_SU22_ADT_OBJECT=>TS_SU2X_HEAD'). + ASSIGN lr_data_head->* TO . + + CREATE DATA lr_data_usobx_ext TYPE ('IF_SU22_ADT_OBJECT=>TT_SU2X_X'). + ASSIGN lr_data_usobx_ext->* TO . + + CREATE DATA lr_data_usobt_ext TYPE ('IF_SU22_ADT_OBJECT=>TT_SU2X_T'). + ASSIGN lr_data_usobt_ext->* TO . + + "HEAD + io_xml->read( EXPORTING iv_name = 'HEAD' + CHANGING cg_data = ). + + "USOBX + io_xml->read( EXPORTING iv_name = 'USOBX' + CHANGING cg_data = lt_usobx ). + + "USOBT + io_xml->read( EXPORTING iv_name = 'USOBT' + CHANGING cg_data = lt_usobt ). + + "USOBX_EXT + io_xml->read( EXPORTING iv_name = 'USOBX_EXT' + CHANGING cg_data = ). + + "USOBT_EXT + io_xml->read( EXPORTING iv_name = 'USOBT_EXT' + CHANGING cg_data = ). + + CREATE OBJECT lo_su22 + TYPE ('CL_SU22_ADT_OBJECT'). + + " check if lead application exists + TRY. + CALL METHOD lo_su22->('IF_SU22_ADT_OBJECT~CHECK') + EXPORTING + id_mode = '02' + CHANGING + cs_head = . + CATCH cx_static_check INTO lx_err. + lv_text = |Lead application of object { ms_item-obj_name } does not exist|. + zcx_abapgit_exception=>raise( lv_text ). + ENDTRY. + + MOVE-CORRESPONDING TO ls_key. + CREATE DATA lr_appl_head TYPE ('CL_SU2X=>TS_HEAD'). + ASSIGN lr_appl_head->* TO . + + CREATE OBJECT lo_appl TYPE ('CL_SU22_APPL'). + + CALL METHOD lo_appl->('GET_DATA') + EXPORTING + is_key = ls_key + IMPORTING + es_head = . + + ASSIGN COMPONENT 'DEVCLASS' OF STRUCTURE TO . + IF <> iv_package. + lv_text = + |Lead application of object { ms_item-obj_name } does not exist in package { }|. + zcx_abapgit_exception=>raise( lv_text ). + ENDIF. + + TRY. + CALL METHOD lo_su22->('IF_SU22_ADT_OBJECT~UPDATE') + EXPORTING + is_head = + it_usobx = lt_usobx + it_usobt = lt_usobt. + CATCH cx_static_check INTO lx_err. + zcx_abapgit_exception=>raise_with_text( lx_err ). + ENDTRY. + + corr_insert( iv_package ). + + CATCH cx_static_check INTO lx_err. + zcx_abapgit_exception=>raise_with_text( lx_err ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + DATA: ls_usobhash TYPE usobhash. + + SELECT SINGLE * FROM usobhash INTO ls_usobhash "#EC CI_ALL_FIELDS_NEEDED + WHERE name = ms_item-obj_name. "#EC CI_SGLSELECT + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_USOBX' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + ls_key TYPE usobkey, + lo_su22 TYPE REF TO object, + lt_usobx TYPE usobx_t, + lt_usobt TYPE usobt_t, + lr_head TYPE REF TO data, + lr_usobx_ext TYPE REF TO data, + lr_usobt_ext TYPE REF TO data, + lx_err TYPE REF TO cx_static_check. + FIELD-SYMBOLS: TYPE any, + TYPE ANY TABLE, + TYPE ANY TABLE. + + ls_key = ms_item-obj_name. + + TRY. + CREATE DATA lr_head TYPE ('IF_SU22_ADT_OBJECT=>TS_SU2X_HEAD'). + ASSIGN lr_head->* TO . + + CREATE DATA lr_usobx_ext TYPE ('IF_SU22_ADT_OBJECT=>TT_SU2X_X'). + ASSIGN lr_usobx_ext->* TO . + + CREATE DATA lr_usobt_ext TYPE ('IF_SU22_ADT_OBJECT=>TT_SU2X_T'). + ASSIGN lr_usobt_ext->* TO . + + CREATE OBJECT lo_su22 + TYPE ('CL_SU22_ADT_OBJECT'). + + TRY. + CALL METHOD lo_su22->('IF_SU22_ADT_OBJECT~SELECT') + EXPORTING + iv_key = ls_key + IMPORTING + es_head = + et_usobx = lt_usobx + et_usobt = lt_usobt + et_usobx_ext = + et_usobt_ext = . + CATCH cx_static_check INTO lx_err. + zcx_abapgit_exception=>raise_with_text( lx_err ). + ENDTRY. + + clear_metadata( + CHANGING + cs_data_head = + ct_usobx = lt_usobx + ct_usobt = lt_usobt + ct_usobx_ext = + ct_usobt_ext = ). + + "HEAD + io_xml->add( iv_name = 'HEAD' + ig_data = ). + + "USOBX + io_xml->add( iv_name = 'USOBX' + ig_data = lt_usobx ). + + "USOBT + io_xml->add( iv_name = 'USOBT' + ig_data = lt_usobt ). + + "USOBX_EXT + io_xml->add( iv_name = 'USOBX_EXT' + ig_data = ). + + "USOBT_EXT + io_xml->add( iv_name = 'USOBT_EXT' + ig_data = ). + + CATCH cx_static_check INTO lx_err. + zcx_abapgit_exception=>raise_with_text( lx_err ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_susc IMPLEMENTATION. + METHOD delete_class. + + DELETE FROM tobc WHERE oclss = iv_auth_object_class. + DELETE FROM tobct WHERE oclss = iv_auth_object_class. + + ENDMETHOD. + METHOD has_authorization. + + AUTHORITY-CHECK OBJECT 'S_DEVELOP' + ID 'DEVCLASS' DUMMY + ID 'OBJTYPE' FIELD 'SUSC' + ID 'OBJNAME' FIELD iv_class + ID 'P_GROUP' DUMMY + ID 'ACTVT' FIELD iv_activity. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( iv_msgid = '01' + iv_msgno = '467' ). + ENDIF. + + ENDMETHOD. + METHOD is_used. + + DATA: lv_used_auth_object_class TYPE tobc-oclss. + + SELECT SINGLE oclss + FROM tobj + INTO lv_used_auth_object_class + WHERE oclss = iv_auth_object_class ##WARN_OK. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise_t100( iv_msgid = '01' + iv_msgno = '212' + iv_msgv1 = |{ iv_auth_object_class }| ). + ENDIF. + + ENDMETHOD. + METHOD put_delete_to_transport. + + DATA: lv_tr_object_name TYPE e071-obj_name, + lv_tr_return TYPE char1, + ls_package_info TYPE tdevc. + lv_tr_object_name = ms_item-obj_name. + + CALL FUNCTION 'SUSR_COMMEDITCHECK' + EXPORTING + objectname = lv_tr_object_name + transobjecttype = c_transobjecttype_class + IMPORTING + return_from_korr = lv_tr_return. + + IF lv_tr_return <> 'M'. + zcx_abapgit_exception=>raise( |error in SUSC delete at SUSR_COMMEDITCHECK| ). + ENDIF. + + CALL FUNCTION 'TR_DEVCLASS_GET' + EXPORTING + iv_devclass = ms_item-devclass + IMPORTING + es_tdevc = ls_package_info + EXCEPTIONS + OTHERS = 1. + IF sy-subrc = 0 AND ls_package_info-korrflag IS INITIAL. + tadir_delete( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " not stored by SAP + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + CONSTANTS lc_activity_delete_06 TYPE activ_auth VALUE '06'. + + DATA: lv_auth_object_class TYPE tobc-oclss. + lv_auth_object_class = ms_item-obj_name. + + TRY. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + CATCH zcx_abapgit_exception. + RETURN. + ENDTRY. + + has_authorization( iv_class = lv_auth_object_class + iv_activity = lc_activity_delete_06 ). + + is_used( lv_auth_object_class ). + + delete_class( lv_auth_object_class ). + + put_delete_to_transport( ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. +* see function group SUSA + + DATA: ls_tobc TYPE tobc, + lv_objectname TYPE e071-obj_name, + ls_tobct TYPE tobct. + io_xml->read( EXPORTING iv_name = 'TOBC' + CHANGING cg_data = ls_tobc ). + io_xml->read( EXPORTING iv_name = 'TOBCT' + CHANGING cg_data = ls_tobct ). + + tadir_insert( iv_package ). + + lv_objectname = ms_item-obj_name. + CALL FUNCTION 'SUSR_COMMEDITCHECK' + EXPORTING + objectname = lv_objectname + transobjecttype = c_transobjecttype_class. + + INSERT tobc FROM ls_tobc. "#EC CI_SUBRC +* ignore sy-subrc as all fields are key fields + + MODIFY tobct FROM ls_tobct. "#EC CI_SUBRC + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_oclss TYPE tobc-oclss. + SELECT SINGLE oclss FROM tobc INTO lv_oclss + WHERE oclss = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lv_objclass TYPE tobc-oclss. + + lv_objclass = ms_item-obj_name. + CALL FUNCTION 'SUSR_SHOW_OBJECT_CLASS' + EXPORTING + objclass = lv_objclass. + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_tobc TYPE tobc, + ls_tobct TYPE tobct. + SELECT SINGLE * FROM tobc INTO ls_tobc + WHERE oclss = ms_item-obj_name. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + SELECT SINGLE * FROM tobct INTO ls_tobct + WHERE oclss = ms_item-obj_name + AND langu = mv_language. + + io_xml->add( iv_name = 'TOBC' + ig_data = ls_tobc ). + io_xml->add( iv_name = 'TOBCT' + ig_data = ls_tobct ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sucu IMPLEMENTATION. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " not stored by SAP + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_styl IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_style TYPE ty_style, + lv_name TYPE itcda-tdstyle. + lv_name = ms_item-obj_name. + + CALL FUNCTION 'READ_STYLE' + EXPORTING + style = lv_name + IMPORTING + style_header = ls_style-header + TABLES + paragraphs = ls_style-paragraphs + strings = ls_style-strings + tabs = ls_style-tabs. + + rv_user = ls_style-header-tdluser. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_style TYPE itcda-tdstyle. + lv_style = ms_item-obj_name. + + CALL FUNCTION 'DELETE_STYLE' + EXPORTING + style = lv_style + language = '*'. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_style TYPE ty_style. + io_xml->read( EXPORTING iv_name = 'STYLE' + CHANGING cg_data = ls_style ). + + CALL FUNCTION 'SAVE_STYLE' + EXPORTING + style_header = ls_style-header + TABLES + paragraphs = ls_style-paragraphs + strings = ls_style-strings + tabs = ls_style-tabs. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_style TYPE ty_style, + lv_name TYPE itcda-tdstyle, + lv_found TYPE abap_bool. + lv_name = ms_item-obj_name. + + CALL FUNCTION 'READ_STYLE' + EXPORTING + style = lv_name + IMPORTING + found = lv_found + TABLES + paragraphs = ls_style-paragraphs + strings = ls_style-strings + tabs = ls_style-tabs. + + rv_bool = boolc( lv_found = abap_true ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_bcdata TYPE bdcdata, + lt_bcdata TYPE STANDARD TABLE OF bdcdata. + + ls_bcdata-program = 'SAPMSSCS'. + ls_bcdata-dynpro = '1100'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'RSSCS-TDSTYLE'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'RSSCS-TDSPRAS'. + ls_bcdata-fval = mv_language. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'RSSCS-TDHEADEROB'. + ls_bcdata-fval = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=SHOW'. + APPEND ls_bcdata TO lt_bcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SE72' + it_bdcdata = lt_bcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_style TYPE ty_style, + lv_name TYPE itcda-tdstyle. + lv_name = ms_item-obj_name. + + CALL FUNCTION 'READ_STYLE' + EXPORTING + style = lv_name + IMPORTING + style_header = ls_style-header + TABLES + paragraphs = ls_style-paragraphs + strings = ls_style-strings + tabs = ls_style-tabs. + + CLEAR: ls_style-header-tdfuser, + ls_style-header-tdfdate, + ls_style-header-tdftime, + ls_style-header-tdfreles, + ls_style-header-tdluser, + ls_style-header-tdldate, + ls_style-header-tdltime, + ls_style-header-tdlreles. + + io_xml->add( iv_name = 'STYLE' + ig_data = ls_style ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_stvi IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_transaction_variant TYPE utcvariant. + + lv_transaction_variant = ms_item-obj_name. + + SELECT SINGLE chuser + FROM shdtvciu + INTO rv_user + WHERE tcvariant = lv_transaction_variant. + IF sy-subrc <> 0 + OR rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_transaction_variant TYPE tcvariant. + + lv_transaction_variant = ms_item-obj_name. + + CALL FUNCTION 'RS_HDSYS_DELETE_VARIANT' + EXPORTING + tcvariant = lv_transaction_variant + i_flag_client_independent = abap_true + EXCEPTIONS + variant_enqueued = 1 + no_correction = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_transaction_variant TYPE ty_transaction_variant. + + io_xml->read( + EXPORTING + iv_name = 'STVI' + CHANGING + cg_data = ls_transaction_variant ). + + CALL FUNCTION 'ENQUEUE_ESTCVARCIU' + EXPORTING + tcvariant = ls_transaction_variant-shdtvciu-tcvariant + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. + MESSAGE e413(ms) WITH ls_transaction_variant-shdtvciu-tcvariant INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + corr_insert( iv_package ). + +* Populate user details + ls_transaction_variant-shdtvciu-crdate = sy-datum. + ls_transaction_variant-shdtvciu-cruser = sy-uname. + ls_transaction_variant-shdtvciu-chdate = sy-datum. + ls_transaction_variant-shdtvciu-chuser = sy-uname. + + MODIFY shdtvciu FROM ls_transaction_variant-shdtvciu. + MODIFY shdttciu FROM TABLE ls_transaction_variant-shdttciu[]. + INSERT shdfvguicu FROM TABLE ls_transaction_variant-shdfvguicu[] ACCEPTING DUPLICATE KEYS. + INSERT shdtvsvciu FROM TABLE ls_transaction_variant-shdtvsvciu[] ACCEPTING DUPLICATE KEYS. + + CALL FUNCTION 'DEQUEUE_ESTCVARCIU' + EXPORTING + tcvariant = ls_transaction_variant-shdtvciu-tcvariant. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_transaction_variant TYPE tcvariant. + + lv_transaction_variant = ms_item-obj_name. + + CALL FUNCTION 'RS_HDSYS_EXIST_CHECK_VARIANT' + EXPORTING + tcvariant = lv_transaction_variant + i_flag_client_independent = abap_true + EXCEPTIONS + no_variant = 1 + OTHERS = 2. + IF sy-subrc = 0. + rv_bool = abap_true. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + + rs_metadata = get_metadata( ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + + rv_active = is_active( ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_transaction_variant TYPE ty_transaction_variant. + + ls_transaction_variant-shdtvciu-tcvariant = ms_item-obj_name. + + CALL FUNCTION 'RS_HDSYS_READ_TC_VARIANT_DB' + EXPORTING + tcvariant = ls_transaction_variant-shdtvciu-tcvariant + flag_client_independent = abap_true + IMPORTING + header_tcvariant = ls_transaction_variant-shdtvciu + TABLES + screen_variants = ls_transaction_variant-shdtvsvciu[] + inactive_functions = ls_transaction_variant-shdfvguicu[] + EXCEPTIONS + no_variant = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + SORT ls_transaction_variant-shdtvsvciu ASCENDING. + SORT ls_transaction_variant-shdfvguicu ASCENDING. + +* Clear all user details + CLEAR: ls_transaction_variant-shdtvciu-crdate, + ls_transaction_variant-shdtvciu-cruser, + ls_transaction_variant-shdtvciu-chdate, + ls_transaction_variant-shdtvciu-chuser. + + SELECT * + FROM shdttciu + INTO TABLE ls_transaction_variant-shdttciu[] + WHERE tcvariant = ls_transaction_variant-shdtvciu-tcvariant + ORDER BY PRIMARY KEY. + + io_xml->add( iv_name = 'STVI' + ig_data = ls_transaction_variant ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ssst IMPLEMENTATION. + METHOD validate_font. + + DATA: lv_tdfamily TYPE tfo01-tdfamily. + SELECT SINGLE tdfamily FROM tfo01 INTO lv_tdfamily + WHERE tdfamily = iv_tdfamily. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Font family not found' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE lastuser FROM stxsadm INTO rv_user + WHERE stylename = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_stylename TYPE tdssname. + lv_stylename = ms_item-obj_name. + + CALL FUNCTION 'SSF_DELETE_STYLE' + EXPORTING + i_stylename = lv_stylename + i_with_dialog = abap_false + i_with_confirm_dialog = abap_false + EXCEPTIONS + no_name = 1 + no_style = 2 + style_locked = 3 + cancelled = 4 + no_access_permission = 5 + illegal_language = 6 + OTHERS = 7. + IF sy-subrc <> 0 AND sy-subrc <> 2. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. +* see fm SSF_UPLOAD_STYLE + + DATA: ls_header TYPE ssfcats, + ls_new_header TYPE ssfcats, + lt_paragraphs TYPE TABLE OF ssfparas, + lt_strings TYPE TABLE OF ssfstrings, + lt_tabstops TYPE TABLE OF stxstab. + + FIELD-SYMBOLS: TYPE spras. + io_xml->read( EXPORTING iv_name = 'HEADER' + CHANGING cg_data = ls_header ). + io_xml->read( EXPORTING iv_name = 'SSFPARAS' + CHANGING cg_data = lt_paragraphs ). + io_xml->read( EXPORTING iv_name = 'SSFSTRINGS' + CHANGING cg_data = lt_strings ). + io_xml->read( EXPORTING iv_name = 'STXSTAB' + CHANGING cg_data = lt_tabstops ). + + validate_font( ls_header-tdfamily ). + + CALL FUNCTION 'SSF_READ_STYLE' "Just load FG + EXPORTING + i_style_name = ls_header-stylename + i_style_active_flag = 'A' + EXCEPTIONS + OTHERS = 0. + + set_default_package( iv_package ). + ASSIGN ('(SAPLSTXBS)MASTER_LANGUAGE') TO . + IF sy-subrc = 0. + = ls_header-masterlang. + ENDIF. + + tadir_insert( iv_package ). + + CALL FUNCTION 'SSF_SAVE_STYLE' + EXPORTING + i_header = ls_header + IMPORTING + e_header = ls_new_header + TABLES + i_paragraphs = lt_paragraphs + i_strings = lt_strings + i_tabstops = lt_tabstops. + + IF ls_new_header IS NOT INITIAL. + + CALL FUNCTION 'SSF_ACTIVATE_STYLE' + EXPORTING + i_stylename = ls_header-stylename + redirect_error_msg = abap_true " otherwise warnings write list output + EXCEPTIONS + no_name = 1 + no_style = 2 + cancelled = 3 + no_access_permission = 4 + illegal_language = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_stylename TYPE stxsadm-stylename. + + SELECT SINGLE stylename + FROM stxshead INTO lv_stylename + WHERE active = c_style_active + AND stylename = ms_item-obj_name + AND vari = ''. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_SMSTYLE' + iv_argument = |{ ms_item-obj_name }| ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_bcdata TYPE bdcdata, + lt_bcdata TYPE STANDARD TABLE OF bdcdata. + + ls_bcdata-program = 'SAPMSSFS'. + ls_bcdata-dynpro = '0100'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'SSFSCREENS-SNAME'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=DISPLAY'. + APPEND ls_bcdata TO lt_bcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SMARTSTYLES' + it_bdcdata = lt_bcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. +* see fm SSF_DOWNLOAD_STYLE + + DATA: lv_style_name TYPE tdssname, + ls_header TYPE ssfcats, + lt_paragraphs TYPE TABLE OF ssfparas, + lt_strings TYPE TABLE OF ssfstrings, + lt_tabstops TYPE TABLE OF stxstab. + lv_style_name = ms_item-obj_name. + + CALL FUNCTION 'SSF_READ_STYLE' + EXPORTING + i_style_name = lv_style_name + i_style_active_flag = c_style_active + i_style_variant = '%MAIN' + i_style_language = mv_language + IMPORTING + e_header = ls_header + TABLES + e_paragraphs = lt_paragraphs + e_strings = lt_strings + e_tabstops = lt_tabstops + EXCEPTIONS + no_name = 1 + no_style = 2 + active_style_not_found = 3 + inactive_style_not_found = 4 + no_variant = 5 + no_main_variant = 6 + cancelled = 7 + no_access_permission = 8 + OTHERS = 9. + IF sy-subrc = 2. + RETURN. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CLEAR ls_header-version. + CLEAR ls_header-firstuser. + CLEAR ls_header-firstdate. + CLEAR ls_header-firsttime. + CLEAR ls_header-lastuser. + CLEAR ls_header-lastdate. + CLEAR ls_header-lasttime. + + io_xml->add( iv_name = 'HEADER' + ig_data = ls_header ). + io_xml->add( ig_data = lt_paragraphs + iv_name = 'SSFPARAS' ). + io_xml->add( ig_data = lt_strings + iv_name = 'SSFSTRINGS' ). + io_xml->add( ig_data = lt_tabstops + iv_name = 'STXSTAB' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ssfo IMPLEMENTATION. + METHOD deserialize_sources. + + DATA: + lv_extra TYPE string, + ls_abap TYPE abaptxt255, + lt_abap TYPE abaptxt255_tab, + li_node TYPE REF TO if_ixml_node, + li_ixml TYPE REF TO if_ixml, + li_xml_doc TYPE REF TO if_ixml_document. + + li_ixml = cl_ixml=>create( ). + li_xml_doc = li_ixml->create_document( ). + + " Old format + lv_extra = ii_node->get_value( ). + IF lv_extra NS c_prefix. + RETURN. + ENDIF. + + " New format + lv_extra = lv_extra+5(*). + + lt_abap = mo_files->read_abap( iv_extra = lv_extra ). + + ii_node->set_value( '' ). + LOOP AT lt_abap INTO ls_abap. + li_node = li_xml_doc->create_element( 'item' ). + li_node->set_value( |{ ls_abap-line }| ). + ii_node->append_child( li_node ). + ENDLOOP. + + ENDMETHOD. + METHOD fix_ids. + + " makes sure ID and IDREF values are the same values for each serialization run + " the standard code has a counter that keeps increasing values. + " + " It is important that IDs and IDREFs which are the same before the fix + " are also the same after the fix. + + TYPES: + BEGIN OF ty_id_mapping, + old TYPE string, + new TYPE string, + END OF ty_id_mapping, + ty_id_mappings TYPE HASHED TABLE OF ty_id_mapping + WITH UNIQUE KEY old. + + DATA: lv_name TYPE string, + li_idref TYPE REF TO if_ixml_node, + li_node TYPE REF TO if_ixml_node, + li_attr TYPE REF TO if_ixml_named_node_map, + li_iterator TYPE REF TO if_ixml_node_iterator, + lt_id_mapping TYPE ty_id_mappings, + ls_id_mapping LIKE LINE OF lt_id_mapping. + + li_iterator = ii_xml_doc->create_iterator( ). + li_node = li_iterator->get_next( ). + WHILE NOT li_node IS INITIAL. + lv_name = li_node->get_name( ). + IF lv_name = 'NODE' OR lv_name = 'WINDOW'. + li_idref = li_node->get_attributes( )->get_named_item( 'IDREF' ). + IF li_idref IS BOUND. + + ls_id_mapping-old = li_idref->get_value( ). + READ TABLE lt_id_mapping WITH KEY old = ls_id_mapping-old + INTO ls_id_mapping. + IF sy-subrc <> 0. + lv_name = lines( lt_id_mapping ) + 1. + ls_id_mapping-new = condense( lv_name ). + INSERT ls_id_mapping INTO TABLE lt_id_mapping. + ENDIF. + + li_idref->set_value( |{ ls_id_mapping-new }| ). + ENDIF. + ENDIF. + li_node = li_iterator->get_next( ). + ENDWHILE. + + li_iterator = ii_xml_doc->create_iterator( ). + li_node = li_iterator->get_next( ). + WHILE NOT li_node IS INITIAL. + lv_name = li_node->get_name( ). + IF lv_name = 'NODE' OR lv_name = 'WINDOW'. + li_idref = li_node->get_attributes( )->get_named_item( 'ID' ). + IF li_idref IS BOUND. + + ls_id_mapping-old = li_idref->get_value( ). + READ TABLE lt_id_mapping WITH KEY old = ls_id_mapping-old + INTO ls_id_mapping. + IF sy-subrc = 0. + li_idref->set_value( |{ ls_id_mapping-new }| ). + ELSE. + li_attr = li_node->get_attributes( ). + li_attr->remove_named_item( 'ID' ). + ENDIF. + + ENDIF. + ENDIF. + li_node = li_iterator->get_next( ). + ENDWHILE. + + ENDMETHOD. + METHOD get_hash_for_path. + + DATA: + lv_name TYPE string, + lv_path TYPE string, + li_node TYPE REF TO if_ixml_node, + li_name TYPE REF TO if_ixml_node, + li_iname TYPE REF TO if_ixml_node. + + li_node = ii_node->get_parent( ). + WHILE NOT li_node IS INITIAL. + lv_name = li_node->get_name( ). + IF ( lv_name = 'CODE' OR lv_name = 'WINDOW' OR lv_name = 'PAGE' ) + AND li_node->get_namespace_prefix( ) IS NOT INITIAL. + li_name = li_node->get_first_child( ). + li_iname = li_node->get_first_child( ). + lv_name = lv_name && ':' && li_iname->get_value( ). + ENDIF. + lv_path = lv_name && '/' && lv_path. + li_node = li_node->get_parent( ). + ENDWHILE. + + rv_hash = substring( + val = zcl_abapgit_hash=>sha1_string( lv_path ) + len = 8 ). + + ENDMETHOD. + METHOD get_range_node_codes. + + DATA: ls_range_node_code TYPE LINE OF ty_string_range. + + IF gt_range_node_codes IS INITIAL. + ls_range_node_code-sign = 'I'. + ls_range_node_code-option = 'EQ'. + ls_range_node_code-low = 'CODE'. + INSERT ls_range_node_code INTO TABLE gt_range_node_codes. + ls_range_node_code-low = 'GTYPES'. + INSERT ls_range_node_code INTO TABLE gt_range_node_codes. + ls_range_node_code-low = 'GCODING'. + INSERT ls_range_node_code INTO TABLE gt_range_node_codes. + ls_range_node_code-low = 'FCODING'. + INSERT ls_range_node_code INTO TABLE gt_range_node_codes. + ENDIF. + + rt_range_node_codes = gt_range_node_codes. + + ENDMETHOD. + METHOD serialize_sources. + + DATA: + lv_extra TYPE string, + ls_abap TYPE abaptxt255, + lt_abap TYPE abaptxt255_tab, + li_node TYPE REF TO if_ixml_node, + li_iterator TYPE REF TO if_ixml_node_iterator. + + " Store code as separate ABAP files instead of XML + lv_extra = to_lower( ii_node->get_name( ) ). + li_iterator = ii_node->get_children( )->create_iterator( ). + li_node = li_iterator->get_next( ). + WHILE NOT li_node IS INITIAL. + ls_abap-line = li_node->get_value( ). + INSERT ls_abap INTO TABLE lt_abap. + + li_node = li_iterator->get_next( ). + ENDWHILE. + + " For CODE sections, get full path and hash it + IF lv_extra = 'code'. + lv_extra = get_hash_for_path( ii_node ). + ENDIF. + + mo_files->add_abap( + iv_extra = lv_extra + it_abap = lt_abap ). + + ii_node->set_value( c_prefix && lv_extra ). + + ENDMETHOD. + METHOD sort_texts. + + DATA: li_node TYPE REF TO if_ixml_node, + li_item TYPE REF TO if_ixml_node, + li_field TYPE REF TO if_ixml_node, + li_item_list TYPE REF TO if_ixml_node_list, + li_iterator TYPE REF TO if_ixml_node_iterator, + li_items TYPE REF TO if_ixml_node_iterator, + lv_index TYPE i, + lv_field TYPE fieldname, + ls_item TYPE stxfobjt, + lt_items TYPE STANDARD TABLE OF stxfobjt. + + FIELD-SYMBOLS TYPE any. + + li_iterator = ii_xml_doc->create_iterator( ). + li_node = li_iterator->get_next( ). + WHILE NOT li_node IS INITIAL. + IF li_node->get_name( ) = 'T_CAPTION'. + + " Read all records for T_CAPTION + CLEAR lt_items. + li_item_list = li_node->get_children( ). + li_items = li_item_list->create_iterator( ). + DO. + li_item = li_items->get_next( ). + IF li_item IS INITIAL. + EXIT. + ENDIF. + CLEAR ls_item. + li_field = li_item->get_first_child( ). + WHILE NOT li_field IS INITIAL. + lv_field = li_field->get_name( ). + ASSIGN COMPONENT lv_field OF STRUCTURE ls_item TO . + ASSERT sy-subrc = 0. + = li_field->get_value( ). + li_field = li_field->get_next( ). + ENDWHILE. + INSERT ls_item INTO TABLE lt_items. + ENDDO. + + SORT lt_items. + + " Write all records back after sorting + lv_index = 1. + li_items = li_item_list->create_iterator( ). + DO. + li_item = li_items->get_next( ). + IF li_item IS INITIAL. + EXIT. + ENDIF. + READ TABLE lt_items INTO ls_item INDEX lv_index. + li_field = li_item->get_first_child( ). + WHILE NOT li_field IS INITIAL. + lv_field = li_field->get_name( ). + ASSIGN COMPONENT lv_field OF STRUCTURE ls_item TO . + ASSERT sy-subrc = 0. + li_field->set_value( |{ }| ). + li_field = li_field->get_next( ). + ENDWHILE. + +* guess this can only happen for CAPTION field, as other are key fields +* always add the empty values or they will cause diffs + IF lv_field <> 'CAPTION'. + ii_xml_doc->create_simple_element( + name = 'CAPTION' + value = |{ ls_item-caption }| + parent = li_item ). + ENDIF. + + lv_index = lv_index + 1. + ENDDO. + + ENDIF. + li_node = li_iterator->get_next( ). + ENDWHILE. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE lastuser FROM stxfadm INTO rv_user + WHERE formname = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_formname TYPE tdsfname. + + lv_formname = ms_item-obj_name. + + CALL FUNCTION 'FB_DELETE_FORM' + EXPORTING + i_formname = lv_formname + i_with_dialog = abap_false + i_with_confirm_dialog = abap_false + EXCEPTIONS + no_form = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. +* see function module FB_UPLOAD_FORM + + DATA: + li_node TYPE REF TO if_ixml_node, + lv_formname TYPE tdsfname, + lv_name TYPE string, + li_iterator TYPE REF TO if_ixml_node_iterator, + lo_sf TYPE REF TO cl_ssf_fb_smart_form, + lo_res TYPE REF TO cl_ssf_fb_smart_form, + lx_error TYPE REF TO cx_ssf_fb, + lv_text TYPE string. + + CREATE OBJECT lo_sf. + +* set "created by" and "changed by" to current user + li_iterator = io_xml->get_raw( )->get_root_element( )->create_iterator( ). + li_node = li_iterator->get_next( ). + WHILE NOT li_node IS INITIAL. + lv_name = li_node->get_name( ). + CASE lv_name. + WHEN 'LASTDATE'. + li_node->set_value( sy-datum(4) && '-' && sy-datum+4(2) && '-' && sy-datum+6(2) ). + WHEN 'LASTTIME'. + li_node->set_value( sy-uzeit(2) && ':' && sy-uzeit+2(2) && ':' && sy-uzeit+4(2) ). + WHEN 'FIRSTUSER' OR 'LASTUSER'. + li_node->set_value( sy-uname && '' ). + + ENDCASE. + + IF lv_name IN get_range_node_codes( ) AND li_node->get_namespace_prefix( ) IS INITIAL. + deserialize_sources( li_node ). + ENDIF. + + li_node = li_iterator->get_next( ). + ENDWHILE. + + tadir_insert( iv_package ). + + lv_formname = ms_item-obj_name. + + TRY. + lo_sf->enqueue( suppress_corr_check = space + master_language = mv_language + mode = 'INSERT' + formname = lv_formname ). + + lo_sf->xml_upload( EXPORTING dom = io_xml->get_raw( )->get_root_element( ) + formname = lv_formname + language = mv_language + CHANGING sform = lo_res ). + + lo_res->store( im_formname = lo_res->header-formname + im_language = mv_language + im_active = abap_true ). + + lo_sf->dequeue( lv_formname ). + + CATCH cx_ssf_fb INTO lx_error. + lv_text = lx_error->get_text( ). + zcx_abapgit_exception=>raise( |{ ms_item-obj_type } { ms_item-obj_name }: { lv_text } | ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_formname TYPE stxfadm-formname. + + SELECT SINGLE formname FROM stxfadm INTO lv_formname + WHERE formname = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + + DATA: lv_ssfo_formname TYPE tdsfname. + DATA lv_inactive TYPE abap_bool. + + lv_ssfo_formname = ms_item-obj_name. + + CALL FUNCTION 'SSF_STATUS_INFO' + EXPORTING + i_formname = lv_ssfo_formname + IMPORTING + o_inactive = lv_inactive. + + rv_active = boolc( lv_inactive = abap_false ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_SMFORM' + iv_argument = |{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lt_bdcdata TYPE TABLE OF bdcdata, + lv_formtype TYPE stxfadm-formtype. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMSSFO'. + -dynpro = '0100'. + -dynbegin = abap_true. + + SELECT SINGLE formtype FROM stxfadm INTO lv_formtype + WHERE formname = ms_item-obj_name. + + IF lv_formtype = cssf_formtype_text. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'RB_TX'. + -fval = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=RB'. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMSSFO'. + -dynpro = '0100'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'SSFSCREEN-TNAME'. + -fval = ms_item-obj_name. + + ELSE. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'SSFSCREEN-FNAME'. + -fval = ms_item-obj_name. + + ENDIF. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=DISPLAY'. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SMARTFORMS' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. +* see function module FB_DOWNLOAD_FORM + + DATA: lo_sf TYPE REF TO cl_ssf_fb_smart_form, + lv_name TYPE string, + li_node TYPE REF TO if_ixml_node, + li_element TYPE REF TO if_ixml_element, + li_iterator TYPE REF TO if_ixml_node_iterator, + lv_formname TYPE tdsfname, + li_ixml TYPE REF TO if_ixml, + li_xml_doc TYPE REF TO if_ixml_document. + + li_ixml = cl_ixml=>create( ). + li_xml_doc = li_ixml->create_document( ). + + CREATE OBJECT lo_sf. + lv_formname = ms_item-obj_name. " convert type + TRY. + lo_sf->load( im_formname = lv_formname + im_language = '' ). + CATCH cx_ssf_fb. +* the smartform is not present in system, or other error occurred + RETURN. + ENDTRY. + + lo_sf->xml_download( EXPORTING parent = li_xml_doc + CHANGING document = li_xml_doc ). + + li_iterator = li_xml_doc->create_iterator( ). + li_node = li_iterator->get_next( ). + WHILE NOT li_node IS INITIAL. + + lv_name = li_node->get_name( ). + IF lv_name = 'DEVCLASS' + OR lv_name = 'LASTDATE' + OR lv_name = 'LASTTIME'. + li_node->set_value( '' ). + ENDIF. + IF lv_name = 'FIRSTUSER' + OR lv_name = 'LASTUSER'. + li_node->set_value( 'DUMMY' ). + ENDIF. + + IF lv_name IN get_range_node_codes( ) AND li_node->get_namespace_prefix( ) IS INITIAL. + serialize_sources( li_node ). + ENDIF. + + li_node = li_iterator->get_next( ). + ENDWHILE. + + fix_ids( li_xml_doc ). + + sort_texts( li_xml_doc ). + + li_element = li_xml_doc->get_root_element( ). + li_element->set_attribute( + name = 'sf' + namespace = 'xmlns' + value = 'urn:sap-com:SmartForms:2000:internal-structure' ). + li_element->set_attribute( + name = 'xmlns' + value = 'urn:sap-com:sdixml-ifr:2000' ). + + io_xml->set_raw( li_xml_doc->get_root_element( ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_srvd IMPLEMENTATION. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_metadata TO . + IF sy-subrc = 0. + CLEAR: . + ENDIF. + + ENDMETHOD. + METHOD clear_fields. + + clear_field( + EXPORTING + iv_fieldname = 'VERSION' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'CREATED_AT' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'CREATED_BY' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGED_AT' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGED_BY' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'RESPONSIBLE' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'PACKAGE_REF' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MASTER_SYSTEM' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'DT_UUID' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'ABAP_LANGUAGE_VERSION' + CHANGING + cs_metadata = cs_metadata ). + clear_field( + EXPORTING + iv_fieldname = 'ABAP_LANGU_VERSION' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'LINKS' + CHANGING + cs_metadata = cs_metadata ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_service_definition_key = ms_item-obj_name. + + TRY. + CREATE DATA mr_service_definition TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_SRVD_OBJECT_DATA'). + + CATCH cx_sy_create_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD get_object_data. + + DATA: + lr_metadata TYPE REF TO data, + lr_data TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE any, + TYPE any. + + CREATE DATA lr_data TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_SRVD_OBJECT_DATA'). + ASSIGN lr_data->* TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + CREATE DATA lr_metadata TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_METADATA_EXTENDED'). + ASSIGN lr_metadata->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = c_xml_parent_name + CHANGING + cg_data = ). + + = . + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + = mo_files->read_string( c_source_file ). + IF IS INITIAL. + = mo_files->read_string( 'assrvd' ). + ENDIF. + + CREATE OBJECT ro_object_data TYPE ('CL_SRVD_WB_OBJECT_DATA'). + ro_object_data->set_data( p_data = ). + + ENDMETHOD. + METHOD get_wb_object_operator. + + DATA: + ls_object_type TYPE wbobjtype, + lx_error TYPE REF TO cx_root. + + IF mo_object_operator IS BOUND. + ro_object_operator = mo_object_operator. + ENDIF. + + ls_object_type-objtype_tr = 'SRVD'. + ls_object_type-subtype_wb = 'SRV'. + + TRY. + CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') + EXPORTING + object_type = ls_object_type + object_key = mv_service_definition_key + RECEIVING + result = mo_object_operator. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ro_object_operator = mo_object_operator. + + ENDMETHOD. + METHOD merge_object_data. + + DATA: + lo_object_data TYPE REF TO object, + lo_object_data_old TYPE REF TO if_wb_object_data_model, + lr_new TYPE REF TO data, + lr_old TYPE REF TO data, + lo_wb_object_operator TYPE REF TO object. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE any, + TYPE any. + + CREATE OBJECT lo_object_data TYPE ('CL_SRVD_WB_OBJECT_DATA'). + lo_object_data = io_object_data. + + CREATE DATA lr_new TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_SRVD_OBJECT_DATA'). + ASSIGN lr_new->* TO . + ASSERT sy-subrc = 0. + + CREATE DATA lr_old TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_SRVD_OBJECT_DATA'). + ASSIGN lr_old->* TO . + ASSERT sy-subrc = 0. + + CALL METHOD lo_object_data->('IF_WB_OBJECT_DATA_MODEL~GET_DATA') + EXPORTING + p_metadata_only = abap_false + p_data_selection = 'AL' + IMPORTING + p_data = . + + lo_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + IMPORTING + eo_object_data = lo_object_data_old. + + CALL METHOD lo_object_data_old->('GET_DATA') + EXPORTING + p_metadata_only = abap_false + p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + IMPORTING + p_data = . + + ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . + ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . + = . + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + = . + + CREATE OBJECT ro_object_data_merged TYPE ('CL_SRVD_WB_OBJECT_DATA'). + + CALL METHOD ro_object_data_merged->('SET_DATA') + EXPORTING + p_data = . + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + li_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = li_object_data_model. + + rv_user = li_object_data_model->get_changed_by( ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + DATA: + lx_error TYPE REF TO cx_root, + li_wb_object_operator TYPE REF TO object. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') + EXPORTING + transport_request = iv_transport. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + lo_object_data TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root, + lo_wb_object_operator TYPE REF TO object, + lo_merged_data_all TYPE REF TO if_wb_object_data_model, + lo_merged_data_prop TYPE REF TO if_wb_object_data_model, + lo_merged_data_cont TYPE REF TO if_wb_object_data_model, + lr_wbobjtype TYPE REF TO data, + lr_category TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE any. + + TRY. + lo_object_data = get_object_data( io_xml ). + lo_wb_object_operator = get_wb_object_operator( ). + + CREATE DATA lr_wbobjtype TYPE ('WBOBJTYPE'). + ASSIGN lr_wbobjtype->* TO . + ASSIGN COMPONENT 'OBJTYPE_TR' OF STRUCTURE TO . + = 'SRVD'. + ASSIGN COMPONENT 'SUBTYPE_WB' OF STRUCTURE TO . + = 'SRV'. + + CREATE DATA lr_category TYPE ('WBADT_RESOURCE_CATEGORY'). + ASSIGN lr_category->* TO . + + CALL METHOD ('CL_BLUE_WB_UTILITY')=>('GET_RESOURCE_CATEGORY') + EXPORTING + is_object_type = + RECEIVING + result = . + + lo_wb_object_operator = get_wb_object_operator( ). + + tadir_insert( iv_package ). + + IF zif_abapgit_object~exists( ) = abap_false. + CASE . + WHEN '1'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = lo_object_data + data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data + version = 'I' "swbm_version_inactive + package = iv_package + transport_request = iv_transport. + WHEN '2'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_compound_s. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = lo_object_data + data_selection = 'P' "if_wb_object_data_selection_co=>c_properties + version = 'I' "swbm_version_inactive + package = iv_package + transport_request = iv_transport. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_object_data + data_selection = 'D' "if_wb_object_data_selection_co=>c_data_content + version = 'I' "swbm_version_inactive + transport_request = iv_transport. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Category '{ }' not supported| ). + ENDCASE. + ELSE. + CASE . + WHEN '1'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. + lo_merged_data_all = merge_object_data( lo_object_data ). + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_merged_data_all + data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data + version = 'I' "swbm_version_inactive + transport_request = iv_transport. + WHEN '2'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_compound_s. + lo_merged_data_prop = merge_object_data( lo_object_data ). + lo_merged_data_cont = merge_object_data( lo_object_data ). + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_merged_data_prop + data_selection = 'P' "if_wb_object_data_selection_co=>c_properties + version = 'I' "swbm_version_inactive + transport_request = iv_transport. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_merged_data_cont + data_selection = 'D' "if_wb_object_data_selection_co=>c_data_content + version = 'I' "swbm_version_inactive + transport_request = iv_transport. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Category '{ }' not supported| ). + ENDCASE. + ENDIF. + + corr_insert( iv_package ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA lo_object_data TYPE REF TO if_wb_object_data_model. + DATA lo_wb_object_operator TYPE REF TO object. + + TRY. + lo_wb_object_operator = get_wb_object_operator( ). + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + data_selection = 'P' + IMPORTING + eo_object_data = lo_object_data. + rv_bool = boolc( lo_object_data IS NOT INITIAL AND lo_object_data->get_object_key( ) IS NOT INITIAL ). + CATCH cx_root. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + li_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root, + lv_source TYPE string. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE string. + + ASSIGN mr_service_definition->* TO . + ASSERT sy-subrc = 0. + + TRY. + li_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + version = 'A' + data_selection = 'AL' + IMPORTING + "data = + eo_object_data = li_object_data_model. + + CALL METHOD li_object_data_model->('GET_DATA') + IMPORTING + p_data = . + + ASSIGN COMPONENT 'METADATA' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + clear_fields( CHANGING cs_metadata = ). + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + lv_source = . + + io_xml->add( + iv_name = c_xml_parent_name + ig_data = ). + + mo_files->add_string( + iv_ext = c_source_file + iv_string = lv_source ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_srvb IMPLEMENTATION. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_service_binding + TO . + ASSERT sy-subrc = 0. + + CLEAR: . + + ENDMETHOD. + METHOD clear_fields. + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-VERSION' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_AT' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_BY' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_AT' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_BY' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-LANGUAGE' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-PACKAGE_REF' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-MASTER_SYSTEM' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-LINKS' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-RESPONSIBLE' + CHANGING + cs_service_binding = cs_service_binding ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-MASTER_LANGUAGE' + CHANGING + cs_service_binding = cs_service_binding ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_service_binding_key = ms_item-obj_name. + + TRY. + CREATE DATA mr_service_binding TYPE ('CL_SRVB_OBJECT_DATA=>TY_OBJECT_DATA'). + CREATE OBJECT mi_persistence TYPE ('CL_SRVB_OBJECT_PERSIST'). + + CATCH cx_sy_create_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + mv_is_inactive_supported = is_ai_supported( ). + + ENDMETHOD. + METHOD get_object_data. + + FIELD-SYMBOLS: + TYPE any, + TYPE data. + + ASSIGN mr_service_binding->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'SRVB' + CHANGING + cg_data = ). + " We have to set the language explicitly, + " because otherwise the description isn't stored + ASSIGN COMPONENT 'METADATA-LANGUAGE' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + = mv_language. + + CREATE OBJECT ro_object_data TYPE ('CL_SRVB_OBJECT_DATA'). + ro_object_data->set_data( p_data = ). + + ENDMETHOD. + METHOD get_wb_object_operator. + + DATA: + ls_object_type TYPE wbobjtype, + lx_error TYPE REF TO cx_root. + + IF mo_object_operator IS BOUND. + ro_object_operator = mo_object_operator. + ENDIF. + + ls_object_type-objtype_tr = 'SRVB'. + ls_object_type-subtype_wb = 'SVB'. + + TRY. + CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') + EXPORTING + object_type = ls_object_type + object_key = mv_service_binding_key + RECEIVING + result = mo_object_operator. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ro_object_operator = mo_object_operator. + + ENDMETHOD. + METHOD is_ai_supported. + TRY. + CREATE OBJECT mr_srvb_svrs_config TYPE ('CL_SRVB_SVRS_CONFIG') + EXPORTING iv_objtype = 'SRVB'. + CATCH cx_sy_create_error. + rv_ai_supported = abap_false. + ENDTRY. + CALL METHOD mr_srvb_svrs_config->('HAS_INACTIVE_VERSION') + RECEIVING + rv_has_inactive = rv_ai_supported. + + ENDMETHOD. + METHOD merge_object_data. + + DATA: + lo_object_data TYPE REF TO object, + lo_object_data_old TYPE REF TO if_wb_object_data_model, + lr_new TYPE REF TO data, + lr_old TYPE REF TO data, + lo_wb_object_operator TYPE REF TO object. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE any, + TYPE any. + + CREATE OBJECT lo_object_data TYPE ('CL_SRVB_OBJECT_DATA'). + lo_object_data = io_object_data. + + CREATE DATA lr_new TYPE ('CL_SRVB_OBJECT_DATA=>TY_OBJECT_DATA'). + ASSIGN lr_new->* TO . + ASSERT sy-subrc = 0. + + CREATE DATA lr_old TYPE ('CL_SRVB_OBJECT_DATA=>TY_OBJECT_DATA'). + ASSIGN lr_old->* TO . + ASSERT sy-subrc = 0. + + CALL METHOD lo_object_data->('IF_WB_OBJECT_DATA_MODEL~GET_DATA') + EXPORTING + p_metadata_only = abap_false + p_data_selection = 'AL' + IMPORTING + p_data = . + + lo_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + IMPORTING + eo_object_data = lo_object_data_old. + + CALL METHOD lo_object_data_old->('GET_DATA') + EXPORTING + p_metadata_only = abap_false + p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + IMPORTING + p_data = . + + ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . + ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . + = . + + CREATE OBJECT ro_object_data_merged TYPE ('CL_SRVB_OBJECT_DATA'). + + CALL METHOD ro_object_data_merged->('SET_DATA') + EXPORTING + p_data = . + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model. + + TRY. + mi_persistence->get( + EXPORTING + p_object_key = mv_service_binding_key + p_version = 'A' + CHANGING + p_object_data = li_object_data_model ). + + rv_user = li_object_data_model->get_changed_by( ). + + CATCH cx_swb_exception. + rv_user = c_user_unknown. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lx_error TYPE REF TO cx_swb_exception. + + TRY. + mi_persistence->delete( mv_service_binding_key ). + + CATCH cx_swb_exception INTO lx_error. + CALL FUNCTION 'DEQUEUE_ESWB_EO' + EXPORTING + objtype = ms_item-obj_type + objname = ms_item-obj_name. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + DATA: + lo_object_data TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root, + lo_wb_object_operator TYPE REF TO object, + lo_merged_data_all TYPE REF TO if_wb_object_data_model, + lv_version TYPE r3state. + + TRY. + lo_object_data = get_object_data( io_xml ). + lo_wb_object_operator = get_wb_object_operator( ). + + IF mv_is_inactive_supported = abap_true. + lv_version = 'I'. + ELSE. + lv_version = 'A'. + ENDIF. + + tadir_insert( iv_package ). + + IF zif_abapgit_object~exists( ) = abap_false. + "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = lo_object_data + data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data + version = lv_version + package = iv_package + transport_request = iv_transport. + + ELSE. + + lo_merged_data_all = merge_object_data( lo_object_data ). + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_merged_data_all + data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data + version = lv_version + transport_request = iv_transport. + + ENDIF. + + corr_insert( iv_package ). + + CATCH cx_root INTO lx_error. + CALL FUNCTION 'DEQUEUE_ESWB_EO' + EXPORTING + objtype = ms_item-obj_type + objname = ms_item-obj_name. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA lo_object_data TYPE REF TO if_wb_object_data_model. + + TRY. + IF mv_is_inactive_supported = abap_true. + TRY. + mi_persistence->get( + EXPORTING + p_object_key = mv_service_binding_key + p_version = 'I' + p_data_selection = 'ST' + CHANGING + p_object_data = lo_object_data ). + + CATCH cx_root. + mi_persistence->get( + EXPORTING + p_object_key = mv_service_binding_key + p_version = 'A' + p_data_selection = 'ST' + CHANGING + p_object_data = lo_object_data ). + + ENDTRY. + ELSE. + + mi_persistence->get( + EXPORTING + p_object_key = mv_service_binding_key + p_version = 'A' + p_data_selection = 'ST' + CHANGING + p_object_data = lo_object_data ). + + ENDIF. + rv_bool = boolc( lo_object_data IS NOT INITIAL AND lo_object_data->get_object_key( ) IS NOT INITIAL ). + CATCH cx_root. + rv_bool = abap_false. + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + li_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: + TYPE any. + + ASSIGN mr_service_binding->* TO . + ASSERT sy-subrc = 0. + + TRY. + li_wb_object_operator = get_wb_object_operator( ). + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + version = 'A' + data_selection = 'AL' + IMPORTING + eo_object_data = li_object_data_model. + + li_object_data_model->get_data( IMPORTING p_data = ). + + clear_fields( CHANGING cs_service_binding = ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + io_xml->add( + iv_name = 'SRVB' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_srfc IMPLEMENTATION. + METHOD constructor. + + DATA li_srfc_persist TYPE REF TO if_wb_object_persist. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). + CATCH cx_root. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: li_object_data TYPE REF TO if_wb_object_data_model, + li_srfc_persist TYPE REF TO if_wb_object_persist, + lr_srfc_data TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + TRY. + CREATE DATA lr_srfc_data TYPE ('UCONRFCSERV_COMPLETE'). + ASSIGN lr_srfc_data->* TO . + ASSERT sy-subrc = 0. + + CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). + + li_srfc_persist->get( + EXPORTING + p_object_key = |{ ms_item-obj_name }| + p_version = 'A' + CHANGING + p_object_data = li_object_data ). + + li_object_data->get_data( IMPORTING p_data = ). + + ASSIGN COMPONENT 'HEADER-CHANGEDBY' OF STRUCTURE TO . + IF sy-subrc = 0 AND IS NOT INITIAL. + rv_user = . + ELSE. + rv_user = c_user_unknown. + ENDIF. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: li_srfc_persist TYPE REF TO if_wb_object_persist, + lx_error TYPE REF TO cx_root. + + TRY. + CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). + + li_srfc_persist->delete( p_object_key = |{ ms_item-obj_name }| + p_version = 'A' ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: li_srfc_persist TYPE REF TO if_wb_object_persist, + li_object_data TYPE REF TO if_wb_object_data_model, + lr_srfc_data TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + TRY. + CREATE DATA lr_srfc_data TYPE ('UCONRFCSERV_COMPLETE'). + ASSIGN lr_srfc_data->* TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'HEADER-CREATEDBY' OF STRUCTURE TO . + IF sy-subrc = 0. + = sy-uname. + ENDIF. + + ASSIGN COMPONENT 'HEADER-CREATEDON' OF STRUCTURE TO . + IF sy-subrc = 0. + = sy-datum. + ENDIF. + + ASSIGN COMPONENT 'HEADER-CREATEDAT' OF STRUCTURE TO . + IF sy-subrc = 0. + = sy-uzeit. + ENDIF. + + io_xml->read( + EXPORTING + iv_name = 'SRFC' + CHANGING + cg_data = ). + + CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). + CREATE OBJECT li_object_data TYPE ('CL_UCONRFC_OBJECT_DATA'). + + li_object_data->set_data( ). + + li_srfc_persist->save( li_object_data ). + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: li_object_data TYPE REF TO if_wb_object_data_model, + li_srfc_persist TYPE REF TO if_wb_object_persist. + + TRY. + CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). + + li_srfc_persist->get( + EXPORTING + p_object_key = |{ ms_item-obj_name }| + p_version = 'A' + CHANGING + p_object_data = li_object_data ). + + CATCH cx_root. + rv_bool = abap_false. + RETURN. + ENDTRY. + + rv_bool = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: li_object_data TYPE REF TO if_wb_object_data_model, + li_srfc_persist TYPE REF TO if_wb_object_persist, + lr_srfc_data TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + TRY. + CREATE DATA lr_srfc_data TYPE ('UCONRFCSERV_COMPLETE'). + ASSIGN lr_srfc_data->* TO . + ASSERT sy-subrc = 0. + + CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). + + li_srfc_persist->get( + EXPORTING + p_object_key = |{ ms_item-obj_name }| + p_version = 'A' + CHANGING + p_object_data = li_object_data ). + + li_object_data->get_data( IMPORTING p_data = ). + + ASSIGN COMPONENT 'HEADER-CREATEDBY' OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + ASSIGN COMPONENT 'HEADER-CREATEDON' OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + ASSIGN COMPONENT 'HEADER-CREATEDAT' OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + io_xml->add( iv_name = 'SRFC' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sqsc IMPLEMENTATION. + METHOD constructor. + + FIELD-SYMBOLS: TYPE ty_abap_name. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE OBJECT mo_proxy + TYPE ('CL_DDIC_WB_DBPROC_PROXY'). + + ASSIGN ('MO_PROXY->IF_DDIC_WB_DBPROC_PROXY~DBPROXYNAME') + TO . + ASSERT sy-subrc = 0. + + CATCH cx_root. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + = ms_item-obj_name. + + ENDMETHOD. + METHOD delete_interface_if_it_exists. + + DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, + lo_interface TYPE REF TO zcl_abapgit_object_intf. + + " The interface is managed by the proxy. If abapGit + " has created it before we have to delete it. Otherwise + " if_dbproc_proxy_ui~create will throw errors. + + ls_item-obj_name = iv_interface. + ls_item-obj_type = 'INTF'. + + IF zcl_abapgit_objects=>exists( ls_item ) = abap_true. + + CREATE OBJECT lo_interface + EXPORTING + is_item = ls_item + iv_language = mv_language + io_files = mo_files + io_i18n_params = mo_i18n_params. + + lo_interface->zif_abapgit_object~delete( iv_package = iv_package + iv_transport = iv_transport ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA lx_error TYPE REF TO cx_root. + + TRY. + CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~READ_FROM_SOURCE') + EXPORTING + if_version = 'A' + IMPORTING + ef_change_user = rv_user. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lx_error TYPE REF TO cx_root. + + TRY. + CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~DELETE') + EXPORTING + if_transport_req = iv_transport. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_proxy TYPE ty_proxy, + lx_error TYPE REF TO cx_root. + + io_xml->read( + EXPORTING + iv_name = 'SQSC' + CHANGING + cg_data = ls_proxy ). + + IF zif_abapgit_object~exists( ) = abap_false. + + delete_interface_if_it_exists( + iv_package = iv_package + iv_transport = iv_transport + iv_interface = ls_proxy-header-interface_pool ). + + CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~CREATE') + EXPORTING + if_interface_pool = ls_proxy-header-interface_pool + if_transport_req = iv_transport + if_package = iv_package + if_langu = mv_language. + + ENDIF. + + TRY. + CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~WRITE_TO_SOURCE') + EXPORTING + if_transport_req = iv_transport + is_header = ls_proxy-header + it_parameter = ls_proxy-parameters + it_parameter_type = ls_proxy-parameter_types. + + CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~WRITE_DESCR') + EXPORTING + if_langu = mv_language + if_descr = ls_proxy-description. + + CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~ACTIVATE'). + + tadir_insert( iv_package ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~EXISTS') + RECEIVING + ef_exists = rv_bool. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_ADT_LINK=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_proxy TYPE ty_proxy, + lx_error TYPE REF TO cx_root. + + TRY. + CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~READ_FROM_SOURCE') + EXPORTING + if_version = 'A' + IMPORTING + es_header = ls_proxy-header + et_parameter = ls_proxy-parameters + et_parameter_type = ls_proxy-parameter_types. + + CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~READ_DESCR') + EXPORTING + if_langu = mv_language + if_version = 'A' + IMPORTING + ef_descr = ls_proxy-description. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + io_xml->add( iv_name = 'SQSC' + ig_data = ls_proxy ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sprx IMPLEMENTATION. + METHOD check_sprx_tadir. + + DATA: lt_abap_keys TYPE prx_abapobjects, + ls_abap_key LIKE LINE OF lt_abap_keys, + lx_error TYPE REF TO cx_proxy_gen_error. + + ls_abap_key-object = mv_object. + ls_abap_key-obj_name = mv_obj_name. + APPEND ls_abap_key TO lt_abap_keys. + + TRY. + cl_proxy_utils=>check_sprx_tadir( + objects = lt_abap_keys + repair = abap_true ). + + CATCH cx_proxy_gen_error INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + get_object_and_name( + IMPORTING + ev_object = mv_object + ev_obj_name = mv_obj_name ). + + ENDMETHOD. + METHOD delta_handling. + + DATA: lo_proxy TYPE REF TO cl_proxy, + lt_delta TYPE sprx_t_delta, + ls_db_data TYPE sprx_db_data. + + "add Delta-Handling to avoid that single objects created without the dependent objects. + "Thereby the dependent objects will be deleted + TRY. + lo_proxy = cl_proxy_fact=>load_by_abap_name( + object = mv_object + obj_name = mv_obj_name ). + lt_delta = lo_proxy->get_delta_all( ). + + ls_db_data = cl_proxy_db=>serialize( + proxy = lo_proxy + inactive = abap_false + delta = lt_delta ). + + et_sproxhdr_new = ls_db_data-sproxhdr. + et_sproxdat_new = ls_db_data-sproxdat. + + CATCH cx_proxy_gen_error. + "No delta for this object -> create + + ii_xml->read( + EXPORTING + iv_name = c_proxy-header + CHANGING + cg_data = et_sproxhdr_new ). + + IF et_sproxhdr_new IS INITIAL. + zcx_abapgit_exception=>raise( |SPRX - error deserialize: { ms_item-obj_name }| ). + ENDIF. + + ii_xml->read( + EXPORTING + iv_name = c_proxy-data + CHANGING + cg_data = et_sproxdat_new ). + + ENDTRY. + + ENDMETHOD. + METHOD get_object_and_name. + + ev_object = ms_item-obj_name(4). + ev_obj_name = ms_item-obj_name+4. + + ENDMETHOD. + METHOD load_db. + +* method cl_proxy_db=>load_by_abap_name does not exist in lower releases + + DATA: lt_packages TYPE prx_t_namespace_package, + ls_package LIKE LINE OF lt_packages, + ls_hdr TYPE prx_s_proxy_hdr, + lv_package TYPE tadir-devclass, + lt_ids TYPE prx_ids. + + cl_proxy_query=>get_hdr_by_abap_name( + EXPORTING + object = mv_object + obj_name = mv_obj_name + IMPORTING + hdr = ls_hdr ). + APPEND ls_hdr-id TO lt_ids. + + IF ls_hdr-gen_appl = 'WEBSERVICES'. + cl_proxy_utils=>get_package( + EXPORTING + object = mv_object + obj_name = mv_obj_name + RECEIVING + rval = lv_package + EXCEPTIONS + OTHERS = 0 ). + + ls_package-namespace = ls_hdr-esr_nspce. + ls_package-prefix = ls_hdr-prefix. + ls_package-package = lv_package. + APPEND ls_package TO lt_packages. + ENDIF. + + rs_data = cl_proxy_db=>load( + inactive = abap_false + ids = lt_ids + generating_application = ls_hdr-gen_appl + packages = lt_packages ). + + ENDMETHOD. + METHOD save. + + DATA: + lt_sproxhdr_old TYPE sprx_hdr_t, + lt_sproxdat_old TYPE sprx_dat_t, + lt_sproxsvar_old TYPE sprx_svar_t, + lt_sproxintf_old TYPE sprx_matchintf_t, + lt_sproxsvar_new TYPE sprx_svar_t, + lt_sproxintf_new TYPE sprx_matchintf_t. + + cl_proxy_data=>db_save( + sproxhdr_old = lt_sproxhdr_old + sproxdat_old = lt_sproxdat_old + sproxsvar_old = lt_sproxsvar_old + sproxintf_old = lt_sproxintf_old + sproxhdr_new = it_sproxhdr_new + sproxdat_new = it_sproxdat_new + sproxsvar_new = lt_sproxsvar_new + sproxintf_new = lt_sproxintf_new ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA lv_changed_by TYPE sproxhdr-changed_by. + + rv_user = c_user_unknown. + + SELECT SINGLE changed_by + FROM sproxhdr + INTO lv_changed_by + WHERE object = mv_object + AND obj_name = mv_obj_name + AND inactive = abap_false. + + IF sy-subrc = 0 AND lv_changed_by IS NOT INITIAL. + rv_user = lv_changed_by. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + lv_object TYPE sproxhdr-object, + lv_obj_name TYPE sproxhdr-obj_name, + lv_transp_flag TYPE abap_bool, + lv_return_code TYPE i, + lt_log TYPE sprx_log_t. + + IF iv_package(1) <> '$'. + lv_transp_flag = abap_true. + ENDIF. + + get_object_and_name( + IMPORTING + ev_object = lv_object + ev_obj_name = lv_obj_name ). + + TRY. + CALL METHOD ('CL_PROXY_DATA')=>('DELETE_SINGLE_PROXY') + EXPORTING + object = lv_object + obj_name = lv_obj_name + i_transport = lv_transp_flag + suppress_dialogs = abap_true + CHANGING + c_return_code = lv_return_code + ct_log = lt_log. + CATCH cx_root. + cl_proxy_data=>delete_single_proxy( + EXPORTING + object = lv_object + obj_name = lv_obj_name + i_transport = lv_transp_flag + CHANGING + c_return_code = lv_return_code + ct_log = lt_log ). + ENDTRY. + IF lv_return_code <> 0. + zcx_abapgit_exception=>raise( 'SPRX: Error from DELETE_SINGLE_PROXY' ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lt_sproxhdr_new TYPE sprx_hdr_t, + lt_sproxdat_new TYPE sprx_dat_t. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + delta_handling( + EXPORTING + ii_xml = io_xml + IMPORTING + et_sproxhdr_new = lt_sproxhdr_new + et_sproxdat_new = lt_sproxdat_new ). + + save( + it_sproxhdr_new = lt_sproxhdr_new + it_sproxdat_new = lt_sproxdat_new ). + + COMMIT WORK. + + check_sprx_tadir( ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: + lv_status TYPE prx_status, + lv_status_text TYPE prx_status_t. + + cl_proxy_data=>db_get_status( + EXPORTING + object = mv_object + obj_name = mv_obj_name + IMPORTING + status = lv_status + status_text = lv_status_text ). + + rv_bool = boolc( lv_status = if_proxy=>c_state_active ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = abap_true. "dummy implementation + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + ls_sprx_db_data TYPE sprx_db_data. + + FIELD-SYMBOLS: + LIKE LINE OF ls_sprx_db_data-sproxhdr, + LIKE LINE OF ls_sprx_db_data-sproxdat. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + ls_sprx_db_data = load_db( ). + + DELETE ls_sprx_db_data-sproxhdr WHERE object <> mv_object OR obj_name <> mv_obj_name. + DELETE ls_sprx_db_data-sproxdat WHERE object <> mv_object OR obj_name <> mv_obj_name. + DELETE ls_sprx_db_data-sproxsvar WHERE object <> mv_object OR obj_name <> mv_obj_name. + DELETE ls_sprx_db_data-sproxpck WHERE object <> mv_object OR obj_name <> mv_obj_name. + DELETE ls_sprx_db_data-sproxintf WHERE object <> mv_object OR obj_name <> mv_obj_name. + + IF lines( ls_sprx_db_data-sproxhdr ) <> 1. + zcx_abapgit_exception=>raise( |SPRX, no header found, { mv_object }, { mv_obj_name }| ). + ENDIF. + + LOOP AT ls_sprx_db_data-sproxhdr ASSIGNING . + + CLEAR: + -created_by, + -created_on, + -changed_by, + -changed_on. + + ENDLOOP. + + LOOP AT ls_sprx_db_data-sproxdat ASSIGNING . + + CLEAR -warnings. + + ENDLOOP. + + io_xml->add( + iv_name = c_proxy-header + ig_data = ls_sprx_db_data-sproxhdr ). + + io_xml->add( + iv_name = c_proxy-data + ig_data = ls_sprx_db_data-sproxdat ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sppf IMPLEMENTATION. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " not stored by SAP + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + set_default_transport( iv_transport ). + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + set_default_transport( iv_transport ). + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_splo IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE chgname1 FROM tsp1d INTO rv_user + WHERE papart = ms_item-obj_name. + IF sy-subrc <> 0 OR rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DELETE FROM tsp1t WHERE papart = ms_item-obj_name. "#EC CI_NOFIRST "#EC CI_SUBRC + DELETE FROM tsp1d WHERE papart = ms_item-obj_name. "#EC CI_SUBRC + DELETE FROM tsp0p WHERE pdpaper = ms_item-obj_name. "#EC CI_SUBRC + + set_default_transport( iv_transport ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_tsp1t TYPE tsp1t, + ls_tsp1d TYPE tsp1d, + ls_tsp0p TYPE tsp0p. + io_xml->read( EXPORTING iv_name = 'TSPLT' + CHANGING cg_data = ls_tsp1t ). + io_xml->read( EXPORTING iv_name = 'TSPLD' + CHANGING cg_data = ls_tsp1d ). + io_xml->read( EXPORTING iv_name = 'TSP0P' + CHANGING cg_data = ls_tsp0p ). + + MODIFY tsp1t FROM ls_tsp1t. "#EC CI_SUBRC + MODIFY tsp1d FROM ls_tsp1d. "#EC CI_SUBRC + MODIFY tsp0p FROM ls_tsp0p. "#EC CI_SUBRC + + set_default_transport( iv_transport ). + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_papart TYPE tsp1d-papart. + SELECT SINGLE papart INTO lv_papart FROM tsp1d + WHERE papart = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_tsp1t TYPE tsp1t, + ls_tsp1d TYPE tsp1d, + ls_tsp0p TYPE tsp0p. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + SELECT SINGLE * FROM tsp1t INTO ls_tsp1t + WHERE papart = ms_item-obj_name + AND spras = mv_language. "#EC CI_GENBUFF "#EC CI_SUBRC + SELECT SINGLE * FROM tsp1d INTO ls_tsp1d + WHERE papart = ms_item-obj_name. "#EC CI_SUBRC + SELECT SINGLE * FROM tsp0p INTO ls_tsp0p + WHERE pdpaper = ms_item-obj_name. "#EC CI_SUBRC + + CLEAR: ls_tsp1d-chgname1, + ls_tsp1d-chgtstmp1, + ls_tsp1d-chgsaprel1, + ls_tsp1d-chgsapsys1. + + io_xml->add( iv_name = 'TSPLT' + ig_data = ls_tsp1t ). + io_xml->add( iv_name = 'TSPLD' + ig_data = ls_tsp1d ). + io_xml->add( iv_name = 'TSP0P' + ig_data = ls_tsp0p ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sots IMPLEMENTATION. + METHOD create_sots. + + " Reimplementation of SOTR_STRING_CREATE_CONCEPT because we can't supply + " concept and it would then be generated. + + DATA: lv_subrc TYPE sy-subrc, + lv_source_langu TYPE spras, + ls_header TYPE btfr_head, + lv_flag_is_string TYPE btfr_flag VALUE abap_true, + lt_text_tab TYPE sotr_text_tt, + lv_concept_default TYPE sotr_conc, + lt_entries TYPE sotr_textl_tt, + lv_concept LIKE is_sots-header-concept, + lv_flag_correction_entry TYPE abap_bool VALUE abap_true. + + lt_entries = is_sots-entries. + + ls_header-paket = iv_package. + ls_header-crea_lan = mv_language. + ls_header-alias_name = is_sots-header-alias_name. + lv_source_langu = mv_language. + lv_concept = is_sots-header-concept. + + PERFORM btfr_create + IN PROGRAM saplsotr_db_string + USING iv_object + lv_source_langu + lv_flag_correction_entry + lv_flag_is_string + CHANGING lt_text_tab + lt_entries + ls_header + lv_concept + lv_concept_default + lv_subrc. + + CASE lv_subrc. + WHEN 1. + zcx_abapgit_exception=>raise( |No entry found| ). + WHEN 2. + zcx_abapgit_exception=>raise( |OTR concept not found| ). + WHEN 3. + zcx_abapgit_exception=>raise( |Enter a permitted object type| ). + WHEN 4. + "The concept will be created in the non-original system (not an error) + RETURN. + WHEN 5. + zcx_abapgit_exception=>raise( |Invalid alias| ). + WHEN 6. + zcx_abapgit_exception=>raise( |No correction entry has been created| ). + WHEN 7. + zcx_abapgit_exception=>raise( |Error in database operation| ). + WHEN 9. + zcx_abapgit_exception=>raise( |Action canceled by user| ). + ENDCASE. + + ENDMETHOD. + METHOD get_raw_text_filename. + + DATA lv_langu TYPE string. + + " Lower case language codes can cause duplicate filenames therefore add suffix to make them unique + " Note: Using ISO code would be better but is not compatible with existing files + lv_langu = is_entry-langu. + IF lv_langu = to_lower( lv_langu ). + lv_langu = lv_langu && '-'. + ENDIF. + + rv_filename = + to_lower( |{ is_entry-concept }_| + && |{ lv_langu }_| + && |{ is_entry-object }_| + && |{ is_entry-lfd_num }| ). + + ENDMETHOD. + METHOD read_sots. + + DATA: lt_sotr_head TYPE STANDARD TABLE OF sotr_headu, + lt_objects TYPE sotr_objects, + lv_object LIKE LINE OF lt_objects, + ls_sots LIKE LINE OF rt_sots. + + FIELD-SYMBOLS: TYPE sotr_head, + LIKE LINE OF ls_sots-entries. + SELECT * FROM sotr_headu + INTO TABLE lt_sotr_head + WHERE paket = ms_item-obj_name + ORDER BY PRIMARY KEY. + + LOOP AT lt_sotr_head ASSIGNING . + + CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' + EXPORTING + object_vector = -objid_vec + IMPORTING + objects = lt_objects + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + + READ TABLE lt_objects INDEX 1 INTO lv_object. + ASSERT sy-subrc = 0. + + " Handled by object serializer + CHECK lv_object <> 'SICF' AND lv_object <> 'CPUB'. + + CLEAR: ls_sots. + + CALL FUNCTION 'SOTR_STRING_GET_CONCEPT' + EXPORTING + concept = -concept + IMPORTING + header = ls_sots-header + entries = ls_sots-entries + EXCEPTIONS + no_entry_found = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + + CLEAR: + ls_sots-header-paket, + ls_sots-header-crea_name, + ls_sots-header-crea_tstut, + ls_sots-header-chan_name, + ls_sots-header-chan_tstut. + + LOOP AT ls_sots-entries ASSIGNING . + CLEAR: -version, + -crea_name, + -crea_tstut, + -chan_name, + -chan_tstut. + ENDLOOP. + + INSERT ls_sots INTO TABLE rt_sots. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + SELECT SINGLE chan_name FROM sotr_headu INTO rv_user + WHERE paket = ms_item-obj_name. "#EC CI_NOORDER + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lt_sots TYPE ty_sots_tt. + + FIELD-SYMBOLS: TYPE ty_sots. + + lt_sots = read_sots( ). + + LOOP AT lt_sots ASSIGNING . + " Remove any usage to ensure deletion, see function module BTFR_CHECK + DELETE FROM sotr_useu WHERE concept = -header-concept. + + CALL FUNCTION 'BTFR_DELETE_SINGLE_TEXT' + EXPORTING + concept = -header-concept + flag_string = abap_true + EXCEPTIONS + text_not_found = 1 + invalid_package = 2 + text_not_changeable = 3 + text_enqueued = 4 + no_correction = 5 + parameter_error = 6 + OTHERS = 7. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lt_sots TYPE ty_sots_tt, + lt_objects TYPE sotr_objects, + lv_object LIKE LINE OF lt_objects. + + FIELD-SYMBOLS: TYPE ty_sots, + LIKE LINE OF -entries. + + io_xml->read( + EXPORTING + iv_name = 'SOTS' + CHANGING + cg_data = lt_sots ). + + tadir_insert( iv_package ). + + LOOP AT lt_sots ASSIGNING . + + CLEAR: lt_objects. + + CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' + EXPORTING + object_vector = -header-objid_vec + IMPORTING + objects = lt_objects + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from SOTR_OBJECT_GET_OBJECTS' ). + ENDIF. + + READ TABLE lt_objects INDEX 1 INTO lv_object. + ASSERT sy-subrc = 0. + + LOOP AT -entries ASSIGNING . + + TRY. + -text = mo_files->read_string( + iv_extra = get_raw_text_filename( ) + iv_ext = 'txt' ). + + CATCH zcx_abapgit_exception. + " Most probably file not found -> ignore + CONTINUE. + ENDTRY. + + ENDLOOP. + + create_sots( + is_sots = + iv_package = iv_package + iv_object = lv_object ). + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_object_type TYPE trobjtype, + lv_object_name TYPE trobj_name. + + lv_object_type = ms_item-obj_type. + lv_object_name = ms_item-obj_name. + + CALL FUNCTION 'SOTR_WBO_OBJECTS_CHECK' + EXPORTING + pgmid = 'R3TR' + object = lv_object_type + obj_name = lv_object_name + IMPORTING + object_exist = rv_bool + EXCEPTIONS + unknown_object = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + rv_bool = abap_false. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lt_sots TYPE ty_sots_tt. + + FIELD-SYMBOLS: TYPE ty_sots, + TYPE sotr_textl. + + lt_sots = read_sots( ). + + LOOP AT lt_sots ASSIGNING . + + LOOP AT -entries ASSIGNING . + + mo_files->add_string( + iv_extra = get_raw_text_filename( ) + iv_ext = 'txt' + iv_string = -text ). + + CLEAR: -text. + + ENDLOOP. + + ENDLOOP. + + io_xml->add( iv_name = 'SOTS' + ig_data = lt_sots ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sod2 IMPLEMENTATION. + METHOD clear_content_fields. + + FIELD-SYMBOLS TYPE any. + + ASSIGN COMPONENT 'CONTENT' OF STRUCTURE cs_data TO . + + clear_field( + EXPORTING + iv_fieldname = 'CHANGE_USER' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGE_TIMESTAMP' + CHANGING + cs_metadata = ). + + ENDMETHOD. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_metadata TO . + IF sy-subrc = 0. + CLEAR: . + ENDIF. + + ENDMETHOD. + METHOD clear_metadata_fields. + + FIELD-SYMBOLS TYPE any. + + ASSIGN COMPONENT 'METADATA' OF STRUCTURE cs_data TO . + + clear_field( + EXPORTING + iv_fieldname = 'VERSION' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CREATED_AT' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CREATED_BY' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGED_AT' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGED_BY' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'RESPONSIBLE' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'PACKAGE_REF' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'MASTER_SYSTEM' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'DT_UUID' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'ABAP_LANGU_VERSION' + CHANGING + cs_metadata = ). + clear_field( + EXPORTING + iv_fieldname = 'ABAP_LANGU_VERSION' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'LINKS' + CHANGING + cs_metadata = ). + + ENDMETHOD. + METHOD constructor. + + DATA lo_data_model TYPE REF TO object. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE OBJECT lo_data_model TYPE (c_data_model_class_name). + CATCH cx_root. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD create_wb_object_operator. + + DATA lx_error TYPE REF TO cx_root. + + TRY. + + CALL METHOD ('CL_WB_OBJECT_OPERATOR_FACTORY')=>('CREATE_OBJECT_OPERATOR') + EXPORTING + object_type = is_object_type + object_key = iv_object_key + transport_request = iv_transport_request + do_commits = iv_do_commits + run_in_test_mode = iv_run_in_test_mode + RECEIVING + result = ro_wb_object_operator. + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD get_wb_object_operator. + + DATA lx_error TYPE REF TO cx_root. + + TRY. + + CALL METHOD ('CL_WB_OBJECT_OPERATOR_FACTORY')=>('GET_OBJECT_OPERATOR') + EXPORTING + object_type = is_object_type + object_key = iv_object_key + transport_request = iv_transport_request + RECEIVING + result = ro_wb_object_operator. + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_data_model TYPE REF TO if_wb_object_data_model, + lo_factory TYPE REF TO object, + ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lx_error TYPE REF TO cx_root. + + TRY. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + lo_factory = create_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key ). + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = lo_data_model. + + rv_user = lo_data_model->get_changed_by( ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lo_factory TYPE REF TO object, + lx_error TYPE REF TO cx_root. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + TRY. + + lo_factory = get_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key + iv_transport_request = iv_transport ). + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~DELETE'). + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lo_factory TYPE REF TO object, + lo_data_model TYPE REF TO if_wb_object_data_model, + lv_data_type_name TYPE string, + ls_data TYPE REF TO data, + ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lo_logger TYPE REF TO cl_wb_checklist, + lx_create_error TYPE REF TO cx_root, + lx_error TYPE REF TO cx_root, + lt_msgs TYPE TABLE OF string, + lt_error_msgs_create TYPE swbme_error_tab, + ls_error_msg_create LIKE LINE OF lt_error_msgs_create, + lv_error_msg TYPE string, + lv_abap_language_version TYPE c LENGTH 1. " abap_language_version + + FIELD-SYMBOLS TYPE any. + + CREATE OBJECT lo_data_model TYPE (c_data_model_class_name). + + " if_wb_object_data_selection_co=>c_all_data + CALL METHOD lo_data_model->('GET_DATATYPE_NAME') + EXPORTING + p_data_selection = 'AL' + RECEIVING + result = lv_data_type_name. + + CREATE DATA ls_data TYPE (lv_data_type_name). + ASSIGN ls_data->* TO . + + io_xml->read( + EXPORTING + iv_name = c_xml_transformation_name + CHANGING + cg_data = ). + + CALL METHOD lo_data_model->('SET_SELECTED_DATA') + EXPORTING + p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + p_data = . + + TRY. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + lo_factory = get_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key ). + + IF zif_abapgit_object~exists( ) = abap_true. + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_data_model + version = 'A' + transport_request = iv_transport. + + ELSE. + + TRY. + + CALL METHOD lo_data_model->('GET_ABAP_LANGUAGE_VERSION') + RECEIVING + result = lv_abap_language_version. + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = lo_data_model + version = 'A' + package = iv_package + abap_language_version = lv_abap_language_version + transport_request = iv_transport + IMPORTING + logger = lo_logger. + + CATCH cx_root INTO lx_create_error. + + " Check for error messages from Workbench API to provide more error infos to user + lo_logger->get_error_messages( IMPORTING p_error_tab = lt_error_msgs_create ). + + IF lt_error_msgs_create IS NOT INITIAL. + + LOOP AT lt_error_msgs_create INTO ls_error_msg_create. + + APPEND LINES OF ls_error_msg_create-mtext TO lt_msgs. + + ENDLOOP. + + CONCATENATE LINES OF lt_msgs INTO lv_error_msg SEPARATED BY '; '. + zcx_abapgit_exception=>raise( iv_text = lv_error_msg + ix_previous = lx_create_error ). + + ELSE. + + zcx_abapgit_exception=>raise_with_text( lx_create_error ). + + ENDIF. + + ENDTRY. + + ENDIF. + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lo_factory TYPE REF TO object, + ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lx_error TYPE REF TO cx_root. + + TRY. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + lo_factory = get_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key ). + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~CHECK_EXISTENCE') + RECEIVING + r_result = rv_bool. + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }*| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_data_model TYPE REF TO if_wb_object_data_model, + lv_data_type_name TYPE string, + lo_factory TYPE REF TO object, + ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lx_error TYPE REF TO cx_root. + + DATA ls_data TYPE REF TO data. + FIELD-SYMBOLS TYPE any. + + TRY. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + lo_factory = create_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key ). + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = lo_data_model. + + " if_wb_object_data_selection_co=>c_all_data + CALL METHOD lo_data_model->('GET_DATATYPE_NAME') + EXPORTING + p_data_selection = 'AL' + RECEIVING + result = lv_data_type_name. + + CREATE DATA ls_data TYPE (lv_data_type_name). + ASSIGN ls_data->* TO . + + CALL METHOD lo_data_model->('GET_SELECTED_DATA') + EXPORTING + p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + IMPORTING + p_data = . + + clear_metadata_fields( CHANGING cs_data = ). + clear_content_fields( CHANGING cs_data = ). + clear_field( EXPORTING iv_fieldname = 'PLUGIN_CONFIG' + CHANGING cs_metadata = ). + + io_xml->add( iv_name = c_xml_transformation_name + ig_data = ). + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sod1 IMPLEMENTATION. + METHOD clear_content_fields. + + FIELD-SYMBOLS TYPE any. + + ASSIGN COMPONENT 'CONTENT' OF STRUCTURE cs_data TO . + + clear_field( + EXPORTING + iv_fieldname = 'CHANGE_USER' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGE_TIMESTAMP' + CHANGING + cs_metadata = ). + + ENDMETHOD. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_metadata TO . + IF sy-subrc = 0. + CLEAR: . + ENDIF. + + ENDMETHOD. + METHOD clear_metadata_fields. + + FIELD-SYMBOLS TYPE any. + + ASSIGN COMPONENT 'METADATA' OF STRUCTURE cs_data TO . + + clear_field( + EXPORTING + iv_fieldname = 'VERSION' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CREATED_AT' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CREATED_BY' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGED_AT' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGED_BY' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'RESPONSIBLE' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'PACKAGE_REF' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'MASTER_SYSTEM' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'DT_UUID' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'ABAP_LANGU_VERSION' + CHANGING + cs_metadata = ). + clear_field( + EXPORTING + iv_fieldname = 'ABAP_LANGU_VERSION' + CHANGING + cs_metadata = ). + + clear_field( + EXPORTING + iv_fieldname = 'LINKS' + CHANGING + cs_metadata = ). + + ENDMETHOD. + METHOD constructor. + + DATA lo_data_model TYPE REF TO object. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE OBJECT lo_data_model TYPE (c_data_model_class_name). + CATCH cx_root. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD create_wb_object_operator. + + DATA lx_error TYPE REF TO cx_root. + + TRY. + + CALL METHOD ('CL_WB_OBJECT_OPERATOR_FACTORY')=>('CREATE_OBJECT_OPERATOR') + EXPORTING + object_type = is_object_type + object_key = iv_object_key + transport_request = iv_transport_request + do_commits = iv_do_commits + run_in_test_mode = iv_run_in_test_mode + RECEIVING + result = ro_wb_object_operator. + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD get_wb_object_operator. + + DATA lx_error TYPE REF TO cx_root. + + TRY. + + CALL METHOD ('CL_WB_OBJECT_OPERATOR_FACTORY')=>('GET_OBJECT_OPERATOR') + EXPORTING + object_type = is_object_type + object_key = iv_object_key + transport_request = iv_transport_request + RECEIVING + result = ro_wb_object_operator. + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_data_model TYPE REF TO if_wb_object_data_model, + lo_factory TYPE REF TO object, + ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lx_error TYPE REF TO cx_root. + + TRY. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + lo_factory = create_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key ). + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = lo_data_model. + + rv_user = lo_data_model->get_changed_by( ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lo_factory TYPE REF TO object, + lx_error TYPE REF TO cx_root. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + TRY. + + lo_factory = get_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key + iv_transport_request = iv_transport ). + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~DELETE'). + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lo_factory TYPE REF TO object, + lo_data_model TYPE REF TO if_wb_object_data_model, + lv_data_type_name TYPE string, + ls_data TYPE REF TO data, + ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lo_logger TYPE REF TO cl_wb_checklist, + lx_create_error TYPE REF TO cx_root, + lx_error TYPE REF TO cx_root, + lt_msgs TYPE TABLE OF string, + lt_error_msgs_create TYPE swbme_error_tab, + ls_error_msg_create LIKE LINE OF lt_error_msgs_create, + lv_error_msg TYPE string, + lv_abap_language_version TYPE c LENGTH 1. " abap_language_version + FIELD-SYMBOLS TYPE any. + + CREATE OBJECT lo_data_model TYPE (c_data_model_class_name). + + " if_wb_object_data_selection_co=>c_all_data + CALL METHOD lo_data_model->('GET_DATATYPE_NAME') + EXPORTING + p_data_selection = 'AL' + RECEIVING + result = lv_data_type_name. + + CREATE DATA ls_data TYPE (lv_data_type_name). + ASSIGN ls_data->* TO . + + io_xml->read( + EXPORTING + iv_name = c_xml_transformation_name + CHANGING + cg_data = ). + + CALL METHOD lo_data_model->('SET_SELECTED_DATA') + EXPORTING + p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + p_data = . + + TRY. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + lo_factory = get_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key ). + + IF zif_abapgit_object~exists( ) = abap_true. + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_data_model + version = 'A' + transport_request = iv_transport. + + ELSE. + + TRY. + + CALL METHOD lo_data_model->('GET_ABAP_LANGUAGE_VERSION') + RECEIVING + result = lv_abap_language_version. + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = lo_data_model + version = 'A' + package = iv_package + abap_language_version = lv_abap_language_version + transport_request = iv_transport + IMPORTING + logger = lo_logger. + + CATCH cx_root INTO lx_create_error. + + " Check for error messages from Workbench API to provide more error infos to user + lo_logger->get_error_messages( IMPORTING p_error_tab = lt_error_msgs_create ). + + IF lt_error_msgs_create IS NOT INITIAL. + + LOOP AT lt_error_msgs_create INTO ls_error_msg_create. + + APPEND LINES OF ls_error_msg_create-mtext TO lt_msgs. + + ENDLOOP. + + CONCATENATE LINES OF lt_msgs INTO lv_error_msg SEPARATED BY '; '. + zcx_abapgit_exception=>raise( iv_text = lv_error_msg + ix_previous = lx_create_error ). + + ELSE. + + zcx_abapgit_exception=>raise_with_text( lx_create_error ). + + ENDIF. + + ENDTRY. + + ENDIF. + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lo_factory TYPE REF TO object, + ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lx_error TYPE REF TO cx_root. + + TRY. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + lo_factory = get_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key ). + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~CHECK_EXISTENCE') + RECEIVING + r_result = rv_bool. + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }*| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_data_model TYPE REF TO if_wb_object_data_model, + lv_data_type_name TYPE string, + lo_factory TYPE REF TO object, + ls_object_type TYPE wbobjtype, + lv_object_key TYPE seu_objkey, + lx_error TYPE REF TO cx_root. + + DATA ls_data TYPE REF TO data. + FIELD-SYMBOLS TYPE any. + + TRY. + + ls_object_type-objtype_tr = ms_item-obj_type. + lv_object_key = ms_item-obj_name. + + lo_factory = create_wb_object_operator( is_object_type = ls_object_type + iv_object_key = lv_object_key ). + + CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = lo_data_model. + + " if_wb_object_data_selection_co=>c_all_data + CALL METHOD lo_data_model->('GET_DATATYPE_NAME') + EXPORTING + p_data_selection = 'AL' + RECEIVING + result = lv_data_type_name. + + CREATE DATA ls_data TYPE (lv_data_type_name). + ASSIGN ls_data->* TO . + + CALL METHOD lo_data_model->('GET_SELECTED_DATA') + EXPORTING + p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + IMPORTING + p_data = . + + clear_metadata_fields( CHANGING cs_data = ). + clear_content_fields( CHANGING cs_data = ). + clear_field( EXPORTING iv_fieldname = 'PLUGIN_CONFIG' + CHANGING cs_metadata = ). + + io_xml->add( iv_name = c_xml_transformation_name + ig_data = ). + + CATCH cx_root INTO lx_error. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sobj IMPLEMENTATION. + METHOD get_field_rules. + + ri_rules = zcl_abapgit_field_rules=>create( ). + ri_rules->add( + iv_table = 'TOJTB' + iv_field = 'CREA_USER' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = 'TOJTB' + iv_field = 'CREA_DATE' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date + )->add( + iv_table = 'TOJTB' + iv_field = 'CREA_TIME' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time + )->add( + iv_table = 'TOJTB' + iv_field = 'CHAN_USER' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = 'TOJTB' + iv_field = 'CHAN_DATE' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date + )->add( + iv_table = 'TOJTB' + iv_field = 'CHAN_TIME' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time + )->add( + iv_table = 'TOJTB' + iv_field = 'ACTV_USER' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = 'TOJTB' + iv_field = 'ACTV_DATE' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date + )->add( + iv_table = 'TOJTB' + iv_field = 'ACTV_TIME' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time + )->add( + iv_table = 'TOJTB' + iv_field = 'REL_USER' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = 'TOJTB' + iv_field = 'REL_DATE' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date + )->add( + iv_table = 'TOJTB' + iv_field = 'REL_TIME' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time ). + + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD get_program. + SELECT SINGLE progname INTO rv_program FROM tojtb WHERE name = ms_item-obj_name. + ENDMETHOD. + METHOD is_locked. + rv_is_locked = boolc( is_objtype_locked( ) = abap_true OR is_program_locked( ) = abap_true ). + ENDMETHOD. + METHOD is_objtype_locked. + CONSTANTS lc_tabname TYPE tabname VALUE 'SWOTBASDAT'. + DATA lv_varkey TYPE vim_enqkey. + + rv_is_locked = abap_false. + lv_varkey = ms_item-obj_name. + + CALL FUNCTION 'ENQUEUE_E_TABLE' + EXPORTING + tabname = lc_tabname + varkey = lv_varkey + EXCEPTIONS + foreign_lock = 1 + OTHERS = 999. + IF sy-subrc IS NOT INITIAL. + rv_is_locked = abap_true. + ELSE. + CALL FUNCTION 'DEQUEUE_E_TABLE' + EXPORTING + tabname = lc_tabname + varkey = lv_varkey. + ENDIF. + ENDMETHOD. + METHOD is_program_locked. + CONSTANTS lc_enqueue_exclusive TYPE enqmode VALUE 'X'. + DATA lv_progname TYPE progname. + + rv_is_locked = abap_false. + lv_progname = get_program( ). + + IF lv_progname IS NOT INITIAL. + CALL FUNCTION 'ENQUEUE_ESRDIRE' + EXPORTING + mode_trdir = lc_enqueue_exclusive + name = lv_progname + EXCEPTIONS + foreign_lock = 1 + OTHERS = 999. + IF sy-subrc IS NOT INITIAL. + rv_is_locked = abap_true. + ELSE. + CALL FUNCTION 'DEQUEUE_ESRDIRE' + EXPORTING + mode_trdir = lc_enqueue_exclusive + name = lv_progname. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + DATA: BEGIN OF ls_userinfo, + crea_user TYPE tojtb-crea_user, + chan_user TYPE tojtb-chan_user, + END OF ls_userinfo. + + SELECT SINGLE + crea_user + chan_user + INTO (ls_userinfo-crea_user, ls_userinfo-chan_user) + FROM tojtb WHERE name = ms_item-obj_name. + + IF ls_userinfo-chan_user IS INITIAL. + ls_userinfo-chan_user = ls_userinfo-crea_user. + ENDIF. + rv_user = ls_userinfo-chan_user. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = is_locked( ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + "No need as GENERIC class already handles it + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_smtg IMPLEMENTATION. + METHOD add_component. + + DATA: + ls_component LIKE LINE OF ct_components, + lo_typedescr TYPE REF TO cl_abap_typedescr. + + cl_abap_structdescr=>describe_by_name( + EXPORTING + p_name = iv_structure_name + RECEIVING + p_descr_ref = lo_typedescr + EXCEPTIONS + type_not_found = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = ms_item-obj_type. + ENDIF. + + ls_component-name = iv_fielname. + ls_component-type ?= lo_typedescr. + INSERT ls_component INTO TABLE ct_components. + + ENDMETHOD. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN + COMPONENT iv_fieldname + OF STRUCTURE cg_header + TO . + ASSERT sy-subrc = 0. + + CLEAR: . + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_template_id = ms_item-obj_name. + mo_structdescr = get_structure( ). + + ENDMETHOD. + METHOD get_structure. + + DATA: lt_components TYPE abap_component_tab. + + add_component( + EXPORTING + iv_fielname = `HEADER` + iv_structure_name = `IF_SMTG_EMAIL_TEMPLATE=>TY_GS_TMPL_HDR` + CHANGING + ct_components = lt_components ). + + add_component( + EXPORTING + iv_fielname = `HEADER_T` + iv_structure_name = `IF_SMTG_EMAIL_TEMPLATE=>TY_GT_TMPL_HDR_T` + CHANGING + ct_components = lt_components ). + + add_component( + EXPORTING + iv_fielname = `CONTENT` + iv_structure_name = `IF_SMTG_EMAIL_TEMPLATE=>TY_GT_TMPL_CONT` + CHANGING + ct_components = lt_components ). + + ro_structdescr = cl_abap_structdescr=>create( lt_components ). + + ENDMETHOD. + METHOD get_template. + + DATA: + lr_template TYPE REF TO data, + lx_error TYPE REF TO cx_root, + lo_template TYPE REF TO object. + + FIELD-SYMBOLS: + TYPE data, + TYPE data, + TYPE INDEX TABLE, + TYPE INDEX TABLE. + CREATE DATA lr_template TYPE HANDLE mo_structdescr. + ASSIGN lr_template->* TO . + ASSERT sy-subrc = 0. + + ASSIGN + COMPONENT 'HEADER' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + ASSIGN + COMPONENT 'HEADER_T' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + ASSIGN + COMPONENT 'CONTENT' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + TRY. + CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>get + EXPORTING + iv_id = mv_template_id + RECEIVING + ro_instance = lo_template. + + CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~GET_TMPL_HDR') + RECEIVING + rs_tmpl_hdr = . + + CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~GET_TMPL_HDR_T_ALL') + RECEIVING + rt_tmpl_hdr_t = . + + CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~GET_TMPL_CONT_ALL') + RECEIVING + rt_tmpl_cont = . + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + es_template = . + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: + lr_template TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE data, + TYPE data. + + CREATE DATA lr_template TYPE HANDLE mo_structdescr. + ASSIGN lr_template->* TO . + ASSERT sy-subrc = 0. + + get_template( IMPORTING es_template = ). + + ASSIGN + COMPONENT 'HEADER-LST_CH_USER_ACCT' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + rv_user = . + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lx_error TYPE REF TO cx_root. + + TRY. + CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>delete + EXPORTING + iv_id = mv_template_id. + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + lr_template TYPE REF TO data, + lx_error TYPE REF TO cx_root, + lo_template TYPE REF TO object. + + FIELD-SYMBOLS: + TYPE data, + TYPE data, + TYPE INDEX TABLE, + TYPE INDEX TABLE, + TYPE data, + TYPE data, + TYPE data. + + CREATE DATA lr_template TYPE HANDLE mo_structdescr. + ASSIGN lr_template->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'SMTG' + CHANGING + cg_data = ). + + ASSIGN + COMPONENT 'HEADER' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + ASSIGN + COMPONENT 'HEADER_T' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + ASSIGN + COMPONENT 'CONTENT' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + TRY. + IF zif_abapgit_object~exists( ) = abap_true. + CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>get + EXPORTING + iv_id = mv_template_id + RECEIVING + ro_instance = lo_template. + ELSE. + CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>create + EXPORTING + is_tmpl_hdr = + RECEIVING + ro_email_template = lo_template. + ENDIF. + + CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~SET_TMPL_CONT_ALL') + EXPORTING + it_tmpl_cont = . + + READ TABLE ASSIGNING + INDEX 1. + IF sy-subrc = 0. + ASSIGN + COMPONENT 'NAME' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + ASSIGN + COMPONENT 'DESCRIPTION' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~SET_TEXT') + EXPORTING + iv_name = + iv_description = . + ENDIF. + + tadir_insert( iv_package ). + corr_insert( iv_package ). + + CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~SAVE') + EXPORTING + iv_lock = abap_true + iv_commit = abap_true + iv_wait = abap_true. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>get + EXPORTING + iv_id = mv_template_id. + + rv_bool = abap_true. + + CATCH cx_root. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_SMTG' + iv_argument = |{ mv_template_id }| ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + lr_template TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: + TYPE data, + TYPE data. + + CREATE DATA lr_template TYPE HANDLE mo_structdescr. + ASSIGN lr_template->* TO . + ASSERT sy-subrc = 0. + + get_template( IMPORTING es_template = ). + + ASSIGN + COMPONENT 'HEADER' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + TRY. + clear_field( EXPORTING iv_fieldname = 'CREA_DATE_TIME' CHANGING cg_header = ). + clear_field( EXPORTING iv_fieldname = 'CREA_USER_ACCT' CHANGING cg_header = ). + clear_field( EXPORTING iv_fieldname = 'LST_CH_DATE_TIME' CHANGING cg_header = ). + clear_field( EXPORTING iv_fieldname = 'LST_CH_USER_ACCT' CHANGING cg_header = ). + + io_xml->add( + iv_name = 'SMTG' + ig_data = ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_smim IMPLEMENTATION. + METHOD build_filename. + + CONCATENATE ms_item-obj_name ms_item-obj_type iv_filename + INTO rv_filename SEPARATED BY '.'. + TRANSLATE rv_filename TO LOWER CASE. + + ENDMETHOD. + METHOD find_content. + + DATA: lv_filename TYPE string, + lt_files TYPE zif_abapgit_git_definitions=>ty_files_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_files. + lv_filename = get_filename( iv_url ). + + lv_filename = build_filename( lv_filename ). + + lt_files = mo_files->get_files( ). + + READ TABLE lt_files ASSIGNING + WITH KEY file + COMPONENTS filename = lv_filename. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'SMIM, file not found' ). + ENDIF. + + rv_content = -data. + + ENDMETHOD. + METHOD get_filename. + + DATA: lv_lines TYPE i, + lt_strings TYPE TABLE OF string. + SPLIT iv_url AT '/' INTO TABLE lt_strings. + lv_lines = lines( lt_strings ). + ASSERT lv_lines > 0. + READ TABLE lt_strings INDEX lv_lines INTO rv_filename. + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD get_url_for_io. + + DATA: ls_io TYPE skwf_io, + lv_url TYPE skwf_url, + ls_smimloio TYPE smimloio, + lv_loio TYPE sdok_docid. + lv_loio = ms_item-obj_name. + + CLEAR ev_url. + CLEAR ev_is_folder. + + SELECT SINGLE * FROM smimloio INTO ls_smimloio + WHERE loio_id = lv_loio. "#EC CI_GENBUFF + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_abapgit_not_found. + ENDIF. + + IF ls_smimloio-lo_class = wbmr_c_skwf_folder_class. + ev_is_folder = abap_true. + ls_io-objtype = skwfc_obtype_folder. + ELSE. + ls_io-objtype = skwfc_obtype_loio. + ENDIF. + ls_io-class = ls_smimloio-lo_class. + ls_io-objid = ls_smimloio-loio_id. + + CALL FUNCTION 'SKWF_NMSPC_IO_ADDRESS_GET' + EXPORTING + io = ls_io + IMPORTING + url = lv_url. + + ev_url = lv_url. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_loio TYPE sdok_docid. + lv_loio = ms_item-obj_name. + + SELECT SINGLE chng_user FROM smimloio INTO rv_user + WHERE loio_id = lv_loio. "#EC CI_GENBUFF + IF sy-subrc <> 0 OR rv_user IS INITIAL. + SELECT SINGLE chng_user FROM smimphio INTO rv_user + WHERE loio_id = lv_loio. "#EC CI_GENBUFF + IF sy-subrc <> 0 OR rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: li_api TYPE REF TO if_mr_api, + lv_url TYPE string. + TRY. + get_url_for_io( IMPORTING ev_url = lv_url ). + CATCH zcx_abapgit_not_found. + " Deleted already (maybe by "folder with children") but record deletion in transport + corr_insert( iv_package ). + RETURN. + ENDTRY. + + li_api = cl_mime_repository_api=>if_mr_api~get_api( ). + li_api->delete( + EXPORTING + i_url = lv_url + i_delete_children = abap_true + EXCEPTIONS + parameter_missing = 1 + error_occured = 2 + cancelled = 3 + permission_failure = 4 + not_found = 5 + OTHERS = 6 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_url TYPE string, + lv_folder TYPE abap_bool, + lv_content TYPE xstring, + lv_filename TYPE skwf_filnm, + lv_io TYPE sdok_docid, + lv_class TYPE smimloio-lo_class, + ls_skwf_io TYPE skwf_io, + li_api TYPE REF TO if_mr_api. + li_api = cl_mime_repository_api=>if_mr_api~get_api( ). + lv_io = ms_item-obj_name. + + io_xml->read( EXPORTING iv_name = 'URL' + CHANGING cg_data = lv_url ). + io_xml->read( EXPORTING iv_name = 'FOLDER' + CHANGING cg_data = lv_folder ). + io_xml->read( EXPORTING iv_name = 'CLASS' + CHANGING cg_data = lv_class ). + + ls_skwf_io-objid = lv_io. + + IF lv_folder = abap_true. + li_api->create_folder( + EXPORTING + i_url = lv_url + i_language = mv_language + i_dev_package = iv_package + i_folder_loio = ls_skwf_io + EXCEPTIONS + parameter_missing = 1 + error_occured = 2 + cancelled = 3 + permission_failure = 4 + folder_exists = 5 + OTHERS = 6 ). + IF sy-subrc <> 5 AND sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ELSE. + lv_filename = get_filename( lv_url ). + ls_skwf_io-class = lv_class. + IF ls_skwf_io-class IS INITIAL. + cl_wb_mime_repository=>determine_io_class( + EXPORTING + filename = lv_filename + IMPORTING + io_class = ls_skwf_io-class ). + CONCATENATE ls_skwf_io-class '_L' INTO ls_skwf_io-class. + ENDIF. + + lv_content = find_content( lv_url ). + + li_api->put( + EXPORTING + i_url = lv_url + i_content = lv_content + i_dev_package = iv_package + i_new_loio = ls_skwf_io + EXCEPTIONS + parameter_missing = 1 + error_occured = 2 + cancelled = 3 + permission_failure = 4 + data_inconsistency = 5 + new_loio_already_exists = 6 + is_folder = 7 + OTHERS = 8 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_loio TYPE sdok_docid. + lv_loio = ms_item-obj_name. + + SELECT SINGLE loio_id FROM smimloio INTO lv_loio + WHERE loio_id = lv_loio. "#EC CI_GENBUFF + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_url TYPE string, + lv_folder TYPE abap_bool, + lv_filename TYPE string, + lv_class TYPE smimloio-lo_class, + ls_file TYPE zif_abapgit_git_definitions=>ty_file, + lv_content TYPE xstring, + li_api TYPE REF TO if_mr_api, + lv_loio TYPE sdok_docid. + lv_loio = ms_item-obj_name. + + TRY. + get_url_for_io( + IMPORTING + ev_url = lv_url + ev_is_folder = lv_folder ). + CATCH zcx_abapgit_not_found. + RETURN. + ENDTRY. + + IF lv_folder = abap_false. + li_api = cl_mime_repository_api=>if_mr_api~get_api( ). + li_api->get( + EXPORTING + i_url = lv_url + IMPORTING + e_content = lv_content + EXCEPTIONS + parameter_missing = 1 + error_occured = 2 + not_found = 3 + permission_failure = 4 + OTHERS = 5 ). + IF sy-subrc <> 0 AND sy-subrc <> 2 AND sy-subrc <> 3. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + lv_filename = get_filename( lv_url ). + CLEAR ls_file. + ls_file-filename = build_filename( lv_filename ). + ls_file-path = '/'. + ls_file-data = lv_content. + mo_files->add( ls_file ). + + SELECT SINGLE lo_class FROM smimloio INTO lv_class + WHERE loio_id = lv_loio. "#EC CI_GENBUFF + ENDIF. + + io_xml->add( iv_name = 'URL' + ig_data = lv_url ). + io_xml->add( iv_name = 'FOLDER' + ig_data = lv_folder ). + io_xml->add( iv_name = 'CLASS' + ig_data = lv_class ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sktd IMPLEMENTATION. + METHOD clear_field. + + FIELD-SYMBOLS TYPE data. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_data TO . + ASSERT sy-subrc = 0. + + CLEAR . + + ENDMETHOD. + METHOD clear_fields. + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-NAME' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-TYPE' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-MASTER_SYSTEM' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-VERSION' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'REF_OBJECT-URI' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'REF_OBJECT-DESCRIPTION' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_AT' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_BY' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_AT' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_BY' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-MASTER_LANGUAGE' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-RESPONSIBLE' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-PACKAGE_REF' + CHANGING + cs_data = cs_data ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-LINKS' + CHANGING + cs_data = cs_data ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_object_key = ms_item-obj_name. + + TRY. + CREATE DATA mr_data TYPE ('CL_KTD_OBJECT_DATA=>TY_KTD_DATA'). + CREATE OBJECT mi_persistence TYPE ('CL_KTD_OBJECT_PERSIST'). + + CATCH cx_sy_create_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD get_wb_object_operator. + + DATA: + ls_object_type TYPE wbobjtype, + lx_error TYPE REF TO cx_root. + + IF mi_wb_object_operator IS BOUND. + ri_wb_object_operator = mi_wb_object_operator. + ENDIF. + + ls_object_type-objtype_tr = 'SKTD'. + ls_object_type-subtype_wb = 'TYP'. + + TRY. + CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') + EXPORTING + object_type = ls_object_type + object_key = mv_object_key + RECEIVING + result = mi_wb_object_operator. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ri_wb_object_operator = mi_wb_object_operator. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: + li_wb_object_operator TYPE REF TO object, + li_object_data_model TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root. + + TRY. + li_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = li_object_data_model. + + rv_user = li_object_data_model->get_changed_by( ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + lx_error TYPE REF TO cx_root, + li_wb_object_operator TYPE REF TO object. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') + EXPORTING + transport_request = iv_transport. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA li_wb_object_operator TYPE REF TO object. + DATA li_object_data_model TYPE REF TO if_wb_object_data_model. + + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE syuname. + FIELD-SYMBOLS TYPE p. + + ASSIGN mr_data->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'SKTD' + CHANGING + cg_data = ). + + " update( ) requires created_at and created_by to be set + ASSIGN COMPONENT 'METADATA' OF STRUCTURE TO . + IF sy-subrc = 0. + ASSIGN COMPONENT 'CREATED_AT' OF STRUCTURE TO . + IF sy-subrc = 0 AND IS INITIAL. + GET TIME STAMP FIELD . + ENDIF. + ASSIGN COMPONENT 'CREATED_BY' OF STRUCTURE TO . + IF sy-subrc = 0 AND IS INITIAL. + = sy-uname. + ENDIF. + ENDIF. + + li_wb_object_operator = get_wb_object_operator( ). + + CREATE OBJECT li_object_data_model TYPE ('CL_KTD_OBJECT_DATA'). + li_object_data_model->set_data( ). + + tadir_insert( iv_package ). + + IF zif_abapgit_object~exists( ) = abap_true. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = li_object_data_model + transport_request = iv_transport. + + ELSE. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = li_object_data_model + data_selection = 'P' " if_wb_object_data_selection_co=>c_properties + package = iv_package + transport_request = iv_transport. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = li_object_data_model + data_selection = 'D' " if_wb_object_data_selection_co=>c_data_content + transport_request = iv_transport. + ENDIF. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~ACTIVATE'). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + mi_persistence->get( + p_object_key = mv_object_key + p_version = 'A' + p_existence_check_only = abap_true ). + rv_bool = abap_true. + + CATCH cx_swb_exception. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( + iv_lock_object = 'WBS_ENQUEUE_STRU' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + li_wb_object_operator TYPE REF TO object, + li_object_data_model TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS TYPE any. + + ASSIGN mr_data->* TO . + ASSERT sy-subrc = 0. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + version = 'A' + IMPORTING + data = + eo_object_data = li_object_data_model. + + clear_fields( CHANGING cs_data = ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + io_xml->add( + iv_name = 'SKTD' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_SICF IMPLEMENTATION. + METHOD change_sicf. + + DATA: lt_icfhndlist TYPE icfhndlist, + lt_existing TYPE TABLE OF icfhandler, + ls_icfserdesc TYPE icfserdesc. + + FIELD-SYMBOLS: LIKE LINE OF lt_existing. + lt_icfhndlist = to_icfhndlist( it_icfhandler ). + + " Do not add handlers if they already exist, it will make the below + " call to SAP standard code raise an exception + SELECT * FROM icfhandler INTO TABLE lt_existing + WHERE icf_name = is_icfservice-icf_name + ORDER BY PRIMARY KEY. + LOOP AT lt_existing ASSIGNING . + DELETE TABLE lt_icfhndlist FROM -icfhandler. + ENDLOOP. + + MOVE-CORRESPONDING is_icfservice TO ls_icfserdesc. + + cl_icf_tree=>if_icf_tree~change_node( + EXPORTING + icf_name = is_icfservice-orig_name + icfaltnme = get_icfaltname( is_icfservice ) + icfparguid = iv_parent + icfdocu = is_icfdocu + doculang = mv_language + icfhandlst = lt_icfhndlist + package = iv_package + application = space + icfserdesc = ls_icfserdesc + icfactive = abap_true + EXCEPTIONS + empty_icf_name = 1 + no_new_virtual_host = 2 + special_service_error = 3 + parent_not_existing = 4 + enqueue_error = 5 + node_already_existing = 6 + empty_docu = 7 + doculang_not_installed = 8 + security_info_error = 9 + user_password_error = 10 + password_encryption_error = 11 + invalid_url = 12 + invalid_otr_concept = 13 + formflg401_error = 14 + handler_error = 15 + transport_error = 16 + tadir_error = 17 + package_not_found = 18 + wrong_application = 19 + not_allow_application = 20 + no_application = 21 + invalid_icfparguid = 22 + alt_name_invalid = 23 + alternate_name_exist = 24 + wrong_icf_name = 25 + no_authority = 26 + OTHERS = 27 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD deserialize_otr. + + DATA: + lt_sots TYPE zcl_abapgit_sots_handler=>ty_sots_tt, + lt_sots_use TYPE zcl_abapgit_sots_handler=>ty_sots_use_tt. + + FIELD-SYMBOLS: + LIKE LINE OF lt_sots_use. + + io_xml->read( EXPORTING iv_name = 'SOTS' + CHANGING cg_data = lt_sots ). + io_xml->read( EXPORTING iv_name = 'SOTS_USE' + CHANGING cg_data = lt_sots_use ). + + LOOP AT lt_sots_use ASSIGNING . + -obj_name = ms_item-obj_name. + ENDLOOP. + + zcl_abapgit_sots_handler=>create_sots_from_data( + iv_package = iv_package + it_sots = lt_sots + it_sots_use = lt_sots_use ). + + ENDMETHOD. + METHOD find_parent. + + cl_icf_tree=>if_icf_tree~service_from_url( + EXPORTING + url = iv_url + hostnumber = 0 + IMPORTING + icfnodguid = rv_parent + EXCEPTIONS + wrong_application = 1 + no_application = 2 + not_allow_application = 3 + wrong_url = 4 + no_authority = 5 + OTHERS = 6 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD get_hash_from_object. + + DATA: + lv_icfnodguid TYPE icfservice-icfnodguid, + lv_url TYPE icfurlbuf, + lv_ext_url TYPE string. + + SELECT SINGLE icfnodguid FROM icfservice INTO lv_icfnodguid + WHERE icf_name = iv_obj_name(15) + AND icfparguid = iv_obj_name+15. + + IF sy-subrc = 0. + CALL FUNCTION 'HTTP_GET_URL_FROM_NODGUID' + EXPORTING + nodguid = lv_icfnodguid + IMPORTING + url = lv_url + extended_url = lv_ext_url + EXCEPTIONS + icf_inconst = 1 + OTHERS = 2. + IF sy-subrc = 0. + " It's possible that the URL contains the system id, for example for WD applications with names + " longer than 15 characters. In that case, use the extended URL to generate the hash (#5064) + IF lv_ext_url <> lv_url. + rv_hash = zcl_abapgit_hash=>sha1_raw( zcl_abapgit_convert=>string_to_xstring_utf8( |{ lv_ext_url }| ) ). + ELSE. + rv_hash = zcl_abapgit_hash=>sha1_raw( zcl_abapgit_convert=>string_to_xstring_utf8( |{ lv_url }| ) ). + ENDIF. + ENDIF. + ELSE. + rv_hash = to_lower( iv_obj_name+15 ). + ENDIF. + + ENDMETHOD. + METHOD get_icfaltname. + + rv_icfaltnme = is_icfservice-icfaltnme. + " If the original name is different (lower vs upper case), it needs to be deserialized + IF is_icfservice-icfaltnme <> is_icfservice-icfaltnme_orig. + rv_icfaltnme = is_icfservice-icfaltnme_orig. + ENDIF. + + ENDMETHOD. + METHOD insert_sicf. + + DATA: lt_icfhndlist TYPE icfhndlist, + ls_icfserdesc TYPE icfserdesc, + ls_icfdocu TYPE icfdocu, + lv_icfnodguid TYPE icfnodguid, + lv_parent TYPE icfparguid. + lt_icfhndlist = to_icfhndlist( it_icfhandler ). + lv_parent = find_parent( iv_url ). + + " Nice, it seems that the structure should be mistreated + ls_icfdocu = is_icfdocu-icf_docu. + + MOVE-CORRESPONDING is_icfservice TO ls_icfserdesc. + + cl_icf_tree=>if_icf_tree~insert_node( + EXPORTING + icf_name = is_icfservice-orig_name + icfparguid = lv_parent + icfdocu = ls_icfdocu + doculang = mv_language + icfhandlst = lt_icfhndlist + package = iv_package + application = space + icfserdesc = ls_icfserdesc + icfactive = abap_true + icfaltnme = get_icfaltname( is_icfservice ) + IMPORTING + icfnodguid = lv_icfnodguid + EXCEPTIONS + empty_icf_name = 1 + no_new_virtual_host = 2 + special_service_error = 3 + parent_not_existing = 4 + enqueue_error = 5 + node_already_existing = 6 + empty_docu = 7 + doculang_not_installed = 8 + security_info_error = 9 + user_password_error = 10 + password_encryption_error = 11 + invalid_url = 12 + invalid_otr_concept = 13 + formflg401_error = 14 + handler_error = 15 + transport_error = 16 + tadir_error = 17 + package_not_found = 18 + wrong_application = 19 + not_allow_application = 20 + no_application = 21 + invalid_icfparguid = 22 + alt_name_invalid = 23 + alternate_name_exist = 24 + wrong_icf_name = 25 + no_authority = 26 + OTHERS = 27 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " Update item with name assigned by system + SELECT SINGLE icfparguid INTO ms_item-obj_name+15 FROM icfservice + WHERE icfnodguid = lv_icfnodguid. + + ENDMETHOD. + METHOD read. + + DATA: lt_serv_info TYPE icfservtbl, + ls_serv_info LIKE LINE OF lt_serv_info, + ls_key TYPE ty_sicf_key. + + FIELD-SYMBOLS: LIKE LINE OF et_icfhandler. + CLEAR es_icfservice. + CLEAR es_icfdocu. + CLEAR et_icfhandler. + CLEAR ev_url. + + ls_key-icf_name = ms_item-obj_name(15). + ls_key-icfparguid = ms_item-obj_name+15. + + cl_icf_tree=>if_icf_tree~get_info_from_serv( + EXPORTING + icf_name = ls_key-icf_name + icfparguid = ls_key-icfparguid + icf_langu = mv_language + IMPORTING + serv_info = lt_serv_info + icfdocu = es_icfdocu + url = ev_url + EXCEPTIONS + wrong_name = 1 + wrong_parguid = 2 + incorrect_service = 3 + no_authority = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ASSERT lines( lt_serv_info ) = 1. + READ TABLE lt_serv_info INDEX 1 INTO ls_serv_info. + ASSERT sy-subrc = 0. + + MOVE-CORRESPONDING ls_serv_info-service TO es_icfservice. + IF iv_clear = abap_true. + CLEAR es_icfservice-icf_cuser. + CLEAR es_icfservice-icf_cdate. + CLEAR es_icfservice-icf_muser. + CLEAR es_icfservice-icf_mdate. + ENDIF. + + CLEAR es_icfdocu-icfparguid. + + APPEND LINES OF ls_serv_info-handlertbl TO et_icfhandler. + LOOP AT et_icfhandler ASSIGNING . + CLEAR -icfparguid. + ENDLOOP. + + ENDMETHOD. + METHOD serialize_otr. + + DATA: + lt_sots TYPE zcl_abapgit_sots_handler=>ty_sots_tt, + lt_sots_use TYPE zcl_abapgit_sots_handler=>ty_sots_use_tt. + + FIELD-SYMBOLS: + LIKE LINE OF lt_sots_use. + + zcl_abapgit_sots_handler=>read_sots( + EXPORTING + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + IMPORTING + et_sots = lt_sots + et_sots_use = lt_sots_use ). + + LOOP AT lt_sots_use ASSIGNING . + CLEAR -obj_name. + ENDLOOP. + + io_xml->add( iv_name = 'SOTS' + ig_data = lt_sots ). + io_xml->add( iv_name = 'SOTS_USE' + ig_data = lt_sots_use ). + + ENDMETHOD. + METHOD to_icfhndlist. + + FIELD-SYMBOLS: LIKE LINE OF it_list. + + " Convert to sorted table + LOOP AT it_list ASSIGNING . + INSERT -icfhandler INTO TABLE rt_list. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_icfservice TYPE icfservice. + + read( EXPORTING iv_clear = abap_false + IMPORTING es_icfservice = ls_icfservice ). + + rv_user = ls_icfservice-icf_muser. + + IF rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA ls_icfservice TYPE icfservice. + + read( IMPORTING es_icfservice = ls_icfservice ). + + IF ls_icfservice IS INITIAL. + " It seems that the ICF service doesn't exist anymore. + " But that's ok, because some objects like SAPC manage + " the lifecycle of its ICF service by itself and already + " deleted the service. + RETURN. + ENDIF. + + IF ls_icfservice-icfparguid CO '0'. + " not supported by the SAP standard API + zcx_abapgit_exception=>raise( 'SICF - cannot delete root node, delete node manually' ). + ENDIF. + + " OTR long texts + zcl_abapgit_sots_handler=>delete_sots( + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name ). + + " Delete Application Customizing Data the hard way, as it isn't done by the API. + " If we wouldn't we would get errors from the API if entries exist. + " Transaction SICF does the same. + DELETE FROM icfapplcust + WHERE icf_name = ls_icfservice-icf_name + AND icfparguid = ls_icfservice-icfparguid. + + cl_icf_tree=>if_icf_tree~delete_node( + EXPORTING + icfparguid = ls_icfservice-icfparguid + CHANGING + icf_name = ls_icfservice-icf_name + EXCEPTIONS + no_virtual_host_delete = 1 + special_service_error = 2 + enqueue_error = 3 + node_not_existing = 4 + node_has_childs = 5 + node_is_aliased = 6 + node_not_in_original_system = 7 + transport_error = 8 + tadir_error = 9 + db_error = 10 + no_authority = 11 + OTHERS = 12 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_icfservice TYPE icfservice, + ls_read TYPE icfservice, + ls_icfdocu TYPE icfdocu, + lv_url TYPE string, + lv_exists TYPE abap_bool, + lt_icfhandler TYPE TABLE OF icfhandler. + + io_xml->read( EXPORTING iv_name = 'URL' + CHANGING cg_data = lv_url ). + io_xml->read( EXPORTING iv_name = 'ICFSERVICE' + CHANGING cg_data = ls_icfservice ). + io_xml->read( EXPORTING iv_name = 'ICFDOCU' + CHANGING cg_data = ls_icfdocu ). + io_xml->read( EXPORTING iv_name = 'ICFHANDLER_TABLE' + CHANGING cg_data = lt_icfhandler ). + + lv_exists = zif_abapgit_object~exists( ). + IF lv_exists = abap_false. + insert_sicf( is_icfservice = ls_icfservice + is_icfdocu = ls_icfdocu + it_icfhandler = lt_icfhandler + iv_package = iv_package + iv_url = lv_url ). + ELSE. + read( IMPORTING es_icfservice = ls_read ). + change_sicf( is_icfservice = ls_icfservice + is_icfdocu = ls_icfdocu + it_icfhandler = lt_icfhandler + iv_package = iv_package + iv_parent = ls_read-icfparguid ). + ENDIF. + + " OTR long texts + deserialize_otr( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA ls_key TYPE ty_sicf_key. + + SELECT SINGLE icfaltnme FROM icfservice INTO ls_key-icf_name + WHERE icf_name = ms_item-obj_name(15) + AND icfparguid = ms_item-obj_name+15. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_argument TYPE seqg3-garg. + + lv_argument = ms_item-obj_name(15). + lv_argument+15(1) = '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESICFSER' + iv_argument = lv_argument ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_bcdata TYPE bdcdata, + lt_bcdata TYPE STANDARD TABLE OF bdcdata. + + ls_bcdata-program = 'RSICFTREE'. + ls_bcdata-dynpro = '1000'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + ls_bcdata-dynpro = space. + ls_bcdata-dynbegin = space. + ls_bcdata-fnam = 'ICF_SERV'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=ONLI'. + APPEND ls_bcdata TO lt_bcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SICF' + it_bdcdata = lt_bcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + + DATA: + lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, + lv_hash TYPE ty_hash, + lv_obj_name TYPE tadir-obj_name. + + FIELD-SYMBOLS LIKE LINE OF lt_tadir. + + lv_obj_name = to_upper( iv_item_part_of_filename(15) ) && '%'. + lv_hash = iv_item_part_of_filename+15(25). + + SELECT * FROM tadir INTO CORRESPONDING FIELDS OF TABLE lt_tadir + WHERE pgmid = 'R3TR' + AND object = 'SICF' + AND obj_name LIKE lv_obj_name + ORDER BY PRIMARY KEY ##TOO_MANY_ITAB_FIELDS. "#EC CI_GENBUFF + + LOOP AT lt_tadir ASSIGNING . + IF get_hash_from_object( -obj_name ) = lv_hash. + cs_item-obj_name = -obj_name. + RETURN. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + + cv_item_part_of_filename = |{ cv_item_part_of_filename(15) }{ get_hash_from_object( is_item-obj_name ) }|. + + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_icfservice TYPE icfservice, + ls_icfdocu TYPE icfdocu, + lv_url TYPE string, + lt_icfhandler TYPE TABLE OF icfhandler. + + read( IMPORTING es_icfservice = ls_icfservice + es_icfdocu = ls_icfdocu + et_icfhandler = lt_icfhandler + ev_url = lv_url ). + + IF ls_icfservice IS INITIAL. + RETURN. + ENDIF. + + CLEAR ls_icfservice-icf_mandt. + CLEAR ls_icfservice-icfnodguid. + CLEAR ls_icfservice-icfparguid. + CLEAR ls_icfservice-icfchildno. + CLEAR ls_icfservice-icfaliasno. + CLEAR ls_icfservice-icf_user. + CLEAR ls_icfservice-icf_cclnt. + CLEAR ls_icfservice-icf_mclnt. + " If the original name is different (lower vs upper case), it needs to be serialized + IF ls_icfservice-icfaltnme = ls_icfservice-icfaltnme_orig. + CLEAR ls_icfservice-icfaltnme_orig. + ENDIF. + CLEAR ls_icfservice-icfbitmap. + + io_xml->add( iv_name = 'URL' + ig_data = lv_url ). + io_xml->add( iv_name = 'ICFSERVICE' + ig_data = ls_icfservice ). + io_xml->add( iv_name = 'ICFDOCU' + ig_data = ls_icfdocu ). + io_xml->add( iv_name = 'ICFHANDLER_TABLE' + ig_data = lt_icfhandler ). + + " OTR long texts + serialize_otr( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_shma IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE chg_user + FROM shma_attributes + INTO rv_user + WHERE area_name = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + " We can't use FM SHMA_DELETE_AREA because it depends + " on the corresponding class, but in abapGit it has its own + " lifecycle. Therefore we have to reimplement most of the + " FMs logic + + CONSTANTS: lc_request_delete TYPE i VALUE 4. + + DATA: lv_request TYPE i, + lv_area_name TYPE shm_area_name, + lv_order TYPE e070-trkorr, + lv_task TYPE e070-trkorr, + lv_append TYPE abap_bool, + ls_tdevc TYPE tdevc, + lo_cts_if TYPE REF TO object. + + lv_area_name = ms_item-obj_name. + + TRY. + CALL FUNCTION 'ENQUEUE_E_SHM_AREA' + EXPORTING + mode_shma_attributes = 'E' + area_name = lv_area_name + x_area_name = ' ' + _scope = '2' + _wait = ' ' + _collect = ' ' + EXCEPTIONS + foreign_lock = 1 + system_failure = 2 + OTHERS = 3. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL METHOD ('\PROGRAM=SAPMSHM_MONITOR\CLASS=LCL_SHMM')=>('FREE_AREA_BY_NAME') + EXPORTING + area_name = lv_area_name + affect_server = cl_shm_area=>affect_all_servers. + + CREATE OBJECT lo_cts_if TYPE ('\FUNCTION-POOL=SHMA\CLASS=LCL_CTS_INTERFACE') + EXPORTING + area = lv_area_name. + + CALL METHOD lo_cts_if->('CHECK_AREA') + EXPORTING + request = lc_request_delete + IMPORTING + access_mode = lv_request + appendable = lv_append. + + IF lv_request <> lc_request_delete. + zcx_abapgit_exception=>raise( |Error deleting SHMA { ms_item-obj_name }| ). + ENDIF. + + CALL METHOD lo_cts_if->('INSERT_AREA') + EXPORTING + request = lc_request_delete + IMPORTING + order = lv_order + task = lv_task. + + DELETE FROM shma_attributes WHERE area_name = lv_area_name. + DELETE FROM shma_start WHERE area_name = lv_area_name. + + CALL FUNCTION 'TR_DEVCLASS_GET' + EXPORTING + iv_devclass = iv_package + IMPORTING + es_tdevc = ls_tdevc + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc = 0 AND ls_tdevc-korrflag IS INITIAL. + + " TADIR entries for local objects must be deleted 'by hand' + tadir_delete( ). + + ENDIF. + + CALL METHOD ('\PROGRAM=SAPLSHMA\CLASS=LCL_SHMA_HELPER')=>('DELETE_RUNTIME_SETTINGS') + EXPORTING + area_name = lv_area_name. + + CALL FUNCTION 'DEQUEUE_E_SHM_AREA' + EXPORTING + mode_shma_attributes = 'E' + area_name = lv_area_name + x_area_name = ' ' + _scope = '3' + _synchron = ' ' + _collect = ' '. + + CATCH cx_root. + zcx_abapgit_exception=>raise( |Error deleting SHMA { ms_item-obj_name }| ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_area_name TYPE shm_area_name, + ls_area_attributes TYPE shma_attributes. + + lv_area_name = ms_item-obj_name. + + io_xml->read( + EXPORTING + iv_name = 'AREA_ATTRIBUTES' + CHANGING + cg_data = ls_area_attributes ). + + tadir_insert( iv_package ). + + TRY. + CALL METHOD ('\PROGRAM=SAPLSHMA\CLASS=LCL_SHMA_HELPER')=>('INSERT_AREA') + EXPORTING + area_name = lv_area_name + attributes = ls_area_attributes + force_overwrite = abap_true + no_class_generation = abap_false + silent_mode = abap_true. + + CATCH cx_root. + zcx_abapgit_exception=>raise( |Error serializing SHMA { ms_item-obj_name }| ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_area_name TYPE shm_area_name. + + SELECT SINGLE area_name + FROM shma_attributes + INTO lv_area_name + WHERE area_name = ms_item-obj_name. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + + rs_metadata = get_metadata( ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_bcdata TYPE bdcdata, + lt_bcdata TYPE STANDARD TABLE OF bdcdata. + + ls_bcdata-program = 'SAPLSHMA'. + ls_bcdata-dynpro = '0100'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'SHMA_ATTRIBUTES-AREA_NAME'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=SHOW'. + APPEND ls_bcdata TO lt_bcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SHMA' + it_bdcdata = lt_bcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_area_name TYPE shm_area_name, + ls_area_attributes TYPE shma_attributes. + + lv_area_name = ms_item-obj_name. + + TRY. + CALL METHOD ('\PROGRAM=SAPLSHMA\CLASS=LCL_SHMA_HELPER')=>('READ_AREA_ATTRIBUTES_ALL') + EXPORTING + area_name = lv_area_name + IMPORTING + area_attributes = ls_area_attributes. + + CLEAR: ls_area_attributes-chg_user, + ls_area_attributes-chg_date, + ls_area_attributes-chg_time, + ls_area_attributes-cls_gen_user, + ls_area_attributes-cls_gen_date, + ls_area_attributes-cls_gen_time. + + io_xml->add( iv_name = 'AREA_ATTRIBUTES' + ig_data = ls_area_attributes ). + + CATCH cx_root. + zcx_abapgit_exception=>raise( |Error serializing SHMA { ms_item-obj_name }| ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_shlp IMPLEMENTATION. + METHOD adjust_exit. + + CONSTANTS lc_standard_exit TYPE dd30v-selmexit VALUE 'RS_DD_SELMEXIT'. + + IF cv_exit IS NOT INITIAL + AND zcl_abapgit_factory=>get_function_module( )->function_exists( cv_exit ) = abap_false. + " If exit function does not exist, replace it with standard SAP function + " which exists in 7.02 and higher + cv_exit = lc_standard_exit. + ENDIF. + + ENDMETHOD. + METHOD check_exit. + + DATA lv_exit TYPE dd30v-selmexit. + + rv_done = abap_true. + + IF iv_exit IS NOT INITIAL. + " Check if exit function is set correctly + SELECT SINGLE selmexit FROM dd30v INTO lv_exit WHERE shlpname = ms_item-obj_name. + IF sy-subrc = 0 AND lv_exit <> iv_exit. + rv_done = abap_false. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD handle_dependencies. + + " For search helps with dependency on exit function, we use two phases: + " 1) DDIC phase: + " - If function does not exit, replace it with a standard SAP function + " 2) LATE phase + " - If function was replaced, change it to the correct exit function + CASE iv_step. + WHEN zif_abapgit_object=>gc_step_id-ddic. + adjust_exit( CHANGING cv_exit = cv_exit ). + + WHEN zif_abapgit_object=>gc_step_id-late. + cv_done = check_exit( cv_exit ). + + WHEN zif_abapgit_object=>gc_step_id-lxe. + cv_done = abap_true. + + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE as4user FROM dd30l INTO rv_user + WHERE shlpname = ms_item-obj_name + AND as4local = 'A'. "#EC CI_GENBUFF + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + delete_ddic( 'H' ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_name TYPE ddobjname, + lv_done TYPE abap_bool, + ls_dd30v TYPE dd30v, + lt_dd31v TYPE TABLE OF dd31v, + lt_dd32p TYPE TABLE OF dd32p, + lt_dd33v TYPE TABLE OF dd33v. + + io_xml->read( EXPORTING iv_name = 'DD30V' + CHANGING cg_data = ls_dd30v ). + + handle_dependencies( + EXPORTING + iv_step = iv_step + CHANGING + cv_exit = ls_dd30v-selmexit + cv_done = lv_done ). + + IF lv_done = abap_true. + RETURN. + ENDIF. + + io_xml->read( EXPORTING iv_name = 'DD31V_TABLE' + CHANGING cg_data = lt_dd31v ). + io_xml->read( EXPORTING iv_name = 'DD32P_TABLE' + CHANGING cg_data = lt_dd32p ). + io_xml->read( EXPORTING iv_name = 'DD33V_TABLE' + CHANGING cg_data = lt_dd33v ). + + corr_insert( iv_package = iv_package + ig_object_class = 'DICT' ). + + lv_name = ms_item-obj_name. + + CALL FUNCTION 'DDIF_SHLP_PUT' + EXPORTING + name = lv_name + dd30v_wa = ls_dd30v + TABLES + dd31v_tab = lt_dd31v + dd32p_tab = lt_dd32p + dd33v_tab = lt_dd33v + EXCEPTIONS + shlp_not_found = 1 + name_inconsistent = 2 + shlp_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_shlpname TYPE dd30l-shlpname. + + SELECT SINGLE shlpname FROM dd30l INTO lv_shlpname + WHERE shlpname = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECT=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_name TYPE ddobjname, + lv_state TYPE ddgotstate, + ls_dd30v TYPE dd30v, + lt_dd31v TYPE TABLE OF dd31v, + lt_dd32p TYPE TABLE OF dd32p, + lt_dd33v TYPE TABLE OF dd33v. + + FIELD-SYMBOLS: LIKE LINE OF lt_dd32p. + FIELD-SYMBOLS TYPE any. + + lv_name = ms_item-obj_name. + + CALL FUNCTION 'DDIF_SHLP_GET' + EXPORTING + name = lv_name + state = 'A' + langu = mv_language + IMPORTING + gotstate = lv_state + dd30v_wa = ls_dd30v + TABLES + dd31v_tab = lt_dd31v + dd32p_tab = lt_dd32p + dd33v_tab = lt_dd33v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF ls_dd30v IS INITIAL OR lv_state <> 'A'. + RETURN. + ENDIF. + + CLEAR: ls_dd30v-as4user, + ls_dd30v-as4date, + ls_dd30v-as4time. + + ASSIGN COMPONENT 'ACTFLAG' OF STRUCTURE ls_dd30v TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + LOOP AT lt_dd32p ASSIGNING . +* clear information inherited from domain + CLEAR: -domname, + -headlen, + -scrlen1, + -scrlen2, + -datatype, + -leng, + -outputlen, + -decimals, + -lowercase, + -signflag, + -convexit. + ENDLOOP. + + io_xml->add( iv_name = 'DD30V' + ig_data = ls_dd30v ). + io_xml->add( ig_data = lt_dd31v + iv_name = 'DD31V_TABLE' ). + io_xml->add( ig_data = lt_dd32p + iv_name = 'DD32P_TABLE' ). + io_xml->add( ig_data = lt_dd33v + iv_name = 'DD33V_TABLE' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_shi8 IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_assignment_id = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " not stored by SAP + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_deleted TYPE abap_bool, + ls_message TYPE hier_mess. + + CALL FUNCTION 'STREE_SFW_ASSIGNMENT_DELETE' + EXPORTING + assignment_id = mv_assignment_id + IMPORTING + id_deleted = lv_deleted + message = ls_message. + + IF lv_deleted = abap_false. + zcx_abapgit_exception=>raise( |{ ls_message-msgtxt }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_assignment_data TYPE ttree_sfw_nodes, + ls_node_data TYPE hier_iface, + lv_saved TYPE abap_bool, + ls_message TYPE hier_mess. + + io_xml->read( + EXPORTING + iv_name = 'SHI8' + CHANGING + cg_data = ls_assignment_data ). + + ls_node_data-tree_id = ls_assignment_data-tree_id. + ls_node_data-node_id = ls_assignment_data-node_id. + + tadir_insert( iv_package ). + + CALL FUNCTION 'STREE_SFW_ASSIGNMENT_SAVE' + EXPORTING + assignment_id = ls_assignment_data-sfw_ass_id + switch_id = ls_assignment_data-switch_id + reaction = ls_assignment_data-reaction + node_data = ls_node_data + IMPORTING + data_saved = lv_saved + message = ls_message. + + IF lv_saved = abap_false. + zcx_abapgit_exception=>raise( |{ ls_message-msgtxt }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL FUNCTION 'STREE_SFW_ASSIGNMENT_ID_EXISTS' + EXPORTING + assignment_id = mv_assignment_id + IMPORTING + exists = rv_bool. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lt_assignments TYPE STANDARD TABLE OF hier_sfw_assignment_id, + ls_assignment LIKE LINE OF lt_assignments, + lt_assignment_data TYPE STANDARD TABLE OF ttree_sfw_nodes, + ls_assignment_data LIKE LINE OF lt_assignment_data. + + ls_assignment-sfw_ass_id = mv_assignment_id. + INSERT ls_assignment INTO TABLE lt_assignments. + + CALL FUNCTION 'STREE_SFW_ASSIGNMENT_READ' + TABLES + it_assignments = lt_assignments + et_assignment_data = lt_assignment_data. + + READ TABLE lt_assignment_data INTO ls_assignment_data + INDEX 1. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error serializing { ms_item-obj_type } { ms_item-obj_name }| ). + ENDIF. + + io_xml->add( iv_name = 'SHI8' + ig_data = ls_assignment_data ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_shi5 IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_extension = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " not stored by SAP + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + ls_msg TYPE hier_mess, + lv_found_users TYPE hier_yesno, + ls_check_extensions TYPE treenamesp, + lt_check_extensions TYPE TABLE OF treenamesp, + lv_obj_name TYPE ko200-obj_name. + + " STREE_EXTENSION_DELETE shows a popup so do the same here + + ls_check_extensions-extension = mv_extension. + INSERT ls_check_extensions INTO TABLE lt_check_extensions. + + CALL FUNCTION 'STREE_CHECK_EXTENSION' + IMPORTING + message = ls_msg + TABLES + check_extension = lt_check_extensions. + + READ TABLE lt_check_extensions INTO ls_check_extensions INDEX 1. + IF ls_check_extensions-original = abap_false. + zcx_abapgit_exception=>raise( 'Delete enhancement ID in your source system' ). + ENDIF. + + lv_obj_name = mv_extension. + + CALL FUNCTION 'STREE_TRANSPORT_CHECK' + EXPORTING + object = 'SHI5' + obj_name = lv_obj_name + IMPORTING + message = ls_msg. + + IF ls_msg-msgty = 'E'. + MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno + WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'STREE_EXTENSION_USAGE' + EXPORTING + extension = mv_extension + no_display = abap_true + IMPORTING + message = ls_msg + extension_is_used = lv_found_users. + + IF ls_msg-msgty = 'E'. + MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno + WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF lv_found_users = abap_true. + zcx_abapgit_exception=>raise( 'Enhancement ID is still used' ). + ENDIF. + + CALL FUNCTION 'STREE_TRANSPORT_INSERT' + EXPORTING + object = 'SHI5' + obj_name = lv_obj_name + IMPORTING + message = ls_msg. + + IF ls_msg-msgty = 'E'. + MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno + WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + DELETE FROM ttree_ext WHERE extension = mv_extension. + DELETE FROM ttree_extt WHERE extension = mv_extension. + + IF ls_check_extensions-transport = abap_false. + " no transportable Devclass -> delete TADIR + tadir_delete( ). + ENDIF. + + " reset some internal tables + CALL FUNCTION 'STREE_RESET_FUGR_SHI5_TABLES'. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + " We cannot use STREE_EXTENSION_NAME_CREATE + " the create logic is directly tied to the UI + " + " Do it like here LSHI20F01 -> SAVE_DATA + + DATA: ls_extension TYPE ty_extension. + + io_xml->read( + EXPORTING + iv_name = 'SHI5' + CHANGING + cg_data = ls_extension ). + + INSERT ttree_ext FROM ls_extension-header. + + DELETE FROM ttrees WHERE extension = ls_extension-header-extension. + MODIFY ttrees FROM TABLE ls_extension-sequences. + + DELETE FROM ttree_extt WHERE extension = ls_extension-header-extension. + MODIFY ttree_extt FROM TABLE ls_extension-texts. + + corr_insert( iv_package ). + + tadir_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_extension_header TYPE ttree_ext. + + CALL FUNCTION 'STREE_EXTENSION_EXISTS' + EXPORTING + extension = mv_extension + IMPORTING + extension_header = ls_extension_header. + + rv_bool = boolc( ls_extension_header IS NOT INITIAL ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + DATA: lt_extension TYPE STANDARD TABLE OF ttree_ext. + FIELD-SYMBOLS: LIKE LINE OF lt_extension. + + INSERT INITIAL LINE INTO TABLE lt_extension ASSIGNING . + -extension = mv_extension. + + CALL FUNCTION 'STREE_EXTENSION_NAME_F4' + EXPORTING + originals_only = abap_true + TABLES + show_only_extensions = lt_extension. + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_extension TYPE ty_extension. + + CALL FUNCTION 'STREE_EXTENSION_EXISTS' + EXPORTING + extension = mv_extension + IMPORTING + extension_header = ls_extension-header. + + SELECT * FROM ttree_extt + INTO TABLE ls_extension-texts + WHERE extension = mv_extension ORDER BY PRIMARY KEY. + + SELECT * FROM ttrees + INTO TABLE ls_extension-sequences + WHERE extension = mv_extension ORDER BY PRIMARY KEY. + + io_xml->add( iv_name = 'SHI5' + ig_data = ls_extension ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_SHI3 IMPLEMENTATION. + METHOD clear_fields. + + FIELD-SYMBOLS LIKE LINE OF ct_nodes. + + CLEAR: cs_head-luser, cs_head-ldate, cs_head-ltime. + CLEAR: cs_head-fuser, cs_head-fdate, cs_head-ftime. + CLEAR: cs_head-frelease, cs_head-lrelease. + CLEAR: cs_head-responsibl. + + LOOP AT ct_nodes ASSIGNING . + CLEAR: -luser, -ldate, -ltime. + CLEAR: -fuser, -fdate, -ftime. + CLEAR: -frelease, -lrelease. + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_tree_id = ms_item-obj_name. + + ENDMETHOD. + METHOD delete_tree_structure. + CALL FUNCTION 'STREE_EXTERNAL_DELETE' + EXPORTING + structure_id = iv_structure_id + no_confirmation_popup = abap_true. + ENDMETHOD. + METHOD has_authorization. + + AUTHORITY-CHECK OBJECT 'S_DEVELOP' + ID 'DEVCLASS' FIELD iv_devclass + ID 'OBJTYPE' FIELD 'MENU' + ID 'OBJNAME' FIELD iv_structure_id + ID 'P_GROUP' DUMMY + ID 'ACTVT' FIELD iv_activity. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( iv_msgid = 'S#' + iv_msgno = '203' ). + ENDIF. + ENDMETHOD. + METHOD insert_transport. + + DATA: + ls_msg TYPE hier_mess, + ls_object TYPE e071, + lt_objects TYPE TABLE OF e071, + lt_keys TYPE TABLE OF e071k, + ls_ko200 TYPE ko200, + lt_ko200 TYPE TABLE OF ko200. + + " This function shows a popup so get objects and keys and insert + " them into transport below + CALL FUNCTION 'STREE_INSERT_ALL_IN_TRANSPORT' + EXPORTING + structure_id = mv_tree_id + iv_return_objects_and_keys = abap_true + IMPORTING + message = ls_msg + TABLES + et_objects = lt_objects + et_keys = lt_keys. + IF ls_msg-msgty = 'E'. + MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno + WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + LOOP AT lt_objects INTO ls_object. + MOVE-CORRESPONDING ls_object TO ls_ko200. + INSERT ls_ko200 INTO TABLE lt_ko200. + ENDLOOP. + + CALL FUNCTION 'TR_RECORD_OBJ_CHANGE_TO_REQ' + EXPORTING + iv_request = iv_transport + it_objects = lt_ko200 + it_keys = lt_keys + EXCEPTIONS + cancel = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD is_used. + + DATA: lt_used_in_structures TYPE STANDARD TABLE OF ttree WITH DEFAULT KEY. + + CALL FUNCTION 'STREE_GET_STRUCTURE_USAGE' + EXPORTING + structure_id = iv_structure_id + TABLES + used_in_structures = lt_used_in_structures. + + IF lt_used_in_structures IS NOT INITIAL. + zcx_abapgit_exception=>raise( |IMG structure ID { iv_structure_id } is still used| ). + ENDIF. + + ENDMETHOD. + METHOD jump_sbach04. + DATA: ls_message TYPE hier_mess, + lv_structure_id TYPE hier_treeg. + + lv_structure_id = ms_item-obj_name. + + CALL FUNCTION 'STREE_EXTERNAL_EDIT' + EXPORTING + structure_id = lv_structure_id + language = mv_language + edit_structure = abap_false + no_commit_work = abap_false + activity = 'D' + IMPORTING + message = ls_message. + IF ls_message IS NOT INITIAL. + zcx_abapgit_exception=>raise_t100( + iv_msgid = ls_message-msgid + iv_msgno = ls_message-msgno + iv_msgv1 = ls_message-msgv1 + iv_msgv2 = ls_message-msgv2 + iv_msgv3 = ls_message-msgv3 + iv_msgv4 = ls_message-msgv4 ). + ENDIF. + ENDMETHOD. + METHOD jump_se43. + + DATA: lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPLBMEN'. + -dynpro = '0200'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=SHOW'. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BMENUNAME-ID'. + -fval = ms_item-obj_name. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SE43' + it_bdcdata = lt_bdcdata ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_head TYPE ttree. + + CALL FUNCTION 'STREE_STRUCTURE_READ' + EXPORTING + structure_id = mv_tree_id + IMPORTING + structure_header = ls_head. + + rv_user = ls_head-luser. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + CONSTANTS lc_activity_delete_06 TYPE activ_auth VALUE '06'. + + TRY. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + CATCH zcx_abapgit_exception. + RETURN. + ENDTRY. + + has_authorization( iv_structure_id = mv_tree_id + iv_devclass = ms_item-devclass + iv_activity = lc_activity_delete_06 ). + + is_used( mv_tree_id ). + + delete_tree_structure( mv_tree_id ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_msg TYPE hier_mess, + ls_head TYPE ttree, + ls_ttree TYPE ttree, + lt_titles TYPE TABLE OF ttreet, + lt_nodes TYPE TABLE OF hier_iface, + lt_texts TYPE TABLE OF hier_texts, + lt_refs TYPE TABLE OF hier_ref. + + io_xml->read( EXPORTING iv_name = 'TREE_HEAD' + CHANGING cg_data = ls_head ). + io_xml->read( EXPORTING iv_name = 'TREE_TITLES' + CHANGING cg_data = lt_titles ). + io_xml->read( EXPORTING iv_name = 'TREE_NODES' + CHANGING cg_data = lt_nodes ). + io_xml->read( EXPORTING iv_name = 'TREE_REFS' + CHANGING cg_data = lt_refs ). + io_xml->read( EXPORTING iv_name = 'TREE_TEXTS' + CHANGING cg_data = lt_texts ). + + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'SPRAS' + iv_keep_master_lang = abap_true + CHANGING + ct_tab = lt_titles ). + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'SPRAS' + iv_keep_master_lang = abap_true + CHANGING + ct_tab = lt_texts ). + + IF zif_abapgit_object~exists( ) = abap_true. + delete_tree_structure( mv_tree_id ). + ENDIF. + + CALL FUNCTION 'STREE_HIERARCHY_SAVE' + EXPORTING + structure_id = mv_tree_id + structure_type = ls_head-type + structure_description = space + structure_masterlanguage = mv_language + structure_responsible = sy-uname + structure_buffermode = ls_head-buffermode + development_class = iv_package + IMPORTING + message = ls_msg + TABLES + list_of_nodes = lt_nodes + list_of_references = lt_refs + list_of_texts = lt_texts + structure_descriptions = lt_titles + EXCEPTIONS + no_nodes_given = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ELSEIF ls_msg-msgty = 'E'. + MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno + WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " Set buffer mode for menus (see function BMENU_CREATE_TREE) + SELECT SINGLE * FROM ttree INTO ls_ttree + WHERE type = 'BMENU' AND id = mv_tree_id. + IF sy-subrc = 0. + ls_ttree-buffermode = ls_head-buffermode. + ls_ttree-buffervar = ls_head-buffervar. + MODIFY ttree FROM ls_ttree. + ENDIF. + + IF zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ) = abap_true. + " Add necessary SHI6, SHI7, and TABU entries to transport (SAP Note 455542) + insert_transport( iv_transport ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_msg TYPE hier_mess, + ls_header TYPE ttree, + ls_tadir TYPE tadir. + + " Ignore buffer and get state from DB + CALL FUNCTION 'STREE_STRUCTURE_EXIST' + EXPORTING + structure_id = mv_tree_id + read_from_database = abap_true + do_not_read_devclass = abap_false + IMPORTING + message = ls_msg + structure_header = ls_header + structure_tadir = ls_tadir. + + rv_bool = boolc( ls_header-id IS NOT INITIAL ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_head TYPE ttree. + + CALL FUNCTION 'STREE_STRUCTURE_READ' + EXPORTING + structure_id = mv_tree_id + IMPORTING + structure_header = ls_head. + + CASE ls_head-type. + WHEN 'BMENU'. + jump_se43( ). + rv_exit = abap_true. + WHEN 'GHIER'. + jump_sbach04( ). + rv_exit = abap_true. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_msg TYPE hier_mess, + ls_head TYPE ttree, + lt_titles TYPE TABLE OF ttreet, + lt_nodes TYPE TABLE OF hier_iface, + lt_texts TYPE TABLE OF hier_texts, + lt_refs TYPE TABLE OF hier_ref, + lv_all_languages TYPE abap_bool. + CALL FUNCTION 'STREE_STRUCTURE_READ' + EXPORTING + structure_id = mv_tree_id + IMPORTING + message = ls_msg + structure_header = ls_head + TABLES + description = lt_titles. + + IF mo_i18n_params->ms_params-main_language_only = abap_true OR mo_i18n_params->is_lxe_applicable( ) = abap_true. + lv_all_languages = abap_false. + DELETE lt_titles WHERE spras <> mv_language. + ELSE. + lv_all_languages = abap_true. + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'SPRAS' + iv_keep_master_lang = abap_true + CHANGING + ct_tab = lt_titles ). + ENDIF. + + CALL FUNCTION 'STREE_HIERARCHY_READ' + EXPORTING + structure_id = mv_tree_id + read_also_texts = abap_true + all_languages = lv_all_languages + language = mv_language + IMPORTING + message = ls_msg + TABLES + list_of_nodes = lt_nodes + list_of_references = lt_refs + list_of_texts = lt_texts. + + clear_fields( CHANGING cs_head = ls_head + ct_nodes = lt_nodes ). + + SORT lt_titles BY id. + DELETE ADJACENT DUPLICATES FROM lt_titles COMPARING spras id. + + SORT lt_texts BY spras node_id. + DELETE ADJACENT DUPLICATES FROM lt_texts COMPARING spras node_id. + + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'SPRAS' + iv_keep_master_lang = abap_true + CHANGING + ct_tab = lt_texts ). + + io_xml->add( iv_name = 'TREE_HEAD' + ig_data = ls_head ). + io_xml->add( iv_name = 'TREE_TITLES' + ig_data = lt_titles ). + io_xml->add( iv_name = 'TREE_NODES' + ig_data = lt_nodes ). + io_xml->add( iv_name = 'TREE_REFS' + ig_data = lt_refs ). + io_xml->add( iv_name = 'TREE_TEXTS' + ig_data = lt_texts ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_SFSW IMPLEMENTATION. + METHOD activate. + + DATA: lt_switches TYPE sfw_switchtab, + lt_msgtab TYPE sprot_u_tab. + + IF zif_abapgit_object~is_active( ) = abap_true. + RETURN. + ENDIF. + + APPEND mv_switch TO lt_switches. + + cl_sfw_activate=>activate_sfsw( + EXPORTING + p_switches = lt_switches + p_version = 'I' + IMPORTING + p_msgtab = lt_msgtab ). + + READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( 'Error activating SFBS' ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_switch = is_item-obj_name. + + ENDMETHOD. + METHOD create. + + TRY. + " make sure to clear cache + ro_switch = cl_sfw_sw=>create_switch( mv_switch ). + ro_switch->free( ). + ro_switch = cl_sfw_sw=>create_switch( mv_switch ). + CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. + zcx_abapgit_exception=>raise( 'Error from CL_SFW_SW=>CREATE_SWITCH' ). + ENDTRY. + + ENDMETHOD. + METHOD get. + + TRY. + " make sure to clear cache + ro_switch = cl_sfw_sw=>get_switch( mv_switch ). + ro_switch->free( ). + ro_switch = cl_sfw_sw=>get_switch( mv_switch ). + CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. + zcx_abapgit_exception=>raise( 'Error from CL_SFW_SW=>GET_SWITCH' ). + ENDTRY. + + ENDMETHOD. + METHOD unlock. + + CALL FUNCTION 'DEQUEUE_EEUDB' + EXPORTING + relid = 'SW' + name = ms_item-obj_name + _synchron = 'X' + _scope = '1' + mode_eudb = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_data TYPE sfw_switch. + ls_data = get( )->get_header_data( ). + + rv_user = ls_data-changedby. + IF rv_user IS INITIAL. + rv_user = ls_data-author. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lt_delete TYPE sfw_switchtab, + lt_msgtab TYPE sprot_u_tab. + + APPEND mv_switch TO lt_delete. + + cl_sfw_activate=>delete_sfsw( EXPORTING p_switches = lt_delete + IMPORTING p_msgtab = lt_msgtab ). + + READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( 'Error deleting SFSW' ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lo_switch TYPE REF TO cl_sfw_sw, + ls_header TYPE sfw_switch, + lv_name_32 TYPE sfw_name32, + lv_name_80 TYPE sfw_name80, + lt_parent_bf TYPE sfw_bf_sw_outtab, + lt_conflicts TYPE sfw_confl_outtab, + lt_packages TYPE sfw_devcl_outtab. + + IF iv_step = zif_abapgit_object=>gc_step_id-late. + activate( ). + RETURN. + ENDIF. + + io_xml->read( EXPORTING iv_name = 'HEADER' + CHANGING cg_data = ls_header ). + io_xml->read( EXPORTING iv_name = 'NAME32' + CHANGING cg_data = lv_name_32 ). + io_xml->read( EXPORTING iv_name = 'NAME80' + CHANGING cg_data = lv_name_80 ). + + io_xml->read( EXPORTING iv_name = 'PARENT_BF' + CHANGING cg_data = lt_parent_bf ). + io_xml->read( EXPORTING iv_name = 'CONFLICTS' + CHANGING cg_data = lt_conflicts ). + io_xml->read( EXPORTING iv_name = 'PACKAGES' + CHANGING cg_data = lt_packages ). + TRY. + IF zif_abapgit_object~exists( ) = abap_true. + lo_switch = get( ). + ELSE. + lo_switch = create( ). + ENDIF. + CATCH cx_pak_not_authorized cx_pak_invalid_state cx_pak_invalid_data. + zcx_abapgit_exception=>raise( 'error in CL_SFW_SW=>CREATE_SWITCH' ). + ENDTRY. + + ls_header-author = sy-uname. + ls_header-createdon = sy-datum. + lo_switch->set_header_data( ls_header ). + + lo_switch->set_texts( p_32 = lv_name_32 + p_80 = lv_name_80 ). + + lo_switch->set_parent_bf( lt_parent_bf ). + lo_switch->set_conflicts( lt_conflicts ). + lo_switch->set_assigned_packages( lt_packages ). + + set_default_package( iv_package ). + tadir_insert( iv_package ). + + lo_switch->save_all( + EXCEPTIONS + not_saved = 1 + OTHERS = 2 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error in CL_SFW_SW->SAVE_ALL' ). + ENDIF. + + unlock( ). + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_sfsw ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA ls_tadir TYPE tadir. + + IF cl_sfw_sw=>check_existence( mv_switch ) = abap_false. + RETURN. + ENDIF. + + SELECT SINGLE * FROM tadir INTO ls_tadir + WHERE pgmid = 'R3TR' + AND object = ms_item-obj_type + AND obj_name = ms_item-obj_name. + IF ls_tadir IS INITIAL. + RETURN. + ENDIF. + + rv_bool = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' + iv_argument = ms_item-obj_name + iv_prefix = 'SW' ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_switch TYPE REF TO cl_sfw_sw, + ls_header TYPE sfw_switch, + lv_name_32 TYPE sfw_name32, + lv_name_80 TYPE sfw_name80, + lt_parent_bf TYPE sfw_bf_sw_outtab, + lt_conflicts TYPE sfw_confl_outtab, + lt_packages TYPE sfw_devcl_outtab. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + lo_switch = get( ). + + ls_header = lo_switch->get_header_data( ). + CLEAR: ls_header-author, + ls_header-version, + ls_header-createdon, + ls_header-changedby, + ls_header-changedon, + ls_header-timestamp. + + lo_switch->get_texts( + IMPORTING + p_32 = lv_name_32 + p_80 = lv_name_80 ). + + lt_parent_bf = lo_switch->get_parent_bf( ). + lt_conflicts = lo_switch->get_conflicts( ). + lt_packages = lo_switch->get_assigned_packages( ). + + io_xml->add( ig_data = ls_header + iv_name = 'HEADER' ). + io_xml->add( ig_data = lv_name_32 + iv_name = 'NAME32' ). + io_xml->add( ig_data = lv_name_80 + iv_name = 'NAME80' ). + + io_xml->add( ig_data = lt_parent_bf + iv_name = 'PARENT_BF' ). + io_xml->add( ig_data = lt_conflicts + iv_name = 'CONFLICTS' ). + io_xml->add( ig_data = lt_packages + iv_name = 'PACKAGES' ). + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_sfsw ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sfpi IMPLEMENTATION. + METHOD interface_to_xstring. + + DATA: li_fp_interface TYPE REF TO if_fp_interface, + li_wb_interface TYPE REF TO if_fp_wb_interface. + TRY. + li_wb_interface = load( ). + li_fp_interface ?= li_wb_interface->get_object( ). + rv_xstr = cl_fp_helper=>convert_interface_to_xstring( li_fp_interface ). + CATCH cx_fp_api. + zcx_abapgit_exception=>raise( 'SFPI error, interface_to_xstring' ). + ENDTRY. + + ENDMETHOD. + METHOD load. + + DATA: lv_name TYPE fpname. + lv_name = ms_item-obj_name. + + TRY. + ri_wb_interface = cl_fp_wb_interface=>load( lv_name ). + CATCH cx_fp_api. + zcx_abapgit_exception=>raise( 'SFPI error, load' ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE lastuser FROM fpinterface + INTO rv_user + WHERE name = ms_item-obj_name + AND state = 'A'. + IF rv_user IS INITIAL. + SELECT SINGLE firstuser FROM fpinterface + INTO rv_user + WHERE name = ms_item-obj_name + AND state = 'A'. + ENDIF. + IF rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_name TYPE fpname, + lo_wb_interface TYPE REF TO cl_fp_wb_interface. + lo_wb_interface ?= load( ). + + lv_name = ms_item-obj_name. + + TRY. + lo_wb_interface->delete( lv_name ). + CATCH cx_fp_api. + zcx_abapgit_exception=>raise( 'SFPI error, delete' ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_xstr TYPE xstring, + lv_name TYPE fpname, + li_wb_object TYPE REF TO if_fp_wb_interface, + li_interface TYPE REF TO if_fp_interface. + lv_name = ms_item-obj_name. + lv_xstr = cl_ixml_80_20=>render_to_xstring( io_xml->get_raw( ) ). + + IF zif_abapgit_object~exists( ) = abap_true. + zif_abapgit_object~delete( iv_package = iv_package + iv_transport = iv_transport ). + ENDIF. + + TRY. + li_interface = cl_fp_helper=>convert_xstring_to_interface( lv_xstr ). + tadir_insert( iv_package ). + li_wb_object = cl_fp_wb_interface=>create( i_name = lv_name + i_interface = li_interface ). + li_wb_object->save( ). + li_wb_object->free( ). + CATCH cx_fp_api. + zcx_abapgit_exception=>raise( 'SFPI error, deserialize' ). + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_name TYPE fpinterface-name. + + SELECT SINGLE name FROM fpinterface + INTO lv_name + WHERE name = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_object TYPE seqg3-garg. + + lv_object = |{ ms_item-obj_name }|. + OVERLAY lv_object WITH ' '. + lv_object = lv_object && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EFPINTERFACE' + iv_argument = lv_object ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_xstr TYPE xstring, + li_document TYPE REF TO if_ixml_document. + lv_xstr = interface_to_xstring( ). + li_document = cl_ixml_80_20=>parse_to_document( stream_xstring = lv_xstr ). + zcl_abapgit_object_sfpf=>fix_oref( li_document ). + io_xml->set_raw( li_document->get_root_element( ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sfpf IMPLEMENTATION. + METHOD fix_oref. + +* During serialization of a SFPF / SFPI object the interface hierarchy +* is represented by attributes "id" and "href", where the id looks +* like "o" and href like "#o". Every run of +* serialization generates a new in these attributes, that +* leads to differences even by comparing of untouched forms. +* The purpose of this method is to renumber the id's consequentially +* and therefore to avoid fictive differences. + +* NB: As the method iterator->get_next() works quite slowly, +* it is better to collect all attributes in a cache table +* instead of implementing of a nested loop using get_next(). + + DATA: + li_iterator TYPE REF TO if_ixml_node_iterator, + li_elem TYPE REF TO if_ixml_element, + lv_new TYPE string, + lv_old TYPE string, + lv_count TYPE i, + BEGIN OF ls_attr_href, + val TYPE string, + attr TYPE REF TO if_ixml_attribute, + END OF ls_attr_href, + lt_attr_href LIKE SORTED TABLE OF ls_attr_href WITH NON-UNIQUE KEY val. + + FIELD-SYMBOLS LIKE LINE OF lt_attr_href. + +* Collect all attributes href='#o...' in the cache table + li_iterator = ii_document->create_iterator_filtered( + ii_document->create_filter_and( + filter1 = ii_document->create_filter_node_type( if_ixml_node=>co_node_element ) + filter2 = ii_document->create_filter_attribute( 'href' ) ) ). + li_elem ?= li_iterator->get_next( ). + WHILE li_elem IS NOT INITIAL. + ls_attr_href-attr = li_elem->get_attribute_node( 'href' ). + ls_attr_href-val = ls_attr_href-attr->get_value( ). + IF ls_attr_href-val CP '##o*'. + INSERT ls_attr_href INTO TABLE lt_attr_href. + ENDIF. + li_elem ?= li_iterator->get_next( ). + ENDWHILE. + +* Renumber id='o...' attributes + li_iterator = ii_document->create_iterator_filtered( + ii_document->create_filter_and( + filter1 = ii_document->create_filter_node_type( if_ixml_node=>co_node_element ) + filter2 = ii_document->create_filter_attribute( 'id' ) ) ). + li_elem ?= li_iterator->get_next( ). + WHILE li_elem IS NOT INITIAL. + lv_old = li_elem->get_attribute( 'id' ). + IF lv_old CP 'o*'. + lv_count = lv_count + 1. + lv_new = |o{ lv_count }|. +* Rewrite id + IF li_elem->set_attribute( name = 'id' + value = lv_new ) IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'SFPF error, FIX_OREF' ). + ENDIF. +* Update references + LOOP AT lt_attr_href ASSIGNING WHERE val = '#' && lv_old. + IF -attr->set_value( '#' && lv_new ) IS NOT INITIAL. + zcx_abapgit_exception=>raise( 'SFPF error, FIX_OREF' ). + ENDIF. + ENDLOOP. + ENDIF. + li_elem ?= li_iterator->get_next( ). + ENDWHILE. + + ENDMETHOD. + METHOD form_to_xstring. + + CONSTANTS: lc_empty_data TYPE xstring VALUE ''. + + DATA: li_fp_form TYPE REF TO if_fp_form, + li_wb_form TYPE REF TO if_fp_wb_form, + li_fp_layout TYPE REF TO if_fp_layout, + lx_fp_err TYPE REF TO cx_fp_api, + lx_fp_conv_err TYPE REF TO cx_fp_api, + lv_layout_data TYPE xstring. + + li_wb_form = load( ). + li_fp_form ?= li_wb_form->get_object( ). + li_fp_layout = li_fp_form->get_layout( ). + lv_layout_data = li_fp_layout->get_layout_data( ). + + mo_files->add_raw( + iv_ext = c_layout_file_ext + iv_data = lv_layout_data ). + + TRY. + li_fp_layout->set_layout_data( i_layout_data = lc_empty_data + i_set_xliff_ids = abap_false ). + CATCH cx_fp_api INTO lx_fp_err. + zcx_abapgit_exception=>raise( |SFPF remove layout: { lx_fp_err->get_text( ) }| ). + ENDTRY. + + TRY. + rv_xstr = cl_fp_helper=>convert_form_to_xstring( li_fp_form ). + CATCH cx_fp_api INTO lx_fp_conv_err ##NO_HANDLER. + " Pass - the exception is handled below! + ENDTRY. + + TRY. + li_fp_layout->set_layout_data( i_layout_data = lv_layout_data + i_set_xliff_ids = abap_false ). + CATCH cx_fp_api INTO lx_fp_err. + " Be aware that there might be another exception + " raised by cl_fp_helper=>convert_form_to_xstring( ) + zcx_abapgit_exception=>raise( |SFPF recover layout: { lx_fp_err->get_text( ) }| ). + ENDTRY. + + IF lx_fp_conv_err IS BOUND. + " This statement handles the exception raised from cl_fp_helper=>convert_form_to_xstring( ) + zcx_abapgit_exception=>raise( |SFPF convert_form_to_xstring: { lx_fp_conv_err->get_text( ) }| ). + ENDIF. + ENDMETHOD. + METHOD load. + + DATA: lv_name TYPE fpname. + lv_name = ms_item-obj_name. + + TRY. + ri_wb_form = cl_fp_wb_form=>load( lv_name ). + CATCH cx_fp_api. + zcx_abapgit_exception=>raise( 'SFPF error, load' ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE lastuser FROM fplayout + INTO rv_user + WHERE name = ms_item-obj_name + AND state = 'A'. + IF rv_user IS INITIAL. + SELECT SINGLE firstuser FROM fplayout + INTO rv_user + WHERE name = ms_item-obj_name + AND state = 'A'. + ENDIF. + IF rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_name TYPE fpname. + + lv_name = ms_item-obj_name. + + TRY. + TRY. + CALL METHOD cl_fp_wb_form=>('DELETE') + EXPORTING + i_name = lv_name + i_ordernum = iv_transport + i_dark = abap_true. " > 740 + CATCH cx_sy_dyn_call_error. + cl_fp_wb_form=>delete( + i_name = lv_name + i_ordernum = iv_transport ). + ENDTRY. + CATCH cx_fp_api. + zcx_abapgit_exception=>raise( 'SFPI error, delete' ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_xstr TYPE xstring, + lv_layout TYPE xstring, + lv_name TYPE fpname, + li_wb_object TYPE REF TO if_fp_wb_form, + li_form TYPE REF TO if_fp_form, + lx_fp_err TYPE REF TO cx_fp_api. + lv_name = ms_item-obj_name. + lv_xstr = cl_ixml_80_20=>render_to_xstring( io_xml->get_raw( ) ). + + TRY. + li_form = cl_fp_helper=>convert_xstring_to_form( lv_xstr ). + + IF mo_files->contains_file( c_layout_file_ext ) = abap_true. + lv_layout = mo_files->read_raw( c_layout_file_ext ). + li_form->get_layout( )->set_layout_data( lv_layout ). + ENDIF. + + IF zif_abapgit_object~exists( ) = abap_true. + TRY. + CALL METHOD cl_fp_wb_form=>('DELETE') + EXPORTING + i_name = lv_name + i_ordernum = iv_transport + i_dark = abap_true. " > 740 + CATCH cx_sy_dyn_call_error. + cl_fp_wb_form=>delete( + i_name = lv_name + i_ordernum = iv_transport ). + ENDTRY. + ENDIF. + + tadir_insert( iv_package ). + + TRY. + CALL METHOD cl_fp_wb_form=>('CREATE') + EXPORTING + i_name = lv_name + i_form = li_form + i_ordernum = iv_transport + i_dark = abap_true " > 740 + RECEIVING + r_wb_form = li_wb_object. + CATCH cx_sy_dyn_call_error. + li_wb_object = cl_fp_wb_form=>create( + i_name = lv_name + i_form = li_form + i_ordernum = iv_transport ). + ENDTRY. + + li_wb_object->save( ). + li_wb_object->free( ). + CATCH cx_fp_api INTO lx_fp_err. + zcx_abapgit_exception=>raise( |SFPF deserialization error: { lx_fp_err->get_text( ) }| ). + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_name TYPE fpname. + + " Check for any state + SELECT SINGLE name FROM fplayout + INTO lv_name + WHERE name = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_object TYPE seqg3-garg. + + lv_object = |{ ms_item-obj_name }|. + OVERLAY lv_object WITH ' '. + lv_object = lv_object && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EFPFORM' + iv_argument = lv_object ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_xstr TYPE xstring, + li_document TYPE REF TO if_ixml_document, + li_node_collection TYPE REF TO if_ixml_node_collection, + li_node_iter TYPE REF TO if_ixml_node_iterator, + li_node TYPE REF TO if_ixml_node, + li_node_new TYPE REF TO if_ixml_node, + li_node_parent TYPE REF TO if_ixml_node. + + lv_xstr = form_to_xstring( ). + li_document = cl_ixml_80_20=>parse_to_document( stream_xstring = lv_xstr ). + +* Clear CACHE_INFO + li_node_collection = li_document->get_elements_by_tag_name_ns( 'CACHE_INFO' ). + IF li_node_collection IS NOT INITIAL. + li_node_iter = li_node_collection->create_iterator( ). + DO. + li_node = li_node_iter->get_next( ). + IF li_node IS INITIAL. + EXIT. + ENDIF. + li_node_new = li_document->create_element_ns( 'CACHE_INFO' ). + li_node_parent = li_node->get_parent( ). + li_node_parent->replace_child( new_child = li_node_new + old_child = li_node ). + ENDDO. + ENDIF. + + fix_oref( li_document ). + io_xml->set_raw( li_document->get_root_element( ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sfbs IMPLEMENTATION. + METHOD activate. + + DATA: lt_bfsets TYPE sfw_bstab, + lt_msgtab TYPE sprot_u_tab. + + IF zif_abapgit_object~is_active( ) = abap_true. + RETURN. + ENDIF. + + APPEND mv_bfset TO lt_bfsets. + + cl_sfw_activate=>activate_sfbs( + EXPORTING + p_bsets = lt_bfsets + p_version = 'I' + IMPORTING + p_msgtab = lt_msgtab ). + + READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( 'Error activating SFBS' ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_bfset = is_item-obj_name. + + ENDMETHOD. + METHOD create. + + TRY. + " make sure to clear cache + ro_bfs = cl_sfw_bfs=>create_bfs( mv_bfset ). + ro_bfs->free( ). + ro_bfs = cl_sfw_bfs=>create_bfs( mv_bfset ). + CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. + zcx_abapgit_exception=>raise( 'Error from CL_SFW_BFS=>CREATE_BFS' ). + ENDTRY. + + ENDMETHOD. + METHOD get. + + TRY. + " make sure to clear cache + ro_bfs = cl_sfw_bfs=>get_bfs( mv_bfset ). + ro_bfs->free( ). + ro_bfs = cl_sfw_bfs=>get_bfs( mv_bfset ). + CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. + zcx_abapgit_exception=>raise( 'Error from CL_SFW_BFS=>GET_BFS' ). + ENDTRY. + + ENDMETHOD. + METHOD unlock. + + CALL FUNCTION 'DEQUEUE_EEUDB' + EXPORTING + relid = 'SS' + name = ms_item-obj_name + _synchron = 'X' + _scope = '1' + mode_eudb = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_data TYPE sfw_bs. + + ls_data = get( )->get_header_data( ). + + rv_user = ls_data-changedby. + + IF rv_user IS INITIAL. + rv_user = ls_data-author. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lt_delete TYPE sfw_bstab, + lt_msgtab TYPE sprot_u_tab. + + APPEND mv_bfset TO lt_delete. + + cl_sfw_activate=>delete_sfbs( EXPORTING p_bsets = lt_delete + IMPORTING p_msgtab = lt_msgtab ). + + READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( 'Error deleting SFBS' ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lo_bfs TYPE REF TO cl_sfw_bfs, + ls_header TYPE sfw_bs, + lv_name_32 TYPE sfw_name32, + lv_name_80 TYPE sfw_name80, + lt_assigned_bf TYPE sfw_bfbs_outtab, + lt_nested_bfs TYPE sfw_bsbs_outtab, + lt_parent_bfs TYPE sfw_bs_bs_parent_outtab. + + IF iv_step = zif_abapgit_object=>gc_step_id-late. + activate( ). + RETURN. + ENDIF. + + io_xml->read( EXPORTING iv_name = 'HEADER' + CHANGING cg_data = ls_header ). + io_xml->read( EXPORTING iv_name = 'NAME32' + CHANGING cg_data = lv_name_32 ). + io_xml->read( EXPORTING iv_name = 'NAME80' + CHANGING cg_data = lv_name_80 ). + + io_xml->read( EXPORTING iv_name = 'ASSIGNED_BF' + CHANGING cg_data = lt_assigned_bf ). + io_xml->read( EXPORTING iv_name = 'NESTED_BFS' + CHANGING cg_data = lt_nested_bfs ). + io_xml->read( EXPORTING iv_name = 'PARENT_BFS' + CHANGING cg_data = lt_parent_bfs ). + + TRY. + IF zif_abapgit_object~exists( ) = abap_true. + lo_bfs = get( ). + ELSE. + lo_bfs = create( ). + ENDIF. + CATCH cx_pak_not_authorized cx_pak_invalid_state cx_pak_invalid_data. + zcx_abapgit_exception=>raise( 'error in CL_SFW_BFS=>CREATE_BFS' ). + ENDTRY. + + ls_header-author = sy-uname. + ls_header-createdon = sy-datum. + lo_bfs->set_header_data( ls_header ). + + lo_bfs->set_texts( p_32 = lv_name_32 + p_80 = lv_name_80 ). + + lo_bfs->set_assigned_bf( lt_assigned_bf ). + lo_bfs->set_assigned_bfs( lt_nested_bfs ). + lo_bfs->set_nested_parent( lt_parent_bfs ). + + set_default_package( iv_package ). + tadir_insert( iv_package ). + + lo_bfs->save_all( ). + + unlock( ). + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_sfbs ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA ls_tadir TYPE tadir. + + IF cl_sfw_bfs=>check_existence( mv_bfset ) = abap_false. + RETURN. + ENDIF. + + SELECT SINGLE * FROM tadir INTO ls_tadir + WHERE pgmid = 'R3TR' + AND object = ms_item-obj_type + AND obj_name = ms_item-obj_name. + IF ls_tadir IS INITIAL. + RETURN. + ENDIF. + + rv_bool = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' + iv_argument = ms_item-obj_name + iv_prefix = 'SS' ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_bfs TYPE REF TO cl_sfw_bfs, + ls_header TYPE sfw_bs, + lv_name_32 TYPE sfw_name32, + lv_name_80 TYPE sfw_name80, + lt_assigned_bf TYPE sfw_bfbs_outtab, + lt_nested_bfs TYPE sfw_bsbs_outtab, + lt_parent_bfs TYPE sfw_bs_bs_parent_outtab. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + lo_bfs = get( ). + + ls_header = lo_bfs->get_header_data( ). + CLEAR: ls_header-author, + ls_header-version, + ls_header-createdon, + ls_header-changedby, + ls_header-changedon, + ls_header-timestamp. + + lo_bfs->get_texts( + IMPORTING + p_32 = lv_name_32 + p_80 = lv_name_80 ). + + lt_assigned_bf = lo_bfs->get_assigned_bf( ). + lt_nested_bfs = lo_bfs->get_nested_bfs( ). + lt_parent_bfs = lo_bfs->get_nested_parent( ). + + io_xml->add( ig_data = ls_header + iv_name = 'HEADER' ). + io_xml->add( ig_data = lv_name_32 + iv_name = 'NAME32' ). + io_xml->add( ig_data = lv_name_80 + iv_name = 'NAME80' ). + + io_xml->add( ig_data = lt_assigned_bf + iv_name = 'ASSIGNED_BF' ). + io_xml->add( ig_data = lt_nested_bfs + iv_name = 'NESTED_BFS' ). + io_xml->add( ig_data = lt_parent_bfs + iv_name = 'PARENT_BFS' ). + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_sfbs ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sfbf IMPLEMENTATION. + METHOD activate. + + DATA: lt_bfuncts TYPE sfw_bftab, + lt_msgtab TYPE sprot_u_tab. + + IF zif_abapgit_object~is_active( ) = abap_true. + RETURN. + ENDIF. + + APPEND mv_bf TO lt_bfuncts. + + cl_sfw_activate=>activate_sfbf( + EXPORTING + p_bfuncts = lt_bfuncts + p_version = 'I' + IMPORTING + p_msgtab = lt_msgtab ). + + READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( 'Error activating SFBF' ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_bf = is_item-obj_name. + + ENDMETHOD. + METHOD create. + + TRY. + " make sure to clear cache + ro_bf = cl_sfw_bf=>create_bf( mv_bf ). + ro_bf->free( ). + ro_bf = cl_sfw_bf=>create_bf( mv_bf ). + CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. + zcx_abapgit_exception=>raise( 'Error from CL_SFW_BF=>CREATE_BF' ). + ENDTRY. + + ENDMETHOD. + METHOD get. + + TRY. + " make sure to clear cache, method GET_BF_FROM_DB does not exist in 702 + ro_bf = cl_sfw_bf=>get_bf( mv_bf ). + ro_bf->free( ). + ro_bf = cl_sfw_bf=>get_bf( mv_bf ). + CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. + zcx_abapgit_exception=>raise( 'Error from CL_SFW_BF=>GET_BF' ). + ENDTRY. + + ENDMETHOD. + METHOD unlock. + + CALL FUNCTION 'DEQUEUE_EEUDB' + EXPORTING + relid = 'SF' + name = ms_item-obj_name + _synchron = 'X' + _scope = '1' + mode_eudb = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_data TYPE sfw_bf. + + ls_data = get( )->get_header_data( ). + + rv_user = ls_data-changedby. + + IF rv_user IS INITIAL. + rv_user = ls_data-author. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lt_delete TYPE sfw_bftab, + lt_msgtab TYPE sprot_u_tab. + + APPEND mv_bf TO lt_delete. + + cl_sfw_activate=>delete_sfbf( EXPORTING p_bfuncts = lt_delete + IMPORTING p_msgtab = lt_msgtab ). + + READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( 'Error deleting SFBF' ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lo_bf TYPE REF TO cl_sfw_bf, + ls_header TYPE sfw_bf, + lv_name_32 TYPE sfw_name32, + lv_name_80 TYPE sfw_name80, + lt_assigned_switches TYPE sfw_swbf_outtab, + lt_dependancies TYPE sfw_depend_outtab, + ls_sfw_bfc_kw TYPE sfw_bfc_kw, + ls_sfw_bfc_tc TYPE sfw_bfc_tc, + ls_sfw_bfc_rn TYPE sfw_bfc_rn, + lt_parent_bfs TYPE sfw_bs_bf_outtab. + + IF iv_step = zif_abapgit_object=>gc_step_id-late. + activate( ). + RETURN. + ENDIF. + + io_xml->read( EXPORTING iv_name = 'HEADER' + CHANGING cg_data = ls_header ). + io_xml->read( EXPORTING iv_name = 'NAME32' + CHANGING cg_data = lv_name_32 ). + io_xml->read( EXPORTING iv_name = 'NAME80' + CHANGING cg_data = lv_name_80 ). + + io_xml->read( EXPORTING iv_name = 'ASSIGNED_SWITCHES' + CHANGING cg_data = lt_assigned_switches ). + io_xml->read( EXPORTING iv_name = 'DEPENDANCIES' + CHANGING cg_data = lt_dependancies ). + io_xml->read( EXPORTING iv_name = 'CONTENT_KW' + CHANGING cg_data = ls_sfw_bfc_kw ). + io_xml->read( EXPORTING iv_name = 'CONTENT_TC' + CHANGING cg_data = ls_sfw_bfc_tc ). + io_xml->read( EXPORTING iv_name = 'CONTENT_RN' + CHANGING cg_data = ls_sfw_bfc_rn ). + io_xml->read( EXPORTING iv_name = 'PARENT_BFS' + CHANGING cg_data = lt_parent_bfs ). + + TRY. + IF zif_abapgit_object~exists( ) = abap_true. + lo_bf = get( ). + ELSE. + lo_bf = create( ). + ENDIF. + CATCH cx_pak_not_authorized cx_pak_invalid_state cx_pak_invalid_data. + zcx_abapgit_exception=>raise( 'error in CL_SFW_BF=>CREATE_BF' ). + ENDTRY. + + ls_header-author = sy-uname. + ls_header-createdon = sy-datum. + + " Get component from package + SELECT SINGLE dlvunit FROM tdevc INTO ls_header-component WHERE devclass = iv_package. + + lo_bf->set_header_data( ls_header ). + + lo_bf->set_texts( p_32 = lv_name_32 + p_80 = lv_name_80 ). + + lo_bf->set_assigned_switches( lt_assigned_switches ). + lo_bf->set_excluded_bf( lt_dependancies ). + lo_bf->set_content_data( + im_sfw_bfc_kw = ls_sfw_bfc_kw + im_sfw_bfc_rn = ls_sfw_bfc_rn + im_sfw_bfc_tc = ls_sfw_bfc_tc ). + lo_bf->set_parent_bfs( lt_parent_bfs ). + + set_default_package( iv_package ). + tadir_insert( iv_package ). + + lo_bf->save_all( ). + + unlock( ). + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_sfbf ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_tadir TYPE tadir, + lv_bf TYPE sfw_bfunction. + + lv_bf = ms_item-obj_name. + IF cl_sfw_bf=>check_existence( lv_bf ) = abap_false. + RETURN. + ENDIF. + + SELECT SINGLE * FROM tadir INTO ls_tadir + WHERE pgmid = 'R3TR' + AND object = ms_item-obj_type + AND obj_name = ms_item-obj_name. + IF ls_tadir IS INITIAL. + RETURN. + ENDIF. + + rv_bool = abap_true. + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' + iv_argument = ms_item-obj_name + iv_prefix = 'SF' ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_bf TYPE REF TO cl_sfw_bf, + ls_header TYPE sfw_bf, + lv_name_32 TYPE sfw_name32, + lv_name_80 TYPE sfw_name80, + lt_assigned_switches TYPE sfw_swbf_outtab, + lt_dependancies TYPE sfw_depend_outtab, + ls_sfw_bfc_kw TYPE sfw_bfc_kw, + ls_sfw_bfc_tc TYPE sfw_bfc_tc, + ls_sfw_bfc_rn TYPE sfw_bfc_rn, + lt_parent_bfs TYPE sfw_bs_bf_outtab. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + lo_bf = get( ). + + ls_header = lo_bf->get_header_data( ). + CLEAR: ls_header-author, + ls_header-version, + ls_header-component, + ls_header-createdon, + ls_header-changedby, + ls_header-changedon, + ls_header-timestamp. + + lo_bf->get_texts( + IMPORTING + p_32 = lv_name_32 + p_80 = lv_name_80 ). + + lt_assigned_switches = lo_bf->get_assigned_switches( ). + lt_dependancies = lo_bf->get_excluded_bf( ). + lo_bf->get_content_data( + IMPORTING + ex_sfw_bfc_kw = ls_sfw_bfc_kw + ex_sfw_bfc_tc = ls_sfw_bfc_tc + ex_sfw_bfc_rn = ls_sfw_bfc_rn ). + lt_parent_bfs = lo_bf->get_parent_bfs( ). + + io_xml->add( ig_data = ls_header + iv_name = 'HEADER' ). + io_xml->add( ig_data = lv_name_32 + iv_name = 'NAME32' ). + io_xml->add( ig_data = lv_name_80 + iv_name = 'NAME80' ). + + io_xml->add( ig_data = lt_assigned_switches + iv_name = 'ASSIGNED_SWITCHES' ). + io_xml->add( ig_data = lt_dependancies + iv_name = 'DEPENDANCIES' ). + io_xml->add( ig_data = ls_sfw_bfc_kw + iv_name = 'CONTENT_KW' ). + io_xml->add( ig_data = ls_sfw_bfc_tc + iv_name = 'CONTENT_TC' ). + io_xml->add( ig_data = ls_sfw_bfc_rn + iv_name = 'CONTENT_RN' ). + io_xml->add( ig_data = lt_parent_bfs + iv_name = 'PARENT_BFS' ). + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_sfbf ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_scvi IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_screen_variant TYPE scvariant. + + lv_screen_variant = ms_item-obj_name. + + SELECT SINGLE chuser + FROM shdsvci + INTO rv_user + WHERE scvariant = lv_screen_variant. + IF sy-subrc <> 0 + OR rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_screen_variant TYPE scvariant. + + lv_screen_variant = ms_item-obj_name. + + CALL FUNCTION 'RS_HDSYS_DELETE_SC_VARIANT' + EXPORTING + scvariant = lv_screen_variant + EXCEPTIONS + variant_enqueued = 1 + no_correction = 2 + scvariant_used = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_screen_variant TYPE ty_screen_variant. + + io_xml->read( + EXPORTING + iv_name = 'SCVI' + CHANGING + cg_data = ls_screen_variant ). + + CALL FUNCTION 'ENQUEUE_ESSCVARCIU' + EXPORTING + scvariant = ls_screen_variant-shdsvci-scvariant + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. + MESSAGE e413(ms) WITH ls_screen_variant-shdsvci-scvariant INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + corr_insert( iv_package ). + +* Populate user details + ls_screen_variant-shdsvci-crdate = sy-datum. + ls_screen_variant-shdsvci-cruser = sy-uname. + ls_screen_variant-shdsvci-chdate = sy-datum. + ls_screen_variant-shdsvci-chuser = sy-uname. + + MODIFY shdsvci FROM ls_screen_variant-shdsvci. + MODIFY shdsvtxci FROM TABLE ls_screen_variant-shdsvtxci[]. + MODIFY shdsvfvci FROM TABLE ls_screen_variant-shdsvfvci[]. + MODIFY shdguixt FROM TABLE ls_screen_variant-shdguixt[]. + MODIFY shdgxtcode FROM TABLE ls_screen_variant-shdgxtcode[]. + + CALL FUNCTION 'DEQUEUE_ESSCVARCIU' + EXPORTING + scvariant = ls_screen_variant-shdsvci-scvariant. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_screen_variant TYPE scvariant. + + lv_screen_variant = ms_item-obj_name. + + CALL FUNCTION 'RS_HDSYS_READ_SC_VARIANT_DB' + EXPORTING + scvariant = lv_screen_variant + EXCEPTIONS + no_variant = 1 + OTHERS = 2. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + + rs_metadata = get_metadata( ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + + rv_active = is_active( ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_screen_variant TYPE ty_screen_variant. + + ls_screen_variant-shdsvci-scvariant = ms_item-obj_name. + + CALL FUNCTION 'RS_HDSYS_READ_SC_VARIANT_DB' + EXPORTING + scvariant = ls_screen_variant-shdsvci-scvariant + IMPORTING + header_scvariant = ls_screen_variant-shdsvci + TABLES + values_scvariant = ls_screen_variant-shdsvfvci[] + guixt_scripts = ls_screen_variant-shdguixt[] + EXCEPTIONS + no_variant = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + SORT ls_screen_variant-shdsvfvci ASCENDING. + SORT ls_screen_variant-shdguixt ASCENDING. + +* Clear all user details + CLEAR: ls_screen_variant-shdsvci-crdate, + ls_screen_variant-shdsvci-cruser, + ls_screen_variant-shdsvci-chdate, + ls_screen_variant-shdsvci-chuser. + + SELECT * + FROM shdsvtxci + INTO TABLE ls_screen_variant-shdsvtxci[] + WHERE scvariant = ls_screen_variant-shdsvci-scvariant + ORDER BY PRIMARY KEY. + + SELECT * + FROM shdgxtcode + INTO TABLE ls_screen_variant-shdgxtcode[] + WHERE scvariant = ls_screen_variant-shdsvci-scvariant + ORDER BY PRIMARY KEY. + + io_xml->add( iv_name = 'SCVI' + ig_data = ls_screen_variant ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_scp1 IMPLEMENTATION. + METHOD adjust_inbound. + + FIELD-SYMBOLS: TYPE scprvals, + TYPE scprreca, + TYPE scprvall. + +* back to internal format + LOOP AT cs_scp1-scprvals ASSIGNING . + SHIFT -recnumber RIGHT DELETING TRAILING space. + ENDLOOP. + LOOP AT cs_scp1-scprreca ASSIGNING . + SHIFT -recnumber RIGHT DELETING TRAILING space. + ENDLOOP. + LOOP AT cs_scp1-scprvall ASSIGNING . + SHIFT -recnumber RIGHT DELETING TRAILING space. + ENDLOOP. + + ENDMETHOD. + METHOD adjust_outbound. + + FIELD-SYMBOLS: TYPE scprvals, + TYPE scprreca, + TYPE scprvall. + +* normalize the XML + LOOP AT cs_scp1-scprvals ASSIGNING . + CONDENSE -recnumber. + ENDLOOP. + LOOP AT cs_scp1-scprreca ASSIGNING . + CONDENSE -recnumber. + ENDLOOP. + LOOP AT cs_scp1-scprvall ASSIGNING . + CONDENSE -recnumber. + ENDLOOP. + + ENDMETHOD. + METHOD call_delete_fms. + + CONSTANTS: + lc_version_new TYPE c VALUE 'N', "Include SCPRINTCONST version_new + lc_operation_delete TYPE c VALUE 'D'. + + DATA: + lv_profile_type TYPE scprattr-type, + lt_fatherprofiles TYPE STANDARD TABLE OF scproprof WITH DEFAULT KEY, + ls_fatherprofile TYPE scproprof. + CALL FUNCTION 'SCPR_DB_ATTR_GET_DETAIL' + EXPORTING + profid = iv_profile_id + version = lc_version_new + IMPORTING + proftype = lv_profile_type + EXCEPTIONS + OTHERS = 0. + + CALL FUNCTION 'SCPR_PRSET_DB_USED_IN' + EXPORTING + profid = iv_profile_id + version = lc_version_new + TABLES + profiles = lt_fatherprofiles. + + ls_fatherprofile-id = iv_profile_id. + APPEND ls_fatherprofile TO lt_fatherprofiles. + CALL FUNCTION 'SCPR_CT_TRANSPORT_ENTRIES' + TABLES + profids = lt_fatherprofiles + EXCEPTIONS + error_in_transport_layer = 1 + user_abort = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error while deleting SCP1 - TRANSPORT, { sy-subrc }| ). + ENDIF. + + CALL FUNCTION 'SCPR_PRSET_DB_DELETE_ALL' + EXPORTING + profid = iv_profile_id + proftype = lv_profile_type + TABLES + fatherprofs = lt_fatherprofiles + EXCEPTIONS + user_abort = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error while deleting SCP1 - DB_DELETE, { sy-subrc }| ). + ENDIF. + + CALL FUNCTION 'SCPR_MEM_SCPR_ACTIONS_ADD' + EXPORTING + bcset_id = iv_profile_id + operation = lc_operation_delete. + + ENDMETHOD. + METHOD dequeue. + + DATA: lv_id TYPE scpr_id. + lv_id = ms_item-obj_name. + + CALL FUNCTION 'SCPR_SV_DEQUEUE_BCSET' + EXPORTING + bcset_id = lv_id. + + ENDMETHOD. + METHOD enqueue. + + DATA: lv_id TYPE scpr_id. + + lv_id = ms_item-obj_name. + + CALL FUNCTION 'SCPR_SV_ENQUEUE_BCSET' + EXPORTING + bcset_id = lv_id + EXCEPTIONS + is_already_locked = 1 + system_failure = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD load. + + CALL FUNCTION 'SCPR_TEMPL_DB_VALS_GET_DETAIL' + EXPORTING + profid = cs_scp1-scprattr-id + category = cs_scp1-scprattr-category + TABLES + values = cs_scp1-scprvals + valuesl = cs_scp1-scprvall + recattr = cs_scp1-scprreca. + + CALL FUNCTION 'SCPR_TEMPL_DB_FLDTXTVAR_GET' + EXPORTING + bcset_id = cs_scp1-scprattr-id + category = cs_scp1-scprattr-category + TABLES + it_fldv = cs_scp1-scprfldv. + + ENDMETHOD. + METHOD load_hier. + + CALL FUNCTION 'SCPR_PRSET_DB_SUBP_GET_DETAIL' + EXPORTING + profid = cs_scp1-scprattr-id + category = cs_scp1-scprattr-category + TABLES + subprofs = cs_scp1-subprofs. + + ENDMETHOD. + METHOD save. + + DATA: ls_scp1 TYPE ty_scp1, + ls_text TYPE scprtext. +* copy everything to local, the function module changes the values + ls_scp1 = is_scp1. + + READ TABLE ls_scp1-scprtext INTO ls_text WITH KEY langu = mv_language. "#EC CI_SUBRC + + CALL FUNCTION 'SCPR_TEMPL_MN_TEMPLATE_SAVE' + EXPORTING + profid = ls_scp1-scprattr-id + proftext = ls_text-text + category = ls_scp1-scprattr-category + cli_dep = ls_scp1-scprattr-cli_dep + cli_cas = ls_scp1-scprattr-cli_cas + reftype = ls_scp1-scprattr-reftype + refname = ls_scp1-scprattr-refname + orgid = ls_scp1-scprattr-orgid + component = ls_scp1-scprattr-component + minrelease = ls_scp1-scprattr-minrelease + maxrelease = ls_scp1-scprattr-maxrelease + act_info = ls_scp1-scprattr-act_info + bcset_type = ls_scp1-scprattr-type + fldtxtvar_supplied = 'YES' + with_transp_insert = abap_false + with_progress_indicator = abap_false + remove_denied_data = abap_true + ask_for_cont_after_remove = abap_true + TABLES + values = ls_scp1-scprvals + valuesl = ls_scp1-scprvall + recattr = ls_scp1-scprreca + it_fldv = ls_scp1-scprfldv + texts = ls_scp1-scprtext + EXCEPTIONS + user_abort = 1 + error_in_transport_layer = 2 + inconsistent_data = 3 + database_error = 4 + OTHERS = 5. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD save_hier. + + DATA: ls_scp1 TYPE ty_scp1, + ls_profs LIKE LINE OF ls_scp1-subprofs, + lt_sub TYPE STANDARD TABLE OF scproprof WITH DEFAULT KEY, + ls_sub LIKE LINE OF lt_sub, + ls_text TYPE scprtext. +* copy everything to local, the function module changes the values + ls_scp1 = is_scp1. + + READ TABLE ls_scp1-scprtext INTO ls_text WITH KEY langu = mv_language. "#EC CI_SUBRC + +* see fm SCPR_PRSET_DB_STORE, only this field and sequence is used + LOOP AT ls_scp1-subprofs INTO ls_profs. + ls_sub-id = ls_profs-subprofile. + APPEND ls_sub TO lt_sub. + ENDLOOP. + + CALL FUNCTION 'SCPR_PRSET_MN_BCSET_SAVE' + EXPORTING + profid = ls_scp1-scprattr-id + proftext = ls_text-text + category = ls_scp1-scprattr-category + cli_dep = ls_scp1-scprattr-cli_dep + cli_cas = ls_scp1-scprattr-cli_cas + reftype = ls_scp1-scprattr-reftype + refname = ls_scp1-scprattr-refname + orgid = ls_scp1-scprattr-orgid + component = ls_scp1-scprattr-component + minrelease = ls_scp1-scprattr-minrelease + maxrelease = ls_scp1-scprattr-maxrelease + act_info = ls_scp1-scprattr-act_info + with_transp_insert = abap_false + with_progress_indicator = abap_false + TABLES + subprofs = lt_sub + texts = ls_scp1-scprtext + EXCEPTIONS + user_abort = 1 + error_in_transport_layer = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE modifier INTO rv_user FROM scprattr + WHERE id = ms_item-obj_name + AND version = 'N'. + IF sy-subrc <> 0 OR rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_profile_id TYPE scpr_id. + + lv_profile_id = ms_item-obj_name. + + enqueue( ). + call_delete_fms( lv_profile_id ). + dequeue( ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_scp1 TYPE ty_scp1. + io_xml->read( + EXPORTING iv_name = 'SCP1' + CHANGING cg_data = ls_scp1 ). + + adjust_inbound( CHANGING cs_scp1 = ls_scp1 ). + + IF ls_scp1-scprattr-type = 'TMP'. + save_hier( ls_scp1 ). + ELSE. + save( ls_scp1 ). + ENDIF. + + dequeue( ). + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_rc TYPE sy-subrc, + lv_profid TYPE scprattr-id. + lv_profid = ms_item-obj_name. + + CALL FUNCTION 'SCPR_BCSET_EXISTS' + EXPORTING + profid = lv_profid + IMPORTING + rc = lv_rc. + rv_bool = boolc( lv_rc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + + rs_metadata = get_metadata( ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lv_display_only TYPE scpr_txt20, + lv_bcset_id TYPE scpr_id. + + lv_display_only = abap_false. + lv_bcset_id = ms_item-obj_name. + + EXPORT scpr3_display_only = lv_display_only + scpr3_bcset_id = lv_bcset_id + TO MEMORY ID 'SCPR3_PARAMETER'. + + SUBMIT scpr3 AND RETURN. + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_scp1 TYPE ty_scp1. + ls_scp1-scprattr-id = ms_item-obj_name. + + CALL FUNCTION 'SCPR_DB_ATTR_GET_DETAIL' + EXPORTING + profid = ls_scp1-scprattr-id + IMPORTING + proftype = ls_scp1-scprattr-type + cli_dep = ls_scp1-scprattr-cli_dep + cli_cas = ls_scp1-scprattr-cli_cas + reftype = ls_scp1-scprattr-reftype + refname = ls_scp1-scprattr-refname + component = ls_scp1-scprattr-component + minrelease = ls_scp1-scprattr-minrelease + maxrelease = ls_scp1-scprattr-maxrelease + orgid = ls_scp1-scprattr-orgid + act_info = ls_scp1-scprattr-act_info. + + CALL FUNCTION 'SCPR_TEXT_GET' + EXPORTING + profid = ls_scp1-scprattr-id + category = ls_scp1-scprattr-category + TABLES + texts = ls_scp1-scprtext + EXCEPTIONS + no_text_found = 1 + OTHERS = 2 ##FM_SUBRC_OK. + + IF ls_scp1-scprattr-type = 'TMP'. + load_hier( CHANGING cs_scp1 = ls_scp1 ). + ELSE. + load( CHANGING cs_scp1 = ls_scp1 ). + ENDIF. + + adjust_outbound( CHANGING cs_scp1 = ls_scp1 ). + + io_xml->add( + iv_name = 'SCP1' + ig_data = ls_scp1 ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_saxx_super IMPLEMENTATION. + + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_object_key = ms_item-obj_name. + + ENDMETHOD. + + METHOD create_channel_objects. + + get_names( ). + + TRY. + CREATE OBJECT mi_appl_obj_data TYPE (mv_appl_obj_cls_name). + CREATE OBJECT mi_persistence TYPE (mv_persistence_cls_name). + + CATCH cx_sy_create_object_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = ms_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD get_data. + + DATA: lx_error TYPE REF TO cx_swb_exception. + + TRY. + mi_persistence->get( + EXPORTING + p_object_key = mv_object_key + p_version = 'A' + CHANGING + p_object_data = mi_appl_obj_data ). + + CATCH cx_swb_exception INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + mi_appl_obj_data->get_data( IMPORTING p_data = eg_data ). + + ENDMETHOD. + METHOD get_names. + + IF mv_data_structure_name IS INITIAL. + mv_data_structure_name = get_data_structure_name( ). + ENDIF. + + IF mv_appl_obj_cls_name IS INITIAL. + mv_appl_obj_cls_name = get_data_class_name( ). + ENDIF. + + IF mv_persistence_cls_name IS INITIAL. + mv_persistence_cls_name = get_persistence_class_name( ). + ENDIF. + + ENDMETHOD. + METHOD lock. + + DATA: lv_objname TYPE trobj_name, + lv_objtype TYPE trobjtype. + + lv_objname = ms_item-obj_name. + lv_objtype = ms_item-obj_type. + + mi_persistence->lock( + EXPORTING + p_objname_tr = lv_objname + p_object_key = mv_object_key + p_objtype_tr = lv_objtype + EXCEPTIONS + foreign_lock = 1 + error_occurred = 2 + OTHERS = 3 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error occurred while locking { ms_item-obj_type } { lv_objname }| ). + ENDIF. + + ENDMETHOD. + METHOD unlock. + + DATA: lv_objname TYPE trobj_name, + lv_objtype TYPE trobjtype. + + lv_objname = ms_item-obj_name. + lv_objtype = ms_item-obj_type. + + mi_persistence->unlock( p_objname_tr = lv_objname + p_object_key = mv_object_key + p_objtype_tr = lv_objtype ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lr_data TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + CREATE DATA lr_data TYPE (mv_data_structure_name). + ASSIGN lr_data->* TO . + + get_data( IMPORTING eg_data = ). + + ASSIGN COMPONENT 'HEADER-CHANGED_BY' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + IF IS NOT INITIAL. + rv_user = . + ELSE. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + TRY. + lock( ). + mi_persistence->delete( mv_object_key ). + unlock( ). + + CATCH cx_swb_exception. + zcx_abapgit_exception=>raise( |Error occurred while deleting { ms_item-obj_type }| ). + ENDTRY. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lr_data TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any. + + CREATE DATA lr_data TYPE (mv_data_structure_name). + ASSIGN lr_data->* TO . + + io_xml->read( + EXPORTING + iv_name = ms_item-obj_type + CHANGING + cg_data = ). + + IF zif_abapgit_object~exists( ) = abap_true. + zif_abapgit_object~delete( iv_package = iv_package + iv_transport = iv_transport ). + ENDIF. + + TRY. + lock( ). + corr_insert( iv_package ). + mi_appl_obj_data->set_data( ). + mi_persistence->save( mi_appl_obj_data ). + unlock( ). + + CATCH cx_swb_exception. + zcx_abapgit_exception=>raise( |Error occurred while creating { ms_item-obj_type }| ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + mi_persistence->get( p_object_key = mv_object_key + p_version = 'A' + p_existence_check_only = abap_true ). + + CATCH cx_swb_exception. + rv_bool = abap_false. + RETURN. + ENDTRY. + + rv_bool = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_argument TYPE seqg3-garg, + lv_lock_object TYPE string. + + lv_lock_object = get_lock_object( ). + + lv_argument = mv_object_key. + OVERLAY lv_argument WITH ' '. + lv_argument = lv_argument && '*'. + + rv_is_locked = exists_a_lock_entry_for( + iv_lock_object = lv_lock_object + iv_argument = lv_argument ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lr_data TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any, + TYPE any, + TYPE any. + + CREATE DATA lr_data TYPE (mv_data_structure_name). + ASSIGN lr_data->* TO . + + get_data( IMPORTING eg_data = ). + + ASSIGN COMPONENT 'HEADER' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'CHANGED_ON' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + CLEAR . + + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + CLEAR . + + ASSIGN COMPONENT 'CHANGED_AT' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + CLEAR . + + ASSIGN COMPONENT 'CHANGED_CLNT' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + CLEAR . + + ASSIGN COMPONENT 'CREATED_ON' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + CLEAR . + + ASSIGN COMPONENT 'CREATED_BY' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + CLEAR . + + ASSIGN COMPONENT 'CREATED_AT' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + CLEAR . + + ASSIGN COMPONENT 'CREATED_CLNT' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + CLEAR . + + io_xml->add( iv_name = ms_item-obj_type + ig_data = ). + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_object_sapc IMPLEMENTATION. + + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + create_channel_objects( ). + + ENDMETHOD. + METHOD get_data_class_name. + + rv_data_class_name = 'CL_APC_APPLICATION_OBJ_DATA'. + + ENDMETHOD. + METHOD get_data_structure_name. + + rv_data_structure_name = 'APC_APPLICATION_COMPLETE'. + + ENDMETHOD. + METHOD get_persistence_class_name. + + rv_persistence_class_name = 'CL_APC_APPLICATION_OBJ_PERS'. + + ENDMETHOD. + METHOD get_lock_object. + + rv_lock_object = 'E_APC_APPL'. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_object_samc IMPLEMENTATION. + + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + create_channel_objects( ). + + ENDMETHOD. + METHOD get_data_class_name. + + rv_data_class_name = 'CL_AMC_APPLICATION_OBJ_DATA'. + + ENDMETHOD. + METHOD get_data_structure_name. + + rv_data_structure_name = 'AMC_APPLICATION_COMPLETE'. + + ENDMETHOD. + METHOD get_persistence_class_name. + + rv_persistence_class_name = 'CL_AMC_APPLICATION_OBJ_PERS'. + + ENDMETHOD. + METHOD get_lock_object. + + rv_lock_object = 'E_AMC_APPL'. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_object_prog IMPLEMENTATION. + METHOD deserialize_texts. + + DATA: lt_tpool_i18n TYPE zif_abapgit_lang_definitions=>ty_i18n_tpools, + lt_tpool TYPE textpool_table. + + FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. + ii_xml->read( EXPORTING iv_name = 'I18N_TPOOL' + CHANGING cg_data = lt_tpool_i18n ). + + LOOP AT lt_tpool_i18n ASSIGNING . + lt_tpool = read_tpool( -textpool ). + deserialize_textpool( iv_program = ms_item-obj_name + iv_language = -language + it_tpool = lt_tpool ). + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_with_ext. + + " Special treatment for extensions + " If the program name exceeds 30 characters it is not a usual ABAP program but might be + " some extension, which requires the internal addition EXTENSION TYPE + " https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.htm?file=abapinsert_report_internal.htm + " This e.g. occurs in case of transportable Code Inspector variants (ending with ===VC) + + zcl_abapgit_factory=>get_sap_report( )->insert_report( + iv_name = is_progdir-name + iv_package = iv_package + it_source = it_source + iv_state = 'I' + iv_version = is_progdir-uccheck + iv_program_type = is_progdir-subc + iv_extension_type = is_progdir-name+30 ). + + zcl_abapgit_factory=>get_sap_report( )->update_progdir( + is_progdir = is_progdir + iv_state = 'I' + iv_package = iv_package ). + + zcl_abapgit_objects_activation=>add( + iv_type = 'REPS' + iv_name = is_progdir-name ). + + ENDMETHOD. + METHOD is_program_locked. + + rv_is_program_locked = exists_a_lock_entry_for( iv_lock_object = 'ESRDIRE' + iv_argument = |{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD serialize_texts. + + DATA: lt_tpool_i18n TYPE zif_abapgit_lang_definitions=>ty_i18n_tpools, + lt_tpool TYPE textpool_table, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + " Table d010tinf stores info. on languages in which program is maintained + " Select all active translations of program texts + " Skip main language - it was already serialized + lt_language_filter = mo_i18n_params->build_language_filter( ). + + SELECT DISTINCT language + INTO CORRESPONDING FIELDS OF TABLE lt_tpool_i18n + FROM d010tinf + WHERE r3state = 'A' + AND prog = ms_item-obj_name + AND language <> mv_language + AND language IN lt_language_filter + ORDER BY language ##TOO_MANY_ITAB_FIELDS. + + SORT lt_tpool_i18n BY language ASCENDING. + LOOP AT lt_tpool_i18n ASSIGNING . + READ TEXTPOOL ms_item-obj_name + LANGUAGE -language + INTO lt_tpool. + -textpool = add_tpool( lt_tpool ). + ENDLOOP. + + IF lines( lt_tpool_i18n ) > 0. + ii_xml->add( iv_name = 'I18N_TPOOL' + ig_data = lt_tpool_i18n ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + SELECT SINGLE unam FROM reposrc INTO rv_user + WHERE progname = ms_item-obj_name + AND r3state = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + lv_program LIKE sy-repid, + lv_obj_name TYPE e071-obj_name. + + lv_program = ms_item-obj_name. + + CALL FUNCTION 'RS_DELETE_PROGRAM' + EXPORTING + corrnumber = iv_transport + program = lv_program + suppress_popup = abap_true + mass_delete_call = abap_true + tadir_devclass = iv_package + force_delete_used_includes = abap_true + EXCEPTIONS + enqueue_lock = 1 + object_not_found = 2 + permission_failure = 3 + reject_deletion = 4 + OTHERS = 5. + IF sy-subrc = 2. + " Drop also any inactive code that is left in REPOSRC + zcl_abapgit_factory=>get_sap_report( )->delete_report( lv_program ). + + " Remove inactive objects from work area + lv_obj_name = lv_program. + + CALL FUNCTION 'RS_DELETE_FROM_WORKING_AREA' + EXPORTING + object = 'REPS' + obj_name = lv_obj_name + immediate = 'X' + actualize_working_area = 'X'. + + CALL FUNCTION 'RS_DELETE_FROM_WORKING_AREA' + EXPORTING + object = 'REPT' + obj_name = lv_obj_name + immediate = 'X' + actualize_working_area = 'X'. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + delete_longtexts( c_longtext_id_prog ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_program_name TYPE syrepid, + ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, + lt_tpool TYPE textpool_table, + lt_dynpros TYPE ty_dynpro_tt, + lt_tpool_ext TYPE zif_abapgit_lang_definitions=>ty_tpool_tt, + ls_cua TYPE ty_cua, + lt_source TYPE abaptxt255_tab. + + " Add R3TR PROG to transport first, otherwise we get several LIMUs + corr_insert( iv_package ). + + lv_program_name = ms_item-obj_name. + + lt_source = mo_files->read_abap( ). + + io_xml->read( EXPORTING iv_name = 'TPOOL' + CHANGING cg_data = lt_tpool_ext ). + lt_tpool = read_tpool( lt_tpool_ext ). + + io_xml->read( EXPORTING iv_name = 'PROGDIR' + CHANGING cg_data = ls_progdir ). + + set_abap_language_version( CHANGING cv_abap_language_version = ls_progdir-uccheck ). + + IF strlen( lv_program_name ) > 30. + + " Objects with extension for example transportable Code Inspector variants (ending with ===VC) + deserialize_with_ext( is_progdir = ls_progdir + iv_package = iv_package + it_source = lt_source ). + + ELSE. + + deserialize_program( is_progdir = ls_progdir + it_source = lt_source + it_tpool = lt_tpool + iv_package = iv_package ). + + io_xml->read( EXPORTING iv_name = 'DYNPROS' + CHANGING cg_data = lt_dynpros ). + deserialize_dynpros( lt_dynpros ). + + io_xml->read( EXPORTING iv_name = 'CUA' + CHANGING cg_data = ls_cua ). + deserialize_cua( iv_program_name = lv_program_name + is_cua = ls_cua ). + + " Texts deserializing (English) + deserialize_textpool( iv_program = lv_program_name + it_tpool = lt_tpool ). + + " Texts deserializing (translations) + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + deserialize_texts( io_xml ). + ENDIF. + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_prog ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_progname TYPE reposrc-progname. + + SELECT SINGLE progname FROM reposrc INTO lv_progname + WHERE progname = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + " Skip PROG generated by CHDO + IF rv_bool = abap_true. + FIND REGEX '^F.*CD[C|F|T|V]' IN ms_item-obj_name. + IF sy-subrc <> 0. + FIND REGEX '^/.*/F.*CD[C|F|T|V]' IN ms_item-obj_name. + ENDIF. + rv_bool = boolc( sy-subrc <> 0 ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + IF is_program_locked( ) = abap_true + OR is_any_dynpro_locked( ms_item-obj_name ) = abap_true + OR is_cua_locked( ms_item-obj_name ) = abap_true + OR is_text_locked( ms_item-obj_name ) = abap_true. + + rv_is_locked = abap_true. + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + +* see SAP note 1025291, run report DELETE_TADIR_FOR_EIMP_INCLUDE to clean bad TADIR entries + ASSERT NOT ms_item-obj_name CP '*=E'. + + serialize_program( io_xml = io_xml + is_item = ms_item + io_files = mo_files ). + + " Texts serializing (translations) + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + serialize_texts( io_xml ). + ENDIF. + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_prog ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_prag IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " not stored by SAP + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_pragma TYPE REF TO cl_abap_pragma, + lx_error TYPE REF TO cx_root. + + TRY. + lo_pragma = cl_abap_pragma=>get_ref( ms_item-obj_name ). + + lo_pragma->delete( ). + lo_pragma->leave_change( ). "unlock + + CATCH cx_root INTO lx_error. + IF lo_pragma IS BOUND. + lo_pragma->leave_change( ). + ENDIF. + zcx_abapgit_exception=>raise( lx_error->get_text( ) ). + ENDTRY. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_pragma TYPE ty_pragma, + lo_pragma TYPE REF TO cl_abap_pragma, + lx_error TYPE REF TO cx_root. + + tadir_insert( iv_package ). + + TRY. + io_xml->read( + EXPORTING + iv_name = 'PRAG' + CHANGING + cg_data = ls_pragma ). + + lo_pragma = cl_abap_pragma=>create( p_pragma = ms_item-obj_name + p_package = iv_package ). + + lo_pragma->set_info( p_description = ls_pragma-description + p_signature = ls_pragma-signature + p_extension = ls_pragma-extension ). + + lo_pragma->save( ). + lo_pragma->leave_change( ). "unlock + CATCH cx_root INTO lx_error. + IF lo_pragma IS BOUND. + lo_pragma->leave_change( ). + ENDIF. + zcx_abapgit_exception=>raise( lx_error->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + cl_abap_pragma=>get_ref( ms_item-obj_name ). + + CATCH cx_abap_pragma_not_exists. + rv_bool = abap_false. + RETURN. + ENDTRY. + + rv_bool = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_pragma TYPE REF TO cl_abap_pragma, + ls_pragma TYPE ty_pragma. + + TRY. + lo_pragma = cl_abap_pragma=>get_ref( ms_item-obj_name ). + + ls_pragma-pragma = lo_pragma->pragma. + ls_pragma-extension = lo_pragma->extension. + ls_pragma-signature = lo_pragma->signature. + ls_pragma-description = lo_pragma->description. + + io_xml->add( iv_name = 'PRAG' + ig_data = ls_pragma ). + + CATCH cx_abap_pragma_not_exists. + zcx_abapgit_exception=>raise( |Pragma { ms_item-obj_name } doesn't exist| ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlqJyKbsVHldwKaGddDbbHeNaet IMPLEMENTATION. + + METHOD constructor. + + mi_interface = ii_interface. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~get_elements. + + mi_interface->get_elements( + IMPORTING + e_elements = rt_elements + EXCEPTIONS + object_invalid = 1 + intern_err = 2 + OTHERS = 3 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~set_elements_changeable. + + mi_interface->set_elements_changeable( + EXPORTING + i_changeable = iv_changeable + EXCEPTIONS + object_already_changeable = 1 + object_already_unlocked = 2 + object_locked_by_other_user = 3 + object_modified = 4 + object_just_created = 5 + object_deleted = 6 + permission_failure = 7 + object_invalid = 8 + unexpected_error = 9 + OTHERS = 10 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~save_elements. + + mi_interface->save_elements( + EXCEPTIONS + object_not_changeable = 1 + object_invalid = 2 + cancelled_in_corr = 3 + permission_failure = 4 + unexpected_error = 5 + intern_err = 6 + OTHERS = 7 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~get_all_attributes. + + mi_interface->get_all_attributes( + IMPORTING + e_package_interface_data = rs_package_interface_data + EXCEPTIONS + object_invalid = 1 + OTHERS = 2 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~set_changeable. + + mi_interface->set_changeable( + EXPORTING + i_changeable = iv_changeable + EXCEPTIONS + object_locked_by_other_user = 1 + permission_failure = 2 + object_already_changeable = 3 + object_already_unlocked = 4 + object_just_created = 5 + object_deleted = 6 + object_modified = 7 + object_not_existing = 8 + object_invalid = 9 + unexpected_error = 10 + OTHERS = 11 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~delete. + + mi_interface->delete( + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + intern_err = 4 + OTHERS = 5 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~save. + + mi_interface->save( + EXCEPTIONS + short_text_missing = 1 + object_not_changeable = 2 + object_invalid = 3 + cancelled_in_corr = 4 + permission_failure = 5 + unexpected_error = 6 + intern_err = 7 + OTHERS = 8 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~remove_elements. + + mi_interface->remove_elements( + EXPORTING + i_elements = it_elements + EXCEPTIONS + object_deleted = 1 + object_invalid = 2 + object_not_changeable = 3 + element_not_contained = 4 + intern_err = 5 + OTHERS = 6 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~add_elements. + + DATA: + lt_mismatched TYPE scomeldata, + ls_mismatched LIKE LINE OF lt_mismatched. + + mi_interface->add_elements( + EXPORTING + i_elements_data = it_elements_data + IMPORTING + e_mismatched_elem_data = lt_mismatched + EXCEPTIONS + object_invalid = 1 + intern_err = 2 + OTHERS = 3 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + LOOP AT lt_mismatched INTO ls_mismatched. + zcx_abapgit_exception=>raise( |Object { ls_mismatched-elem_type } { ls_mismatched-elem_key } | && + |from different package { ls_mismatched-elem_pack }| ). + ENDLOOP. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~set_all_attributes. + + mi_interface->set_all_attributes( + EXPORTING + i_package_interface_data = is_package_interface_data + i_data_sign = is_data_sign + EXCEPTIONS + object_deleted = 1 + object_not_changeable = 2 + interface_not_empty = 3 + acl_not_empty = 4 + author_not_existing = 5 + object_type_mismatch = 6 + object_invalid = 7 + OTHERS = 8 ). +* Downport: exception "logical_package_types_differ" +* does not exist in lower versions + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~get_changeable. + + mi_interface->get_changeable( + IMPORTING + e_changeable = rv_changeable + EXCEPTIONS + object_invalid = 1 + OTHERS = 2 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_object_pinf IMPLEMENTATION. + METHOD create_facade. + + CREATE OBJECT ri_facade TYPE kHGwlqJyKbsVHldwKaGddDbbHeNaet + EXPORTING + ii_interface = ii_interface. + + ENDMETHOD. + METHOD create_or_load. + + DATA: li_interface TYPE REF TO if_package_interface, + lv_pkg_interface_data TYPE scompidtln. + + lv_pkg_interface_data-default_if = is_pinf-attributes-default_if. + lv_pkg_interface_data-tadir_devc = iv_package. + + "Important if the package name comes from another package + IF is_pinf-attributes-pack_name IS INITIAL. + lv_pkg_interface_data-pack_name = iv_package. + ELSE. + lv_pkg_interface_data-pack_name = is_pinf-attributes-pack_name. + ENDIF. + + IF zif_abapgit_object~exists( ) = abap_false. + cl_package_interface=>create_new_package_interface( + EXPORTING + i_pkg_interface_name = is_pinf-attributes-intf_name + i_publisher_pkg_name = lv_pkg_interface_data-pack_name + i_pkg_interface_data = lv_pkg_interface_data + IMPORTING + e_package_interface = li_interface + EXCEPTIONS + object_already_existing = 1 + object_just_created = 2 + interface_name_invalid = 3 + unexpected_error = 4 + OTHERS = 7 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error creating new package interface' ). + ENDIF. + + ri_interface = create_facade( li_interface ). + + ELSE. + + ri_interface = load( is_pinf-attributes-intf_name ). + + ENDIF. + + ENDMETHOD. + METHOD delete_elements. + + DATA: lt_elements TYPE ty_elements. + + FIELD-SYMBOLS: LIKE LINE OF lt_elements. + ii_interface->set_elements_changeable( abap_true ). + + lt_elements = ii_interface->get_elements( ). + + LOOP AT lt_elements ASSIGNING . + ->delete( ). + ENDLOOP. + + ii_interface->save_elements( ). + + ENDMETHOD. + METHOD load. + + DATA: li_interface TYPE REF TO if_package_interface. + + cl_package_interface=>load_package_interface( + EXPORTING + i_package_interface_name = iv_name + i_force_reload = abap_true + IMPORTING + e_package_interface = li_interface ). + + ri_interface = create_facade( li_interface ). + + ENDMETHOD. + METHOD update_attributes. + + DATA: ls_sign TYPE scompisign, + lv_changeable TYPE abap_bool. + lv_changeable = ii_interface->get_changeable( ). + IF lv_changeable = abap_false. +* at creation the object is already in change mode + ii_interface->set_changeable( abap_true ). + ENDIF. + + ls_sign-descript = abap_true. + ls_sign-pinftype = abap_true. + ls_sign-restricted = abap_true. + ls_sign-default_if = abap_true. + ls_sign-def_sever = abap_true. + ls_sign-acl_flag = abap_true. + ls_sign-pifstablty = abap_true. + ls_sign-release_status = abap_true. + + ii_interface->set_all_attributes( + is_package_interface_data = is_pinf-attributes + is_data_sign = ls_sign ). + + set_default_package( iv_package ). +* looks like setting "i_suppress_dialog = abap_true" will make +* it fail for local($) packages + ii_interface->save( ). + + ii_interface->set_changeable( abap_false ). + + ENDMETHOD. + METHOD update_elements. + + DATA: lt_existing TYPE ty_elements, + ls_element LIKE LINE OF is_pinf-elements, + lt_add TYPE scomeldata, + lv_index TYPE i, + lv_found TYPE abap_bool, + ls_attr TYPE scomeldtln. + + FIELD-SYMBOLS LIKE LINE OF lt_existing. + + ii_interface->set_elements_changeable( abap_true ). + + lt_existing = ii_interface->get_elements( ). + + LOOP AT is_pinf-elements INTO ls_element. + + lv_found = abap_false. + LOOP AT lt_existing ASSIGNING . + lv_index = sy-tabix. + ->get_all_attributes( IMPORTING e_element_data = ls_attr ). + IF ls_element-elem_type = ls_attr-elem_type + AND ls_element-elem_key = ls_attr-elem_key. + DELETE lt_existing INDEX lv_index. + CONTINUE. " current loop + ENDIF. + ENDLOOP. + + IF lv_found = abap_false. + ls_element-elem_pack = iv_package. + APPEND ls_element TO lt_add. + ENDIF. + ENDLOOP. + + ii_interface->remove_elements( lt_existing ). + + ii_interface->add_elements( lt_add ). + + ii_interface->save_elements( ). + + ii_interface->set_elements_changeable( abap_false ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE changed_by FROM intf INTO rv_user + WHERE intf_name = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: li_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. + + corr_insert( iv_package ). + + li_interface = load( |{ ms_item-obj_name }| ). + +* elements must be deleted before the package interface +* can be deleted + delete_elements( li_interface ). + + li_interface->set_changeable( abap_true ). + + li_interface->delete( ). + + li_interface->save( ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: li_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT, + ls_pinf TYPE ty_pinf. + io_xml->read( EXPORTING iv_name = 'PINF' + CHANGING cg_data = ls_pinf ). + + "needed for update_attributes + ls_pinf-attributes-tadir_devc = iv_package. + + li_interface = create_or_load( + is_pinf = ls_pinf + iv_package = iv_package ). + + update_attributes( + iv_package = iv_package + is_pinf = ls_pinf + ii_interface = li_interface ). + + update_elements( + iv_package = iv_package + is_pinf = ls_pinf + ii_interface = li_interface ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_pack_name TYPE intf-pack_name, + lv_main_pack TYPE tdevc-mainpack. + SELECT SINGLE pack_name FROM intf INTO lv_pack_name + WHERE intf_name = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + IF rv_bool = abap_true. + SELECT SINGLE mainpack FROM tdevc INTO lv_main_pack + WHERE devclass = lv_pack_name. "#EC CI_GENBUFF + rv_bool = boolc( sy-subrc = 0 ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' + iv_argument = ms_item-obj_name + iv_prefix = 'PF' ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_pinf TYPE ty_pinf, + lt_elements TYPE ty_elements, + li_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. + + FIELD-SYMBOLS: TYPE any, + LIKE LINE OF lt_elements, + LIKE LINE OF ls_pinf-elements. + + li_interface = load( |{ ms_item-obj_name }| ). + + ls_pinf-attributes = li_interface->get_all_attributes( ). + + "Delete the package name if it comes from the same package + IF ls_pinf-attributes-tadir_devc = ls_pinf-attributes-pack_name OR + ms_item-devclass = ls_pinf-attributes-pack_name. + CLEAR ls_pinf-attributes-pack_name. + ENDIF. + + CLEAR: ls_pinf-attributes-author, + ls_pinf-attributes-created_by, + ls_pinf-attributes-created_on, + ls_pinf-attributes-changed_by, + ls_pinf-attributes-changed_on, + ls_pinf-attributes-tadir_devc. + +* fields does not exist in older SAP versions + ASSIGN COMPONENT 'SW_COMP_LOGICAL_PACKAGE' OF STRUCTURE ls_pinf-attributes TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'SW_COMP_TADIR_PACKAGE' OF STRUCTURE ls_pinf-attributes TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + lt_elements = li_interface->get_elements( ). + + LOOP AT lt_elements ASSIGNING . + APPEND INITIAL LINE TO ls_pinf-elements ASSIGNING . + ->get_all_attributes( IMPORTING e_element_data = ). + CLEAR -elem_pack. + ENDLOOP. + + io_xml->add( ig_data = ls_pinf + iv_name = 'PINF' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_pers IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_pers_key = ms_item-obj_name. + + ENDMETHOD. + METHOD get_personalization_object. + + CREATE OBJECT ro_personalization_object + EXPORTING + p_create = iv_create + p_pers_key = mv_pers_key + p_view_only = iv_view_only + EXCEPTIONS + pers_key_already_exists = 1 + pers_key_does_not_exist = 2 + transport_view_only = 3 + transport_canceled = 4 + OTHERS = 5. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE author FROM spers_reg INTO rv_user + WHERE pers_key = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_personalization_object TYPE REF TO cl_pers_reg. + + lo_personalization_object = get_personalization_object( ). + + lo_personalization_object->delete( + EXPORTING + p_no_confirm = abap_true + EXCEPTIONS + deletion_canceled = 1 + deletion_failed = 2 + transport_canceled = 3 + OTHERS = 4 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + ls_personalization_object TYPE ty_personalization_object, + lo_personalization_object TYPE REF TO cl_pers_reg. + + io_xml->read( + EXPORTING + iv_name = 'PERS' + CHANGING + cg_data = ls_personalization_object ). + + tadir_insert( iv_package ). + + lo_personalization_object = get_personalization_object( iv_create = abap_true ). + + lo_personalization_object->set_reg_data( + p_pers_reg = ls_personalization_object-pers_reg + p_pers_reg_text = ls_personalization_object-pers_reg_text ). + + lo_personalization_object->save( + EXPORTING + no_check = abap_true + EXCEPTIONS + data_not_saved = 1 + transport_canceled = 2 + OTHERS = 3 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + cl_pers_reg=>exists( + EXPORTING + p_pers_key = mv_pers_key + EXCEPTIONS + pers_key_does_not_exist = 1 + OTHERS = 2 ). + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + " There's no object specific locking. Just a global one. + rv_is_locked = exists_a_lock_entry_for( 'E_SPERSREG' ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_bcdata TYPE bdcdata, + lt_bcdata TYPE STANDARD TABLE OF bdcdata. + + ls_bcdata-program = 'SAPLSPERS_REG_DIALOG'. + ls_bcdata-dynpro = '0100'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'SPERS_REG-PERS_KEY'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=PERSDISPLAY'. + APPEND ls_bcdata TO lt_bcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'PERSREG' + it_bdcdata = lt_bcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + lo_personalization_object TYPE REF TO cl_pers_reg, + ls_personalization_object TYPE ty_personalization_object. + + lo_personalization_object = get_personalization_object( iv_view_only = abap_true ). + + lo_personalization_object->get_reg_data( + IMPORTING + p_pers_reg = ls_personalization_object-pers_reg + p_pers_reg_text = ls_personalization_object-pers_reg_text ). + + CLEAR: + ls_personalization_object-pers_reg-author, + ls_personalization_object-pers_reg-fdate, + ls_personalization_object-pers_reg-ftime. + + io_xml->add( iv_name = 'PERS' + ig_data = ls_personalization_object ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_pdxx_super IMPLEMENTATION. + METHOD check_subrc_for. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( iv_call && ' returned ' && sy-subrc ). + ENDIF. + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + ms_objkey-otype = is_item-obj_type+2(2). + ms_objkey-objid = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE uname + INTO rv_user + FROM hrs1201 + WHERE otype = ms_item-obj_type AND + objid = ms_item-obj_name. + + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + CALL FUNCTION 'RH_HRSOBJECT_DELETE' + EXPORTING + act_otype = ms_objkey-otype + act_objid = ms_objkey-objid + no_confirmation_msg = abap_true + EXCEPTIONS + enqueue_failed = 1 + object_not_deleted = 2 + object_not_found = 3 + OTHERS = 4 ##FM_SUBRC_OK. + + check_subrc_for( `RH_HRSOBJECT_DELETE` ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + ASSERT 1 = 2. "Must be redefined + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL FUNCTION 'RH_READ_OBJECT' + EXPORTING + plvar = '01' + otype = ms_objkey-otype + objid = ms_objkey-objid + istat = '1' + begda = sy-datum + endda = '99991231' + ointerval = 'X' + read_db = 'X' + EXCEPTIONS + not_found = 1 + OTHERS = 2. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = abap_true. + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'HRSOBJECT' + iv_argument = ms_objkey-otype && ms_objkey-objid ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + ASSERT 1 = 2. "Must be redefined + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ DEFINITION DEFERRED. +CLASS kHGwlvrpxwdUTiJUSNzxpMacLYgbxq DEFINITION DEFERRED. +* renamed: zcl_abapgit_object_pdts :: lcl_attribute_setter +CLASS kHGwlvrpxwdUTiJUSNzxpMacLYgbxq DEFINITION + INHERITING FROM cl_workflow_general_task_def + CREATE PUBLIC + FINAL. + PUBLIC SECTION. + + CLASS-METHODS set_objid IMPORTING iv_objid TYPE hrobject-objid + io_task TYPE REF TO cl_workflow_general_task_def. + + CLASS-METHODS set_container_id IMPORTING iv_id TYPE guid_32 + io_task TYPE REF TO cl_workflow_general_task_def. "#EC NEEDED +ENDCLASS. + +CLASS kHGwlvrpxwdUTiJUSNzxpMacLYgbxq IMPLEMENTATION. + + METHOD set_container_id. + + FIELD-SYMBOLS TYPE REF TO if_swf_cnt_container. + + ASSIGN ('IO_TASK->CONTAINER') TO . + ASSERT sy-subrc = 0. + + CALL METHOD ->('SET_GUID') + EXPORTING + guid_32 = iv_id. + + ENDMETHOD. + METHOD set_objid. + io_task->objid = iv_objid. + ENDMETHOD. + +ENDCLASS. +* renamed: zcl_abapgit_object_pdts :: lcl_task_definition +CLASS kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ DEFINITION + CREATE PUBLIC + FINAL. + + PUBLIC SECTION. + + INTERFACES iUFTsvrpxwdUTiJUSNzxoTkdegmNBa. + + CLASS-METHODS load IMPORTING iv_objid TYPE hrobject-objid + RETURNING VALUE(ri_result) TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa + RAISING zcx_abapgit_exception. + + CLASS-METHODS create IMPORTING iv_objid TYPE hrobject-objid + is_task_data TYPE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa=>ty_task_data + RETURNING VALUE(ri_result) TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa + RAISING zcx_abapgit_exception. + PRIVATE SECTION. + CONSTANTS c_subty_task_description TYPE hr_s_subty VALUE '0120'. + + DATA mo_taskdef TYPE REF TO cl_workflow_task_ts. + DATA ms_task TYPE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa=>ty_task_data. + + DATA: mv_objid TYPE hrobjid. + + METHODS supply_instance RAISING zcx_abapgit_exception. + METHODS check_subrc_for IMPORTING iv_call TYPE clike OPTIONAL + RAISING zcx_abapgit_exception. + +ENDCLASS. +CLASS kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ IMPLEMENTATION. + + METHOD load. + + DATA lo_taskdef TYPE REF TO kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ. + + CREATE OBJECT lo_taskdef. + lo_taskdef->mv_objid = iv_objid. + lo_taskdef->supply_instance( ). + + ri_result = lo_taskdef. + + ENDMETHOD. + + METHOD check_subrc_for. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( iv_call && ' returned ' && sy-subrc ). + ENDIF. + ENDMETHOD. + METHOD supply_instance. + + cl_workflow_factory=>create_ts( + EXPORTING + objid = mv_objid + RECEIVING + ts_inst = mo_taskdef + EXCEPTIONS + standard_task_does_not_exist = 1 + object_could_not_be_locked = 2 + objid_not_given = 3 + OTHERS = 4 ) ##SUBRC_OK. + + check_subrc_for( 'CREATE_TS' ). + + ms_task-wi_text = mo_taskdef->wi_text. + ms_task-short_text = mo_taskdef->short_text. + ms_task-plvar = mo_taskdef->plvar. + ms_task-method = mo_taskdef->method. + ms_task-method_binding = mo_taskdef->method_binding. + ms_task-starting_events = mo_taskdef->starting_events. + ms_task-starting_events_binding = mo_taskdef->starting_events_binding. + ms_task-terminating_events = mo_taskdef->terminating_events. + ms_task-terminating_events_binding = mo_taskdef->terminating_events_binding. + ms_task-descriptions = mo_taskdef->descriptions. + + ENDMETHOD. + + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~clear_origin_data. + + FIELD-SYMBOLS: TYPE hrs1002, + TYPE hrs1214, + TYPE hrs1212, + TYPE hrs1212. + + CLEAR: ms_task-method-aedtm, + ms_task-method-uname. + + LOOP AT ms_task-method_binding ASSIGNING . + CLEAR: -aedtm, + -uname. + ENDLOOP. + + LOOP AT ms_task-starting_events_binding ASSIGNING . + CLEAR: -aedtm, + -uname. + ENDLOOP. + + LOOP AT ms_task-descriptions ASSIGNING . + CLEAR: -aedtm, + -uname. + ENDLOOP. + + LOOP AT ms_task-terminating_events_binding ASSIGNING . + CLEAR: -aedtm, + -uname. + ENDLOOP. + + ENDMETHOD. + + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~get_definition. + rs_result = me->ms_task. + ENDMETHOD. + + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~get_container. + ri_result = mo_taskdef->container. + ENDMETHOD. + + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~get_user_container. + + DATA: li_container TYPE REF TO if_swf_cnt_element_access_1, + lt_user_elements TYPE swfdnamtab, + lt_system_elements TYPE swfdnamtab, + lv_element TYPE swfdname. + + li_container = mo_taskdef->container. + lt_user_elements = li_container->all_elements_list( ). + lt_system_elements = li_container->all_elements_list( list_system = abap_true ). + + LOOP AT lt_system_elements INTO lv_element. + READ TABLE lt_user_elements WITH KEY table_line = lv_element TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + TRY. + li_container->element_remove( name = lv_element ). + CATCH cx_swf_cnt_container ##NO_HANDLER. + "Shouldn't happen, doesn't matter if it does + ENDTRY. + ENDIF. + ENDLOOP. + + ri_result ?= li_container. + + ENDMETHOD. + + METHOD create. + DATA lo_task TYPE REF TO kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ. + + CREATE OBJECT lo_task TYPE kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ. + lo_task->mv_objid = iv_objid. + lo_task->ms_task = is_task_data. + ri_result = lo_task. + + ENDMETHOD. + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~import_container. + + DATA lt_exception_list TYPE swf_cx_tab. + DATA lx_exception TYPE REF TO cx_swf_ifs_exception. + + mo_taskdef->container->import_from_xml( + EXPORTING xml_stream = iv_xml_string + IMPORTING exception_list = lt_exception_list ). + + IF lt_exception_list IS NOT INITIAL. + READ TABLE lt_exception_list INDEX 1 INTO lx_exception. + zcx_abapgit_exception=>raise_with_text( lx_exception ). + ENDIF. + + ENDMETHOD. + + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~create_task. + + cl_workflow_factory=>create_new_ts( + EXPORTING + short_text = |{ ms_task-short_text }| + text = |{ ms_task-wi_text }| + RECEIVING + task_object = mo_taskdef + EXCEPTIONS + text_exists_already = 1 + OTHERS = 2 ). "#EC SUBRC_OK + + check_subrc_for( `CREATE_NEW_TS` ). + + kHGwlvrpxwdUTiJUSNzxpMacLYgbxq=>set_objid( iv_objid = mv_objid + io_task = mo_taskdef ). + + kHGwlvrpxwdUTiJUSNzxpMacLYgbxq=>set_container_id( iv_id = |TS{ mv_objid }| + io_task = mo_taskdef ). + + ENDMETHOD. + + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_start_events. + + mo_taskdef->change_start_events_complete( + EXPORTING + starting_events = ms_task-starting_events + EXCEPTIONS + no_changes_allowed = 1 + OTHERS = 2 ). "#EC SUBRC_OK + + check_subrc_for( `CHANGE_START_EVENTS_COMPLETE` ). + + mo_taskdef->change_start_evt_bind_complete( + EXPORTING + new_bindings = ms_task-starting_events_binding + EXCEPTIONS + no_changes_allowed = 1 + OTHERS = 2 ). "#EC SUBRC_OK + + check_subrc_for( `CHANGE_START_EVT_BIND_COMPLETE` ). + + ENDMETHOD. + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~save. + + DATA ls_hrsobject TYPE hrsobject. + ls_hrsobject-otype = 'TS'. "swfco_org_standard_task - todo: linter can't resolve this + ls_hrsobject-objid = mv_objid. + INSERT hrsobject FROM ls_hrsobject. + + mo_taskdef->save_standard_task( + EXPORTING + development_class = iv_package + iv_force_gen = abap_true + EXCEPTIONS + no_changes_allowed = 1 + no_client_indep_maint = 2 + update_error = 3 + insert_error_new_ts = 4 + new_ts_could_not_be_locked = 5 + save_abort_by_user = 6 + OTHERS = 7 ). "#EC SUBRC_OK + + check_subrc_for( `SAVE_STANDARD_TASK` ). + + ENDMETHOD. + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_wi_text. + + mo_taskdef->change_wi_text( + EXPORTING + new_wi_text = ms_task-wi_text + EXCEPTIONS + no_changes_allowed = 1 + OTHERS = 2 ). "#EC SUBRC_OK + + check_subrc_for( `CHANGE_WI_TEXT` ). + + ENDMETHOD. + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_method. + + FIELD-SYMBOLS TYPE hrs1214. + + mo_taskdef->change_method( + EXPORTING + new_method = ms_task-method " New Method or Settings + EXCEPTIONS + no_changes_allowed = 1 + problem_method_web_enabling = 2 + problem_method_phon_enabling = 3 + OTHERS = 4 ). "#EC SUBRC_OK + + check_subrc_for( `CHANGE_METHOD` ). + + LOOP AT ms_task-method_binding ASSIGNING . + + mo_taskdef->change_method_binding( + EXPORTING + binding = + delete = abap_false + insert = abap_true + EXCEPTIONS + no_changes_allowed = 1 + desired_action_not_clear = 2 + ts_cnt_element_does_not_exist = 3 + binding_could_not_be_deleted = 4 + OTHERS = 5 ). "#EC SUBRC_OK + + check_subrc_for( `CHANGE_METHOD_BINDING` ). + + ENDLOOP. + + ENDMETHOD. + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_terminating_events. + + mo_taskdef->change_term_events_complete( + EXPORTING + terminating_events = ms_task-terminating_events + EXCEPTIONS + no_changes_allowed = 1 + OTHERS = 2 ). "#EC SUBRC_OK + + check_subrc_for( `CHANGE_TERM_EVENTS_COMPLETE` ). + + mo_taskdef->change_term_evt_bind_complete( + EXPORTING + new_bindings = ms_task-terminating_events_binding + EXCEPTIONS + no_changes_allowed = 1 + OTHERS = 2 ). "#EC SUBRC_OK + + check_subrc_for( `CHANGE_TERM_EVT_BIND_COMPLETE` ). + + ENDMETHOD. + METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_text. + + mo_taskdef->change_text( + EXPORTING + subty = c_subty_task_description + new_text = ms_task-descriptions + EXCEPTIONS + no_changes_allowed = 1 + OTHERS = 2 ). "#EC SUBRC_OK + + check_subrc_for( `CHANGE_TEXT` ). + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_object_pdts IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + ms_objkey-otype = 'TS'. + ms_objkey-objid = ms_item-obj_name. + + mv_objid = ms_item-obj_name. "Todo: Obsolete + + ENDMETHOD. + METHOD extract_container. + + DATA li_stream TYPE REF TO if_ixml_ostream. + DATA li_container_element TYPE REF TO if_ixml_element. + DATA li_document TYPE REF TO if_ixml_document. + + li_document = io_xml->get_raw( ). + + li_container_element = li_document->find_from_name_ns( 'CONTAINER' ). + + IF li_container_element IS BOUND. + + li_document = cl_ixml=>create( )->create_document( ). + + li_stream = cl_ixml=>create( )->create_stream_factory( )->create_ostream_xstring( rv_result ). + + li_document->append_child( li_container_element ). + + cl_ixml=>create( )->create_renderer( + document = li_document + ostream = li_stream + )->render( ). + + ENDIF. + + ENDMETHOD. + METHOD get_container_xml. + + DATA li_xml_dom TYPE REF TO if_ixml_document. + DATA li_elements TYPE REF TO if_ixml_node_collection. + DATA li_iterator TYPE REF TO if_ixml_node_iterator. + DATA li_element TYPE REF TO if_ixml_node. + DATA li_children TYPE REF TO if_ixml_node_list. + DATA li_child_iterator TYPE REF TO if_ixml_node_iterator. + DATA li_attributes TYPE REF TO if_ixml_named_node_map. + DATA lv_name TYPE string. + DATA li_container TYPE REF TO if_swf_cnt_container. + + "Todo: get_user_container strips out system elements, but to_xml adds them back in (hardcoded internally) + " Dirty hack further down to remove them from XML until we get this to work properly + li_container = ii_task->get_user_container( ). + li_container->to_xml( + EXPORTING + include_null_values = abap_true + include_initial_values = abap_true + include_typenames = abap_true + include_change_data = abap_true + include_texts = abap_false "Todo: Get texts to work properly #4164 + include_extension_elements = abap_true + save_delta_handling_info = abap_true + use_xslt = abap_false + IMPORTING + xml_dom = li_xml_dom + EXCEPTIONS + conversion_error = 1 + OTHERS = 2 ). "#EC SUBRC_OK + + check_subrc_for( `TO_XML` ). + + ri_first_element ?= li_xml_dom->get_first_child( ). + li_elements = ri_first_element->get_elements_by_tag_name( 'ELEMENTS' ). + li_iterator = li_elements->create_iterator( ). + + DO. + li_element = li_iterator->get_next( ). + + IF li_element IS NOT BOUND. + EXIT. + ENDIF. + + li_children = li_element->get_children( ). + li_child_iterator = li_children->create_iterator( ). + + DO. + + li_element = li_child_iterator->get_next( ). + IF li_element IS NOT BOUND. + EXIT. + ENDIF. + + "Remove system container elements - causing too much trouble + "Todo: This is a bad hack, but obsolete if we can fix todo above + li_attributes = li_element->get_attributes( ). + lv_name = li_attributes->get_named_item( 'NAME' )->get_value( ). + IF lv_name(1) = '_'. + li_element->remove_node( ). + li_child_iterator->reset( ). + CONTINUE. + ENDIF. + + li_attributes->remove_named_item( 'CHGDTA' ). + + ENDDO. + + ENDDO. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_task TYPE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa=>ty_task_data, + lv_xml_string TYPE xstring, + li_task TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa. + + io_xml->read( EXPORTING iv_name = 'PDTS' + CHANGING cg_data = ls_task ). + + li_task = kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ=>create( + iv_objid = mv_objid + is_task_data = ls_task ). + + li_task->create_task( ). + li_task->change_wi_text( ). + li_task->change_method( ). + + lv_xml_string = extract_container( io_xml ). + li_task->import_container( lv_xml_string ). + + li_task->change_start_events( ). + li_task->change_terminating_events( ). + li_task->change_text( ). + + tadir_insert( iv_package ). + + li_task->save( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA li_task TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa. + + li_task = kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ=>load( mv_objid ). + li_task->clear_origin_data( ). + io_xml->add( iv_name = 'PDTS' + ig_data = li_task->get_definition( ) ). + + io_xml->add_xml( iv_name = 'CONTAINER' + ii_xml = get_container_xml( li_task ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_para IMPLEMENTATION. + METHOD unlock. + + CALL FUNCTION 'RS_ACCESS_PERMISSION' + EXPORTING + mode = 'FREE' + object = iv_paramid + object_class = 'PARA'. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. +* looks like "changed by user" is not stored in the database + rv_user = c_user_unknown. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + " We can't use FM RS_PARAMETER_DELETE because of the popup to confirm + "Therefore we have to reimplement most of the FMs logic + + DATA lv_paramid TYPE tpara-paramid. + + lv_paramid = ms_item-obj_name. + + CALL FUNCTION 'RS_ACCESS_PERMISSION' + EXPORTING + global_lock = abap_true + language_upd_exit = 'RS_PARAMETER_LANGUAGE_EXIT' " Name FuBa for maintenance language change + object = lv_paramid + object_class = ms_item-obj_type + suppress_language_check = space + EXCEPTIONS + canceled_in_corr = 1 + enqueued_by_user = 2 + enqueue_system_failure = 3 + illegal_parameter_values = 4 + locked_by_author = 5 + no_modify_permission = 6 + no_show_permission = 7 + permission_failure = 8 + request_language_denied = 9 + OTHERS = 10. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + SELECT COUNT(*) FROM cross + WHERE ( type = 'P' OR type = 'Q' ) AND name = lv_paramid. + IF sy-subrc = 0. + unlock( lv_paramid ). + zcx_abapgit_exception=>raise( 'PARA: Parameter is still used' ). + ELSE. + SELECT COUNT(*) FROM dd04l BYPASSING BUFFER + WHERE memoryid = lv_paramid + AND as4local = 'A'. + IF sy-subrc = 0. + unlock( lv_paramid ). + zcx_abapgit_exception=>raise( 'PARA: Parameter is still used' ). + ENDIF. + ENDIF. + + unlock( lv_paramid ). + + zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( + iv_object = 'PARA' + iv_obj_name = lv_paramid + iv_package = iv_package + iv_language = mv_language + iv_mode = zif_abapgit_cts_api=>c_transport_mode-delete ). + + DELETE FROM tpara WHERE paramid = lv_paramid. + DELETE FROM tparat WHERE paramid = lv_paramid. + + CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' + EXPORTING + object = lv_paramid + operation = 'DELETE' + type = 'CR'. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. +* see fm RS_PARAMETER_ADD and RS_PARAMETER_EDIT + + DATA: lv_mode TYPE c LENGTH 1, + ls_tpara TYPE tpara, + ls_tparat TYPE tparat. + + SELECT SINGLE * FROM tpara INTO ls_tpara + WHERE paramid = ms_item-obj_name. "#EC CI_GENBUFF + IF sy-subrc = 0. + lv_mode = 'M'. + ELSE. + lv_mode = 'I'. + ENDIF. + + io_xml->read( EXPORTING iv_name = 'TPARA' + CHANGING cg_data = ls_tpara ). + + CALL FUNCTION 'RS_CORR_INSERT' + EXPORTING + object = ms_item-obj_name + object_class = 'PARA' + mode = lv_mode + global_lock = abap_true + devclass = iv_package + master_language = mv_language + suppress_dialog = abap_true + EXCEPTIONS + cancelled = 1 + permission_failure = 2 + unknown_objectclass = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + MODIFY tpara FROM ls_tpara. "#EC CI_SUBRC + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING iv_name = 'TPARAT' + CHANGING cg_data = ls_tparat ). + + MODIFY tparat FROM ls_tparat. "#EC CI_SUBRC + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_paramid TYPE tpara-paramid. + SELECT SINGLE paramid FROM tpara INTO lv_paramid + WHERE paramid = ms_item-obj_name. "#EC CI_GENBUFF + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' + iv_argument = ms_item-obj_name + iv_prefix = 'PA' ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_tpara TYPE tpara, + ls_tparat TYPE tparat. + + SELECT SINGLE * FROM tpara INTO ls_tpara + WHERE paramid = ms_item-obj_name. "#EC CI_GENBUFF + IF sy-subrc <> 0. + RETURN. + ENDIF. + + SELECT SINGLE * FROM tparat INTO ls_tparat + WHERE paramid = ms_item-obj_name + AND sprache = mv_language. "#EC CI_GENBUFF "#EC CI_SUBRC + + io_xml->add( iv_name = 'TPARA' + ig_data = ls_tpara ). + + io_xml->add( + iv_name = 'TPARAT' + ig_data = ls_tparat ). + " Here only the original language is serialized, + " so it should be present for the moment. LXEs are just translations + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_otgr IMPLEMENTATION. + METHOD instantiate_and_lock_otgr. + DATA: + lv_new TYPE abap_bool, + lv_name TYPE cls_attribute_name, + lv_state TYPE cls_type_group-activation_state. + + SELECT SINGLE name FROM cls_type_group INTO lv_name WHERE name = ms_item-obj_name. + IF sy-subrc = 0. + lv_new = abap_false. + lv_state = cl_pak_wb_domains=>co_activation_state-invalid. + ELSE. + lv_new = abap_true. + lv_state = cl_pak_wb_domains=>co_activation_state-active. + ENDIF. + lv_name = ms_item-obj_name. + + TRY. + CREATE OBJECT ro_otgr + EXPORTING + im_name = lv_name + im_new = lv_new + im_activation_state = lv_state. + CATCH cx_pak_invalid_data + cx_pak_not_authorized + cx_pak_invalid_state + cx_pak_wb_object_locked. + zcx_abapgit_exception=>raise( |OTGR { lv_name }: error while instantiating CL_CLS_OBJECT_TYPE_GROUP| ). + ENDTRY. + + IF lv_new = abap_false. + TRY. + ro_otgr->if_pak_wb_object~lock_and_refresh( ). + CATCH cx_pak_invalid_data + cx_pak_not_authorized + cx_pak_invalid_state + cx_pak_wb_object_locked. + zcx_abapgit_exception=>raise( |OTGR { lv_name }: could not acquire lock| ). + ENDTRY. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + SELECT SINGLE changed_by FROM cls_type_group INTO rv_user + WHERE name = ms_item-obj_name + AND activation_state = cl_pak_wb_domains=>co_activation_state-active. + + IF rv_user IS INITIAL. + SELECT SINGLE created_by FROM cls_type_group INTO rv_user + WHERE name = ms_item-obj_name + AND activation_state = cl_pak_wb_domains=>co_activation_state-active. + ENDIF. + + IF rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + DATA: lo_otgr TYPE REF TO cl_cls_object_type_group, + lx_pak_error TYPE REF TO cx_root, + lv_text TYPE string. + + lo_otgr = instantiate_and_lock_otgr( ). + + TRY. + lo_otgr->if_pak_wb_object~delete( ). + lo_otgr->if_pak_wb_object~save( ). + lo_otgr->unlock( ). + + CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. + lo_otgr->unlock( ). + + lv_text = lx_pak_error->get_text( ). + zcx_abapgit_exception=>raise( |OTGR { ms_item-obj_name }: delete: { lv_text }| ). + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + DATA: ls_otgr TYPE ty_otgr, + lo_otgr TYPE REF TO cl_cls_object_type_group, + lx_pak_error TYPE REF TO cx_root, + lv_text TYPE string, + lv_main_lang TYPE sy-langu, + lo_parents TYPE REF TO data. + + FIELD-SYMBOLS: LIKE LINE OF ls_otgr-texts, + LIKE LINE OF ls_otgr-elements, + TYPE any, + TYPE any, + TYPE ANY TABLE. + + io_xml->read( EXPORTING iv_name = 'OTGR' + CHANGING cg_data = ls_otgr ). + + LOOP AT ls_otgr-texts ASSIGNING . + -activation_state = cl_pak_wb_domains=>co_activation_state-inactive. + " Removed in the method serialize. + -name = ms_item-obj_name. + ENDLOOP. + + " Parents (cls_tygr_parent) does not exist in lower releases + TRY. + CREATE DATA lo_parents TYPE TABLE OF ('CLS_TYGR_PARENT'). + ASSIGN lo_parents->* TO . + CATCH cx_sy_create_data_error ##NO_HANDLER. + ENDTRY. + + IF IS ASSIGNED. + io_xml->read( EXPORTING iv_name = 'PARENTS' + CHANGING cg_data = ). + + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'ACTIVATION_STATE' OF STRUCTURE TO . + IF sy-subrc = 0. + = cl_pak_wb_domains=>co_activation_state-inactive. + ENDIF. + ASSIGN COMPONENT 'OBJ_TYPE_GROUP' OF STRUCTURE TO . + IF sy-subrc = 0. + " Removed in the method serialize. + = ms_item-obj_name. + ENDIF. + ENDLOOP. + ENDIF. + + LOOP AT ls_otgr-elements ASSIGNING . + -activation_state = cl_pak_wb_domains=>co_activation_state-inactive. + " Removed in the method serialize. + -obj_type_group = ms_item-obj_name. + ENDLOOP. + + tadir_insert( iv_package ). + + lo_otgr = instantiate_and_lock_otgr( ). + + TRY. + lo_otgr->if_cls_object_type_group~set_proxy_filter( ls_otgr-cls_type_group-proxy_flag ). + lo_otgr->if_cls_object_type_group~set_elements( ls_otgr-elements ). + + IF IS ASSIGNED. + CALL METHOD lo_otgr->('IF_CLS_OBJECT_TYPE_GROUP~SET_PARENT_GROUPS') + EXPORTING + im_parent_groups = . + ENDIF. + + lv_main_lang = lo_otgr->if_pak_wb_object~get_master_language( ). + READ TABLE ls_otgr-texts WITH KEY langu = lv_main_lang ASSIGNING . + IF sy-subrc = 0. + lo_otgr->set_description( -text ). + " ELSE. + " Do we want to clear the main language description if not present in the XML content? + " Main language is non-deterministic - it depends on sy-langu, so rather don't touch + " description if the main language is not present + " Perhaps, we can display some sort of a message but how? + ENDIF. + + set_default_package( iv_package ). + + lo_otgr->if_pak_wb_object~save( ). + + lo_otgr->if_pak_wb_object~activate( ). + lo_otgr->unlock( ). + + CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. + lo_otgr->unlock( ). + + lv_text = lx_pak_error->get_text( ). + zcx_abapgit_exception=>raise( |OTGR { ms_item-obj_name }: deserialize: { lv_text }| ). + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_object~exists. + rv_bool = cl_cls_object_type_group=>exists_object_type_group( ms_item-obj_name ). + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ECLS_ATTRIBUTE' + iv_argument = |{ ms_item-obj_name }*| ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + DATA: lv_text TYPE string, + lv_name TYPE ty_otgr-cls_type_group, + ls_otgr TYPE ty_otgr, + lo_otgr TYPE REF TO cl_cls_object_type_group, + lx_pak_error TYPE REF TO cx_root, + lo_parents TYPE REF TO data. + + FIELD-SYMBOLS: LIKE LINE OF ls_otgr-texts, + LIKE LINE OF ls_otgr-elements, + TYPE any, + TYPE any, + TYPE ANY TABLE. + + lo_otgr = instantiate_and_lock_otgr( ). + +* Description part 1: +* Dealing with Description of OTGR objects is problematic. +* The API supports setting of main language only and +* if we want to save also translations we would have to implement +* our own logic for merging and activation. To keep it simple stupid +* the current version focuses on the main language only. +* If anybody ever runs into the need to version also translation, +* ask the maintainers of CL_CLS_OBJECT_TYPE_GROUP to add a method for it. +* +* However, the XML content will pretend we support also translations, +* so if someone adds support for them in future, there will be no format change. + APPEND INITIAL LINE TO ls_otgr-texts ASSIGNING . + + " Parents (cls_tygr_parent) does not exist in lower releases + TRY. + CREATE DATA lo_parents TYPE TABLE OF ('CLS_TYGR_PARENT'). + ASSIGN lo_parents->* TO . + CATCH cx_sy_create_data_error ##NO_HANDLER. + ENDTRY. + + TRY. + ls_otgr-cls_type_group-name = lo_otgr->if_cls_object_type_group~get_name( ). + ls_otgr-cls_type_group-proxy_flag = lo_otgr->if_cls_object_type_group~get_proxy_filter( ). + + TRY. + CALL METHOD lo_otgr->('GET_ELEMENTS') + EXPORTING + im_explicit_elements_only = abap_true " doesn't exist on lower releases. Eg. 752 SP04 + IMPORTING + ex_elements = ls_otgr-elements. + + CATCH cx_sy_dyn_call_param_not_found. + + lo_otgr->get_elements( IMPORTING ex_elements = ls_otgr-elements ). + + ENDTRY. + + " Remove children since they are created automatically (by the child group) + LOOP AT ls_otgr-elements ASSIGNING . + SELECT SINGLE name FROM cls_type_group INTO lv_name WHERE name = -type. + IF sy-subrc = 0. + DELETE ls_otgr-elements. + ENDIF. + ENDLOOP. + + IF IS ASSIGNED. + CALL METHOD lo_otgr->('IF_CLS_OBJECT_TYPE_GROUP~GET_PARENT_GROUPS') + EXPORTING + im_explicit_parents_only = abap_true + IMPORTING + ex_parent_groups = . + ENDIF. + + " Beware: the following method returns the main language description only if the object is locked! + -text = lo_otgr->if_cls_object_type_group~get_description( ). + -langu = lo_otgr->if_pak_wb_object~get_master_language( ). + + lo_otgr->unlock( ). + + CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. + lo_otgr->unlock( ). + + lv_text = lx_pak_error->get_text( ). + zcx_abapgit_exception=>raise( |OTGR { ms_item-obj_name }: serialize: { lv_text }| ). + ENDTRY. + + CLEAR: ls_otgr-cls_type_group-created_by, + ls_otgr-cls_type_group-created_on, + ls_otgr-cls_type_group-changed_by, + ls_otgr-cls_type_group-changed_on. + +* Description part 2: +* +* lt_lang_sel TYPE RANGE OF langu, +* ls_lang_sel LIKE LINE OF lt_lang_sel, +* +* IF io_xml->i18n_params( )-main_language_only = abap_true. +* ls_lang_sel-low = mv_language. +* ls_lang_sel-sign = 'I'. +* ls_lang_sel-option = 'EQ'. +* ENDIF. +* +* SELECT * FROM cls_type_groupt INTO TABLE ls_otgr-texts +* WHERE name = ms_item-obj_name +* AND activation_state = 'A' +* AND langu in lt_lang_sel. +* +* Description ideas end + + LOOP AT ls_otgr-texts ASSIGNING . + " Not necessary as we serialize only Active + CLEAR -activation_state. + " Not necessary as we have it in the root XML node + CLEAR -name. + ENDLOOP. + + LOOP AT ls_otgr-elements ASSIGNING . + " Not necessary as we serialize only Active + CLEAR -activation_state. + " Not necessary as we have it in the root XML node + CLEAR -obj_type_group. + ENDLOOP. + + io_xml->add( iv_name = 'OTGR' + ig_data = ls_otgr ). + + IF IS ASSIGNED. + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'ACTIVATION_STATE' OF STRUCTURE TO . + IF sy-subrc = 0. + " Not necessary as we serialize only Active + CLEAR . + ENDIF. + ASSIGN COMPONENT 'OBJ_TYPE_GROUP' OF STRUCTURE TO . + IF sy-subrc = 0. + " Not necessary as we have it in the root XML node + CLEAR . + ENDIF. + ENDLOOP. + + io_xml->add( iv_name = 'PARENTS' + ig_data = ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_odso IMPLEMENTATION. + + METHOD constructor. + + DATA: lr_details TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE DATA lr_details TYPE ('BAPI6116'). + CATCH cx_sy_create_data_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname + OF STRUCTURE cg_metadata + TO . + ASSERT sy-subrc = 0. + + CLEAR: . + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_dsonam TYPE c LENGTH 30, + ls_return TYPE bapiret2, + lr_details TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + CREATE DATA lr_details TYPE ('BAPI6116'). + + ASSIGN lr_details->* TO . + + lv_dsonam = ms_item-obj_name. + + CALL FUNCTION 'BAPI_ODSO_GETDETAIL' + EXPORTING + odsobject = lv_dsonam + IMPORTING + details = + return = ls_return. + + IF ls_return-type = 'E'. + zcx_abapgit_exception=>raise( |Error when getting changed by of ODSO: { ls_return-message }| ). + ENDIF. + + ASSIGN COMPONENT 'TSTPNM' OF STRUCTURE TO . + + rv_user = . + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_odsonam TYPE c LENGTH 30, + lv_objname TYPE sobj_name, + lo_collection TYPE REF TO object, + lt_msg TYPE STANDARD TABLE OF bal_s_msg, + ls_msg TYPE bal_s_msg. + + CREATE OBJECT lo_collection TYPE ('CL_RSD_ODSO_COLLECTION'). + + lv_odsonam = ms_item-obj_name. + lv_objname = ms_item-obj_name. + + TRY. + CALL METHOD lo_collection->('ADD_TLOGO') + EXPORTING + i_objnm = lv_objname + i_modify = abap_true + i_delete = abap_true. + + CALL METHOD lo_collection->('DELETE'). + + CALL METHOD ('CL_RSO_APPLICATION_LOG')=>('APPL_LOG_MSG_READ') + IMPORTING + e_t_msg = lt_msg. + + READ TABLE lt_msg WITH KEY msgty = 'E' INTO ls_msg. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( + |Error when deleting ODSO: { ms_item-obj_name } { ls_msg-msgv1 } { ls_msg-msgv2 }| ). + ENDIF. + + CATCH cx_root. + zcx_abapgit_exception=>raise( |Canceled deletion of ODSO: { ms_item-obj_name }| ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_dsonam TYPE c LENGTH 30, + lr_details TYPE REF TO data, + lr_infoobjects TYPE REF TO data, + lr_navigation TYPE REF TO data, + lr_indexes TYPE REF TO data, + lr_index_iobj TYPE REF TO data, + lt_return TYPE STANDARD TABLE OF bapiret2, + ls_return TYPE bapiret2. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE. + + CREATE DATA lr_details TYPE ('BAPI6116'). + CREATE DATA lr_infoobjects TYPE STANDARD TABLE OF ('BAPI6116IO'). + CREATE DATA lr_navigation TYPE STANDARD TABLE OF ('BAPI6116NA'). + CREATE DATA lr_indexes TYPE STANDARD TABLE OF ('BAPI6116IN'). + CREATE DATA lr_index_iobj TYPE STANDARD TABLE OF ('BAPI6116II'). + + ASSIGN lr_details->* TO . + ASSIGN lr_infoobjects->* TO . + ASSIGN lr_navigation->* TO . + ASSIGN lr_indexes->* TO . + ASSIGN lr_index_iobj->* TO . + + io_xml->read( EXPORTING iv_name = 'ODSO' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'INFOOBJECTS' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'NAVIGATION' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'INDEXES' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'INDEX_IOBJ' + CHANGING cg_data = ). + TRY. + + ASSIGN COMPONENT 'ODSOBJECT' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + IF zif_abapgit_object~exists( ) = abap_false. + CALL FUNCTION 'BAPI_ODSO_CREATE' + EXPORTING + details = + IMPORTING + odsobject = lv_dsonam + TABLES + infoobjects = + navigationattributes = + indexes = + indexesinfoobjects = + return = lt_return. + ELSE. + CALL FUNCTION 'BAPI_ODSO_CHANGE' + EXPORTING + odsobject = + details = + TABLES + infoobjects = + navigationattributes = + indexes = + indexesinfoobjects = + return = lt_return. + ENDIF. + + CATCH cx_sy_dyn_call_illegal_func. + zcx_abapgit_exception=>raise( |Necessary BW function modules not found or object not supported| ). + ENDTRY. + + READ TABLE lt_return WITH KEY type = 'E' INTO ls_return. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( |Error when creating ODSO: { ls_return-message }| ). + ENDIF. + + CALL FUNCTION 'BAPI_ODSO_ACTIVATE' + EXPORTING + odsobject = + TABLES + return = lt_return. + + READ TABLE lt_return WITH KEY type = 'E' INTO ls_return. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( |Error when activating ODSO: { ls_return-message }| ). + ENDIF. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_iobjnm TYPE c LENGTH 30. + + SELECT SINGLE odsobject + FROM ('RSDODSO') + INTO lv_iobjnm + WHERE odsobject = ms_item-obj_name. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + + DATA: lv_dsona TYPE c LENGTH 30, + lo_odso TYPE REF TO object, + lv_isact TYPE abap_bool. + + lv_dsona = ms_item-obj_name. + + CALL METHOD ('CL_RSD_ODSO')=>('FACTORY') + EXPORTING + i_odsobject = lv_dsona + RECEIVING + r_r_odso = lo_odso. + + CALL METHOD lo_odso->('IS_ACTIVE') + RECEIVING + r_is_active = lv_isact. + + rv_active = lv_isact. + + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_object TYPE eqegraarg. + + lv_object = ms_item-obj_name. + OVERLAY lv_object WITH ' '. + lv_object = lv_object && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'RSD_S_PROV' + iv_argument = lv_object ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_dsonam TYPE c LENGTH 30, + lr_details TYPE REF TO data, + lr_infoobjects TYPE REF TO data, + lr_navigation TYPE REF TO data, + lr_indexes TYPE REF TO data, + lr_index_iobj TYPE REF TO data, + ls_return TYPE bapiret2. + + FIELD-SYMBOLS: + TYPE any, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE. + + CREATE DATA lr_details TYPE ('BAPI6116'). + CREATE DATA lr_infoobjects TYPE STANDARD TABLE OF ('BAPI6116IO'). + CREATE DATA lr_navigation TYPE STANDARD TABLE OF ('BAPI6116NA'). + CREATE DATA lr_indexes TYPE STANDARD TABLE OF ('BAPI6116IN'). + CREATE DATA lr_index_iobj TYPE STANDARD TABLE OF ('BAPI6116II'). + + ASSIGN lr_details->* TO . + ASSIGN lr_infoobjects->* TO . + ASSIGN lr_navigation->* TO . + ASSIGN lr_indexes->* TO . + ASSIGN lr_index_iobj->* TO . + + lv_dsonam = ms_item-obj_name. + + CALL FUNCTION 'BAPI_ODSO_GETDETAIL' + EXPORTING + odsobject = lv_dsonam + IMPORTING + details = + return = ls_return + TABLES + infoobjects = + navigationattributes = + indexes = + indexesinfoobjects = . + + IF ls_return-type = 'E'. + zcx_abapgit_exception=>raise( |Error when getting details of ODSO: { ls_return-message }| ). + ENDIF. + + clear_field( EXPORTING iv_fieldname = 'TSTPNM' + CHANGING cg_metadata = ). + + clear_field( EXPORTING iv_fieldname = 'TIMESTMP' + CHANGING cg_metadata = ). + + clear_field( EXPORTING iv_fieldname = 'CONTTIMESTMP' + CHANGING cg_metadata = ). + + clear_field( EXPORTING iv_fieldname = 'OWNER' + CHANGING cg_metadata = ). + + io_xml->add( iv_name = 'ODSO' + ig_data = ). + + io_xml->add( iv_name = 'INFOOBJECTS' + ig_data = ). + + io_xml->add( iv_name = 'NAVIGATION' + ig_data = ). + + io_xml->add( iv_name = 'INDEXES' + ig_data = ). + + io_xml->add( iv_name = 'INDEX_IOBJ' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_oa2p IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_profile = is_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_persist TYPE REF TO object, + lr_wb TYPE REF TO data, + lo_profile TYPE REF TO object, + lv_profile_key TYPE seu_objkey. + + FIELD-SYMBOLS: TYPE any. + lv_profile_key = mv_profile. + CREATE OBJECT lo_persist TYPE ('CL_OA2P_OBJECT_PERSIST'). + + CREATE OBJECT lo_profile TYPE ('CL_OA2P_OBJECT_DATA'). + CREATE DATA lr_wb TYPE REF TO ('IF_WB_OBJECT_DATA_MODEL'). + ASSIGN lr_wb->* TO . + ?= lo_profile. + + TRY. + CALL METHOD lo_persist->('IF_WB_OBJECT_PERSIST~GET') + EXPORTING + p_object_key = lv_profile_key " Object Key + p_version = 'A' " Version (Active/Inactive) + CHANGING + p_object_data = . " Object Data + CATCH cx_swb_object_does_not_exist. + zcx_abapgit_exception=>raise( |OAuth2 Profile { lv_profile_key } doesn't exist.| ). + CATCH cx_swb_exception. + zcx_abapgit_exception=>raise( |Error when getting details of OAuth2 Profile { lv_profile_key }.| ). + ENDTRY. + + lo_profile = . + CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~GET_CHANGED_BY') + RECEIVING + p_user_name = rv_user. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + CONSTANTS: lc_actvt TYPE c LENGTH 2 VALUE `06`. + + DATA: lo_persist TYPE REF TO object, + lv_profile_key TYPE seu_objkey. + + "authority check + AUTHORITY-CHECK OBJECT 'S_OA2C_ADM' + ID 'ACTVT' FIELD lc_actvt ##AUTH_OBJ_OK. + IF sy-subrc <> 0. + MESSAGE e463(01) WITH mv_profile INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + "delete profile + lv_profile_key = mv_profile. + CREATE OBJECT lo_persist TYPE ('CL_OA2P_OBJECT_PERSIST'). + + TRY. + CALL METHOD lo_persist->('IF_WB_OBJECT_PERSIST~DELETE') + EXPORTING + p_object_key = lv_profile_key. " Object Key + CATCH cx_swb_object_does_not_exist ##NO_HANDLER. + CATCH cx_swb_exception. + zcx_abapgit_exception=>raise( |Error when deleting OAuth2 Profile { lv_profile_key }.| ). + ENDTRY. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lo_persist TYPE REF TO object, + lo_profile TYPE REF TO object, + lr_wb TYPE REF TO data, + lr_profile_data TYPE REF TO data. + FIELD-SYMBOLS: TYPE data, + TYPE any. + + CREATE DATA lr_profile_data TYPE ('OA2C_SX_OA2P_OBJECT_DATA'). + ASSIGN lr_profile_data->* TO . + + io_xml->read( EXPORTING iv_name = 'PROFILE' + CHANGING cg_data = ). + + CREATE OBJECT lo_profile TYPE ('CL_OA2P_OBJECT_DATA'). + CREATE DATA lr_wb TYPE REF TO ('IF_WB_OBJECT_DATA_MODEL'). + ASSIGN lr_wb->* TO . + ?= lo_profile. + + CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_DATA') + EXPORTING + p_data = . + + CREATE OBJECT lo_persist TYPE ('CL_OA2P_OBJECT_PERSIST'). + TRY. + CALL METHOD lo_persist->('IF_WB_OBJECT_PERSIST~SAVE') + EXPORTING + p_object_data = . " Object Data + CATCH cx_swb_exception. + zcx_abapgit_exception=>raise( |Error deserialize profile { mv_profile }.| ). + ENDTRY. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL METHOD ('CL_OA2P_OBJECT_PERSIST')=>('CHECK_EXISTS_ON_DB') + EXPORTING + i_profile = mv_profile + RECEIVING + r_exists = rv_bool. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_profile_name TYPE eqegraarg, + lv_lock_number TYPE i, + lt_locks TYPE STANDARD TABLE OF seqg3. + + lv_profile_name = mv_profile. + + CALL FUNCTION 'ENQUEUE_READ' + EXPORTING + gclient = sy-mandt " Client + gname = 'OA2C_PROFILES' " Granularity name (-> table name) + garg = lv_profile_name " Granularity value(->values of key fields) + IMPORTING + number = lv_lock_number + TABLES + enq = lt_locks. " Number of chosen lock entries + rv_is_locked = boolc( lv_lock_number > 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_persist TYPE REF TO object, + lo_profile TYPE REF TO object, + lv_profile_key TYPE seu_objkey, + lr_profile_data TYPE REF TO data, + lr_wb TYPE REF TO data. + + FIELD-SYMBOLS: TYPE data, + TYPE any, + TYPE any. + + CREATE DATA lr_profile_data TYPE ('OA2C_SX_OA2P_OBJECT_DATA'). + ASSIGN lr_profile_data->* TO . + lv_profile_key = mv_profile. + CREATE OBJECT lo_persist TYPE ('CL_OA2P_OBJECT_PERSIST'). + CREATE OBJECT lo_profile TYPE ('CL_OA2P_OBJECT_DATA'). + CREATE DATA lr_wb TYPE REF TO ('IF_WB_OBJECT_DATA_MODEL'). + ASSIGN lr_wb->* TO . + ?= lo_profile. + TRY. + CALL METHOD lo_persist->('IF_WB_OBJECT_PERSIST~GET') + EXPORTING + p_object_key = lv_profile_key " Object Key + p_version = 'A' " Version (Active/Inactive) + CHANGING + p_object_data = . " Object Data + CATCH cx_swb_object_does_not_exist. + zcx_abapgit_exception=>raise( |OAuth2 Profile { lv_profile_key } doesn't exist.| ). + CATCH cx_swb_exception. + zcx_abapgit_exception=>raise( |Error when getting details of OAuth2 Profile { lv_profile_key }.| ). + ENDTRY. + + "remove system specific information + lo_profile = . + CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_CHANGED_BY') + EXPORTING + p_user_name = ''. + CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_CHANGED_ON') + EXPORTING + p_date = '00000000' + p_time = '000000'. + CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_CREATED_BY') + EXPORTING + p_user_name = ''. + CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_CREATED_ON') + EXPORTING + p_date = '00000000' + p_time = '000000'. + + CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~GET_DATA') + IMPORTING + p_data = . + + "remove runtime information + ASSIGN COMPONENT 'O_SPECIFICS' OF STRUCTURE TO . + CLEAR . + + io_xml->add( iv_name = 'PROFILE' + ig_data = ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_nspc IMPLEMENTATION. + METHOD add_to_transport. + + DATA: li_sap_package TYPE REF TO zif_abapgit_sap_package. + + li_sap_package = zcl_abapgit_factory=>get_sap_package( iv_package ). + + IF li_sap_package->are_changes_recorded_in_tr_req( ) = abap_true. + corr_insert( iv_package ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_component = replace( val = is_item-obj_name + sub = '/' + with = '' + occ = 0 ). + + ENDMETHOD. + METHOD deserialize_sw_component. + + DATA: + ls_cvers_old TYPE cvers, + ls_cvers_new TYPE cvers, + ls_cvers_ref TYPE cvers_ref. + + ii_xml->read( EXPORTING iv_name = 'CVERS' + CHANGING cg_data = ls_cvers_new ). + + ii_xml->read( EXPORTING iv_name = 'CVERS_REF' + CHANGING cg_data = ls_cvers_ref ). + + IF ls_cvers_new IS NOT INITIAL. + SELECT SINGLE * FROM cvers INTO ls_cvers_old WHERE component = mv_component. + IF sy-subrc = 0. + IF ls_cvers_old <> ls_cvers_new. + zcx_abapgit_exception=>raise( `Update of software component not supported.` + && ` Use Software Update Manager (SUM)` ). + ENDIF. + ELSE. + INSERT cvers FROM ls_cvers_new. + ENDIF. + ENDIF. + + IF ls_cvers_ref IS NOT INITIAL. + MODIFY cvers_ref FROM ls_cvers_ref. + IF sy-subrc <> 0. + INSERT cvers_ref FROM ls_cvers_ref. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD deserialize_texts. + + DATA: + ls_trnspacett TYPE trnspacett, + lt_i18n_langs TYPE TABLE OF langu, + lt_cvers_refs TYPE TABLE OF cvers_ref, + ls_cvers_ref TYPE cvers_ref, + lt_nspc_texts TYPE ty_nspc_texts. + + FIELD-SYMBOLS: + LIKE LINE OF lt_i18n_langs, + LIKE LINE OF lt_nspc_texts. + + ii_xml->read( EXPORTING iv_name = 'I18N_LANGS' + CHANGING cg_data = lt_i18n_langs ). + + ii_xml->read( EXPORTING iv_name = 'NSPC_TEXTS' + CHANGING cg_data = lt_nspc_texts ). + + ii_xml->read( EXPORTING iv_name = 'CVERS_REFS' + CHANGING cg_data = lt_cvers_refs ). + + SORT lt_i18n_langs. + SORT lt_nspc_texts BY spras. " Optimization + SORT lt_cvers_refs BY langu. " Optimization + + LOOP AT lt_i18n_langs ASSIGNING . + ls_trnspacett-namespace = iv_namespace. + READ TABLE lt_nspc_texts ASSIGNING WITH KEY spras = . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Cannot find language { } in XML| ). + ENDIF. + MOVE-CORRESPONDING TO ls_trnspacett. + + MODIFY trnspacett FROM ls_trnspacett. + IF sy-subrc <> 0. + INSERT trnspacett FROM ls_trnspacett. + ENDIF. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error upserting text for namespace| ). + ENDIF. + + READ TABLE lt_cvers_refs INTO ls_cvers_ref WITH KEY langu = . + IF sy-subrc = 0. + MODIFY cvers_ref FROM ls_cvers_ref. + IF sy-subrc <> 0. + INSERT cvers_ref FROM ls_cvers_ref. + ENDIF. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error upserting text for software component| ). + ENDIF. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD serialize_sw_component. + + DATA: + ls_cvers TYPE cvers, + ls_cvers_ref TYPE cvers_ref. + + SELECT SINGLE * FROM cvers INTO ls_cvers WHERE component = mv_component. + IF sy-subrc = 0. + ii_xml->add( iv_name = 'CVERS' + ig_data = ls_cvers ). + ENDIF. + + SELECT SINGLE * FROM cvers_ref INTO ls_cvers_ref WHERE component = mv_component AND langu = mv_language. + IF sy-subrc = 0. + ii_xml->add( iv_name = 'CVERS_REF' + ig_data = ls_cvers_ref ). + ENDIF. + + ENDMETHOD. + METHOD serialize_texts. + + DATA: + ls_trnspacett TYPE trnspacett, + lt_nspc_texts TYPE ty_nspc_texts, + lt_cvers_refs TYPE TABLE OF cvers_ref, + lt_i18n_langs TYPE TABLE OF langu. + + FIELD-SYMBOLS: + LIKE LINE OF lt_i18n_langs, + LIKE LINE OF lt_nspc_texts. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + " Collect additional languages, skip main lang - it was serialized already + SELECT DISTINCT spras AS langu FROM trnspacett INTO TABLE lt_i18n_langs + WHERE namespace = ms_item-obj_name AND spras <> mv_language + ORDER BY langu. "#EC CI_SUBRC + + LOOP AT lt_i18n_langs ASSIGNING . + SELECT SINGLE * FROM trnspacett INTO ls_trnspacett + WHERE namespace = ms_item-obj_name AND spras = . + IF sy-subrc = 0. + APPEND INITIAL LINE TO lt_nspc_texts ASSIGNING . + MOVE-CORRESPONDING ls_trnspacett TO . + ENDIF. + + SELECT * FROM cvers_ref APPENDING TABLE lt_cvers_refs + WHERE component = mv_component AND langu = + ORDER BY PRIMARY KEY. + ENDLOOP. + + SORT lt_i18n_langs ASCENDING. + SORT lt_nspc_texts BY spras ASCENDING. + SORT lt_cvers_refs. + + IF lines( lt_i18n_langs ) > 0. + ii_xml->add( iv_name = 'I18N_LANGS' + ig_data = lt_i18n_langs ). + + ii_xml->add( iv_name = 'NSPC_TEXTS' + ig_data = lt_nspc_texts ). + + ii_xml->add( iv_name = 'CVERS_REFS' + ig_data = lt_cvers_refs ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + SELECT SINGLE changeuser FROM trnspacet INTO rv_user + WHERE namespace = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + RETURN. " not supported + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + ls_nspc TYPE ty_nspc, + ls_nspc_text TYPE ty_nspc_text, + lv_modifiable TYPE abap_bool, + ls_trnspacet TYPE trnspacet, + ls_trnspacett TYPE trnspacett. + + io_xml->read( EXPORTING iv_name = 'NSPC' + CHANGING cg_data = ls_nspc ). + + io_xml->read( EXPORTING iv_name = 'NSPC_TEXT' + CHANGING cg_data = ls_nspc_text ). + + add_to_transport( iv_package ). + + SELECT SINGLE * FROM trnspacet INTO ls_trnspacet WHERE namespace = ls_nspc-namespace. + IF sy-subrc = 0. + " For existing namespace, check if it's modifiable (SE03) + SELECT SINGLE editflag FROM trnspace INTO lv_modifiable WHERE namespace = ls_nspc-namespace. + IF sy-subrc = 0 AND lv_modifiable = abap_false. + zcx_abapgit_exception=>raise( |Namespace is not modifiable| ). + ENDIF. + + " keep existing role + ls_trnspacet-replicense = ls_nspc-replicense. + ls_trnspacet-sscrflag = ls_nspc-sscrflag. + ls_trnspacet-sapflag = ls_nspc-sapflag. + ls_trnspacet-gen_only = ls_nspc-gen_only. + ls_trnspacet-changeuser = sy-uname. + ls_trnspacet-changedate = sy-datum. + MODIFY trnspacet FROM ls_trnspacet. + ELSE. + MOVE-CORRESPONDING ls_nspc TO ls_trnspacet. + ls_trnspacet-role = 'C'. " customer repair license + ls_trnspacet-changeuser = sy-uname. + ls_trnspacet-changedate = sy-datum. + INSERT trnspacet FROM ls_trnspacet. + ENDIF. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error upserting namespace| ). + ENDIF. + + SELECT SINGLE * FROM trnspacett INTO ls_trnspacett + WHERE namespace = ls_nspc-namespace AND spras = mv_language. + IF sy-subrc = 0. + ls_trnspacett-descriptn = ls_nspc_text-descriptn. + ls_trnspacett-owner = ls_nspc_text-owner. + MODIFY trnspacett FROM ls_trnspacett. + ELSE. + MOVE-CORRESPONDING ls_nspc_text TO ls_trnspacett. + ls_trnspacett-namespace = ls_nspc-namespace. + INSERT trnspacett FROM ls_trnspacett. + ENDIF. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error upserting text for namespace| ). + ENDIF. + + deserialize_texts( ii_xml = io_xml + iv_namespace = ls_nspc-namespace ). + + deserialize_sw_component( io_xml ). + + " Fill trnspace and trnspacel tables + CALL FUNCTION 'TR_ACTIVATE_NAMESPACE' + EXPORTING + iv_namespace = ls_nspc-namespace + EXCEPTIONS + deletion_not_allowed = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error activating namespace| ). + ENDIF. + + " Make namespace modifiable + UPDATE trnspace SET editflag = abap_true WHERE namespace = ls_nspc-namespace. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA lv_namespace TYPE trnspace-namespace. + + lv_namespace = ms_item-obj_name. + + CALL FUNCTION 'TR_CHECK_NAMESPACE' + EXPORTING + iv_namespace = lv_namespace + EXCEPTIONS + namespace_not_valid = 1 + OTHERS = 2. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = zif_abapgit_object~exists( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Launch general maintenance for namespaces + CALL FUNCTION 'VIEW_MAINTENANCE_CALL' + EXPORTING + action = 'S' + view_name = 'V_TRNSPACE' + no_warning_for_clientindep = 'X' + variant_for_selection = 'STANDARD' + EXCEPTIONS + client_reference = 1 + foreign_lock = 2 + invalid_action = 3 + no_clientindependent_auth = 4 + no_database_function = 5 + no_editor_function = 6 + no_show_auth = 7 + no_tvdir_entry = 8 + no_upd_auth = 9 + only_show_allowed = 10 + system_failure = 11 + unknown_field_in_dba_sellist = 12 + view_not_found = 13 + OTHERS = 14. + + rv_exit = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + ls_nspc TYPE ty_nspc, + ls_nspc_text TYPE ty_nspc_text. + + SELECT SINGLE * FROM trnspacet INTO CORRESPONDING FIELDS OF ls_nspc + WHERE namespace = ms_item-obj_name. + + SELECT SINGLE * FROM trnspacett INTO CORRESPONDING FIELDS OF ls_nspc_text + WHERE namespace = ms_item-obj_name AND spras = mv_language. + + io_xml->add( iv_name = 'NSPC' + ig_data = ls_nspc ). + + io_xml->add( iv_name = 'NSPC_TEXT' + ig_data = ls_nspc_text ). + + serialize_texts( io_xml ). + + serialize_sw_component( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_nrob IMPLEMENTATION. + METHOD delete_intervals. + + DATA: lv_error TYPE c LENGTH 1, + ls_error TYPE inrer, + lt_list TYPE STANDARD TABLE OF inriv WITH DEFAULT KEY, + lt_error_iv TYPE STANDARD TABLE OF inriv WITH DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF lt_list. + CALL FUNCTION 'NUMBER_RANGE_INTERVAL_LIST' + EXPORTING + object = iv_object + TABLES + interval = lt_list + EXCEPTIONS + nr_range_nr1_not_found = 1 + nr_range_nr1_not_intern = 2 + nr_range_nr2_must_be_space = 3 + nr_range_nr2_not_extern = 4 + nr_range_nr2_not_found = 5 + object_not_found = 6 + subobject_must_be_space = 7 + subobject_not_found = 8 + OTHERS = 9. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF lines( lt_list ) = 0. + RETURN. + ENDIF. + + LOOP AT lt_list ASSIGNING . + CLEAR -nrlevel. + -procind = 'D'. + ENDLOOP. + + CALL FUNCTION 'NUMBER_RANGE_INTERVAL_UPDATE' + EXPORTING + object = iv_object + IMPORTING + error = ls_error + error_occured = lv_error + TABLES + error_iv = lt_error_iv + interval = lt_list + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0 OR lv_error = abap_true. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'NUMBER_RANGE_UPDATE_CLOSE' + EXPORTING + object = iv_object + EXCEPTIONS + no_changes_made = 1 + object_not_initialized = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_objectid TYPE cdhdr-objectid, + lt_cdhdr TYPE cdhdr_tab. + + FIELD-SYMBOLS: LIKE LINE OF lt_cdhdr. + lv_objectid = ms_item-obj_name. + + CALL FUNCTION 'CHANGEDOCUMENT_READ_HEADERS' + EXPORTING + objectclass = 'NRKROBJ' + objectid = lv_objectid + TABLES + i_cdhdr = lt_cdhdr + EXCEPTIONS + no_position_found = 1 + wrong_access_to_archive = 2 + time_zone_conversion_error = 3 + OTHERS = 4. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + RETURN. + ENDIF. + + SORT lt_cdhdr BY udate DESCENDING utime DESCENDING. + + READ TABLE lt_cdhdr INDEX 1 ASSIGNING . + ASSERT sy-subrc = 0. + + rv_user = -username. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_object TYPE tnro-object. + lv_object = ms_item-obj_name. + + delete_intervals( lv_object ). + + CALL FUNCTION 'NUMBER_RANGE_OBJECT_DELETE' + EXPORTING + language = mv_language + object = lv_object + EXCEPTIONS + delete_not_allowed = 1 + object_not_found = 2 + wrong_indicator = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lt_errors TYPE TABLE OF inoer, + ls_attributes TYPE tnro, + ls_text TYPE tnrot. + + FIELD-SYMBOLS TYPE any. + + io_xml->read( EXPORTING iv_name = 'ATTRIBUTES' + CHANGING cg_data = ls_attributes ). + io_xml->read( EXPORTING iv_name = 'TEXT' + CHANGING cg_data = ls_text ). + + ASSIGN COMPONENT 'CHANGED_AT' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + GET TIME STAMP FIELD . + ENDIF. + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + = sy-uname. + ENDIF. + ASSIGN COMPONENT 'ENAME' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + = sy-uname. + ENDIF. + ASSIGN COMPONENT 'EDATE' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + = sy-datum. + ENDIF. + ASSIGN COMPONENT 'ETIME' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + = sy-uzeit. + ENDIF. + + ASSIGN COMPONENT 'UNAME' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + = sy-uname. + ENDIF. + ASSIGN COMPONENT 'UDATE' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + = sy-datum. + ENDIF. + ASSIGN COMPONENT 'UTIME' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + = sy-uzeit. + ENDIF. + ASSIGN COMPONENT 'ENAME' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + = sy-uname. + ENDIF. + ASSIGN COMPONENT 'EDATE' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + = sy-datum. + ENDIF. + ASSIGN COMPONENT 'ETIME' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + = sy-uzeit. + ENDIF. + + CALL FUNCTION 'NUMBER_RANGE_OBJECT_UPDATE' + EXPORTING + indicator = 'I' + object_attributes = ls_attributes + object_text = ls_text + TABLES + errors = lt_errors + EXCEPTIONS + object_already_exists = 1 + object_attributes_missing = 2 + object_not_found = 3 + object_text_missing = 4 + wrong_indicator = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + tadir_insert( iv_package ). + corr_insert( iv_package ). + + CALL FUNCTION 'NUMBER_RANGE_OBJECT_CLOSE' + EXPORTING + object = ls_attributes-object + EXCEPTIONS + object_not_initialized = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_object TYPE tnro-object. + SELECT SINGLE object FROM tnro INTO lv_object + WHERE object = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_bcdata TYPE bdcdata, + lt_bcdata TYPE STANDARD TABLE OF bdcdata. + + ls_bcdata-program = 'SAPMSNRO'. + ls_bcdata-dynpro = '0150'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'NRIV-OBJECT'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=DISP'. + APPEND ls_bcdata TO lt_bcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SNRO' + it_bdcdata = lt_bcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_object TYPE tnro-object, + ls_attributes TYPE tnro, + ls_text TYPE tnrot. + + FIELD-SYMBOLS TYPE any. + lv_object = ms_item-obj_name. + + CALL FUNCTION 'NUMBER_RANGE_OBJECT_READ' + EXPORTING + language = mv_language + object = lv_object + IMPORTING + object_attributes = ls_attributes + object_text = ls_text + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + IF sy-subrc = 1. + RETURN. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ASSIGN COMPONENT 'CHANGED_AT' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'ENAME' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'EDATE' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'ETIME' OF STRUCTURE ls_attributes TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + ASSIGN COMPONENT 'UNAME' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'UDATE' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'UTIME' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'ENAME' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'EDATE' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'ETIME' OF STRUCTURE ls_text TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + io_xml->add( iv_name = 'ATTRIBUTES' + ig_data = ls_attributes ). + io_xml->add( iv_name = 'TEXT' + ig_data = ls_text ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_msag IMPLEMENTATION. + METHOD delete_documentation. + DATA: lv_key_s TYPE dokhl-object. + + CLEAR lv_key_s. + CALL FUNCTION 'DOCU_OBJECT_NAME_CONCATENATE' + EXPORTING + docu_id = c_longtext_id_msag + element = iv_message_id + addition = ' ' + IMPORTING + object = lv_key_s. + + CALL FUNCTION 'DOKU_DELETE_ALL' + EXPORTING + doku_id = c_longtext_id_msag + doku_object = lv_key_s + generic_use = 'X' + suppress_authority = space + suppress_enqueue = space + suppress_transport = space + EXCEPTIONS + header_without_text = 1 + index_without_header = 2 + no_authority_for_devclass_xxxx = 3 + no_docu_found = 4 + object_is_already_enqueued = 5 + object_is_enqueued_by_corr = 6 + user_break = 7 + OTHERS = 8. + IF sy-subrc <> 0 AND sy-subrc <> 4. + zcx_abapgit_exception=>raise( 'Error deleting longtext for message' ). + ENDIF. + + ENDMETHOD. + METHOD delete_msgid. + + delete_documentation( iv_message_id ). + + DELETE FROM t100a WHERE arbgb = iv_message_id. + IF sy-subrc = 0 OR sy-subrc = 4. + CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' + EXPORTING + object = iv_message_id + operation = 'DELETE' + program = space + type = 'CN'. + DELETE FROM t100o WHERE arbgb = iv_message_id. + DELETE FROM t100t WHERE arbgb = iv_message_id. "#EC CI_NOFIRST + DELETE FROM t100u WHERE arbgb = iv_message_id. + DELETE FROM t100x WHERE arbgb = iv_message_id. + DELETE FROM t100 WHERE arbgb = iv_message_id. + ENDIF. + ENDMETHOD. + METHOD deserialize_texts. + + DATA: lv_msg_id TYPE rglif-message_id, + ls_t100 TYPE t100, + lt_t100t TYPE TABLE OF t100t, + lt_t100_texts TYPE ty_t100_texts, + lt_t100u TYPE TABLE OF t100u. + + FIELD-SYMBOLS: TYPE ty_t100_text. + lv_msg_id = ms_item-obj_name. + + SELECT * FROM t100u INTO TABLE lt_t100u + WHERE arbgb = lv_msg_id ORDER BY PRIMARY KEY. "#EC CI_GENBUFF + + ii_xml->read( EXPORTING iv_name = 'T100_TEXTS' + CHANGING cg_data = lt_t100_texts ). + + ii_xml->read( EXPORTING iv_name = 'T100T' + CHANGING cg_data = lt_t100t ). + + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'SPRSL' + CHANGING + ct_tab = lt_t100_texts ). + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'SPRSL' + CHANGING + ct_tab = lt_t100t ). + + MODIFY t100t FROM TABLE lt_t100t. "#EC CI_SUBRC + + LOOP AT lt_t100_texts ASSIGNING . + "check if message exists + READ TABLE lt_t100u TRANSPORTING NO FIELDS + WITH KEY arbgb = lv_msg_id msgnr = -msgnr BINARY SEARCH. + CHECK sy-subrc = 0. "if original message doesn't exist no translations added + + MOVE-CORRESPONDING TO ls_t100. + ls_t100-arbgb = lv_msg_id. + MODIFY t100 FROM ls_t100. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'MSAG: Table T100 modify failed' ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD free_access_permission. + CALL FUNCTION 'RS_ACCESS_PERMISSION' + EXPORTING + mode = 'FREE' + object = iv_message_id + object_class = 'T100'. + ENDMETHOD. + METHOD serialize_longtexts_msag. + + DATA: lv_doku_object_name TYPE dokhl-object, + lt_doku_object_names TYPE STANDARD TABLE OF dokhl-object + WITH NON-UNIQUE DEFAULT KEY, + lt_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt, + ls_dokil LIKE LINE OF lt_dokil, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + FIELD-SYMBOLS: TYPE t100. + + IF lines( it_t100 ) = 0. + RETURN. + ENDIF. + + LOOP AT it_t100 ASSIGNING . + + lv_doku_object_name = -arbgb && -msgnr. + INSERT lv_doku_object_name INTO TABLE lt_doku_object_names. + + ENDLOOP. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + SELECT * FROM dokil + INTO TABLE lt_dokil + FOR ALL ENTRIES IN lt_doku_object_names + WHERE id = c_longtext_id_msag + AND object = lt_doku_object_names-table_line + AND masterlang = abap_true + ORDER BY PRIMARY KEY. + ELSE. + lt_language_filter = mo_i18n_params->build_language_filter( ). + SELECT * FROM dokil + INTO TABLE lt_dokil + FOR ALL ENTRIES IN lt_doku_object_names + WHERE id = c_longtext_id_msag + AND object = lt_doku_object_names-table_line + AND langu IN lt_language_filter + ORDER BY PRIMARY KEY. + ENDIF. + + CLEAR ls_dokil-dokstate. + MODIFY lt_dokil FROM ls_dokil TRANSPORTING dokstate WHERE dokstate IS NOT INITIAL. + + IF lines( lt_dokil ) > 0. + serialize_longtexts( ii_xml = ii_xml + it_dokil = lt_dokil ). + ENDIF. + + ENDMETHOD. + METHOD serialize_texts. + + DATA: lv_msg_id TYPE rglif-message_id, + lt_t100_texts TYPE ty_t100_texts, + lt_t100t TYPE TABLE OF t100t, + lt_i18n_langs TYPE TABLE OF langu, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + lv_msg_id = ms_item-obj_name. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. " skip + ENDIF. + + " Collect additional languages + " Skip main lang - it has been already serialized and also technical languages + lt_language_filter = mo_i18n_params->build_language_filter( ). + + SELECT DISTINCT sprsl AS langu INTO TABLE lt_i18n_langs + FROM t100t + WHERE arbgb = lv_msg_id + AND sprsl IN lt_language_filter + AND sprsl <> mv_language + ORDER BY langu. "#EC CI_BYPASS "#EC CI_GENBUFF + + SORT lt_i18n_langs ASCENDING. + + IF lines( lt_i18n_langs ) > 0. + + SELECT * FROM t100t INTO CORRESPONDING FIELDS OF TABLE lt_t100t + WHERE sprsl IN lt_language_filter + AND sprsl <> mv_language + AND arbgb = lv_msg_id + ORDER BY PRIMARY KEY. "#EC CI_GENBUFF + + SELECT * FROM t100 INTO CORRESPONDING FIELDS OF TABLE lt_t100_texts + WHERE sprsl IN lt_language_filter + AND sprsl <> mv_language + AND arbgb = lv_msg_id + ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF + + SORT lt_t100t BY sprsl ASCENDING. + SORT lt_t100_texts BY sprsl msgnr ASCENDING. + + ii_xml->add( iv_name = 'I18N_LANGS' + ig_data = lt_i18n_langs ). + + ii_xml->add( iv_name = 'T100T' + ig_data = lt_t100t ). + + ii_xml->add( iv_name = 'T100_TEXTS' + ig_data = lt_t100_texts ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE lastuser FROM t100a INTO rv_user + WHERE arbgb = ms_item-obj_name. "#EC CI_GENBUFF + IF sy-subrc <> 0 OR rv_user = ''. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + DATA: ls_t100a TYPE t100a, + lv_frozen TYPE abap_bool, + lv_message_id TYPE arbgb. + +* parameter SUPPRESS_DIALOG doesn't exist in all versions of FM RS_DELETE_MESSAGE_ID +* replaced with a copy + lv_message_id = ms_item-obj_name. + IF ms_item-obj_name = space. + zcx_abapgit_exception=>raise( 'Error from (copy of) RS_DELETE_MESSAGE_ID' )."blank message id + ENDIF. + + SELECT SINGLE * FROM t100a INTO ls_t100a WHERE arbgb = ms_item-obj_name. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error from (copy of) RS_DELETE_MESSAGE_ID' )."not found + ENDIF. + + CLEAR lv_frozen. + CALL FUNCTION 'RS_ACCESS_PERMISSION' + EXPORTING + authority_check = 'X' + global_lock = 'X' + mode = 'MODIFY' + object = lv_message_id + object_class = 'T100' + IMPORTING + frozen = lv_frozen + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc <> 0 OR lv_frozen <> space. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( + iv_object = 'MSAG' + iv_obj_name = lv_message_id + iv_package = iv_package + iv_language = mv_language + iv_mode = zif_abapgit_cts_api=>c_transport_mode-delete ). + + delete_msgid( lv_message_id ). + + free_access_permission( lv_message_id ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. +* fm RPY_MESSAGE_ID_INSERT almost works, but not in older versions + + DATA: ls_t100a TYPE t100a, + ls_t100t TYPE t100t, + ls_t100u TYPE t100u, + lt_t100 TYPE TABLE OF t100, + lt_before TYPE TABLE OF t100u. + + FIELD-SYMBOLS: LIKE LINE OF lt_t100. + io_xml->read( EXPORTING iv_name = 'T100A' + CHANGING cg_data = ls_t100a ). + io_xml->read( EXPORTING iv_name = 'T100' + CHANGING cg_data = lt_t100 ). + + corr_insert( iv_package ). + + SELECT * FROM t100u INTO TABLE lt_before + WHERE arbgb = ls_t100a-arbgb ORDER BY msgnr. "#EC CI_GENBUFF "#EC CI_BYPASS + + LOOP AT lt_t100 ASSIGNING . + DELETE lt_before WHERE msgnr = -msgnr. + MODIFY t100 FROM . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'MSAG: Table T100 modify failed' ). + ENDIF. + CLEAR ls_t100u. + MOVE-CORRESPONDING TO ls_t100u ##ENH_OK. + ls_t100u-name = sy-uname. + ls_t100u-datum = sy-datum. + ls_t100u-selfdef = '3'. + MODIFY t100u FROM ls_t100u. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'MSAG: Table T100U modify failed' ). + ENDIF. + ENDLOOP. + + ls_t100a-masterlang = mv_language. + ls_t100a-lastuser = sy-uname. + ls_t100a-respuser = sy-uname. + ls_t100a-ldate = sy-datum. + ls_t100a-ltime = sy-uzeit. + MODIFY t100a FROM ls_t100a. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'MSAG: Table T100A modify failed' ). + ENDIF. + + ls_t100t-sprsl = mv_language. + ls_t100t-arbgb = ls_t100a-arbgb. + ls_t100t-stext = ls_t100a-stext. + MODIFY t100t FROM ls_t100t. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'MSAG: Table T100T modify failed' ). + ENDIF. + + LOOP AT lt_before INTO ls_t100u. + DELETE FROM t100 WHERE arbgb = ls_t100u-arbgb + AND msgnr = ls_t100u-msgnr. "#EC CI_SUBRC + + DELETE FROM t100u WHERE arbgb = ls_t100u-arbgb + AND msgnr = ls_t100u-msgnr. "#EC CI_SUBRC + ENDLOOP. + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_msag ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + deserialize_texts( io_xml ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_arbgb TYPE t100a-arbgb. + SELECT SINGLE arbgb FROM t100a INTO lv_arbgb + WHERE arbgb = ms_item-obj_name. "#EC CI_GENBUFF + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_argument TYPE seqg3-garg. + + lv_argument = |{ ms_item-obj_name }|. + OVERLAY lv_argument WITH ' '. + lv_argument = lv_argument && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = |ES_MSGSI| + iv_argument = lv_argument ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_msg_id TYPE rglif-message_id, + ls_inf TYPE t100a, + lt_source TYPE ty_t100s. + lv_msg_id = ms_item-obj_name. + + SELECT SINGLE * FROM t100a INTO ls_inf + WHERE arbgb = lv_msg_id. "#EC CI_GENBUFF + IF sy-subrc <> 0. + RETURN. + ENDIF. + CLEAR ls_inf-respuser. + + SELECT * FROM t100 INTO TABLE lt_source + WHERE sprsl = mv_language + AND arbgb = lv_msg_id + ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF + + CLEAR: ls_inf-lastuser, + ls_inf-ldate, + ls_inf-ltime. + + io_xml->add( iv_name = 'T100A' + ig_data = ls_inf ). + io_xml->add( ig_data = lt_source + iv_name = 'T100' ). + + serialize_longtexts_msag( it_t100 = lt_source + ii_xml = io_xml ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + serialize_texts( io_xml ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_jobd IMPLEMENTATION. + + METHOD constructor. + + DATA: lr_job_definition TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE DATA lr_job_definition TYPE ('CL_JR_JOB_DEFINITION=>TY_JOB_DEFINITION'). + CATCH cx_sy_ref_creation. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lr_job_definition TYPE REF TO data, + lo_job_definition TYPE REF TO object, + lv_name TYPE ty_jd_name. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + lv_name = ms_item-obj_name. + + TRY. + CREATE DATA lr_job_definition TYPE ('CL_JR_JOB_DEFINITION=>TY_JOB_DEFINITION'). + ASSIGN lr_job_definition->* TO . + ASSERT sy-subrc = 0. + + CREATE OBJECT lo_job_definition TYPE ('CL_JR_JOB_DEFINITION') + EXPORTING + im_jd_name = lv_name. + + CALL METHOD lo_job_definition->('GET_JD_ATTRIBUTES') + IMPORTING + ex_jd_attributes = . + + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + IF sy-subrc = 0. + rv_user = . + ENDIF. + + CATCH cx_root ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_job_definition TYPE REF TO object, + lv_name TYPE c LENGTH 32. + + lv_name = ms_item-obj_name. + + TRY. + CREATE OBJECT lo_job_definition TYPE ('CL_JR_JOB_DEFINITION') + EXPORTING + im_jd_name = lv_name. + + CALL METHOD lo_job_definition->('DELETE_JD'). + + CATCH cx_root. + zcx_abapgit_exception=>raise( |Error deleting JOBD| ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lr_job_definition TYPE REF TO data, + lo_job_definition TYPE REF TO object, + lx_error TYPE REF TO cx_root, + lv_name TYPE ty_jd_name. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + lv_name = ms_item-obj_name. + + TRY. + CREATE DATA lr_job_definition TYPE ('CL_JR_JOB_DEFINITION=>TY_JOB_DEFINITION'). + ASSIGN lr_job_definition->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'JOBD' + CHANGING + cg_data = ). + + CREATE OBJECT lo_job_definition TYPE ('CL_JR_JOB_DEFINITION') + EXPORTING + im_jd_name = lv_name. + + ASSIGN COMPONENT 'JDPACKAGE' OF STRUCTURE TO . + + = iv_package. + + CALL METHOD lo_job_definition->('CREATE_JD') + EXPORTING + im_jd_attributes = . + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_name TYPE ty_jd_name. + + lv_name = ms_item-obj_name. + + CALL METHOD ('CL_JR_JD_MANAGER')=>('CHECK_JD_EXISTENCE') + EXPORTING + im_jd_name = lv_name + IMPORTING + ex_is_existing = rv_bool. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lv_obj_name TYPE e071-obj_name. + lv_obj_name = ms_item-obj_name. + + CALL FUNCTION 'TR_OBJECT_JUMP_TO_TOOL' + EXPORTING + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = lv_obj_name + iv_action = 'SHOW' + EXCEPTIONS + jump_not_possible = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lr_job_definition TYPE REF TO data, + lo_job_definition TYPE REF TO object, + lv_name TYPE ty_jd_name. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + lv_name = ms_item-obj_name. + + TRY. + CREATE DATA lr_job_definition TYPE ('CL_JR_JOB_DEFINITION=>TY_JOB_DEFINITION'). + ASSIGN lr_job_definition->* TO . + ASSERT sy-subrc = 0. + + CREATE OBJECT lo_job_definition TYPE ('CL_JR_JOB_DEFINITION') + EXPORTING + im_jd_name = lv_name. + + CALL METHOD lo_job_definition->('GET_JD_ATTRIBUTES') + IMPORTING + ex_jd_attributes = . + + ASSIGN COMPONENT 'JDPACKAGE' OF STRUCTURE TO . + CLEAR . + + ASSIGN COMPONENT 'BTCJOB_USER' OF STRUCTURE TO . + CLEAR . + + ASSIGN COMPONENT 'OWNER' OF STRUCTURE TO . + CLEAR . + + ASSIGN COMPONENT 'CREATED_DATE' OF STRUCTURE TO . + CLEAR . + + ASSIGN COMPONENT 'CREATED_TIME' OF STRUCTURE TO . + CLEAR . + + ASSIGN COMPONENT 'CHANGEDBY' OF STRUCTURE TO . + CLEAR . + + ASSIGN COMPONENT 'CHANGED_DATE' OF STRUCTURE TO . + CLEAR . + + ASSIGN COMPONENT 'CHANGED_TIME' OF STRUCTURE TO . + CLEAR . + + io_xml->add( iv_name = 'JOBD' + ig_data = ). + + CATCH cx_root. + zcx_abapgit_exception=>raise( |Error serializing JOBD| ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iwvb IMPLEMENTATION. + METHOD get_field_rules. + ro_result = zcl_abapgit_field_rules=>create( ). + ro_result->add( + iv_table = '/IWBEP/I_MGW_VAH' + iv_field = 'CREATED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_MGW_VAH' + iv_field = 'CREATED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_MGW_VAH' + iv_field = 'CHANGED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_MGW_VAH' + iv_field = 'CHANGED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). + + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + ro_result->add( + iv_table = '/IWBEP/I_MGW_VAH' + iv_field = 'ABAP_LANGUAGE_VERSION' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-abap_language_version ). + ENDIF. + + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA lv_created TYPE sy-uname. + DATA lv_changed TYPE sy-uname. + + " Get entry with highest version + SELECT created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_MGW_VAH') + WHERE technical_name = ms_item-obj_name + ORDER BY PRIMARY KEY. + rv_user = lv_changed. + IF lv_changed IS INITIAL. + rv_user = lv_created. + ENDIF. + ENDSELECT. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA lv_prog TYPE progname. + + lv_prog = '/IWBEP/R_DST_VOCAN_REGISTER'. + + SUBMIT (lv_prog) + WITH ip_aname = ms_item-obj_name + WITH ip_avers = ms_item-obj_name+32(4) + AND RETURN. + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iwsv IMPLEMENTATION. + METHOD get_field_rules. + ro_result = zcl_abapgit_field_rules=>create( ). + ro_result->add( + iv_table = '/IWBEP/I_MGW_SRH' + iv_field = 'CREATED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_MGW_SRH' + iv_field = 'CREATED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_MGW_SRH' + iv_field = 'CHANGED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_MGW_SRH' + iv_field = 'CHANGED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). + + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + ro_result->add( + iv_table = '/IWBEP/I_MGW_SRH' + iv_field = 'ABAP_LANGUAGE_VERSION' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-abap_language_version ). + ENDIF. + + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA lv_created TYPE sy-uname. + DATA lv_changed TYPE sy-uname. + + " Get entry with highest version + SELECT created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_MGW_SRH') + WHERE technical_name = ms_item-obj_name + ORDER BY PRIMARY KEY. + rv_user = lv_changed. + IF lv_changed IS INITIAL. + rv_user = lv_created. + ENDIF. + ENDSELECT. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lv_technical_name TYPE c LENGTH 35, + lv_version TYPE bdc_fval, + lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + + lv_technical_name = ms_item-obj_name(36). + lv_version = ms_item-obj_name+36(4). + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = '/IWBEP/R_DST_SERVICE_BUILDER'. + -dynpro = '0100'. + -dynbegin = 'X'. + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'GS_SCREEN_100-TECHNICAL_NAME'. + -fval = lv_technical_name. + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'GS_SCREEN_100-VERSION'. + -fval = lv_version. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = '/IWBEP/REG_SERVICE' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iwsg IMPLEMENTATION. + METHOD get_field_rules. + + ro_result = zcl_abapgit_field_rules=>create( ). + ro_result->add( + iv_table = '/IWFND/I_MED_SRH' + iv_field = 'CREATED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWFND/I_MED_SRH' + iv_field = 'CREATED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWFND/I_MED_SRH' + iv_field = 'CHANGED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWFND/I_MED_SRH' + iv_field = 'CHANGED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). + + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + ro_result->add( + iv_table = '/IWFND/I_MED_SRH' + iv_field = 'ABAP_LANGUAGE_VERSION' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-abap_language_version ). + ENDIF. + + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE changed_by FROM ('/IWFND/I_MED_SRH') INTO rv_user + WHERE srv_identifier = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iwpr IMPLEMENTATION. + METHOD get_field_rules. + ro_result = zcl_abapgit_field_rules=>create( ). + ro_result->add( + iv_table = '/IWBEP/I_SBD_GA' + iv_field = 'CREATION_USER_ID' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_SBD_GA' + iv_field = 'CREATION_TIME' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_SBD_GA' + iv_field = 'LAST_CHG_USER_ID' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_SBD_GA' + iv_field = 'LAST_CHG_TIME' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE last_chg_user_id FROM ('/IWBEP/I_SBD_PR') INTO rv_user + WHERE project = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA lv_prog TYPE progname. + + lv_prog = '/IWBEP/R_SBUI_SERVICE_BUILDER'. + + SUBMIT (lv_prog) + WITH i_prname = ms_item-obj_name + AND RETURN. + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iwom IMPLEMENTATION. + METHOD get_field_rules. + ro_result = zcl_abapgit_field_rules=>create( ). + ro_result->add( + iv_table = '/IWFND/I_MED_OHD' + iv_field = 'CREATED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWFND/I_MED_OHD' + iv_field = 'CREATED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWFND/I_MED_OHD' + iv_field = 'CHANGED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWFND/I_MED_OHD' + iv_field = 'CHANGED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). + + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + ro_result->add( + iv_table = '/IWFND/I_MED_OHD' + iv_field = 'ABAP_LANGUAGE_VERSION' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-abap_language_version ). + ENDIF. + + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE changed_by FROM ('/IWFND/I_MED_OHD') INTO rv_user + WHERE model_identifier = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iwmo IMPLEMENTATION. + METHOD get_field_rules. + ro_result = zcl_abapgit_field_rules=>create( ). + ro_result->add( + iv_table = '/IWBEP/I_MGW_OHD' + iv_field = 'CREATED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_MGW_OHD' + iv_field = 'CREATED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_MGW_OHD' + iv_field = 'CHANGED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_MGW_OHD' + iv_field = 'CHANGED_TIMESTMP' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). + + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + ro_result->add( + iv_table = '/IWBEP/I_MGW_OHD' + iv_field = 'ABAP_LANGUAGE_VERSION' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-abap_language_version ). + ENDIF. + + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA lv_created TYPE sy-uname. + DATA lv_changed TYPE sy-uname. + + " Get entry with highest version + SELECT created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_MGW_OHD') + WHERE technical_name = ms_item-obj_name + ORDER BY PRIMARY KEY. + rv_user = lv_changed. + IF lv_changed IS INITIAL. + rv_user = lv_created. + ENDIF. + ENDSELECT. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lv_mdl_technical_name TYPE c LENGTH 32, + lv_version TYPE bdc_fval, + lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + + lv_mdl_technical_name = ms_item-obj_name. + lv_version = ms_item-obj_name+32(4). + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = '/IWBEP/R_DST_MODEL_BUILDER'. + -dynpro = '0100'. + -dynbegin = 'X'. + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'GS_MODEL_SCREEN_100-TECHNICAL_NAME'. + -fval = lv_mdl_technical_name. + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'GS_MODEL_SCREEN_100-VERSION'. + -fval = lv_version. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = '/IWBEP/REG_MODEL' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iobj IMPLEMENTATION. + + METHOD constructor. + + DATA lr_viobj TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE DATA lr_viobj TYPE ('RSD_S_VIOBJ'). + CATCH cx_sy_create_data_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname + OF STRUCTURE cg_metadata + TO . + ASSERT sy-subrc = 0. + + CLEAR: . + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_objna TYPE c LENGTH 30, + lr_viobj TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE any. + + lv_objna = ms_item-obj_name. + + CREATE DATA lr_viobj TYPE ('RSD_S_VIOBJ'). + ASSIGN lr_viobj->* TO . + + CALL FUNCTION 'RSD_IOBJ_GET' + EXPORTING + i_iobjnm = lv_objna + i_objvers = 'A' + IMPORTING + e_s_viobj = + EXCEPTIONS + iobj_not_found = 1 + illegal_input = 2 + bct_comp_invalid = 3 +* not_authorized = 4 " not in lower releases + OTHERS = 5. + IF sy-subrc = 0. + ASSIGN COMPONENT 'TSTPNM' OF STRUCTURE TO . + rv_user = . + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + TYPES: BEGIN OF ty_iobj, + objnm TYPE c LENGTH 30. + TYPES END OF ty_iobj. + + DATA: lt_iobjname TYPE STANDARD TABLE OF ty_iobj, + lv_subrc TYPE sy-subrc. + + APPEND ms_item-obj_name TO lt_iobjname. + + CALL FUNCTION 'RSDG_IOBJ_MULTI_DELETE' + EXPORTING + i_t_iobjnm = lt_iobjname + i_check_dependent = abap_false + i_manual = abap_false + IMPORTING + e_subrc = lv_subrc. + + IF lv_subrc <> 0. + zcx_abapgit_exception=>raise( |Error when deleting InfoObject { ms_item-obj_name }| ). + ENDIF. + + corr_insert( iv_package ). + + TRY. + " In case of IOBJ dependencies, tadir entry might be leftover so we remove it + tadir_delete( ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + lr_details TYPE REF TO data, + lr_infoobj TYPE REF TO data, + ls_return TYPE bapiret2, + lt_return TYPE STANDARD TABLE OF bapiret2, + lr_compounds TYPE REF TO data, + lr_attributes TYPE REF TO data, + lr_navigationattributes TYPE REF TO data, + lr_atrnavinfoprovider TYPE REF TO data, + lr_hierarchycharacteristics TYPE REF TO data, + lr_elimination TYPE REF TO data, + lr_hanafieldsmapping TYPE REF TO data, + lr_xxlattributes TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE data, + TYPE STANDARD TABLE. + + CREATE DATA lr_details TYPE ('BAPI6108'). + CREATE DATA lr_compounds TYPE STANDARD TABLE OF ('BAPI6108CM'). + CREATE DATA lr_attributes TYPE STANDARD TABLE OF ('BAPI6108AT'). + CREATE DATA lr_navigationattributes TYPE STANDARD TABLE OF ('BAPI6108AN'). + CREATE DATA lr_atrnavinfoprovider TYPE STANDARD TABLE OF ('BAPI6108NP'). + CREATE DATA lr_hierarchycharacteristics TYPE STANDARD TABLE OF ('BAPI6108HC'). + CREATE DATA lr_elimination TYPE STANDARD TABLE OF ('BAPI6108IE'). + CREATE DATA lr_hanafieldsmapping TYPE STANDARD TABLE OF ('BAPI6108HANA_MAP'). + CREATE DATA lr_xxlattributes TYPE STANDARD TABLE OF ('BAPI6108ATXXL'). + CREATE DATA lr_infoobj TYPE STANDARD TABLE OF ('BAPI6108'). + + ASSIGN lr_details->* TO . + ASSIGN lr_compounds->* TO . + ASSIGN lr_attributes->* TO . + ASSIGN lr_navigationattributes->* TO . + ASSIGN lr_atrnavinfoprovider->* TO . + ASSIGN lr_hierarchycharacteristics->* TO . + ASSIGN lr_elimination->* TO . + ASSIGN lr_hanafieldsmapping->* TO . + ASSIGN lr_xxlattributes->* TO . + ASSIGN lr_infoobj->* TO . + + io_xml->read( EXPORTING iv_name = 'IOBJ' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'COMPOUNDS' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'ATTRIBUTES' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'NAVIGATION_ATTRIBUTES' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'ATTR_NAVIGATION' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'HIERARCHY' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'ELIMINATION' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'HANA_FIELDS_MAPPING' + CHANGING cg_data = ). + + io_xml->read( EXPORTING iv_name = 'XXL_ATTRIBUTES' + CHANGING cg_data = ). + + " Number ranges are local (should not have been serialized) + clear_field( EXPORTING iv_fieldname = 'NUMBRANR' + CHANGING cg_metadata = ). + + TRY. + + ASSIGN + COMPONENT 'INFOOBJECT' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + IF zif_abapgit_object~exists( ) = abap_false. + TRY. + CALL FUNCTION 'BAPI_IOBJ_CREATE' + EXPORTING + details = + IMPORTING + return = ls_return + TABLES + compounds = + attributes = + navigationattributes = + atrnavinfoprovider = + hierarchycharacteristics = + elimination = + hanafieldsmapping = + xxlattributes = ##ARG_OK. + CATCH cx_sy_dyn_call_param_not_found. + CALL FUNCTION 'BAPI_IOBJ_CREATE' + EXPORTING + details = + IMPORTING + return = ls_return + TABLES + compounds = + attributes = + navigationattributes = + atrnavinfoprovider = + hierarchycharacteristics = + elimination = . + ENDTRY. + ELSE. + TRY. + CALL FUNCTION 'BAPI_IOBJ_CHANGE' + EXPORTING + infoobject = + details = + IMPORTING + return = ls_return + TABLES + compounds = + attributes = + navigationattributes = + atrnavinfoprovider = + hierarchycharacteristics = + elimination = + hanafieldsmapping = + xxlattributes = ##ARG_OK. + CATCH cx_sy_dyn_call_param_not_found. + CALL FUNCTION 'BAPI_IOBJ_CHANGE' + EXPORTING + infoobject = + details = + IMPORTING + return = ls_return + TABLES + compounds = + attributes = + navigationattributes = + atrnavinfoprovider = + hierarchycharacteristics = + elimination = . + ENDTRY. + ENDIF. + + IF ls_return-type = 'E'. + zcx_abapgit_exception=>raise( |Error when creating iobj: { ls_return-message }| ). + ENDIF. + + APPEND TO . + + CALL FUNCTION 'BAPI_IOBJ_ACTIVATE_MULTIPLE' + TABLES + infoobjects = + return = lt_return. + + READ TABLE lt_return WITH KEY type = 'E' INTO ls_return. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( |Error when activating iobj: { ls_return-message }| ). + ENDIF. + + CATCH cx_sy_dyn_call_illegal_func. + zcx_abapgit_exception=>raise( |Necessary BW function modules not found| ). + ENDTRY. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_iobjnm TYPE c LENGTH 30. + + SELECT SINGLE iobjnm + FROM ('RSDIOBJ') + INTO lv_iobjnm + WHERE iobjnm = ms_item-obj_name. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + + DATA: lv_objna TYPE c LENGTH 30, + lr_viobj TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE any. + + lv_objna = ms_item-obj_name. + + CREATE DATA lr_viobj TYPE ('RSD_S_VIOBJ'). + + ASSIGN lr_viobj->* TO . + + CALL FUNCTION 'RSD_IOBJ_GET' + EXPORTING + i_iobjnm = lv_objna + i_objvers = 'A' + IMPORTING + e_s_viobj = . + + ASSIGN COMPONENT 'OBJSTAT' OF STRUCTURE TO . + + IF = 'ACT' AND sy-subrc = 0. + rv_active = abap_true. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_object TYPE eqegraarg. + + lv_object = ms_item-obj_name. + OVERLAY lv_object WITH ' '. + lv_object = lv_object && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_BIW_PROV' + iv_argument = lv_object ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + lv_iobjnam TYPE rsiobjnm, + ls_return TYPE bapiret2, + lr_details TYPE REF TO data, + lr_compounds TYPE REF TO data, + lr_attributes TYPE REF TO data, + lr_navigationattributes TYPE REF TO data, + lr_atrnavinfoprovider TYPE REF TO data, + lr_hierarchycharacteristics TYPE REF TO data, + lr_elimination TYPE REF TO data, + lr_hanafieldsmapping TYPE REF TO data, + lr_xxlattributes TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE, + TYPE STANDARD TABLE. + + CREATE DATA lr_details TYPE ('BAPI6108'). + CREATE DATA lr_compounds TYPE STANDARD TABLE OF ('BAPI6108CM'). + CREATE DATA lr_attributes TYPE STANDARD TABLE OF ('BAPI6108AT'). + CREATE DATA lr_navigationattributes TYPE STANDARD TABLE OF ('BAPI6108AN'). + CREATE DATA lr_atrnavinfoprovider TYPE STANDARD TABLE OF ('BAPI6108NP'). + CREATE DATA lr_hierarchycharacteristics TYPE STANDARD TABLE OF ('BAPI6108HC'). + CREATE DATA lr_elimination TYPE STANDARD TABLE OF ('BAPI6108IE'). + CREATE DATA lr_hanafieldsmapping TYPE STANDARD TABLE OF ('BAPI6108HANA_MAP'). + CREATE DATA lr_xxlattributes TYPE STANDARD TABLE OF ('BAPI6108ATXXL'). + + ASSIGN lr_details->* TO . + ASSIGN lr_compounds->* TO . + ASSIGN lr_attributes->* TO . + ASSIGN lr_navigationattributes->* TO . + ASSIGN lr_atrnavinfoprovider->* TO . + ASSIGN lr_hierarchycharacteristics->* TO . + ASSIGN lr_elimination->* TO . + ASSIGN lr_hanafieldsmapping->* TO . + ASSIGN lr_xxlattributes->* TO . + + lv_iobjnam = ms_item-obj_name. + + TRY. + CALL FUNCTION 'BAPI_IOBJ_GETDETAIL' + EXPORTING + infoobject = lv_iobjnam + IMPORTING + details = + return = ls_return + TABLES + compounds = + attributes = + navigationattributes = + atrnavinfoprovider = + hierarchycharacteristics = + elimination = + hanafieldsmapping = + xxlattributes = ##ARG_OK. + CATCH cx_sy_dyn_call_param_not_found. + CALL FUNCTION 'BAPI_IOBJ_GETDETAIL' + EXPORTING + infoobject = lv_iobjnam + IMPORTING + details = + return = ls_return + TABLES + compounds = + attributes = + navigationattributes = + atrnavinfoprovider = + hierarchycharacteristics = + elimination = . + ENDTRY. + + IF ls_return-type = 'E'. + zcx_abapgit_exception=>raise( |Error getting details of InfoObject: { ls_return-message }| ). + ENDIF. + + clear_field( EXPORTING iv_fieldname = 'TSTPNM' + CHANGING cg_metadata = ). + + clear_field( EXPORTING iv_fieldname = 'TIMESTMP' + CHANGING cg_metadata = ). + + clear_field( EXPORTING iv_fieldname = 'DBROUTID' + CHANGING cg_metadata = ). + + " Number ranges are local + clear_field( EXPORTING iv_fieldname = 'NUMBRANR' + CHANGING cg_metadata = ). + + io_xml->add( iv_name = 'IOBJ' + ig_data = ). + + io_xml->add( iv_name = 'COMPOUNDS' + ig_data = ). + + io_xml->add( iv_name = 'ATTRIBUTES' + ig_data = ). + + io_xml->add( iv_name = 'NAVIGATION_ATTRIBUTES' + ig_data = ). + + io_xml->add( iv_name = 'ATTR_NAVIGATION' + ig_data = ). + + io_xml->add( iv_name = 'HIERARCHY' + ig_data = ). + + io_xml->add( iv_name = 'ELIMINATION' + ig_data = ). + + io_xml->add( iv_name = 'HANA_FIELDS_MAPPING' + ig_data = ). + + io_xml->add( iv_name = 'XXL_ATTRIBUTES' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlUKtFBXjILcBRBJOrsxFJiznPf DEFINITION DEFERRED. +CLASS kHGwlUKtFBXjILcBRBJOvDDGtKNvAd DEFINITION DEFERRED. +CLASS kHGwlUKtFBXjILcBRBJOnvUCODLJDd DEFINITION DEFERRED. +* renamed: zcl_abapgit_object_intf :: lcl_aff_helper +CLASS kHGwlUKtFBXjILcBRBJOnvUCODLJDd DEFINITION. + PUBLIC SECTION. + CLASS-METHODS: + get_descriptions_compo_subco + IMPORTING iv_language TYPE sy-langu + iv_clif_name TYPE seoclsname + RETURNING VALUE(rs_properties) TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions , + get_descr_comp_subc_w_exposure + IMPORTING iv_language TYPE sy-langu + iv_clif_name TYPE seoclsname + iv_exposure TYPE seoexpose DEFAULT seoc_exposure_public + RETURNING VALUE(rs_properties) TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions , + set_descriptions_compo_subco + IMPORTING iv_clif_name TYPE seoclsname + iv_language TYPE langu + is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions . + PRIVATE SECTION. + TYPES: + BEGIN OF ty_component, + visibility TYPE seoexpose, + cmpname TYPE seocmpname, + descript TYPE seodescr, + cmptype TYPE seocmptype, + END OF ty_component, + BEGIN OF ty_sub_component, + cmpname TYPE seocmpname, + sconame TYPE seosconame, + descript TYPE seodescr, + scotype TYPE seoscotype, + END OF ty_sub_component, + ty_compontents TYPE SORTED TABLE OF ty_component WITH UNIQUE DEFAULT KEY, + ty_sub_compontents TYPE SORTED TABLE OF ty_sub_component WITH UNIQUE DEFAULT KEY. + + CLASS-METHODS: + get_attributes + IMPORTING is_components TYPE ty_compontents + RETURNING VALUE(rs_result) TYPE zif_abapgit_aff_oo_types_v1=>ty_component_descriptions, + get_methods + IMPORTING is_components TYPE ty_compontents + is_sub_components TYPE ty_sub_compontents + RETURNING VALUE(rs_result) TYPE zif_abapgit_aff_oo_types_v1=>ty_methods, + get_types + IMPORTING is_components TYPE ty_compontents + RETURNING VALUE(rs_result) TYPE zif_abapgit_aff_oo_types_v1=>ty_component_descriptions, + get_events + IMPORTING is_components TYPE ty_compontents + is_sub_components TYPE ty_sub_compontents + RETURNING VALUE(rs_result) TYPE zif_abapgit_aff_oo_types_v1=>ty_events, + set_methods + IMPORTING iv_clif_name TYPE seoclsname + iv_language TYPE langu + is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions, + set_attributes + IMPORTING iv_clif_name TYPE seoclsname + iv_language TYPE langu + is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions, + set_events + IMPORTING iv_clif_name TYPE seoclsname + iv_language TYPE langu + is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions, + set_types + IMPORTING iv_clif_name TYPE seoclsname + iv_language TYPE langu + is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions . +ENDCLASS. +CLASS kHGwlUKtFBXjILcBRBJOnvUCODLJDd IMPLEMENTATION. + + METHOD get_descr_comp_subc_w_exposure. + DATA: + lt_components TYPE ty_compontents, + lt_sub_components TYPE ty_sub_compontents. + SELECT df~exposure AS visibility component~cmpname component_text~descript component~cmptype + INTO TABLE lt_components + FROM seocompo AS component + LEFT OUTER JOIN seocompotx AS component_text + ON component~cmpname = component_text~cmpname AND component~clsname = component_text~clsname AND + component_text~langu = iv_language + INNER JOIN seocompodf AS df + ON component~clsname = df~clsname AND + component~cmpname = df~cmpname + WHERE component~clsname = iv_clif_name AND + df~exposure = iv_exposure. "#EC CI_BUFFJOIN + + SELECT sub_component~cmpname sub_component~sconame sub_component_text~descript sub_component~scotype + INTO TABLE lt_sub_components + FROM seosubco AS sub_component JOIN seosubcotx AS sub_component_text + ON sub_component~clsname = sub_component_text~clsname AND + sub_component~cmpname = sub_component_text~cmpname AND + sub_component~sconame = sub_component_text~sconame + INNER JOIN seocompodf AS df + ON sub_component~clsname = df~clsname AND + sub_component~cmpname = df~cmpname + WHERE sub_component~clsname = iv_clif_name + AND df~exposure = iv_exposure + AND sub_component_text~langu = iv_language + AND sub_component_text~descript <> space. "#EC CI_BUFFJOIN + + rs_properties-attributes = get_attributes( lt_components ). + rs_properties-methods = get_methods( is_components = lt_components + is_sub_components = lt_sub_components ). + rs_properties-events = get_events( is_components = lt_components + is_sub_components = lt_sub_components ). + rs_properties-types = get_types( lt_components ). + ENDMETHOD. + METHOD get_descriptions_compo_subco. + TYPES: + BEGIN OF ty_helper_type, + cmpname TYPE seocmpname, + descript TYPE seodescr, + cmptype TYPE seocmptype, + END OF ty_helper_type. + DATA: + lt_components TYPE STANDARD TABLE OF ty_helper_type, + lt_sub_components TYPE ty_sub_compontents, + lt_components_exp TYPE ty_compontents, + ls_component_exp LIKE LINE OF lt_components_exp. + FIELD-SYMBOLS: + LIKE LINE OF lt_components. + SELECT component~cmpname component_text~descript component~cmptype + INTO TABLE lt_components + FROM seocompo AS component + LEFT OUTER JOIN seocompotx AS component_text + ON component~cmpname = component_text~cmpname AND component~clsname = component_text~clsname + AND component_text~langu = iv_language + WHERE component~clsname = iv_clif_name + ORDER BY component~cmpname. "#EC CI_BUFFJOIN + + SELECT sub_component~cmpname sub_component~sconame sub_component_text~descript sub_component~scotype + INTO TABLE lt_sub_components + FROM seosubco AS sub_component JOIN seosubcotx AS sub_component_text + ON sub_component~clsname = sub_component_text~clsname + AND sub_component~cmpname = sub_component_text~cmpname + AND sub_component~sconame = sub_component_text~sconame + WHERE sub_component~clsname = iv_clif_name + AND sub_component_text~langu = iv_language + AND sub_component_text~descript <> space. "#EC CI_BUFFJOIN + + LOOP AT lt_components ASSIGNING . + CLEAR ls_component_exp. + MOVE-CORRESPONDING TO ls_component_exp. + INSERT ls_component_exp INTO TABLE lt_components_exp. + ENDLOOP. + + rs_properties-attributes = get_attributes( lt_components_exp ). + rs_properties-methods = get_methods( is_components = lt_components_exp + is_sub_components = lt_sub_components ). + rs_properties-events = get_events( is_components = lt_components_exp + is_sub_components = lt_sub_components ). + rs_properties-types = get_types( lt_components_exp ). + + ENDMETHOD. + METHOD get_attributes. + DATA: + lo_component TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. + FIELD-SYMBOLS TYPE ty_component. + + LOOP AT is_components ASSIGNING WHERE cmptype = seoo_cmptype_attribute AND descript IS NOT INITIAL. + lo_component-name = -cmpname. + lo_component-description = -descript. + INSERT lo_component INTO TABLE rs_result. + ENDLOOP. + ENDMETHOD. + + METHOD get_methods. + DATA: + lo_method TYPE zif_abapgit_aff_oo_types_v1=>ty_method, + lo_exception TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description, + lo_parameter TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. + + FIELD-SYMBOLS TYPE ty_sub_component. + FIELD-SYMBOLS TYPE ty_component. + + LOOP AT is_components ASSIGNING WHERE cmptype = seoo_cmptype_method. + lo_method-name = -cmpname. + lo_method-description = -descript. + + LOOP AT is_sub_components ASSIGNING WHERE cmpname = -cmpname. + CASE -scotype. + WHEN seos_scotype_parameter. + lo_parameter-name = -sconame. + lo_parameter-description = -descript. + INSERT lo_parameter INTO TABLE lo_method-parameters. + WHEN seos_scotype_exception. + lo_exception-name = -sconame. + lo_exception-description = -descript. + INSERT lo_exception INTO TABLE lo_method-exceptions. + ENDCASE. + ENDLOOP. + + IF lo_method-description IS NOT INITIAL + OR lo_method-exceptions IS NOT INITIAL + OR lo_method-parameters IS NOT INITIAL. + INSERT lo_method INTO TABLE rs_result. + ENDIF. + ENDLOOP. + ENDMETHOD. + + METHOD get_types. + DATA: + lo_type TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. + FIELD-SYMBOLS: TYPE ty_component. + + LOOP AT is_components ASSIGNING + WHERE cmptype = seoo_cmptype_type AND descript IS NOT INITIAL. + lo_type-name = -cmpname. + lo_type-description = -descript. + INSERT lo_type INTO TABLE rs_result. + ENDLOOP. + ENDMETHOD. + + METHOD get_events. + DATA: + lo_parameter TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description, + lo_event TYPE zif_abapgit_aff_oo_types_v1=>ty_event. + FIELD-SYMBOLS TYPE ty_component. + FIELD-SYMBOLS TYPE ty_sub_component. + + LOOP AT is_components ASSIGNING WHERE cmptype = seoo_cmptype_event. + lo_event-name = -cmpname. + lo_event-description = -descript. + + LOOP AT is_sub_components ASSIGNING WHERE cmpname = -cmpname. + lo_parameter-name = -sconame. + lo_parameter-description = -descript. + INSERT lo_parameter INTO TABLE lo_event-parameters. + ENDLOOP. + + IF lo_event-description IS NOT INITIAL OR lo_event-parameters IS NOT INITIAL. + INSERT lo_event INTO TABLE rs_result. + ENDIF. + ENDLOOP. + ENDMETHOD. + METHOD set_attributes. + DATA: + lo_attribute TYPE seocompotx. + FIELD-SYMBOLS: TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. + + LOOP AT is_properties-attributes ASSIGNING . + lo_attribute-clsname = iv_clif_name. + lo_attribute-cmpname = -name. + lo_attribute-langu = iv_language. + lo_attribute-descript = -description. + MODIFY seocompotx FROM lo_attribute. + ENDLOOP. + ENDMETHOD. + METHOD set_methods. + DATA: + lo_method TYPE seocompotx, + lo_method_exception TYPE seosubcotx, + lo_method_parameter TYPE seosubcotx. + FIELD-SYMBOLS: TYPE zif_abapgit_aff_oo_types_v1=>ty_method, + TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description, + TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. + + LOOP AT is_properties-methods ASSIGNING . + lo_method-clsname = iv_clif_name. + lo_method-cmpname = -name. + lo_method-langu = iv_language. + lo_method-descript = -description. + MODIFY seocompotx FROM lo_method. + + LOOP AT -parameters ASSIGNING . + lo_method_parameter-clsname = iv_clif_name. + lo_method_parameter-cmpname = -name. + lo_method_parameter-sconame = -name. + lo_method_parameter-langu = iv_language. + lo_method_parameter-descript = -description. + MODIFY seosubcotx FROM lo_method_parameter. + ENDLOOP. + + LOOP AT -exceptions ASSIGNING . + lo_method_exception-clsname = iv_clif_name. + lo_method_exception-cmpname = -name. + lo_method_exception-sconame = -name. + lo_method_exception-langu = iv_language. + lo_method_exception-descript = -description. + MODIFY seosubcotx FROM lo_method_exception. + ENDLOOP. + ENDLOOP. + ENDMETHOD. + METHOD set_events. + DATA: + lo_event_parameter TYPE seosubcotx, + lo_event TYPE seocompotx. + FIELD-SYMBOLS: TYPE zif_abapgit_aff_oo_types_v1=>ty_event, + TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. + + LOOP AT is_properties-events ASSIGNING . + lo_event-clsname = iv_clif_name. + lo_event-cmpname = -name. + lo_event-langu = iv_language. + lo_event-descript = -description. + MODIFY seocompotx FROM lo_event. + + LOOP AT -parameters ASSIGNING . + lo_event_parameter-clsname = iv_clif_name. + lo_event_parameter-cmpname = -name. + lo_event_parameter-sconame = -name. + lo_event_parameter-langu = iv_language. + lo_event_parameter-descript = -description. + MODIFY seosubcotx FROM lo_event_parameter. + ENDLOOP. + ENDLOOP. + ENDMETHOD. + METHOD set_types. + DATA: + lo_type TYPE seocompotx. + FIELD-SYMBOLS: TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. + + LOOP AT is_properties-types ASSIGNING . + lo_type-clsname = iv_clif_name. + lo_type-cmpname = -name. + lo_type-langu = iv_language. + lo_type-descript = -description. + MODIFY seocompotx FROM lo_type. + ENDLOOP. + ENDMETHOD. + METHOD set_descriptions_compo_subco. + set_attributes( is_properties = is_properties + iv_clif_name = iv_clif_name + iv_language = iv_language ). + set_methods( is_properties = is_properties + iv_clif_name = iv_clif_name + iv_language = iv_language ). + set_events( is_properties = is_properties + iv_clif_name = iv_clif_name + iv_language = iv_language ). + set_types( is_properties = is_properties + iv_clif_name = iv_clif_name + iv_language = iv_language ). + ENDMETHOD. + +ENDCLASS. + +* renamed: zcl_abapgit_object_intf :: lcl_aff_type_mapping +CLASS kHGwlUKtFBXjILcBRBJOvDDGtKNvAd DEFINITION. + PUBLIC SECTION. + INTERFACES zif_abapgit_aff_type_mapping. + PRIVATE SECTION. + METHODS set_abapgit_descriptions + IMPORTING is_clsname TYPE seoclsname + is_intf_aff TYPE zif_abapgit_aff_intf_v1=>ty_main + EXPORTING et_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt + et_descriptions_sub TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt. +ENDCLASS. + +CLASS kHGwlUKtFBXjILcBRBJOvDDGtKNvAd IMPLEMENTATION. + + METHOD zif_abapgit_aff_type_mapping~to_aff. + DATA: + ls_data_abapgit TYPE zcl_abapgit_object_intf=>ty_intf, + ls_data_aff TYPE zif_abapgit_aff_intf_v1=>ty_main. + + ls_data_abapgit = iv_data. + + ls_data_aff-format_version = '1'. + + " get header + ls_data_aff-header-description = ls_data_abapgit-vseointerf-descript. + ls_data_aff-header-abap_language_version = ls_data_abapgit-vseointerf-unicode. + ls_data_aff-header-original_language = ls_data_abapgit-vseointerf-langu. + + " get category and proxy + ls_data_aff-category = ls_data_abapgit-vseointerf-category. + ls_data_aff-proxy = ls_data_abapgit-vseointerf-clsproxy. + + " get descriptions + ls_data_aff-descriptions = kHGwlUKtFBXjILcBRBJOnvUCODLJDd=>get_descriptions_compo_subco( + iv_language = ls_data_aff-header-original_language + iv_clif_name = ls_data_abapgit-vseointerf-clsname ). + + es_data = ls_data_aff. + ENDMETHOD. + + METHOD zif_abapgit_aff_type_mapping~to_abapgit. + DATA: + ls_data_abapgit TYPE zcl_abapgit_object_intf=>ty_intf, + ls_data_aff TYPE zif_abapgit_aff_intf_v1=>ty_main, + lv_classname TYPE seoclsname. + ls_data_aff = iv_data. + + lv_classname = to_upper( iv_object_name ). + + set_abapgit_descriptions( EXPORTING is_clsname = lv_classname + is_intf_aff = ls_data_aff + IMPORTING et_descriptions = ls_data_abapgit-description + et_descriptions_sub = ls_data_abapgit-description_sub ). + + ls_data_abapgit-vseointerf-clsname = lv_classname. + ls_data_abapgit-vseointerf-descript = ls_data_aff-header-description. + ls_data_abapgit-vseointerf-category = ls_data_aff-category. + ls_data_abapgit-vseointerf-unicode = ls_data_aff-header-abap_language_version. + ls_data_abapgit-vseointerf-langu = ls_data_aff-header-original_language. + ls_data_abapgit-vseointerf-clsproxy = ls_data_aff-proxy. + ls_data_abapgit-vseointerf-exposure = seoc_exposure_public. + ls_data_abapgit-vseointerf-state = seoc_state_implemented. + + es_data = ls_data_abapgit. + + ENDMETHOD. + + METHOD set_abapgit_descriptions. + + DATA ls_description TYPE seocompotx. + DATA ls_description_subco TYPE seosubcotx. + FIELD-SYMBOLS TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. + FIELD-SYMBOLS TYPE zif_abapgit_aff_oo_types_v1=>ty_method. + FIELD-SYMBOLS TYPE zif_abapgit_aff_oo_types_v1=>ty_event. + LOOP AT is_intf_aff-descriptions-types ASSIGNING . + ls_description-clsname = is_clsname. + ls_description-cmpname = -name. + ls_description-langu = is_intf_aff-header-original_language. + ls_description-descript = -description. + APPEND ls_description TO et_descriptions. + ENDLOOP. + + LOOP AT is_intf_aff-descriptions-attributes ASSIGNING . + ls_description-clsname = is_clsname. + ls_description-cmpname = -name. + ls_description-langu = is_intf_aff-header-original_language. + ls_description-descript = -description. + APPEND ls_description TO et_descriptions. + ENDLOOP. + + LOOP AT is_intf_aff-descriptions-methods ASSIGNING . + ls_description-clsname = is_clsname. + ls_description-cmpname = -name. + ls_description-langu = is_intf_aff-header-original_language. + ls_description-descript = -description. + APPEND ls_description TO et_descriptions. + + LOOP AT -parameters ASSIGNING . + ls_description_subco-clsname = ls_description-clsname. + ls_description_subco-cmpname = ls_description-cmpname. + ls_description_subco-langu = ls_description-langu. + ls_description_subco-sconame = -name. + ls_description_subco-descript = -description. + APPEND ls_description_subco TO et_descriptions_sub. + ENDLOOP. + + LOOP AT -exceptions ASSIGNING . + ls_description_subco-clsname = ls_description-clsname. + ls_description_subco-cmpname = ls_description-cmpname. + ls_description_subco-langu = ls_description-langu. + ls_description_subco-sconame = -name. + ls_description_subco-descript = -description. + APPEND ls_description_subco TO et_descriptions_sub. + ENDLOOP. + ENDLOOP. + + LOOP AT is_intf_aff-descriptions-events ASSIGNING . + ls_description-clsname = is_clsname. + ls_description-cmpname = -name. + ls_description-langu = is_intf_aff-header-original_language. + ls_description-descript = -description. + APPEND ls_description TO et_descriptions. + + LOOP AT -parameters ASSIGNING . + ls_description_subco-clsname = ls_description-clsname. + ls_description_subco-cmpname = ls_description-cmpname. + ls_description_subco-langu = ls_description-langu. + ls_description_subco-sconame = -name. + ls_description_subco-descript = -description. + APPEND ls_description_subco TO et_descriptions_sub. + ENDLOOP. + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. +* renamed: zcl_abapgit_object_intf :: lcl_aff_metadata_handler +CLASS kHGwlUKtFBXjILcBRBJOrsxFJiznPf DEFINITION. + PUBLIC SECTION. + + CLASS-METHODS serialize + IMPORTING is_intf TYPE zcl_abapgit_object_intf=>ty_intf + RETURNING VALUE(rv_result) TYPE xstring + RAISING zcx_abapgit_exception. + CLASS-METHODS serialize_translations + IMPORTING is_intf TYPE zcl_abapgit_object_intf=>ty_intf + it_language TYPE zif_abapgit_definitions=>ty_languages + RETURNING VALUE(rt_result) TYPE zif_abapgit_i18n_file=>ty_table_of + RAISING zcx_abapgit_exception. + CLASS-METHODS deserialize + IMPORTING iv_data TYPE string + RETURNING VALUE(rv_result) TYPE zif_abapgit_aff_intf_v1=>ty_main + RAISING zcx_abapgit_exception. + CLASS-METHODS deserialize_translation + IMPORTING io_files TYPE REF TO zcl_abapgit_objects_files + is_item TYPE zif_abapgit_definitions=>ty_item + EXPORTING et_description_int TYPE zcl_abapgit_object_intf=>ty_intf-description_int + et_description TYPE zcl_abapgit_object_intf=>ty_intf-description + et_description_sub TYPE zcl_abapgit_object_intf=>ty_intf-description_sub + RAISING zcx_abapgit_exception. + PRIVATE SECTION. + CLASS-METHODS: + "! For serialization + "! @parameter rt_result | Map/table that associates ABAP values to JSON values (enums) + get_mappings + RETURNING VALUE(rt_result) TYPE zcl_abapgit_json_handler=>ty_enum_mappings, + "! For serialization + "! @parameter rt_result | Paths that will not be serialized (depending on value) + get_paths_to_skip + RETURNING VALUE(rt_result) TYPE zcl_abapgit_json_handler=>ty_skip_paths, + fill_translation + IMPORTING iv_name TYPE seoclsname + iv_language TYPE laiso + RETURNING VALUE(rt_result) TYPE zif_abapgit_aff_intf_v1=>ty_main. +ENDCLASS. + +CLASS kHGwlUKtFBXjILcBRBJOrsxFJiznPf IMPLEMENTATION. + + METHOD serialize. + DATA: + ls_data_aff TYPE zif_abapgit_aff_intf_v1=>ty_main, + lx_exception TYPE REF TO cx_root, + lo_aff_handler TYPE REF TO zcl_abapgit_json_handler, + lo_aff_mapper TYPE REF TO zif_abapgit_aff_type_mapping, + lt_enum_mappings TYPE zcl_abapgit_json_handler=>ty_enum_mappings, + lt_paths_to_skip TYPE zcl_abapgit_json_handler=>ty_skip_paths. + CREATE OBJECT lo_aff_mapper TYPE kHGwlUKtFBXjILcBRBJOvDDGtKNvAd. + lo_aff_mapper->to_aff( EXPORTING iv_data = is_intf + IMPORTING es_data = ls_data_aff ). + + lt_enum_mappings = get_mappings( ). + lt_paths_to_skip = get_paths_to_skip( ). + + CREATE OBJECT lo_aff_handler. + TRY. + rv_result = lo_aff_handler->serialize( iv_data = ls_data_aff + iv_enum_mappings = lt_enum_mappings + iv_skip_paths = lt_paths_to_skip ). + CATCH cx_root INTO lx_exception. + zcx_abapgit_exception=>raise_with_text( lx_exception ). + ENDTRY. + + ENDMETHOD. + + METHOD get_mappings. + DATA: + ls_category_mapping TYPE zcl_abapgit_json_handler=>ty_enum_mapping, + ls_json_abap_mapping TYPE zcl_abapgit_json_handler=>ty_json_abap_mapping, + lt_json_abap_mappings TYPE zcl_abapgit_json_handler=>ty_json_abap_mappings. + + ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-general. + ls_json_abap_mapping-json = 'standard'. + APPEND ls_json_abap_mapping TO lt_json_abap_mappings. + ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-classic_badi. + ls_json_abap_mapping-json = 'classicBadi'. + APPEND ls_json_abap_mapping TO lt_json_abap_mappings. + ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-business_static_components. + ls_json_abap_mapping-json = 'businessStaticComponents'. + APPEND ls_json_abap_mapping TO lt_json_abap_mappings. + ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-db_procedure_proxy. + ls_json_abap_mapping-json = 'dbProcedureProxy'. + APPEND ls_json_abap_mapping TO lt_json_abap_mappings. + ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-web_dynpro_runtime. + ls_json_abap_mapping-json = 'webDynproRuntime'. + APPEND ls_json_abap_mapping TO lt_json_abap_mappings. + ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-enterprise_service. + ls_json_abap_mapping-json = 'enterpriseService'. + APPEND ls_json_abap_mapping TO lt_json_abap_mappings. + + ls_category_mapping-path = '/category'. + ls_category_mapping-mappings = lt_json_abap_mappings. + + APPEND ls_category_mapping TO rt_result. + ENDMETHOD. + + METHOD get_paths_to_skip. + DATA: + ls_path_to_skipp TYPE zcl_abapgit_json_handler=>ty_path_value_pair. + + ls_path_to_skipp-path = '/category'. + ls_path_to_skipp-value = 'standard'. + + APPEND ls_path_to_skipp TO rt_result. + ENDMETHOD. + + METHOD deserialize. + DATA: + lo_ajson TYPE REF TO zcl_abapgit_json_handler, + lx_exception TYPE REF TO cx_static_check, + lt_enum_mappings TYPE zcl_abapgit_json_handler=>ty_enum_mappings, + lt_default_abap_langu_version TYPE zcl_abapgit_json_handler=>ty_path_value_pair, + lt_values_for_initial TYPE zcl_abapgit_json_handler=>ty_skip_paths. + + lt_values_for_initial = get_paths_to_skip( ). + + lt_default_abap_langu_version-path = '/header/abap_language_version'. + lt_default_abap_langu_version-value = zif_abapgit_dot_abapgit=>c_abap_language_version-standard. + APPEND lt_default_abap_langu_version TO lt_values_for_initial. + + lt_enum_mappings = get_mappings( ). + CREATE OBJECT lo_ajson. + TRY. + lo_ajson->deserialize( + EXPORTING + iv_content = iv_data + iv_defaults = lt_values_for_initial + iv_enum_mappings = lt_enum_mappings + IMPORTING + ev_data = rv_result ). + CATCH cx_static_check INTO lx_exception. + zcx_abapgit_exception=>raise_with_text( lx_exception ). + ENDTRY. + + ENDMETHOD. + + METHOD serialize_translations. + DATA: ls_data TYPE zif_abapgit_aff_intf_v1=>ty_main, + lv_langu TYPE laiso, + lv_json TYPE string, + lo_ajson TYPE REF TO zif_abapgit_ajson, + lo_json_path TYPE REF TO zcl_abapgit_json_path, + lt_translation TYPE string_table, + lx_exception TYPE REF TO zcx_abapgit_ajson_error, + lo_trans_file TYPE REF TO zcl_abapgit_properties_file. + LOOP AT it_language INTO lv_langu. + + ls_data = fill_translation( iv_name = is_intf-vseointerf-clsname + iv_language = lv_langu ). + + " convert AFF type to JSON + TRY. + lo_ajson = zcl_abapgit_ajson=>new( iv_keep_item_order = abap_true + )->set( iv_path = '/' + iv_val = ls_data + )->map( zcl_abapgit_ajson_mapping=>create_to_camel_case( ) + )->filter( zcl_abapgit_ajson_filter_lib=>create_empty_filter( ) ). + " remove manually the non-primitive types that are initial or not relevant for translation + lo_ajson->delete( '/category/' ). + lo_ajson->delete( '/proxy/' ). + lv_json = lo_ajson->stringify( ). + CATCH zcx_abapgit_ajson_error INTO lx_exception. + zcx_abapgit_exception=>raise_with_text( lx_exception ). + ENDTRY. + CREATE OBJECT lo_json_path. + lt_translation = lo_json_path->serialize( lv_json ). + + CREATE OBJECT lo_trans_file + EXPORTING iv_lang = lv_langu. + + lo_trans_file->push_text_pairs( lt_translation ). + + APPEND lo_trans_file TO rt_result. + ENDLOOP. + + ENDMETHOD. + METHOD fill_translation. + DATA: lv_langu_sap1 TYPE sy-langu. + + lv_langu_sap1 = zcl_abapgit_convert=>language_sap2_to_sap1( iv_language ). + + rt_result-descriptions = kHGwlUKtFBXjILcBRBJOnvUCODLJDd=>get_descriptions_compo_subco( + iv_clif_name = iv_name + iv_language = lv_langu_sap1 ). + + SELECT SINGLE descript FROM seoclasstx INTO rt_result-header-description + WHERE clsname = iv_name AND + langu = lv_langu_sap1. + + ENDMETHOD. + METHOD deserialize_translation. + DATA: lo_properties_file TYPE REF TO zcl_abapgit_properties_file, + lt_description_int LIKE LINE OF et_description_int, + lt_translation_file TYPE zif_abapgit_i18n_file=>ty_table_of, + li_translation_file LIKE LINE OF lt_translation_file, + ls_aff_data TYPE zif_abapgit_aff_intf_v1=>ty_main, + lo_type_mapper TYPE REF TO zif_abapgit_aff_type_mapping, + ls_ag_data TYPE zcl_abapgit_object_intf=>ty_intf, + lv_sap1 TYPE sy-langu. + + lt_translation_file = io_files->read_i18n_files( ). + + LOOP AT lt_translation_file INTO li_translation_file. + + CLEAR ls_ag_data. + + lo_properties_file ?= li_translation_file. + lo_properties_file->get_translations( IMPORTING ev_data = ls_aff_data ). + + lv_sap1 = zcl_abapgit_convert=>language_sap2_to_sap1( li_translation_file->lang( ) ). + ls_aff_data-header-original_language = lv_sap1. + CREATE OBJECT lo_type_mapper TYPE kHGwlUKtFBXjILcBRBJOvDDGtKNvAd. + lo_type_mapper->to_abapgit( + EXPORTING + iv_data = ls_aff_data + iv_object_name = is_item-obj_name + IMPORTING + es_data = ls_ag_data ). + lt_description_int-clsname = ls_ag_data-vseointerf-clsname. + lt_description_int-langu = ls_ag_data-vseointerf-langu. + lt_description_int-descript = ls_ag_data-vseointerf-descript. + + APPEND lt_description_int TO et_description_int. + APPEND LINES OF ls_ag_data-description TO et_description. + APPEND LINES OF ls_ag_data-description_sub TO et_description_sub. + + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_intf IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mi_object_oriented_object_fct = zcl_abapgit_oo_factory=>get_by_type( ms_item-obj_type ). + + mv_aff_enabled = zcl_abapgit_aff_factory=>get_registry( )->is_supported_object_type( 'INTF' ). + + ENDMETHOD. + METHOD deserialize_descr_class. + DATA ls_clskey TYPE seoclskey. + ls_clskey-clsname = ms_item-obj_name. + + mi_object_oriented_object_fct->update_descriptions_class( + is_key = ls_clskey + iv_language = mv_language + it_descriptions = it_description ). + ENDMETHOD. + METHOD deserialize_descr_compo. + DATA ls_clskey TYPE seoclskey. + ls_clskey-clsname = ms_item-obj_name. + + mi_object_oriented_object_fct->update_descriptions_compo( + is_key = ls_clskey + it_descriptions = it_description ). + ENDMETHOD. + METHOD deserialize_descr_subco. + DATA ls_clskey TYPE seoclskey. + ls_clskey-clsname = ms_item-obj_name. + + mi_object_oriented_object_fct->update_descriptions_subco( + is_key = ls_clskey + it_descriptions = it_description ). + ENDMETHOD. + METHOD deserialize_docu. + DATA: lv_object TYPE dokhl-object, + ls_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_line. + + lv_object = ms_item-obj_name. + + IF lines( is_docu-lines ) = 0. + mi_object_oriented_object_fct->delete_documentation( + iv_id = c_longtext_id-interface + iv_object_name = lv_object + iv_language = mv_language ). + RETURN. + ENDIF. + + mi_object_oriented_object_fct->create_documentation( + it_lines = is_docu-lines + iv_id = c_longtext_id-interface + iv_object_name = lv_object + iv_language = mv_language ). + + LOOP AT is_docu-i18n_lines INTO ls_i18n_lines. + mi_object_oriented_object_fct->create_documentation( + it_lines = ls_i18n_lines-lines + iv_id = c_longtext_id-interface + iv_object_name = lv_object + iv_language = ls_i18n_lines-language + iv_no_masterlang = abap_true ). + ENDLOOP. + + deserialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-attributes + iv_longtext_id = c_longtext_id-attributes ). + + deserialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-methods + iv_longtext_id = c_longtext_id-methods ). + + deserialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-events + iv_longtext_id = c_longtext_id-events ). + + ENDMETHOD. + METHOD deserialize_pre_ddic. + + DATA ls_intf TYPE ty_intf. + + IF mv_aff_enabled = abap_true. + ls_intf = read_json( ). + ELSE. + ii_xml->read( EXPORTING iv_name = 'VSEOINTERF' + CHANGING cg_data = ls_intf-vseointerf ). + ENDIF. + + set_abap_language_version( CHANGING cv_abap_language_version = ls_intf-vseointerf-unicode ). + + mi_object_oriented_object_fct->create( + EXPORTING + iv_check = abap_false + iv_package = iv_package + CHANGING + cg_properties = ls_intf-vseointerf ). + + ENDMETHOD. + METHOD deserialize_proxy. + + DATA: lv_transport TYPE trkorr, + li_proxy_object TYPE REF TO if_px_main, + lv_name TYPE prx_r3name, + lx_proxy_fault TYPE REF TO cx_proxy_fault. + + lv_name = ms_item-obj_name. + + lv_transport = iv_transport. + + TRY. + li_proxy_object = cl_pxn_factory=>create( + application = 'PROXY_UI' + display_only = abap_false + saveable = abap_true + )->if_pxn_factory~load_by_abap_name( + object = ms_item-obj_type + obj_name = lv_name ). + + li_proxy_object->activate( + EXPORTING + activate_all = abap_true + CHANGING + transport_number = lv_transport ). + + li_proxy_object->dequeue( ). + + CATCH cx_proxy_fault INTO lx_proxy_fault. + IF li_proxy_object IS BOUND. + TRY. + li_proxy_object->dequeue( ). + CATCH cx_proxy_fault ##NO_HANDLER. + ENDTRY. + ENDIF. + zcx_abapgit_exception=>raise_with_text( lx_proxy_fault ). + ENDTRY. + + ENDMETHOD. + METHOD extract_languages_for_transl. + DATA: lv_desc TYPE seocompotx, + lv_desc_int TYPE seoclasstx, + lv_desc_sub TYPE seosubcotx, + lv_unique TYPE sy-langu, + lv_sap2 TYPE string, + lt_unique_language TYPE STANDARD TABLE OF sy-langu, + lv_original_language TYPE sy-langu. + lv_original_language = mo_i18n_params->ms_params-main_language. + + LOOP AT is_intf-description INTO lv_desc WHERE langu <> lv_original_language. + APPEND lv_desc-langu TO lt_unique_language. + ENDLOOP. + + LOOP AT is_intf-description_int INTO lv_desc_int WHERE langu <> lv_original_language. + APPEND lv_desc_int-langu TO lt_unique_language. + ENDLOOP. + + LOOP AT is_intf-description_sub INTO lv_desc_sub WHERE langu <> lv_original_language. + APPEND lv_desc_sub-langu TO lt_unique_language. + ENDLOOP. + + SORT lt_unique_language ASCENDING. + DELETE ADJACENT DUPLICATES FROM lt_unique_language. + + LOOP AT lt_unique_language INTO lv_unique. + lv_sap2 = zcl_abapgit_convert=>language_sap1_to_sap2( lv_unique ). + APPEND lv_sap2 TO rs_result. + ENDLOOP. + + ENDMETHOD. + METHOD read_json. + DATA lv_json_data TYPE string. + DATA ls_intf_aff TYPE zif_abapgit_aff_intf_v1=>ty_main. + DATA lo_aff_mapper TYPE REF TO zif_abapgit_aff_type_mapping. + + lv_json_data = mo_files->read_string( 'json' ). + ls_intf_aff = kHGwlUKtFBXjILcBRBJOrsxFJiznPf=>deserialize( lv_json_data ). + + CREATE OBJECT lo_aff_mapper TYPE kHGwlUKtFBXjILcBRBJOvDDGtKNvAd. + lo_aff_mapper->to_abapgit( EXPORTING iv_data = ls_intf_aff + iv_object_name = ms_item-obj_name + IMPORTING es_data = rs_intf ). + ENDMETHOD. + METHOD read_xml. + ii_xml->read( EXPORTING iv_name = 'VSEOINTERF' + CHANGING cg_data = rs_intf-vseointerf ). + ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS_INTERFACE' + CHANGING cg_data = rs_intf-description_int ). + ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS' + CHANGING cg_data = rs_intf-description ). + ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS_SUB' + CHANGING cg_data = rs_intf-description_sub ). + ii_xml->read( EXPORTING iv_name = 'LINES' + CHANGING cg_data = rs_intf-docu-lines ). + ii_xml->read( EXPORTING iv_name = 'I18N_LINES' + CHANGING cg_data = rs_intf-docu-i18n_lines ). + ENDMETHOD. + METHOD serialize_descr_class. + + DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seoclasstx_tt, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + " Main language is already in VSEOCLASS so we serialize only translations + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + lt_descriptions = mi_object_oriented_object_fct->read_descriptions_class( + iv_object_name = iv_clsname + iv_language = mv_language ). + + " Remove technical languages + lt_language_filter = mo_i18n_params->build_language_filter( ). + DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. + + IF lines( lt_descriptions ) = 0. + RETURN. + ENDIF. + + rs_description = lt_descriptions. + + ENDMETHOD. + METHOD serialize_descr_compo. + + DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, + lv_language TYPE spras, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + lv_language = mv_language. + ENDIF. + + lt_descriptions = mi_object_oriented_object_fct->read_descriptions_compo( + iv_object_name = iv_clsname + iv_language = lv_language ). + + " Remove technical languages + lt_language_filter = mo_i18n_params->build_language_filter( ). + DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. + + IF lines( lt_descriptions ) = 0. + RETURN. + ENDIF. + + rs_description = lt_descriptions. + + ENDMETHOD. + METHOD serialize_descr_subco. + + DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt, + lv_language TYPE spras, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + lv_language = mv_language. + ENDIF. + + lt_descriptions = mi_object_oriented_object_fct->read_descriptions_subco( + iv_object_name = iv_clsname + iv_language = lv_language ). + + " Remove technical languages + lt_language_filter = mo_i18n_params->build_language_filter( ). + DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. + + IF lines( lt_descriptions ) = 0. + RETURN. + ENDIF. + + rs_description = lt_descriptions. + + ENDMETHOD. + METHOD serialize_docu. + + DATA: lt_lines TYPE tlinetab, + lv_object TYPE dokhl-object, + lv_langu TYPE sy-langu, + lt_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_lines, + ls_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_line. + + lv_object = iv_clsname. + + lt_lines = mi_object_oriented_object_fct->read_documentation( + iv_id = c_longtext_id-interface + iv_object_name = lv_object + iv_language = mv_language ). + + rs_docu-lines = lt_lines. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + LOOP AT it_langu_additional INTO lv_langu. + + lt_lines = mi_object_oriented_object_fct->read_documentation( + iv_id = c_longtext_id-interface + iv_object_name = lv_object + iv_language = lv_langu ). + + IF lines( lt_lines ) > 0. + CLEAR ls_i18n_lines. + ls_i18n_lines-language = lv_langu. + ls_i18n_lines-lines = lt_lines. + INSERT ls_i18n_lines INTO TABLE lt_i18n_lines. + ENDIF. + + ENDLOOP. + + rs_docu-i18n_lines = lt_i18n_lines. + + ENDMETHOD. + METHOD serialize_xml. + + DATA: + ls_intf TYPE ty_intf, + ls_clskey TYPE seoclskey, + lv_serialized_data TYPE xstring, + lt_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus, + lt_i18n_file TYPE zif_abapgit_i18n_file=>ty_table_of, + lo_i18n_file TYPE REF TO zif_abapgit_i18n_file, + lt_languages_for_translation TYPE zif_abapgit_definitions=>ty_languages. + + ls_clskey-clsname = ms_item-obj_name. + + ls_intf-vseointerf = mi_object_oriented_object_fct->get_interface_properties( ls_clskey ). + + clear_abap_language_version( CHANGING cv_abap_language_version = ls_intf-vseointerf-unicode ). + + " Select all active translations of documentation + " Skip main language - it was already serialized + SELECT DISTINCT langu + INTO TABLE lt_langu_additional + FROM dokhl + WHERE id = c_longtext_id-interface + AND object = ls_clskey-clsname + AND langu <> mv_language + ORDER BY langu. + + ls_intf-docu = serialize_docu( + iv_clsname = ls_clskey-clsname + it_langu_additional = lt_langu_additional ). + + ls_intf-description_int = serialize_descr_class( ls_clskey-clsname ). + ls_intf-description = serialize_descr_compo( ls_clskey-clsname ). + ls_intf-description_sub = serialize_descr_subco( ls_clskey-clsname ). + + " HERE: switch with feature flag for XML or JSON file format + IF mv_aff_enabled = abap_true. + lv_serialized_data = kHGwlUKtFBXjILcBRBJOrsxFJiznPf=>serialize( ls_intf ). + mo_files->add_raw( iv_ext = 'json' + iv_data = lv_serialized_data ). + + lt_languages_for_translation = extract_languages_for_transl( ls_intf ). + + lt_i18n_file = kHGwlUKtFBXjILcBRBJOrsxFJiznPf=>serialize_translations( + is_intf = ls_intf + it_language = lt_languages_for_translation ). + + LOOP AT lt_i18n_file INTO lo_i18n_file. + mo_files->add_i18n_file( lo_i18n_file ). + ENDLOOP. + ELSE. + io_xml->add( iv_name = 'VSEOINTERF' + ig_data = ls_intf-vseointerf ). + io_xml->add( iv_name = 'DESCRIPTIONS_INTERFACE' + ig_data = ls_intf-description_int ). + io_xml->add( iv_name = 'DESCRIPTIONS' + ig_data = ls_intf-description ). + io_xml->add( iv_name = 'DESCRIPTIONS_SUB' + ig_data = ls_intf-description_sub ). + io_xml->add( iv_name = 'LINES' + ig_data = ls_intf-docu-lines ). + io_xml->add( iv_name = 'I18N_LINES' + ig_data = ls_intf-docu-i18n_lines ). + + serialize_longtexts( + ii_xml = io_xml + iv_longtext_name = c_longtext_name-attributes + iv_longtext_id = c_longtext_id-attributes ). + + serialize_longtexts( + ii_xml = io_xml + iv_longtext_name = c_longtext_name-methods + iv_longtext_id = c_longtext_id-methods ). + + serialize_longtexts( + ii_xml = io_xml + iv_longtext_name = c_longtext_name-events + iv_longtext_id = c_longtext_id-events ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + TYPES: BEGIN OF ty_includes, + programm TYPE syrepid, + END OF ty_includes. + + TYPES: BEGIN OF ty_reposrc, + unam TYPE reposrc-unam, + udat TYPE reposrc-udat, + utime TYPE reposrc-utime, + END OF ty_reposrc. + + DATA: lt_reposrc TYPE STANDARD TABLE OF ty_reposrc, + ls_reposrc LIKE LINE OF lt_reposrc, + lt_includes TYPE STANDARD TABLE OF ty_includes. + + lt_includes = mi_object_oriented_object_fct->get_includes( ms_item-obj_name ). + ASSERT lines( lt_includes ) > 0. + + SELECT unam udat utime FROM reposrc + INTO TABLE lt_reposrc + FOR ALL ENTRIES IN lt_includes + WHERE progname = lt_includes-programm + AND r3state = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ELSE. + SORT lt_reposrc BY udat DESCENDING utime DESCENDING. + READ TABLE lt_reposrc INDEX 1 INTO ls_reposrc. + ASSERT sy-subrc = 0. + rv_user = ls_reposrc-unam. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + DATA: ls_clskey TYPE seoclskey, + ls_vseointerf TYPE vseointerf. + + ls_clskey-clsname = ms_item-obj_name. + ls_vseointerf = mi_object_oriented_object_fct->get_interface_properties( ls_clskey ). + + IF ls_vseointerf-clsproxy = abap_true. + " Proxy interfaces are managed via SPRX + RETURN. + ENDIF. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + corr_insert( iv_package ). + + mi_object_oriented_object_fct->delete( ls_clskey ). + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + DATA: + lt_source TYPE rswsourcet, + ls_clskey TYPE seoclskey, + ls_intf TYPE ty_intf, + lt_description TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, + lt_description_int TYPE zif_abapgit_oo_object_fnc=>ty_seoclasstx_tt, + lt_description_sub TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt. + + IF iv_step = zif_abapgit_object=>gc_step_id-abap. + " HERE: switch with feature flag between XML and JSON file format + IF mv_aff_enabled = abap_true. + ls_intf = read_json( ). + + kHGwlUKtFBXjILcBRBJOrsxFJiznPf=>deserialize_translation( + EXPORTING + io_files = mo_files + is_item = ms_item + IMPORTING + et_description = lt_description + et_description_int = lt_description_int + et_description_sub = lt_description_sub ). + + APPEND LINES OF lt_description TO ls_intf-description. + APPEND LINES OF lt_description_int TO ls_intf-description_int. + APPEND LINES OF lt_description_sub TO ls_intf-description_sub. + + ELSE. + ls_intf = read_xml( io_xml ). + ENDIF. + + set_abap_language_version( CHANGING cv_abap_language_version = ls_intf-vseointerf-unicode ). + + IF ls_intf-vseointerf-clsproxy = abap_true. + " Proxy interfaces are managed via SPRX + deserialize_proxy( iv_transport ). + + ELSE. + mi_object_oriented_object_fct->create( + EXPORTING + iv_check = abap_true + iv_package = iv_package + CHANGING + cg_properties = ls_intf-vseointerf ). + + ls_clskey-clsname = ms_item-obj_name. + lt_source = mo_files->read_abap( ). + + mi_object_oriented_object_fct->deserialize_source( + is_key = ls_clskey + iv_package = iv_package + iv_version = ls_intf-vseointerf-unicode + it_source = lt_source ). + + deserialize_descr_class( ls_intf-description_int ). + + deserialize_descr_compo( ls_intf-description ). + + deserialize_descr_subco( ls_intf-description_sub ). + + deserialize_docu( + is_docu = ls_intf-docu + ii_xml = io_xml ). + + mi_object_oriented_object_fct->add_to_activation_list( ms_item ). + ENDIF. + + ELSEIF iv_step = zif_abapgit_object=>gc_step_id-early. + + " If interface does not exist, create it + " so DDIC that depends on it does not fail activation + IF zif_abapgit_object~exists( ) = abap_false. + deserialize_pre_ddic( + ii_xml = io_xml + iv_package = iv_package ). + ELSE. + corr_insert( iv_package ). + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_class_key TYPE seoclskey, + lv_category TYPE seoclassdf-category. + + ls_class_key-clsname = ms_item-obj_name. + + rv_bool = mi_object_oriented_object_fct->exists( ls_class_key-clsname ). + + IF rv_bool = abap_true. + SELECT SINGLE category FROM seoclassdf INTO lv_category + WHERE clsname = ls_class_key-clsname + AND ( version = '1' + OR version = '0' ) ##WARN_OK. "#EC CI_GENBUFF + IF sy-subrc = 0 AND lv_category = seoc_category_webdynpro_class. + rv_bool = abap_false. + ELSE. + SELECT SINGLE obj_name FROM sproxhdr INTO ls_class_key-clsname + WHERE object = 'INTF' AND obj_name = ls_class_key-clsname. + IF sy-subrc = 0. + " generated by proxy + rv_bool = abap_false. + ENDIF. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-early TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_object TYPE eqegraarg. + + lv_object = |{ ms_item-obj_name }|. + OVERLAY lv_object WITH '==============================P'. + lv_object = lv_object && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESEOCLASS' + iv_argument = lv_object ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lt_source TYPE seop_source_string, + ls_interface_key TYPE seoclskey. + + ls_interface_key-clsname = ms_item-obj_name. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + version = seoc_version_active + force = abap_true. + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + version = seoc_version_inactive + force = abap_true. + + lt_source = mi_object_oriented_object_fct->serialize_abap( ls_interface_key ). + + mo_files->add_abap( lt_source ). + + serialize_xml( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iext IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_extension = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_attributes TYPE edi_iapi01. + + CALL FUNCTION 'EXTTYPE_READ' + EXPORTING + pi_cimtyp = mv_extension + IMPORTING + pe_attributes = ls_attributes + EXCEPTIONS + OTHERS = 1. + IF sy-subrc = 0. + rv_user = ls_attributes-plast. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + CALL FUNCTION 'EXTTYPE_DELETE' + EXPORTING + pi_cimtyp = mv_extension + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_extension TYPE ty_extention, + ls_attributes TYPE edi_iapi05. + + io_xml->read( EXPORTING iv_name = c_dataname_iext + CHANGING cg_data = ls_extension ). + + MOVE-CORRESPONDING ls_extension-attributes TO ls_attributes. + ls_attributes-presp = sy-uname. + ls_attributes-pwork = ls_attributes-presp. + + IF zif_abapgit_object~exists( ) = abap_true. + CALL FUNCTION 'EXTTYPE_UPDATE' + EXPORTING + pi_cimtyp = mv_extension + pi_attributes = ls_attributes + TABLES + pt_syntax = ls_extension-t_syntax + EXCEPTIONS + OTHERS = 1. + ELSE. + " Avoid popup asking for package + tadir_insert( iv_package ). + + CALL FUNCTION 'EXTTYPE_CREATE' + EXPORTING + pi_cimtyp = mv_extension + pi_devclass = iv_package + pi_attributes = ls_attributes + TABLES + pt_syntax = ls_extension-t_syntax + EXCEPTIONS + OTHERS = 1. + ENDIF. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL FUNCTION 'EXTTYPE_READ' + EXPORTING + pi_cimtyp = mv_extension + EXCEPTIONS + OTHERS = 1. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMSED5'. + -dynpro = '0010'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'SED5STRUC-OBJECT'. + -fval = ms_item-obj_name. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'SED5STRUC-SELECT_EXT'. + -fval = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=DISP'. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'WE30' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA ls_extension TYPE ty_extention. + + CALL FUNCTION 'EXTTYPE_READ' + EXPORTING + pi_cimtyp = mv_extension + IMPORTING + pe_attributes = ls_extension-attributes + TABLES + pt_syntax = ls_extension-t_syntax + EXCEPTIONS + OTHERS = 1. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + zcl_abapgit_object_idoc=>clear_idoc_segement_fields( CHANGING cg_structure = ls_extension-attributes ). + + io_xml->add( iv_name = c_dataname_iext + ig_data = ls_extension ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_idoc IMPLEMENTATION. + METHOD clear_idoc_segement_field. + + FIELD-SYMBOLS TYPE any. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cg_structure TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + ENDMETHOD. + METHOD clear_idoc_segement_fields. + + clear_idoc_segement_field( EXPORTING iv_fieldname = 'DEVC' + CHANGING cg_structure = cg_structure ). + clear_idoc_segement_field( EXPORTING iv_fieldname = 'PLAST' + CHANGING cg_structure = cg_structure ). + clear_idoc_segement_field( EXPORTING iv_fieldname = 'PWORK' + CHANGING cg_structure = cg_structure ). + clear_idoc_segement_field( EXPORTING iv_fieldname = 'PRESP' + CHANGING cg_structure = cg_structure ). + clear_idoc_segement_field( EXPORTING iv_fieldname = 'CREDATE' + CHANGING cg_structure = cg_structure ). + clear_idoc_segement_field( EXPORTING iv_fieldname = 'CRETIME' + CHANGING cg_structure = cg_structure ). + clear_idoc_segement_field( EXPORTING iv_fieldname = 'LDATE' + CHANGING cg_structure = cg_structure ). + clear_idoc_segement_field( EXPORTING iv_fieldname = 'LTIME' + CHANGING cg_structure = cg_structure ). + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_idoctyp = ms_item-obj_name. + + ENDMETHOD. + METHOD is_closed. + + DATA ls_idoc TYPE ty_idoc. + + CALL FUNCTION 'IDOCTYPE_READ' + EXPORTING + pi_idoctyp = mv_idoctyp + IMPORTING + pe_attributes = ls_idoc-attributes + EXCEPTIONS + object_not_found = 1 + db_error = 2 + no_authority = 3 + OTHERS = 4. + rv_closed = boolc( sy-subrc = 0 AND ls_idoc-attributes-closed = abap_true ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_attributes TYPE edi_iapi01. + + CALL FUNCTION 'IDOCTYPE_READ' + EXPORTING + pi_idoctyp = mv_idoctyp + IMPORTING + pe_attributes = ls_attributes + EXCEPTIONS + object_not_found = 1 + db_error = 2 + no_authority = 3 + OTHERS = 4. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + rv_user = ls_attributes-plast. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + CALL FUNCTION 'IDOCTYPE_DELETE' + EXPORTING + pi_idoctyp = mv_idoctyp + EXCEPTIONS + object_not_found = 1 + lock_error = 2 + action_not_possible = 3 + transport_error = 4 + db_error = 5 + no_authority = 6 + OTHERS = 7. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_idoc TYPE ty_idoc, + lv_transport TYPE trkorr, + ls_edbas TYPE edbas, + ls_attributes TYPE edi_iapi05. + + io_xml->read( + EXPORTING + iv_name = 'IDOC' + CHANGING + cg_data = ls_idoc ). + + MOVE-CORRESPONDING ls_idoc-attributes TO ls_attributes. + + IF zif_abapgit_object~exists( ) = abap_false. + " Avoid popup asking for package + tadir_insert( iv_package ). + + CALL FUNCTION 'IDOCTYPE_CREATE' + EXPORTING + pi_idoctyp = mv_idoctyp + pi_devclass = iv_package + pi_attributes = ls_attributes + TABLES + pt_syntax = ls_idoc-t_syntax + EXCEPTIONS + object_not_found = 1 + object_exists = 2 + syntax_error = 3 + segment_error = 4 + transport_error = 5 + db_error = 6 + no_authority = 7 + OTHERS = 8. + ELSE. + IF is_closed( ) = abap_true. + CALL FUNCTION 'IDOCTYPE_UNCLOSE' + EXPORTING + pi_idoctyp = mv_idoctyp + EXCEPTIONS + object_not_found = 1 + action_not_possible = 2 + db_error = 3 + no_authority = 4 + OTHERS = 5. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + CALL FUNCTION 'IDOCTYPE_UPDATE' + EXPORTING + pi_idoctyp = mv_idoctyp + pi_attributes = ls_attributes + TABLES + pt_syntax = ls_idoc-t_syntax + EXCEPTIONS + object_not_found = 1 + object_exists = 2 + syntax_error = 3 + segment_error = 4 + transport_error = 5 + db_error = 6 + no_authority = 7 + OTHERS = 8. + ENDIF. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF ls_idoc-attributes-closed = abap_true. + IF iv_transport IS NOT INITIAL. + lv_transport = iv_transport. + + CALL FUNCTION 'IDOCTYPE_CLOSE' + EXPORTING + pi_idoctyp = mv_idoctyp + CHANGING + pc_order = lv_transport + EXCEPTIONS + object_not_found = 1 + action_not_possible = 2 + db_error = 3 + no_authority = 4 + OTHERS = 5. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + " IDOCTYPE_CLOSE saves current release but it should be same as in repo + SELECT SINGLE * FROM edbas INTO ls_edbas WHERE idoctyp = mv_idoctyp. + ls_edbas-released = ls_idoc-attributes-released. + ls_edbas-applrel = ls_idoc-attributes-applrel. + ls_edbas-closed = ls_idoc-attributes-closed. + UPDATE edbas FROM ls_edbas. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error updating IDOC { mv_idoctyp }| ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL FUNCTION 'IDOCTYPE_EXISTENCE_CHECK' + EXPORTING + pi_idoctyp = mv_idoctyp + EXCEPTIONS + object_not_found = 1 + db_error = 2 + OTHERS = 3. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMSED5'. + -dynpro = '0010'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'SED5STRUC-OBJECT'. + -fval = ms_item-obj_name. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'SED5STRUC-SELECT_ORG'. + -fval = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=DISP'. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'WE30' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_idoc TYPE ty_idoc. + + CALL FUNCTION 'IDOCTYPE_READ' + EXPORTING + pi_idoctyp = mv_idoctyp + IMPORTING + pe_attributes = ls_idoc-attributes + TABLES + pt_syntax = ls_idoc-t_syntax + EXCEPTIONS + object_not_found = 1 + db_error = 2 + no_authority = 3 + OTHERS = 4. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + clear_idoc_segement_fields( CHANGING cg_structure = ls_idoc-attributes ). + + io_xml->add( iv_name = 'IDOC' + ig_data = ls_idoc ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iaxu IMPLEMENTATION. + METHOD read. + + DATA: ls_name TYPE iacikeyt. + ls_name = ms_item-obj_name. + + w3_api_load( EXPORTING is_name = ls_name + IMPORTING es_attr = rs_attr ). + + CLEAR: rs_attr-chname, + rs_attr-tdate, + rs_attr-ttime, + rs_attr-devclass. + + ENDMETHOD. + METHOD save. + + DATA: lo_xml_api TYPE REF TO object. + + lo_xml_api = w3_api_create_new( is_attr ). + + w3_api_save( lo_xml_api ). + + w3_api_set_changeable( io_xml_api = lo_xml_api + iv_changeable = abap_false ). + + ENDMETHOD. + METHOD w3_api_create_new. + + DATA: lr_xml_api TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any. + + CREATE DATA lr_xml_api TYPE REF TO ('CL_W3_API_XML3'). + ASSIGN lr_xml_api->* TO . + ASSERT sy-subrc = 0. + + CALL METHOD ('CL_W3_API_XML3')=>create_new + EXPORTING + p_source_style_2006 = mv_source_style_2006 + p_xml_data = is_attr + p_generator_class = mv_generator_class + p_program_name = is_attr-programm + IMPORTING + p_xml = + EXCEPTIONS + undefined_name = 1 + error_occured = 2 + object_already_existing = 3 + not_authorized = 4 + action_cancelled = 5 + OTHERS = 6. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_xml3~create_new subrc={ sy-subrc }| ). + ENDIF. + + ro_xml_api ?= . + + ENDMETHOD. + METHOD w3_api_delete. + + CALL METHOD io_xml_api->('IF_W3_API_OBJECT~DELETE') + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + error_occured = 4 + OTHERS = 5. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_xml3~delete subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_load. + + DATA: lr_xml_api TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any. + + CREATE DATA lr_xml_api TYPE REF TO ('CL_W3_API_XML3'). + ASSIGN lr_xml_api->* TO . + ASSERT sy-subrc = 0. + + CALL METHOD ('CL_W3_API_XML3')=>load + EXPORTING + p_xml_name = is_name + IMPORTING + p_attributes = es_attr + p_xml = + EXCEPTIONS + object_not_existing = 1 + permission_failure = 2 + data_corrupt = 3 + error_occured = 4 + OTHERS = 5. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_xml3~load subrc={ sy-subrc }| ). + ENDIF. + + eo_xml_api ?= . + + ENDMETHOD. + METHOD w3_api_save. + + CALL METHOD io_xml_api->('IF_W3_API_OBJECT~SAVE') + EXCEPTIONS + object_invalid = 1 + object_not_changeable = 2 + action_cancelled = 3 + permission_failure = 4 + not_changed = 5 + data_invalid = 6 + error_occured = 7 + OTHERS = 8. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_xml3~save subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_changeable. + + CALL METHOD io_xml_api->('IF_W3_API_OBJECT~SET_CHANGEABLE') + EXPORTING + p_changeable = iv_changeable + EXCEPTIONS + action_cancelled = 1 + object_locked_by_other_user = 2 + permission_failure = 3 + object_already_changeable = 4 + object_already_unlocked = 5 + object_just_created = 6 + object_deleted = 7 + object_modified = 8 + object_not_existing = 9 + object_invalid = 10 + error_occured = 11 + OTHERS = 12. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_xml3~set_changeable subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = read( )-chname. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_xml_api TYPE REF TO object, + ls_name TYPE iacikeyt. + + ls_name = ms_item-obj_name. + + w3_api_load( EXPORTING is_name = ls_name + IMPORTING eo_xml_api = lo_xml_api ). + + w3_api_set_changeable( io_xml_api = lo_xml_api + iv_changeable = abap_true ). + + w3_api_delete( lo_xml_api ). + + w3_api_save( lo_xml_api ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_attr TYPE w3tempattr. + io_xml->read( EXPORTING iv_name = 'ATTR' + CHANGING cg_data = ls_attr ). + + ls_attr-devclass = iv_package. + + IF zif_abapgit_object~exists( ) = abap_true. + zif_abapgit_object~delete( iv_package = iv_package + iv_transport = iv_transport ). + ENDIF. + + save( ls_attr ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_name TYPE iacikeyt. + ls_name = ms_item-obj_name. + + CALL METHOD ('CL_W3_API_XML3')=>s_check_exist + EXPORTING + p_xml_name = ls_name + IMPORTING + p_exists = rv_bool. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_attr TYPE w3tempattr. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + ls_attr = read( ). + + io_xml->add( iv_name = 'ATTR' + ig_data = ls_attr ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iatu IMPLEMENTATION. + METHOD read. + + DATA: li_template TYPE REF TO if_w3_api_template, + lt_source TYPE w3htmltabtype, + ls_name TYPE iacikeyt. + + ls_name = ms_item-obj_name. + + li_template = w3_api_load( ls_name ). + + es_attr = w3_api_get_attributes( li_template ). + + CLEAR: es_attr-chname, + es_attr-tdate, + es_attr-ttime, + es_attr-devclass. + + lt_source = w3_api_get_source( li_template ). + + CONCATENATE LINES OF lt_source INTO ev_source RESPECTING BLANKS. + + ENDMETHOD. + METHOD save. + + DATA: lt_source TYPE w3htmltabtype, + lv_source TYPE string, + li_template TYPE REF TO if_w3_api_template. + li_template = w3_api_create_new( is_attr ). + + w3_api_set_attributes( ii_template = li_template + is_attr = is_attr ). + + lv_source = iv_source. + WHILE strlen( lv_source ) >= 255. + APPEND lv_source(255) TO lt_source. + lv_source = lv_source+255. + ENDWHILE. + IF NOT lv_source IS INITIAL. + APPEND lv_source TO lt_source. + ENDIF. + + w3_api_set_source( ii_template = li_template + it_source = lt_source ). + + w3_api_save( li_template ). + + " Release locks + w3_api_set_changeable( + ii_template = li_template + iv_changeable = abap_false ). + + ENDMETHOD. + METHOD w3_api_create_new. + + cl_w3_api_template=>if_w3_api_template~create_new( + EXPORTING + p_template_data = is_template_data + p_program_name = is_template_data-programm + IMPORTING + p_template = ri_template + EXCEPTIONS + object_already_existing = 1 + object_just_created = 2 + not_authorized = 3 + undefined_name = 4 + author_not_existing = 5 + action_cancelled = 6 + error_occured = 7 + user_error = 8 + OTHERS = 9 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_template~create_new subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_delete. + + ii_template->if_w3_api_object~delete( + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + error_occured = 4 + OTHERS = 5 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_template~delete subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_get_attributes. + + ii_template->get_attributes( + IMPORTING + p_attributes = rs_attributes + EXCEPTIONS + object_invalid = 1 + template_deleted = 2 + error_occured = 3 + OTHERS = 4 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_template~get_attributes subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_get_source. + + ii_template->get_source( + IMPORTING + p_source = rt_source + EXCEPTIONS + object_invalid = 1 + template_deleted = 2 + error_occured = 3 + OTHERS = 4 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_template~get_source subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_load. + + cl_w3_api_template=>if_w3_api_template~load( + EXPORTING + p_template_name = is_name + IMPORTING + p_template = ri_template + EXCEPTIONS + object_not_existing = 1 + permission_failure = 2 + error_occured = 3 + OTHERS = 4 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from if_w3_api_template~load subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_save. + + ii_template->if_w3_api_object~save( + EXCEPTIONS + object_invalid = 1 + object_not_changeable = 2 + action_cancelled = 3 + permission_failure = 4 + not_changed = 5 + data_invalid = 6 + error_occured = 7 + OTHERS = 8 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_template~save subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_attributes. + + ii_template->set_attributes( + EXPORTING + p_attributes = is_attr + EXCEPTIONS + object_not_changeable = 1 + object_deleted = 2 + object_invalid = 3 + author_not_existing = 4 + authorize_failure = 5 + error_occured = 6 + OTHERS = 7 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_template~set_attributes subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_changeable. + + ii_template->if_w3_api_object~set_changeable( + EXPORTING + p_changeable = iv_changeable + EXCEPTIONS + action_cancelled = 1 + object_locked_by_other_user = 2 + permission_failure = 3 + object_already_changeable = 4 + object_already_unlocked = 5 + object_just_created = 6 + object_deleted = 7 + object_modified = 8 + object_not_existing = 9 + object_invalid = 10 + error_occured = 11 + OTHERS = 12 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_template~set_changeable subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_source. + + ii_template->set_source( + EXPORTING + p_source = it_source + EXCEPTIONS + object_not_changeable = 1 + object_deleted = 2 + object_invalid = 3 + authorize_failure = 4 + invalid_parameter = 5 + error_occured = 6 + OTHERS = 7 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from w3_api_template~set_source subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA ls_attributes TYPE w3tempattr. + + read( IMPORTING es_attr = ls_attributes ). + + rv_user = ls_attributes-chname. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: li_template TYPE REF TO if_w3_api_template, + ls_name TYPE iacikeyt. + ls_name = ms_item-obj_name. + + li_template = w3_api_load( ls_name ). + + w3_api_set_changeable( ii_template = li_template + iv_changeable = abap_true ). + + w3_api_delete( li_template ). + + w3_api_save( li_template ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_attr TYPE w3tempattr, + lv_source TYPE string. + io_xml->read( EXPORTING iv_name = 'ATTR' + CHANGING cg_data = ls_attr ). + + lv_source = mo_files->read_string( 'html' ). + + ls_attr-devclass = iv_package. + save( is_attr = ls_attr + iv_source = lv_source ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_name TYPE iacikeyt. + ls_name = ms_item-obj_name. + + cl_w3_api_template=>s_check_exist( EXPORTING p_template_name = ls_name + IMPORTING p_exists = rv_bool ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_attr TYPE w3tempattr, + lv_source TYPE string. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + read( IMPORTING es_attr = ls_attr + ev_source = lv_source ). + + io_xml->add( iv_name = 'ATTR' + ig_data = ls_attr ). + + mo_files->add_string( + iv_ext = 'html' + iv_string = lv_source ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iasp IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_name = ms_item-obj_name. + + ENDMETHOD. + METHOD read. + + DATA: li_service TYPE REF TO if_w3_api_service. + + li_service = w3_api_load( ). + es_attr = w3_api_get_attributes( li_service ). + + CLEAR: es_attr-chname, + es_attr-tdate, + es_attr-ttime, + es_attr-devclass. + + et_parameters = w3_api_get_parameters( li_service ). + + ENDMETHOD. + METHOD save. + + DATA: li_service TYPE REF TO if_w3_api_service. + + li_service = w3_api_create_new( is_attr ). + + w3_api_set_attributes( + ii_service = li_service + is_attributes = is_attr ). + + w3_api_set_parameters( + ii_service = li_service + it_parameters = it_parameters ). + + w3_api_save( li_service ). + + " Release locks + w3_api_set_changeable( + ii_service = li_service + iv_changeable = abap_false ). + + ENDMETHOD. + METHOD w3_api_create_new. + + cl_w3_api_service=>if_w3_api_service~create_new( + EXPORTING + p_service_data = is_attributes + IMPORTING + p_service = ri_service + EXCEPTIONS + object_already_existing = 1 + object_just_created = 2 + not_authorized = 3 + undefined_name = 4 + author_not_existing = 5 + action_cancelled = 6 + error_occured = 7 + invalid_parameter = 8 + OTHERS = 9 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_service~create_new. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_delete. + + ii_service->if_w3_api_object~delete( + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + error_occured = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_object~delete. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_get_attributes. + + ii_service->get_attributes( IMPORTING p_attributes = rs_attributes ). + + ENDMETHOD. + METHOD w3_api_get_parameters. + + ii_service->get_parameters( IMPORTING p_parameters = rt_parameters ). + + ENDMETHOD. + METHOD w3_api_load. + + cl_w3_api_service=>if_w3_api_service~load( + EXPORTING + p_service_name = mv_name + IMPORTING + p_service = ri_service + EXCEPTIONS + object_not_existing = 1 + permission_failure = 2 + error_occured = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from w3api_service~load' ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_save. + + ii_service->if_w3_api_object~save( + EXCEPTIONS + object_invalid = 1 + object_not_changeable = 2 + action_cancelled = 3 + permission_failure = 4 + not_changed = 5 + data_invalid = 6 + error_occured = 7 + OTHERS = 8 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_object~save. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_attributes. + + ii_service->set_attributes( + EXPORTING + p_attributes = is_attributes + EXCEPTIONS + object_not_changeable = 1 + object_deleted = 2 + object_invalid = 3 + author_not_existing = 4 + authorize_failure = 5 + error_occured = 6 + OTHERS = 7 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_service~set_attributes. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_changeable. + + ii_service->if_w3_api_object~set_changeable( + EXPORTING + p_changeable = iv_changeable + EXCEPTIONS + action_cancelled = 1 + object_locked_by_other_user = 2 + permission_failure = 3 + object_already_changeable = 4 + object_already_unlocked = 5 + object_just_created = 6 + object_deleted = 7 + object_modified = 8 + object_not_existing = 9 + object_invalid = 10 + error_occured = 11 + OTHERS = 12 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_object~set_changeable. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_parameters. + + ii_service->set_parameters( + EXPORTING + p_parameters = it_parameters + EXCEPTIONS + object_not_changeable = 1 + object_deleted = 2 + object_invalid = 3 + authorize_failure = 4 + invalid_parameter = 5 + error_occured = 6 + OTHERS = 7 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_service~set_parameters. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " todo + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: li_service TYPE REF TO if_w3_api_service. + + li_service = w3_api_load( ). + + w3_api_set_changeable( li_service ). + w3_api_delete( li_service ). + w3_api_save( li_service ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_attr TYPE w3servattr, + lt_parameters TYPE w3servpara_tabletype. + io_xml->read( EXPORTING iv_name = 'ATTR' + CHANGING cg_data = ls_attr ). + io_xml->read( EXPORTING iv_name = 'PARAMETERS' + CHANGING cg_data = lt_parameters ). + + ls_attr-devclass = iv_package. + save( is_attr = ls_attr + it_parameters = lt_parameters ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lx_error TYPE REF TO zcx_abapgit_exception. + + TRY. + w3_api_load( ). + rv_bool = abap_true. + + CATCH zcx_abapgit_exception INTO lx_error. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_attr TYPE w3servattr, + lt_parameters TYPE w3servpara_tabletype. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + read( IMPORTING es_attr = ls_attr + et_parameters = lt_parameters ). + + io_xml->add( iv_name = 'ATTR' + ig_data = ls_attr ). + io_xml->add( iv_name = 'PARAMETERS' + ig_data = lt_parameters ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iarp IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + ms_name = ms_item-obj_name. + + ENDMETHOD. + METHOD read. + + DATA: li_resource TYPE REF TO if_w3_api_resource. + + li_resource = w3_api_load( ). + es_attributes = w3_api_get_attributes( li_resource ). + + CLEAR: es_attributes-chname, + es_attributes-tdate, + es_attributes-ttime, + es_attributes-devclass. + + et_parameters = w3_api_get_parameters( li_resource ). + + ENDMETHOD. + METHOD save. + + DATA: li_resource TYPE REF TO if_w3_api_resource. + + li_resource = w3_api_create_new( is_attributes ). + + w3_api_set_attributes( + ii_resource = li_resource + is_attributes = is_attributes ). + + w3_api_set_parameters( + ii_resource = li_resource + it_parameters = it_parameters ). + + w3_api_save( li_resource ). + + " Release locks + w3_api_set_changeable( + ii_resource = li_resource + iv_changeable = abap_false ). + + ENDMETHOD. + METHOD w3_api_create_new. + + cl_w3_api_resource=>if_w3_api_resource~create_new( + EXPORTING + p_resource_data = is_attributes + IMPORTING + p_resource = ri_resource + EXCEPTIONS + object_already_existing = 1 + object_just_created = 2 + not_authorized = 3 + undefined_name = 4 + author_not_existing = 5 + action_cancelled = 6 + error_occured = 7 + OTHERS = 8 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_resource~create_new. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_delete. + + ii_resource->if_w3_api_object~delete( + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + error_occured = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_object~delete. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_get_attributes. + + ii_resource->get_attributes( + IMPORTING + p_attributes = rs_attributes + EXCEPTIONS + object_invalid = 1 + resource_deleted = 2 + error_occured = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_resource~get_attributes. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_get_parameters. + + ii_resource->get_parameters( + IMPORTING + p_parameters = rt_parameters + EXCEPTIONS + object_invalid = 1 + resource_deleted = 2 + error_occured = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_resource~get_parameters. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_load. + + cl_w3_api_resource=>if_w3_api_resource~load( + EXPORTING + p_resource_name = ms_name + IMPORTING + p_resource = ri_resource + EXCEPTIONS + object_not_existing = 1 + permission_failure = 2 + error_occured = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from w3api_resource~load. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_save. + + ii_resource->if_w3_api_object~save( + EXCEPTIONS + object_invalid = 1 + object_not_changeable = 2 + action_cancelled = 3 + permission_failure = 4 + not_changed = 5 + data_invalid = 6 + error_occured = 7 + OTHERS = 8 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_object~save. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_attributes. + + ii_resource->set_attributes( + EXPORTING + p_attributes = is_attributes + EXCEPTIONS + object_not_changeable = 1 + object_deleted = 2 + object_invalid = 3 + author_not_existing = 4 + authorize_failure = 5 + error_occured = 6 + OTHERS = 7 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_resource~set_attributes. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_changeable. + + ii_resource->if_w3_api_object~set_changeable( + EXPORTING + p_changeable = iv_changeable + EXCEPTIONS + action_cancelled = 1 + object_locked_by_other_user = 2 + permission_failure = 3 + object_already_changeable = 4 + object_already_unlocked = 5 + object_just_created = 6 + object_deleted = 7 + object_modified = 8 + object_not_existing = 9 + object_invalid = 10 + error_occured = 11 + OTHERS = 12 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_object~set_changeable. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD w3_api_set_parameters. + + ii_resource->set_parameters( + EXPORTING + p_parameters = it_parameters + EXCEPTIONS + object_not_changeable = 1 + object_deleted = 2 + object_invalid = 3 + authorize_failure = 4 + invalid_parameter = 5 + error_occured = 6 + OTHERS = 7 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |error from if_w3_api_resource~set_parameters. Subrc={ sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA ls_attributes TYPE w3resoattr. + + read( IMPORTING es_attributes = ls_attributes ). + + rv_user = ls_attributes-chname. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: li_resource TYPE REF TO if_w3_api_resource. + + li_resource = w3_api_load( ). + w3_api_set_changeable( li_resource ). + w3_api_delete( li_resource ). + w3_api_save( li_resource ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_attr TYPE w3resoattr, + lt_parameters TYPE w3resopara_tabletype. + io_xml->read( EXPORTING iv_name = 'ATTR' + CHANGING cg_data = ls_attr ). + io_xml->read( EXPORTING iv_name = 'PARAMETERS' + CHANGING cg_data = lt_parameters ). + + ls_attr-devclass = iv_package. + save( is_attributes = ls_attr + it_parameters = lt_parameters ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lx_error TYPE REF TO zcx_abapgit_exception. + + TRY. + w3_api_load( ). + rv_bool = abap_true. + + CATCH zcx_abapgit_exception INTO lx_error. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_attr TYPE w3resoattr, + lt_parameters TYPE w3resopara_tabletype. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + read( IMPORTING es_attributes = ls_attr + et_parameters = lt_parameters ). + + io_xml->add( iv_name = 'ATTR' + ig_data = ls_attr ). + io_xml->add( iv_name = 'PARAMETERS' + ig_data = lt_parameters ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_iamu IMPLEMENTATION. + METHOD get_extension. + + CONSTANTS: + lc_jpg TYPE xstring VALUE 'FFD8FF', + lc_png TYPE xstring VALUE '89504E470D0A1A0A', + lc_gif TYPE xstring VALUE '47494638', + lc_bmp TYPE xstring VALUE '424D'. + + DATA lv_len TYPE i. + + " Try to derive type of MIME object from the long name + FIND REGEX '\.(\w)$' IN iv_name SUBMATCHES rv_extension. + IF sy-subrc = 0. + rv_extension = to_lower( rv_extension ). + ELSEIF zcl_abapgit_utils=>is_binary( iv_data ) = abap_true. + " Use magic numbers to detect common file types + lv_len = xstrlen( iv_data ). + IF lv_len > 3 AND iv_data(3) = lc_jpg. + rv_extension = 'jpg'. + ELSEIF lv_len > 8 AND iv_data(8) = lc_png. + rv_extension = 'png'. + ELSEIF lv_len > 4 AND iv_data(4) = lc_gif. + rv_extension = 'git'. + ELSEIF lv_len > 2 AND iv_data(2) = lc_bmp. + rv_extension = 'bmp'. + ELSE. + rv_extension = 'bin'. + ENDIF. + ELSE. + rv_extension = 'txt'. + ENDIF. + + ENDMETHOD. + METHOD load_mime_api. + + DATA: ls_mime_name TYPE iacikeym. + + ls_mime_name = ms_item-obj_name. + + cl_w3_api_mime=>if_w3_api_mime~load( + EXPORTING + p_mime_name = ls_mime_name + IMPORTING + p_mime = mi_mime_api + EXCEPTIONS + object_not_existing = 1 + permission_failure = 2 + data_corrupt = 3 + error_occured = 4 + OTHERS = 6 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from if_w3_api_mime~load' ). + ENDIF. + + ENDMETHOD. + METHOD lock. + + " As a side effect this method removes also existing locks + mi_mime_api->if_w3_api_object~set_changeable( + EXPORTING + p_changeable = iv_changable + EXCEPTIONS + action_cancelled = 1 + object_locked_by_other_user = 2 + permission_failure = 3 + object_already_changeable = 4 + object_already_unlocked = 5 + object_just_created = 6 + object_deleted = 7 + object_modified = 8 + object_not_existing = 9 + object_invalid = 10 + error_occured = 11 + OTHERS = 12 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~set_changeable| ). + ENDIF. + + ENDMETHOD. + METHOD read. + + load_mime_api( ). + + mi_mime_api->get_attributes( + IMPORTING + p_attributes = rs_internet_appl_comp_binary-attributes + EXCEPTIONS + object_invalid = 1 + mime_deleted = 2 + error_occured = 3 + OTHERS = 4 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~get_attributes| ). + ENDIF. + + CLEAR: rs_internet_appl_comp_binary-attributes-chname, + rs_internet_appl_comp_binary-attributes-tdate, + rs_internet_appl_comp_binary-attributes-ttime, + rs_internet_appl_comp_binary-attributes-devclass. + + mi_mime_api->get_source( + IMPORTING + p_source = rs_internet_appl_comp_binary-source + p_datalength = rs_internet_appl_comp_binary-length + EXCEPTIONS + object_invalid = 1 + mime_deleted = 2 + error_occured = 3 + OTHERS = 4 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~get_source| ). + ENDIF. + + ENDMETHOD. + METHOD save. + + IF zif_abapgit_object~exists( ) = abap_true. + load_mime_api( ). + lock( abap_true ). + + mi_mime_api->set_source( + EXPORTING + p_source = is_internet_appl_comp_binary-source + p_datalength = is_internet_appl_comp_binary-length + EXCEPTIONS + object_not_changeable = 1 + object_deleted = 2 + object_invalid = 3 + authorize_failure = 4 + invalid_content = 5 + error_occured = 6 + OTHERS = 7 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error { sy-subrc } from set_source| ). + ENDIF. + ELSE. + cl_w3_api_mime=>if_w3_api_mime~create_new( + EXPORTING + p_mime_data = is_internet_appl_comp_binary-attributes + p_mime_content = is_internet_appl_comp_binary-source + p_datalength = is_internet_appl_comp_binary-length + IMPORTING + p_mime = mi_mime_api + EXCEPTIONS + object_already_existing = 1 + object_just_created = 2 + not_authorized = 3 + undefined_name = 4 + author_not_existing = 5 + action_cancelled = 6 + error_occured = 7 + OTHERS = 8 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error { sy-subrc } from create_new| ). + ENDIF. + ENDIF. + + " Create_new does not update text, so set attributes explicitly + mi_mime_api->set_attributes( + EXPORTING + p_attributes = is_internet_appl_comp_binary-attributes + EXCEPTIONS + object_not_changeable = 1 + object_deleted = 2 + object_invalid = 3 + author_not_existing = 4 + authorize_failure = 5 + error_occured = 6 + OTHERS = 7 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error { sy-subrc } from set_attributes| ). + ENDIF. + + mi_mime_api->if_w3_api_object~save( + EXCEPTIONS + object_invalid = 1 + object_not_changeable = 2 + action_cancelled = 3 + permission_failure = 4 + not_changed = 5 + data_invalid = 6 + error_occured = 7 + OTHERS = 8 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error { sy-subrc } from save| ). + ENDIF. + + lock( abap_false ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = read( )-attributes-chname. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + load_mime_api( ). + + mi_mime_api->if_w3_api_object~set_changeable( + EXPORTING + p_changeable = abap_true + EXCEPTIONS + action_cancelled = 1 + object_locked_by_other_user = 2 + permission_failure = 3 + object_already_changeable = 4 + object_already_unlocked = 5 + object_just_created = 6 + object_deleted = 7 + object_modified = 8 + object_not_existing = 9 + object_invalid = 10 + error_occured = 11 + OTHERS = 12 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~set_changeable| ). + ENDIF. + + mi_mime_api->if_w3_api_object~delete( + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + error_occured = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~delete| ). + ENDIF. + + mi_mime_api->if_w3_api_object~save( + EXCEPTIONS + object_invalid = 1 + object_not_changeable = 2 + action_cancelled = 3 + permission_failure = 4 + not_changed = 5 + data_invalid = 6 + error_occured = 7 + OTHERS = 8 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~save| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_internet_appl_comp_binary TYPE ty_internet_appl_comp_binary. + DATA lv_xstring TYPE xstring. + + io_xml->read( + EXPORTING + iv_name = 'IAMU' + CHANGING + cg_data = ls_internet_appl_comp_binary ). + + ls_internet_appl_comp_binary-attributes-devclass = iv_package. + + IF io_xml->get_metadata( )-version = 'v2.0.0'. + lv_xstring = mo_files->read_raw( ls_internet_appl_comp_binary-extension ). + + zcl_abapgit_convert=>xstring_to_bintab( + EXPORTING + iv_xstr = lv_xstring + IMPORTING + et_bintab = ls_internet_appl_comp_binary-source + ev_size = ls_internet_appl_comp_binary-length ). + ENDIF. + + save( ls_internet_appl_comp_binary ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_mime_name TYPE iacikeym. + + ls_mime_name = ms_item-obj_name. + + cl_w3_api_mime=>s_check_exist( + EXPORTING + p_mime_name = ls_mime_name + IMPORTING + p_exists = rv_bool ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + rs_metadata-version = 'v2.0.0'. " Serialization v2, separate data file + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_internet_appl_comp_binary TYPE ty_internet_appl_comp_binary. + DATA lv_xstring TYPE xstring. + + FIELD-SYMBOLS: LIKE LINE OF ls_internet_appl_comp_binary-source. + + ls_internet_appl_comp_binary = read( ). + + " Serialization v2, separate data file + LOOP AT ls_internet_appl_comp_binary-source ASSIGNING . + lv_xstring = lv_xstring && -line. + ENDLOOP. + lv_xstring = lv_xstring(ls_internet_appl_comp_binary-length). + + CLEAR: ls_internet_appl_comp_binary-source, ls_internet_appl_comp_binary-length. + + ls_internet_appl_comp_binary-extension = get_extension( + iv_name = ls_internet_appl_comp_binary-attributes-longname + iv_data = lv_xstring ). + + mo_files->add_raw( + iv_data = lv_xstring + iv_ext = ls_internet_appl_comp_binary-extension ). + + io_xml->add( iv_name = 'IAMU' + ig_data = ls_internet_appl_comp_binary ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_http IMPLEMENTATION. + + METHOD constructor. + + DATA: lr_dummy TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE DATA lr_dummy TYPE ('UCONHTTPSERVHEAD'). + CATCH cx_root. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE changedby FROM ('UCONHTTPSERVHEAD') INTO rv_user WHERE id = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA lv_name TYPE c LENGTH 30. + + lv_name = ms_item-obj_name. + + CALL METHOD ('CL_UCON_API_FACTORY')=>('DELETE_HTTP_SERVICE') + EXPORTING + name = lv_name + devclass = iv_package. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_http_servid TYPE c LENGTH 30, + lt_handler TYPE TABLE OF ty_handler, + ls_handler LIKE LINE OF lt_handler, + ls_description TYPE ty_uconhttpservtext, + lv_check_object_name TYPE c LENGTH 40, + lx_root TYPE REF TO cx_root, + lo_http TYPE REF TO object, + ls_abap_lang TYPE ty_gs_object_version, + lo_instance TYPE REF TO object, + lv_icfnode TYPE ty_icf_node. + + TRY. + io_xml->read( + EXPORTING iv_name = 'HTTPID' + CHANGING cg_data = lv_http_servid ). + io_xml->read( + EXPORTING iv_name = 'HTTPTEXT' + CHANGING cg_data = ls_description ). + io_xml->read( + EXPORTING iv_name = 'HTTPHDL' + CHANGING cg_data = lt_handler ). + + TRY. + "link to icf node (in releases older than 757, a http service requires a icf node to function) + io_xml->read( + EXPORTING iv_name = 'HTTPICFNODE' + CHANGING cg_data = lv_icfnode ). + CATCH cx_root. + ENDTRY. + + SELECT COUNT(*) FROM ('UCONHTTPSERVHEAD') WHERE id = lv_http_servid. + IF sy-dbcnt > 0. + "update + CALL METHOD ('CL_UCON_API_FACTORY')=>('GET_HTTP_SERVICE') + EXPORTING + name = lv_http_servid + no_auth_check = abap_true + RECEIVING + http_service = lo_http. + ELSE. + "create + CALL METHOD ('CL_UCON_API_FACTORY')=>('NEW_HTTP_SERVICE') + EXPORTING + name = lv_http_servid + RECEIVING + http_service = lo_http. + ENDIF. + + CALL METHOD lo_http->('IF_UCON_API_HTTP_SERVICE~SET_HANDLER') + EXPORTING + handler = lt_handler. + IF lt_handler IS NOT INITIAL. + READ TABLE lt_handler INTO ls_handler INDEX 1. + "get language version from abap class + + lv_check_object_name = ls_handler-servicehandler. + IF lv_check_object_name IS NOT INITIAL. + TRY. + CALL METHOD ('CL_ABAP_LANGUAGE_VERSION')=>('GET_INSTANCE') + RECEIVING + ro_version_handler = lo_instance. + CALL METHOD lo_instance->('IF_ABAP_LANGUAGE_VERSION~GET_VERSION_OF_OBJECT') + EXPORTING + iv_object_type = 'CLAS' + iv_object_name = lv_check_object_name + RECEIVING + rs_object_version = ls_abap_lang. + + IF ls_abap_lang-id = 'X'. "language version X not supported, use space instead + ls_abap_lang-id = space. + ENDIF. + + CALL METHOD lo_http->('IF_UCON_API_HTTP_SERVICE~SET_LANGUAGE_VERSION') + EXPORTING + iv_langu_version = ls_abap_lang-id. + CATCH cx_root ##NO_HANDLER. + " ABAP language version not supported in this system + ENDTRY. + ENDIF. + ENDIF. + + CALL METHOD lo_http->('IF_UCON_API_HTTP_SERVICE~SET_DESCRIPTION') + EXPORTING + texts = ls_description. + CALL METHOD lo_http->('IF_UCON_API_HTTP_SERVICE~SET_ICF_SERVICE') + EXPORTING + iv_icfservice = lv_icfnode. + CALL METHOD lo_http->('IF_UCON_API_HTTP_SERVICE~ACTIVATE'). + CALL METHOD lo_http->('IF_UCON_API_HTTP_SERVICE~SAVE') + EXPORTING + run_dark = abap_true + dev_class = iv_package + korrnum = iv_transport. + CALL METHOD lo_http->('IF_UCON_API_HTTP_SERVICE~FREE'). + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + SELECT COUNT(*) FROM ('UCONHTTPSERVHEAD') WHERE id = ms_item-obj_name. + rv_bool = boolc( sy-dbcnt > 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_http_srv_id TYPE c LENGTH 30, + lo_serv TYPE REF TO object, "if_ucon_api_http_service + lt_handler TYPE TABLE OF ty_uconservhttphandler, + ls_description TYPE ty_uconhttpservtext, + lx_root TYPE REF TO cx_root, + lv_icfnode TYPE ty_icf_node, + lv_name TYPE c LENGTH 30. + + TRY. + lv_http_srv_id = ms_item-obj_name. + "read http service object + CALL METHOD ('CL_UCON_API_FACTORY')=>('GET_HTTP_SERVICE') + EXPORTING + name = lv_http_srv_id + no_auth_check = abap_true + RECEIVING + http_service = lo_serv. + + CALL METHOD lo_serv->('IF_UCON_API_HTTP_SERVICE~GET_HANDLER') RECEIVING handler = lt_handler. + CALL METHOD lo_serv->('IF_UCON_API_HTTP_SERVICE~GET_DESCRIPTION') + EXPORTING + lang = sy-langu + RECEIVING + text = ls_description. + + "add data to output + CALL METHOD lo_serv->('IF_UCON_API_HTTP_SERVICE~GET_NAME') RECEIVING name = lv_name. + + io_xml->add( + iv_name = 'HTTPID' + ig_data = lv_name ). + + io_xml->add( + iv_name = 'HTTPTEXT' + ig_data = ls_description ). + + io_xml->add( + iv_name = 'HTTPHDL' + ig_data = lt_handler ). + + TRY. + "link to icf node (in releases older than 757, a http service requires a icf node to function) + CALL METHOD lo_serv->('IF_UCON_API_HTTP_SERVICE~GET_ICF_SERVICE') IMPORTING ev_icfservice = lv_icfnode. + io_xml->add( + iv_name = 'HTTPICFNODE' + ig_data = lv_icfnode ). + CATCH cx_root. + ENDTRY. + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_g4bs IMPLEMENTATION. + METHOD get_field_rules. + + ro_result = zcl_abapgit_field_rules=>create( ). + ro_result->add( + iv_table = '/IWBEP/I_V4_MSRV' + iv_field = 'CREATED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_V4_MSRV' + iv_field = 'CHANGED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_V4_MSRV' + iv_field = 'CREATED_TS' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_V4_MSRV' + iv_field = 'CHANGED_TS' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_V4_MSRT' + iv_field = 'CREATED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_V4_MSRT' + iv_field = 'CHANGED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_V4_MSRT' + iv_field = 'CREATED_TS' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_V4_MSRT' + iv_field = 'CHANGED_TS' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). + + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + ro_result->add( + iv_table = '/IWBEP/I_V4_MSRV' + iv_field = 'ABAP_LANGUAGE_VERSION' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-abap_language_version ). + ENDIF. + + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA lv_created TYPE sy-uname. + DATA lv_changed TYPE sy-uname. + + " Get entry with highest version + SELECT created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_V4_MSRV') + WHERE service_id = ms_item-obj_name ORDER BY PRIMARY KEY. + rv_user = lv_changed. + IF lv_changed IS INITIAL. + rv_user = lv_created. + ENDIF. + ENDSELECT. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_g4ba IMPLEMENTATION. + METHOD get_field_rules. + + ro_result = zcl_abapgit_field_rules=>create( ). + ro_result->add( + iv_table = '/IWBEP/I_V4_MSGR' + iv_field = 'CREATED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_V4_MSGR' + iv_field = 'CHANGED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_V4_MSGR' + iv_field = 'CREATED_TS' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_V4_MSGR' + iv_field = 'CHANGED_TS' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_V4_MSGA' + iv_field = 'CREATED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_V4_MSGA' + iv_field = 'CHANGED_BY' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = '/IWBEP/I_V4_MSGA' + iv_field = 'CREATED_TS' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp + )->add( + iv_table = '/IWBEP/I_V4_MSGA' + iv_field = 'CHANGED_TS' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). + + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + ro_result->add( + iv_table = '/IWBEP/I_V4_MSGR' + iv_field = 'ABAP_LANGUAGE_VERSION' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-abap_language_version ). + ENDIF. + + ENDMETHOD. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + io_field_rules = get_field_rules( ) + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + DATA lv_created TYPE sy-uname. + DATA lv_changed TYPE sy-uname. + + SELECT SINGLE created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_V4_MSGR') + WHERE group_id = ms_item-obj_name. + + rv_user = lv_changed. + IF lv_changed IS INITIAL. + rv_user = lv_created. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_fugs IMPLEMENTATION. +ENDCLASS. + +CLASS zcl_abapgit_object_fugr IMPLEMENTATION. + METHOD check_rfc_parameters. + +* function module RS_FUNCTIONMODULE_INSERT does the same deep down, but the right error +* message is not returned to the user, this is a workaround to give a proper error +* message to the user + + DATA: ls_parameter TYPE rsfbpara, + lt_fupa TYPE rsfb_param, + ls_fupa LIKE LINE OF lt_fupa. + IF is_function-remote_call = 'R'. + cl_fb_parameter_conversion=>convert_parameter_old_to_fupa( + EXPORTING + functionname = is_function-funcname + import = is_function-import + export = is_function-export + change = is_function-changing + tables = is_function-tables + except = is_function-exception + IMPORTING + fupararef = lt_fupa ). + + LOOP AT lt_fupa INTO ls_fupa WHERE paramtype = 'I' OR paramtype = 'E' OR paramtype = 'C' OR paramtype = 'T'. + cl_fb_parameter_conversion=>convert_intern_to_extern( + EXPORTING + parameter_db = ls_fupa + IMPORTING + parameter_vis = ls_parameter ). + + CALL FUNCTION 'RS_FB_CHECK_PARAMETER_REMOTE' + EXPORTING + parameter = ls_parameter + basxml_enabled = is_function-remote_basxml + EXCEPTIONS + not_remote_compatible = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD deserialize_functions. + + DATA: lv_include TYPE rs38l-include, + lv_area TYPE rs38l-area, + lv_group TYPE rs38l-area, + lv_namespace TYPE rs38l-namespace, + lt_source TYPE TABLE OF abaptxt255, + lv_msg TYPE string, + lx_error TYPE REF TO zcx_abapgit_exception. + + FIELD-SYMBOLS: LIKE LINE OF it_functions. + + LOOP AT it_functions ASSIGNING . + + lt_source = mo_files->read_abap( iv_extra = -funcname ). + + lv_area = ms_item-obj_name. + + CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' + EXPORTING + complete_area = lv_area + IMPORTING + namespace = lv_namespace + group = lv_group + EXCEPTIONS + OTHERS = 12. + + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_msg. + ii_log->add_error( iv_msg = |Function module { -funcname }: { lv_msg }| + is_item = ms_item ). + CONTINUE. "with next function module + ENDIF. + + IF zcl_abapgit_factory=>get_function_module( )->function_exists( -funcname ) = abap_true. +* delete the function module to make sure the parameters are updated +* haven't found a nice way to update the parameters + CALL FUNCTION 'FUNCTION_DELETE' + EXPORTING + funcname = -funcname + suppress_success_message = abap_true + EXCEPTIONS + error_message = 1 + OTHERS = 2. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_msg. + ii_log->add_error( iv_msg = |Function module { -funcname }: { lv_msg }| + is_item = ms_item ). + CONTINUE. "with next function module + ENDIF. + ENDIF. + + TRY. + check_rfc_parameters( ). + CATCH zcx_abapgit_exception INTO lx_error. + ii_log->add_error( + iv_msg = |Function module { -funcname }: { lx_error->get_text( ) }| + is_item = ms_item ). + CONTINUE. "with next function module + ENDTRY. + + CALL FUNCTION 'RS_FUNCTIONMODULE_INSERT' + EXPORTING + funcname = -funcname + function_pool = lv_group + interface_global = -global_flag + remote_call = -remote_call + short_text = -short_text + update_task = -update_task + exception_class = -exception_classes + namespace = lv_namespace + remote_basxml_supported = -remote_basxml + corrnum = iv_transport + IMPORTING + function_include = lv_include + TABLES + import_parameter = -import + export_parameter = -export + tables_parameter = -tables + changing_parameter = -changing + exception_list = -exception + parameter_docu = -documentation + EXCEPTIONS + double_task = 1 + error_message = 2 + function_already_exists = 3 + invalid_function_pool = 4 + invalid_name = 5 + too_many_functions = 6 + no_modify_permission = 7 + no_show_permission = 8 + enqueue_system_failure = 9 + canceled_in_corr = 10 + OTHERS = 11. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_msg. + ii_log->add_error( iv_msg = |Function module { -funcname }: { lv_msg }| + is_item = ms_item ). + CONTINUE. "with next function module + ENDIF. + + zcl_abapgit_factory=>get_sap_report( )->insert_report( + iv_name = lv_include + iv_package = iv_package + iv_version = iv_version + it_source = lt_source ). + + ii_log->add_success( iv_msg = |Function module { -funcname } imported| + is_item = ms_item ). + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_function_docs. + + FIELD-SYMBOLS LIKE LINE OF it_functions. + + zcl_abapgit_factory=>get_longtexts( )->deserialize( + iv_longtext_id = c_longtext_id_prog + iv_object_name = iv_prog_name + ii_xml = ii_xml + iv_main_language = mv_language ). + + LOOP AT it_functions ASSIGNING . + zcl_abapgit_factory=>get_longtexts( )->deserialize( + iv_longtext_name = |LONGTEXTS_{ -funcname }| + iv_longtext_id = c_longtext_id_func + iv_object_name = -funcname + ii_xml = ii_xml + iv_main_language = mv_language ). + zcl_abapgit_factory=>get_longtexts( )->deserialize( + iv_longtext_name = |LONGTEXTS_{ -funcname }___EXC| + iv_longtext_id = c_longtext_id_func_exc + iv_object_name = -funcname + ii_xml = ii_xml + iv_main_language = mv_language ). + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_includes. + + DATA: lo_xml TYPE REF TO zif_abapgit_xml_input, + ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, + lt_includes TYPE ty_sobj_name_tt, + lt_tpool TYPE textpool_table, + lt_tpool_ext TYPE zif_abapgit_lang_definitions=>ty_tpool_tt, + lt_source TYPE TABLE OF abaptxt255, + lx_exc TYPE REF TO zcx_abapgit_exception. + + FIELD-SYMBOLS: LIKE LINE OF lt_includes. + tadir_insert( iv_package ). + + ii_xml->read( EXPORTING iv_name = 'INCLUDES' + CHANGING cg_data = lt_includes ). + + LOOP AT lt_includes ASSIGNING . + + "ignore simple transformation includes (as long as they remain in existing repositories) + IF strlen( ) = 33 AND +30(3) = 'XTI'. + ii_log->add_warning( iv_msg = |Simple Transformation include { } ignored| + is_item = ms_item ). + CONTINUE. + ENDIF. + + TRY. + lt_source = mo_files->read_abap( iv_extra = ). + + lo_xml = mo_files->read_xml( ). + + lo_xml->read( EXPORTING iv_name = 'PROGDIR' + CHANGING cg_data = ls_progdir ). + + set_abap_language_version( CHANGING cv_abap_language_version = ls_progdir-uccheck ). + + lo_xml->read( EXPORTING iv_name = 'TPOOL' + CHANGING cg_data = lt_tpool_ext ). + lt_tpool = read_tpool( lt_tpool_ext ). + + deserialize_program( is_progdir = ls_progdir + it_source = lt_source + it_tpool = lt_tpool + iv_package = iv_package ). + + deserialize_textpool( iv_program = + it_tpool = lt_tpool + iv_is_include = abap_true ). + + ii_log->add_success( iv_msg = |Include { ls_progdir-name } imported| + is_item = ms_item ). + + CATCH zcx_abapgit_exception INTO lx_exc. + ii_log->add_exception( ix_exc = lx_exc + is_item = ms_item ). + CONTINUE. + ENDTRY. + + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_texts. + DATA: lt_tpool_i18n TYPE zif_abapgit_lang_definitions=>ty_i18n_tpools, + lt_tpool TYPE textpool_table. + + FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. + ii_xml->read( EXPORTING iv_name = 'I18N_TPOOL' + CHANGING cg_data = lt_tpool_i18n ). + + LOOP AT lt_tpool_i18n ASSIGNING . + lt_tpool = read_tpool( -textpool ). + deserialize_textpool( iv_program = iv_prog_name + iv_language = -language + it_tpool = lt_tpool ). + ENDLOOP. + ENDMETHOD. + METHOD deserialize_xml. + + DATA: lv_complete TYPE rs38l-area, + lv_namespace TYPE rs38l-namespace, + lv_areat TYPE tlibt-areat, + lv_stext TYPE tftit-stext, + lv_group TYPE rs38l-area. + + lv_complete = ms_item-obj_name. + + CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' + EXPORTING + complete_area = lv_complete + IMPORTING + namespace = lv_namespace + group = lv_group + EXCEPTIONS + include_not_exists = 1 + group_not_exists = 2 + no_selections = 3 + no_function_include = 4 + no_function_pool = 5 + delimiter_wrong_position = 6 + no_customer_function_group = 7 + no_customer_function_include = 8 + reserved_name_customer = 9 + namespace_too_long = 10 + area_length_error = 11 + OTHERS = 12. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ii_xml->read( EXPORTING iv_name = 'AREAT' + CHANGING cg_data = lv_areat ). + lv_stext = lv_areat. + + CALL FUNCTION 'RS_FUNCTION_POOL_INSERT' + EXPORTING + function_pool = lv_group + short_text = lv_stext + namespace = lv_namespace + devclass = iv_package + unicode_checks = iv_version + corrnum = iv_transport + suppress_corr_check = abap_false + EXCEPTIONS + name_already_exists = 1 + name_not_correct = 2 + function_already_exists = 3 + invalid_function_pool = 4 + invalid_name = 5 + too_many_functions = 6 + no_modify_permission = 7 + no_show_permission = 8 + enqueue_system_failure = 9 + canceled_in_corr = 10 + undefined_error = 11 + OTHERS = 12. + + CASE sy-subrc. + WHEN 0. + " Everything is ok + WHEN 1 OR 3. + " If the function group exists we need to manually update the short text + update_func_group_short_text( iv_group = lv_group + iv_short_text = lv_stext ). + WHEN OTHERS. + zcx_abapgit_exception=>raise_t100( ). + ENDCASE. + + ENDMETHOD. + METHOD functions. + + DATA: lv_area TYPE rs38l-area, + lt_enlfdir TYPE STANDARD TABLE OF enlfdir. + DATA lv_index TYPE i. + + FIELD-SYMBOLS: TYPE LINE OF ty_rs38l_incl_tt, + TYPE enlfdir. + + lv_area = ms_item-obj_name. + + CALL FUNCTION 'RS_FUNCTION_POOL_CONTENTS' + EXPORTING + function_pool = lv_area + TABLES + functab = rt_functab + EXCEPTIONS + function_pool_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + "FM is not reliable if Function Group is inconsistent, so cross-check results (#7147) + SELECT * FROM enlfdir + INTO TABLE lt_enlfdir + WHERE area = ms_item-obj_name + AND active = abap_true + ORDER BY funcname. "#EC CI_SUBRC + + LOOP AT lt_enlfdir ASSIGNING . + TRANSLATE -funcname TO UPPER CASE. + ENDLOOP. + + SORT lt_enlfdir BY funcname ASCENDING. + + "Remove anything not in FM attributes table + LOOP AT rt_functab ASSIGNING . + TRANSLATE TO UPPER CASE. + lv_index = sy-tabix. + READ TABLE lt_enlfdir WITH KEY funcname = -funcname TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + DELETE rt_functab INDEX lv_index. + ENDIF. + ENDLOOP. + + SORT rt_functab BY funcname ASCENDING. + DELETE ADJACENT DUPLICATES FROM rt_functab COMPARING funcname. + + ENDMETHOD. + METHOD get_abap_version. + + DATA: lt_includes TYPE ty_sobj_name_tt, + ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, + lo_xml TYPE REF TO zif_abapgit_xml_input. + + FIELD-SYMBOLS: LIKE LINE OF lt_includes. + + ii_xml->read( EXPORTING iv_name = 'INCLUDES' + CHANGING cg_data = lt_includes ). + + LOOP AT lt_includes ASSIGNING . + + lo_xml = mo_files->read_xml( ). + + lo_xml->read( EXPORTING iv_name = 'PROGDIR' + CHANGING cg_data = ls_progdir ). + + IF ls_progdir-uccheck IS INITIAL. + CONTINUE. + ELSEIF rv_abap_version IS INITIAL. + rv_abap_version = ls_progdir-uccheck. + CONTINUE. + ELSEIF rv_abap_version <> ls_progdir-uccheck. +*** All includes need to have the same ABAP language version + zcx_abapgit_exception=>raise( 'different ABAP Language Versions' ). + ENDIF. + ENDLOOP. + + IF rv_abap_version IS INITIAL. + set_abap_language_version( CHANGING cv_abap_language_version = rv_abap_version ). + ENDIF. + + ENDMETHOD. + METHOD includes. + + TYPES: BEGIN OF ty_reposrc, + progname TYPE reposrc-progname, + END OF ty_reposrc. + + DATA: lt_reposrc TYPE STANDARD TABLE OF ty_reposrc WITH DEFAULT KEY, + ls_reposrc LIKE LINE OF lt_reposrc, + lv_program TYPE program, + lv_maintviewname LIKE LINE OF rt_includes, + lv_offset_ns TYPE i, + lv_tabix LIKE sy-tabix, + lt_functab TYPE ty_rs38l_incl_tt, + lt_tadir_includes TYPE HASHED TABLE OF objname WITH UNIQUE KEY table_line. + + FIELD-SYMBOLS: LIKE LINE OF rt_includes, + LIKE LINE OF lt_functab. + IF lines( mt_includes_cache ) > 0. + rt_includes = mt_includes_cache. + RETURN. + ENDIF. + + lv_program = main_name( ). + lt_functab = functions( ). + + CALL FUNCTION 'RS_GET_ALL_INCLUDES' + EXPORTING + program = lv_program + TABLES + includetab = rt_includes + EXCEPTIONS + not_existent = 1 + no_program = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error from RS_GET_ALL_INCLUDES' ). + ENDIF. + + LOOP AT lt_functab ASSIGNING . + DELETE TABLE rt_includes FROM -include. + ENDLOOP. + +* handle generated maintenance views + IF ms_item-obj_name(1) <> '/'. + "FGroup name does not contain a namespace + lv_maintviewname = |L{ ms_item-obj_name }T00|. + ELSE. + "FGroup name contains a namespace + lv_offset_ns = find( val = ms_item-obj_name+1 + sub = '/' ). + lv_offset_ns = lv_offset_ns + 2. + lv_maintviewname = |{ ms_item-obj_name(lv_offset_ns) }L{ ms_item-obj_name+lv_offset_ns }T00|. + ENDIF. + + READ TABLE rt_includes WITH KEY table_line = lv_maintviewname TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + APPEND lv_maintviewname TO rt_includes. + ENDIF. + + SORT rt_includes. + IF lines( rt_includes ) > 0. + " check which includes have their own tadir entry + " these includes might reside in a different package or might be shared between multiple function groups + " or other programs and are hence no part of the to serialized FUGR object + " they will be handled as individual objects when serializing their package + " in addition, referenced XTI includes referencing (simple) transformations must be ignored + SELECT obj_name + INTO TABLE lt_tadir_includes + FROM tadir + FOR ALL ENTRIES IN rt_includes + WHERE pgmid = 'R3TR' + AND object = 'PROG' + AND obj_name = rt_includes-table_line. + LOOP AT rt_includes ASSIGNING . + " skip autogenerated includes from Table Maintenance Generator + IF CP 'LSVIM*'. + DELETE rt_includes INDEX sy-tabix. + CONTINUE. + ENDIF. + READ TABLE lt_tadir_includes WITH KEY table_line = TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + DELETE rt_includes. + CONTINUE. + ENDIF. + IF strlen( ) = 33 AND +30(3) = 'XTI'. + "ignore referenced (simple) transformation includes + DELETE rt_includes. + CONTINUE. + ENDIF. + ENDLOOP. + + IF lines( rt_includes ) > 0. + SELECT progname FROM reposrc + INTO TABLE lt_reposrc + FOR ALL ENTRIES IN rt_includes + WHERE progname = rt_includes-table_line + AND r3state = 'A'. + ENDIF. + SORT lt_reposrc BY progname ASCENDING. + ENDIF. + + LOOP AT rt_includes ASSIGNING . + lv_tabix = sy-tabix. + +* make sure the include exists + READ TABLE lt_reposrc INTO ls_reposrc + WITH KEY progname = BINARY SEARCH. + IF sy-subrc <> 0. + DELETE rt_includes INDEX lv_tabix. + CONTINUE. + ENDIF. + + "Make sure that the include does not belong to another function group + IF is_part_of_other_fugr( ) = abap_true. + DELETE rt_includes. + ENDIF. + ENDLOOP. + + APPEND lv_program TO rt_includes. + SORT rt_includes. + + mt_includes_cache = rt_includes. + + ENDMETHOD. + METHOD is_any_function_module_locked. + + DATA: lt_functions TYPE ty_rs38l_incl_tt. + + FIELD-SYMBOLS: TYPE rs38l_incl. + + TRY. + lt_functions = functions( ). + CATCH zcx_abapgit_exception. + RETURN. + ENDTRY. + + LOOP AT lt_functions ASSIGNING . + + IF exists_a_lock_entry_for( iv_lock_object = 'ESFUNCTION' + iv_argument = |{ -funcname }| ) = abap_true. + rv_any_function_module_locked = abap_true. + EXIT. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD is_any_include_locked. + + DATA: lt_includes TYPE ty_sobj_name_tt. + FIELD-SYMBOLS: TYPE sobj_name. + + TRY. + lt_includes = includes( ). + CATCH zcx_abapgit_exception. + RETURN. + ENDTRY. + + LOOP AT lt_includes ASSIGNING . + + IF exists_a_lock_entry_for( iv_lock_object = 'ESRDIRE' + iv_argument = |{ }| ) = abap_true. + rv_is_any_include_locked = abap_true. + EXIT. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD is_function_group_locked. + rv_is_functions_group_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' + iv_argument = ms_item-obj_name + iv_prefix = 'FG' ). + ENDMETHOD. + METHOD is_part_of_other_fugr. + " make sure that the include belongs to the function group + " like in LSEAPFAP Form TADIR_MAINTENANCE + DATA ls_tadir TYPE tadir. + DATA lv_namespace TYPE rs38l-namespace. + DATA lv_function_group TYPE rs38l-area. + DATA lv_include TYPE rs38l-include. + DATA ls_item_key TYPE zif_abapgit_definitions=>ty_item. + + rv_belongs_to_other_fugr = abap_false. + IF iv_include(1) = 'L' OR iv_include+1 CS '/L'. + lv_include = iv_include. + ls_tadir-object = 'FUGR'. + + CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' + IMPORTING + namespace = lv_namespace + group = lv_function_group + CHANGING + include = lv_include + EXCEPTIONS + OTHERS = 1 ##FM_SUBRC_OK. + + IF lv_function_group(1) = 'X'. " "EXIT"-function-module + ls_tadir-object = 'FUGS'. + ENDIF. + + IF sy-subrc = 0. + + CONCATENATE lv_namespace lv_function_group INTO ls_tadir-obj_name. + ls_item_key-obj_type = ls_tadir-object. + ls_item_key-obj_name = ls_tadir-obj_name. + + " compare complete tadir key to distinguish between regular and exit function groups + IF ( ls_tadir-obj_name <> ms_item-obj_name OR ls_tadir-object <> ms_item-obj_type ) AND + zcl_abapgit_objects=>exists( ls_item_key ) = abap_true. + rv_belongs_to_other_fugr = abap_true. + ENDIF. + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD main_name. + + DATA: lv_area TYPE rs38l-area, + lv_namespace TYPE rs38l-namespace, + lv_group TYPE rs38l-area. + lv_area = ms_item-obj_name. + + CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' + EXPORTING + complete_area = lv_area + IMPORTING + namespace = lv_namespace + group = lv_group + EXCEPTIONS + include_not_exists = 1 + group_not_exists = 2 + no_selections = 3 + no_function_include = 4 + no_function_pool = 5 + delimiter_wrong_position = 6 + no_customer_function_group = 7 + no_customer_function_include = 8 + reserved_name_customer = 9 + namespace_too_long = 10 + area_length_error = 11 + OTHERS = 12. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CONCATENATE lv_namespace 'SAPL' lv_group INTO rv_program. + + ENDMETHOD. + METHOD serialize_functions. + + DATA: + lt_source TYPE TABLE OF rssource, + lt_functab TYPE ty_rs38l_incl_tt, + lt_new_source TYPE rsfb_source, + ls_function LIKE LINE OF rt_functions. + + FIELD-SYMBOLS: LIKE LINE OF lt_functab, + TYPE LINE OF ty_function-documentation. + + lt_functab = functions( ). + + LOOP AT lt_functab ASSIGNING . +* fm RPY_FUNCTIONMODULE_READ does not support source code +* lines longer than 72 characters + CLEAR ls_function. + MOVE-CORRESPONDING TO ls_function. + + CLEAR lt_new_source. + CLEAR lt_source. + + CALL FUNCTION 'RPY_FUNCTIONMODULE_READ_NEW' + EXPORTING + functionname = -funcname + IMPORTING + global_flag = ls_function-global_flag + remote_call = ls_function-remote_call + update_task = ls_function-update_task + short_text = ls_function-short_text + remote_basxml_supported = ls_function-remote_basxml + TABLES + import_parameter = ls_function-import + changing_parameter = ls_function-changing + export_parameter = ls_function-export + tables_parameter = ls_function-tables + exception_list = ls_function-exception + documentation = ls_function-documentation + source = lt_source + CHANGING + new_source = lt_new_source + EXCEPTIONS + error_message = 1 + function_not_found = 2 + invalid_name = 3 + OTHERS = 4. + IF sy-subrc = 2. + CONTINUE. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error from RPY_FUNCTIONMODULE_READ_NEW' ). + ENDIF. + + LOOP AT ls_function-documentation ASSIGNING . + CLEAR -index. + ENDLOOP. + + SELECT SINGLE exten3 INTO ls_function-exception_classes FROM enlfdir + WHERE funcname = -funcname. "#EC CI_SUBRC + + APPEND ls_function TO rt_functions. + + IF NOT lt_new_source IS INITIAL. + strip_generation_comments( CHANGING ct_source = lt_new_source ). + mo_files->add_abap( + iv_extra = -funcname + it_abap = lt_new_source ). + ELSE. + strip_generation_comments( CHANGING ct_source = lt_source ). + mo_files->add_abap( + iv_extra = -funcname + it_abap = lt_source ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD serialize_function_docs. + + FIELD-SYMBOLS LIKE LINE OF it_functions. + + zcl_abapgit_factory=>get_longtexts( )->serialize( + iv_longtext_id = c_longtext_id_prog + iv_object_name = iv_prog_name + io_i18n_params = mo_i18n_params + ii_xml = ii_xml ). + + LOOP AT it_functions ASSIGNING . + zcl_abapgit_factory=>get_longtexts( )->serialize( + iv_longtext_name = |LONGTEXTS_{ -funcname }| + iv_longtext_id = c_longtext_id_func + iv_object_name = -funcname + io_i18n_params = mo_i18n_params + ii_xml = ii_xml ). + zcl_abapgit_factory=>get_longtexts( )->serialize( + iv_longtext_name = |LONGTEXTS_{ -funcname }___EXC| + iv_longtext_id = c_longtext_id_func_exc + iv_object_name = -funcname + io_i18n_params = mo_i18n_params + ii_xml = ii_xml ). + ENDLOOP. + + ENDMETHOD. + METHOD serialize_includes. + + DATA: lt_includes TYPE ty_sobj_name_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_includes. + + lt_includes = includes( ). + + LOOP AT lt_includes ASSIGNING . + +* todo, filename is not correct, a include can be used in several programs + serialize_program( is_item = ms_item + io_files = mo_files + iv_program = + iv_extra = ). + + ENDLOOP. + + ENDMETHOD. + METHOD serialize_texts. + DATA: lt_tpool_i18n TYPE zif_abapgit_lang_definitions=>ty_i18n_tpools, + lt_tpool TYPE textpool_table. + + FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + " Table d010tinf stores info. on languages in which program is maintained + " Select all active translations of program texts + " Skip main language - it was already serialized + SELECT DISTINCT language + INTO CORRESPONDING FIELDS OF TABLE lt_tpool_i18n + FROM d010tinf + WHERE r3state = 'A' + AND prog = iv_prog_name + AND language <> mv_language + ORDER BY language ##TOO_MANY_ITAB_FIELDS. + + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'LANGUAGE' + CHANGING + ct_tab = lt_tpool_i18n ). + + SORT lt_tpool_i18n BY language ASCENDING. + LOOP AT lt_tpool_i18n ASSIGNING . + READ TEXTPOOL iv_prog_name + LANGUAGE -language + INTO lt_tpool. + -textpool = add_tpool( lt_tpool ). + ENDLOOP. + + IF lines( lt_tpool_i18n ) > 0. + ii_xml->add( iv_name = 'I18N_TPOOL' + ig_data = lt_tpool_i18n ). + ENDIF. + ENDMETHOD. + METHOD serialize_xml. + + DATA: lt_includes TYPE ty_sobj_name_tt, + lv_areat TYPE tlibt-areat. + SELECT SINGLE areat INTO lv_areat + FROM tlibt + WHERE spras = mv_language + AND area = ms_item-obj_name. "#EC CI_GENBUFF "#EC CI_SUBRC + + lt_includes = includes( ). + + ii_xml->add( iv_name = 'AREAT' + ig_data = lv_areat ). + ii_xml->add( iv_name = 'INCLUDES' + ig_data = lt_includes ). + + ENDMETHOD. + METHOD update_func_group_short_text. + + " We update the short text directly. + " SE80 does the same in + " Program SAPLSEUF / LSEUFF07 + " FORM GROUP_CHANGE + + UPDATE tlibt SET areat = iv_short_text + WHERE spras = mv_language AND area = iv_group. + + ENDMETHOD. + METHOD update_where_used. +* make extra sure the where-used list is updated after deletion +* Experienced some problems with the T00 include +* this method just tries to update everything + + DATA: lv_include LIKE LINE OF it_includes, + lo_cross TYPE REF TO cl_wb_crossreference. + LOOP AT it_includes INTO lv_include. + + CREATE OBJECT lo_cross + EXPORTING + p_name = lv_include + p_include = lv_include. + + lo_cross->index_actualize( ). + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + TYPES: BEGIN OF ty_stamps, + user TYPE syuname, + date TYPE d, + time TYPE t, + END OF ty_stamps. + + DATA: + lt_stamps TYPE STANDARD TABLE OF ty_stamps WITH DEFAULT KEY, + lv_program TYPE program, + lv_found TYPE abap_bool, + lt_functions TYPE ty_rs38l_incl_tt. + + FIELD-SYMBOLS: + LIKE LINE OF lt_functions, + LIKE LINE OF mt_includes_all, + LIKE LINE OF lt_stamps. + + lv_program = main_name( ). + + IF mt_includes_all IS INITIAL. + CALL FUNCTION 'RS_GET_ALL_INCLUDES' + EXPORTING + program = lv_program + TABLES + includetab = mt_includes_all + EXCEPTIONS + not_existent = 1 + no_program = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error from RS_GET_ALL_INCLUDES' ). + ENDIF. + ENDIF. + + " Check if changed_by for include object was requested + LOOP AT mt_includes_all ASSIGNING WHERE table_line = to_upper( iv_extra ). + lv_program = . + lv_found = abap_true. + EXIT. + ENDLOOP. + + " Check if changed_by for function module was requested + lt_functions = functions( ). + + LOOP AT lt_functions ASSIGNING WHERE funcname = to_upper( iv_extra ). + lv_program = -include. + lv_found = abap_true. + EXIT. + ENDLOOP. + + SELECT unam AS user udat AS date utime AS time FROM reposrc + APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps + WHERE progname = lv_program + AND r3state = 'A' + ORDER BY PRIMARY KEY. "#EC CI_SUBRC + + IF mt_includes_all IS NOT INITIAL AND lv_found = abap_false. + SELECT unam AS user udat AS date utime AS time FROM reposrc + APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps + FOR ALL ENTRIES IN mt_includes_all + WHERE progname = mt_includes_all-table_line + AND r3state = 'A'. "#EC CI_SUBRC + ENDIF. + + SELECT unam AS user udat AS date utime AS time FROM repotext " Program text pool + APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps + WHERE progname = lv_program + AND r3state = 'A' + ORDER BY PRIMARY KEY. "#EC CI_SUBRC + + SELECT vautor AS user vdatum AS date vzeit AS time FROM eudb " GUI + APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps + WHERE relid = 'CU' + AND name = lv_program + AND srtf2 = 0 + ORDER BY PRIMARY KEY ##TOO_MANY_ITAB_FIELDS. + +* Screens: username not stored in D020S database table + + SORT lt_stamps BY date DESCENDING time DESCENDING. + + READ TABLE lt_stamps INDEX 1 ASSIGNING . + IF sy-subrc = 0. + rv_user = -user. + ELSE. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_area TYPE rs38l-area, + lt_includes TYPE ty_sobj_name_tt. + + " FUGR related to change documents will be deleted by CHDO + SELECT SINGLE fgrp FROM tcdrps INTO lv_area WHERE fgrp = ms_item-obj_name. + IF sy-subrc = 0. + RETURN. + ENDIF. + + lt_includes = includes( ). + + lv_area = ms_item-obj_name. + + CALL FUNCTION 'RS_FUNCTION_POOL_DELETE' + EXPORTING + area = lv_area + suppress_popups = abap_true + skip_progress_ind = abap_true + corrnum = iv_transport + EXCEPTIONS + canceled_in_corr = 1 + enqueue_system_failure = 2 + function_exist = 3 + not_executed = 4 + no_modify_permission = 5 + no_show_permission = 6 + permission_failure = 7 + pool_not_exist = 8 + cancelled = 9 + OTHERS = 10. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + update_where_used( lt_includes ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_program_name TYPE syrepid, + lv_abap_version TYPE trdir-uccheck, + lt_functions TYPE ty_function_tt, + lt_dynpros TYPE ty_dynpro_tt, + ls_cua TYPE ty_cua. + + lv_abap_version = get_abap_version( io_xml ). + + deserialize_xml( + ii_xml = io_xml + iv_version = lv_abap_version + iv_package = iv_package + iv_transport = iv_transport ). + + io_xml->read( EXPORTING iv_name = 'FUNCTIONS' + CHANGING cg_data = lt_functions ). + + deserialize_functions( + it_functions = lt_functions + ii_log = ii_log + iv_version = lv_abap_version + iv_package = iv_package + iv_transport = iv_transport ). + + deserialize_includes( + ii_xml = io_xml + iv_package = iv_package + ii_log = ii_log ). + + lv_program_name = main_name( ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + deserialize_texts( iv_prog_name = lv_program_name + ii_xml = io_xml ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'DYNPROS' + CHANGING cg_data = lt_dynpros ). + + deserialize_dynpros( lt_dynpros ). + + io_xml->read( EXPORTING iv_name = 'CUA' + CHANGING cg_data = ls_cua ). + + deserialize_cua( iv_program_name = lv_program_name + is_cua = ls_cua ). + + deserialize_function_docs( + iv_prog_name = lv_program_name + it_functions = lt_functions + ii_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_pool TYPE tlibg-area. + lv_pool = ms_item-obj_name. + CALL FUNCTION 'RS_FUNCTION_POOL_EXISTS' + EXPORTING + function_pool = lv_pool + EXCEPTIONS + pool_not_exists = 1. + rv_bool = boolc( sy-subrc <> 1 ). + + " Skip FUGR generated by CHDO + IF rv_bool = abap_true. + SELECT SINGLE fgrp FROM tcdrp INTO lv_pool WHERE fgrp = lv_pool. + IF sy-subrc = 0. + rv_bool = abap_false. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_program TYPE program. + + lv_program = main_name( ). + + IF is_function_group_locked( ) = abap_true + OR is_any_include_locked( ) = abap_true + OR is_any_function_module_locked( ) = abap_true + OR is_any_dynpro_locked( lv_program ) = abap_true + OR is_cua_locked( lv_program ) = abap_true + OR is_text_locked( lv_program ) = abap_true. + + rv_is_locked = abap_true. + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: + ls_item TYPE zif_abapgit_definitions=>ty_item, + lt_functions TYPE ty_rs38l_incl_tt, + lt_includes TYPE ty_sobj_name_tt. + + FIELD-SYMBOLS: + LIKE LINE OF lt_functions, + LIKE LINE OF lt_includes. + + ls_item-obj_type = 'PROG'. + ls_item-obj_name = to_upper( iv_extra ). + + lt_functions = functions( ). + + LOOP AT lt_functions ASSIGNING WHERE funcname = ls_item-obj_name. + ls_item-obj_name = -include. + rv_exit = zcl_abapgit_objects_factory=>get_gui_jumper( )->jump( ls_item ). + IF rv_exit = abap_true. + RETURN. + ENDIF. + ENDLOOP. + + lt_includes = includes( ). + + LOOP AT lt_includes ASSIGNING WHERE table_line = ls_item-obj_name. + rv_exit = zcl_abapgit_objects_factory=>get_gui_jumper( )->jump( ls_item ). + IF rv_exit = abap_true. + RETURN. + ENDIF. + ENDLOOP. + + " Otherwise covered by ZCL_ABAPGIT_OBJECTS=>JUMP + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + +* function group SEUF +* function group SIFP +* function group SUNI + + DATA: lt_functions TYPE ty_function_tt, + ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, + lv_program_name TYPE syrepid, + lt_dynpros TYPE ty_dynpro_tt, + ls_cua TYPE ty_cua. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + serialize_xml( io_xml ). + + lt_functions = serialize_functions( ). + + io_xml->add( iv_name = 'FUNCTIONS' + ig_data = lt_functions ). + + serialize_includes( ). + + lv_program_name = main_name( ). + + ls_progdir = zcl_abapgit_factory=>get_sap_report( )->read_progdir( lv_program_name ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + serialize_texts( + iv_prog_name = lv_program_name + ii_xml = io_xml ). + ENDIF. + + IF ls_progdir-subc = 'F'. + lt_dynpros = serialize_dynpros( lv_program_name ). + io_xml->add( iv_name = 'DYNPROS' + ig_data = lt_dynpros ). + + ls_cua = serialize_cua( lv_program_name ). + io_xml->add( iv_name = 'CUA' + ig_data = ls_cua ). + ENDIF. + + serialize_function_docs( iv_prog_name = lv_program_name + it_functions = lt_functions + ii_xml = io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ftgl IMPLEMENTATION. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN + COMPONENT iv_fieldname + OF STRUCTURE cg_header + TO . + ASSERT sy-subrc = 0. + + CLEAR: . + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_toggle_id = ms_item-obj_name. + + TRY. + CREATE DATA mr_toggle TYPE ('FTGL_S_WB_FEATURE_TOGGLE'). + CATCH cx_root. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE changedby FROM ('FTGL_ID') INTO rv_user + WHERE feature_id = ms_item-obj_name AND version = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + lv_return_code TYPE i. + + CALL METHOD ('CL_FEATURE_TOGGLE_OBJECT')=>delete + EXPORTING + iv_toggle_id = mv_toggle_id + RECEIVING + rv_rc = lv_return_code. + + IF lv_return_code <> 0. + zcx_abapgit_exception=>raise( |Cannot delete feature toggle { mv_toggle_id }. | + && |Error { sy-subrc } from cl_feature_toggle_object=>delete| ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + lo_toggle TYPE REF TO object, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN mr_toggle->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'FTGL' + CHANGING + cg_data = ). + + TRY. + CALL METHOD ('CL_FEATURE_TOGGLE_OBJECT')=>create_toggle_by_content + EXPORTING + is_content = + RECEIVING + ro_toggle = lo_toggle. + + CALL METHOD lo_toggle->('SAVE'). + + tadir_insert( iv_package ). + corr_insert( iv_package ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL METHOD ('CL_FEATURE_TOGGLE')=>is_defined + EXPORTING + iv_toggle_id = mv_toggle_id + RECEIVING + rc_exists = rv_bool. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_FTGL' + iv_argument = |{ mv_toggle_id }*| ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + lx_error TYPE REF TO cx_root, + lo_toggle TYPE REF TO object. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN mr_toggle->* TO . + ASSERT sy-subrc = 0. + + TRY. + CALL METHOD ('CL_FEATURE_TOGGLE_OBJECT')=>create_toggle_by_id + EXPORTING + iv_toggle_id = mv_toggle_id + RECEIVING + ro_toggle = lo_toggle. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + CALL METHOD lo_toggle->('GET_CONTENT') + RECEIVING + rs_content = . + + clear_field( EXPORTING iv_fieldname = 'HEADER-OWNER' CHANGING cg_header = ). + clear_field( EXPORTING iv_fieldname = 'HEADER-CREATED_DATE' CHANGING cg_header = ). + clear_field( EXPORTING iv_fieldname = 'HEADER-CREATED_TIME' CHANGING cg_header = ). + clear_field( EXPORTING iv_fieldname = 'HEADER-CHANGEDBY ' CHANGING cg_header = ). + clear_field( EXPORTING iv_fieldname = 'HEADER-CHANGED_DATE' CHANGING cg_header = ). + clear_field( EXPORTING iv_fieldname = 'HEADER-CHANGED_TIME' CHANGING cg_header = ). + + io_xml->add( + iv_name = 'FTGL' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_form IMPLEMENTATION. + METHOD build_extra_from_header. + + DATA lv_tdspras TYPE laiso. + + lv_tdspras = zcl_abapgit_convert=>conversion_exit_isola_output( is_header-tdspras ). + + rv_result = c_objectname_tdlines && '_' && lv_tdspras. + + ENDMETHOD. + METHOD build_extra_from_header_old. + rv_result = c_objectname_tdlines && '_' && is_header-tdspras. + ENDMETHOD. + METHOD compress_lines. + + DATA lv_string TYPE string. + DATA li_xml TYPE REF TO zif_abapgit_xml_output. + + CREATE OBJECT li_xml TYPE zcl_abapgit_xml_output. + li_xml->add( iv_name = c_objectname_tdlines + ig_data = it_lines ). + lv_string = li_xml->render( ). + IF lv_string IS NOT INITIAL. + mo_files->add_string( iv_extra = + build_extra_from_header( is_form_data-form_header ) + iv_ext = c_extension_xml + iv_string = lv_string ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_form_name = ms_item-obj_name. + + ENDMETHOD. + METHOD extract_tdlines. + + DATA lv_string TYPE string. + DATA li_xml TYPE REF TO zif_abapgit_xml_input. + + TRY. + lv_string = mo_files->read_string( iv_extra = + build_extra_from_header( is_form_data-form_header ) + iv_ext = c_extension_xml ). + CATCH zcx_abapgit_exception. + + lv_string = mo_files->read_string( iv_extra = + build_extra_from_header_old( is_form_data-form_header ) + iv_ext = c_extension_xml ). + + ENDTRY. + + CREATE OBJECT li_xml TYPE zcl_abapgit_xml_input EXPORTING iv_xml = lv_string. + li_xml->read( EXPORTING iv_name = c_objectname_tdlines + CHANGING cg_data = rt_lines ). + + ENDMETHOD. + METHOD find_form. + + DATA: lv_text_name TYPE thead-tdname. + + lv_text_name = iv_object_name. + + CALL FUNCTION 'SELECT_TEXT' + EXPORTING + database_only = abap_true + id = 'TXT' + language = '*' + name = lv_text_name + object = c_objectname_form + TABLES + selections = rt_text_header + EXCEPTIONS + OTHERS = 1 ##FM_SUBRC_OK. "#EC CI_SUBRC + + ENDMETHOD. + METHOD get_last_changes. + + DATA: lv_form_name TYPE thead-tdform. + + CLEAR rs_last_changed. + + lv_form_name = iv_form_name. + + CALL FUNCTION 'READ_FORM' + EXPORTING + form = lv_form_name + read_only_header = abap_true + IMPORTING + form_header = rs_last_changed. + + ENDMETHOD. + METHOD order_check_and_insert. + + DATA: lv_order TYPE e071k-trkorr. + + CALL FUNCTION 'SAPSCRIPT_ORDER_CHECK' + EXPORTING + objecttype = ms_item-obj_type + form = mv_form_name + EXCEPTIONS + invalid_input = 1 + object_locked = 2 + object_not_available = 3 + OTHERS = 4. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'SAPSCRIPT_ORDER_INSERT' + EXPORTING + objecttype = ms_item-obj_type + form = mv_form_name + masterlang = mv_language + CHANGING + order = lv_order + EXCEPTIONS + invalid_input = 1 + order_canceled = 2 + OTHERS = 3. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_last_changed TYPE ty_s_form_header. + + ls_last_changed = get_last_changes( ms_item-obj_name ). + + IF ls_last_changed-tdluser IS NOT INITIAL. + rv_user = ls_last_changed-tdluser. + ELSE. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + CALL FUNCTION 'DELETE_FORM' + EXPORTING + form = mv_form_name + language = '*'. + + order_check_and_insert( ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lt_form_data TYPE ty_t_form_data. + DATA: lt_lines TYPE ty_t_lines. + FIELD-SYMBOLS: TYPE LINE OF ty_t_form_data. + + io_xml->read( EXPORTING iv_name = c_objectname_form + CHANGING cg_data = lt_form_data ). + + LOOP AT lt_form_data ASSIGNING . + + lt_lines = extract_tdlines( ). + + _save_form( EXPORTING it_lines = lt_lines + CHANGING cs_form_data = ). + + ENDLOOP. + + CALL FUNCTION 'SAPSCRIPT_DELETE_LOAD' + EXPORTING + delete = abap_true + form = '*' + write = space. + + tadir_insert( iv_package ). + + order_check_and_insert( ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA lv_lang TYPE sy-langu. + +* this will try to read the FORM in language EN +* if it exists in other language, then "found" will be set to abap_false +* so check the "olanguage" to see if the FORM exists + CALL FUNCTION 'READ_FORM' + EXPORTING + form = mv_form_name + read_only_header = abap_true + IMPORTING + olanguage = lv_lang. + + rv_bool = boolc( lv_lang IS NOT INITIAL ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_object TYPE seqg3-garg. + + " example lock entry + "'001FORM ZTEST_SAPSCRIPT TXT' + lv_object = |{ sy-mandt }{ ms_item-obj_type } { ms_item-obj_name }|. + OVERLAY lv_object WITH ' '. + lv_object = lv_object && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESSFORM' + iv_argument = lv_object ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMSSCF'. + -dynpro = '1102'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=SHOW'. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'RSSCF-TDFORM'. + -fval = ms_item-obj_name. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SE71' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lt_form_data TYPE ty_t_form_data. + DATA: ls_form_data TYPE ty_s_form_data. + DATA: lt_text_header TYPE ty_t_text_header. + DATA: lt_lines TYPE ty_t_lines. + DATA: lv_form_found TYPE abap_bool. + FIELD-SYMBOLS: LIKE LINE OF lt_text_header. + + lt_text_header = find_form( ms_item-obj_name ). + + LOOP AT lt_text_header ASSIGNING . + CLEAR lt_lines. + CLEAR ls_form_data. + + _read_form( EXPORTING is_text_header = + IMPORTING ev_form_found = lv_form_found + es_form_data = ls_form_data + et_lines = lt_lines ). + + IF lv_form_found = abap_true. + + _clear_changed_fields( CHANGING cs_form_data = ls_form_data ). + + compress_lines( is_form_data = ls_form_data + it_lines = lt_lines ). + + INSERT ls_form_data INTO TABLE lt_form_data. + + ENDIF. + + ENDLOOP. + + IF lt_form_data IS NOT INITIAL. + + io_xml->add( iv_name = c_objectname_form + ig_data = lt_form_data ). + + ENDIF. + + ENDMETHOD. + METHOD _clear_changed_fields. + + CLEAR: cs_form_data-form_header-tdfuser, + cs_form_data-form_header-tdfdate, + cs_form_data-form_header-tdftime, + cs_form_data-form_header-tdfreles, + cs_form_data-form_header-tdluser, + cs_form_data-form_header-tdldate, + cs_form_data-form_header-tdltime, + cs_form_data-form_header-tdlreles. + CLEAR: cs_form_data-text_header-tdfuser, + cs_form_data-text_header-tdfdate, + cs_form_data-text_header-tdftime, + cs_form_data-text_header-tdfreles, + cs_form_data-text_header-tdluser, + cs_form_data-text_header-tdldate, + cs_form_data-text_header-tdltime, + cs_form_data-text_header-tdlreles. + + ENDMETHOD. + METHOD _read_form. + + CLEAR es_form_data. + + CALL FUNCTION 'READ_FORM' + EXPORTING + form = is_text_header-tdform + language = is_text_header-tdspras + status = ' ' + IMPORTING + form_header = es_form_data-form_header + found = ev_form_found + header = es_form_data-text_header + olanguage = es_form_data-orig_language + TABLES + form_lines = et_lines + pages = es_form_data-pages + page_windows = es_form_data-page_windows + paragraphs = es_form_data-paragraphs + strings = es_form_data-strings + tabs = es_form_data-tabs + windows = es_form_data-windows. + + _sort_tdlines_by_windows( CHANGING ct_form_windows = es_form_data-windows + ct_lines = et_lines ). + + es_form_data-form_header-tdversion = '00001'. + es_form_data-text_header-tdversion = '00001'. + + ENDMETHOD. + METHOD _save_form. + + CALL FUNCTION 'SAVE_FORM' + EXPORTING + form_header = cs_form_data-form_header + TABLES + form_lines = it_lines + pages = cs_form_data-pages + page_windows = cs_form_data-page_windows + paragraphs = cs_form_data-paragraphs + strings = cs_form_data-strings + tabs = cs_form_data-tabs + windows = cs_form_data-windows. + + CALL FUNCTION 'SAPSCRIPT_CHANGE_OLANGUAGE' + EXPORTING + forced = abap_true + name = cs_form_data-text_header-tdname + object = cs_form_data-text_header-tdobject + olanguage = cs_form_data-orig_language + EXCEPTIONS + OTHERS = 1 ##FM_SUBRC_OK. "#EC CI_SUBRC + + ENDMETHOD. + METHOD _sort_tdlines_by_windows. + DATA lt_lines TYPE ty_t_lines. + DATA ls_lines LIKE LINE OF lt_lines. + DATA ls_form_windows LIKE LINE OF ct_form_windows. + DATA lv_elt_windows TYPE tdformat VALUE '/W'. + DATA lv_firstloop TYPE abap_bool. + + lt_lines = ct_lines. + CLEAR ct_lines. + + SORT ct_form_windows BY tdwindow. + + LOOP AT ct_form_windows INTO ls_form_windows. + lv_firstloop = abap_true. + READ TABLE lt_lines INTO ls_lines WITH KEY tdformat = lv_elt_windows + tdline = ls_form_windows-tdwindow. + IF sy-subrc <> 0. + CONTINUE. " current loop + ENDIF. + LOOP AT lt_lines INTO ls_lines FROM sy-tabix. + IF lv_firstloop = abap_false AND + ls_lines-tdformat = lv_elt_windows. + EXIT. + ENDIF. + APPEND ls_lines TO ct_lines. + lv_firstloop = abap_false. + ENDLOOP. + ENDLOOP. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_fdt0 IMPLEMENTATION. + METHOD before_xml_deserialize. + + DATA lv_application_id TYPE fdt_admn_0000s-application_id. + DATA lv_timestamp TYPE timestamp. + DATA lv_transport TYPE string. + DATA lv_dlvunit TYPE tdevc-dlvunit. + DATA lo_node_local TYPE REF TO if_ixml_element. + DATA lo_node_package TYPE REF TO if_ixml_element. + DATA lo_node_id TYPE REF TO if_ixml_element. + DATA lo_xml_element TYPE REF TO if_ixml_element. + DATA lv_count TYPE i. + + lo_node_local = co_dom_tree->find_from_name( name = 'Local' + namespace = 'FDTNS' ). + + IF lo_node_local IS BOUND. + ev_is_local = lo_node_local->get_value( ). + ENDIF. + + lo_node_package = co_dom_tree->find_from_name( + name = 'DevelopmentPackage' + namespace = 'FDTNS' ). + IF lo_node_package IS BOUND. + lo_node_package->set_value( |{ iv_package }| ). + ENDIF. + + lo_node_id = co_dom_tree->find_from_name( + name = 'ApplicationId' + namespace = 'FDTNS' ). + IF lo_node_id IS BOUND. + lv_application_id = lo_node_id->get_value( ). + SELECT COUNT( * ) FROM fdt_admn_0000s INTO lv_count + WHERE object_type = 'AP' + AND id = lv_application_id + AND deleted = ''. + ev_create = boolc( lv_count = 0 ). + ENDIF. + + " Fill in user/time/system-specific fields + GET TIME STAMP FIELD lv_timestamp. + lv_transport = |${ sy-sysid }0000000000000001|. + + lo_xml_element = co_dom_tree->get_root_element( ). + + IF ev_create = abap_true. + set_field( + EXPORTING + iv_name = 'CreationUser' + iv_value = |{ sy-uname }| + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'CreationTimestamp' + iv_value = |{ lv_timestamp }| + CHANGING + co_ixml_element = lo_xml_element ). + ENDIF. + + set_field( + EXPORTING + iv_name = 'ChangeUser' + iv_value = |{ sy-uname }| + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'ChangeTimestamp' + iv_value = |{ lv_timestamp }| + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'User' + iv_value = |{ sy-uname }| + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'Timestamp' + iv_value = |{ lv_timestamp }| + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'Trrequest' + iv_value = lv_transport + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'Trversion' + iv_value = '000001' + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'Trtimestamp' + iv_value = |{ lv_timestamp }| + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'Trsysid' + iv_value = |{ sy-sysid }| + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'Trclient' + iv_value = |{ sy-mandt }| + CHANGING + co_ixml_element = lo_xml_element ). + + set_field( + EXPORTING + iv_name = 'OversId' + iv_value = |{ lv_application_id }| + CHANGING + co_ixml_element = lo_xml_element ). + + SELECT SINGLE dlvunit FROM tdevc INTO lv_dlvunit WHERE devclass = iv_package. + IF sy-subrc = 0. + set_field( + EXPORTING + iv_name = 'SoftwareComponent' + iv_value = |{ lv_dlvunit }| + CHANGING + co_ixml_element = lo_xml_element ). + ENDIF. + + lo_xml_element->set_attribute( + name = 'Client' + value = |{ sy-mandt }| ). + lo_xml_element->set_attribute( + name = 'Date' + value = |{ sy-datum }| ). + lo_xml_element->set_attribute( + name = 'SAPRelease' + value = |{ sy-saprl }| ). + lo_xml_element->set_attribute( + name = 'Server' + value = |{ sy-host }| ). + lo_xml_element->set_attribute( + name = 'SourceExportReqID' + value = lv_transport ). + lo_xml_element->set_attribute( + name = 'SystemID' + value = |{ sy-sysid }| ). + lo_xml_element->set_attribute( + name = 'Time' + value = |{ sy-uzeit }| ). + lo_xml_element->set_attribute( + name = 'User' + value = |{ sy-uname }| ). + + ENDMETHOD. + METHOD check_is_local. + + SELECT SINGLE local_object FROM fdt_admn_0000s INTO rv_is_local + WHERE object_type = 'AP' + AND name = ms_item-obj_name. + + ENDMETHOD. + METHOD filter_xml_serialize. + + DATA lo_components_node TYPE REF TO if_ixml_element. + + lo_components_node = co_ixml_element->find_from_name( name = 'ComponentReleases' + namespace = 'FDTNS' ). + IF lo_components_node IS BOUND. + co_ixml_element->remove_child( lo_components_node ). + ENDIF. + + " Clear user/time/system-specific fields + set_field( + EXPORTING + iv_name = 'CreationUser' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'CreationTimestamp' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'ChangeUser' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'ChangeTimestamp' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'User' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'Timestamp' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'Trrequest' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'Trversion' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'Trtimestamp' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'Trsysid' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'Trclient' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'OversId' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'SoftwareComponent' + CHANGING + co_ixml_element = co_ixml_element ). + + set_field( + EXPORTING + iv_name = 'DevelopmentPackage' + CHANGING + co_ixml_element = co_ixml_element ). + + " Clear attributes of root FDTNS:Fdt node + co_ixml_element->set_attribute( + name = 'Client' + value = '' ). + co_ixml_element->set_attribute( + name = 'Date' + value = '' ). + co_ixml_element->set_attribute( + name = 'SAPRelease' + value = '' ). + co_ixml_element->set_attribute( + name = 'Server' + value = '' ). + co_ixml_element->set_attribute( + name = 'SourceExportReqID' + value = '' ). + co_ixml_element->set_attribute( + name = 'SystemID' + value = '' ). + co_ixml_element->set_attribute( + name = 'Time' + value = '' ). + co_ixml_element->set_attribute( + name = 'User' + value = '' ). + + ENDMETHOD. + METHOD get_application_id. + + SELECT SINGLE application_id FROM fdt_admn_0000s INTO rv_application_id + WHERE object_type = 'AP' + AND name = ms_item-obj_name. + + ENDMETHOD. + METHOD set_field. + + DATA: + lo_node_collection TYPE REF TO if_ixml_node_collection, + lo_node TYPE REF TO if_ixml_node, + lv_index TYPE i. + + lo_node_collection = co_ixml_element->get_elements_by_tag_name( + namespace = 'FDTNS' + name = iv_name ). + + lv_index = 0. + WHILE lv_index < lo_node_collection->get_length( ). + lo_node = lo_node_collection->get_item( lv_index ). + lo_node->set_value( iv_value ). + lv_index = lv_index + 1. + ENDWHILE. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA lv_ch_user TYPE fdt_admn_0000s-ch_user. + + SELECT SINGLE ch_user FROM fdt_admn_0000s INTO lv_ch_user + WHERE object_type = 'AP' + AND name = ms_item-obj_name. + + rv_user = lv_ch_user. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA lv_is_local TYPE abap_bool. + DATA lt_application_id TYPE TABLE OF fdt_admn_0000s-application_id. + DATA ls_object_category_sel TYPE if_fdt_query=>s_object_category_sel. + DATA lv_failure TYPE abap_bool. + DATA lx_fdt_input TYPE REF TO cx_fdt_input. + + lv_is_local = check_is_local( ). + + SELECT application_id FROM fdt_admn_0000s INTO TABLE lt_application_id + WHERE object_type = 'AP' + AND name = ms_item-obj_name + ORDER BY application_id. + + ls_object_category_sel-system_objects = 'X'. + + TRY. + IF lv_is_local = abap_true. + + cl_fdt_delete_handling=>mark_for_delete_via_job( + EXPORTING + is_object_category_sel = ls_object_category_sel + ita_application_id = lt_application_id + iv_background = abap_true + iv_local_option = '1' + iv_appl_transported_option = '2' + iv_obj_transported_option = '2' + IMPORTING + ev_failure = lv_failure ). + IF lv_failure IS INITIAL. + cl_fdt_delete_handling=>delete_logical_via_job( + EXPORTING + is_object_category_sel = ls_object_category_sel + ita_application_id = lt_application_id + iv_retention_time = 0 + iv_background = abap_true + iv_local_option = '1' + iv_appl_transported_option = '2' + iv_obj_transported_option = '2' + IMPORTING + ev_failure = lv_failure ). + IF lv_failure IS INITIAL. + cl_fdt_delete_handling=>delete_physical_via_job( + EXPORTING + is_object_category_sel = ls_object_category_sel + ita_application_id = lt_application_id + iv_retention_time = 0 + iv_background = abap_true + iv_local_option = '1' + iv_appl_transported_option = '2' + IMPORTING + ev_failure = lv_failure ). + ENDIF. + ENDIF. + + ELSE. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + cl_fdt_delete_handling=>mark_for_delete_via_job( + EXPORTING + is_object_category_sel = ls_object_category_sel + ita_application_id = lt_application_id + iv_background = abap_true + iv_local_option = '2' + iv_appl_transported_option = '1' + iv_obj_transported_option = '1' + IMPORTING + ev_failure = lv_failure ). + IF lv_failure IS INITIAL. + cl_fdt_delete_handling=>delete_logical_via_job( + EXPORTING + is_object_category_sel = ls_object_category_sel + ita_application_id = lt_application_id + iv_retention_time = 0 + iv_background = abap_true + iv_local_option = '2' + iv_appl_transported_option = '1' + iv_obj_transported_option = '1' + IMPORTING + ev_failure = lv_failure ). + IF lv_failure IS INITIAL. + cl_fdt_delete_handling=>delete_physical_via_job( + EXPORTING + is_object_category_sel = ls_object_category_sel + ita_application_id = lt_application_id + iv_retention_time = 0 + iv_background = abap_true + iv_local_option = '2' + iv_appl_transported_option = '1' + IMPORTING + ev_failure = lv_failure ). + ENDIF. + ENDIF. + + ENDIF. + + IF lv_failure = abap_true. + zcx_abapgit_exception=>raise( |Error deleting { ms_item-obj_type } { ms_item-obj_name }| ). + ENDIF. + + CATCH cx_fdt_input INTO lx_fdt_input. + zcx_abapgit_exception=>raise_with_text( lx_fdt_input ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA lo_dexc TYPE REF TO if_fdt_data_exchange. + DATA lx_fdt_input TYPE REF TO cx_fdt_input. + DATA lo_dom_tree TYPE REF TO if_ixml_document. + DATA lv_transportable_package TYPE abap_bool. + DATA lv_is_local TYPE abap_bool. + DATA lt_message TYPE if_fdt_types=>t_message. + DATA lv_create TYPE abap_bool. + + FIELD-SYMBOLS TYPE if_fdt_types=>s_message. + + lo_dom_tree = io_xml->get_raw( ). + + before_xml_deserialize( + EXPORTING + iv_package = iv_package + IMPORTING + ev_create = lv_create + ev_is_local = lv_is_local + CHANGING + co_dom_tree = lo_dom_tree ). + + lv_transportable_package = zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ). + + IF lv_transportable_package = abap_true AND lv_is_local = abap_true. + zcx_abapgit_exception=>raise( 'Local applications can only be imported into a local package' ). + ELSEIF lv_transportable_package = abap_false AND lv_is_local = abap_false. + zcx_abapgit_exception=>raise( 'Transportable application can only be imported into transportable package' ). + ENDIF. + + lo_dexc = cl_fdt_factory=>if_fdt_factory~get_instance( )->get_data_exchange( ). + + TRY. + + IF lv_is_local = abap_true. "Local Object + + lo_dexc->import_xml( + EXPORTING + io_dom_tree = lo_dom_tree + iv_create = lv_create + iv_activate = abap_true + iv_simulate = abap_false + IMPORTING + et_message = lt_message ). + + ELSE. "Transportable Object + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + lo_dexc->import_xml( + EXPORTING + io_dom_tree = lo_dom_tree + iv_create = lv_create + iv_activate = abap_true + iv_simulate = abap_false + iv_workbench_trrequest = iv_transport + IMPORTING + et_message = lt_message ). + + ENDIF. + + LOOP AT lt_message ASSIGNING . + ii_log->add( + iv_msg = -text + iv_type = -msgty ). + ENDLOOP. + + CATCH cx_fdt_input INTO lx_fdt_input. + zcx_abapgit_exception=>raise_with_text( lx_fdt_input ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA lv_count TYPE i. + + SELECT COUNT( * ) FROM fdt_admn_0000s INTO lv_count + WHERE object_type = 'AP' + AND name = ms_item-obj_name + AND deleted = ''. + + rv_bool = boolc( lv_count > 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + + DATA lv_application_id TYPE fdt_admn_0000s-application_id. + DATA lx_fdt_input TYPE REF TO cx_fdt_input. + DATA lo_instance TYPE REF TO if_fdt_admin_data. + DATA lt_version TYPE if_fdt_admin_data=>ts_version. + DATA lv_index TYPE sy-tabix. + + FIELD-SYMBOLS LIKE LINE OF lt_version. + + lv_application_id = get_application_id( ). + + TRY. + cl_fdt_factory=>get_instance_generic( + EXPORTING + iv_id = lv_application_id + IMPORTING + eo_instance = lo_instance ). + + CATCH cx_fdt_input INTO lx_fdt_input. + zcx_abapgit_exception=>raise_with_text( lx_fdt_input ). + ENDTRY. + + lo_instance->get_versions( IMPORTING ets_version = lt_version ). + lv_index = lines( lt_version ). + READ TABLE lt_version ASSIGNING INDEX lv_index. + + rv_active = boolc( -state = 'A' ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA lv_application_id TYPE string. + + lv_application_id = get_application_id( ). + + rv_is_locked = exists_a_lock_entry_for( + iv_lock_object = 'FDT_ENQUEUE_ID' + iv_argument = |$ST{ lv_application_id }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA lv_application_id TYPE fdt_admn_0000s-application_id. + DATA lx_root TYPE REF TO cx_root. + DATA lo_fdt_wd TYPE REF TO if_fdt_wd_factory. + + lv_application_id = get_application_id( ). + + IF lv_application_id IS NOT INITIAL. + TRY. + lo_fdt_wd = cl_fdt_wd_factory=>if_fdt_wd_factory~get_instance( ). + lo_fdt_wd->get_ui_execution( )->execute_workbench( iv_id = lv_application_id ). + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + ELSE. + zcx_abapgit_exception=>raise( 'Could not open BRF+ Workbench' ). + ENDIF. + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA lo_dexc TYPE REF TO if_fdt_data_exchange. + DATA lv_application_id TYPE fdt_admn_0000s-application_id. + DATA lx_fdt_input TYPE REF TO cx_fdt_input. + DATA lv_xml_fdt0_application TYPE string. + DATA lo_xml_document TYPE REF TO if_ixml_document. + DATA lo_xml_element TYPE REF TO if_ixml_element. + + lv_application_id = get_application_id( ). + + lo_dexc = cl_fdt_factory=>if_fdt_factory~get_instance( )->get_data_exchange( ). + + TRY. + lo_dexc->export_xml_application( + EXPORTING + iv_application_id = lv_application_id + iv_schema = if_fdt_data_exchange=>gc_xml_schema_type_external + iv_xml_version = if_fdt_data_exchange=>gc_xml_version + IMPORTING + ev_string = lv_xml_fdt0_application ). + + lo_xml_document = cl_ixml_80_20=>parse_to_document( stream_string = lv_xml_fdt0_application ). + lo_xml_element = lo_xml_document->get_root_element( ). + + filter_xml_serialize( CHANGING co_ixml_element = lo_xml_element ). + + io_xml->set_raw( lo_xml_element ). + + CATCH cx_fdt_input INTO lx_fdt_input. + zcx_abapgit_exception=>raise_with_text( lx_fdt_input ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_ENSC IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_spot_name TYPE enhspotcompositename, + li_spot_ref TYPE REF TO if_enh_spot_composite, + lo_spot_ref TYPE REF TO cl_enh_spot_composite. + + lv_spot_name = ms_item-obj_name. + + TRY. + li_spot_ref = cl_enh_factory=>get_enhancement_spot_comp( + lock = '' + run_dark = abap_true + name = lv_spot_name ). + + lo_spot_ref ?= li_spot_ref. + + lo_spot_ref->if_enh_spot_composite~get_change_attributes( IMPORTING changedby = rv_user ). + CATCH cx_root. + rv_user = c_user_unknown. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + DATA: lv_spot_name TYPE enhspotcompositename, + lv_message TYPE string, + lx_root TYPE REF TO cx_root, + li_spot_ref TYPE REF TO if_enh_spot_composite. + + lv_spot_name = ms_item-obj_name. + + TRY. + li_spot_ref = cl_enh_factory=>get_enhancement_spot_comp( + lock = abap_true + run_dark = abap_true + name = lv_spot_name ). + + IF li_spot_ref IS BOUND. + li_spot_ref->if_enh_object~delete( + nevertheless_delete = abap_true + run_dark = abap_true ). + ENDIF. + li_spot_ref->if_enh_object~unlock( ). + CATCH cx_enh_root INTO lx_root. + lv_message = `Error occurred while deleting ENSC: ` + && lx_root->get_text( ). + zcx_abapgit_exception=>raise( lv_message ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_spot_name TYPE enhspotcompositename, + lv_message TYPE string, + lv_enh_shtext TYPE string, + lv_enh_spot TYPE enhspotname, + lt_enh_spots TYPE enhspotname_it, + lt_comp_spots TYPE enhspotname_it, + lx_root TYPE REF TO cx_root, + lv_package LIKE iv_package, + li_spot_ref TYPE REF TO if_enh_spot_composite, + lo_spot_ref TYPE REF TO cl_enh_spot_composite. + lv_spot_name = ms_item-obj_name. + + io_xml->read( EXPORTING iv_name = 'SHORTTEXT' + CHANGING cg_data = lv_enh_shtext ). + io_xml->read( EXPORTING iv_name = 'ENH_SPOTS' "Enhancement spots + CHANGING cg_data = lt_enh_spots ). + io_xml->read( EXPORTING iv_name = 'COMP_ENH_SPOTS' "Composite enhancement spots + CHANGING cg_data = lt_comp_spots ). + + IF zif_abapgit_object~exists( ) = abap_true. + zif_abapgit_object~delete( iv_package = iv_package + iv_transport = iv_transport ). + ENDIF. + + lv_package = iv_package. + + TRY. + cl_enh_factory=>create_enhancement_spot_comp( + EXPORTING + name = lv_spot_name + run_dark = abap_true + IMPORTING + composite = li_spot_ref + CHANGING + devclass = lv_package ). + + lo_spot_ref ?= li_spot_ref. + + lo_spot_ref->if_enh_object_docu~set_shorttext( lv_enh_shtext ). + "Add subsequent enhancement spots + LOOP AT lt_enh_spots INTO lv_enh_spot. + lo_spot_ref->if_enh_spot_composite~add_enh_spot_child( lv_enh_spot ). + ENDLOOP. + "Add subsequent composite enhancement spots + LOOP AT lt_comp_spots INTO lv_enh_spot. + lo_spot_ref->if_enh_spot_composite~add_composite_child( lv_enh_spot ). + ENDLOOP. + + lo_spot_ref->if_enh_object~save( ). + lo_spot_ref->if_enh_object~activate( ). + lo_spot_ref->if_enh_object~unlock( ). + + zcl_abapgit_sotr_handler=>create_sotr( + iv_package = iv_package + io_xml = io_xml ). + + CATCH cx_enh_root INTO lx_root. + lv_message = `Error occurred while deserializing ENSC: ` + && lx_root->get_text( ). + zcx_abapgit_exception=>raise( lv_message ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_spot_name TYPE enhspotcompositename. + lv_spot_name = ms_item-obj_name. + + TRY. + cl_enh_factory=>get_enhancement_spot_comp( + lock = '' + run_dark = abap_true + name = lv_spot_name ). + rv_bool = abap_true. + CATCH cx_enh_root. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_spot_name TYPE enhspotcompositename, + lv_message TYPE string, + lv_enh_shtext TYPE string, + lt_enh_spots TYPE enhspotname_it, + lt_comp_spots TYPE enhspotname_it, + lx_root TYPE REF TO cx_root, + li_spot_ref TYPE REF TO if_enh_spot_composite, + lo_spot_ref TYPE REF TO cl_enh_spot_composite. + lv_spot_name = ms_item-obj_name. + + TRY. + li_spot_ref = cl_enh_factory=>get_enhancement_spot_comp( + lock = '' + run_dark = abap_true + name = lv_spot_name ). + + lo_spot_ref ?= li_spot_ref. + + lv_enh_shtext = li_spot_ref->if_enh_object_docu~get_shorttext( ). + "find subsequent enhancement spots + lt_enh_spots = lo_spot_ref->if_enh_spot_composite~get_enh_spot_childs( ). + "find subsequent composite enhancement spots + lt_comp_spots = lo_spot_ref->if_enh_spot_composite~get_composite_childs( ). + + io_xml->add( ig_data = lv_enh_shtext + iv_name = 'SHORTTEXT' ). + io_xml->add( ig_data = lt_enh_spots + iv_name = 'ENH_SPOTS' ). "Enhancement spots + io_xml->add( ig_data = lt_comp_spots + iv_name = 'COMP_ENH_SPOTS' ). "Composite enhancement spots + + zcl_abapgit_sotr_handler=>read_sotr( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + io_xml = io_xml ). + + CATCH cx_enh_root INTO lx_root. + lv_message = `Error occurred while serializing ENSC: ` + && lx_root->get_text( ). + zcx_abapgit_exception=>raise( lv_message ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enqu IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE as4user FROM dd25l + INTO rv_user + WHERE viewname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + delete_ddic( 'L' ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_name TYPE ddobjname, + ls_dd25v TYPE dd25v, + ls_extra TYPE ty_extra, + lt_dd26e TYPE TABLE OF dd26e, + lt_dd27p TYPE ty_dd27p. + + io_xml->read( EXPORTING iv_name = 'DD25V' + CHANGING cg_data = ls_dd25v ). + io_xml->read( EXPORTING iv_name = 'DD26E_TABLE' + CHANGING cg_data = lt_dd26e ). + io_xml->read( EXPORTING iv_name = 'DD27P_TABLE' + CHANGING cg_data = lt_dd27p ). + + corr_insert( iv_package = iv_package + ig_object_class = 'DICT' ). + + lv_name = ms_item-obj_name. + + CALL FUNCTION 'DDIF_ENQU_PUT' + EXPORTING + name = lv_name + dd25v_wa = ls_dd25v + TABLES + dd26e_tab = lt_dd26e + dd27p_tab = lt_dd27p + EXCEPTIONS + enqu_not_found = 1 + name_inconsistent = 2 + enqu_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " Fields that are not part of dd25v + io_xml->read( EXPORTING iv_name = 'DD25L_EXTRA' + CHANGING cg_data = ls_extra ). + + TRY. + set_abap_language_version( CHANGING cv_abap_language_version = ls_extra-abap_language_version ). + + UPDATE ('DD25L') SET abap_language_version = ls_extra-abap_language_version WHERE viewname = lv_name. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_viewname TYPE dd25l-viewname. + + SELECT SINGLE viewname FROM dd25l INTO lv_viewname + WHERE viewname = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECT=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_name TYPE ddobjname, + lv_state TYPE ddgotstate, + ls_dd25v TYPE dd25v, + ls_extra TYPE ty_extra, + lt_dd26e TYPE TABLE OF dd26e, + lt_dd27p TYPE ty_dd27p. + + FIELD-SYMBOLS TYPE any. + + lv_name = ms_item-obj_name. + + CALL FUNCTION 'DDIF_ENQU_GET' + EXPORTING + name = lv_name + state = 'A' + langu = mv_language + IMPORTING + gotstate = lv_state + dd25v_wa = ls_dd25v + TABLES + dd26e_tab = lt_dd26e + dd27p_tab = lt_dd27p + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF ls_dd25v IS INITIAL OR lv_state <> 'A'. + RETURN. + ENDIF. + + CLEAR: ls_dd25v-as4user, + ls_dd25v-as4date, + ls_dd25v-as4time, + ls_dd25v-as4local, + ls_dd25v-as4vers. + + ASSIGN COMPONENT 'ACTFLAG' OF STRUCTURE ls_dd25v TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + _clear_dd27p_fields( CHANGING ct_dd27p = lt_dd27p ). + + io_xml->add( iv_name = 'DD25V' + ig_data = ls_dd25v ). + io_xml->add( ig_data = lt_dd26e + iv_name = 'DD26E_TABLE' ). + io_xml->add( ig_data = lt_dd27p + iv_name = 'DD27P_TABLE' ). + + ls_extra-abap_language_version = get_abap_language_version( ). + + io_xml->add( iv_name = 'DD25L_EXTRA' + ig_data = ls_extra ). + + ENDMETHOD. + METHOD _clear_dd27p_fields. + + FIELD-SYMBOLS TYPE dd27p. + + LOOP AT ct_dd27p ASSIGNING . + "taken from table + CLEAR -headlen. + CLEAR -scrlen1. + CLEAR -scrlen2. + CLEAR -scrlen3. + CLEAR -intlen. + CLEAR -outputlen. + CLEAR -flength. + CLEAR -ddtext. + CLEAR -reptext. + CLEAR -scrtext_s. + CLEAR -scrtext_m. + CLEAR -scrtext_l. + CLEAR -rollname. + CLEAR -rollnamevi. + CLEAR -entitytab. + CLEAR -datatype. + CLEAR -inttype. + CLEAR -ddlanguage. + CLEAR -domname. + CLEAR -signflag. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enhs IMPLEMENTATION. + METHOD factory. + + CASE iv_tool. + WHEN cl_enh_tool_badi_def=>tooltype. + CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enhs_badi_d. + WHEN cl_enh_tool_hook_def=>tool_type. + CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enhs_hook_d. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |ENHS: Unsupported tool { iv_tool }| ). + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_spot_name TYPE enhspotname, + li_spot_ref TYPE REF TO if_enh_spot_tool. + + lv_spot_name = ms_item-obj_name. + + TRY. + li_spot_ref = cl_enh_factory=>get_enhancement_spot( spot_name = lv_spot_name + run_dark = abap_true ). + li_spot_ref->get_attributes( IMPORTING changedby = rv_user ). + + CATCH cx_enh_root. + rv_user = c_user_unknown. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_spot_name TYPE enhspotname, + lx_enh_root TYPE REF TO cx_enh_root, + li_enh_object TYPE REF TO if_enh_object. + + zcl_abapgit_sotr_handler=>delete_sotr( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name ). + + zcl_abapgit_sots_handler=>delete_sots( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name ). + + lv_spot_name = ms_item-obj_name. + + TRY. + li_enh_object ?= cl_enh_factory=>get_enhancement_spot( spot_name = lv_spot_name + run_dark = abap_true + lock = abap_true ). + + li_enh_object->delete( nevertheless_delete = abap_true + run_dark = abap_true ). + + li_enh_object->unlock( ). + + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_parent TYPE enhspotcompositename, + lv_spot_name TYPE enhspotname, + lv_tool TYPE enhspottooltype, + lv_package LIKE iv_package, + lx_enh_root TYPE REF TO cx_enh_root, + li_spot_ref TYPE REF TO if_enh_spot_tool, + li_enhs TYPE REF TO zif_abapgit_object_enhs. + + IF zif_abapgit_object~exists( ) = abap_true. + zif_abapgit_object~delete( iv_package = iv_package + iv_transport = iv_transport ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'TOOL' + CHANGING cg_data = lv_tool ). + + lv_spot_name = ms_item-obj_name. + lv_package = iv_package. + + TRY. + cl_enh_factory=>create_enhancement_spot( + EXPORTING + spot_name = lv_spot_name + tooltype = lv_tool + dark = abap_false + compositename = lv_parent + IMPORTING + spot = li_spot_ref + CHANGING + devclass = lv_package ). + + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + li_enhs = factory( lv_tool ). + + li_enhs->deserialize( ii_xml = io_xml + iv_package = iv_package + ii_enh_spot_tool = li_spot_ref ). + + zcl_abapgit_sotr_handler=>create_sotr( + iv_package = iv_package + io_xml = io_xml ). + + zcl_abapgit_sots_handler=>create_sots( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_spot_name TYPE enhspotname, + li_spot_ref TYPE REF TO if_enh_spot_tool. + + lv_spot_name = ms_item-obj_name. + + TRY. + li_spot_ref = cl_enh_factory=>get_enhancement_spot( spot_name = lv_spot_name + run_dark = abap_true ). + + rv_bool = abap_true. + + CATCH cx_enh_root. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_spot_name TYPE enhspotname, + li_spot_ref TYPE REF TO if_enh_spot_tool, + li_enhs TYPE REF TO zif_abapgit_object_enhs, + lx_enh_root TYPE REF TO cx_enh_root. + + lv_spot_name = ms_item-obj_name. + + TRY. + li_spot_ref = cl_enh_factory=>get_enhancement_spot( spot_name = lv_spot_name + run_dark = abap_true ). + + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + li_enhs = factory( li_spot_ref->get_tool( ) ). + + li_enhs->serialize( ii_xml = io_xml + ii_enh_spot_tool = li_spot_ref ). + + zcl_abapgit_sotr_handler=>read_sotr( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + io_xml = io_xml ). + + zcl_abapgit_sots_handler=>read_sots( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + io_xml = io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enho IMPLEMENTATION. + METHOD factory. + + CASE iv_tool. + WHEN cl_enh_tool_badi_impl=>tooltype. + CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_badi + EXPORTING + is_item = ms_item. + WHEN cl_enh_tool_hook_impl=>tooltype. + CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_hook + EXPORTING + is_item = ms_item + io_files = mo_files. + WHEN cl_enh_tool_class=>tooltype. + CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_class + EXPORTING + is_item = ms_item + io_files = mo_files. + WHEN cl_enh_tool_intf=>tooltype. + CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_intf + EXPORTING + is_item = ms_item + io_files = mo_files. + WHEN cl_wdr_cfg_enhancement=>tooltype. + CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_wdyc + EXPORTING + is_item = ms_item. + WHEN 'FUGRENH'. + CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_fugr + EXPORTING + is_item = ms_item + io_files = mo_files. + WHEN 'WDYENH'. + CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_wdyn + EXPORTING + is_item = ms_item. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Unsupported ENHO type { iv_tool }| ). + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_enh_id TYPE enhname, + lt_log TYPE enh_log_it, + li_log_obj TYPE REF TO if_enh_log, + ls_enhlog TYPE enhlog, + lv_lines TYPE i, + lt_enhlog TYPE STANDARD TABLE OF enhlog WITH DEFAULT KEY, + li_enh_tool TYPE REF TO if_enh_tool. + lv_enh_id = ms_item-obj_name. + TRY. + li_enh_tool = cl_enh_factory=>get_enhancement( + enhancement_id = lv_enh_id + run_dark = abap_true + bypassing_buffer = abap_true ). + CATCH cx_enh_root. + rv_user = c_user_unknown. + RETURN. + ENDTRY. + + lt_log = li_enh_tool->get_log( ). + + LOOP AT lt_log INTO li_log_obj. + ls_enhlog = li_log_obj->get_enhlog( ). + APPEND ls_enhlog TO lt_enhlog. + ENDLOOP. + + lv_lines = lines( lt_enhlog ). + READ TABLE lt_enhlog INTO ls_enhlog INDEX lv_lines. + IF sy-subrc = 0. + rv_user = ls_enhlog-loguser. + ELSE. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_enh_id TYPE enhname, + li_enh_object TYPE REF TO if_enh_object, + lx_enh_root TYPE REF TO cx_enh_root, + lv_corrnum TYPE trkorr. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + zcl_abapgit_sotr_handler=>delete_sotr( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name ). + + zcl_abapgit_sots_handler=>delete_sots( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name ). + + lv_corrnum = iv_transport. + + lv_enh_id = ms_item-obj_name. + TRY. + li_enh_object = cl_enh_factory=>get_enhancement( + enhancement_id = lv_enh_id + run_dark = abap_true + lock = abap_true ). + li_enh_object->delete( + EXPORTING + nevertheless_delete = abap_true + run_dark = abap_true + CHANGING + trkorr = lv_corrnum ). + li_enh_object->unlock( ). + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_tool TYPE enhtooltype, + li_enho TYPE REF TO zif_abapgit_object_enho. + + IF zif_abapgit_object~exists( ) = abap_true. + zif_abapgit_object~delete( iv_package = iv_package + iv_transport = iv_transport ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'TOOL' + CHANGING cg_data = lv_tool ). + + li_enho = factory( lv_tool ). + + li_enho->deserialize( ii_xml = io_xml + iv_package = iv_package ). + + zcl_abapgit_sotr_handler=>create_sotr( + iv_package = iv_package + io_xml = io_xml ). + + zcl_abapgit_sots_handler=>create_sots( + iv_package = iv_package + io_xml = io_xml ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_enh_id TYPE enhname. + lv_enh_id = ms_item-obj_name. + TRY. + cl_enh_factory=>get_enhancement( + enhancement_id = lv_enh_id + run_dark = abap_true + bypassing_buffer = abap_true ). + rv_bool = abap_true. + CATCH cx_enh_root. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_object TYPE seqg3-garg. + + lv_object = |{ ms_item-obj_type }{ ms_item-obj_name }|. + OVERLAY lv_object WITH ' '. + lv_object = lv_object && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_ENHANCE' + iv_argument = lv_object ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_enh_id TYPE enhname, + li_enho TYPE REF TO zif_abapgit_object_enho, + li_enh_tool TYPE REF TO if_enh_tool, + lx_enh_root TYPE REF TO cx_enh_root. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + lv_enh_id = ms_item-obj_name. + TRY. + li_enh_tool = cl_enh_factory=>get_enhancement( + enhancement_id = lv_enh_id + run_dark = abap_true + bypassing_buffer = abap_true ). + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + li_enho = factory( li_enh_tool->get_tool( ) ). + + li_enho->serialize( ii_xml = io_xml + ii_enh_tool = li_enh_tool ). + + zcl_abapgit_sotr_handler=>read_sotr( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + io_xml = io_xml ). + + zcl_abapgit_sots_handler=>read_sots( + iv_pgmid = 'R3TR' + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + io_xml = io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enhc IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_composite_id = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE changedby INTO rv_user FROM enhcompheader + WHERE enhcomposite = ms_item-obj_name AND version = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lx_enh_root TYPE REF TO cx_enh_root, + li_enh_object TYPE REF TO if_enh_object. + + TRY. + li_enh_object = cl_enh_factory=>load_enhancement_composite( + name = mv_composite_id + lock = abap_true ). + + li_enh_object->delete( nevertheless_delete = abap_true + run_dark = abap_true ). + li_enh_object->unlock( ). + + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lx_enh_root TYPE REF TO cx_enh_root, + li_enh_composite TYPE REF TO if_enh_composite, + lv_package TYPE devclass, + lt_composite_childs TYPE enhcompositename_it, + lt_enh_childs TYPE enhname_it, + lv_longtext_id TYPE enhdocuobject, + lv_vers TYPE enhcompheader-version, + lv_shorttext TYPE string. + + FIELD-SYMBOLS: TYPE enhcompositename, + LIKE LINE OF lt_enh_childs. + + lv_package = iv_package. + io_xml->read( EXPORTING iv_name = 'SHORTTEXT' + CHANGING cg_data = lv_shorttext ). + io_xml->read( EXPORTING iv_name = 'COMPOSITE_CHILDS' + CHANGING cg_data = lt_composite_childs ). + io_xml->read( EXPORTING iv_name = 'ENH_CHILDS' + CHANGING cg_data = lt_enh_childs ). + io_xml->read( EXPORTING iv_name = 'LONGTEXT_ID' + CHANGING cg_data = lv_longtext_id ). + + SELECT SINGLE version FROM enhcompheader INTO lv_vers WHERE enhcomposite = ms_item-obj_name. + IF sy-subrc = 0. + " If object exists already, then set TADIR entry to deleted + " otherwise create_enhancement_composite will fail + tadir_delete( ). + ENDIF. + + TRY. + cl_enh_factory=>create_enhancement_composite( + EXPORTING + name = mv_composite_id + run_dark = abap_true + IMPORTING + composite = li_enh_composite + CHANGING + devclass = lv_package ). + + li_enh_composite->if_enh_object_docu~set_shorttext( lv_shorttext ). + + LOOP AT lt_composite_childs ASSIGNING . + li_enh_composite->add_composite_child( ). + ENDLOOP. + + LOOP AT lt_enh_childs ASSIGNING . + li_enh_composite->add_enh_child( ). + ENDLOOP. + + li_enh_composite->set_longtext_id( lv_longtext_id ). + + li_enh_composite->if_enh_object~save( ). + li_enh_composite->if_enh_object~activate( ). + li_enh_composite->if_enh_object~unlock( ). + + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + cl_enh_factory=>load_enhancement_composite( + name = mv_composite_id + lock = abap_false ). + rv_bool = abap_true. + CATCH cx_enh_root. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_argument TYPE seqg3-garg. + + lv_argument = |{ mv_composite_id }|. + OVERLAY lv_argument WITH ' '. + lv_argument = |{ lv_argument }*|. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = |E_ENHANCE| + iv_argument = lv_argument ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lx_enh_root TYPE REF TO cx_enh_root, + li_enh_composite TYPE REF TO if_enh_composite, + lt_composite_childs TYPE enhcompositename_it, + lt_enh_childs TYPE enhname_it, + lv_longtext_id TYPE enhdocuobject, + lv_shorttext TYPE string. + + TRY. + li_enh_composite = cl_enh_factory=>load_enhancement_composite( + name = mv_composite_id + lock = abap_false ). + + lv_shorttext = li_enh_composite->if_enh_object_docu~get_shorttext( ). + + lt_composite_childs = li_enh_composite->get_composite_childs( ). + lt_enh_childs = li_enh_composite->get_enh_childs( ). + lv_longtext_id = li_enh_composite->get_longtext_id( ). + + io_xml->add( iv_name = 'SHORTTEXT' + ig_data = lv_shorttext ). + io_xml->add( iv_name = 'COMPOSITE_CHILDS' + ig_data = lt_composite_childs ). + io_xml->add( iv_name = 'ENH_CHILDS' + ig_data = lt_enh_childs ). + io_xml->add( iv_name = 'LONGTEXT_ID' + ig_data = lv_longtext_id ). + + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ecvo IMPLEMENTATION. + METHOD get_download. + + CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_val_obj_down. + + ENDMETHOD. + METHOD get_lock_object. + + rv_lock_object = 'E_ECATT_TD'. + + ENDMETHOD. + METHOD get_object_type. + +* constant missing in 702, cl_apl_ecatt_const=>obj_type_ecatt_vo + rv_object_type = 'ECVO'. + + ENDMETHOD. + METHOD get_upload. + + CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_val_obj_upl. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ectd IMPLEMENTATION. + METHOD get_download. + + CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_data_downl. + + ENDMETHOD. + METHOD get_lock_object. + + rv_lock_object = 'E_ECATT_TD'. + + ENDMETHOD. + METHOD get_object_type. + + rv_object_type = cl_apl_ecatt_const=>obj_type_test_data. + + ENDMETHOD. + METHOD get_upload. + + CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_data_upload. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ectc IMPLEMENTATION. + METHOD get_download. + + CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_config_downl. + + ENDMETHOD. + METHOD get_lock_object. + + rv_lock_object = 'E_ECATT_TC'. + + ENDMETHOD. + METHOD get_object_type. + + rv_object_type = cl_apl_ecatt_const=>obj_type_test_config. + + ENDMETHOD. + METHOD get_upload. + + CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_config_upl. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ecsp IMPLEMENTATION. + METHOD get_download. + + CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_sp_download. + + ENDMETHOD. + METHOD get_lock_object. + + rv_lock_object = 'E_ECATT_SP'. + + ENDMETHOD. + METHOD get_object_type. + +* constant missing in 702, cl_apl_ecatt_const=>obj_type_start_profile + rv_object_type = 'ECSP'. + + ENDMETHOD. + METHOD get_upload. + + CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_sp_upload. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ecsd IMPLEMENTATION. + METHOD get_download. + + CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_system_downl. + + ENDMETHOD. + METHOD get_lock_object. + + rv_lock_object = 'E_ECATT_SD'. + + ENDMETHOD. + METHOD get_object_type. + + rv_object_type = cl_apl_ecatt_const=>obj_type_system_data. + + ENDMETHOD. + METHOD get_upload. + + CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_system_upl. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ecatt_super IMPLEMENTATION. + METHOD clear_attributes. + + DATA: li_element TYPE REF TO if_ixml_element, + lv_object_type TYPE etobj_type. + + lv_object_type = get_object_type( ). + + li_element = ci_document->find_from_name( |{ lv_object_type }| ). + li_element->remove_attribute( |SAPRL| ). + li_element->remove_attribute( |DOWNLOADDATE| ). + li_element->remove_attribute( |DOWNLOADTIME| ). + + ENDMETHOD. + METHOD clear_element. + + DATA: li_element TYPE REF TO if_ixml_element. + + li_element = ci_document->find_from_name( iv_name ). + + IF li_element IS BOUND. + li_element->set_value( || ). + ENDIF. + + ENDMETHOD. + METHOD clear_elements. + + clear_element( EXPORTING iv_name = |FUSER| + CHANGING ci_document = ci_document ). + + clear_element( EXPORTING iv_name = |FDATE| + CHANGING ci_document = ci_document ). + + clear_element( EXPORTING iv_name = |LUSER| + CHANGING ci_document = ci_document ). + + clear_element( EXPORTING iv_name = |LDATE| + CHANGING ci_document = ci_document ). + + clear_element( EXPORTING iv_name = |LTIME| + CHANGING ci_document = ci_document ). + + clear_element( EXPORTING iv_name = |TWB_RESP| + CHANGING ci_document = ci_document ). + + clear_element( EXPORTING iv_name = |DEVCLASS| + CHANGING ci_document = ci_document ). + + clear_element( EXPORTING iv_name = |TADIR_RESP| + CHANGING ci_document = ci_document ). + + " Clearing just VAR_EXT_PATH will lead to diffs in batch + clear_element( EXPORTING iv_name = |ETVAR_EXT| + CHANGING ci_document = ci_document ). + + " SORTLNR is part of ETPAR_VARI and causing diffs + " We can clear it since it's automatically filled during deserialize + clear_element_collection( EXPORTING iv_name = |SORTLNR| + CHANGING ci_document = ci_document ). + + ENDMETHOD. + METHOD clear_element_collection. + + DATA: + lo_node_collection TYPE REF TO if_ixml_node_collection, + lo_node TYPE REF TO if_ixml_node, + lv_index TYPE i. + + lo_node_collection = ci_document->get_elements_by_tag_name( iv_name ). + + lv_index = 0. + WHILE lv_index < lo_node_collection->get_length( ). + lo_node = lo_node_collection->get_item( lv_index ). + lo_node->set_value( '' ). + lv_index = lv_index + 1. + ENDWHILE. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_object_name = ms_item-obj_name. + + ENDMETHOD. + METHOD deserialize_version. + + DATA: ls_object TYPE etmobjects, + lo_upload TYPE REF TO cl_apl_ecatt_upload, + li_upload TYPE REF TO zif_abapgit_ecatt_upload, + lv_xml TYPE xstring, + li_document TYPE REF TO if_ixml_document, + lv_version TYPE string, + lx_error TYPE REF TO cx_ecatt. + + lv_version = get_version_from_node( ii_version_node ). + + IF lv_version IS INITIAL. + RETURN. + ENDIF. + + lo_upload = get_upload( ). + li_upload ?= lo_upload. + + li_document = cl_ixml=>create( )->create_document( ). + li_document->append_child( ii_version_node->get_first_child( ) ). + + lv_xml = cl_ixml_80_20=>render_to_xstring( li_document ). + + li_upload->set_stream_for_upload( lv_xml ). + + ls_object-d_obj_name = mv_object_name. + ls_object-s_obj_type = get_object_type( ). + ls_object-d_devclass = iv_package. + ls_object-d_obj_ver = lv_version. + ls_object-d_overwrite = abap_true. + + TRY. + lo_upload->upload( CHANGING ch_object = ls_object ). + + CATCH cx_ecatt INTO lx_error. + zcx_abapgit_exception=>raise( lx_error->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD get_changed_by_user. + + rv_changed_by_user = ii_document->find_from_name( 'LUSER' )->get_value( ). + + ENDMETHOD. + METHOD get_changed_date. + + DATA: lv_changed_date_external TYPE string. + + lv_changed_date_external = ii_document->find_from_name( 'LDATE' )->get_value( ). + + REPLACE ALL OCCURRENCES OF '-' IN lv_changed_date_external WITH ''. + rv_changed_date = lv_changed_date_external. + + ENDMETHOD. + METHOD get_changed_time. + + DATA: lv_changed_time_external TYPE string. + + lv_changed_time_external = ii_document->find_from_name( 'LTIME' )->get_value( ). + + REPLACE ALL OCCURRENCES OF ':' IN lv_changed_time_external WITH ''. + rv_changed_time = lv_changed_time_external. + + ENDMETHOD. + METHOD get_change_information. + + DATA: li_document TYPE REF TO if_ixml_document, + lv_xml TYPE xstring, + lo_download TYPE REF TO cl_apl_ecatt_download, + lv_object_type TYPE etobj_type. + + lo_download = get_download( ). + + lv_object_type = get_object_type( ). + + lv_xml = zcl_abapgit_ecatt_helper=>build_xml_of_object( + iv_object_name = mv_object_name + iv_object_version = is_version_info-version + iv_object_type = lv_object_type + io_download = lo_download ). + + li_document = cl_ixml_80_20=>parse_to_document( stream_xstring = lv_xml ). + + rs_change_information-ldate = get_changed_date( li_document ). + rs_change_information-ltime = get_changed_time( li_document ). + rs_change_information-luser = get_changed_by_user( li_document ). + + ENDMETHOD. + METHOD get_version_from_node. + + TRY. + rv_version = ii_node->get_first_child( + )->get_first_child( + )->get_first_child( + )->get_first_child( + )->get_value( ). + + CATCH cx_sy_ref_is_initial. + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD is_change_more_recent_than. + + IF is_currently_changed-ldate > is_last_changed-ldate + OR ( is_currently_changed-ldate = is_last_changed-ldate + AND is_currently_changed-ltime > is_last_changed-ltime ). + + rv_is_change_more_recent = abap_true. + + ENDIF. + + ENDMETHOD. + METHOD serialize_version. + + DATA: li_document TYPE REF TO if_ixml_document, + lv_xml TYPE xstring, + li_node TYPE REF TO if_ixml_element, + lo_download TYPE REF TO cl_apl_ecatt_download, + lv_object_type TYPE etobj_type. + + lo_download = get_download( ). + + lv_object_type = get_object_type( ). + + lv_xml = zcl_abapgit_ecatt_helper=>build_xml_of_object( + iv_object_name = mv_object_name + iv_object_version = iv_version + iv_object_type = lv_object_type + io_download = lo_download ). + + IF lv_xml IS INITIAL. + zcx_abapgit_exception=>raise( |ECATT, empty xml, { mv_object_name }| ). + ENDIF. + + li_document = cl_ixml_80_20=>parse_to_document( stream_xstring = lv_xml ). + + clear_attributes( CHANGING ci_document = li_document ). + + clear_elements( CHANGING ci_document = li_document ). + + li_node = li_document->create_element( c_name-version ). + li_node->append_child( li_document->get_root_element( ) ). + + ci_node->append_child( li_node ). + + ENDMETHOD. + METHOD serialize_versions. + + DATA: li_versions_node TYPE REF TO if_ixml_element. + FIELD-SYMBOLS: LIKE LINE OF it_version_info. + + li_versions_node = ci_document->create_element( c_name-versions ). + + IF lines( it_version_info ) > 0. + + LOOP AT it_version_info ASSIGNING . + + serialize_version( + EXPORTING + iv_version = -version + CHANGING + ci_node = li_versions_node ). + + ENDLOOP. + + ELSE. + + serialize_version( + EXPORTING + iv_version = c_default_version + CHANGING + ci_node = li_versions_node ). + + ENDIF. + + ci_document->append_child( li_versions_node ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: ls_last_changed TYPE ty_last_changed, + ls_currently_changed TYPE ty_last_changed, + lt_version_info TYPE etversinfo_tabtype, + lx_error TYPE REF TO cx_static_check, + lv_text TYPE string, + lv_object_type TYPE etobj_type. + + FIELD-SYMBOLS: LIKE LINE OF lt_version_info. + + TRY. + lv_object_type = get_object_type( ). + + cl_apl_ecatt_object=>get_version_info_object( + EXPORTING + im_name = mv_object_name + im_obj_type = lv_object_type + IMPORTING + ex_version_info = lt_version_info ). + + LOOP AT lt_version_info ASSIGNING . + + ls_currently_changed = get_change_information( ). + + IF is_change_more_recent_than( is_currently_changed = ls_currently_changed + is_last_changed = ls_last_changed ) = abap_true. + ls_last_changed = ls_currently_changed. + ENDIF. + + ENDLOOP. + + CATCH cx_static_check INTO lx_error. + lv_text = lx_error->get_text( ). + MESSAGE lv_text TYPE 'S' DISPLAY LIKE 'E'. + ENDTRY. + + IF ls_last_changed-luser IS NOT INITIAL. + rv_user = ls_last_changed-luser. + ELSE. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lx_error TYPE REF TO cx_ecatt_apl, + lv_text TYPE string, + lv_object_type TYPE etobj_type. + + lv_object_type = get_object_type( ). + + TRY. + cl_apl_ecatt_object=>delete_object( im_obj_type = lv_object_type + im_name = mv_object_name + " we have to supply a version, so let's use the default version + " and delete them all + im_version = c_default_version + im_delete_all_versions = abap_true ). + + CATCH cx_ecatt_apl INTO lx_error. + lv_text = lx_error->get_text( ). + zcx_abapgit_exception=>raise( lv_text ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: li_document TYPE REF TO if_ixml_document, + li_versions TYPE REF TO if_ixml_node_collection, + li_version_iterator TYPE REF TO if_ixml_node_iterator, + li_version_node TYPE REF TO if_ixml_node. + + li_document = io_xml->get_raw( ). + + li_versions = li_document->get_elements_by_tag_name( depth = 0 + name = c_name-version ). + + li_version_iterator = li_versions->create_iterator( ). + + DO. + li_version_node = li_version_iterator->get_next( ). + + IF li_version_node IS NOT BOUND. + EXIT. + ENDIF. + + deserialize_version( ii_version_node = li_version_node + iv_package = iv_package ). + + ENDDO. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_object_type TYPE etobj_type. + + lv_object_type = get_object_type( ). + + TRY. + rv_bool = cl_apl_ecatt_object=>existence_check_object( im_name = mv_object_name + im_version = c_default_version + im_obj_type = lv_object_type + im_exists_any_version = abap_true ). + + CATCH cx_ecatt. + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + DATA: lv_object TYPE seqg3-garg. + + lv_object = ms_item-obj_name. + OVERLAY lv_object WITH ' '. + lv_object = lv_object && '*'. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = get_lock_object( ) + iv_argument = lv_object ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + lt_version_info TYPE etversinfo_tabtype, + li_document TYPE REF TO if_ixml_document, + lx_error TYPE REF TO cx_ecatt, + lv_text TYPE string, + lv_object_type TYPE etobj_type. + + lv_object_type = get_object_type( ). + + TRY. + cl_apl_ecatt_object=>get_version_info_object( + EXPORTING + im_name = mv_object_name + im_obj_type = lv_object_type + IMPORTING + ex_version_info = lt_version_info ). + + SORT lt_version_info BY version. + + li_document = cl_ixml=>create( )->create_document( ). + + serialize_versions( + EXPORTING + it_version_info = lt_version_info + CHANGING + ci_document = li_document ). + + io_xml->set_raw( li_document->get_root_element( ) ). + + CATCH cx_ecatt INTO lx_error. + lv_text = lx_error->get_text( ). + MESSAGE lv_text TYPE 'S' DISPLAY LIKE 'E'. + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ecat IMPLEMENTATION. + METHOD get_download. + + CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_script_downl. + + ENDMETHOD. + METHOD get_lock_object. + + rv_lock_object = 'E_ECATT'. + + ENDMETHOD. + METHOD get_object_type. + + rv_object_type = cl_apl_ecatt_const=>obj_type_test_script. + + ENDMETHOD. + METHOD get_upload. + + CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_script_upl. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_dtel IMPLEMENTATION. + METHOD deserialize_texts. + + DATA: lv_name TYPE ddobjname, + ls_dd04v_tmp TYPE dd04v, + lt_i18n_langs TYPE TABLE OF langu, + lt_dd04_texts TYPE ty_dd04_texts. + + FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, + LIKE LINE OF lt_dd04_texts. + lv_name = ms_item-obj_name. + + ii_xml->read( EXPORTING iv_name = 'I18N_LANGS' + CHANGING cg_data = lt_i18n_langs ). + + ii_xml->read( EXPORTING iv_name = 'DD04_TEXTS' + CHANGING cg_data = lt_dd04_texts ). + + mo_i18n_params->trim_saplang_list( CHANGING ct_sap_langs = lt_i18n_langs ). + + SORT lt_i18n_langs. + SORT lt_dd04_texts BY ddlanguage. " Optimization + + LOOP AT lt_i18n_langs ASSIGNING . + + " Data element description + ls_dd04v_tmp = is_dd04v. + READ TABLE lt_dd04_texts ASSIGNING WITH KEY ddlanguage = . + IF sy-subrc > 0. + zcx_abapgit_exception=>raise( |DD04_TEXTS cannot find lang { } in XML| ). + ENDIF. + MOVE-CORRESPONDING TO ls_dd04v_tmp. + CALL FUNCTION 'DDIF_DTEL_PUT' + EXPORTING + name = lv_name + dd04v_wa = ls_dd04v_tmp + EXCEPTIONS + dtel_not_found = 1 + name_inconsistent = 2 + dtel_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD serialize_texts. + + DATA: lv_name TYPE ddobjname, + lv_index TYPE i, + ls_dd04v TYPE dd04v, + lt_dd04_texts TYPE ty_dd04_texts, + lt_i18n_langs TYPE TABLE OF langu, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, + LIKE LINE OF lt_dd04_texts. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + lv_name = ms_item-obj_name. + + " Collect additional languages, skip main lang - it was serialized already + lt_language_filter = mo_i18n_params->build_language_filter( ). + + SELECT DISTINCT ddlanguage AS langu INTO TABLE lt_i18n_langs + FROM dd04v + WHERE rollname = lv_name + AND ddlanguage IN lt_language_filter + AND ddlanguage <> mv_language + ORDER BY langu. "#EC CI_SUBRC + + LOOP AT lt_i18n_langs ASSIGNING . + lv_index = sy-tabix. + CALL FUNCTION 'DDIF_DTEL_GET' + EXPORTING + name = lv_name + langu = + IMPORTING + dd04v_wa = ls_dd04v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0 OR ls_dd04v-ddlanguage IS INITIAL. + DELETE lt_i18n_langs INDEX lv_index. " Don't save this lang + CONTINUE. + ENDIF. + + APPEND INITIAL LINE TO lt_dd04_texts ASSIGNING . + MOVE-CORRESPONDING ls_dd04v TO . + + ENDLOOP. + + SORT lt_i18n_langs ASCENDING. + SORT lt_dd04_texts BY ddlanguage ASCENDING. + + IF lines( lt_i18n_langs ) > 0. + ii_xml->add( iv_name = 'I18N_LANGS' + ig_data = lt_i18n_langs ). + + ii_xml->add( iv_name = 'DD04_TEXTS' + ig_data = lt_dd04_texts ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE as4user FROM dd04l INTO rv_user + WHERE rollname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + delete_ddic( 'E' ). + + delete_longtexts( c_longtext_id_dtel ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_dd04v TYPE dd04v, + ls_extra TYPE ty_extra, + lv_name TYPE ddobjname. + + io_xml->read( EXPORTING iv_name = 'DD04V' + CHANGING cg_data = ls_dd04v ). + + corr_insert( iv_package = iv_package + ig_object_class = 'DICT' ). + + lv_name = ms_item-obj_name. " type conversion + + CALL FUNCTION 'DDIF_DTEL_PUT' + EXPORTING + name = lv_name + dd04v_wa = ls_dd04v + EXCEPTIONS + dtel_not_found = 1 + name_inconsistent = 2 + dtel_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " Fields that are not part of dd04v + io_xml->read( EXPORTING iv_name = 'DD04L_EXTRA' + CHANGING cg_data = ls_extra ). + + TRY. + set_abap_language_version( CHANGING cv_abap_language_version = ls_extra-abap_language_version ). + + UPDATE ('DD04L') SET abap_language_version = ls_extra-abap_language_version WHERE rollname = lv_name. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + deserialize_texts( + ii_xml = io_xml + is_dd04v = ls_dd04v ). + ENDIF. + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_dtel ). + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_name = 'LONGTEXTS_' && c_longtext_id_dtel_suppl + iv_longtext_id = c_longtext_id_dtel_suppl ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_rollname TYPE dd04l-rollname. + + lv_rollname = ms_item-obj_name. + + " Check nametab because it's fast + CALL FUNCTION 'DD_GET_NAMETAB_HEADER' + EXPORTING + tabname = lv_rollname + EXCEPTIONS + not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + " Check for inactive or modified versions + SELECT SINGLE rollname FROM dd04l INTO lv_rollname + WHERE rollname = lv_rollname. + ENDIF. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECT=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. +* fm DDIF_DTEL_GET bypasses buffer, so SELECTs are +* done directly from here + + DATA: lv_name TYPE ddobjname, + ls_extra TYPE ty_extra, + ls_dd04v TYPE dd04v. + + FIELD-SYMBOLS TYPE any. + + lv_name = ms_item-obj_name. + + SELECT SINGLE * FROM dd04l + INTO CORRESPONDING FIELDS OF ls_dd04v + WHERE rollname = lv_name + AND as4local = 'A' + AND as4vers = '0000'. + IF sy-subrc <> 0 OR ls_dd04v IS INITIAL. + RETURN. + ENDIF. + + SELECT SINGLE * FROM dd04t + INTO CORRESPONDING FIELDS OF ls_dd04v + WHERE rollname = lv_name + AND ddlanguage = mv_language + AND as4local = 'A' + AND as4vers = '0000'. + + CLEAR: ls_dd04v-as4user, + ls_dd04v-as4date, + ls_dd04v-as4time. + + IF ls_dd04v-refkind = 'D'. +* clear values inherited from domain + CLEAR: ls_dd04v-datatype, + ls_dd04v-leng, + ls_dd04v-decimals, + ls_dd04v-outputlen, + ls_dd04v-valexi, + ls_dd04v-lowercase, + ls_dd04v-signflag, + ls_dd04v-convexit, + ls_dd04v-entitytab. + ENDIF. + + ASSIGN COMPONENT 'ACTFLAG' OF STRUCTURE ls_dd04v TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'RESERVEDTE' OF STRUCTURE ls_dd04v TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + + IF ls_dd04v-routputlen = ''. +* numeric field, make sure it is initial or XML serialization will dump + CLEAR ls_dd04v-routputlen. + ENDIF. + IF ls_dd04v-authclass = ''. + CLEAR ls_dd04v-authclass. + ENDIF. + + io_xml->add( iv_name = 'DD04V' + ig_data = ls_dd04v ). + + ls_extra-abap_language_version = get_abap_language_version( ). + + io_xml->add( iv_name = 'DD04L_EXTRA' + ig_data = ls_extra ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + serialize_texts( io_xml ). + ENDIF. + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_dtel ). + + serialize_longtexts( ii_xml = io_xml + iv_longtext_name = 'LONGTEXTS_' && c_longtext_id_dtel_suppl + iv_longtext_id = c_longtext_id_dtel_suppl ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_dtdc IMPLEMENTATION. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_dynamic_cache + TO . + IF sy-subrc = 0. + CLEAR: . + ENDIF. + + ENDMETHOD. + METHOD clear_fields. + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_AT' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_BY' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_AT' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_BY' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-MASTER_LANGUAGE' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-RESPONSIBLE' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-PACKAGE_REF' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-ABAP_LANGUAGE_VERSION' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + clear_field( + EXPORTING + iv_fieldname = 'METADATA-ABAP_LANGU_VERSION' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + + clear_field( + EXPORTING + iv_fieldname = 'CONTENT-SOURCE' + CHANGING + cs_dynamic_cache = cs_dynamic_cache ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_dynamic_cache_key = ms_item-obj_name. + mv_has_own_wb_data_class = has_own_wb_data_class( ). + + TRY. + IF mv_has_own_wb_data_class = abap_true. + CREATE DATA mr_dynamic_cache TYPE ('CL_DTDC_WB_OBJECT_DATA=>TY_DTDC_OBJECT_DATA'). + ELSE. + CREATE DATA mr_dynamic_cache TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). + ENDIF. + CREATE OBJECT mi_persistence TYPE ('CL_DTDC_OBJECT_PERSIST'). + + CATCH cx_sy_create_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD fill_metadata_from_db. + + DATA: + li_wb_object_operator TYPE REF TO object, + lr_dynamic_cache_old TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE xsddatetime_z, + TYPE syuname, + TYPE xsddatetime_z, + TYPE syuname. + + li_wb_object_operator = get_wb_object_operator( ). + + IF mv_has_own_wb_data_class = abap_true. + CREATE DATA lr_dynamic_cache_old TYPE ('CL_DTDC_WB_OBJECT_DATA=>TY_DTDC_OBJECT_DATA'). + ELSE. + CREATE DATA lr_dynamic_cache_old TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). + ENDIF. + ASSIGN lr_dynamic_cache_old->* TO . + ASSERT sy-subrc = 0. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + data = . + + ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE cs_dynamic_cache + TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE cs_dynamic_cache + TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + = . + = . + + ENDMETHOD. + METHOD get_wb_object_operator. + + DATA: + ls_object_type TYPE wbobjtype, + lx_error TYPE REF TO cx_root. + + IF mi_wb_object_operator IS BOUND. + ri_wb_object_operator = mi_wb_object_operator. + ENDIF. + + ls_object_type-objtype_tr = 'DTDC'. + ls_object_type-subtype_wb = 'DF'. + + TRY. + CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') + EXPORTING + object_type = ls_object_type + object_key = mv_dynamic_cache_key + RECEIVING + result = mi_wb_object_operator. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ri_wb_object_operator = mi_wb_object_operator. + + ENDMETHOD. + METHOD has_own_wb_data_class. + + DATA: + lr_own_type TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + TRY. + CREATE DATA lr_own_type TYPE ('CL_DTDC_WB_OBJECT_DATA=>TY_DTDC_OBJECT_DATA'). + rv_supported = abap_true. + CATCH cx_root INTO lx_error. + rv_supported = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root, + li_wb_object_operator TYPE REF TO object. + + TRY. + li_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = li_object_data_model. + + rv_user = li_object_data_model->get_changed_by( ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + lx_error TYPE REF TO cx_root, + li_wb_object_operator TYPE REF TO object. + + TRY. + li_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') + EXPORTING + transport_request = iv_transport. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + li_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: + TYPE uccheck, + TYPE any, + TYPE data. + + ASSIGN mr_dynamic_cache->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'DTDC' + CHANGING + cg_data = ). + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + IF mv_has_own_wb_data_class = abap_true. + CREATE OBJECT li_object_data_model TYPE ('CL_DTDC_WB_OBJECT_DATA'). + ELSE. + CREATE OBJECT li_object_data_model TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). + ENDIF. + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + = mo_files->read_string( 'asdtdc' ). + + tadir_insert( iv_package ). + + IF zif_abapgit_object~exists( ) = abap_true. + + " We need to populate created_at, created_by, because otherwise update is not possible + fill_metadata_from_db( CHANGING cs_dynamic_cache = ). + li_object_data_model->set_data( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = li_object_data_model + transport_request = iv_transport. + + ELSE. + + li_object_data_model->set_data( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = li_object_data_model + data_selection = 'P' " if_wb_object_data_selection_co=>c_properties + package = iv_package + transport_request = iv_transport. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = li_object_data_model + data_selection = 'D' " if_wb_object_data_selection_co=>c_data_content + transport_request = iv_transport. + + ENDIF. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~ACTIVATE'). + + ASSIGN COMPONENT 'METADATA-ABAP_LANGUAGE_VERSION' OF STRUCTURE + TO . + IF sy-subrc = 0. + set_abap_language_version( CHANGING cv_abap_language_version = ). + + TRY. + UPDATE ('DDDTDC_SOURCE') SET abap_language_version = + WHERE dtdc_name = ms_item-obj_name. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + ENDIF. + + corr_insert( iv_package ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + mi_persistence->get( + p_object_key = mv_dynamic_cache_key + p_version = 'A' + p_existence_check_only = abap_true ). + rv_bool = abap_true. + + CATCH cx_swb_exception. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + li_wb_object_operator TYPE REF TO object, + li_object_data_model TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root, + lv_source TYPE string. + + FIELD-SYMBOLS: + TYPE uccheck, + TYPE any, + TYPE string. + + ASSIGN mr_dynamic_cache->* TO . + ASSERT sy-subrc = 0. + + TRY. + li_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + version = 'A' + IMPORTING + data = + eo_object_data = li_object_data_model. + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + lv_source = . + + clear_fields( CHANGING cs_dynamic_cache = ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ASSIGN COMPONENT 'METADATA-ABAP_LANGUAGE_VERSION' OF STRUCTURE TO . + IF sy-subrc = 0. + = get_abap_language_version( ). + ENDIF. + + io_xml->add( + iv_name = 'DTDC' + ig_data = ). + + mo_files->add_string( + iv_ext = 'asdtdc' + iv_string = lv_source ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_dsys IMPLEMENTATION. + METHOD constructor. + + DATA: lv_prefix TYPE namespace, + lv_bare_name TYPE progname. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + IF ms_item-obj_name(1) = '/'. + + CALL FUNCTION 'RS_NAME_SPLIT_NAMESPACE' + EXPORTING + name_with_namespace = ms_item-obj_name + IMPORTING + namespace = lv_prefix + name_without_namespace = lv_bare_name. + + mv_doc_object = |{ lv_bare_name+0(4) }{ lv_prefix }{ lv_bare_name+4(*) }|. + ELSE. + + mv_doc_object = ms_item-obj_name. + ENDIF. + + ENDMETHOD. + METHOD deserialize_dsys. + + DATA: ls_data TYPE ty_data, + ls_docu_info TYPE dokil, + lv_version TYPE dokvers, + lv_doku_obj TYPE doku_obj. + + lv_doku_obj = mv_doc_object. + ii_xml->read( EXPORTING iv_name = 'DSYS' + CHANGING cg_data = ls_data ). + + CALL FUNCTION 'DOCU_INIT' + EXPORTING + id = c_id + langu = mv_language + object = lv_doku_obj + typ = c_typ + IMPORTING + xdokil = ls_docu_info. + + lv_version = ls_docu_info-version. + + CALL FUNCTION 'DOCU_UPDATE' + EXPORTING + head = ls_data-head + state = 'A' + typ = c_typ + version = lv_version + TABLES + line = ls_data-lines. + + ENDMETHOD. + METHOD get_main_lang. + + SELECT SINGLE langu FROM dokil INTO rv_language + WHERE id = c_id + AND object = mv_doc_object + AND masterlang = abap_true. "#EC CI_NOORDER + + IF sy-subrc <> 0. + rv_language = mv_language. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + rv_user = zcl_abapgit_factory=>get_longtexts( )->changed_by( + iv_object_name = mv_doc_object + iv_longtext_id = c_id ). + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + zcl_abapgit_factory=>get_longtexts( )->delete( + iv_object_name = mv_doc_object + iv_longtext_id = c_id ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_metadata TYPE zif_abapgit_definitions=>ty_metadata. + + ls_metadata = io_xml->get_metadata( ). + + CASE ls_metadata-version. + + WHEN 'v1.0.0'. + deserialize_dsys( io_xml ). + + WHEN 'v2.0.0'. + zcl_abapgit_factory=>get_longtexts( )->deserialize( + ii_xml = io_xml + iv_object_name = mv_doc_object + iv_longtext_id = c_id + iv_main_language = mv_language ). + + WHEN OTHERS. + zcx_abapgit_exception=>raise( 'unsupported DSYS version' ). + + ENDCASE. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_count TYPE i. + + SELECT SINGLE COUNT( * ) FROM dokil INTO lv_count + WHERE id = c_id + AND object = mv_doc_object. "#EC CI_GENBUFF "#EC CI_NOORDER + + rv_bool = boolc( lv_count > 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + rs_metadata-version = 'v2.0.0'. + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA lv_lang TYPE sy-langu. + + lv_lang = get_main_lang( ). + + CALL FUNCTION 'DSYS_EDIT' + EXPORTING + dokclass = mv_doc_object+0(4) + dokname = mv_doc_object+4(*) + doklangu = lv_lang + EXCEPTIONS + not_hypertext_class = 1 + no_editor = 2 + OTHERS = 3. + + rv_exit = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + zcl_abapgit_factory=>get_longtexts( )->serialize( + iv_object_name = mv_doc_object + iv_longtext_id = c_id + io_i18n_params = mo_i18n_params + ii_xml = io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_drul IMPLEMENTATION. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_dependency_rule + TO . + ASSERT sy-subrc = 0. + + CLEAR: . + + ENDMETHOD. + METHOD clear_fields. + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_AT' + CHANGING + cs_dependency_rule = cs_dependency_rule ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_BY' + CHANGING + cs_dependency_rule = cs_dependency_rule ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_AT' + CHANGING + cs_dependency_rule = cs_dependency_rule ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_BY' + CHANGING + cs_dependency_rule = cs_dependency_rule ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-MASTER_LANGUAGE' + CHANGING + cs_dependency_rule = cs_dependency_rule ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-RESPONSIBLE' + CHANGING + cs_dependency_rule = cs_dependency_rule ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-PACKAGE_REF' + CHANGING + cs_dependency_rule = cs_dependency_rule ). + + clear_field( + EXPORTING + iv_fieldname = 'CONTENT-SOURCE' + CHANGING + cs_dependency_rule = cs_dependency_rule ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_dependency_rule_key = ms_item-obj_name. + + TRY. + CREATE DATA mr_dependency_rule TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). + CREATE OBJECT mi_persistence TYPE ('CL_DRUL_WB_OBJECT_PERSIST'). + + CATCH cx_sy_create_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD fill_metadata_from_db. + + DATA: + li_wb_object_operator TYPE REF TO object, + lr_dependency_rule_old TYPE REF TO data, + lv_drul_object_data_clas_exist TYPE c LENGTH 1. + + FIELD-SYMBOLS: + TYPE any, + TYPE xsddatetime_z, + TYPE syuname, + TYPE xsddatetime_z, + TYPE syuname. + + li_wb_object_operator = get_wb_object_operator( ). + + CREATE DATA lr_dependency_rule_old TYPE ('CL_BLUE_SOURCE_OBJECT_DATA2=>TY_OBJECT_DATA'). + CALL FUNCTION 'CHECK_EXIST_CLAS' + EXPORTING + name = 'CL_DRUL_WB_OBJECT_DATA' + IMPORTING + exist = lv_drul_object_data_clas_exist + EXCEPTIONS + tr_invalid_type = 1 + OTHERS = 2. + + IF sy-subrc = 0 AND lv_drul_object_data_clas_exist = abap_true. + CREATE DATA lr_dependency_rule_old TYPE ('CL_DRUL_WB_OBJECT_DATA=>TY_OBJECT_DATA'). + ELSE. + CREATE DATA lr_dependency_rule_old TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). + ENDIF. + ASSIGN lr_dependency_rule_old->* TO . + ASSERT sy-subrc = 0. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + data = . + + ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE cs_dependency_rule + TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE cs_dependency_rule + TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + = . + = . + + ENDMETHOD. + METHOD get_wb_object_operator. + + DATA: + ls_object_type TYPE wbobjtype, + lx_error TYPE REF TO cx_root. + + IF mi_wb_object_operator IS BOUND. + ri_wb_object_operator = mi_wb_object_operator. + ENDIF. + + ls_object_type-objtype_tr = 'DRUL'. + ls_object_type-subtype_wb = 'DRL'. + + TRY. + CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') + EXPORTING + object_type = ls_object_type + object_key = mv_dependency_rule_key + RECEIVING + result = mi_wb_object_operator. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ri_wb_object_operator = mi_wb_object_operator. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: + li_wb_object_operator TYPE REF TO object, + li_object_data_model TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root. + + TRY. + li_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = li_object_data_model. + + rv_user = li_object_data_model->get_changed_by( ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + lx_error TYPE REF TO cx_root, + li_wb_object_operator TYPE REF TO object. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') + EXPORTING + transport_request = iv_transport. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + li_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root, + lv_drul_object_data_clas_exist TYPE c LENGTH 1. + + FIELD-SYMBOLS: + TYPE any, + TYPE data. + + ASSIGN mr_dependency_rule->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'DRUL' + CHANGING + cg_data = ). + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL FUNCTION 'CHECK_EXIST_CLAS' + EXPORTING + name = 'CL_DRUL_WB_OBJECT_DATA' + IMPORTING + exist = lv_drul_object_data_clas_exist + EXCEPTIONS + tr_invalid_type = 1 + OTHERS = 2. + + IF sy-subrc = 0 AND lv_drul_object_data_clas_exist = abap_true. + CREATE OBJECT li_object_data_model TYPE ('CL_DRUL_WB_OBJECT_DATA'). + ELSE. + CREATE OBJECT li_object_data_model TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). + ENDIF. + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + = mo_files->read_string( 'asdrul' ). + + tadir_insert( iv_package ). + + IF zif_abapgit_object~exists( ) = abap_true. + + " We need to populate created_at, created_by, because otherwise update is not possible + fill_metadata_from_db( CHANGING cs_dependency_rule = ). + li_object_data_model->set_data( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = li_object_data_model + transport_request = iv_transport. + + ELSE. + + li_object_data_model->set_data( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = li_object_data_model + data_selection = 'P' " if_wb_object_data_selection_co=>c_properties + package = iv_package + transport_request = iv_transport. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = li_object_data_model + data_selection = 'D' " if_wb_object_data_selection_co=>c_data_content + transport_request = iv_transport. + + ENDIF. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~ACTIVATE'). + + corr_insert( iv_package ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + mi_persistence->get( + p_object_key = mv_dependency_rule_key + p_version = 'A' + p_existence_check_only = abap_true ). + rv_bool = abap_true. + + CATCH cx_swb_exception. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + li_wb_object_operator TYPE REF TO object, + li_object_data_model TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root, + lv_source TYPE string. + + FIELD-SYMBOLS: + TYPE any, + TYPE string. + + ASSIGN mr_dependency_rule->* TO . + ASSERT sy-subrc = 0. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + version = 'A' + IMPORTING + data = + eo_object_data = li_object_data_model. + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + lv_source = . + + clear_fields( CHANGING cs_dependency_rule = ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + io_xml->add( + iv_name = 'DRUL' + ig_data = ). + + mo_files->add_string( + iv_ext = 'asdrul' + iv_string = lv_source ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_doma IMPLEMENTATION. + METHOD adjust_exit. + + DATA lv_function TYPE funcname. + + IF cv_exit IS NOT INITIAL. + lv_function = |CONVERSION_EXIT_{ cv_exit }_INPUT|. + + " If exit function does not exist, remove it + IF zcl_abapgit_factory=>get_function_module( )->function_exists( lv_function ) = abap_false. + cv_exit = ''. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD check_exit. + + DATA lv_exit TYPE dd01v-convexit. + + rv_done = abap_true. + + IF iv_exit IS NOT INITIAL. + " Check if exit function is set correctly + SELECT SINGLE convexit FROM dd01v INTO lv_exit WHERE domname = ms_item-obj_name. + IF sy-subrc = 0 AND lv_exit <> iv_exit. + rv_done = abap_false. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD deserialize_texts. + + DATA: lv_name TYPE ddobjname, + lv_valpos TYPE valpos, + ls_dd01v_tmp TYPE dd01v, + lt_dd07v_tmp TYPE TABLE OF dd07v, + lt_i18n_langs TYPE TABLE OF langu, + lt_dd01_texts TYPE ty_dd01_texts, + lt_dd07_texts TYPE ty_dd07_texts. + + FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, + LIKE LINE OF it_dd07v, + LIKE LINE OF lt_dd01_texts, + LIKE LINE OF lt_dd07_texts. + + lv_name = ms_item-obj_name. + + ii_xml->read( EXPORTING iv_name = 'I18N_LANGS' + CHANGING cg_data = lt_i18n_langs ). + + ii_xml->read( EXPORTING iv_name = 'DD01_TEXTS' + CHANGING cg_data = lt_dd01_texts ). + + ii_xml->read( EXPORTING iv_name = 'DD07_TEXTS' + CHANGING cg_data = lt_dd07_texts ). + + mo_i18n_params->trim_saplang_list( CHANGING ct_sap_langs = lt_i18n_langs ). + + SORT lt_i18n_langs. + SORT lt_dd07_texts BY ddlanguage. " Optimization + + LOOP AT lt_i18n_langs ASSIGNING . + + " Domain description + ls_dd01v_tmp = is_dd01v. + READ TABLE lt_dd01_texts ASSIGNING WITH KEY ddlanguage = . + IF sy-subrc > 0. + zcx_abapgit_exception=>raise( |DD01_TEXTS cannot find lang { } in XML| ). + ENDIF. + MOVE-CORRESPONDING TO ls_dd01v_tmp. + + " Domain values + lt_dd07v_tmp = it_dd07v. + LOOP AT lt_dd07v_tmp ASSIGNING . + lv_valpos = -valpos. + " it_dd07v was potentially renumbered so lookup by value + READ TABLE lt_dd07_texts ASSIGNING + WITH KEY ddlanguage = domvalue_l = -domvalue_l domvalue_h = -domvalue_h. + IF sy-subrc = 0. + MOVE-CORRESPONDING TO . + -valpos = lv_valpos. + DELETE lt_dd07_texts INDEX sy-tabix. " Optimization + ELSE. + " no translation -> keep entry but clear texts + -ddlanguage = . + CLEAR: -ddtext, -domval_ld, -domval_hd. + ENDIF. + ENDLOOP. + + CALL FUNCTION 'DDIF_DOMA_PUT' + EXPORTING + name = lv_name + dd01v_wa = ls_dd01v_tmp + TABLES + dd07v_tab = lt_dd07v_tmp + EXCEPTIONS + doma_not_found = 1 + name_inconsistent = 2 + doma_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD handle_dependencies. + + " For domains with dependency on conversion exit function, we use two phases: + " 1) DDIC phase: + " - If function does not exit, remove the exit function + " 2) LATE phase + " - If function was removed, change it to the correct exit function + CASE iv_step. + WHEN zif_abapgit_object=>gc_step_id-ddic. + adjust_exit( CHANGING cv_exit = cv_exit ). + + WHEN zif_abapgit_object=>gc_step_id-late. + cv_done = check_exit( cv_exit ). + + WHEN zif_abapgit_object=>gc_step_id-lxe. + cv_done = abap_true. + + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + + ENDMETHOD. + METHOD serialize_texts. + + DATA: lv_name TYPE ddobjname, + lv_index TYPE i, + ls_dd01v TYPE dd01v, + lt_dd07v TYPE TABLE OF dd07v, + lt_i18n_langs TYPE TABLE OF langu, + lt_dd01_texts TYPE ty_dd01_texts, + lt_dd07_texts TYPE ty_dd07_texts, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, + LIKE LINE OF lt_dd07v, + LIKE LINE OF lt_dd07v, + LIKE LINE OF lt_dd01_texts, + LIKE LINE OF lt_dd07_texts. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + lv_name = ms_item-obj_name. + + " Collect additional languages, skip main lang - it was serialized already + lt_language_filter = mo_i18n_params->build_language_filter( ). + + SELECT DISTINCT ddlanguage AS langu INTO TABLE lt_i18n_langs + FROM dd01v + WHERE domname = lv_name + AND ddlanguage IN lt_language_filter + AND ddlanguage <> mv_language + ORDER BY langu. "#EC CI_SUBRC + + SELECT DISTINCT ddlanguage AS langu APPENDING TABLE lt_i18n_langs + FROM dd07v + WHERE domname = lv_name + AND ddlanguage IN lt_language_filter + AND ddlanguage <> mv_language + ORDER BY langu. "#EC CI_SUBRC + + SORT lt_i18n_langs. + DELETE ADJACENT DUPLICATES FROM lt_i18n_langs. + + LOOP AT lt_i18n_langs ASSIGNING . + lv_index = sy-tabix. + + CALL FUNCTION 'DDIF_DOMA_GET' + EXPORTING + name = lv_name + langu = + IMPORTING + dd01v_wa = ls_dd01v + TABLES + dd07v_tab = lt_dd07v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + DELETE lt_i18n_langs INDEX lv_index. " Don't save this lang + CONTINUE. + ENDIF. + + IF ls_dd01v-ddlanguage IS INITIAL. + ls_dd01v-ddlanguage = . + ENDIF. + + APPEND INITIAL LINE TO lt_dd01_texts ASSIGNING . + MOVE-CORRESPONDING ls_dd01v TO . + + " Process main language entries and find corresponding translation + LOOP AT it_dd07v ASSIGNING WHERE NOT ddlanguage IS INITIAL. + APPEND INITIAL LINE TO lt_dd07_texts ASSIGNING . + READ TABLE lt_dd07v ASSIGNING + WITH KEY ddlanguage = domvalue_l = -domvalue_l domvalue_h = -domvalue_h. + IF sy-subrc = 0. + MOVE-CORRESPONDING TO . + ELSE. + " no translation -> keep entry but clear texts + MOVE-CORRESPONDING TO . + -ddlanguage = . + CLEAR: -ddtext, -domval_ld, -domval_hd. + ENDIF. + ENDLOOP. + + ENDLOOP. + + SORT lt_i18n_langs ASCENDING. + SORT lt_dd01_texts BY ddlanguage ASCENDING. + SORT lt_dd07_texts BY valpos ASCENDING ddlanguage ASCENDING. + + IF lines( lt_i18n_langs ) > 0. + ii_xml->add( iv_name = 'I18N_LANGS' + ig_data = lt_i18n_langs ). + + ii_xml->add( iv_name = 'DD01_TEXTS' + ig_data = lt_dd01_texts ). + + ii_xml->add( iv_name = 'DD07_TEXTS' + ig_data = lt_dd07_texts ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE as4user FROM dd01l INTO rv_user + WHERE domname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + delete_ddic( iv_objtype = 'D' + iv_no_ask_delete_append = abap_true ). + + delete_longtexts( c_longtext_id_doma ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + +* package SEDD +* package SDIC + + DATA: lv_name TYPE ddobjname, + lv_done TYPE abap_bool, + ls_dd01v TYPE dd01v, + ls_extra TYPE ty_extra, + lt_dd07v TYPE TABLE OF dd07v. + + FIELD-SYMBOLS TYPE dd07v. + + io_xml->read( EXPORTING iv_name = 'DD01V' + CHANGING cg_data = ls_dd01v ). + io_xml->read( EXPORTING iv_name = 'DD07V_TAB' + CHANGING cg_data = lt_dd07v ). + + handle_dependencies( + EXPORTING + iv_step = iv_step + CHANGING + cv_exit = ls_dd01v-convexit + cv_done = lv_done ). + + IF lv_done = abap_true. + RETURN. + ENDIF. + + corr_insert( iv_package = iv_package + ig_object_class = 'DICT' ). + + lv_name = ms_item-obj_name. " type conversion + + LOOP AT lt_dd07v ASSIGNING . + -domname = lv_name. + -valpos = sy-tabix. + ENDLOOP. + + CALL FUNCTION 'DDIF_DOMA_PUT' + EXPORTING + name = lv_name + dd01v_wa = ls_dd01v + TABLES + dd07v_tab = lt_dd07v + EXCEPTIONS + doma_not_found = 1 + name_inconsistent = 2 + doma_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " Fields that are not part of dd01v + io_xml->read( EXPORTING iv_name = 'DD01L_EXTRA' + CHANGING cg_data = ls_extra ). + + TRY. + set_abap_language_version( CHANGING cv_abap_language_version = ls_extra-abap_language_version ). + + UPDATE ('DD01L') SET abap_language_version = ls_extra-abap_language_version WHERE domname = lv_name. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + deserialize_texts( + ii_xml = io_xml + is_dd01v = ls_dd01v + it_dd07v = lt_dd07v ). + ENDIF. + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_doma ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA lv_domname TYPE dd01l-domname. + + SELECT SINGLE domname FROM dd01l INTO lv_domname + WHERE domname = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECT=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_name TYPE ddobjname, + lv_state TYPE ddgotstate, + ls_dd01v TYPE dd01v, + ls_extra TYPE ty_extra, + lv_masklen TYPE c LENGTH 4, + lt_dd07v TYPE TABLE OF dd07v. + + FIELD-SYMBOLS TYPE dd07v. + FIELD-SYMBOLS TYPE any. + + lv_name = ms_item-obj_name. + + CALL FUNCTION 'DDIF_DOMA_GET' + EXPORTING + name = lv_name + state = 'A' + langu = mv_language + IMPORTING + gotstate = lv_state + dd01v_wa = ls_dd01v + TABLES + dd07v_tab = lt_dd07v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF ls_dd01v IS INITIAL OR lv_state <> 'A'. + RETURN. + ENDIF. + + CLEAR: ls_dd01v-as4user, + ls_dd01v-as4date, + ls_dd01v-as4time, + ls_dd01v-appexist. + + ASSIGN COMPONENT 'ACTFLAG' OF STRUCTURE ls_dd01v TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + +* make sure XML serialization does not dump if the field contains invalid data +* note that this is a N field, so '' is not valid + IF ls_dd01v-authclass = ''. + CLEAR ls_dd01v-authclass. + ENDIF. + lv_masklen = ls_dd01v-masklen. + IF lv_masklen = '' OR NOT lv_masklen CO '0123456789'. + CLEAR ls_dd01v-masklen. + ENDIF. + + DELETE lt_dd07v WHERE appval = abap_true. + + SORT lt_dd07v BY + valpos ASCENDING + ddlanguage ASCENDING. + + LOOP AT lt_dd07v ASSIGNING . + CLEAR -domname. + ENDLOOP. + + io_xml->add( iv_name = 'DD01V' + ig_data = ls_dd01v ). + io_xml->add( iv_name = 'DD07V_TAB' + ig_data = lt_dd07v ). + + ls_extra-abap_language_version = get_abap_language_version( ). + + io_xml->add( iv_name = 'DD01L_EXTRA' + ig_data = ls_extra ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + serialize_texts( + ii_xml = io_xml + it_dd07v = lt_dd07v ). + ENDIF. + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_doma ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_docv IMPLEMENTATION. + METHOD constructor. + + DATA: lv_prefix TYPE namespace, + lv_bare_name TYPE progname. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + IF ms_item-obj_name(2) <> 'DT' AND ms_item-obj_name NP '/*/DT*'. " IN, MO, UO, UP + mv_id = ms_item-obj_name(2). + mv_doc_object = ms_item-obj_name+2. + ELSE. " DT + CALL FUNCTION 'RS_NAME_SPLIT_NAMESPACE' + EXPORTING + name_with_namespace = ms_item-obj_name + IMPORTING + namespace = lv_prefix + name_without_namespace = lv_bare_name + EXCEPTIONS + delimiter_error = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error determining namespace for { ms_item-obj_type } { ms_item-obj_name }| ). + ENDIF. + + mv_id = lv_bare_name(2). + mv_doc_object = |{ lv_prefix }{ lv_bare_name+2 }|. + ENDIF. + + ENDMETHOD. + METHOD read. + + CALL FUNCTION 'DOCU_READ' + EXPORTING + id = mv_id + langu = mv_language + object = mv_doc_object + typ = c_typ + version = c_version + IMPORTING + doktitle = rs_data-doctitle + head = rs_data-head + TABLES + line = rs_data-lines. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = read( )-head-tdluser. + IF rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + CALL FUNCTION 'DOCU_DEL' + EXPORTING + id = mv_id + langu = mv_language + object = mv_doc_object + typ = c_typ + EXCEPTIONS + ret_code = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_data TYPE ty_data. + io_xml->read( EXPORTING iv_name = c_name + CHANGING cg_data = ls_data ). + + CALL FUNCTION 'DOCU_UPDATE' + EXPORTING + head = ls_data-head + state = 'A' + typ = c_typ + version = c_version + TABLES + line = ls_data-lines. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + SELECT SINGLE id FROM dokil INTO mv_id + WHERE id = mv_id + AND object = mv_doc_object. "#EC CI_GENBUFF "#EC CI_NOORDER + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_data TYPE ty_data. + ls_data = read( ). + + CLEAR: ls_data-head-tdfuser, + ls_data-head-tdfreles, + ls_data-head-tdfdate, + ls_data-head-tdftime, + ls_data-head-tdluser, + ls_data-head-tdlreles, + ls_data-head-tdldate, + ls_data-head-tdltime. + + io_xml->add( iv_name = c_name + ig_data = ls_data ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_doct IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mi_longtexts = zcl_abapgit_factory=>get_longtexts( ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + rv_user = mi_longtexts->changed_by( + iv_object_name = ms_item-obj_name + iv_longtext_id = c_id ). + + IF rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + mi_longtexts->delete( + iv_object_name = ms_item-obj_name + iv_longtext_id = c_id ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + mi_longtexts->deserialize( + iv_longtext_name = c_name + iv_object_name = ms_item-obj_name + iv_longtext_id = c_id + ii_xml = io_xml + iv_main_language = mv_language ). + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_id TYPE dokil-id, + lv_object TYPE dokhl-object. + lv_object = ms_item-obj_name. + + SELECT SINGLE id FROM dokil INTO lv_id + WHERE id = c_id + AND object = lv_object. "#EC CI_GENBUFF "#EC CI_NOORDER + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: ls_dokentry TYPE dokentry, + ls_bcdata TYPE bdcdata, + lt_bcdata TYPE STANDARD TABLE OF bdcdata. + + " We need to modify dokentry directly, otherwise + " Batch Input on SE61 wouldn't work because it stores + " the last seen Document Class in this table. There's + " no standard function to do this. SE61 does this + " directly in its dialog modules + ls_dokentry-username = sy-uname. + ls_dokentry-langu = mv_language. + ls_dokentry-class = c_id. + MODIFY dokentry FROM ls_dokentry. + + ls_bcdata-program = 'SAPMSDCU'. + ls_bcdata-dynpro = '0100'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'RSDCU-OBJECT7'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=SHOW'. + APPEND ls_bcdata TO lt_bcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SE61' + it_bdcdata = lt_bcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + mi_longtexts->serialize( + iv_longtext_name = c_name + iv_object_name = ms_item-obj_name + iv_longtext_id = c_id + io_i18n_params = mo_i18n_params + ii_xml = io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_dial IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " not stored by SAP + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: ls_bcdata TYPE bdcdata, + lt_bcdata TYPE STANDARD TABLE OF bdcdata. + + ls_bcdata-program = 'SAPMSDIA'. + ls_bcdata-dynpro = '1010'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'DIAPAR-DNAM'. + ls_bcdata-fval = ms_item-obj_name. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'RS38L-PARM'. + ls_bcdata-fval = abap_true. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=DELF'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-program = 'SAPLSPO1'. + ls_bcdata-dynpro = '0100'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=YES'. + APPEND ls_bcdata TO lt_bcdata. + + ls_bcdata-program = 'SAPMSDIA'. + ls_bcdata-dynpro = '1010'. + ls_bcdata-dynbegin = 'X'. + APPEND ls_bcdata TO lt_bcdata. + + CLEAR ls_bcdata. + ls_bcdata-fnam = 'BDC_OKCODE'. + ls_bcdata-fval = '=BACK'. + APPEND ls_bcdata TO lt_bcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SE35' + it_bdcdata = lt_bcdata + iv_new_window = abap_false ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_dialog_module TYPE ty_dialog_module. + + " Prefill popup asking for package + set_default_package( iv_package ). + + io_xml->read( + EXPORTING + iv_name = 'DIAL' + CHANGING + cg_data = ls_dialog_module ). + + CALL FUNCTION 'RS_DIALOG_CREATE' + EXPORTING + dialogname = ls_dialog_module-tdct-dnam + dynpronumber = ls_dialog_module-tdct-dynr + programname = ls_dialog_module-tdct-prog + suppress_corr_check = abap_false +* It seems that dia_par parameter doesn't do anything, but we can't omit it +* Parameters are inserted below + TABLES + dia_par = ls_dialog_module-dia_pars + EXCEPTIONS + dialog_already_exists = 1 + invalid_name = 2 + OTHERS = 3. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error deserializing dialogmodule { ms_item-obj_name }| ). + ENDIF. + + " It seems that there's no API for diapar, therefore we manipulate it directly + INSERT diapar FROM TABLE ls_dialog_module-dia_pars. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_tdct TYPE tdct. + + ls_tdct = _read_tdct( ). + + rv_bool = boolc( ls_tdct IS NOT INITIAL ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + + rs_metadata = get_metadata( ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lv_objectname TYPE tdct-dnam. + + lv_objectname = ms_item-obj_name. + + CALL FUNCTION 'RS_DIALOG_SHOW' + EXPORTING + objectname = lv_objectname + type = 'VW' + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + + rv_exit = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA ls_dialog_module TYPE ty_dialog_module. + + ls_dialog_module-tdct = _read_tdct( ). + + SELECT * FROM diapar + INTO TABLE ls_dialog_module-dia_pars + WHERE dnam = ls_dialog_module-tdct-dnam + ORDER BY PRIMARY KEY. + + io_xml->add( iv_name = 'DIAL' + ig_data = ls_dialog_module ). + + ENDMETHOD. + METHOD _read_tdct. + + DATA: lv_dnam TYPE tdct-dnam. + + lv_dnam = ms_item-obj_name. + + SELECT SINGLE * FROM tdct + INTO rs_tdct + WHERE dnam = lv_dnam. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_devc IMPLEMENTATION. + METHOD adjust_sw_component. + + DATA: + lv_namespace TYPE namespace, + lv_comp_type TYPE c LENGTH 1. + + " Keep software component of a package for ABAP add-ons (customer and partner developments)... + SELECT SINGLE comp_type FROM cvers INTO lv_comp_type WHERE component = cv_dlvunit. + IF sy-subrc = 0 AND lv_comp_type = 'A'. + " ... with a matching namespace (typical Add-on Assembly Kit scenario) + lv_namespace = |/{ cv_dlvunit }/|. + SELECT SINGLE namespace FROM trnspace INTO lv_namespace WHERE namespace = lv_namespace. + IF sy-subrc <> 0. + CLEAR cv_dlvunit. + ENDIF. + ELSE. + CLEAR cv_dlvunit. + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + IF is_item-devclass IS NOT INITIAL. + mv_local_devclass = is_item-devclass. + ELSE. + mv_local_devclass = is_item-obj_name. + ENDIF. + + ENDMETHOD. + METHOD get_package. + IF zif_abapgit_object~exists( ) = abap_true. + ri_package = load_package( mv_local_devclass ). + ENDIF. + ENDMETHOD. + METHOD is_empty. + + DATA: lv_object_name TYPE tadir-obj_name, + lt_subpackages TYPE zif_abapgit_sap_package=>ty_devclass_tt. + + lt_subpackages = zcl_abapgit_factory=>get_sap_package( iv_package_name )->list_subpackages( ). + + IF lines( lt_subpackages ) > 0. + rv_is_empty = abap_false. + RETURN. + ENDIF. + + " Ignore the SOTR if is linked to the current SAP package (DEVC) + SELECT SINGLE obj_name + FROM tadir + INTO lv_object_name + WHERE pgmid = 'R3TR' + AND NOT ( ( object = 'DEVC' OR object = 'SOTR' ) AND obj_name = iv_package_name ) + AND devclass = iv_package_name. + rv_is_empty = boolc( sy-subrc <> 0 ). + + ENDMETHOD. + METHOD is_local. + + DATA lv_dlvunit TYPE tdevc-dlvunit. + + SELECT SINGLE dlvunit FROM tdevc INTO lv_dlvunit + WHERE devclass = iv_package_name AND intsys <> 'SAP'. + IF sy-subrc = 0 AND lv_dlvunit = 'LOCAL'. + rv_is_local = abap_true. + ENDIF. + + ENDMETHOD. + METHOD load_package. + + cl_package_factory=>load_package( + EXPORTING + i_package_name = iv_package_name + i_force_reload = abap_true + IMPORTING + e_package = ri_package + EXCEPTIONS + object_not_existing = 1 + unexpected_error = 2 + intern_err = 3 + no_access = 4 + object_locked_and_modified = 5 + OTHERS = 6 ). + IF sy-subrc = 1. + RETURN. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD remove_obsolete_tadir. + + DATA: + lv_pack TYPE devclass, + lt_pack TYPE STANDARD TABLE OF devclass, + ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, + lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, + ls_item TYPE zif_abapgit_definitions=>ty_item. + + " TADIR entries must remain for transportable packages + IF is_local( iv_package_name ) = abap_false. + RETURN. + ENDIF. + + " Clean-up sub packages first + SELECT devclass FROM tdevc INTO TABLE lt_pack + WHERE parentcl = iv_package_name + ORDER BY PRIMARY KEY. + + LOOP AT lt_pack INTO lv_pack. + remove_obsolete_tadir( lv_pack ). + ENDLOOP. + + " Remove TADIR entries for objects that do not exist anymore + SELECT * FROM tadir INTO CORRESPONDING FIELDS OF TABLE lt_tadir + WHERE devclass = iv_package_name + ORDER BY PRIMARY KEY ##TOO_MANY_ITAB_FIELDS. + + LOOP AT lt_tadir INTO ls_tadir. + ls_item-obj_type = ls_tadir-object. + ls_item-obj_name = ls_tadir-obj_name. + + IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. + zcl_abapgit_factory=>get_tadir( )->delete_single( + iv_object = ls_tadir-object + iv_obj_name = ls_tadir-obj_name ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD set_lock. + + DATA: lv_changeable TYPE abap_bool. + + ii_package->get_changeable( IMPORTING e_changeable = lv_changeable ). + IF lv_changeable <> iv_lock. + TRY. + CALL METHOD ii_package->('SET_CHANGEABLE') + EXPORTING + i_changeable = iv_lock + i_suppress_dialog = abap_true " Parameter missing in 702 + EXCEPTIONS + object_locked_by_other_user = 1 + permission_failure = 2 + object_already_changeable = 3 + object_already_unlocked = 4 + object_just_created = 5 + object_deleted = 6 + object_modified = 7 + object_not_existing = 8 + object_invalid = 9 + unexpected_error = 10 + OTHERS = 11. + CATCH cx_sy_dyn_call_param_not_found. + ii_package->set_changeable( + EXPORTING + i_changeable = iv_lock + EXCEPTIONS + object_locked_by_other_user = 1 + permission_failure = 2 + object_already_changeable = 3 + object_already_unlocked = 4 + object_just_created = 5 + object_deleted = 6 + object_modified = 7 + object_not_existing = 8 + object_invalid = 9 + unexpected_error = 10 + OTHERS = 11 ). + ENDTRY. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + TRY. + CALL METHOD ii_package->('SET_PERMISSIONS_CHANGEABLE') + EXPORTING + i_changeable = iv_lock + i_suppress_dialog = abap_true " Parameter missing in 702 + EXCEPTIONS + object_already_changeable = 1 + object_already_unlocked = 2 + object_locked_by_other_user = 3 + object_modified = 4 + object_just_created = 5 + object_deleted = 6 + permission_failure = 7 + object_invalid = 8 + unexpected_error = 9 + OTHERS = 10. + CATCH cx_sy_dyn_call_param_not_found. + ii_package->set_permissions_changeable( + EXPORTING + i_changeable = iv_lock + EXCEPTIONS + object_already_changeable = 1 + object_already_unlocked = 2 + object_locked_by_other_user = 3 + object_modified = 4 + object_just_created = 5 + object_deleted = 6 + permission_failure = 7 + object_invalid = 8 + unexpected_error = 9 + OTHERS = 10 ). + ENDTRY. + IF ( sy-subrc = 1 AND iv_lock = abap_true ) OR ( sy-subrc = 2 AND iv_lock = abap_false ). + " There's no getter to find out beforehand... + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD unlock_and_raise_error. + + DATA ls_msg TYPE bal_s_msg. + + " Remember message since unlock overwrites it (for example with XT465) + MOVE-CORRESPONDING sy TO ls_msg. + + set_lock( ii_package = ii_package + iv_lock = abap_false ). + + zcx_abapgit_exception=>raise_t100( + iv_msgid = ls_msg-msgid + iv_msgno = ls_msg-msgno + iv_msgv1 = ls_msg-msgv1 + iv_msgv2 = ls_msg-msgv2 + iv_msgv3 = ls_msg-msgv3 + iv_msgv4 = ls_msg-msgv4 ). + + ENDMETHOD. + METHOD update_pinf_usages. + DATA: lt_current_permissions TYPE tpak_permission_to_use_list, + li_usage TYPE REF TO if_package_permission_to_use, + ls_data_sign TYPE scomppsign, + ls_add_permission_data TYPE pkgpermdat, + lt_handled TYPE SORTED TABLE OF i WITH UNIQUE KEY table_line. + FIELD-SYMBOLS: LIKE LINE OF it_usage_data. + + " Get the current permissions + ii_package->get_permissions_to_use( + IMPORTING + e_permissions = lt_current_permissions + EXCEPTIONS + object_invalid = 1 + unexpected_error = 2 + OTHERS = 3 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ls_data_sign-err_sever = abap_true. + + " New permissions + LOOP AT it_usage_data ASSIGNING . + READ TABLE lt_current_permissions + WITH KEY table_line->package_interface_name = -intf_name + INTO li_usage. + + IF sy-subrc = 0 AND li_usage IS BOUND. + INSERT sy-tabix INTO TABLE lt_handled. + + " Permission already exists, update attributes + li_usage->set_all_attributes( + EXPORTING + i_permission_data = + i_data_sign = ls_data_sign + EXCEPTIONS + object_not_changeable = 1 + object_invalid = 2 + intern_err = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ELSE. + " Permission does not exist yet, add it + MOVE-CORRESPONDING TO ls_add_permission_data. + ii_package->add_permission_to_use( + EXPORTING + i_pkg_permission_data = ls_add_permission_data + EXCEPTIONS + object_not_changeable = 1 + object_access_error = 2 + object_already_existing = 3 + object_invalid = 4 + unexpected_error = 5 + OTHERS = 6 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDIF. + + FREE li_usage. + ENDLOOP. + + " Delete missing usages + LOOP AT lt_current_permissions INTO li_usage. + READ TABLE lt_handled WITH TABLE KEY table_line = sy-tabix TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + CONTINUE. + ENDIF. + + li_usage->delete( + EXCEPTIONS + object_not_changeable = 1 + object_invalid = 2 +* deletion_not_allowed = 3 downport, does not exist in 7.30 + intern_err = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDLOOP. + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + DATA li_package TYPE REF TO if_package. + + li_package = get_package( ). + IF li_package IS BOUND. + rv_user = li_package->changed_by. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: li_package TYPE REF TO if_package, + lv_package TYPE devclass. + + " Package deletion is a bit tricky. A package can only be deleted if there are no objects + " contained in it. This includes subpackages, so first the leaf packages need to be deleted. + " Unfortunately deleted objects that are still contained in an unreleased transport request + " also count towards the contained objects counter. + " -> Currently we delete only empty packages + " + " If objects are deleted, the TADIR entry is deleted when the transport request is released. + " So before we can delete the package, the transport which deletes the objects + " in the package has to be released. + + lv_package = ms_item-obj_name. + + " Remove remaining OTR entries + zcl_abapgit_sotr_handler=>delete_sotr_package( iv_package ). + + remove_obsolete_tadir( lv_package ). + + IF is_empty( lv_package ) = abap_true. + + li_package = load_package( lv_package ). + + IF li_package IS NOT BOUND. + RETURN. + ENDIF. + + IF lv_package(1) = '$'. + zcl_abapgit_persist_factory=>get_packages( )->modify( lv_package ). + ENDIF. + + set_lock( ii_package = li_package + iv_lock = abap_true ). + + TRY. + CALL METHOD li_package->('DELETE') + EXPORTING + i_suppress_dialog = abap_true " Parameter missing in 702 + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + intern_err = 4 + OTHERS = 5. + + CATCH cx_sy_dyn_call_param_not_found. + + li_package->delete( + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + intern_err = 4 + OTHERS = 5 ). + + ENDTRY. + + IF sy-subrc <> 0. + unlock_and_raise_error( li_package ). + ENDIF. + + TRY. + CALL METHOD li_package->('SAVE') + EXPORTING + i_suppress_dialog = abap_true + EXCEPTIONS + object_invalid = 1 + object_not_changeable = 2 + cancelled_in_corr = 3 + permission_failure = 4 + unexpected_error = 5 + intern_err = 6 + OTHERS = 7. + + CATCH cx_sy_dyn_call_param_not_found. + + li_package->save( + EXCEPTIONS + object_invalid = 1 + object_not_changeable = 2 + cancelled_in_corr = 3 + permission_failure = 4 + unexpected_error = 5 + intern_err = 6 + OTHERS = 7 ). + + ENDTRY. + + IF sy-subrc <> 0. + unlock_and_raise_error( li_package ). + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: li_package TYPE REF TO if_package, + ls_package_data TYPE scompkdtln, + ls_data_sign TYPE scompksign, + lt_usage_data TYPE scomppdata, + ls_save_sign TYPE paksavsign. + + FIELD-SYMBOLS: TYPE scomppdtln. + FIELD-SYMBOLS: TYPE any. + + mv_local_devclass = iv_package. + + io_xml->read( + EXPORTING + iv_name = 'DEVC' + CHANGING + cg_data = ls_package_data ). + + IF mv_local_devclass(1) = '$'. + IF ls_package_data-mainpack = 'X'. + zcx_abapgit_exception=>raise( |Main package { iv_package } cannot be used in local package| ). + ELSEIF ls_package_data-mainpack = 'S'. + zcx_abapgit_exception=>raise( |Structure package { iv_package } cannot be used in local package| ). + ENDIF. + ENDIF. + + li_package = get_package( ). + + " Swap out repository package name with the local installation package name + ls_package_data-devclass = mv_local_devclass. + IF li_package IS BOUND. + ls_package_data-pdevclass = li_package->transport_layer. + ENDIF. + + " For local packages store application component + IF ls_package_data-devclass(1) = '$'. + zcl_abapgit_persist_factory=>get_packages( )->modify( + iv_package = ls_package_data-devclass + iv_component = ls_package_data-component + iv_comp_posid = ls_package_data-comp_posid ). + ENDIF. + + " Parent package is not changed. Assume the folder logic already created the package and set + " the hierarchy before. + CLEAR ls_package_data-parentcl. + + ASSIGN COMPONENT 'PACKKIND' OF STRUCTURE ls_package_data TO . + IF sy-subrc = 0. + set_abap_language_version( CHANGING cv_abap_language_version = ). + ENDIF. + ASSIGN COMPONENT 'PACKKIND' OF STRUCTURE ls_data_sign TO . + IF sy-subrc = 0. + = abap_true. + ENDIF. + +* Fields not set: +* korrflag +* parentcl +* cli_check +* intprefx + IF ls_package_data-dlvunit IS NOT INITIAL. + ls_data_sign-dlvunit = abap_true. + ENDIF. + ls_data_sign-ctext = abap_true. + ls_data_sign-as4user = abap_true. + ls_data_sign-pdevclass = abap_true. + ls_data_sign-comp_posid = abap_true. + ls_data_sign-component = abap_true. + ls_data_sign-perminher = abap_true. + ls_data_sign-packtype = abap_true. + ls_data_sign-restricted = abap_true. + ls_data_sign-mainpack = abap_true. + ls_data_sign-srv_check = abap_true. + ls_data_sign-ext_alias = abap_true. + ls_data_sign-project_guid = abap_true. + ls_data_sign-project_id = abap_true. + ls_data_sign-project_passdown = abap_true. + + IF ls_package_data-ctext IS INITIAL. + ls_package_data-ctext = mv_local_devclass. + ENDIF. + IF ls_package_data-dlvunit IS INITIAL. + ls_package_data-dlvunit = 'HOME'. + ENDIF. + + ls_package_data-as4user = sy-uname. + + IF li_package IS BOUND. + " Package already exists, change it + set_lock( ii_package = li_package + iv_lock = abap_true ). + + li_package->set_all_attributes( + EXPORTING + i_package_data = ls_package_data + i_data_sign = ls_data_sign + EXCEPTIONS + object_not_changeable = 1 + object_deleted = 2 + object_invalid = 3 + short_text_missing = 4 + author_not_existing = 5 + local_package = 6 + software_component_invalid = 7 + layer_invalid = 8 + korrflag_invalid = 9 + component_not_existing = 10 + component_missing = 11 + authorize_failure = 12 + prefix_in_use = 13 + unexpected_error = 14 + intern_err = 15 +* wrong_mainpack_value = 16 downport, does not exist in 7.30 +* superpackage_invalid = 17 downport, does not exist in 7.30 + OTHERS = 18 ). + IF sy-subrc <> 0. + unlock_and_raise_error( li_package ). + ENDIF. + + ELSE. + " Package does not exist yet, create it + " This shouldn't really happen, because the folder logic initially creates the packages. + cl_package_factory=>create_new_package( + IMPORTING + e_package = li_package + CHANGING + c_package_data = ls_package_data + EXCEPTIONS + object_already_existing = 1 + object_just_created = 2 + not_authorized = 3 + wrong_name_prefix = 4 + undefined_name = 5 + reserved_local_name = 6 + invalid_package_name = 7 + short_text_missing = 8 + software_component_invalid = 9 + layer_invalid = 10 + author_not_existing = 11 + component_not_existing = 12 + component_missing = 13 + prefix_in_use = 14 + unexpected_error = 15 + intern_err = 16 + no_access = 17 +* invalid_translation_depth = 18 downport, does not exist in 7.30 +* wrong_mainpack_value = 19 downport, does not exist in 7.30 +* superpackage_invalid = 20 downport, does not exist in 7.30 +* error_in_cts_checks = 21 downport, does not exist in 7.31 + OTHERS = 22 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + " Load package interface usages + TRY. + io_xml->read( + EXPORTING + iv_name = 'PERMISSION' + CHANGING + cg_data = lt_usage_data ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + " No permissions saved + ENDTRY. + + LOOP AT lt_usage_data ASSIGNING . + -client_pak = mv_local_devclass. + ENDLOOP. + + update_pinf_usages( ii_package = li_package + it_usage_data = lt_usage_data ). + + ls_save_sign-pack = abap_true. + ls_save_sign-permis = abap_true. + ls_save_sign-elems = abap_true. + ls_save_sign-interf = abap_true. + + li_package->save_generic( + EXPORTING + i_save_sign = ls_save_sign + i_transport_request = iv_transport + i_suppress_dialog = abap_true + EXCEPTIONS + cancelled_in_corr = 1 + permission_failure = 2 + object_not_changeable = 3 + object_invalid = 4 + OTHERS = 5 ). + IF sy-subrc <> 0. + unlock_and_raise_error( li_package ). + ENDIF. + + set_lock( ii_package = li_package + iv_lock = abap_false ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + " Check remote package if deserialize has not been called before this + IF mv_local_devclass IS INITIAL. + rv_bool = abap_false. + ELSE. + cl_package_helper=>check_package_existence( + EXPORTING + i_package_name = mv_local_devclass + IMPORTING + e_package_exists = rv_bool + EXCEPTIONS + intern_err = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' + iv_argument = ms_item-obj_name + iv_prefix = 'DV' ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + + IF iv_item_part_of_filename <> zcl_abapgit_filename_logic=>c_package_file-obj_name. + zcx_abapgit_exception=>raise( |Unexpected filename for package { cs_item-obj_name }| ). + ENDIF. + + " Try to get a unique package name for DEVC by using the path + cs_item-obj_name = zcl_abapgit_folder_logic=>get_instance( )->path_to_package( + iv_top = iv_package + io_dot = io_dot + iv_create_if_not_exists = abap_false + iv_path = iv_path ). + + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + + " Packages have a fixed filename so that the repository can be installed to a different + " package(-hierarchy) on the client and not show up as a different package in the repo. + cv_item_part_of_filename = zcl_abapgit_filename_logic=>c_package_file-obj_name. + " use just obj_name ("package") so that e.g. translation files also have this first part + " yet be able to modify the extension e.g. package.i18n.de.po + + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + DATA: ls_package_data TYPE scompkdtln, + ls_package_comp TYPE zif_abapgit_persist_packages=>ty_package, + li_package TYPE REF TO if_package, + lt_intf_usages TYPE tpak_permission_to_use_list, + lt_usage_data TYPE scomppdata, + ls_usage_data TYPE scomppdtln, + li_usage TYPE REF TO if_package_permission_to_use. + + FIELD-SYMBOLS: TYPE any. + li_package = get_package( ). + IF li_package IS NOT BOUND. + zcx_abapgit_exception=>raise( |Could not find package to serialize.| ). + ENDIF. + + li_package->get_all_attributes( + IMPORTING + e_package_data = ls_package_data + EXCEPTIONS + object_invalid = 1 + package_deleted = 2 + intern_err = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " For local packages get application component + IF is_local( ls_package_data-devclass ) = abap_true. + ls_package_comp = zcl_abapgit_persist_factory=>get_packages( )->read( ls_package_data-devclass ). + ls_package_data-component = ls_package_comp-component. + ls_package_data-comp_posid = ls_package_comp-comp_posid. + ENDIF. + + CLEAR: ls_package_data-devclass, + ls_package_data-parentcl. + + " Clear administrative data to prevent diffs + CLEAR: ls_package_data-created_by, + ls_package_data-created_on, + ls_package_data-changed_by, + ls_package_data-changed_on, + ls_package_data-as4user. + + " Clear text descriptions that might be localized + CLEAR: ls_package_data-comp_text, + ls_package_data-dlvu_text, + ls_package_data-layer_text. + + " Clear obsolete fields + CLEAR: ls_package_data-intfprefx, + ls_package_data-cli_check. + + " If software component is related to add-on and a valid namespace, then keep it + adjust_sw_component( CHANGING cv_dlvunit = ls_package_data-dlvunit ). + + ASSIGN COMPONENT 'TRANSLATION_DEPTH_TEXT' + OF STRUCTURE ls_package_data + TO . + IF sy-subrc = 0. + CLEAR: . + ENDIF. + + ASSIGN COMPONENT 'TRANSLATION_GRAPH_DEPTH_TEXT' + OF STRUCTURE ls_package_data + TO . + IF sy-subrc = 0. + CLEAR: . + ENDIF. + + " Clear things related to local installation package + CLEAR: ls_package_data-namespace, + ls_package_data-dlvunit, + ls_package_data-tpclass, + ls_package_data-pdevclass. + + " Not usable on customer systems + ASSIGN COMPONENT 'TRANSLATION_DEPTH' + OF STRUCTURE ls_package_data + TO . + IF sy-subrc = 0. + CLEAR: . + ENDIF. + + ASSIGN COMPONENT 'TRANSLATION_GRAPH_DEPTH' + OF STRUCTURE ls_package_data + TO . + IF sy-subrc = 0. + CLEAR: . + ENDIF. + + CLEAR: ls_package_data-korrflag. + + ASSIGN COMPONENT 'PACKKIND' OF STRUCTURE ls_package_data TO . + IF sy-subrc = 0. + clear_abap_language_version( CHANGING cv_abap_language_version = ). + ENDIF. + + io_xml->add( iv_name = 'DEVC' + ig_data = ls_package_data ). + + " Save package interface usages + li_package->get_permissions_to_use( + IMPORTING + e_permissions = lt_intf_usages + EXCEPTIONS + object_invalid = 1 + unexpected_error = 2 + OTHERS = 3 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + LOOP AT lt_intf_usages INTO li_usage. + li_usage->get_all_attributes( + IMPORTING + e_permission_data = ls_usage_data + EXCEPTIONS + object_invalid = 1 + intern_err = 2 + OTHERS = 3 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CLEAR: ls_usage_data-pack_name, ls_usage_data-client_pak. + + APPEND ls_usage_data TO lt_usage_data. + ENDLOOP. + + IF lt_usage_data IS NOT INITIAL. + io_xml->add( iv_name = 'PERMISSION' + ig_data = lt_usage_data ). + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ddlx IMPLEMENTATION. + + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_object_key = ms_item-obj_name. + + TRY. + CREATE OBJECT mi_persistence + TYPE ('CL_DDLX_ADT_OBJECT_PERSIST'). + + CREATE OBJECT mi_data_model + TYPE ('CL_DDLX_WB_OBJECT_DATA'). + + CATCH cx_sy_create_object_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lr_data TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE data. + + CREATE DATA lr_data + TYPE ('CL_DDLX_WB_OBJECT_DATA=>TY_OBJECT_DATA'). + ASSIGN lr_data->* TO . + + TRY. + mi_persistence->get( + EXPORTING + p_object_key = mv_object_key + p_version = swbm_version_active + CHANGING + p_object_data = mi_data_model ). + CATCH cx_swb_exception. + rv_user = c_user_unknown. + RETURN. + ENDTRY. + + mi_data_model->get_data( IMPORTING p_data = ). + + ASSIGN COMPONENT 'METADATA-CHANGED_BY' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + rv_user = . + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lx_error TYPE REF TO cx_swb_exception. + + TRY. + mi_persistence->delete( p_object_key = mv_object_key + p_version = swbm_version_active ). + + CATCH cx_swb_exception INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lr_data TYPE REF TO data, + lx_error TYPE REF TO cx_swb_exception. + + FIELD-SYMBOLS: TYPE any, + TYPE data, + TYPE data, + TYPE data, + TYPE syuname, + TYPE xsddatetime_z, + TYPE data. + + CREATE DATA lr_data + TYPE ('CL_DDLX_WB_OBJECT_DATA=>TY_OBJECT_DATA'). + ASSIGN lr_data->* TO . + + io_xml->read( + EXPORTING + iv_name = 'DDLX' + CHANGING + cg_data = ). + + ASSIGN COMPONENT 'METADATA-ABAP_LANGU_VERSION' OF STRUCTURE TO . + IF sy-subrc = 0. + set_abap_language_version( CHANGING cv_abap_language_version = ). + ENDIF. + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + TRY. + " If the file doesn't exist that's ok, because previously + " the source code was stored in the xml. We are downward compatible. + = mo_files->read_string( 'asddlxs' ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + ASSIGN COMPONENT 'METADATA-VERSION' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + " We have to always save as inactive. Standard activation below activates then + " and also creates transport request entry if necessary + = 'inactive'. + + "package needed to be able to determine ABAP language version + ASSIGN COMPONENT 'METADATA-PACKAGE_REF-NAME' OF STRUCTURE TO . + IF IS ASSIGNED. + = iv_package. + ENDIF. + + ASSIGN COMPONENT 'METADATA-CHANGED_BY' OF STRUCTURE TO . + IF IS ASSIGNED. + = sy-uname. + ENDIF. + ASSIGN COMPONENT 'METADATA-CHANGED_AT' OF STRUCTURE TO . + IF IS ASSIGNED. + GET TIME STAMP FIELD . + ENDIF. + + mi_data_model->set_data( ). + + TRY. + mi_persistence->save( mi_data_model ). + CATCH cx_swb_exception INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + tadir_insert( iv_package ). + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = abap_true. + + TRY. + mi_persistence->get( p_object_key = mv_object_key + p_version = swbm_version_active + p_existence_check_only = abap_true ). + + CATCH cx_swb_exception. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_ADT_LINK=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lr_data TYPE REF TO data, + lx_error TYPE REF TO cx_swb_exception. + + FIELD-SYMBOLS: TYPE any, + TYPE data. + CREATE DATA lr_data + TYPE ('CL_DDLX_WB_OBJECT_DATA=>TY_OBJECT_DATA'). + ASSIGN lr_data->* TO . + + TRY. + IF zcl_abapgit_factory=>get_environment( )->compare_with_inactive( ) = abap_true. + "Retrieve inactive version + mi_persistence->get( + EXPORTING + p_object_key = mv_object_key + p_version = swbm_version_inactive + CHANGING + p_object_data = mi_data_model ). + IF mi_data_model->get_object_name( ) IS INITIAL. + "Fallback: retrieve active version + mi_persistence->get( + EXPORTING + p_object_key = mv_object_key + p_version = swbm_version_active + CHANGING + p_object_data = mi_data_model ). + ENDIF. + ELSE. + "Retrieve active version + mi_persistence->get( + EXPORTING + p_object_key = mv_object_key + p_version = swbm_version_active + CHANGING + p_object_data = mi_data_model ). + ENDIF. + + CATCH cx_swb_exception INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + mi_data_model->get_data( IMPORTING p_data = ). + + clear_fields( CHANGING cg_data = ). + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + mo_files->add_string( + iv_ext = 'asddlxs' + iv_string = ). + + CLEAR . + + io_xml->add( iv_name = 'DDLX' + ig_data = ). + + ENDMETHOD. + METHOD clear_fields. + + DATA: + BEGIN OF ls_fields_to_clear, + BEGIN OF metadata, + changed_at TYPE d, + changed_by TYPE c, + created_at TYPE d, + created_by TYPE c, + responsible TYPE c, + BEGIN OF package_ref, + name TYPE c, + END OF package_ref, + BEGIN OF container_ref, + name TYPE c, + END OF container_ref, + version TYPE c, + master_system TYPE c, + END OF metadata, + END OF ls_fields_to_clear. + + FIELD-SYMBOLS: + TYPE any. + + MOVE-CORRESPONDING ls_fields_to_clear TO cg_data. + + ASSIGN COMPONENT 'METADATA-ABAP_LANGUAGE_VERSION' OF STRUCTURE cg_data TO . + IF sy-subrc = 0. + clear_abap_language_version( CHANGING cv_abap_language_version = ). + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_object_ddls IMPLEMENTATION. + METHOD clear_fields. + + DATA: + BEGIN OF ls_fields_to_clear, + as4user TYPE c, + as4date TYPE d, + as4time TYPE t, + actflag TYPE c, + chgflag TYPE c, + abap_langu_version TYPE c, + END OF ls_fields_to_clear. + + FIELD-SYMBOLS: + TYPE any. + + MOVE-CORRESPONDING ls_fields_to_clear TO cg_data. + + ASSIGN COMPONENT 'ABAP_LANGUAGE_VERSION' OF STRUCTURE cg_data TO . + IF sy-subrc = 0. + = get_abap_language_version( ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CALL METHOD ('CL_DD_DDL_HANDLER_FACTORY')=>('CREATE') + RECEIVING + handler = mo_ddl_handler. + + CATCH cx_root. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD format_source_before_serialize. + + DATA: + lv_len TYPE i, + lv_lastchar1 TYPE c, + lv_lastchar2 TYPE c. + + " New line included in 751+ by CL_DD_DDL_HANDLER=>ADD_BASEOBJS_INFO_TO_DDLS + " Change for 750- + + lv_len = strlen( cv_string ) - 1. + IF lv_len < 0. + RETURN. + ENDIF. + lv_lastchar1 = cv_string+lv_len(1). + + lv_len = strlen( cv_string ) - 2. + IF lv_len < 0. + RETURN. + ENDIF. + lv_lastchar2 = cv_string+lv_len(1). + + " only add a line break, if the last character is unequal to cr_lf and newline ! + IF lv_lastchar1 <> cl_abap_char_utilities=>cr_lf AND lv_lastchar1 <> cl_abap_char_utilities=>newline AND + lv_lastchar1 <> space OR + ( lv_lastchar1 = space AND + ( lv_lastchar2 <> cl_abap_char_utilities=>cr_lf AND lv_lastchar2 <> cl_abap_char_utilities=>newline ) ). + cv_string = |{ cv_string }{ cl_abap_char_utilities=>cr_lf }|. + ENDIF. + + ENDMETHOD. + METHOD is_baseinfo_supported. + + DATA: + lr_data_baseinfo TYPE REF TO data. + + TRY. + CREATE DATA lr_data_baseinfo TYPE ('IF_DD_DDL_TYPES=>TY_S_BASEINFO_STRING_SAVE'). + rv_supported = abap_true. + CATCH cx_root. + rv_supported = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD open_adt_stob. + + DATA: lr_data TYPE REF TO data. + + FIELD-SYMBOLS: TYPE STANDARD TABLE. + FIELD-SYMBOLS: TYPE STANDARD TABLE. + FIELD-SYMBOLS: TYPE any. + FIELD-SYMBOLS: TYPE any. + FIELD-SYMBOLS: TYPE any. + FIELD-SYMBOLS: TYPE any. + CREATE DATA lr_data TYPE ('IF_DD_DDL_TYPES=>TY_T_DDOBJ'). + ASSIGN lr_data->* TO . + + CREATE DATA lr_data LIKE LINE OF . + ASSIGN lr_data->* TO . + + CREATE DATA lr_data TYPE ('IF_DD_DDL_TYPES=>TY_T_ENTITY_OF_VIEW'). + ASSIGN lr_data->* TO . + + CREATE DATA lr_data LIKE LINE OF . + ASSIGN lr_data->* TO . + + CLEAR . + ASSIGN COMPONENT 'NAME' OF STRUCTURE TO . + = iv_ddls_name. + INSERT INTO TABLE . + + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~GET_VIEWNAME_FROM_ENTITYNAME') + EXPORTING + ddnames = + IMPORTING + view_of_entity = . + + READ TABLE ASSIGNING INDEX 1. + IF sy-subrc = 0. + ASSIGN COMPONENT 'DDLNAME' OF STRUCTURE TO . + + zcl_abapgit_adt_link=>jump( iv_obj_name = + iv_obj_type = 'DDLS' ). + + ENDIF. + + ENDMETHOD. + METHOD read_baseinfo. + + TRY. + rv_baseinfo_string = mo_files->read_string( 'baseinfo' ). + + CATCH zcx_abapgit_exception. + " File not found. That's ok, as the object could have been created in a + " system where baseinfo wasn't supported. + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lr_data TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + CREATE DATA lr_data TYPE ('DDDDLSRCV'). + ASSIGN lr_data->* TO . + + TRY. + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~READ') + EXPORTING + name = ms_item-obj_name + get_state = 'A' + IMPORTING + ddddlsrcv_wa = . + + ASSIGN COMPONENT 'AS4USER' OF STRUCTURE TO . + IF sy-subrc = 0. + rv_user = . + ENDIF. + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + IF rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + lt_deltab TYPE TABLE OF dcdeltb, + ls_deltab TYPE dcdeltb, + lt_gentab TYPE TABLE OF dcgentb, + lv_rc TYPE sy-subrc. + + " CL_DD_DDL_HANDLER->DELETE does not work for CDS views that reference other views + " To drop any views regardless of reference, we use delnoref = false + ls_deltab-objtyp = 'DDLS'. + ls_deltab-objname = ms_item-obj_name. + APPEND ls_deltab TO lt_deltab. + + CALL FUNCTION 'DD_MASS_ACT_C3' + EXPORTING + ddmode = 'O' + inactive = abap_true + write_log = abap_false + delall = abap_true + delnoref = abap_false + prid = -1 + IMPORTING + act_rc = lv_rc + TABLES + gentab = lt_gentab + deltab = lt_deltab + EXCEPTIONS + access_failure = 1 + no_objects = 2 + locked = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + corr_insert( iv_package ). + + " rebuild object list to delete remaining TADIR entry + CALL FUNCTION 'WB_TREE_UPDATE_OBJECTLIST' + EXPORTING + p_object_type = 'DF' + p_object_name = ms_item-obj_name + p_operation = 'DELETE' + EXCEPTIONS + OTHERS = 0. + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + lr_data TYPE REF TO data, + lr_data_baseinfo TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE any, + TYPE any, + TYPE any, + TYPE any. + + CREATE DATA lr_data TYPE ('DDDDLSRCV'). + ASSIGN lr_data->* TO . + + TRY. + io_xml->read( EXPORTING iv_name = 'DDLS' + CHANGING cg_data = ). + + ASSIGN COMPONENT 'SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = mo_files->read_string( 'asddls' ). + + ASSIGN COMPONENT 'ABAP_LANGUAGE_VERSION' OF STRUCTURE TO . + IF sy-subrc = 0. + set_abap_language_version( CHANGING cv_abap_language_version = ). + ENDIF. + + IF is_baseinfo_supported( ) = abap_true. + CREATE DATA lr_data_baseinfo TYPE ('IF_DD_DDL_TYPES=>TY_S_BASEINFO_STRING_SAVE'). + ASSIGN lr_data_baseinfo->* TO . + + ASSIGN COMPONENT 'BASEINFO_STRING' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + = read_baseinfo( ). + + ASSIGN COMPONENT 'DDLNAME' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = ms_item-obj_name. + + TRY. + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~SAVE') + EXPORTING + name = ms_item-obj_name + put_state = 'N' + ddddlsrcv_wa = + baseinfo_string = + save_language_version = abap_true. + CATCH cx_sy_dyn_call_param_not_found. + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~SAVE') + EXPORTING + name = ms_item-obj_name + put_state = 'N' + ddddlsrcv_wa = + baseinfo_string = . + ENDTRY. + ELSE. + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~SAVE') + EXPORTING + name = ms_item-obj_name + put_state = 'N' + ddddlsrcv_wa = . + ENDIF. + + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~WRITE_TADIR') + EXPORTING + objectname = ms_item-obj_name + devclass = iv_package + prid = 0. + + corr_insert( iv_package ). + + CATCH cx_root INTO lx_error. + " Attempt clean-up but catch error if it doesn't work + TRY. + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~DELETE') + EXPORTING + name = ms_item-obj_name + prid = 0. + CATCH cx_root ##NO_HANDLER. + ENDTRY. + + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_state TYPE objstate. + + TRY. + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~READ') + EXPORTING + name = ms_item-obj_name + IMPORTING + got_state = lv_state. + rv_bool = boolc( NOT lv_state IS INITIAL ). + CATCH cx_root. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lv_typename TYPE typename. + DATA: lv_ddtypekind TYPE ddtypekind. + + lv_typename = ms_item-obj_name. + + CALL FUNCTION 'DDIF_TYPEINFO_GET' + EXPORTING + typename = lv_typename + IMPORTING + typekind = lv_ddtypekind. + + IF lv_ddtypekind = 'STOB'. + open_adt_stob( ms_item-obj_name ). + rv_exit = abap_true. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lr_data TYPE REF TO data, + lr_data_baseinfo TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any, + TYPE ANY TABLE, + TYPE any, + TYPE any, + TYPE any. + CREATE DATA lr_data TYPE ('DDDDLSRCV'). + ASSIGN lr_data->* TO . + + TRY. + + IF is_baseinfo_supported( ) = abap_true. + CREATE DATA lr_data_baseinfo TYPE ('IF_DD_DDL_TYPES=>TY_T_BASEINFO_STRING'). + ASSIGN lr_data_baseinfo->* TO . + + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~READ') + EXPORTING + name = ms_item-obj_name + get_state = 'A' + IMPORTING + ddddlsrcv_wa = + baseinfo_string = . + + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'DDLNAME' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'AS4LOCAL' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + IF = ms_item-obj_name AND = 'A'. + ASSIGN COMPONENT 'BASEINFO_STRING' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + mo_files->add_string( + iv_ext = 'baseinfo' + iv_string = ). + EXIT. + ENDIF. + ENDLOOP. + ELSE. + CALL METHOD mo_ddl_handler->('IF_DD_DDL_HANDLER~READ') + EXPORTING + name = ms_item-obj_name + get_state = 'A' + IMPORTING + ddddlsrcv_wa = . + ENDIF. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + clear_fields( CHANGING cg_data = ). + + ASSIGN COMPONENT 'SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + format_source_before_serialize( CHANGING cv_string = ). + + mo_files->add_string( + iv_ext = 'asddls' + iv_string = ). + + CLEAR . + + io_xml->add( iv_name = 'DDLS' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_dcls IMPLEMENTATION. + + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CALL METHOD ('CL_ACM_DCL_HANDLER_FACTORY')=>('CREATE') + RECEIVING + ro_handler = mo_dcl_handler. + + CATCH cx_root. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + DATA: lr_data TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + CREATE DATA lr_data TYPE ('ACM_S_DCLSRC'). + ASSIGN lr_data->* TO . + + TRY. + CALL METHOD mo_dcl_handler->('READ') + EXPORTING + iv_dclname = ms_item-obj_name + IMPORTING + es_dclsrc = . + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ASSIGN COMPONENT 'AS4USER' OF STRUCTURE TO . + IF sy-subrc = 0. + rv_user = . + ELSE. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lx_error TYPE REF TO cx_root. + + TRY. + CALL METHOD mo_dcl_handler->('DELETE') + EXPORTING + iv_dclname = ms_item-obj_name. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lr_data TYPE REF TO data, + lx_error TYPE REF TO cx_root, + lv_abap_language_version TYPE uccheck. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + CREATE DATA lr_data TYPE ('ACM_S_DCLSRC'). + ASSIGN lr_data->* TO . + + io_xml->read( + EXPORTING + iv_name = 'DCLS' + CHANGING + cg_data = ). + + ASSIGN COMPONENT 'SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = mo_files->read_string( 'asdcls' ). + + ASSIGN COMPONENT 'ABAP_LANGUAGE_VERSION' OF STRUCTURE TO . + IF sy-subrc = 0. + lv_abap_language_version = . + set_abap_language_version( CHANGING cv_abap_language_version = lv_abap_language_version ). + ENDIF. + + tadir_insert( iv_package ). + + TRY. + TRY. + CALL METHOD mo_dcl_handler->('SAVE') + EXPORTING + iv_dclname = ms_item-obj_name + iv_put_state = 'I' + is_dclsrc = + iv_devclass = iv_package + iv_access_mode = 'INSERT' + iv_abap_language_version = lv_abap_language_version. + CATCH cx_sy_dyn_call_param_not_found. + CALL METHOD mo_dcl_handler->('SAVE') + EXPORTING + iv_dclname = ms_item-obj_name + iv_put_state = 'I' + is_dclsrc = + iv_devclass = iv_package + iv_access_mode = 'INSERT'. + ENDTRY. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL METHOD mo_dcl_handler->('CHECK_EXISTENCE') + EXPORTING + iv_objectname = ms_item-obj_name + RECEIVING + rv_exists = rv_bool. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_ACMDCLSRC' + iv_argument = |{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_ADT_LINK=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lr_data TYPE REF TO data, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + CREATE DATA lr_data TYPE ('ACM_S_DCLSRC'). + ASSIGN lr_data->* TO . + + TRY. + CALL METHOD mo_dcl_handler->('READ') + EXPORTING + iv_dclname = ms_item-obj_name + IMPORTING + es_dclsrc = . + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + clear_fields( CHANGING cg_data = ). + + ASSIGN COMPONENT 'SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + mo_files->add_string( + iv_ext = 'asdcls' + iv_string = ). + + CLEAR . + + io_xml->add( iv_name = 'DCLS' + ig_data = ). + + ENDMETHOD. + METHOD clear_fields. + + DATA: + BEGIN OF ls_fields_to_clear, + as4user TYPE c, + as4date TYPE d, + as4time TYPE t, + created_by TYPE c, + created_date TYPE d, + as4local TYPE c, + END OF ls_fields_to_clear. + + FIELD-SYMBOLS: + TYPE any. + + MOVE-CORRESPONDING ls_fields_to_clear TO cg_data. + + ASSIGN COMPONENT 'ABAP_LANGUAGE_VERSION' OF STRUCTURE cg_data TO . + IF sy-subrc = 0. + clear_abap_language_version( CHANGING cv_abap_language_version = ). + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_object_cus2 IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_img_attribute = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA ls_header TYPE ty_customizing_attribute-header. + + CALL FUNCTION 'S_CUS_ATTRIBUTES_READ' + EXPORTING + img_attribute = mv_img_attribute + IMPORTING + attribute_header = ls_header. + + rv_user = ls_header-luser. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: ls_message TYPE hier_mess. + + CALL FUNCTION 'S_CUS_ATTRIBUTES_DELETE' + EXPORTING + img_attribute = mv_img_attribute + IMPORTING + message = ls_message. + + IF ls_message-msgty <> 'S'. + zcx_abapgit_exception=>raise( |error from delete CUS2 { mv_img_attribute } S_CUS_ATTRIBUTES_DELETE| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_customizing_attribute TYPE ty_customizing_attribute, + ls_message TYPE hier_mess. + + io_xml->read( + EXPORTING + iv_name = 'CUS2' + CHANGING + cg_data = ls_customizing_attribute ). + + CALL FUNCTION 'S_CUS_ATTRIBUTES_SAVE' + EXPORTING + img_attribute = ls_customizing_attribute-header + IMPORTING + message = ls_message + TABLES + attributes_title = ls_customizing_attribute-titles + attributes_countries = ls_customizing_attribute-countries + attributes_components = ls_customizing_attribute-components. + + IF ls_message-msgty <> 'S'. + zcx_abapgit_exception=>raise( |error from deserialize CUS2 { mv_img_attribute } S_CUS_ATTRIBUTES_SAVE| ). + ENDIF. + + corr_insert( iv_package ). + + tadir_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL FUNCTION 'S_CUS_ATTRIBUTES_EXIST' + EXPORTING + img_attribute = mv_img_attribute + EXCEPTIONS + attributes_exists_not = 1 + OTHERS = 2. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = abap_true. + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_customizing_attribute TYPE ty_customizing_attribute. + + CALL FUNCTION 'S_CUS_ATTRIBUTES_READ' + EXPORTING + img_attribute = mv_img_attribute + IMPORTING + attribute_header = ls_customizing_attribute-header + TABLES + attribute_title = ls_customizing_attribute-titles + attribute_countries = ls_customizing_attribute-countries + attribute_components = ls_customizing_attribute-components + attribute_components_variants = ls_customizing_attribute-components_variants. + + CLEAR: ls_customizing_attribute-header-fdatetime, + ls_customizing_attribute-header-fuser, + ls_customizing_attribute-header-ldatetime, + ls_customizing_attribute-header-luser. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + DELETE ls_customizing_attribute-titles WHERE spras <> mv_language. + ENDIF. + + io_xml->add( iv_name = 'CUS2' + ig_data = ls_customizing_attribute ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_cus1 IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_customizing_activity = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA ls_header TYPE ty_customzing_activity-activity_header. + + CALL FUNCTION 'S_CUS_ACTIVITY_READ' + EXPORTING + activity = mv_customizing_activity + IMPORTING + activity_header = ls_header. + + rv_user = ls_header-luser. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: ls_message TYPE hier_mess. + + CALL FUNCTION 'S_CUS_ACTIVITY_DELETE' + EXPORTING + activity = mv_customizing_activity + IMPORTING + message = ls_message. + + IF ls_message-msgty <> 'S'. + zcx_abapgit_exception=>raise( |error from delete CUS1 { mv_customizing_activity } S_CUS_ACTIVITY_DELETE| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_customzing_activity TYPE ty_customzing_activity, + ls_message TYPE hier_mess. + + io_xml->read( + EXPORTING + iv_name = 'CUS1' + CHANGING + cg_data = ls_customzing_activity ). + + CALL FUNCTION 'S_CUS_ACTIVITY_SAVE' + EXPORTING + activity = ls_customzing_activity-activity_header-act_id + activity_type = ls_customzing_activity-activity_header-act_type + tcode = ls_customzing_activity-activity_header-tcode + customer_exit = ls_customzing_activity-activity_customer_exit-exit_name + customer_exit_enhancement = ls_customzing_activity-activity_customer_exit-enhancement + customer_exit_implementation = ls_customzing_activity-activity_customer_exit-impl_name + IMPORTING + message = ls_message + TABLES + activity_title = ls_customzing_activity-activity_title + objects = ls_customzing_activity-objects + objects_texts = ls_customzing_activity-objects_title. + + IF ls_message-msgty <> 'S'. + zcx_abapgit_exception=>raise( |error from deserialize CUS1 { mv_customizing_activity } S_CUS_ACTIVITY_SAVE| ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL FUNCTION 'S_CUS_ACTIVITY_EXIST' + EXPORTING + activity = mv_customizing_activity + EXCEPTIONS + activity_exists_not = 1 + OTHERS = 2. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = abap_true. + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + DATA: lt_bdc_data TYPE STANDARD TABLE OF bdcdata. + FIELD-SYMBOLS: TYPE bdcdata. + + APPEND INITIAL LINE TO lt_bdc_data ASSIGNING . + -program = 'SAPLS_CUS_ACTIVITY'. + -dynpro = '0200'. + -dynbegin = 'X'. + + APPEND INITIAL LINE TO lt_bdc_data ASSIGNING . + -fnam = 'CUS_ACTH-ACT_ID'. + -fval = mv_customizing_activity. + + APPEND INITIAL LINE TO lt_bdc_data ASSIGNING . + -fnam = 'BDC_OKCODE'. + -fval = '=ACT_DISP'. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'S_CUS_ACTIVITY' + it_bdcdata = lt_bdc_data ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_customzing_activity TYPE ty_customzing_activity. + + CALL FUNCTION 'S_CUS_ACTIVITY_READ' + EXPORTING + activity = mv_customizing_activity + IMPORTING + activity_header = ls_customzing_activity-activity_header + activity_customer_exit = ls_customzing_activity-activity_customer_exit + TABLES + activity_title = ls_customzing_activity-activity_title + objects = ls_customzing_activity-objects + objects_title = ls_customzing_activity-objects_title. + + CLEAR: ls_customzing_activity-activity_header-fdatetime, + ls_customzing_activity-activity_header-fuser, + ls_customzing_activity-activity_header-ldatetime, + ls_customzing_activity-activity_header-luser. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + DELETE ls_customzing_activity-activity_title WHERE spras <> mv_language. + ENDIF. + + SORT ls_customzing_activity-activity_title. + SORT ls_customzing_activity-objects. + SORT ls_customzing_activity-objects_title. + + io_xml->add( iv_name = 'CUS1' + ig_data = ls_customzing_activity ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_cus0 IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_img_activity = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA ls_header TYPE ty_img_activity-header. + + CALL FUNCTION 'S_CUS_IMG_ACTIVITY_READ' + EXPORTING + img_activity = mv_img_activity + IMPORTING + img_activity_header = ls_header. + + rv_user = ls_header-luser. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: ls_message TYPE hier_mess. + + CALL FUNCTION 'S_CUS_IMG_ACTIVITY_DELETE' + EXPORTING + img_activity = mv_img_activity + IMPORTING + message = ls_message. + + IF ls_message-msgty <> 'S'. + zcx_abapgit_exception=>raise( |error from delete CUS0 { mv_img_activity } S_CUS_IMG_ACTIVITY_DELETE| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_img_activity TYPE ty_img_activity, + ls_text LIKE LINE OF ls_img_activity-texts. + + io_xml->read( + EXPORTING + iv_name = 'CUS0' + CHANGING + cg_data = ls_img_activity ). + + READ TABLE ls_img_activity-texts INTO ls_text + WITH KEY spras = mv_language. + + CALL FUNCTION 'S_CUS_IMG_ACTIVITY_SAVE' + EXPORTING + img_activity = ls_img_activity-header-activity + i_docu = ls_img_activity-header-docu_id + i_attributes = ls_img_activity-header-attributes + i_activity = ls_img_activity-header-c_activity + i_description = ls_text + i_tcode = ls_img_activity-header-tcode. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: ls_message TYPE hier_mess. + + CALL FUNCTION 'S_CUS_IMG_ACTIVITY_EXISTS' + EXPORTING + img_activity = mv_img_activity + IMPORTING + message = ls_message. + + rv_bool = boolc( ls_message IS INITIAL ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = abap_true. + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + DATA: lv_img_activity TYPE cus_img_ac. + + lv_img_activity = mv_img_activity. + + CALL FUNCTION 'S_CUS_IMG_ACTIVITY_MAINTAIN' + EXPORTING + i_display = abap_true + CHANGING + img_activity = lv_img_activity. + + rv_exit = abap_true. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_img_activity TYPE ty_img_activity. + + CALL FUNCTION 'S_CUS_IMG_ACTIVITY_READ' + EXPORTING + img_activity = mv_img_activity + IMPORTING + img_activity_header = ls_img_activity-header + TABLES + img_activity_texts = ls_img_activity-texts. + + CLEAR: ls_img_activity-header-fuser, + ls_img_activity-header-fdate, + ls_img_activity-header-ftime, + ls_img_activity-header-luser, + ls_img_activity-header-ldate, + ls_img_activity-header-ltime. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + DELETE ls_img_activity-texts WHERE spras <> mv_language. + ENDIF. + + SORT ls_img_activity-texts. + + io_xml->add( iv_name = 'CUS0' + ig_data = ls_img_activity ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_cmpt IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CALL METHOD ('CL_CMP_TEMPLATE')=>('S_GET_DB_ACCESS') + RECEIVING + r_ref_db_access = mo_cmp_db. + + CATCH cx_root. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + mv_name = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_cmp_template TYPE REF TO object. + + CALL METHOD ('CL_CMP_TEMPLATE')=>('S_CREATE_FROM_DB') + EXPORTING + i_name = mv_name + i_version = 'A' + RECEIVING + r_ref_template = lo_cmp_template. + + CALL METHOD lo_cmp_template->('IF_CMP_TEMPLATE_EDIT~GET_CHANGE_USER') + RECEIVING + r_user = rv_user. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_deleted TYPE abap_bool. + + CALL METHOD mo_cmp_db->('IF_CMP_TEMPLATE_DB~DELETE_TEMPLATE') + EXPORTING + i_name = mv_name + i_version = 'A' + i_flg_header = abap_true + i_flg_lines = abap_true + RECEIVING + r_flg_deleted = lv_deleted. + + IF lv_deleted = abap_false. + zcx_abapgit_exception=>raise( |Error deleting CMPT { ms_item-obj_name }| ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lr_template TYPE REF TO data. + FIELD-SYMBOLS: TYPE any, + TYPE any, + TYPE any. + + CREATE DATA lr_template TYPE ('IF_CMP_TEMPLATE_DB=>TYP_TEMPLATE'). + ASSIGN lr_template->* TO . + + io_xml->read( + EXPORTING + iv_name = 'CMPT' + CHANGING + cg_data = ). + + ASSIGN COMPONENT 'STR_HEADER' OF STRUCTURE TO . + IF sy-subrc = 0. + ASSIGN COMPONENT 'NAME' OF STRUCTURE TO . + IF sy-subrc = 0. + = ms_item-obj_name. + ENDIF. + ASSIGN COMPONENT 'VERSION' OF STRUCTURE TO . + IF sy-subrc = 0. + = 'A'. + ENDIF. + ENDIF. + + CALL METHOD mo_cmp_db->('IF_CMP_TEMPLATE_DB~SAVE_TEMPLATE') + EXPORTING + i_template_db = + i_flg_header = abap_true + i_flg_lines = abap_true. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + CALL METHOD ('CL_CMP_TEMPLATE')=>('S_TEMPLATE_EXISTS') + EXPORTING + i_name = mv_name + i_version = 'A' + RECEIVING + r_flg_exists = rv_bool. + IF rv_bool = abap_false. + CALL METHOD ('CL_CMP_TEMPLATE')=>('S_TEMPLATE_EXISTS') + EXPORTING + i_name = mv_name + i_version = 'I' + RECEIVING + r_flg_exists = rv_bool. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lr_template TYPE REF TO data. + FIELD-SYMBOLS: TYPE any, + TYPE any, + TYPE any. + + CREATE DATA lr_template TYPE ('IF_CMP_TEMPLATE_DB=>TYP_TEMPLATE'). + ASSIGN lr_template->* TO . + + CALL METHOD mo_cmp_db->('IF_CMP_TEMPLATE_DB~READ_TEMPLATE') + EXPORTING + i_name = |{ ms_item-obj_name }| + i_version = 'A' + RECEIVING + r_template = . + + ASSIGN COMPONENT 'STR_HEADER' OF STRUCTURE TO . + IF sy-subrc = 0. + ASSIGN COMPONENT 'NAME' OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'VERSION' OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'CHANGED_ON' OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ASSIGN COMPONENT 'CHANGED_TS' OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ENDIF. + + io_xml->add( iv_name = 'CMPT' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_cmod IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE anam FROM modattr INTO rv_user WHERE name = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA lv_name TYPE modact-name. + + lv_name = ms_item-obj_name. + + CALL FUNCTION 'MOD_KUN_ACTIVATE' + EXPORTING + activate = abap_false + deactivate = abap_true + modname = lv_name + EXCEPTIONS + call_error = 1 + generate_error = 2 + modattr_status = 3 + mod_active = 4 + mod_enqueued = 5 + not_activated = 6 + no_modification = 7 + permission_failure = 8 + OTHERS = 9. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'MOD_KUN_DELETE' + EXPORTING + modname = lv_name + screen = abap_false + EXCEPTIONS + attr_enqueued = 1 + mod_active = 2 + mod_enqueued = 3 + text_enqueued = 4 + permission_failure = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_name TYPE modact-name, + lt_modact TYPE TABLE OF modact, + lt_modtext TYPE TABLE OF modtext, + lt_modattr TYPE TABLE OF modattr. + + lv_name = ms_item-obj_name. + + DELETE FROM modact WHERE name = lv_name. + DELETE FROM modtext WHERE name = lv_name. + DELETE FROM modattr WHERE name = lv_name. + + io_xml->read( EXPORTING iv_name = 'MODACT' + CHANGING cg_data = lt_modact ). + + io_xml->read( EXPORTING iv_name = 'MODTEXT' + CHANGING cg_data = lt_modtext ). + + io_xml->read( EXPORTING iv_name = 'MODATTR' + CHANGING cg_data = lt_modattr ). + + INSERT modact FROM TABLE lt_modact. + INSERT modtext FROM TABLE lt_modtext. + INSERT modattr FROM TABLE lt_modattr. + + tadir_insert( iv_package ). + + CALL FUNCTION 'MOD_KUN_ACTIVATE' + EXPORTING + activate = abap_true + deactivate = abap_false + modname = lv_name + EXCEPTIONS + call_error = 1 + generate_error = 2 + modattr_status = 3 + mod_active = 4 + mod_enqueued = 5 + not_activated = 6 + no_modification = 7 + permission_failure = 8 + OTHERS = 9. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_name TYPE modact-name. + + SELECT SINGLE name FROM modact INTO lv_name WHERE name = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lt_modact TYPE TABLE OF modact, + lt_modtext TYPE TABLE OF modtext, + lt_modattr TYPE TABLE OF modattr. + + FIELD-SYMBOLS: TYPE modattr. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + SELECT * FROM modact INTO TABLE lt_modact WHERE name = ms_item-obj_name + ORDER BY PRIMARY KEY. + IF sy-subrc = 0. + io_xml->add( iv_name = 'MODACT' + ig_data = lt_modact ). + ENDIF. + + SELECT * FROM modtext INTO TABLE lt_modtext WHERE name = ms_item-obj_name AND sprsl = mv_language + ORDER BY PRIMARY KEY. + IF sy-subrc = 0. + io_xml->add( iv_name = 'MODTEXT' + ig_data = lt_modtext ). + ENDIF. + + SELECT * FROM modattr INTO TABLE lt_modattr WHERE name = ms_item-obj_name + ORDER BY PRIMARY KEY. + IF sy-subrc = 0. + LOOP AT lt_modattr ASSIGNING . + CLEAR: + -cnam, -cdat, + -unam, -udat, + -anam, -adat, + -fnam, -fdat. + ENDLOOP. + + io_xml->add( iv_name = 'MODATTR' + ig_data = lt_modattr ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_clas IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mi_object_oriented_object_fct = zcl_abapgit_oo_factory=>get_by_type( ms_item-obj_type ). + + mv_classpool_name = cl_oo_classname_service=>get_classpool_name( |{ is_item-obj_name }| ). + + ENDMETHOD. + METHOD deserialize_abap. + + DATA: ls_vseoclass TYPE vseoclass, + lt_source TYPE seop_source_string, + lt_local_definitions TYPE seop_source_string, + lt_local_implementations TYPE seop_source_string, + lt_local_macros TYPE seop_source_string, + lt_test_classes TYPE seop_source_string, + ls_class_key TYPE seoclskey, + lt_attributes TYPE zif_abapgit_oo_object_fnc=>ty_obj_attribute_tt. + lt_source = mo_files->read_abap( ). + + lt_local_definitions = mo_files->read_abap( + iv_extra = zif_abapgit_oo_object_fnc=>c_parts-locals_def + iv_error = abap_false ). + + lt_local_implementations = mo_files->read_abap( + iv_extra = zif_abapgit_oo_object_fnc=>c_parts-locals_imp + iv_error = abap_false ). + + lt_local_macros = mo_files->read_abap( + iv_extra = zif_abapgit_oo_object_fnc=>c_parts-macros + iv_error = abap_false ). + + lt_test_classes = mo_files->read_abap( + iv_extra = zif_abapgit_oo_object_fnc=>c_parts-testclasses + iv_error = abap_false ). + + ls_class_key-clsname = ms_item-obj_name. + + ii_xml->read( EXPORTING iv_name = 'VSEOCLASS' + CHANGING cg_data = ls_vseoclass ). + + set_abap_language_version( CHANGING cv_abap_language_version = ls_vseoclass-unicode ). + + ii_xml->read( EXPORTING iv_name = 'ATTRIBUTES' + CHANGING cg_data = lt_attributes ). + + " Remove code for test classes if they have been deleted + IF ls_vseoclass-with_unit_tests = abap_false. + CLEAR lt_test_classes. + ENDIF. + + mi_object_oriented_object_fct->create( + EXPORTING + iv_check = abap_true + iv_package = iv_package + it_attributes = lt_attributes + CHANGING + cg_properties = ls_vseoclass ). + + mi_object_oriented_object_fct->generate_locals( + is_key = ls_class_key + iv_package = iv_package + iv_version = ls_vseoclass-unicode + it_local_definitions = lt_local_definitions + it_local_implementations = lt_local_implementations + it_local_macros = lt_local_macros + it_local_test_classes = lt_test_classes ). + + repo_apack_replacement( CHANGING ct_source = lt_source ). + + mi_object_oriented_object_fct->deserialize_source( + is_key = ls_class_key + iv_package = iv_package + iv_version = ls_vseoclass-unicode + it_source = lt_source ). + + ENDMETHOD. + METHOD deserialize_descr. + + DATA: + ls_class_key TYPE seoclskey, + lt_descriptions_class TYPE zif_abapgit_oo_object_fnc=>ty_seoclasstx_tt, + lt_descriptions_compo TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, + lt_descriptions_subco TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt. + + ls_class_key-clsname = ms_item-obj_name. + + ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS_CLASS' + CHANGING cg_data = lt_descriptions_class ). + + mi_object_oriented_object_fct->update_descriptions_class( + is_key = ls_class_key + iv_language = mv_language + it_descriptions = lt_descriptions_class ). + + ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS' + CHANGING cg_data = lt_descriptions_compo ). + + mi_object_oriented_object_fct->update_descriptions_compo( + is_key = ls_class_key + it_descriptions = lt_descriptions_compo ). + + ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS_SUB' + CHANGING cg_data = lt_descriptions_subco ). + + mi_object_oriented_object_fct->update_descriptions_subco( + is_key = ls_class_key + it_descriptions = lt_descriptions_subco ). + + ENDMETHOD. + METHOD deserialize_docu. + + DATA: lt_lines TYPE tlinetab, + lv_object TYPE dokhl-object, + lt_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_lines, + ls_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_line. + + ii_xml->read( EXPORTING iv_name = 'LINES' + CHANGING cg_data = lt_lines ). + + lv_object = ms_item-obj_name. + + IF lines( lt_lines ) = 0. + mi_object_oriented_object_fct->delete_documentation( + iv_id = c_longtext_id-class + iv_object_name = lv_object + iv_language = mv_language ). + ELSE. + mi_object_oriented_object_fct->create_documentation( + it_lines = lt_lines + iv_id = c_longtext_id-class + iv_object_name = lv_object + iv_language = mv_language ). + + ii_xml->read( EXPORTING iv_name = 'I18N_LINES' + CHANGING cg_data = lt_i18n_lines ). + + LOOP AT lt_i18n_lines INTO ls_i18n_lines. + mi_object_oriented_object_fct->create_documentation( + it_lines = ls_i18n_lines-lines + iv_id = c_longtext_id-class + iv_object_name = lv_object + iv_language = ls_i18n_lines-language + iv_no_masterlang = abap_true ). + ENDLOOP. + ENDIF. + + deserialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-attributes + iv_longtext_id = c_longtext_id-attributes ). + + deserialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-methods + iv_longtext_id = c_longtext_id-methods ). + + deserialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-events + iv_longtext_id = c_longtext_id-events ). + + deserialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-types + iv_longtext_id = c_longtext_id-types ). + + ENDMETHOD. + METHOD deserialize_exceptions. + + DATA: ls_vseoclass TYPE vseoclass. + + ii_xml->read( EXPORTING iv_name = 'VSEOCLASS' + CHANGING cg_data = ls_vseoclass ). + + " For exceptions that are sub-class of another exception, we need to set the category explicitly (#6490) + IF ls_vseoclass-category = '40'. + UPDATE seoclassdf SET category = '40' WHERE clsname = ls_vseoclass-clsname. + ENDIF. + + ENDMETHOD. + METHOD deserialize_pre_ddic. + + DATA: ls_vseoclass TYPE vseoclass. + + ii_xml->read( EXPORTING iv_name = 'VSEOCLASS' + CHANGING cg_data = ls_vseoclass ). + + set_abap_language_version( CHANGING cv_abap_language_version = ls_vseoclass-unicode ). + + IF ls_vseoclass-category = '40'. + " In lower releases, creating exception classes raise a popup asking for package + " To avoid this, we set the default package here + set_default_package( iv_package ). + ENDIF. + + mi_object_oriented_object_fct->create( + EXPORTING + iv_check = abap_false + iv_package = iv_package + CHANGING + cg_properties = ls_vseoclass ). + + ENDMETHOD. + METHOD deserialize_sotr. + "OTR stands for Online Text Repository + mi_object_oriented_object_fct->create_sotr( + iv_object_name = ms_item-obj_name + iv_package = iv_package + ii_xml = ii_xml ). + ENDMETHOD. + METHOD deserialize_tpool. + + DATA: lv_clsname TYPE seoclsname, + lt_tpool_ext TYPE zif_abapgit_lang_definitions=>ty_tpool_tt, + lt_tpool TYPE textpool_table. + + ii_xml->read( EXPORTING iv_name = 'TPOOL' + CHANGING cg_data = lt_tpool_ext ). + lt_tpool = read_tpool( lt_tpool_ext ). + + IF lines( lt_tpool ) = 0. + RETURN. + ENDIF. + + lv_clsname = ms_item-obj_name. + + mi_object_oriented_object_fct->insert_text_pool( + iv_class_name = lv_clsname + it_text_pool = lt_tpool + iv_language = mv_language ). + + ENDMETHOD. + METHOD deserialize_tpool_i18n. + + DATA: lv_clsname TYPE seoclsname, + lt_tpool TYPE textpool_table, + lt_i18n_tpool TYPE zif_abapgit_lang_definitions=>ty_i18n_tpools, + ls_i18n_tpool TYPE zif_abapgit_lang_definitions=>ty_i18n_tpool. + + lv_clsname = ms_item-obj_name. + + ii_xml->read( EXPORTING iv_name = 'I18N_TPOOL' + CHANGING cg_data = lt_i18n_tpool ). + + mo_i18n_params->trim_saplang_keyed_table( + EXPORTING + iv_lang_field_name = 'LANGUAGE' + CHANGING + ct_tab = lt_i18n_tpool ). + + LOOP AT lt_i18n_tpool INTO ls_i18n_tpool. + lt_tpool = read_tpool( ls_i18n_tpool-textpool ). + mi_object_oriented_object_fct->insert_text_pool( + iv_class_name = lv_clsname + it_text_pool = lt_tpool + iv_language = ls_i18n_tpool-language + iv_state = 'A' ). + ENDLOOP. + + ENDMETHOD. + METHOD interface_replacement. + + DATA lv_tabix TYPE sy-tabix. + + FIELD-SYMBOLS LIKE LINE OF ct_source. + + FIND REGEX '^\s*INTERFACES(:| )\s*' && iv_from_interface && '\s*.' IN TABLE ct_source MATCH LINE lv_tabix. + IF sy-subrc = 0. + READ TABLE ct_source ASSIGNING INDEX lv_tabix. + ASSERT sy-subrc = 0. + + REPLACE FIRST OCCURRENCE OF iv_from_interface IN + WITH iv_to_interface IGNORING CASE. + + REPLACE ALL OCCURRENCES OF iv_from_interface && '~descriptor' IN TABLE ct_source + WITH iv_to_interface && '~descriptor' IGNORING CASE. + REPLACE ALL OCCURRENCES OF iv_from_interface && '=>' IN TABLE ct_source + WITH iv_to_interface && '=>' IGNORING CASE. + REPLACE ALL OCCURRENCES OF iv_from_interface && '->' IN TABLE ct_source + WITH iv_to_interface && '->' IGNORING CASE. + ENDIF. + + ENDMETHOD. + METHOD is_class_locked. + + DATA: lv_argument TYPE seqg3-garg. + + lv_argument = ms_item-obj_name. + OVERLAY lv_argument WITH '=============================='. + lv_argument = lv_argument && '*'. + + rv_is_class_locked = exists_a_lock_entry_for( iv_lock_object = 'ESEOCLASS' + iv_argument = lv_argument ). + + ENDMETHOD. + METHOD repo_apack_replacement. + + DATA lv_apack TYPE seoclsname. + + " Check if SAP-version of APACK manifest exists + SELECT SINGLE clsname INTO lv_apack + FROM seoclass + WHERE clsname = zif_abapgit_apack_definitions=>c_apack_interface_sap. + IF sy-subrc = 0. + RETURN. + ENDIF. + + " If not, replace with abapGit version + interface_replacement( + EXPORTING + iv_from_interface = to_lower( zif_abapgit_apack_definitions=>c_apack_interface_sap ) + iv_to_interface = to_lower( zif_abapgit_apack_definitions=>c_apack_interface_cust ) + CHANGING + ct_source = ct_source ). + + ENDMETHOD. + METHOD serialize_attr. + + DATA: lt_attributes TYPE zif_abapgit_oo_object_fnc=>ty_obj_attribute_tt. + + lt_attributes = mi_object_oriented_object_fct->read_attributes( iv_clsname ). + IF lines( lt_attributes ) = 0. + RETURN. + ENDIF. + + ii_xml->add( iv_name = 'ATTRIBUTES' + ig_data = lt_attributes ). + + ENDMETHOD. + METHOD serialize_descr_class. + + DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seoclasstx_tt, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + " Main language is already in VSEOCLASS so we serialize only translations + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + lt_descriptions = mi_object_oriented_object_fct->read_descriptions_class( + iv_object_name = iv_clsname + iv_language = mv_language ). + + IF lines( lt_descriptions ) = 0. + RETURN. + ENDIF. + " Remove technical languages + lt_language_filter = mo_i18n_params->build_language_filter( ). + DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. + + ii_xml->add( iv_name = 'DESCRIPTIONS_CLASS' + ig_data = lt_descriptions ). + + ENDMETHOD. + METHOD serialize_descr_compo. + + DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, + lv_language TYPE spras, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + lv_language = mv_language. + ENDIF. + + lt_descriptions = mi_object_oriented_object_fct->read_descriptions_compo( + iv_object_name = iv_clsname + iv_language = lv_language ). + + IF lines( lt_descriptions ) = 0. + RETURN. + ENDIF. + " Remove technical languages + lt_language_filter = mo_i18n_params->build_language_filter( ). + DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. + + ii_xml->add( iv_name = 'DESCRIPTIONS' + ig_data = lt_descriptions ). + + ENDMETHOD. + METHOD serialize_descr_subco. + + DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt, + lv_language TYPE spras, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + lv_language = mv_language. + ENDIF. + + lt_descriptions = mi_object_oriented_object_fct->read_descriptions_subco( + iv_object_name = iv_clsname + iv_language = lv_language ). + + IF lines( lt_descriptions ) = 0. + RETURN. + ENDIF. + " Remove technical languages + lt_language_filter = mo_i18n_params->build_language_filter( ). + DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. + + ii_xml->add( iv_name = 'DESCRIPTIONS_SUB' + ig_data = lt_descriptions ). + + ENDMETHOD. + METHOD serialize_docu. + + DATA: lt_lines TYPE tlinetab, + lv_object TYPE dokhl-object, + lv_langu TYPE sy-langu, + lt_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_lines, + ls_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_line. + + lv_object = iv_clsname. + + lt_lines = mi_object_oriented_object_fct->read_documentation( + iv_id = c_longtext_id-class + iv_object_name = lv_object + iv_language = mv_language ). + IF lines( lt_lines ) > 0. + ii_xml->add( iv_name = 'LINES' + ig_data = lt_lines ). + ENDIF. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + LOOP AT it_langu_additional INTO lv_langu. + + lt_lines = mi_object_oriented_object_fct->read_documentation( + iv_id = c_longtext_id-class + iv_object_name = lv_object + iv_language = lv_langu ). + + IF lines( lt_lines ) > 0. + CLEAR ls_i18n_lines. + ls_i18n_lines-language = lv_langu. + ls_i18n_lines-lines = lt_lines. + INSERT ls_i18n_lines INTO TABLE lt_i18n_lines. + ENDIF. + + ENDLOOP. + + IF lines( lt_i18n_lines ) > 0. + ii_xml->add( iv_name = 'I18N_LINES' + ig_data = lt_i18n_lines ). + ENDIF. + + serialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-attributes + iv_longtext_id = c_longtext_id-attributes ). + + serialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-methods + iv_longtext_id = c_longtext_id-methods ). + + serialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-events + iv_longtext_id = c_longtext_id-events ). + + serialize_longtexts( + ii_xml = ii_xml + iv_longtext_name = c_longtext_name-types + iv_longtext_id = c_longtext_id-types ). + + ENDMETHOD. + METHOD serialize_sotr. + mi_object_oriented_object_fct->read_sotr( + iv_object_name = ms_item-obj_name + io_i18n_params = mo_i18n_params + ii_xml = ii_xml ). + ENDMETHOD. + METHOD serialize_tpool. + + DATA lt_tpool TYPE textpool_table. + + lt_tpool = mi_object_oriented_object_fct->read_text_pool( + iv_class_name = iv_clsname + iv_language = mv_language ). + ii_xml->add( iv_name = 'TPOOL' + ig_data = add_tpool( lt_tpool ) ). + + rt_tpool = lt_tpool. + + ENDMETHOD. + METHOD serialize_tpool_i18n. + + DATA: lt_tpool TYPE textpool_table, + lv_index TYPE i, + lv_langu TYPE sy-langu, + lt_i18n_tpool TYPE zif_abapgit_lang_definitions=>ty_i18n_tpools, + ls_i18n_tpool TYPE zif_abapgit_lang_definitions=>ty_i18n_tpool. + + FIELD-SYMBOLS LIKE LINE OF it_tpool_main. + + DATA lt_tpool_main LIKE SORTED TABLE OF WITH UNIQUE KEY id key. + + IF mo_i18n_params->ms_params-main_language_only = abap_true OR lines( it_tpool_main ) = 0. + RETURN. + ENDIF. + + " Copy single records to be able to catch duplicate key error + LOOP AT it_tpool_main ASSIGNING . + INSERT INTO TABLE lt_tpool_main. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Inconsistent textpool in { ms_item-obj_type } { ms_item-obj_name }| ). + ENDIF. + ENDLOOP. + + LOOP AT it_langu_additional INTO lv_langu. + + lt_tpool = mi_object_oriented_object_fct->read_text_pool( + iv_class_name = iv_clsname + iv_language = lv_langu ). + + LOOP AT lt_tpool ASSIGNING . + lv_index = sy-tabix. + READ TABLE lt_tpool_main WITH KEY id = -id key = -key + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + DELETE lt_tpool INDEX lv_index. + ENDIF. + ENDLOOP. + + IF lines( lt_tpool ) > 0. + CLEAR ls_i18n_tpool. + ls_i18n_tpool-language = lv_langu. + ls_i18n_tpool-textpool = add_tpool( lt_tpool ). + INSERT ls_i18n_tpool INTO TABLE lt_i18n_tpool. + ENDIF. + + ENDLOOP. + + IF lines( lt_i18n_tpool ) > 0. + ii_xml->add( iv_name = 'I18N_TPOOL' + ig_data = lt_i18n_tpool ). + ENDIF. + + ENDMETHOD. + METHOD serialize_xml. + + DATA: ls_vseoclass TYPE vseoclass, + lt_tpool TYPE textpool_table, + ls_clskey TYPE seoclskey, + lt_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + ls_clskey-clsname = ms_item-obj_name. + + "If class was deserialized with a previous version of abapGit and current language was different + "from main language at this time, this call would return SY-LANGU as main language. To fix + "these objects, set SY-LANGU to main language temporarily. + zcl_abapgit_language=>set_current_language( mv_language ). + + TRY. + ls_vseoclass = mi_object_oriented_object_fct->get_class_properties( ls_clskey ). + + clear_abap_language_version( CHANGING cv_abap_language_version = ls_vseoclass-unicode ). + + CLEANUP. + zcl_abapgit_language=>restore_login_language( ). + + ENDTRY. + + zcl_abapgit_language=>restore_login_language( ). + + IF mv_skip_testclass = abap_true. + CLEAR ls_vseoclass-with_unit_tests. + ENDIF. + + " Table d010tinf stores info. on languages in which program is maintained + " Select all active translations of program texts + " Skip main language - it was already serialized + lt_language_filter = mo_i18n_params->build_language_filter( ). + + SELECT DISTINCT language + INTO TABLE lt_langu_additional + FROM d010tinf + WHERE r3state = 'A' + AND prog = mv_classpool_name + AND language IN lt_language_filter + AND language <> mv_language + ORDER BY language. + + ii_xml->add( iv_name = 'VSEOCLASS' + ig_data = ls_vseoclass ). + + lt_tpool = serialize_tpool( + ii_xml = ii_xml + iv_clsname = ls_clskey-clsname ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + serialize_tpool_i18n( + ii_xml = ii_xml + it_langu_additional = lt_langu_additional + it_tpool_main = lt_tpool + iv_clsname = ls_clskey-clsname ). + ENDIF. + + IF ls_vseoclass-category = seoc_category_exception. + serialize_sotr( ii_xml ). + ENDIF. + + SELECT DISTINCT langu + INTO TABLE lt_langu_additional + FROM dokhl + WHERE id = 'CL' + AND object = ls_clskey-clsname + AND langu IN lt_language_filter + AND langu <> mv_language + ORDER BY langu. + + serialize_docu( ii_xml = ii_xml + iv_clsname = ls_clskey-clsname + it_langu_additional = lt_langu_additional ). + + serialize_descr_class( ii_xml = ii_xml + iv_clsname = ls_clskey-clsname ). + + serialize_descr_compo( ii_xml = ii_xml + iv_clsname = ls_clskey-clsname ). + + serialize_descr_subco( ii_xml = ii_xml + iv_clsname = ls_clskey-clsname ). + + serialize_attr( ii_xml = ii_xml + iv_clsname = ls_clskey-clsname ). + + ENDMETHOD. + METHOD source_apack_replacement. + + DATA lv_clsname TYPE seoclsname. + + " Check if abapGit version of APACK manifest is used + SELECT SINGLE clsname INTO lv_clsname + FROM seometarel + WHERE clsname = ms_item-obj_name + AND refclsname = zif_abapgit_apack_definitions=>c_apack_interface_cust + AND version = '1'. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + " If yes, replace with SAP-version + interface_replacement( + EXPORTING + iv_from_interface = to_lower( zif_abapgit_apack_definitions=>c_apack_interface_cust ) + iv_to_interface = to_lower( zif_abapgit_apack_definitions=>c_apack_interface_sap ) + CHANGING + ct_source = ct_source ). + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + TYPES: BEGIN OF ty_reposrc, + unam TYPE reposrc-unam, + udat TYPE reposrc-udat, + utime TYPE reposrc-utime, + END OF ty_reposrc. + + DATA: lt_reposrc TYPE STANDARD TABLE OF ty_reposrc, + ls_reposrc LIKE LINE OF lt_reposrc, + lv_include TYPE syrepid, + lt_includes TYPE STANDARD TABLE OF syrepid. + + CASE iv_extra. + WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_def. + lv_include = cl_oo_classname_service=>get_ccdef_name( |{ ms_item-obj_name }| ). + INSERT lv_include INTO TABLE lt_includes. + WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_imp. + lv_include = cl_oo_classname_service=>get_ccimp_name( |{ ms_item-obj_name }| ). + INSERT lv_include INTO TABLE lt_includes. + WHEN zif_abapgit_oo_object_fnc=>c_parts-macros. + lv_include = cl_oo_classname_service=>get_ccmac_name( |{ ms_item-obj_name }| ). + INSERT lv_include INTO TABLE lt_includes. + WHEN zif_abapgit_oo_object_fnc=>c_parts-testclasses. + lv_include = cl_oo_classname_service=>get_ccau_name( |{ ms_item-obj_name }| ). + INSERT lv_include INTO TABLE lt_includes. + WHEN OTHERS. + lt_includes = mi_object_oriented_object_fct->get_includes( ms_item-obj_name ). + ENDCASE. + + ASSERT lines( lt_includes ) > 0. + + SELECT unam udat utime FROM reposrc + INTO TABLE lt_reposrc + FOR ALL ENTRIES IN lt_includes + WHERE progname = lt_includes-table_line + AND r3state = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ELSE. + SORT lt_reposrc BY udat DESCENDING utime DESCENDING. + READ TABLE lt_reposrc INDEX 1 INTO ls_reposrc. + ASSERT sy-subrc = 0. + rv_user = ls_reposrc-unam. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + DATA: ls_clskey TYPE seoclskey. + ls_clskey-clsname = ms_item-obj_name. + + corr_insert( iv_package ). + + mi_object_oriented_object_fct->delete( ls_clskey ). + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + IF iv_step = zif_abapgit_object=>gc_step_id-abap. + + deserialize_abap( ii_xml = io_xml + iv_package = iv_package ). + + deserialize_descr( io_xml ). + + deserialize_tpool( io_xml ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + deserialize_tpool_i18n( io_xml ). + ENDIF. + + deserialize_sotr( ii_xml = io_xml + iv_package = iv_package ). + + deserialize_docu( io_xml ). + + mi_object_oriented_object_fct->add_to_activation_list( ms_item ). + + ELSEIF iv_step = zif_abapgit_object=>gc_step_id-early. + + " If class does not exist, create it + " so DDIC that depends on it does not fail activation + IF zif_abapgit_object~exists( ) = abap_false. + deserialize_pre_ddic( + ii_xml = io_xml + iv_package = iv_package ). + ELSE. + corr_insert( iv_package ). + ENDIF. + + ELSEIF iv_step = zif_abapgit_object=>gc_step_id-late. + + deserialize_exceptions( io_xml ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA ls_class_key TYPE seoclskey. + + ls_class_key-clsname = ms_item-obj_name. + + rv_bool = mi_object_oriented_object_fct->exists( ls_class_key-clsname ). + + " Skip classes generated by DDLS (SADL) + IF rv_bool = abap_true AND + mi_object_oriented_object_fct->read_superclass( ls_class_key-clsname ) = 'CL_SADL_GTK_EXPOSURE_MPC'. + rv_bool = abap_false. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-early TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + IF is_class_locked( ) = abap_true OR is_text_locked( mv_classpool_name ) = abap_true. + rv_is_locked = abap_true. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + + ls_item-obj_type = 'PROG'. + + CASE iv_extra. + WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_def. + ls_item-obj_name = cl_oo_classname_service=>get_ccdef_name( |{ ms_item-obj_name }| ). + WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_imp. + ls_item-obj_name = cl_oo_classname_service=>get_ccimp_name( |{ ms_item-obj_name }| ). + WHEN zif_abapgit_oo_object_fnc=>c_parts-macros. + ls_item-obj_name = cl_oo_classname_service=>get_ccmac_name( |{ ms_item-obj_name }| ). + WHEN zif_abapgit_oo_object_fnc=>c_parts-testclasses. + ls_item-obj_name = cl_oo_classname_service=>get_ccau_name( |{ ms_item-obj_name }| ). + ENDCASE. + + IF ls_item-obj_name IS NOT INITIAL. + rv_exit = zcl_abapgit_objects_factory=>get_gui_jumper( )->jump( ls_item ). + ENDIF. + + " Otherwise covered by ZCL_ABAPGIT_OBJECTS=>JUMP + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lt_source TYPE seop_source_string, + ls_class_key TYPE seoclskey. + + ls_class_key-clsname = ms_item-obj_name. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + version = seoc_version_active + force = abap_true. + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + version = seoc_version_inactive + force = abap_true. + + lt_source = mi_object_oriented_object_fct->serialize_abap( ls_class_key ). + + source_apack_replacement( CHANGING ct_source = lt_source ). + + mo_files->add_abap( lt_source ). + + lt_source = mi_object_oriented_object_fct->serialize_abap( + is_class_key = ls_class_key + iv_type = seop_ext_class_locals_def ). + IF lines( lt_source ) > 0. + mo_files->add_abap( + iv_extra = zif_abapgit_oo_object_fnc=>c_parts-locals_def + it_abap = lt_source ). + ENDIF. + + lt_source = mi_object_oriented_object_fct->serialize_abap( + is_class_key = ls_class_key + iv_type = seop_ext_class_locals_imp ). + IF lines( lt_source ) > 0. + mo_files->add_abap( + iv_extra = zif_abapgit_oo_object_fnc=>c_parts-locals_imp + it_abap = lt_source ). + ENDIF. + + lt_source = mi_object_oriented_object_fct->serialize_abap( + is_class_key = ls_class_key + iv_type = seop_ext_class_testclasses ). + + mv_skip_testclass = mi_object_oriented_object_fct->get_skip_test_classes( ). + IF lines( lt_source ) > 0 AND mv_skip_testclass = abap_false. + mo_files->add_abap( + iv_extra = zif_abapgit_oo_object_fnc=>c_parts-testclasses + it_abap = lt_source ). + ENDIF. + + lt_source = mi_object_oriented_object_fct->serialize_abap( + is_class_key = ls_class_key + iv_type = seop_ext_class_macros ). + IF lines( lt_source ) > 0. + mo_files->add_abap( + iv_extra = zif_abapgit_oo_object_fnc=>c_parts-macros + it_abap = lt_source ). + ENDIF. + + serialize_xml( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_chdo IMPLEMENTATION. + METHOD after_import. + + DATA: lt_cts_object_entry TYPE STANDARD TABLE OF e071 WITH DEFAULT KEY, + ls_cts_object_entry LIKE LINE OF lt_cts_object_entry, + lt_errormsg TYPE STANDARD TABLE OF sprot_u WITH DEFAULT KEY. + + ls_cts_object_entry-pgmid = 'R3TR'. + ls_cts_object_entry-object = ms_item-obj_type. + ls_cts_object_entry-obj_name = ms_item-obj_name. + INSERT ls_cts_object_entry INTO TABLE lt_cts_object_entry. + + CALL FUNCTION 'AFTER_IMP_CHDO' + EXPORTING + iv_tarclient = sy-mandt + iv_is_upgrade = abap_false + TABLES + tt_e071 = lt_cts_object_entry + tt_errormsg = lt_errormsg. + + LOOP AT lt_errormsg TRANSPORTING NO FIELDS WHERE severity = 'E' OR severity = 'A'. + EXIT. + ENDLOOP. + + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( 'Error from AFTER_IMP_CHDO' ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_object = is_item-obj_name. + + ENDMETHOD. + METHOD delete_tadir_cdnames. + + IF is_cdnames-repnamec IS NOT INITIAL. + zcl_abapgit_factory=>get_tadir( )->delete_single( + iv_object = 'PROG' + iv_obj_name = is_cdnames-repnamec ). + ENDIF. + + IF is_cdnames-repnamet IS NOT INITIAL. + zcl_abapgit_factory=>get_tadir( )->delete_single( + iv_object = 'PROG' + iv_obj_name = is_cdnames-repnamet ). + ENDIF. + + IF is_cdnames-repnamefix IS NOT INITIAL. + zcl_abapgit_factory=>get_tadir( )->delete_single( + iv_object = 'PROG' + iv_obj_name = is_cdnames-repnamefix ). + ENDIF. + + IF is_cdnames-repnamevar IS NOT INITIAL. + zcl_abapgit_factory=>get_tadir( )->delete_single( + iv_object = 'PROG' + iv_obj_name = is_cdnames-repnamevar ). + ENDIF. + + IF is_cdnames-fgrp IS NOT INITIAL. + zcl_abapgit_factory=>get_tadir( )->delete_single( + iv_object = 'FUGR' + iv_obj_name = is_cdnames-fgrp ). + ENDIF. + + ENDMETHOD. + METHOD delete_tadir_tabl. + + IF is_tcdrs-tabname IS NOT INITIAL. + zcl_abapgit_factory=>get_tadir( )->delete_single( + iv_object = 'TABL' + iv_obj_name = is_tcdrs-tabname ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE updname INTO rv_user + FROM tcdrp + WHERE object = mv_object. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lt_cdnames TYPE STANDARD TABLE OF cdnames, + ls_cdnames TYPE cdnames, + lt_tcdrs TYPE STANDARD TABLE OF tcdrs, + ls_tcdrs TYPE tcdrs, + lv_msg TYPE symsgv. + + CALL FUNCTION 'CDNAMES_GET' + EXPORTING + iv_object = mv_object + TABLES + it_tcdrs = lt_tcdrs + it_names = lt_cdnames + EXCEPTIONS + object_space = 1 + object_not_found = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'CHDO_DELETE' + EXPORTING + iv_object = mv_object + iv_with_tadir = abap_true + EXCEPTIONS + object_is_space = 1 + object_not_found = 2 + other_error = 3 + OTHERS = 4. + IF sy-subrc <> 0. + lv_msg = mv_object. + zcx_abapgit_exception=>raise_t100( iv_msgid = 'CD' + iv_msgno = '869' + iv_msgv1 = lv_msg ). + ENDIF. + + LOOP AT lt_cdnames INTO ls_cdnames. + delete_tadir_cdnames( ls_cdnames ). + ENDLOOP. + + LOOP AT lt_tcdrs INTO ls_tcdrs. + delete_tadir_tabl( ls_tcdrs ). + ENDLOOP. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_change_object TYPE ty_change_document. + FIELD-SYMBOLS: LIKE LINE OF ls_change_object-reports_generated. + + io_xml->read( EXPORTING iv_name = 'CHDO' + CHANGING cg_data = ls_change_object ). + + DELETE FROM tcdobs WHERE object = mv_object. + DELETE FROM tcdobts WHERE object = mv_object. + DELETE FROM tcdrps WHERE object = mv_object. + + LOOP AT ls_change_object-reports_generated ASSIGNING . + -devclass = iv_package. + ENDLOOP. + + INSERT tcdobs FROM TABLE ls_change_object-objects. + INSERT tcdobts FROM TABLE ls_change_object-objects_text. + INSERT tcdrps FROM TABLE ls_change_object-reports_generated. + + tadir_insert( iv_package ). + + after_import( ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + SELECT COUNT(*) + FROM tcdrp + WHERE object = mv_object. + + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA: lt_bdcdata TYPE STANDARD TABLE OF bdcdata, + ls_bdcdata LIKE LINE OF lt_bdcdata. + + CLEAR: ls_bdcdata. + ls_bdcdata-program = 'SAPMSCDO_NEW'. + ls_bdcdata-dynpro = '0100'. + ls_bdcdata-dynbegin = abap_true. + APPEND ls_bdcdata TO lt_bdcdata. + + CLEAR: ls_bdcdata. + ls_bdcdata-fnam = 'TCDOB-OBJECT'. + ls_bdcdata-fval = mv_object. + APPEND ls_bdcdata TO lt_bdcdata. + + CLEAR: ls_bdcdata. + ls_bdcdata-fnam = 'BDC_OKCODE'. + ls_bdcdata-fval = '=DISP'. + APPEND ls_bdcdata TO lt_bdcdata. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SCDO' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_change_object TYPE ty_change_document, + lt_tcdrp TYPE STANDARD TABLE OF tcdrp, + lt_tcdob TYPE STANDARD TABLE OF tcdob, + lt_tcdobt TYPE STANDARD TABLE OF tcdobt, + BEGIN OF ls_nulldatetime, " hack ro reset fields when they exist without syntax errors when they don't + udate TYPE sy-datum, + utime TYPE sy-uzeit, + END OF ls_nulldatetime. + + FIELD-SYMBOLS: LIKE LINE OF ls_change_object-reports_generated, + LIKE LINE OF ls_change_object-objects, + LIKE LINE OF ls_change_object-objects_text. + + CALL FUNCTION 'CDNAMES_GET' + EXPORTING + iv_object = mv_object + TABLES + it_tcdrp = lt_tcdrp + it_tcdob = lt_tcdob + it_tcdobt = lt_tcdobt + EXCEPTIONS + object_space = 1 + object_not_found = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ls_change_object-reports_generated = lt_tcdrp. + ls_change_object-objects = lt_tcdob. + ls_change_object-objects_text = lt_tcdobt. + + " At import, when CHDO is generated date & time change, so always detects changes for this fields + LOOP AT ls_change_object-reports_generated ASSIGNING . + CLEAR: -datum, -uzeit, + -author, -updname, + -devclass. + ENDLOOP. + + LOOP AT ls_change_object-objects ASSIGNING . + MOVE-CORRESPONDING ls_nulldatetime TO . " reset date and time + ENDLOOP. + + LOOP AT ls_change_object-objects_text ASSIGNING . + MOVE-CORRESPONDING ls_nulldatetime TO . " reset date and time + ENDLOOP. + + io_xml->add( iv_name = 'CHDO' + ig_data = ls_change_object ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_CHAR IMPLEMENTATION. + METHOD instantiate_char_and_lock. + + DATA: lv_new TYPE abap_bool, + lv_name TYPE cls_attribute_name. + SELECT SINGLE name FROM cls_attribute INTO lv_name WHERE name = ms_item-obj_name. + lv_new = boolc( sy-subrc <> 0 ). + lv_name = ms_item-obj_name. + + TRY. + CREATE OBJECT ro_char + EXPORTING + im_name = lv_name + im_type_group = iv_type_group + im_new = lv_new + im_activation_state = iv_activation_state. + CATCH cx_pak_invalid_data + cx_pak_not_authorized + cx_pak_invalid_state + cx_pak_wb_object_locked. + zcx_abapgit_exception=>raise( 'Error while instantiating CL_CLS_ATTRIBUTE' ). + ENDTRY. + + IF lv_new = abap_false. + TRY. + ro_char->if_pak_wb_object~lock_and_refresh( ). + CATCH cx_pak_invalid_data + cx_pak_not_authorized + cx_pak_invalid_state + cx_pak_wb_object_locked. + zcx_abapgit_exception=>raise( |Could not acquire lock, CHAR { lv_name }| ). + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + SELECT SINGLE changed_by FROM cls_attribute INTO rv_user + WHERE name = ms_item-obj_name + AND activation_state = 'A'. + + IF rv_user IS INITIAL. + SELECT SINGLE created_by FROM cls_attribute INTO rv_user + WHERE name = ms_item-obj_name + AND activation_state = 'A'. + ENDIF. + + IF rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_char TYPE REF TO cl_cls_attribute, + lv_type_group TYPE cls_attribute-type_group, + lx_pak_error TYPE REF TO cx_root, + lv_text TYPE string. + SELECT SINGLE type_group FROM cls_attribute INTO lv_type_group + WHERE name = ms_item-obj_name + AND activation_state = 'A'. + + lo_char = instantiate_char_and_lock( iv_type_group = lv_type_group + iv_activation_state = cl_pak_wb_domains=>co_activation_state-active ). + + TRY. + lo_char->if_pak_wb_object~delete( ). + + lo_char->if_pak_wb_object~save( ). + + lo_char->if_pak_wb_object_internal~unlock( ). + + CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. + lo_char->if_pak_wb_object_internal~unlock( ). + lv_text = lx_pak_error->get_text( ). + zcx_abapgit_exception=>raise( lv_text ). + CLEANUP. + lo_char->if_pak_wb_object_internal~unlock( ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_char TYPE ty_char, + ls_description LIKE LINE OF ls_char-cls_attributet, + lo_char TYPE REF TO cl_cls_attribute, + lx_pak_error TYPE REF TO cx_root, + lv_text TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF ls_char-cls_attr_value, + TYPE any, + LIKE LINE OF ls_char-cls_attr_valuet. + io_xml->read( EXPORTING iv_name = 'CHAR' + CHANGING cg_data = ls_char ). + + tadir_insert( iv_package ). + + lo_char = instantiate_char_and_lock( iv_type_group = ls_char-cls_attribute-type_group + iv_activation_state = cl_pak_wb_domains=>co_activation_state-inactive ). + + TRY. + lo_char->if_cls_attribute~set_kind( ls_char-cls_attribute-kind ). + lo_char->if_cls_attribute~set_single_valued( ls_char-cls_attribute-is_single_valued ). + lo_char->if_cls_attribute~set_aspect( + im_aspect_for = ls_char-cls_attribute-is_aspect_for + im_aspect_value = ls_char-cls_attribute-aspect_value ). + lo_char->if_cls_attribute~set_default_flag( ls_char-cls_attribute-default_flag ). + lo_char->if_cls_attribute~set_default_value( ls_char-cls_attribute-default_value ). + lo_char->if_cls_attribute~set_sub_object_treatment( ls_char-cls_attribute-sub_obj_treatm ). + lo_char->if_cls_attribute~set_automatic_changes_allowed( ls_char-cls_attribute-automatic_change ). + lo_char->if_cls_attribute~set_manual_changes_allowed( ls_char-cls_attribute-manu_chag_allow ). + lo_char->if_cls_attribute~set_implicit_changes_allowed( ls_char-cls_attribute-implicit_change ). + lo_char->if_cls_attribute~set_expl_values_dominate_links( ls_char-cls_attribute-weak_links ). + lo_char->if_cls_attribute~set_assignment_package_rule( ls_char-cls_attribute-assignment_devc ). + +* Method SET_HIDE_ICON does not exist in some releases, not present in 751 + ASSIGN COMPONENT 'HIDE_ICONS' OF STRUCTURE ls_char-cls_attribute TO . + IF sy-subrc = 0. + CALL METHOD lo_char->('IF_CLS_ATTRIBUTE~SET_HIDE_ICON') + EXPORTING + im_hide_icon = . + ENDIF. + + lo_char->if_cls_attribute~set_hide_remark( ls_char-cls_attribute-hide_remark ). + lo_char->if_cls_attribute~set_visible_in_customer_system( ls_char-cls_attribute-visible_for_cust ). + lo_char->if_cls_attribute~set_value_table( ls_char-cls_attribute-value_table ). + lo_char->if_cls_attribute~set_vtable_field( ls_char-cls_attribute-vtable_field ). + lo_char->if_cls_attribute~set_vtable_icon_f( ls_char-cls_attribute-vtable_icon_f ). + lo_char->if_cls_attribute~set_vtext_langu_f( ls_char-cls_attribute-vtext_langu_f ). + lo_char->if_cls_attribute~set_vtext_table( ls_char-cls_attribute-vtext_table ). + lo_char->if_cls_attribute~set_vtext_text_f( ls_char-cls_attribute-vtext_text_f ). + lo_char->if_cls_attribute~set_vtext_value_f( ls_char-cls_attribute-vtext_value_f ). + lo_char->if_cls_attribute~set_existing_objects_only( ls_char-cls_attribute-existing_objects ). + lo_char->if_cls_attribute~set_objs_of_typegr( ls_char-cls_attribute-objs_of_typegr ). + lo_char->if_cls_attribute~set_obj_values_have_subtypes( ls_char-cls_attribute-objs_w_subtype ). + lo_char->if_cls_attribute~set_arbtry_val_type( ls_char-cls_attribute-arbtry_val_type ). + + READ TABLE ls_char-cls_attributet INTO ls_description WITH KEY langu = mv_language. + IF sy-subrc <> 0. + READ TABLE ls_char-cls_attributet INTO ls_description INDEX 1. + ENDIF. + lo_char->if_cls_attribute~set_description( ls_description-text ). + + LOOP AT ls_char-cls_attr_value ASSIGNING . + -activation_state = 'I'. + ENDLOOP. + LOOP AT ls_char-cls_attr_valuet ASSIGNING . + -activation_state = 'I'. + ENDLOOP. + + lo_char->if_cls_attribute~set_values( + im_values = ls_char-cls_attr_value + im_values_t = ls_char-cls_attr_valuet ). + + set_default_package( iv_package ). + + lo_char->if_pak_wb_object~save( ). + + lo_char->if_pak_wb_object~activate( ). + + lo_char->if_pak_wb_object_internal~unlock( ). + + CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. + lo_char->if_pak_wb_object_internal~unlock( ). + lv_text = lx_pak_error->get_text( ). + zcx_abapgit_exception=>raise( lv_text ). + CLEANUP. + lo_char->if_pak_wb_object_internal~unlock( ). + ENDTRY. + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_char ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = cl_cls_attribute=>exists_object_attribute( ms_item-obj_name ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ECLS_ATTRIBUTE' + iv_argument = |{ ms_item-obj_name }*| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_char TYPE ty_char. + + CONSTANTS: lc_active TYPE c LENGTH 1 VALUE 'A'. + SELECT SINGLE * FROM cls_attribute INTO ls_char-cls_attribute + WHERE name = ms_item-obj_name + AND activation_state = lc_active. +* todo, ASSIGNMENT_DEVC? + + CLEAR: ls_char-cls_attribute-created_by, + ls_char-cls_attribute-created_on, + ls_char-cls_attribute-changed_by, + ls_char-cls_attribute-changed_on. + + SELECT * FROM cls_attributet INTO TABLE ls_char-cls_attributet + WHERE name = ms_item-obj_name + AND activation_state = lc_active + ORDER BY PRIMARY KEY. + IF mo_i18n_params->ms_params-main_language_only = abap_true. + DELETE ls_char-cls_attributet WHERE langu <> mv_language. + ENDIF. + + SELECT * FROM cls_attr_value INTO TABLE ls_char-cls_attr_value + WHERE name = ms_item-obj_name + AND activation_state = lc_active + ORDER BY PRIMARY KEY. + + SELECT * FROM cls_attr_valuet INTO TABLE ls_char-cls_attr_valuet + WHERE name = ms_item-obj_name + AND activation_state = lc_active + ORDER BY PRIMARY KEY. + IF mo_i18n_params->ms_params-main_language_only = abap_true. + DELETE ls_char-cls_attr_valuet WHERE langu <> mv_language. + ENDIF. + + io_xml->add( iv_name = 'CHAR' + ig_data = ls_char ). + + serialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_char ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_bdef IMPLEMENTATION. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_metadata + TO . + ASSERT sy-subrc = 0. + + CLEAR: . + + ENDMETHOD. + METHOD clear_fields. + + FIELD-SYMBOLS: TYPE ANY TABLE. + FIELD-SYMBOLS: TYPE data. + FIELD-SYMBOLS TYPE any. + + clear_field( + EXPORTING + iv_fieldname = 'VERSION' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'CREATED_AT' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'CREATED_BY' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGED_AT' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'CHANGED_BY' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'RESPONSIBLE' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'PACKAGE_REF' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'CONTAINER_REF' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MASTER_SYSTEM' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MAIN_OBJECT-CHANGED_AT' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MAIN_OBJECT-CHANGED_BY' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MAIN_OBJECT-CREATED_AT' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MAIN_OBJECT-CREATED_BY' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MAIN_OBJECT-RESPONSIBLE' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MAIN_OBJECT-PACKAGE_REF' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MAIN_OBJECT-CONTAINER_REF' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'MAIN_OBJECT-MASTER_SYSTEM' + CHANGING + cs_metadata = cs_metadata ). + + clear_field( + EXPORTING + iv_fieldname = 'SYNTAX_CONFIGURATION' + CHANGING + cs_metadata = cs_metadata ). + + ASSIGN COMPONENT 'LINKS' OF STRUCTURE cs_metadata TO . + ASSERT sy-subrc = 0. + + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'COMMON_ATTRIBUTES' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + CLEAR: . + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_behaviour_definition_key = ms_item-obj_name. + + TRY. + CREATE DATA mr_behaviour_definition TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). + CREATE OBJECT mi_persistence TYPE ('CL_BDEF_OBJECT_PERSIST'). + + CATCH cx_sy_create_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD get_object_data. + + DATA: + lr_metadata TYPE REF TO data, + lr_data TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE any, + TYPE any. + + CREATE DATA lr_data TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). + ASSIGN lr_data->* TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + CREATE DATA lr_metadata TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA-METADATA'). + ASSIGN lr_metadata->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'BDEF' + CHANGING + cg_data = ). + + = . + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + = mo_files->read_string( 'asbdef' ). + + CREATE OBJECT ro_object_data TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). + + ro_object_data->set_data( p_data = ). + + ENDMETHOD. + METHOD get_wb_object_operator. + + DATA: + ls_object_type TYPE wbobjtype, + lx_error TYPE REF TO cx_root. + + IF mi_wb_object_operator IS BOUND. + ri_wb_object_operator = mi_wb_object_operator. + ENDIF. + + ls_object_type-objtype_tr = 'BDEF'. + ls_object_type-subtype_wb = 'BDO'. + + TRY. + CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') + EXPORTING + object_type = ls_object_type + object_key = mv_behaviour_definition_key + RECEIVING + result = mi_wb_object_operator. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ri_wb_object_operator = mi_wb_object_operator. + + ENDMETHOD. + METHOD merge_object_data. + + DATA: + lo_object_data TYPE REF TO object, + lo_object_data_old TYPE REF TO if_wb_object_data_model, + lr_new TYPE REF TO data, + lr_old TYPE REF TO data, + lo_wb_object_operator TYPE REF TO object. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE any, + TYPE any. + + CREATE OBJECT lo_object_data TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). + lo_object_data = io_object_data. + + CREATE DATA lr_new TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). + ASSIGN lr_new->* TO . + ASSERT sy-subrc = 0. + + CREATE DATA lr_old TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). + ASSIGN lr_old->* TO . + ASSERT sy-subrc = 0. + + CALL METHOD lo_object_data->('IF_WB_OBJECT_DATA_MODEL~GET_DATA') + EXPORTING + p_metadata_only = abap_false + p_data_selection = 'AL' + IMPORTING + p_data = . + + lo_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + IMPORTING + eo_object_data = lo_object_data_old. + + CALL METHOD lo_object_data_old->('GET_DATA') + EXPORTING + p_metadata_only = abap_false + p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + IMPORTING + p_data = . + + ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . + ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . + = . + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + = . + + CREATE OBJECT ro_object_data_merged TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). + + CALL METHOD ro_object_data_merged->('SET_DATA') + EXPORTING + p_data = . + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + li_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = li_object_data_model. + + rv_user = li_object_data_model->get_changed_by( ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + lx_error TYPE REF TO cx_root, + li_wb_object_operator TYPE REF TO object. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') + EXPORTING + transport_request = iv_transport. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + lo_object_data TYPE REF TO if_wb_object_data_model, + lo_object_data_merged TYPE REF TO if_wb_object_data_model, + lo_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root, + lr_wbobjtype TYPE REF TO data, + lr_category TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE any. + + TRY. + + lo_object_data = get_object_data( io_xml ). + + CREATE DATA lr_wbobjtype TYPE ('WBOBJTYPE'). + ASSIGN lr_wbobjtype->* TO . + ASSIGN COMPONENT 'OBJTYPE_TR' OF STRUCTURE TO . + = 'BDEF'. + ASSIGN COMPONENT 'SUBTYPE_WB' OF STRUCTURE TO . + = 'BDO'. + + CREATE DATA lr_category TYPE ('WBADT_RESOURCE_CATEGORY'). + ASSIGN lr_category->* TO . + + CALL METHOD ('CL_BLUE_WB_UTILITY')=>('GET_RESOURCE_CATEGORY') + EXPORTING + is_object_type = + RECEIVING + result = . + + lo_wb_object_operator = get_wb_object_operator( ). + + tadir_insert( iv_package ). + + IF zif_abapgit_object~exists( ) = abap_false. + CASE . + WHEN '1'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = lo_object_data + data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data + version = 'I' + package = iv_package + transport_request = iv_transport. + WHEN '2'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_compound_s. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = lo_object_data + data_selection = 'P' " if_wb_object_data_selection_co=>c_properties + version = 'I' + package = iv_package + transport_request = iv_transport. + + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_object_data + data_selection = 'D' "if_wb_object_data_selection_co=>c_data_content + version = 'I' + transport_request = iv_transport. + WHEN OTHERS. + ENDCASE. + ELSE. + lo_object_data_merged = merge_object_data( lo_object_data ). + CASE . + WHEN '1'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_object_data_merged + data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data + version = 'I' + transport_request = iv_transport. + WHEN '2'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_compound_s. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_object_data_merged + data_selection = 'P' "if_wb_object_data_selection_co=>c_properties + version = 'I' + transport_request = iv_transport. + CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = lo_object_data_merged + data_selection = 'D' "if_wb_object_data_selection_co=>c_data_content + version = 'I' + transport_request = iv_transport. + WHEN OTHERS. + ENDCASE. + ENDIF. + + corr_insert( iv_package ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + mi_persistence->get( + p_object_key = mv_behaviour_definition_key + p_version = 'A' + p_existence_check_only = abap_true ). + rv_bool = abap_true. + + CATCH cx_swb_exception. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDIC' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + li_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root, + lv_source TYPE string. + + FIELD-SYMBOLS: + TYPE any, + TYPE any, + TYPE string. + + ASSIGN mr_behaviour_definition->* TO . + ASSERT sy-subrc = 0. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + version = 'A' + IMPORTING + data = + eo_object_data = li_object_data_model. + + ASSIGN COMPONENT 'METADATA' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + clear_fields( CHANGING cs_metadata = ). + + ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + lv_source = . + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + io_xml->add( + iv_name = 'BDEF' + ig_data = ). + + mo_files->add_string( + iv_ext = 'asbdef' + iv_string = lv_source ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_avas IMPLEMENTATION. + METHOD insert_assignments. + + DATA: lt_assignment TYPE STANDARD TABLE OF cls_assignment, + ls_assignment LIKE LINE OF lt_assignment, + ls_value LIKE LINE OF is_avas-values. + LOOP AT is_avas-values INTO ls_value. + CLEAR ls_assignment. + ls_assignment-guid = is_avas-header-guid. + ls_assignment-value = ls_value-value. + ls_assignment-trobjtype = is_avas-header-object-trobjtype. + ls_assignment-sobj_name = is_avas-header-object-sobj_name. + ls_assignment-object_type = is_avas-header-object-object_type. + ls_assignment-sub_key = is_avas-header-object-sub_key. + ls_assignment-attribute = is_avas-header-attribute. + ls_assignment-set_by = sy-uname. + ls_assignment-changed_on = sy-datum. + ls_assignment-remark = ls_value-remark. + APPEND ls_assignment TO lt_assignment. + ENDLOOP. + + DELETE FROM cls_assignment WHERE guid = is_avas-header-guid. + + INSERT cls_assignment FROM TABLE lt_assignment. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error inserting into CLS_ASSIGNMENT| ). + ENDIF. + + ENDMETHOD. + METHOD instantiate. + + DATA: lv_id TYPE guid_32, + lx_err TYPE REF TO cx_root. + + lv_id = ms_item-obj_name. + + TRY. + CREATE OBJECT ro_avas + EXPORTING + im_assignment_id = lv_id. + CATCH cx_pak_wb_object_locked INTO lx_err. + zcx_abapgit_exception=>raise( |AVAS { lv_id }: locked: { lx_err->get_longtext( ) }| ). + CATCH cx_pak_not_authorized INTO lx_err. + zcx_abapgit_exception=>raise( |AVAS { lv_id }: not authorized: { lx_err->get_longtext( ) }| ). + CATCH cx_pak_invalid_state INTO lx_err. + zcx_abapgit_exception=>raise( |AVAS { lv_id }: invalid state: { lx_err->get_longtext( ) }| ). + CATCH cx_pak_invalid_data INTO lx_err. + zcx_abapgit_exception=>raise( |AVAS { lv_id }: invalid data: { lx_err->get_longtext( ) }| ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_avas TYPE REF TO cl_cls_attr_value_assignment. + lo_avas = instantiate( ). + + lo_avas->if_pak_wb_object~get_last_changed( IMPORTING ex_changed_by = rv_user ). + + IF rv_user IS INITIAL. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_avas TYPE REF TO cl_cls_attr_value_assignment. + lo_avas = instantiate( ). + + TRY. + lo_avas->if_cls_attr_value_assignment~lock_and_refresh( im_allow_popups = abap_false ). + CATCH cx_pak_invalid_state + cx_pak_invalid_data + cx_pak_not_authorized + cx_pak_wb_object_locked. + zcx_abapgit_exception=>raise( |AVAS error| ). + ENDTRY. + + lo_avas->if_pak_wb_object~delete( ). + + lo_avas->if_pak_wb_object~save( ). + + lo_avas->if_pak_wb_object_internal~unlock( ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: ls_avas TYPE ty_avas. + io_xml->read( EXPORTING iv_name = 'AVAS' + CHANGING cg_data = ls_avas ). + +* The AVAS API cannot be used in this case, as it will always create a new GUID + + ASSERT NOT ls_avas-header-guid IS INITIAL. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + insert_assignments( ls_avas ). +* todo, how does links work? + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_guid TYPE cls_assignment-guid. + + SELECT SINGLE guid FROM cls_assignment INTO lv_guid + WHERE guid = ms_item-obj_name. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + + rs_metadata = get_metadata( ). + + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( + iv_lock_object = 'CLS_ENQUEUE_STRU' + iv_argument = |{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_avas TYPE REF TO cl_cls_attr_value_assignment, + ls_avas TYPE ty_avas. + + FIELD-SYMBOLS: LIKE LINE OF ls_avas-values, + LIKE LINE OF ls_avas-links. + lo_avas = instantiate( ). + + ls_avas-header-guid = lo_avas->if_cls_attr_value_assignment~get_guid( ). + ls_avas-header-attribute = lo_avas->if_cls_attr_value_assignment~get_attribute( ). + ls_avas-header-object = lo_avas->if_cls_attr_value_assignment~get_object( ). + + lo_avas->if_cls_attr_value_assignment~get_values( IMPORTING ex_values = ls_avas-values ). + + lo_avas->if_cls_attr_value_assignment~get_links( IMPORTING ex_links = ls_avas-links ). + + LOOP AT ls_avas-values ASSIGNING . + CLEAR: -set_by, -changed_on. + ENDLOOP. + + LOOP AT ls_avas-links ASSIGNING . + CLEAR: -set_by, -changed_on. + ENDLOOP. + + io_xml->add( + iv_name = 'AVAS' + ig_data = ls_avas ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_avar IMPLEMENTATION. + METHOD create_object. + + DATA: lv_name TYPE aab_var_name. + + lv_name = ms_item-obj_name. + + CREATE OBJECT ro_aab_var + EXPORTING + im_name = lv_name + im_local = '' + EXCEPTIONS + name_not_allowed = 1 + user_not_valid = 2 + no_authorization = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_aab TYPE REF TO cl_aab_variant. + + lo_aab = create_object( ). + lo_aab->get_author( IMPORTING ex_author = rv_user ). + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_aab TYPE REF TO cl_aab_variant. + + lo_aab = create_object( ). + lo_aab->enqueue( ). + lo_aab->delete( + EXCEPTIONS + var_not_found = 1 + prop_error = 2 + propt_error = 3 + var_id_error = 4 + no_authorization = 5 + cts_error = 6 + cts_devclass = 7 + OTHERS = 8 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error deleting AVAR { ms_item-obj_name }| ). + ENDIF. + lo_aab->dequeue( ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_possible TYPE abap_bool, + lv_description TYPE aab_var_descript, + ls_is TYPE aab_var_obj_act, + lt_ids TYPE aab_var_obj_act_tab, + lo_aab TYPE REF TO cl_aab_variant. + + " AVAR can only be created in transportable packages + lv_possible = zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ). + IF lv_possible = abap_false. + zcx_abapgit_exception=>raise( |Global activation variants require a transportable package| ). + ENDIF. + + " Create AVAR with description and object (id) list + io_xml->read( EXPORTING iv_name = 'DESCRIPTION' + CHANGING cg_data = lv_description ). + + io_xml->read( EXPORTING iv_name = 'IDS' + CHANGING cg_data = lt_ids ). + + lo_aab = create_object( ). + lo_aab->enqueue( ). + lo_aab->set_descript( + EXPORTING + im_descript = lv_description + EXCEPTIONS + no_authorization = 1 ). + IF sy-subrc <> 0. + lo_aab->dequeue( ). + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + LOOP AT lt_ids INTO ls_is. + lo_aab->set_id( + EXPORTING + im_name = ls_is-name + im_object = ls_is-object + im_actmode = ls_is-actmode + EXCEPTIONS + no_authorization = 1 + id_not_exists = 2 + id_not_transportable = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + lo_aab->dequeue( ). + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDLOOP. + + tadir_insert( iv_package ). + + lo_aab->save( + EXCEPTIONS + no_descript_specified = 1 + prop_error = 2 + propt_error = 3 + var_id_error = 4 + no_changes_found = 5 + cts_error = 6 ). + IF sy-subrc <> 0. + lo_aab->dequeue( ). + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + lo_aab->dequeue( ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_state TYPE abap_bool, + lo_aab TYPE REF TO cl_aab_variant. + + lo_aab = create_object( ). + + lo_aab->get_state( IMPORTING ex_state = lv_state ). + rv_bool = boolc( lv_state = abap_true ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_aab TYPE REF TO cl_aab_variant, + lt_ids TYPE aab_var_obj_act_tab, + lv_description TYPE aab_var_descript. + + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + lo_aab = create_object( ). + + lo_aab->get_descript( + IMPORTING + ex_descript = lv_description + EXCEPTIONS + no_descript_found = 1 ). + IF sy-subrc = 0. + io_xml->add( iv_name = 'DESCRIPTION' + ig_data = lv_description ). + ENDIF. + + lo_aab->get_ids( IMPORTING ex_ids = lt_ids ). + + io_xml->add( iv_name = 'IDS' + ig_data = lt_ids ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_auth IMPLEMENTATION. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_fieldname = ms_item-obj_name. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. +* looks like "changed by user" is not stored in the database + rv_user = c_user_unknown. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + " there is a bug in SAP standard, the TADIR entries are not deleted + " when the AUTH object is deleted in transaction SU20 + + " FM SUSR_AUTF_DELETE_FIELD calls the UI, therefore we reimplement its logic + + DATA: + lt_objlst TYPE susr_t_xuobject, + lo_auth TYPE REF TO cl_auth_tools. + + " authority check + CREATE OBJECT lo_auth. + IF lo_auth->authority_check_suso( actvt = '06' + fieldname = mv_fieldname ) <> 0. + MESSAGE e463(01) WITH mv_fieldname INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " if field is used check + lt_objlst = lo_auth->suso_where_used_afield( mv_fieldname ). + IF lt_objlst IS NOT INITIAL. + MESSAGE i453(01) WITH mv_fieldname INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " collect fieldname into a transport task + IF lo_auth->add_afield_to_trkorr( mv_fieldname ) <> 0. + "no transport -> no deletion + MESSAGE e507(0m) INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + DELETE FROM authx WHERE fieldname = mv_fieldname. + IF sy-subrc <> 0. + MESSAGE e507(0m) INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. +* see include LSAUT_FIELDF02 + + DATA: ls_authx TYPE authx, + lo_auth TYPE REF TO cl_auth_tools. + io_xml->read( EXPORTING iv_name = 'AUTHX' + CHANGING cg_data = ls_authx ). + + tadir_insert( iv_package ). + + CREATE OBJECT lo_auth. + + IF lo_auth->add_afield_to_trkorr( ls_authx-fieldname ) <> 0. + zcx_abapgit_exception=>raise( 'Error deserializing AUTH' ). + ENDIF. + + MODIFY authx FROM ls_authx. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error deserializing AUTH' ). + ENDIF. + + CALL FUNCTION 'DB_COMMIT'. + lo_auth->set_authfld_info_from_db( ls_authx-fieldname ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + SELECT SINGLE fieldname FROM authx + INTO mv_fieldname + WHERE fieldname = ms_item-obj_name. "#EC CI_GENBUFF + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + IF zcl_abapgit_factory=>get_function_module( )->function_exists( 'SU20_MAINTAIN_SNGL' ) = abap_true. + " this function module does not exist in 740 + CALL FUNCTION 'SU20_MAINTAIN_SNGL' + EXPORTING + id_field = mv_fieldname + id_wbo_mode = abap_false ##EXISTS. + rv_exit = abap_true. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: ls_authx TYPE authx. + SELECT SINGLE * FROM authx INTO ls_authx + WHERE fieldname = ms_item-obj_name. "#EC CI_GENBUFF + IF sy-subrc <> 0. + RETURN. + ENDIF. + + io_xml->add( iv_name = 'AUTHX' + ig_data = ls_authx ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_asfc IMPLEMENTATION. + METHOD get_generic. + + CREATE OBJECT ro_generic + EXPORTING + is_item = ms_item + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. " not stored by SAP + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + set_default_transport( iv_transport ). + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + set_default_transport( iv_transport ). + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_area IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_user TYPE string. + + SELECT SINGLE tstpnm FROM ('RSDAREA') INTO lv_user. + + rv_user = lv_user. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + lr_area TYPE REF TO object. + + CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). + + CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~DELETE_NODE') + EXPORTING + i_nodename = ms_item-obj_name + i_with_dialog = ''. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error while deleting AREA: { ms_item-obj_name }| ). + ENDIF. + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + lv_nodename TYPE c LENGTH 40, + lv_parentname TYPE c LENGTH 40, + lv_txtsh TYPE c LENGTH 20, + lv_txtlg TYPE c LENGTH 60, + lr_area TYPE REF TO object. + + io_xml->read( EXPORTING iv_name = 'NODENAME' + CHANGING cg_data = lv_nodename ). + + io_xml->read( EXPORTING iv_name = 'PARENTNAME' + CHANGING cg_data = lv_parentname ). + + io_xml->read( EXPORTING iv_name = 'TXTSH' + CHANGING cg_data = lv_txtsh ). + + io_xml->read( EXPORTING iv_name = 'TXTLG' + CHANGING cg_data = lv_txtlg ). + + CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). + + CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~CREATE_NODE') + EXPORTING + i_parentname = lv_parentname + i_nodename = lv_nodename + i_txtsh = lv_txtsh + i_txtlg = lv_txtlg. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error while creating AREA: { ms_item-obj_name }| ). + ENDIF. + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: + lr_area TYPE REF TO object, + lr_tab_tree TYPE REF TO data, + lr_str_tee TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + TYPE any. + + CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). + + CREATE DATA lr_tab_tree TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). + ASSIGN lr_tab_tree->* TO . + + CREATE DATA lr_str_tee TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). + ASSIGN lr_str_tee->* TO . + + CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~GET_TREE') + EXPORTING + i_objvers = '' + i_langu = '' + IMPORTING + e_t_tree = . + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error while read AREA tree| ). + ENDIF. + + READ TABLE WITH KEY ('NODENAME') = ms_item-obj_name ASSIGNING . + + IF sy-subrc = 0. + rv_bool = abap_true. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + + DATA: + lr_area TYPE REF TO object, + lr_tab_tree TYPE REF TO data, + lr_str_tee TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + TYPE any. + + CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). + + CREATE DATA lr_tab_tree TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). + ASSIGN lr_tab_tree->* TO . + + CREATE DATA lr_str_tee TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). + ASSIGN lr_str_tee->* TO . + + CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~GET_TREE') + EXPORTING + i_objvers = 'A' + i_langu = mv_language + IMPORTING + e_t_tree = . + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error while read AREA tree| ). + ENDIF. + + READ TABLE WITH KEY ('NODENAME') = ms_item-obj_name ASSIGNING . + + IF sy-subrc = 0. + rv_active = abap_true. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = exists_a_lock_entry_for( 'ERSDAREA' ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + lr_area TYPE REF TO object, + lr_tab_tree TYPE REF TO data, + lr_str_tee TYPE REF TO data, + lr_rsdareat TYPE REF TO data, + lv_select TYPE string. + + FIELD-SYMBOLS: + TYPE STANDARD TABLE, + TYPE any, + TYPE any, + TYPE any, + TYPE any, + TYPE any. + + CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). + + CREATE DATA lr_tab_tree TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). + ASSIGN lr_tab_tree->* TO . + + CREATE DATA lr_str_tee TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). + ASSIGN lr_str_tee->* TO . + + CREATE DATA lr_rsdareat TYPE ('RSDAREAT'). + ASSIGN lr_rsdareat->* TO . + + CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~GET_TREE') + EXPORTING + i_objvers = 'A' + i_langu = mv_language + IMPORTING + e_t_tree = . + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error while read AREA tree| ). + ENDIF. + + READ TABLE WITH KEY ('NODENAME') = ms_item-obj_name ASSIGNING . + + lv_select = |INFOAREA = '{ ms_item-obj_name }'|. + + SELECT SINGLE * FROM ('RSDAREAT') + INTO + WHERE infoarea = ms_item-obj_name. + + ASSIGN COMPONENT 'TXTSH' OF STRUCTURE TO . + ASSIGN COMPONENT 'TXTLG' OF STRUCTURE TO . + ASSIGN COMPONENT 'PARENTNAME' OF STRUCTURE TO . + + io_xml->add( iv_name = 'NODENAME' + ig_data = ms_item-obj_name ). + + io_xml->add( iv_name = 'PARENTNAME' + ig_data = ). + + io_xml->add( iv_name = 'TXTSH' + ig_data = ). + + io_xml->add( iv_name = 'TXTLG' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_aqsg IMPLEMENTATION. + METHOD get_field_rules. + + ro_result = zcl_abapgit_field_rules=>create( ). + +* add rules here if needed + + ENDMETHOD. + METHOD get_generic. + " transaction SQ02 + CREATE OBJECT ro_generic + EXPORTING + is_item = ms_item + io_field_rules = get_field_rules( ) + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMS38O'. + -dynpro = '0050'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'RS38Q-NAME'. + -fval = ms_item-obj_name. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SQ02' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + get_generic( )->serialize( io_xml ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_aqqu IMPLEMENTATION. + METHOD get_field_rules. + + ro_result = zcl_abapgit_field_rules=>create( ). + +* add rules here if needed + + ENDMETHOD. + METHOD get_generic. + " transaction SQ01 + CREATE OBJECT ro_generic + EXPORTING + is_item = ms_item + io_field_rules = get_field_rules( ) + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + rv_user = c_user_unknown. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMS38R'. + -dynpro = '0050'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'RS38R-QNUM'. + -fval = ms_item-obj_name. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SQ01' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + get_generic( )->serialize( io_xml ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_aqbg IMPLEMENTATION. + METHOD get_field_rules. + + ro_result = zcl_abapgit_field_rules=>create( ). + + ro_result->add( + iv_table = 'AQGDBBG' + iv_field = 'BGCNAM' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user + )->add( + iv_table = 'AQGDBBG' + iv_field = 'BGUNAM' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user ). + + ro_result->add( + iv_table = 'AQGDBBG' + iv_field = 'BGCDAT' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date + )->add( + iv_table = 'AQGDBBG' + iv_field = 'BGUDAT' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date ). + + ro_result->add( + iv_table = 'AQGDBBG' + iv_field = 'DEVC' + iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-package ). + + ENDMETHOD. + METHOD get_generic. + " transaction SQ03 + CREATE OBJECT ro_generic + EXPORTING + is_item = ms_item + io_field_rules = get_field_rules( ) + iv_language = mv_language. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + SELECT SINGLE bgunam FROM aqgdbbg INTO rv_user WHERE num = ms_item-obj_name. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + get_generic( )->delete( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + get_generic( )->deserialize( + iv_package = iv_package + io_xml = io_xml ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + rv_bool = get_generic( )->exists( ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + + DATA lt_bdcdata TYPE TABLE OF bdcdata. + + FIELD-SYMBOLS LIKE LINE OF lt_bdcdata. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -program = 'SAPMS38S'. + -dynpro = '0050'. + -dynbegin = abap_true. + + APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . + -fnam = 'RS38S-BGNUM'. + -fval = ms_item-obj_name. + + zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( + iv_tcode = 'SQ03' + it_bdcdata = lt_bdcdata ). + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + get_generic( )->serialize( io_xml ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_apis IMPLEMENTATION. + METHOD constructor. + + DATA lr_data TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE DATA lr_data TYPE (c_model). + CATCH cx_sy_create_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD initialize. + + IF mo_handler IS NOT BOUND. + CREATE OBJECT mo_handler TYPE ('CL_ARS_API_ABAPGIT') + EXPORTING + iv_api_object_name = ms_item-obj_name. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + initialize( ). + + TRY. + CALL METHOD mo_handler->('IF_ARS_API_ABAPGIT~GET_CHANGED_BY') + RECEIVING + rv_changed_by = rv_user. + CATCH cx_root. + rv_user = c_user_unknown. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + +* IF_ARS_API_ABAPGIT~DELETE_API_STATE dumps and checks fail, even though I as a developer can delete it + + DATA lo_db TYPE REF TO object. + DATA lr_data TYPE REF TO data. + FIELD-SYMBOLS TYPE any. + CREATE DATA lr_data TYPE ('IF_ARS_STATE_DB_ACCESS=>TY_S_API_KEY'). + ASSIGN lr_data->* TO . + = ms_item-obj_name. + ASSERT IS NOT INITIAL. + + CALL METHOD ('CL_ARS_STATE_DB_ACCESS')=>('GET_INSTANCE') + RECEIVING + ro_state_db_access = lo_db. + + CALL METHOD lo_db->('IF_ARS_STATE_DB_ACCESS~DELETE') + EXPORTING + is_api_key = . + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + +* IF_ARS_API_ABAPGIT~SAVE_API_STATE dumps in some package checks + + DATA lr_data TYPE REF TO data. + DATA lo_db TYPE REF TO object. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE simple. + CREATE DATA lr_data TYPE (c_model). + ASSIGN lr_data->* TO . + CREATE DATA lr_data TYPE ('IF_ARS_STATE_DB_ACCESS=>TY_S_HEADER'). + ASSIGN lr_data->* TO . + CREATE DATA lr_data TYPE ('IF_ARS_STATE_DB_ACCESS=>TY_T_STATE'). + ASSIGN lr_data->* TO . + + io_xml->read( + EXPORTING + iv_name = 'APIS' + CHANGING + cg_data = ). + + MOVE-CORRESPONDING TO . + + ASSIGN COMPONENT 'API_STATES' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + +* the state table is sorted, + LOOP AT ASSIGNING . + CREATE DATA lr_data TYPE ('IF_ARS_STATE_DB_ACCESS=>TY_S_STATE'). + ASSIGN lr_data->* TO . + MOVE-CORRESPONDING TO . + MOVE-CORRESPONDING TO . + + ASSIGN COMPONENT 'SOFTWARE_RELEASE_NAME' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = '1908'. + ASSIGN COMPONENT 'CREATED_AT' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = sy-datum. + ASSIGN COMPONENT 'CREATED_BY' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = sy-uname. + ASSIGN COMPONENT 'LAST_CHANGED_AT' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = sy-datum. + ASSIGN COMPONENT 'LAST_CHANGED_BY' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + = sy-uname. + + INSERT INTO TABLE . + ENDLOOP. + + CALL METHOD ('CL_ARS_STATE_DB_ACCESS')=>('GET_INSTANCE') + RECEIVING + ro_state_db_access = lo_db. + + CALL METHOD lo_db->('IF_ARS_STATE_DB_ACCESS~SAVE') + EXPORTING + is_header = + it_release_states = . + + tadir_insert( iv_package ). + + corr_insert( iv_package ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + initialize( ). + CALL METHOD mo_handler->('IF_ARS_API_ABAPGIT~CHECK_EXISTS') + RECEIVING + rv_api_exists = rv_bool. + CATCH cx_root. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + rs_metadata-version = 'v2.0.0'. + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = zif_abapgit_object~exists( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. +* looks like there is no enqueue lock +* E_ARS_API ? + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " todo + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA lr_data TYPE REF TO data. + FIELD-SYMBOLS TYPE any. + + CREATE DATA lr_data TYPE (c_model). + ASSIGN lr_data->* TO . + + initialize( ). + + CALL METHOD mo_handler->('IF_ARS_API_ABAPGIT~GET_API_STATE') + RECEIVING + rs_apis_object = . + + io_xml->add( iv_name = 'APIS' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_amsd IMPLEMENTATION. + METHOD clear_field. + + FIELD-SYMBOLS: TYPE data. + + ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_logical_db_schema + TO . + ASSERT sy-subrc = 0. + + CLEAR: . + + ENDMETHOD. + METHOD clear_fields. + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_AT' + CHANGING + cs_logical_db_schema = cs_logical_db_schema ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CREATED_BY' + CHANGING + cs_logical_db_schema = cs_logical_db_schema ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_AT' + CHANGING + cs_logical_db_schema = cs_logical_db_schema ). + + clear_field( + EXPORTING + iv_fieldname = 'METADATA-CHANGED_BY' + CHANGING + cs_logical_db_schema = cs_logical_db_schema ). + + ENDMETHOD. + METHOD constructor. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + mv_logical_db_schema_key = ms_item-obj_name. + + TRY. + CREATE DATA mr_logical_db_schema TYPE ('CL_AMDP_SCHEMA_OBJECT_DATA=>TY_OBJECT_DATA'). + CREATE OBJECT mi_persistence TYPE ('CL_AMDP_SCHEMA_OBJECT_PERSIST'). + + CATCH cx_sy_create_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD fill_metadata_from_db. + + DATA: + li_wb_object_operator TYPE REF TO object, + lr_logical_db_schema_old TYPE REF TO data. + + FIELD-SYMBOLS: + TYPE any, + TYPE xsddatetime_z, + TYPE syuname, + TYPE xsddatetime_z, + TYPE syuname. + + li_wb_object_operator = get_wb_object_operator( ). + + CREATE DATA lr_logical_db_schema_old TYPE ('CL_AMDP_SCHEMA_OBJECT_DATA=>TY_OBJECT_DATA'). + ASSIGN lr_logical_db_schema_old->* TO . + ASSERT sy-subrc = 0. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + data = . + + ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE cs_logical_db_schema + TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE cs_logical_db_schema + TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + = . + = . + + ENDMETHOD. + METHOD get_wb_object_operator. + + DATA: + ls_object_type TYPE wbobjtype, + lx_error TYPE REF TO cx_root. + + IF mi_wb_object_operator IS BOUND. + ri_wb_object_operator = mi_wb_object_operator. + ENDIF. + + ls_object_type-objtype_tr = 'AMSD'. + ls_object_type-subtype_wb = 'TYP'. + + TRY. + CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') + EXPORTING + object_type = ls_object_type + object_key = mv_logical_db_schema_key + RECEIVING + result = mi_wb_object_operator. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ri_wb_object_operator = mi_wb_object_operator. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: + li_wb_object_operator TYPE REF TO object, + li_object_data_model TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root. + + TRY. + li_wb_object_operator = get_wb_object_operator( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + IMPORTING + eo_object_data = li_object_data_model. + + rv_user = li_object_data_model->get_changed_by( ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: + li_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') + EXPORTING + transport_request = iv_transport. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + li_wb_object_operator TYPE REF TO object, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: + TYPE any. + + ASSIGN mr_logical_db_schema->* TO . + ASSERT sy-subrc = 0. + + io_xml->read( + EXPORTING + iv_name = 'AMSD' + CHANGING + cg_data = ). + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CREATE OBJECT li_object_data_model TYPE ('CL_AMDP_SCHEMA_OBJECT_DATA'). + + tadir_insert( iv_package ). + + IF zif_abapgit_object~exists( ) = abap_true. + + " We need to populate created_at, created_by, because otherwise update is not possible + fill_metadata_from_db( CHANGING cs_logical_db_schema = ). + li_object_data_model->set_data( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = li_object_data_model + transport_request = iv_transport. + + ELSE. + + li_object_data_model->set_data( ). + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') + EXPORTING + io_object_data = li_object_data_model + data_selection = 'P' " if_wb_object_data_selection_co=>c_properties + package = iv_package + transport_request = iv_transport. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') + EXPORTING + io_object_data = li_object_data_model + data_selection = 'D' " if_wb_object_data_selection_co=>c_data_content + transport_request = iv_transport. + + ENDIF. + + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~ACTIVATE'). + + corr_insert( iv_package ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + TRY. + mi_persistence->get( + p_object_key = mv_logical_db_schema_key + p_version = 'A' + p_existence_check_only = abap_true ). + rv_bool = abap_true. + + CATCH cx_swb_exception. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: + li_object_data_model TYPE REF TO if_wb_object_data_model, + lx_error TYPE REF TO cx_root, + li_wb_object_operator TYPE REF TO object. + + FIELD-SYMBOLS: + TYPE any. + + ASSIGN mr_logical_db_schema->* TO . + ASSERT sy-subrc = 0. + + li_wb_object_operator = get_wb_object_operator( ). + + TRY. + CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + version = 'A' + IMPORTING + data = + eo_object_data = li_object_data_model. + + clear_fields( CHANGING cs_logical_db_schema = ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + io_xml->add( + iv_name = 'AMSD' + ig_data = ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_aifc IMPLEMENTATION. + METHOD authorization_check. + DATA: lx_root TYPE REF TO cx_root. + + rv_success = abap_false. + TRY. + CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~AUTHORIZATION_CHECK') + RECEIVING + rv_success = rv_success. + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + ENDMETHOD. + METHOD clear_client. + DATA: + BEGIN OF ls_data_to_clear, + mandt TYPE sy-mandt, + client TYPE sy-mandt, + END OF ls_data_to_clear. + + FIELD-SYMBOLS: + TYPE any. + + LOOP AT ct_data ASSIGNING . + MOVE-CORRESPONDING ls_data_to_clear TO . + ENDLOOP. + ENDMETHOD. + METHOD compress_interface. + DATA: lx_root TYPE REF TO cx_root. + + TRY. + CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~COMPRESS_INTERFACE') + EXPORTING + is_ifkeys = is_ifkeys + RECEIVING + rv_success = rv_success. + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + ENDMETHOD. + METHOD constructor. + DATA: lx_exc_ref TYPE REF TO cx_sy_dyn_call_error. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + ms_icd_data_key = is_item-obj_name. + + TRY. + CALL METHOD ('/AIF/CL_ABAPGIT_AIFC_UTIL')=>('GET_INSTANCE') + RECEIVING + rr_abapgit_aifc_util = mo_abapgit_util. + + CATCH cx_sy_dyn_call_error INTO lx_exc_ref. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + ENDMETHOD. + METHOD execute_checks. + DATA ls_ifkeys TYPE ty_aif_key_s. + + DATA lr_tabledescr TYPE REF TO cl_abap_tabledescr. + DATA lr_structdescr TYPE REF TO cl_abap_structdescr. + DATA lr_table TYPE REF TO data. + FIELD-SYMBOLS TYPE STANDARD TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS: TYPE any. + + DATA: lx_root TYPE REF TO cx_root. + + lr_structdescr ?= cl_abap_typedescr=>describe_by_name( p_name = '/AIF/T_FINF' ). + lr_tabledescr = cl_abap_tabledescr=>create( p_line_type = lr_structdescr ). + + CREATE DATA lr_table TYPE HANDLE lr_tabledescr. + ASSIGN lr_table->* TO . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Field Symbol not assigned' ). + ENDIF. + + TRY. + io_xml->read( EXPORTING + iv_name = '/AIF/T_FINF' + CHANGING + cg_data = ). + + READ TABLE ASSIGNING INDEX 1. + IF sy-subrc = 0. + ASSIGN COMPONENT 'NS' OF STRUCTURE TO . + IF sy-subrc = 0. + ls_ifkeys-ns = . + ENDIF. + + ASSIGN COMPONENT 'IFNAME' OF STRUCTURE TO . + IF sy-subrc = 0. + ls_ifkeys-ifname = . + ENDIF. + + ASSIGN COMPONENT 'IFVERSION' OF STRUCTURE TO . + IF sy-subrc = 0. + ls_ifkeys-ifver = . + ENDIF. + + CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~EXECUTE_CHECKS') + EXPORTING + is_ifkeys = ls_ifkeys + is_finf = + RECEIVING + rv_success = rv_success. + ENDIF. + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + ENDMETHOD. + METHOD get_content_compress. + DATA: lx_root TYPE REF TO cx_root. + DATA: lo_log TYPE REF TO object. + + TRY. + CREATE OBJECT lo_log TYPE ('/AIF/CL_ABAPGIT_BAL_LOG') + EXPORTING ir_git_log = io_log + is_item = ms_item. + + CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~INITIALIZE_CONTENT_COMPRESS') + EXPORTING + ir_bal = lo_log + is_ifkey = is_ifkeys + iv_package = iv_package + iv_depl_id = ms_icd_data_key-depl_scenario. + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + ENDMETHOD. + METHOD handle_table_data. + DATA: lx_root TYPE REF TO cx_root. + + TRY. + CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~HANDLE_TABLE_DATA') + EXPORTING + iv_tabname = iv_tabname + it_data = it_data. + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + ENDMETHOD. + METHOD validate_interface. + DATA: lx_root TYPE REF TO cx_root. + + rv_success = abap_false. + TRY. + CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~VALIDATE_INTERFACE') + EXPORTING + is_ifkeys = is_ifkeys + RECEIVING + rv_success = rv_success. + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + DATA ls_icd_data_key TYPE ty_icd_data_key. + ls_icd_data_key-depl_scenario = ms_icd_data_key-depl_scenario. + ls_icd_data_key-ns = ms_icd_data_key-ns. + ls_icd_data_key-ifname = ms_icd_data_key-ifname. + ls_icd_data_key-ifver2 = ms_icd_data_key-ifver2. + + CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~CHANGED_BY') + EXPORTING + is_key = ls_icd_data_key + RECEIVING + rv_user = rv_user. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + zcx_abapgit_exception=>raise( 'Delete not supported.' ). + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + DATA: lx_root TYPE REF TO cx_root. + DATA: lt_content TYPE ty_content_t. + + DATA lr_tabledescr TYPE REF TO cl_abap_tabledescr. + DATA lr_structdescr TYPE REF TO cl_abap_structdescr. + DATA lr_table TYPE REF TO data. + FIELD-SYMBOLS TYPE STANDARD TABLE. + FIELD-SYMBOLS TYPE any. + + DATA ls_ifkey TYPE ty_aif_key_s. + DATA lr_content TYPE REF TO ty_content_s. + + DATA lx_abap_not_a_table TYPE REF TO cx_abap_not_a_table. + + DATA lv_tablename TYPE string. + FIELD-SYMBOLS: TYPE any. + + IF iv_step <> zif_abapgit_object=>gc_step_id-abap. + RETURN. + ENDIF. + + TRY. + IF execute_checks( io_xml ) = abap_false. + zcx_abapgit_exception=>raise( 'AIF interface checks failed' ). + ENDIF. + + io_xml->read( EXPORTING + iv_name = `Content_table` + CHANGING + cg_data = lt_content ). + LOOP AT lt_content REFERENCE INTO lr_content. + TRY. + lv_tablename = cl_abap_dyn_prg=>check_table_name_str( val = lr_content->tabname + packages = '' ). + CATCH cx_abap_not_a_table INTO lx_abap_not_a_table. + zcx_abapgit_exception=>raise_with_text( lx_abap_not_a_table ). + CATCH cx_abap_not_in_package ##NO_HANDLER. + "that's fine + ENDTRY. + + CLEAR lr_tabledescr. + lr_structdescr ?= cl_abap_typedescr=>describe_by_name( p_name = lr_content->tabname ). + lr_tabledescr = cl_abap_tabledescr=>create( p_line_type = lr_structdescr ). + + CREATE DATA lr_table TYPE HANDLE lr_tabledescr. + ASSIGN lr_table->* TO . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Field Symbol not assigned' ). + ENDIF. + + io_xml->read( EXPORTING + iv_name = lr_content->tabname + CHANGING + cg_data = ). + + handle_table_data( iv_tabname = lr_content->tabname + it_data = ). + + IF lr_content->tabname = '/AIF/T_FINF'. + READ TABLE ASSIGNING INDEX 1. + + ASSIGN COMPONENT 'NS' OF STRUCTURE TO . + IF IS ASSIGNED. + ls_ifkey-ns = . + UNASSIGN . + ENDIF. + + ASSIGN COMPONENT 'IFNAME' OF STRUCTURE TO . + IF IS ASSIGNED. + ls_ifkey-ifname = . + UNASSIGN . + ENDIF. + + ASSIGN COMPONENT 'IFVERSION' OF STRUCTURE TO . + IF IS ASSIGNED. + ls_ifkey-ifver = . + UNASSIGN . + ENDIF. + ENDIF. + + ENDLOOP. + + IF ls_ifkey IS INITIAL. + RETURN. + ENDIF. + + get_content_compress( io_log = ii_log + is_ifkeys = ls_ifkey + iv_package = iv_package ). + IF authorization_check( ) = abap_false. + RETURN. + ENDIF. + + IF validate_interface( ls_ifkey ) = abap_false. + RETURN. + ENDIF. + + IF compress_interface( ls_ifkey ) = abap_false. + RETURN. + ENDIF. + + CATCH cx_root INTO lx_root. + ii_log->add_exception( ix_exc = lx_root + is_item = ms_item ). + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_object~exists. + DATA ls_icd_data_key TYPE ty_icd_data_key. + + ls_icd_data_key-depl_scenario = ms_icd_data_key-depl_scenario. + ls_icd_data_key-ns = ms_icd_data_key-ns. + ls_icd_data_key-ifname = ms_icd_data_key-ifname. + ls_icd_data_key-ifver2 = ms_icd_data_key-ifver2. + + rv_bool = abap_false. + + CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~EXISTS') + EXPORTING + is_key = ls_icd_data_key + RECEIVING + rv_bool = rv_bool. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = abap_false. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + rv_active = abap_true. + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + rv_is_locked = abap_false. + ENDMETHOD. + METHOD zif_abapgit_object~jump. + TYPES: ty_rsparamsl_255_t TYPE STANDARD TABLE OF rsparamsl_255 WITH NON-UNIQUE DEFAULT KEY. + + DATA lv_report TYPE progname VALUE '/AIF/CONTENT_DISPLAY'. + DATA lt_params TYPE ty_rsparamsl_255_t. + DATA ls_param LIKE LINE OF lt_params. + + ls_param-selname = 'P_DEPL'. + ls_param-kind = 'P'. + ls_param-sign = 'I'. + ls_param-option = 'EQ'. + ls_param-low = ms_icd_data_key-depl_scenario. + APPEND ls_param TO lt_params. + + SUBMIT (lv_report) WITH SELECTION-TABLE lt_params AND RETURN. + + rv_exit = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + DATA lx_root TYPE REF TO cx_root. + DATA ls_icd_data_key TYPE ty_icd_data_key. + DATA lt_ifdata TYPE ty_table_data_t. + + DATA lr_data TYPE REF TO data. + FIELD-SYMBOLS TYPE any. + + DATA lt_content TYPE ty_content_t. + DATA ls_content TYPE ty_content_s. + DATA lr_ifdata TYPE REF TO ty_table_data_s. + FIELD-SYMBOLS TYPE ANY TABLE. + + TRY. + + ASSIGN lr_data TO . + IF NOT IS ASSIGNED. + RETURN. + ENDIF. + + ls_icd_data_key-depl_scenario = ms_icd_data_key-depl_scenario. + ls_icd_data_key-ns = ms_icd_data_key-ns. + ls_icd_data_key-ifname = ms_icd_data_key-ifname. + ls_icd_data_key-ifver2 = ms_icd_data_key-ifver2. + + CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~GET_IF_DATA') + EXPORTING + is_key = ls_icd_data_key + RECEIVING + rt_ifdata = lt_ifdata. + + LOOP AT lt_ifdata REFERENCE INTO lr_ifdata. + + UNASSIGN . + ASSIGN lr_ifdata->table_data->* TO . + IF IS NOT ASSIGNED. + CONTINUE. + ENDIF. + + clear_client( CHANGING ct_data = ). + + io_xml->add( iv_name = lr_ifdata->tabname + ig_data = ). + + ls_content-tabname = lr_ifdata->tabname. + APPEND ls_content TO lt_content. + + ENDLOOP. + + io_xml->add( iv_name = `Content_table` + ig_data = lt_content ). + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise( iv_text = 'Serialize not possible' + ix_previous = lx_root ). + ENDTRY. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_acid IMPLEMENTATION. + METHOD create_object. + + DATA: lv_name TYPE aab_id_name. + lv_name = ms_item-obj_name. + + CREATE OBJECT ro_aab + EXPORTING + im_name = lv_name + EXCEPTIONS + name_not_allowed = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. +* looks like "changed by user" is not stored in the database + rv_user = c_user_unknown. + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lo_aab TYPE REF TO cl_aab_id. + lo_aab = create_object( ). + lo_aab->enqueue( + EXCEPTIONS + foreign_lock = 1 + system_error = 2 + cts_error = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + lo_aab->delete( + EXCEPTIONS + prop_error = 1 + propt_error = 2 + act_error = 3 + cts_error = 4 + cts_devclass = 5 + id_not_found = 6 + no_authorization = 7 + id_still_used = 8 + where_used_error = 9 + OTHERS = 10 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + lo_aab->dequeue( ). + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_description TYPE aab_id_descript, + lo_aab TYPE REF TO cl_aab_id. + io_xml->read( EXPORTING iv_name = 'DESCRIPTION' + CHANGING cg_data = lv_description ). + + lo_aab = create_object( ). + + lo_aab->enqueue( + EXCEPTIONS + foreign_lock = 1 + system_error = 2 + cts_error = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + lo_aab->set_descript( + EXPORTING + im_descript = lv_description + EXCEPTIONS + no_authorization = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + tadir_insert( iv_package ). + + lo_aab->save( + EXCEPTIONS + no_descript_specified = 1 + no_changes_found = 2 + prop_error = 3 + propt_error = 4 + act_error = 5 + cts_error = 6 + sync_attributes_error = 7 + action_canceled = 8 + OTHERS = 9 ). + IF sy-subrc >= 3. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + lo_aab->dequeue( ). + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA: lv_state TYPE abap_bool, + lo_aab TYPE REF TO cl_aab_id. + lo_aab = create_object( ). + + lo_aab->get_state( IMPORTING ex_state = lv_state ). + rv_bool = boolc( lv_state = abap_true ). + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = abap_false. + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lo_aab TYPE REF TO cl_aab_id, + lv_description TYPE aab_id_descript. + IF zif_abapgit_object~exists( ) = abap_false. + RETURN. + ENDIF. + + lo_aab = create_object( ). + + lo_aab->get_descript( + IMPORTING ex_descript = lv_description + EXCEPTIONS no_description_found = 1 ). + + io_xml->add( iv_name = 'DESCRIPTION' + ig_data = lv_description ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_SOTS_HANDLER IMPLEMENTATION. + METHOD create_sots. + + DATA: + lt_sots TYPE ty_sots_tt, + lt_sots_use TYPE ty_sots_use_tt. + + io_xml->read( EXPORTING iv_name = 'SOTS' + CHANGING cg_data = lt_sots ). + io_xml->read( EXPORTING iv_name = 'SOTS_USE' + CHANGING cg_data = lt_sots_use ). + + create_sots_from_data( + iv_package = iv_package + it_sots = lt_sots + it_sots_use = lt_sots_use ). + + ENDMETHOD. + METHOD create_sots_from_data. + + DATA: + lt_objects TYPE sotr_objects, + lv_object LIKE LINE OF lt_objects, + lv_subrc TYPE sy-subrc, + ls_header TYPE btfr_head, + lt_text_tab TYPE sotr_text_tt, + lt_string_tab TYPE sotr_textl_tt, + ls_entry LIKE LINE OF lt_string_tab, + lv_concept TYPE sotr_conc, + lv_concept_default TYPE sotr_conc. + + FIELD-SYMBOLS LIKE LINE OF it_sots. + + LOOP AT it_sots ASSIGNING . + + CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' + EXPORTING + object_vector = -header-objid_vec + IMPORTING + objects = lt_objects + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + READ TABLE lt_objects INDEX 1 INTO lv_object. + ASSERT sy-subrc = 0. + + " Reimplementation of SOTR_STRING_CREATE_CONCEPT because we can't supply + " concept and it would then be generated. + + LOOP AT -entries INTO ls_entry. + ls_entry-langu = -header-crea_lan. + ls_entry-concept = -header-concept. + INSERT ls_entry INTO TABLE lt_string_tab. + ENDLOOP. + + MOVE-CORRESPONDING -header TO ls_header. + ls_header-paket = iv_package. + + lv_concept = -header-concept. + + PERFORM btfr_create IN PROGRAM saplsotr_db_string + USING lv_object + sy-langu + abap_false + abap_true + CHANGING lt_text_tab + lt_string_tab + ls_header + lv_concept + lv_concept_default + lv_subrc. + + CASE lv_subrc. + WHEN 1. + MESSAGE e100(sotr_mess) INTO zcx_abapgit_exception=>null. + WHEN 2. + MESSAGE e101(sotr_mess) INTO zcx_abapgit_exception=>null. + WHEN 3. + MESSAGE i305(sotr_mess) INTO zcx_abapgit_exception=>null. + WHEN 4. + " The concept will be created in the non-original system (not an error) + WHEN 5. + MESSAGE e504(sotr_mess) INTO zcx_abapgit_exception=>null. + WHEN 6. + MESSAGE e035(sotr_mess) INTO zcx_abapgit_exception=>null. + WHEN 7. + MESSAGE e170(sotr_mess) INTO zcx_abapgit_exception=>null. + WHEN 9. + MESSAGE e102(sotr_mess) INTO zcx_abapgit_exception=>null. + ENDCASE. + + IF lv_subrc <> 0 AND lv_subrc <> 4. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDLOOP. + + CALL FUNCTION 'SOTR_USAGE_STRING_MODIFY' + EXPORTING + sotr_usage = it_sots_use. + + ENDMETHOD. + METHOD delete_sots. + + DATA lt_sots_use TYPE ty_sots_use_tt. + + FIELD-SYMBOLS LIKE LINE OF lt_sots_use. + + lt_sots_use = get_sots_usage( iv_pgmid = iv_pgmid + iv_object = iv_object + iv_obj_name = iv_obj_name ). + + " Remove any usage to ensure deletion, see function module BTFR_CHECK + DELETE sotr_useu FROM TABLE lt_sots_use ##SUBRC_OK. + + LOOP AT lt_sots_use ASSIGNING WHERE concept IS NOT INITIAL. + + CALL FUNCTION 'BTFR_DELETE_SINGLE_TEXT' + EXPORTING + concept = -concept + flag_string = abap_true + EXCEPTIONS + text_not_found = 1 "ok + invalid_package = 3 + text_not_changeable = 4 + text_enqueued = 5 + no_correction = 6 + parameter_error = 7 + OTHERS = 8. + IF sy-subrc > 2. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD get_sots_4_concept. + + DATA: ls_header TYPE ty_sots-header, + lt_entries TYPE ty_sots-entries. + + FIELD-SYMBOLS LIKE LINE OF lt_entries. + + CALL FUNCTION 'SOTR_STRING_GET_CONCEPT' + EXPORTING + concept = iv_concept + IMPORTING + header = ls_header + entries = lt_entries + EXCEPTIONS + no_entry_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + CLEAR: ls_header-paket, + ls_header-crea_name, + ls_header-crea_tstut, + ls_header-chan_name, + ls_header-chan_tstut, + ls_header-system_id. + + LOOP AT lt_entries ASSIGNING . + CLEAR: -version, + -crea_name, + -crea_tstut, + -chan_name, + -chan_tstut. + ENDLOOP. + + rs_sots-header = ls_header. + rs_sots-entries = lt_entries. + + ENDMETHOD. + METHOD get_sots_usage. + + DATA: lv_obj_name TYPE trobj_name. + + lv_obj_name = iv_obj_name. + + " Objects with multiple components + IF iv_pgmid = 'LIMU' AND ( iv_object CP 'WDY*' OR iv_object = 'WAPP' ). + lv_obj_name+30 = '%'. + ENDIF. + + CALL FUNCTION 'SOTR_USAGE_STRING_READ' + EXPORTING + pgmid = iv_pgmid + object = iv_object + obj_name = lv_obj_name + IMPORTING + sotr_usage = rt_sots_use + EXCEPTIONS + no_entry_found = 1 + error_in_pgmid = 2 + OTHERS = 3. + IF sy-subrc = 0. + SORT rt_sots_use. + ENDIF. + + ENDMETHOD. + METHOD read_sots. + + FIELD-SYMBOLS LIKE LINE OF et_sots_use. + + DATA ls_sots TYPE ty_sots. + + " OTR long text (string) usage: see TABLE BTFR_OBJ_IDS + " LIMU: CPUB, WAPP + " R3TR: ENHO, ENHS, SICF, SMIF, WEBI, XSLT + + et_sots_use = get_sots_usage( iv_pgmid = iv_pgmid + iv_object = iv_object + iv_obj_name = iv_obj_name ). + + LOOP AT et_sots_use ASSIGNING WHERE concept IS NOT INITIAL. + ls_sots = get_sots_4_concept( -concept ). + + IF io_i18n_params->ms_params-main_language_only = abap_true. + DELETE ls_sots-entries WHERE langu <> io_i18n_params->ms_params-main_language. + CHECK ls_sots-entries IS NOT INITIAL. + ENDIF. + + INSERT ls_sots INTO TABLE et_sots. + ENDLOOP. + + IF io_xml IS BOUND. + io_xml->add( iv_name = 'SOTS' + ig_data = et_sots ). + io_xml->add( iv_name = 'SOTS_USE' + ig_data = et_sots_use ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_sotr_handler IMPLEMENTATION. + METHOD change_sotr_package. + + DATA lt_concepts TYPE btfr_conc_tt. + + " Short texts + SELECT concept FROM sotr_head INTO TABLE lt_concepts + WHERE paket = iv_old_package + ORDER BY PRIMARY KEY. + + IF lt_concepts IS NOT INITIAL. + CALL FUNCTION 'BTFR_CHANGE_PACKAGE' + EXPORTING + concept_tab = lt_concepts + new_package = iv_new_package + flag_string = abap_false + flag_ignore_system = abap_true + EXCEPTIONS + invalid_package = 1 + invalid_tadir_entry = 2 + update_error = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + CLEAR lt_concepts. + + " Long texts + SELECT concept FROM sotr_headu INTO TABLE lt_concepts + WHERE paket = iv_old_package + ORDER BY PRIMARY KEY. + + IF lt_concepts IS NOT INITIAL. + CALL FUNCTION 'BTFR_CHANGE_PACKAGE' + EXPORTING + concept_tab = lt_concepts + new_package = iv_new_package + flag_string = abap_true + flag_ignore_system = abap_true + EXCEPTIONS + invalid_package = 1 + invalid_tadir_entry = 2 + update_error = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD create_sotr. + + DATA: + lt_sotr TYPE ty_sotr_tt, + lt_sotr_use TYPE ty_sotr_use_tt. + + io_xml->read( EXPORTING iv_name = 'SOTR' + CHANGING cg_data = lt_sotr ). + io_xml->read( EXPORTING iv_name = 'SOTR_USE' + CHANGING cg_data = lt_sotr_use ). + + create_sotr_from_data( + iv_package = iv_package + it_sotr = lt_sotr + it_sotr_use = lt_sotr_use ). + + ENDMETHOD. + METHOD create_sotr_from_data. + + DATA: + lt_objects TYPE sotr_objects, + ls_paket TYPE sotr_pack, + lv_alias TYPE sotr_head-alias_name, + lv_object LIKE LINE OF lt_objects. + + FIELD-SYMBOLS: LIKE LINE OF it_sotr. + + LOOP AT it_sotr ASSIGNING . + CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' + EXPORTING + object_vector = -header-objid_vec + IMPORTING + objects = lt_objects + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + READ TABLE lt_objects INDEX 1 INTO lv_object. + ASSERT sy-subrc = 0. + + ls_paket-paket = iv_package. + + " Replace package in alias with new package + lv_alias = -header-alias_name. + IF lv_alias CS '/'. + lv_alias = iv_package && lv_alias+sy-fdpos(*). + ENDIF. + + CALL FUNCTION 'SOTR_CREATE_CONCEPT' + EXPORTING + paket = ls_paket + crea_lan = -header-crea_lan + alias_name = lv_alias + object = lv_object + entries = -entries + concept_default = -header-concept + EXCEPTIONS + package_missing = 1 + crea_lan_missing = 2 + object_missing = 3 + paket_does_not_exist = 4 + alias_already_exist = 5 + object_type_not_found = 6 + langu_missing = 7 + identical_context_not_allowed = 8 + text_too_long = 9 + error_in_update = 10 + no_master_langu = 11 + error_in_concept_id = 12 + alias_not_allowed = 13 + tadir_entry_creation_failed = 14 + internal_error = 15 + error_in_correction = 16 + user_cancelled = 17 + no_entry_found = 18 + OTHERS = 19. + IF sy-subrc <> 0 AND sy-subrc <> 5. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDLOOP. + + CALL FUNCTION 'SOTR_USAGE_MODIFY' + EXPORTING + sotr_usage = it_sotr_use. + + ENDMETHOD. + METHOD delete_sotr. + + DATA lt_sotr_use TYPE ty_sotr_use_tt. + + FIELD-SYMBOLS LIKE LINE OF lt_sotr_use. + + lt_sotr_use = get_sotr_usage( iv_pgmid = iv_pgmid + iv_object = iv_object + iv_obj_name = iv_obj_name ). + + " Remove any usage to ensure deletion, see function module BTFR_CHECK + DELETE sotr_use FROM TABLE lt_sotr_use ##SUBRC_OK. + + LOOP AT lt_sotr_use ASSIGNING WHERE concept IS NOT INITIAL. + + CALL FUNCTION 'SOTR_DELETE_CONCEPT' + EXPORTING + concept = -concept + EXCEPTIONS + no_entry_found = 1 + text_not_found = 2 + invalid_package = 3 + text_not_changeable = 4 + text_enqueued = 5 + no_correction = 6 + parameter_error = 7 + OTHERS = 8. + IF sy-subrc > 2. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD delete_sotr_package. + + DATA lt_sotr_head TYPE STANDARD TABLE OF sotr_head WITH DEFAULT KEY. + DATA lv_obj_name TYPE tadir-obj_name. + + FIELD-SYMBOLS LIKE LINE OF lt_sotr_head. + + SELECT * FROM sotr_head INTO TABLE lt_sotr_head WHERE paket = iv_package ORDER BY PRIMARY KEY. + + LOOP AT lt_sotr_head ASSIGNING WHERE concept IS NOT INITIAL. + + CALL FUNCTION 'SOTR_DELETE_CONCEPT' + EXPORTING + concept = -concept + EXCEPTIONS + no_entry_found = 1 + text_not_found = 2 + invalid_package = 3 + text_not_changeable = 4 + text_enqueued = 5 + no_correction = 6 + parameter_error = 7 + OTHERS = 8. + IF sy-subrc > 2. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDLOOP. + + " Nothing left, then delete SOTR from TADIR + SELECT * FROM sotr_head INTO TABLE lt_sotr_head WHERE paket = iv_package ORDER BY PRIMARY KEY. + IF sy-subrc <> 0. + SELECT SINGLE obj_name FROM tadir INTO lv_obj_name + WHERE pgmid = 'R3TR' AND object = 'SOTR' AND obj_name = iv_package. + IF sy-subrc = 0. + zcl_abapgit_factory=>get_tadir( )->delete_single( + iv_object = 'SOTR' + iv_obj_name = lv_obj_name ). + + IF zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ) = abap_true. + + zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( + iv_object = 'SOTR' + iv_obj_name = lv_obj_name + iv_package = iv_package + iv_mode = zif_abapgit_cts_api=>c_transport_mode-delete ). + + ENDIF. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD get_sotr_4_concept. + + DATA: ls_header TYPE ty_sotr-header, + lv_paket LIKE ls_header-alias_name, + lt_entries TYPE ty_sotr-entries. + + FIELD-SYMBOLS: LIKE LINE OF lt_entries. + + CALL FUNCTION 'SOTR_GET_CONCEPT' + EXPORTING + concept = iv_concept + IMPORTING + header = ls_header + TABLES + entries = lt_entries + EXCEPTIONS + no_entry_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + " If alias contains package, remove it + lv_paket = ls_header-paket && '/'. + IF ls_header-alias_name CS lv_paket. + ls_header-alias_name = replace( + val = ls_header-alias_name + sub = lv_paket + with = '/' + occ = 1 ). + ENDIF. + + CLEAR: ls_header-paket, + ls_header-crea_name, + ls_header-crea_tstut, + ls_header-chan_name, + ls_header-chan_tstut, + ls_header-system_id. + + LOOP AT lt_entries ASSIGNING . + CLEAR: -version, + -crea_name, + -crea_tstut, + -chan_name, + -chan_tstut. + ENDLOOP. + + rs_sotr-header = ls_header. + rs_sotr-entries = lt_entries. + + ENDMETHOD. + METHOD get_sotr_usage. + + DATA: lv_obj_name TYPE trobj_name. + + lv_obj_name = iv_obj_name. + + " Objects with multiple components + IF iv_pgmid = 'LIMU' AND ( iv_object CP 'WDY*' OR iv_object = 'WAPP' ). + lv_obj_name+30 = '%'. + ENDIF. + + CALL FUNCTION 'SOTR_USAGE_READ' + EXPORTING + pgmid = iv_pgmid + object = iv_object + obj_name = lv_obj_name + IMPORTING + sotr_usage = rt_sotr_use + EXCEPTIONS + no_entry_found = 1 + error_in_pgmid = 2 + OTHERS = 3. + IF sy-subrc = 0. + SORT rt_sotr_use. + ENDIF. + + ENDMETHOD. + METHOD read_sotr. + + FIELD-SYMBOLS LIKE LINE OF et_sotr_use. + + DATA: lv_sotr TYPE ty_sotr, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + " OTR short text usage: see TABLE BTFR_OBJ_IDS + " LIMU: CPUB, WAPP, WDYC, WDYD, WDYV + " R3TR: ENHC, ENHO, ENHS, ENSC, SCGR, SMIF, WDCA, WDCC, WEBI, WEBS + + et_sotr_use = get_sotr_usage( iv_pgmid = iv_pgmid + iv_object = iv_object + iv_obj_name = iv_obj_name ). + + LOOP AT et_sotr_use ASSIGNING WHERE concept IS NOT INITIAL. + lv_sotr = get_sotr_4_concept( -concept ). + + IF io_xml IS BOUND AND io_i18n_params->ms_params-main_language_only = abap_true. + DELETE lv_sotr-entries WHERE langu <> io_i18n_params->ms_params-main_language. + CHECK lv_sotr-entries IS NOT INITIAL. + ENDIF. + lt_language_filter = io_i18n_params->build_language_filter( ). + DELETE lv_sotr-entries WHERE NOT langu IN lt_language_filter + AND langu <> io_i18n_params->ms_params-main_language. + CHECK lv_sotr-entries IS NOT INITIAL. + + INSERT lv_sotr INTO TABLE et_sotr. + ENDLOOP. + + IF io_xml IS BOUND. + io_xml->add( iv_name = 'SOTR' + ig_data = et_sotr ). + io_xml->add( iv_name = 'SOTR_USE' + ig_data = et_sotr_use ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_PROPERTIES_FILE IMPLEMENTATION. + METHOD constructor. + mv_lang = to_upper( iv_lang ). + ENDMETHOD. + METHOD get_translations. + + DATA: + lv_translation TYPE string, + lo_ajson TYPE REF TO zif_abapgit_ajson, + lo_json_path TYPE REF TO zcl_abapgit_json_path, + lx_exception TYPE REF TO cx_static_check. + + CREATE OBJECT lo_json_path. + + TRY. + lv_translation = lo_json_path->deserialize( mt_translation ). + + lo_ajson = zcl_abapgit_ajson=>parse( lv_translation + )->map( zcl_abapgit_ajson_mapping=>create_to_snake_case( ) ). + + lo_ajson->to_abap( IMPORTING ev_container = ev_data ). + + CATCH cx_static_check INTO lx_exception. + zcx_abapgit_exception=>raise_with_text( lx_exception ). + ENDTRY. + + ENDMETHOD. + METHOD parse. + + DATA lv_data TYPE string. + + lv_data = zcl_abapgit_convert=>xstring_to_string_utf8( iv_xdata ). + + SPLIT lv_data AT cl_abap_char_utilities=>newline INTO TABLE mt_translation. + + ENDMETHOD. + METHOD push_text_pairs. + mt_translation = it_translation. + ENDMETHOD. + METHOD zif_abapgit_i18n_file~ext. + rv_ext = 'properties'. + ENDMETHOD. + METHOD zif_abapgit_i18n_file~lang. + rv_lang = mv_lang. + ENDMETHOD. + METHOD zif_abapgit_i18n_file~lang_suffix. + + DATA: lv_langu_sap1 TYPE sy-langu, + lv_langu_bcp47 TYPE string. + + lv_langu_sap1 = zcl_abapgit_convert=>language_sap2_to_sap1( to_upper( mv_lang ) ). + lv_langu_bcp47 = zcl_abapgit_convert=>language_sap1_to_bcp47( lv_langu_sap1 ). + + rv_lang_suffix = lv_langu_bcp47. + + ENDMETHOD. + METHOD zif_abapgit_i18n_file~render. + + DATA lv_translation TYPE string. + + lv_translation = concat_lines_of( table = mt_translation + sep = cl_abap_char_utilities=>newline ) && cl_abap_char_utilities=>newline. + rv_data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_translation ). + + ENDMETHOD. + METHOD zif_abapgit_i18n_file~translate. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_PO_FILE IMPLEMENTATION. + METHOD build_po_body. + + FIELD-SYMBOLS LIKE LINE OF mt_pairs. + FIELD-SYMBOLS LIKE LINE OF -comments. + + CREATE OBJECT ro_buf. + + LOOP AT mt_pairs ASSIGNING . + IF sy-tabix <> 1. + ro_buf->add( '' ). + ENDIF. + + " TODO integrate translator comments ? + + SORT -comments BY kind. + LOOP AT -comments ASSIGNING . + ro_buf->add( |#{ get_comment_marker( -kind ) } { -text }| ). + ENDLOOP. + + ro_buf->add( |msgid { quote( -source ) }| ). + ro_buf->add( |msgstr { quote( -target ) }| ). + ENDLOOP. + + ENDMETHOD. + METHOD build_po_head. + + CREATE OBJECT ro_buf. + + " TODO, more headers ? sample: https://www.gnu.org/software/trans-coord/manual/gnun/html_node/PO-Header.html + " TODO, does \n really necessary ? check editors support for non-\n + " TODO, should be unfuzzy for final version, and potentially should have more fields + + ro_buf->add( '#, fuzzy' ). + ro_buf->add( 'msgid ""' ). + ro_buf->add( 'msgstr ""' ). + ro_buf->add( '"MIME-Version: 1.0\n"' ). + ro_buf->add( '"Content-Type: text/plain; charset=UTF-8\n"' ). + ro_buf->add( '"Content-Transfer-Encoding: 8bit\n"' ). + ro_buf->add( '' ). + + ENDMETHOD. + METHOD constructor. + mv_lang = to_lower( iv_lang ). + mv_suppress_comments = iv_suppress_comments. + ENDMETHOD. + METHOD get_comment_marker. + CASE iv_comment_kind. + WHEN c_comment-translator. + rv_marker = ''. + WHEN c_comment-extracted. + rv_marker = '.'. + WHEN c_comment-reference. + rv_marker = ':'. + WHEN c_comment-flag. + rv_marker = ','. + WHEN c_comment-previous. + rv_marker = '|'. + ENDCASE. + ENDMETHOD. + METHOD parse. + + DATA lv_xdata TYPE xstring. + DATA lv_data TYPE string. + + IF xstrlen( iv_xdata ) > 3 AND iv_xdata(3) = cl_abap_char_utilities=>byte_order_mark_utf8. + lv_xdata = iv_xdata+3. + ELSE. + lv_xdata = iv_xdata. + ENDIF. + + lv_data = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xdata ). + + parse_po( lv_data ). + + ENDMETHOD. + METHOD parse_po. + + CONSTANTS: + BEGIN OF c_state, + wait_id TYPE i VALUE 0, + wait_str TYPE i VALUE 1, + wait_eos TYPE i VALUE 2, + " TODO msgctx + END OF c_state. + + DATA lv_state TYPE i VALUE c_state-wait_id. + DATA lt_lines TYPE string_table. + DATA ls_pair LIKE LINE OF mt_pairs. + DATA lv_whitespace TYPE c LENGTH 2. + FIELD-SYMBOLS TYPE string. + + lv_whitespace = ` ` && cl_abap_char_utilities=>horizontal_tab. + + SPLIT iv_data AT cl_abap_char_utilities=>newline INTO TABLE lt_lines. + APPEND '' TO lt_lines. " terminator + + LOOP AT lt_lines ASSIGNING . + IF lv_state = c_state-wait_eos. + IF strlen( ) >= 1 AND +0(1) = '"'. + ls_pair-target = ls_pair-target && unquote( ). + CONTINUE. + ELSE. + lv_state = c_state-wait_id. + IF ls_pair-source IS NOT INITIAL. " skip header entry for now + INSERT ls_pair INTO TABLE mt_pairs. " Sorted, duplicates will not be inserted + ENDIF. + CLEAR ls_pair. + ENDIF. + ENDIF. + + CASE lv_state. + WHEN c_state-wait_id. + IF IS INITIAL + OR +0(1) = '#' " TODO, potentially parse comments in future, to re-integrate + OR CO lv_whitespace. + CONTINUE. + ENDIF. + IF strlen( ) >= 6 AND +0(6) = `msgid `. " w/trailing space + ls_pair-source = unquote( substring( + val = + off = 6 ) ). + lv_state = c_state-wait_str. + ELSE. + zcx_abapgit_exception=>raise( 'PO file format error: expected msgid' ). + ENDIF. + + WHEN c_state-wait_str. + IF strlen( ) >= 7 AND +0(7) = `msgstr `. " w/trailing space + ls_pair-target = unquote( substring( + val = + off = 7 ) ). + lv_state = c_state-wait_eos. + ELSE. + zcx_abapgit_exception=>raise( 'PO file format error: expected msgstr' ). + ENDIF. + + ENDCASE. + ENDLOOP. + + ENDMETHOD. + METHOD push_text_pairs. + + DATA ls_out LIKE LINE OF mt_pairs. + FIELD-SYMBOLS LIKE LINE OF it_text_pairs. + FIELD-SYMBOLS LIKE LINE OF mt_pairs. + DATA ls_comment LIKE LINE OF -comments. + + LOOP AT it_text_pairs ASSIGNING . + CHECK -s_text IS NOT INITIAL. + + READ TABLE mt_pairs ASSIGNING WITH KEY source = -s_text. + IF sy-subrc <> 0. + ls_out-source = -s_text. + INSERT ls_out INTO TABLE mt_pairs ASSIGNING . + ASSERT sy-subrc = 0. + ENDIF. + + IF -target IS INITIAL. " For a case of orig text duplication + -target = -t_text. + ENDIF. + + IF mv_suppress_comments = abap_false. + ls_comment-kind = c_comment-reference. + ls_comment-text = condense( |{ iv_objtype }/{ iv_objname }/{ -textkey }| ) + && |, maxlen={ -unitmlt }|. + APPEND ls_comment TO -comments. + ASSERT sy-subrc = 0. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD quote. + rv_text = '"' && replace( + val = iv_text + sub = '"' + with = '\"' + occ = 0 ) && '"'. + ENDMETHOD. + METHOD unquote. + + DATA lv_len TYPE i. + DATA lv_prev_char TYPE i. + + rv_text = iv_text. + SHIFT rv_text RIGHT DELETING TRAILING space. " Measure perf ? Could be slowish, maybe use find + SHIFT rv_text LEFT DELETING LEADING space. + lv_len = strlen( rv_text ). + + IF lv_len < 2. + zcx_abapgit_exception=>raise( 'PO file format error: bad quoting' ). + ENDIF. + + lv_prev_char = lv_len - 1. + IF rv_text+0(1) <> '"' OR rv_text+lv_prev_char(1) <> '"'. + zcx_abapgit_exception=>raise( 'PO file format error: bad quoting' ). + ENDIF. + + lv_prev_char = lv_prev_char - 1. + IF lv_len >= 3 AND rv_text+lv_prev_char(1) = '\'. " escaped quote + zcx_abapgit_exception=>raise( 'PO file format error: bad quoting' ). + ENDIF. + + rv_text = substring( + val = rv_text + off = 1 + len = lv_len - 2 ). + + rv_text = replace( + val = rv_text + sub = '\"' + with = '"' + occ = 0 ). + + rv_text = replace( + val = rv_text + sub = '\n' + with = cl_abap_char_utilities=>newline + occ = 0 ). + + " TODO: theoretically there can be unescaped " - is it a problem ? check standard + + ENDMETHOD. + METHOD zif_abapgit_i18n_file~ext. + rv_ext = 'po'. + ENDMETHOD. + METHOD zif_abapgit_i18n_file~lang. + rv_lang = mv_lang. + ENDMETHOD. + METHOD zif_abapgit_i18n_file~lang_suffix. + rv_lang_suffix = mv_lang. + ENDMETHOD. + METHOD zif_abapgit_i18n_file~render. + + DATA lv_str TYPE string. + + lv_str = build_po_body( )->join_w_newline_and_flush( ). + + IF lv_str IS NOT INITIAL. + lv_str = build_po_head( )->join_w_newline_and_flush( ) + && cl_abap_char_utilities=>newline + && lv_str + && cl_abap_char_utilities=>newline. " Trailing LF + rv_data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_str ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_i18n_file~translate. + + FIELD-SYMBOLS LIKE LINE OF ct_text_pairs. + FIELD-SYMBOLS LIKE LINE OF mt_pairs. + DATA lv_idx TYPE i. + + LOOP AT ct_text_pairs ASSIGNING . + CHECK -s_text IS NOT INITIAL. + lv_idx = sy-tabix. + + READ TABLE mt_pairs ASSIGNING WITH KEY source = -s_text. + IF sy-subrc = 0 AND -target IS NOT INITIAL. + IF -t_text <> -target. + cv_changed = abap_true. + -t_text = -target. + ENDIF. + ELSE. + DELETE ct_text_pairs INDEX lv_idx. " Otherwise error in LXE FMs for empty translation + cv_changed = abap_true. + ENDIF. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_lxe_texts IMPLEMENTATION. + METHOD check_langs_versus_installed. + + DATA lt_installed_hash TYPE HASHED TABLE OF laiso WITH UNIQUE KEY table_line. + FIELD-SYMBOLS LIKE LINE OF it_languages. + + CLEAR: et_intersection, et_missfits. + lt_installed_hash = it_installed. + + LOOP AT it_languages ASSIGNING . + READ TABLE lt_installed_hash WITH KEY table_line = TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + APPEND TO et_intersection. + ELSE. + APPEND TO et_missfits. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD convert_lang_string_to_table. + + DATA: + lt_langs_str TYPE string_table, + lv_laiso TYPE laiso, + lv_skip_main_lang_iso TYPE laiso. + + FIELD-SYMBOLS: + LIKE LINE OF lt_langs_str. + + " Keep * as indicator for 'all installed languages' + IF iv_langs = '*'. + APPEND iv_langs TO rt_languages. + RETURN. + ENDIF. + + " Convert string of 2-letter ISO languages into table of sy-langu codes + SPLIT iv_langs AT ',' INTO TABLE lt_langs_str. + + LOOP AT lt_langs_str ASSIGNING . + lv_laiso = condense( to_upper( ) ). + APPEND lv_laiso TO rt_languages. + ENDLOOP. + + IF iv_skip_main_language IS NOT INITIAL. + lv_skip_main_lang_iso = langu_to_laiso_safe( iv_skip_main_language ). + DELETE rt_languages WHERE table_line = lv_skip_main_lang_iso. + ENDIF. + + SORT rt_languages. + DELETE ADJACENT DUPLICATES FROM rt_languages. + + ENDMETHOD. + METHOD convert_table_to_lang_string. + + DATA: + lt_langs_str TYPE string_table. + + FIELD-SYMBOLS: + LIKE LINE OF it_languages, + TYPE string. + + " Convert table of sy-langu codes into string of 2-letter ISO languages + LOOP AT it_languages ASSIGNING . + " Keep * as indicator for 'all installed languages' + IF = '*'. + CLEAR lt_langs_str. + APPEND '*' TO lt_langs_str. + EXIT. + ENDIF. + + APPEND INITIAL LINE TO lt_langs_str ASSIGNING . + = . + ENDLOOP. + + CONCATENATE LINES OF lt_langs_str INTO rv_langs SEPARATED BY ','. + + ENDMETHOD. + METHOD deserialize_from_po. + + DATA lv_lang LIKE LINE OF mo_i18n_params->ms_params-translation_languages. + DATA lt_po_files TYPE zif_abapgit_i18n_file=>ty_table_of. + DATA li_po LIKE LINE OF lt_po_files. + DATA lt_text_pairs_tmp TYPE ty_lxe_translation-text_pairs. + DATA lt_obj_list TYPE lxe_tt_colob. + DATA lv_main_lang TYPE lxeisolang. + DATA lv_target_lang TYPE lxeisolang. + DATA lv_changed TYPE abap_bool. + + FIELD-SYMBOLS LIKE LINE OF lt_obj_list. + + lt_obj_list = get_lxe_object_list( + iv_object_name = iv_object_name + iv_object_type = iv_object_type ). + + IF lt_obj_list IS INITIAL. + RETURN. + ENDIF. + + lt_po_files = mo_files->read_i18n_files( ). + lv_main_lang = get_lang_iso4( langu_to_laiso_safe( mo_i18n_params->ms_params-main_language ) ). + + LOOP AT mo_i18n_params->ms_params-translation_languages INTO lv_lang. + lv_target_lang = get_lang_iso4( lv_lang ). + + LOOP AT lt_po_files INTO li_po. + IF li_po->lang( ) = to_lower( lv_lang ). " Not quite efficient but the list is presumably very short + EXIT. + ELSE. + CLEAR li_po. + ENDIF. + ENDLOOP. + + CHECK li_po IS BOUND. " Ignore missing files, missing translation is not a crime + + LOOP AT lt_obj_list ASSIGNING . + + lt_text_pairs_tmp = read_lxe_object_text_pair( + iv_s_lang = lv_main_lang + iv_t_lang = lv_target_lang + iv_custmnr = -custmnr + iv_objtype = -objtype + iv_objname = -objname + iv_read_only = abap_false ). + + li_po->translate( + CHANGING + cv_changed = lv_changed + ct_text_pairs = lt_text_pairs_tmp ). + + IF lv_changed = abap_true AND lines( lt_text_pairs_tmp ) > 0. + " If lt_text_pairs_tmp is empty it raises error, while this is a practical case + write_lxe_object_text_pair( + iv_s_lang = lv_main_lang + iv_t_lang = lv_target_lang + iv_custmnr = -custmnr + iv_objtype = -objtype + iv_objname = -objname + it_pcx_s1 = lt_text_pairs_tmp ). + + rv_changed = abap_true. + ENDIF. + ENDLOOP. + + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_xml. + + DATA: + lt_lxe_texts TYPE ty_lxe_translations, + ls_lxe_item LIKE LINE OF lt_lxe_texts, + lt_text_pairs_tmp LIKE ls_lxe_item-text_pairs. + + mi_xml_in->read( + EXPORTING iv_name = iv_lxe_text_name + CHANGING cg_data = lt_lxe_texts ). + + LOOP AT lt_lxe_texts INTO ls_lxe_item. + " Call Read first for buffer prefill + + lt_text_pairs_tmp = read_lxe_object_text_pair( + iv_s_lang = ls_lxe_item-source_lang + iv_t_lang = ls_lxe_item-target_lang + iv_custmnr = ls_lxe_item-custmnr + iv_objtype = ls_lxe_item-objtype + iv_objname = ls_lxe_item-objname + iv_read_only = abap_false ). + + "Call actual Write FM + write_lxe_object_text_pair( + iv_s_lang = ls_lxe_item-source_lang + iv_t_lang = ls_lxe_item-target_lang + iv_custmnr = ls_lxe_item-custmnr + iv_objtype = ls_lxe_item-objtype + iv_objname = ls_lxe_item-objname + it_pcx_s1 = ls_lxe_item-text_pairs ). + + ENDLOOP. + + ENDMETHOD. + METHOD detect_unsupported_languages. + + check_langs_versus_installed( + EXPORTING + it_languages = it_languages + it_installed = get_installed_languages( ) + IMPORTING + et_missfits = rt_unsupported_languages ). + + ENDMETHOD. + METHOD get_installed_languages. + + DATA: + lv_index TYPE i, + lv_langu TYPE sy-langu, + lv_laiso TYPE laiso, + lv_installed_languages TYPE string, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + IF gt_installed_languages_cache IS INITIAL. + CALL FUNCTION 'SYSTEM_INSTALLED_LANGUAGES' + IMPORTING + languages = lv_installed_languages + EXCEPTIONS + sapgparam_error = 1 " Error requesting profile parameter + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Fail to get system SYSTEM_INSTALLED_LANGUAGES' ). + ENDIF. + + lt_language_filter = zcl_abapgit_factory=>get_environment( )->get_system_language_filter( ). + + DO strlen( lv_installed_languages ) TIMES. + lv_index = sy-index - 1. + lv_langu = lv_installed_languages+lv_index(1). + + IF lv_langu NOT IN lt_language_filter. + CONTINUE. + ENDIF. + + lv_laiso = langu_to_laiso_safe( lv_langu ). + APPEND lv_laiso TO gt_installed_languages_cache. + ENDDO. + ENDIF. + + rt_languages = gt_installed_languages_cache. + + ENDMETHOD. + METHOD get_lang_iso4. + + DATA ls_lang LIKE LINE OF gt_lxe_lang_cache. + DATA lt_lang TYPE STANDARD TABLE OF lxe_t002. + + FIELD-SYMBOLS LIKE LINE OF lt_lang. + + IF gt_lxe_lang_cache IS INITIAL. " Cache + + CALL FUNCTION 'LXE_T002_GET_LANGUAGES' + EXPORTING + r3_lang_only = abap_true + TABLES + lt_lang = lt_lang. + + LOOP AT lt_lang ASSIGNING . + CLEAR ls_lang. + ls_lang-language = -language. + ls_lang-r3_lang = -r3_lang. + IF ls_lang-language = 'zhTW'. + ls_lang-langshort = 'ZF'. + ELSE. + ls_lang-langshort = to_upper( -language ). + ENDIF. + INSERT ls_lang INTO TABLE gt_lxe_lang_cache. + ENDLOOP. + + ENDIF. + + READ TABLE gt_lxe_lang_cache INTO ls_lang WITH TABLE KEY iso2 COMPONENTS langshort = iv_src. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Failed to convert [{ iv_src }] lang to iso639| ). + ENDIF. + + rv_iso4 = ls_lang-language. + + ENDMETHOD. + METHOD get_lxe_object_list. + + DATA lv_object_name TYPE trobj_name. + + lv_object_name = iv_object_name. + + CALL FUNCTION 'LXE_OBJ_EXPAND_TRANSPORT_OBJ' + EXPORTING + pgmid = 'R3TR' + object = iv_object_type + obj_name = lv_object_name + TABLES + ex_colob = rt_obj_list + EXCEPTIONS + unknown_object = 1 + unknown_ta_type = 2 + OTHERS = 3. + IF sy-subrc <> 0. + RETURN. " Ignore error and return empty list + ENDIF. + + ENDMETHOD. + METHOD get_translation_languages. + + " Returns a list of translation languages for serialization + " If the setting is initial, no translations shall be serialized + " If the setting is `*`, all installed system languages shall be serialized + " Else, the setting shall contain all languages to be serialized + + DATA lv_main_lang_laiso TYPE laiso. + + IF it_i18n_languages IS NOT INITIAL. + READ TABLE it_i18n_languages TRANSPORTING NO FIELDS WITH KEY table_line = '*'. + IF sy-subrc = 0. + rt_languages = get_installed_languages( ). + ELSE. + check_langs_versus_installed( + EXPORTING + it_languages = it_i18n_languages + it_installed = get_installed_languages( ) + IMPORTING + et_intersection = rt_languages ). + ENDIF. + ENDIF. + + " Remove main language from translation languages + lv_main_lang_laiso = langu_to_laiso_safe( iv_main_language ). + DELETE rt_languages WHERE table_line = lv_main_lang_laiso. + + ENDMETHOD. + METHOD iso4_to_iso2. + rv_laiso = iv_lxe_lang+0(2). + ENDMETHOD. + METHOD langu_to_laiso_safe. + + zcl_abapgit_convert=>language_sap1_to_sap2( + EXPORTING + im_lang_sap1 = iv_langu + RECEIVING + re_lang_sap2 = rv_laiso + EXCEPTIONS + no_assignment = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Could not convert lang [{ iv_langu }] to ISO| ). + ENDIF. + + ENDMETHOD. + METHOD read_lxe_object_text_pair. + + DATA: + lv_error TYPE lxestring. + + TRY. + CALL FUNCTION 'LXE_OBJ_TEXT_PAIR_READ' + EXPORTING + s_lang = iv_s_lang + t_lang = iv_t_lang + custmnr = iv_custmnr + objtype = iv_objtype + objname = iv_objname + read_only = iv_read_only + IMPORTING + err_msg = lv_error " doesn't exist in NW <= 750 + TABLES + lt_pcx_s1 = rt_text_pairs_tmp. + IF lv_error IS NOT INITIAL. + zcx_abapgit_exception=>raise( lv_error ). + ENDIF. + + CATCH cx_sy_dyn_call_param_not_found. + + CALL FUNCTION 'LXE_OBJ_TEXT_PAIR_READ' + EXPORTING + s_lang = iv_s_lang + t_lang = iv_t_lang + custmnr = iv_custmnr + objtype = iv_objtype + objname = iv_objname + read_only = iv_read_only + TABLES + lt_pcx_s1 = rt_text_pairs_tmp. + + ENDTRY. + + remove_irrelevant( + EXPORTING + iv_objtype = iv_objtype + CHANGING + ct_text_pairs_tmp = rt_text_pairs_tmp ). + + ENDMETHOD. + METHOD read_text_items. + + DATA: + lt_obj_list TYPE lxe_tt_colob, + lv_main_lang TYPE lxeisolang, + ls_lxe_text_item LIKE LINE OF rt_text_items. + + FIELD-SYMBOLS: + LIKE LINE OF mo_i18n_params->ms_params-translation_languages, + LIKE LINE OF lt_obj_list. + + lt_obj_list = get_lxe_object_list( + iv_object_name = iv_object_name + iv_object_type = iv_object_type ). + + IF lt_obj_list IS INITIAL. + RETURN. + ENDIF. + + " Get list of languages that need to be serialized (already resolves * and installed languages) + lv_main_lang = get_lang_iso4( langu_to_laiso_safe( mo_i18n_params->ms_params-main_language ) ). + + LOOP AT lt_obj_list ASSIGNING . + CLEAR ls_lxe_text_item. + ls_lxe_text_item-custmnr = -custmnr. + ls_lxe_text_item-objtype = -objtype. + ls_lxe_text_item-objname = -objname. + + LOOP AT mo_i18n_params->ms_params-translation_languages ASSIGNING . + ls_lxe_text_item-source_lang = lv_main_lang. + ls_lxe_text_item-target_lang = get_lang_iso4( ). + IF ls_lxe_text_item-source_lang = ls_lxe_text_item-target_lang. + CONTINUE. " if source = target -> skip + ENDIF. + + ls_lxe_text_item-text_pairs = read_lxe_object_text_pair( + iv_s_lang = ls_lxe_text_item-source_lang + iv_t_lang = ls_lxe_text_item-target_lang + iv_custmnr = ls_lxe_text_item-custmnr + iv_objtype = ls_lxe_text_item-objtype + iv_objname = ls_lxe_text_item-objname ). + + IF ls_lxe_text_item-text_pairs IS NOT INITIAL. + APPEND ls_lxe_text_item TO rt_text_items. + ENDIF. + ENDLOOP. + ENDLOOP. + + ENDMETHOD. + METHOD remove_irrelevant. + + IF iv_objtype = 'RPT4'. + DELETE ct_text_pairs_tmp WHERE textkey = 'DUMMY KEY FOR DDIC FLAG COPY'. " see #7314 + ENDIF. + " Add more when identified ... + + ENDMETHOD. + METHOD serialize_as_po. + + DATA lt_lxe_texts TYPE ty_lxe_translations. + DATA lo_po_file TYPE REF TO zcl_abapgit_po_file. + DATA lv_lang LIKE LINE OF mo_i18n_params->ms_params-translation_languages. + FIELD-SYMBOLS LIKE LINE OF lt_lxe_texts. + + lt_lxe_texts = read_text_items( + iv_object_name = iv_object_name + iv_object_type = iv_object_type ). + + LOOP AT mo_i18n_params->ms_params-translation_languages INTO lv_lang. + lv_lang = to_lower( lv_lang ). + CREATE OBJECT lo_po_file + EXPORTING + iv_suppress_comments = mo_i18n_params->ms_params-suppress_po_comments + iv_lang = lv_lang. + LOOP AT lt_lxe_texts ASSIGNING . + IF iso4_to_iso2( -target_lang ) = lv_lang. + lo_po_file->push_text_pairs( + iv_objtype = -objtype + iv_objname = -objname + it_text_pairs = -text_pairs ). + ENDIF. + ENDLOOP. + mo_files->add_i18n_file( lo_po_file ). + ENDLOOP. + + ENDMETHOD. + METHOD serialize_xml. + + DATA lt_lxe_texts TYPE ty_lxe_translations. + + lt_lxe_texts = read_text_items( + iv_object_name = iv_object_name + iv_object_type = iv_object_type ). + + IF lines( lt_lxe_texts ) > 0. + mi_xml_out->add( + iv_name = iv_lxe_text_name + ig_data = lt_lxe_texts ). + ENDIF. + + ENDMETHOD. + METHOD write_lxe_object_text_pair. + + DATA: + lv_status TYPE lxestatprc, + lv_error TYPE lxestring. + + TRY. + CALL FUNCTION 'LXE_OBJ_TEXT_PAIR_WRITE' + EXPORTING + s_lang = iv_s_lang + t_lang = iv_t_lang + custmnr = iv_custmnr + objtype = iv_objtype + objname = iv_objname + IMPORTING + pstatus = lv_status + err_msg = lv_error " doesn't exist in NW <= 750 + TABLES + lt_pcx_s1 = it_pcx_s1. + IF lv_error IS NOT INITIAL. + zcx_abapgit_exception=>raise( lv_error ). + ENDIF. + + CATCH cx_sy_dyn_call_param_not_found. + + CALL FUNCTION 'LXE_OBJ_TEXT_PAIR_WRITE' + EXPORTING + s_lang = iv_s_lang + t_lang = iv_t_lang + custmnr = iv_custmnr + objtype = iv_objtype + objname = iv_objname + IMPORTING + pstatus = lv_status + TABLES + lt_pcx_s1 = it_pcx_s1. + + ENDTRY. + + IF lv_status <> 'S'. + zcx_abapgit_exception=>raise( 'Error updating translations' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_lxe_texts~deserialize. + + DATA lv_changed TYPE abap_bool. + + mo_i18n_params = io_i18n_params. + mi_xml_in = ii_xml. + mo_files = io_files. + + " MAYBE TODO: see comment in serialize + + IF 1 = 1. + lv_changed = deserialize_from_po( + iv_object_type = iv_object_type + iv_object_name = iv_object_name ). + + IF lv_changed = abap_true. + zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( + iv_object = iv_object_type + iv_obj_name = iv_object_name + iv_package = iv_package + iv_language = mo_i18n_params->ms_params-main_language ). + ENDIF. + ELSE. + deserialize_xml( + iv_object_type = iv_object_type + iv_object_name = iv_object_name ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_lxe_texts~serialize. + + mo_i18n_params = io_i18n_params. + mi_xml_out = ii_xml. + mo_files = io_files. + + " MAYBE TODO + " if other formats are needed, including the old in-XML approach + " here is the place to implement it. Supposed architecture: + " I18N_PARAMS should contain an option which format to use + " The option should be originally maintained in dot_abapgit structures (e.g. `translation_storage_format`) + " Consequently it comes here + " The serialize method can read it and call a corresponding submethod, + " e.g. serialize_xml or serialize_as_po or ... + " both ii_xml and io_files are accessible intentionally to enable both XML based or file based formats + " access to json can be easily added too, + " or maybe (maybe) some kind of zif_ag_object_ctl with all DAO instead + + IF 1 = 1. + serialize_as_po( + iv_object_type = iv_object_type + iv_object_name = iv_object_name ). + ELSE. + serialize_xml( + iv_object_type = iv_object_type + iv_object_name = iv_object_name ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_longtexts IMPLEMENTATION. + METHOD escape_name. + " Prepare name for SQL LIKE condition + rv_object = iv_object_name. + + IF 'CA,CE,CO,CT,IA,IE,IO,WC,FU,FX,DI,IS,PS' CS iv_longtext_id. + " Document types of objects with sub-objects + rv_object+30 = '%'. + ELSEIF 'OD' CS iv_longtext_id. + rv_object+10 = '%'. + ENDIF. + + rv_object = replace( + val = rv_object + sub = '_' + with = '#_' + occ = 0 ). + ENDMETHOD. + METHOD read. + + DATA: ls_longtext TYPE zif_abapgit_longtexts=>ty_longtext, + lv_object TYPE dokil-object, + lt_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_dokil. + + IF iv_object_name CA '#'. + zcx_abapgit_exception=>raise( |Invalid name for longtext: { iv_longtext_id } { iv_object_name }| ). + ENDIF. + + lv_object = escape_name( + iv_longtext_id = iv_longtext_id + iv_object_name = iv_object_name ). + + IF lines( it_dokil ) > 0. + + lt_dokil = it_dokil. + + IF iv_main_lang_only = abap_true. + DELETE lt_dokil WHERE masterlang <> abap_true. + ENDIF. + + ELSEIF iv_longtext_id IS NOT INITIAL. + IF iv_main_lang_only = abap_true. + SELECT * FROM dokil + INTO TABLE lt_dokil + WHERE id = iv_longtext_id + AND object LIKE lv_object ESCAPE '#' + AND masterlang = abap_true + ORDER BY PRIMARY KEY. + ELSE. + SELECT * FROM dokil + INTO TABLE lt_dokil + WHERE id = iv_longtext_id + AND object LIKE lv_object ESCAPE '#' + ORDER BY PRIMARY KEY. + ENDIF. + ELSE. + + zcx_abapgit_exception=>raise( |serialize_longtexts parameter error| ). + + ENDIF. + + LOOP AT lt_dokil ASSIGNING + WHERE txtlines > 0. + + CLEAR: ls_longtext. + + ls_longtext-dokil = . + + CALL FUNCTION 'DOCU_READ' + EXPORTING + id = -id + langu = -langu + object = -object + typ = -typ + version = -version + IMPORTING + head = ls_longtext-head + TABLES + line = ls_longtext-lines. + + IF iv_clear_fields = abap_true. + CLEAR: ls_longtext-head-tdfuser, + ls_longtext-head-tdfreles, + ls_longtext-head-tdfdate, + ls_longtext-head-tdftime, + ls_longtext-head-tdluser, + ls_longtext-head-tdlreles, + ls_longtext-head-tdldate, + ls_longtext-head-tdltime. + ENDIF. + + INSERT ls_longtext INTO TABLE rt_longtexts. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_longtexts~changed_by. + + DATA: lt_longtexts TYPE zif_abapgit_longtexts=>ty_longtexts. + FIELD-SYMBOLS: TYPE zif_abapgit_longtexts=>ty_longtext. + + lt_longtexts = read( iv_object_name = iv_object_name + iv_longtext_id = iv_longtext_id + it_dokil = it_dokil + iv_clear_fields = abap_false ). + + READ TABLE lt_longtexts INDEX 1 ASSIGNING . + IF sy-subrc = 0. + rv_user = -head-tdluser. + IF rv_user IS INITIAL. + rv_user = -head-tdfuser. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_longtexts~delete. + + DATA: lt_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt, + lv_object TYPE dokil-object. + + FIELD-SYMBOLS: TYPE dokil. + + lv_object = escape_name( + iv_longtext_id = iv_longtext_id + iv_object_name = iv_object_name ). + + SELECT * FROM dokil + INTO TABLE lt_dokil + WHERE id = iv_longtext_id AND object LIKE lv_object ESCAPE '#' + ORDER BY PRIMARY KEY. + + LOOP AT lt_dokil ASSIGNING . + + CALL FUNCTION 'DOCU_DEL' + EXPORTING + id = -id + langu = -langu + object = -object + typ = -typ + EXCEPTIONS + ret_code = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_longtexts~deserialize. + + DATA: lt_longtexts TYPE zif_abapgit_longtexts=>ty_longtexts, + lv_object TYPE dokil-object, + lt_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt, + lv_no_main_lang TYPE dokil-masterlang. + + FIELD-SYMBOLS: TYPE zif_abapgit_longtexts=>ty_longtext, + TYPE dokil. + + lv_object = escape_name( + iv_longtext_id = iv_longtext_id + iv_object_name = iv_object_name ). + + ii_xml->read( + EXPORTING + iv_name = iv_longtext_name + CHANGING + cg_data = lt_longtexts ). + + LOOP AT lt_longtexts ASSIGNING . + + lv_no_main_lang = boolc( iv_main_language <> -dokil-langu ). + + CALL FUNCTION 'DOCU_UPDATE' + EXPORTING + head = -head + state = c_docu_state_active + typ = -dokil-typ + version = -dokil-version + no_masterlang = lv_no_main_lang + TABLES + line = -lines. + + ENDLOOP. + + " Read existing texts and check if they were deserialized above + " If not, delete the texts + SELECT * FROM dokil + INTO TABLE lt_dokil + WHERE id = iv_longtext_id AND object LIKE lv_object ESCAPE '#' + ORDER BY PRIMARY KEY. + + LOOP AT lt_dokil ASSIGNING . + + READ TABLE lt_longtexts TRANSPORTING NO FIELDS WITH KEY + dokil-id = -id + dokil-langu = -langu + dokil-object = -object + dokil-typ = -typ. + IF sy-subrc <> 0. + CALL FUNCTION 'DOCU_DEL' + EXPORTING + id = -id + langu = -langu + object = -object + typ = -typ + EXCEPTIONS + ret_code = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_longtexts~serialize. + + rt_longtexts = read( iv_object_name = iv_object_name + iv_longtext_id = iv_longtext_id + it_dokil = it_dokil + iv_main_lang_only = io_i18n_params->ms_params-main_language_only ). + + IF rt_longtexts IS SUPPLIED. + RETURN. + ENDIF. + + ii_xml->add( iv_name = iv_longtext_name + ig_data = rt_longtexts ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_I18N_PARAMS IMPLEMENTATION. + METHOD build_language_filter. + IF mt_language_filter IS INITIAL. + " translation_languages are includes, system langs are excludes, so the do not interfere + IF ms_params-translation_languages IS NOT INITIAL. + mt_language_filter = iso_langs_to_lang_filter( ms_params-translation_languages ). + ELSE. + mt_language_filter = zcl_abapgit_factory=>get_environment( )->get_system_language_filter( ). + ENDIF. + ENDIF. + rt_language_filter = mt_language_filter. + ENDMETHOD. + METHOD constructor. + IF is_params IS NOT INITIAL. + ms_params = is_params. + ELSE. + ms_params-main_language = iv_main_language. + ms_params-main_language_only = iv_main_language_only. + ms_params-translation_languages = it_translation_langs. + ms_params-use_lxe = iv_use_lxe. + ENDIF. + ASSERT ms_params-main_language IS NOT INITIAL. + ENDMETHOD. + METHOD iso_langs_to_lang_filter. + + DATA lv_laiso LIKE LINE OF it_iso_filter. + DATA lv_langu TYPE sy-langu. + DATA ls_range LIKE LINE OF rt_language_filter. + + ls_range-sign = 'I'. + ls_range-option = 'EQ'. + + LOOP AT it_iso_filter INTO lv_laiso. + + zcl_abapgit_convert=>language_sap2_to_sap1( + EXPORTING + im_lang_sap2 = lv_laiso + RECEIVING + re_lang_sap1 = lv_langu + EXCEPTIONS + no_assignment = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + + ls_range-low = lv_langu. + APPEND ls_range TO rt_language_filter. + + ENDLOOP. + + ENDMETHOD. + METHOD is_lxe_applicable. + + rv_yes = boolc( ms_params-main_language_only = abap_false AND + ms_params-use_lxe = abap_true AND + ms_params-translation_languages IS NOT INITIAL ). + + ENDMETHOD. + METHOD match_obj_patterns. + + DATA lv_pattern TYPE string. + DATA lv_path TYPE string. + + LOOP AT it_wo_translation_patterns INTO lv_pattern. + CHECK lv_pattern IS NOT INITIAL. + IF NOT lv_pattern+0(1) CA '*/'. + " The idea is to simplify entering package paths e.g. subpkg/* instead of /src/subpkg/* or */subpkg/* + " or object names: zcl.clas instead of */zcl.clas + " But maybe it is a bad idea ... to see on practice + lv_pattern = `*/` && lv_pattern. + ENDIF. + + " Compose simplified file path + lv_path = is_tadir-path && to_lower( is_tadir-obj_name ) && `.` && to_lower( is_tadir-object ). + + IF lv_path CP lv_pattern. + rv_yes = abap_true. + EXIT. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD new. + CREATE OBJECT ro_instance + EXPORTING + iv_main_language = iv_main_language + iv_main_language_only = iv_main_language_only + it_translation_langs = it_translation_langs + iv_use_lxe = iv_use_lxe + is_params = is_params. + ENDMETHOD. + METHOD normalize_obj_patterns. + + DATA lv_pattern TYPE string. + + LOOP AT it_wo_translation_patterns INTO lv_pattern. + CONDENSE lv_pattern. + CHECK lv_pattern IS NOT INITIAL. + lv_pattern = to_lower( lv_pattern ). + " TODO validation if needed + APPEND lv_pattern TO rt_wo_translation_clean. + ENDLOOP. + + ENDMETHOD. + METHOD trim_saplang_keyed_table. + + DATA lv_laiso TYPE laiso. + DATA lv_index TYPE i. + + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE sy-langu. + + IF ms_params-translation_languages IS INITIAL OR iv_lang_field_name IS INITIAL. + RETURN. " Nothing to filter + ENDIF. + + LOOP AT ct_tab ASSIGNING . + lv_index = sy-tabix. + ASSIGN COMPONENT iv_lang_field_name OF STRUCTURE TO . + ASSERT sy-subrc = 0. + + IF iv_keep_master_lang = abap_true AND = ms_params-main_language. + CONTINUE. " Just keep it + ENDIF. + + zcl_abapgit_convert=>language_sap1_to_sap2( + EXPORTING + im_lang_sap1 = + RECEIVING + re_lang_sap2 = lv_laiso + EXCEPTIONS + no_assignment = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + DELETE ct_tab INDEX lv_index. " Not in the list anyway ... + CONTINUE. + ENDIF. + + " Not a sorted table, but presumably the list is small, so no significant performance flow + READ TABLE ms_params-translation_languages TRANSPORTING NO FIELDS WITH KEY table_line = lv_laiso. + IF sy-subrc <> 0. + DELETE ct_tab INDEX lv_index. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD trim_saplang_list. + + DATA lv_langu TYPE sy-langu. + DATA lv_laiso TYPE laiso. + DATA lv_index TYPE i. + + IF ms_params-translation_languages IS INITIAL. + RETURN. " Nothing to filter + ENDIF. + + LOOP AT ct_sap_langs INTO lv_langu. + lv_index = sy-tabix. + + zcl_abapgit_convert=>language_sap1_to_sap2( + EXPORTING + im_lang_sap1 = lv_langu + RECEIVING + re_lang_sap2 = lv_laiso + EXCEPTIONS + no_assignment = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + DELETE ct_sap_langs INDEX lv_index. " Not in the list anyway ... + CONTINUE. + ENDIF. + + " Not a sorted table, but presumably the list is small, so no significant performance flow + READ TABLE ms_params-translation_languages TRANSPORTING NO FIELDS WITH KEY table_line = lv_laiso. + IF sy-subrc <> 0. + DELETE ct_sap_langs INDEX lv_index. + ENDIF. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_tabl_ddl IMPLEMENTATION. + METHOD deserialize. + +* https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/abenddicddl_define_table.htm + +* CL_SBD_STRUCTURE_OBJDATA has serializer in local class + + DATA lv_ddl TYPE string. + DATA lv_fields TYPE string. + DATA lv_start TYPE i. + DATA lv_length TYPE i. + DATA lv_end TYPE i. + DATA lt_fields TYPE STANDARD TABLE OF string WITH DEFAULT KEY. + DATA lv_field TYPE string. + lv_ddl = iv_ddl. + + parse_top_annotations( CHANGING + cs_data = rs_data + cv_ddl = lv_ddl ). + + FIND FIRST OCCURRENCE OF '{' IN lv_ddl MATCH OFFSET lv_start. + ASSERT lv_start > 0. + FIND FIRST OCCURRENCE OF '}' IN lv_ddl MATCH OFFSET lv_end. + ASSERT lv_end > 0. + + lv_start = lv_start + 1. + lv_length = lv_end - lv_start - 1. + lv_fields = lv_ddl+lv_start(lv_length). + SPLIT lv_fields AT |;| INTO TABLE lt_fields. + + LOOP AT lt_fields INTO lv_field WHERE table_line IS NOT INITIAL. + parse_field( EXPORTING iv_field = lv_field CHANGING cs_data = rs_data ). + ENDLOOP. + + ENDMETHOD. + METHOD escape_string. + rv_string = |'{ replace( val = iv_string + sub = |'| + with = |''| + occ = 0 ) }'|. + ENDMETHOD. + METHOD parse_field. + + CONSTANTS: BEGIN OF lc_mode, + start TYPE i VALUE 0, + colon TYPE i VALUE 1, + type TYPE i VALUE 2, + aftertype TYPE i VALUE 3, + null TYPE i VALUE 4, + afternull TYPE i VALUE 5, + END OF lc_mode. + + DATA lv_field TYPE string. + DATA lv_mode TYPE i. + DATA lt_tokens TYPE STANDARD TABLE OF string WITH DEFAULT KEY. + DATA lv_token TYPE string. + DATA ls_dd08v TYPE dd08v. + + FIELD-SYMBOLS LIKE LINE OF cs_data-dd03p. + lv_field = iv_field. + parse_field_annotations( + IMPORTING es_dd08v = ls_dd08v + CHANGING cv_ddl = lv_field ). + + SPLIT lv_field AT space INTO TABLE lt_tokens. + + APPEND INITIAL LINE TO cs_data-dd03p ASSIGNING . + + LOOP AT lt_tokens INTO lv_token WHERE table_line IS NOT INITIAL. + CASE lv_mode. + WHEN lc_mode-start. +* todo, is it possible to have a key field named "key" ? + IF lv_token = 'key'. + -keyflag = abap_true. + ELSE. + -fieldname = to_upper( lv_token ). + lv_mode = lc_mode-colon. + ENDIF. + WHEN lc_mode-colon. + ASSERT lv_token = ':'. + lv_mode = lc_mode-type. + WHEN lc_mode-type. + parse_type( + EXPORTING iv_token = lv_token + CHANGING cs_dd03p = ). + RETURN. + WHEN lc_mode-aftertype. + IF lv_token = 'not'. + -notnull = abap_true. + lv_mode = lc_mode-null. + ENDIF. + WHEN lc_mode-null. + ASSERT lv_token = 'null'. + lv_mode = lc_mode-afternull. + WHEN lc_mode-afternull. + ASSERT lv_token = 'with'. + RETURN. " todo + WHEN OTHERS. + ASSERT 1 = 'todo'. + ENDCASE. + ENDLOOP. + + ENDMETHOD. + METHOD parse_field_annotations. + + DATA lv_annotation TYPE string. + DATA lv_name TYPE string. + DATA lv_value TYPE string. + REPLACE FIRST OCCURRENCE OF REGEX '^[\n ]*' IN cv_ddl WITH ||. + + WHILE cv_ddl CP '@*'. + SPLIT cv_ddl AT |\n| INTO lv_annotation cv_ddl. + CONDENSE cv_ddl. + + SPLIT lv_annotation AT ':' INTO lv_name lv_value. + CONDENSE lv_name. + CONDENSE lv_value. + ASSERT lv_name IS NOT INITIAL. + ASSERT lv_value IS NOT INITIAL. + + CASE lv_name. + WHEN '@AbapCatalog.foreignKey.label'. + es_dd08v-ddtext = unescape_string( lv_value ). + WHEN '@AbapCatalog.foreignKey.keyType'. + ASSERT lv_value(1) = '#'. + es_dd08v-frkart = lv_value+1. + WHEN '@AbapCatalog.foreignKey.screenCheck'. + ASSERT lv_value = 'true'. + WHEN OTHERS. + WRITE: / 'todo:', lv_name, lv_value. + ASSERT 1 = 'todo'. + ENDCASE. + ENDWHILE. + + ENDMETHOD. + METHOD parse_top_annotations. + + DATA lv_annotation TYPE string. + DATA lv_name TYPE string. + DATA lv_value TYPE string. + WHILE cv_ddl CP '@*'. + SPLIT cv_ddl AT |\n| INTO lv_annotation cv_ddl. + SPLIT lv_annotation AT ':' INTO lv_name lv_value. + CONDENSE lv_name. + CONDENSE lv_value. + ASSERT lv_name IS NOT INITIAL. + ASSERT lv_value IS NOT INITIAL. + CASE lv_name. + WHEN '@EndUserText.label'. + cs_data-dd02v-ddtext = unescape_string( lv_value ). + WHEN '@AbapCatalog.enhancementCategory'. + CASE lv_value. + WHEN '#NOT_EXTENSIBLE'. + cs_data-dd02v-contflag = '1'. + WHEN OTHERS. + ASSERT 1 = 'todo'. + ENDCASE. + WHEN '@AbapCatalog.tableCategory'. + CASE lv_value. + WHEN '#TRANSPARENT'. + cs_data-dd02v-tabclass = 'TRANSP'. + WHEN OTHERS. + ASSERT 1 = 'todo'. + ENDCASE. + WHEN '@AbapCatalog.deliveryClass'. + ASSERT lv_value(1) = '#'. + cs_data-dd02v-contflag = lv_value+1. + WHEN '@AbapCatalog.dataMaintenance'. + CASE lv_value. + WHEN '#ALLOWED'. + cs_data-dd02v-mainflag = abap_true. + WHEN '#LIMITED'. + cs_data-dd02v-mainflag = abap_false. + WHEN OTHERS. + ASSERT 1 = 'todo'. + ENDCASE. + WHEN OTHERS. + WRITE: / 'todo:', lv_name, lv_value. + ASSERT 1 = 'todo'. + ENDCASE. + + ENDWHILE. + + ENDMETHOD. + METHOD parse_type. + + DATA lv_token TYPE string. + + lv_token = iv_token. + IF lv_token CP 'abap.*'. + lv_token = lv_token+5. + IF lv_token(4) = 'char'. +* todo, length + cs_dd03p-datatype = 'CHAR'. + ELSEIF lv_token(6) = 'string'. + cs_dd03p-intlen = 8. + cs_dd03p-inttype = 'g'. + cs_dd03p-datatype = 'STRG'. + ELSE. + ASSERT 1 = 'todo'. + ENDIF. + ELSE. + cs_dd03p-rollname = to_upper( lv_token ). + ENDIF. + + ENDMETHOD. + METHOD read_data. +* temporary method for testing + + DATA lv_name TYPE ddobjname. + + lv_name = iv_name. + + CALL FUNCTION 'DDIF_TABL_GET' + EXPORTING + name = lv_name + langu = 'E' + IMPORTING + dd02v_wa = rs_data-dd02v + dd09l_wa = rs_data-dd09l + TABLES + dd03p_tab = rs_data-dd03p + dd05m_tab = rs_data-dd05m + dd08v_tab = rs_data-dd08v + dd12v_tab = rs_data-dd12v + dd17v_tab = rs_data-dd17v + dd35v_tab = rs_data-dd35v + dd36m_tab = rs_data-dd36m + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + ASSERT sy-subrc = 0. + + ENDMETHOD. + METHOD serialize. + + DATA ls_dd03p LIKE LINE OF is_data-dd03p. + DATA lv_key TYPE string. + DATA lv_type TYPE string. + DATA lv_pre TYPE string. + DATA lv_int TYPE i. + DATA lv_suffix TYPE string. + DATA lv_notnull TYPE string. + DATA lv_colon TYPE i. + rv_ddl = rv_ddl && serialize_top( is_data ). + + rv_ddl = rv_ddl && |define table { to_lower( is_data-dd02v-tabname ) } \{\n|. + + LOOP AT is_data-dd03p INTO ls_dd03p + WHERE ( fieldname NP '.INCLU*' OR groupname IS NOT INITIAL ) + AND adminfield = '0'. + lv_int = 0. + IF ls_dd03p-keyflag = abap_true. + lv_int = 4. + ENDIF. + IF ls_dd03p-groupname IS INITIAL. + lv_int = lv_int + strlen( ls_dd03p-fieldname ). + ELSE. + lv_int = lv_int + strlen( ls_dd03p-groupname ). + ENDIF. + IF lv_int > lv_colon. + lv_colon = lv_int. + ENDIF. + ENDLOOP. + +* ADMINFIELD: skip fields inside .INCLUDEs + LOOP AT is_data-dd03p INTO ls_dd03p WHERE adminfield = '0'. + CLEAR lv_key. + CLEAR lv_notnull. + IF ls_dd03p-keyflag = abap_true. + lv_key = |key |. + ENDIF. + + lv_pre = |{ lv_key }{ to_lower( ls_dd03p-fieldname ) }|. + IF ls_dd03p-groupname IS NOT INITIAL. + lv_pre = |{ lv_key }{ to_lower( ls_dd03p-groupname ) }|. + ENDIF. + IF strlen( lv_pre ) < lv_colon. + lv_pre = lv_pre && repeat( + val = | | + occ = lv_colon - strlen( lv_pre ) ). + ENDIF. + + IF ls_dd03p-fieldname = '.INCLU--AP'. + CONTINUE. + ELSEIF ls_dd03p-fieldname CP '.INCLU*'. + IF ls_dd03p-notnull = abap_true. + lv_notnull = | not null|. + ENDIF. + CLEAR lv_suffix. + IF ls_dd03p-fieldname CA '-'. + SPLIT ls_dd03p-fieldname AT '-' INTO lv_suffix lv_suffix. + lv_suffix = | with suffix { to_lower( lv_suffix ) }|. + ENDIF. + IF ls_dd03p-groupname IS INITIAL. + rv_ddl = rv_ddl && | { lv_key }include { to_lower( ls_dd03p-precfield ) }{ lv_suffix }{ lv_notnull }|. + ELSE. + rv_ddl = rv_ddl && | { lv_pre } : include { to_lower( ls_dd03p-precfield ) }{ lv_suffix }{ lv_notnull }|. + ENDIF. + rv_ddl = rv_ddl && serialize_extend( + is_dd03p = ls_dd03p + is_data = is_data ). + rv_ddl = rv_ddl && |;\n|. + CONTINUE. + ENDIF. + + rv_ddl = rv_ddl && serialize_field_annotations( + iv_fieldname = ls_dd03p-fieldname + is_data = is_data ). + rv_ddl = rv_ddl && serialize_fkey_annotations( + iv_fieldname = ls_dd03p-fieldname + is_data = is_data ). + + lv_type = serialize_type( ls_dd03p ). + rv_ddl = rv_ddl && | { lv_pre } : { lv_type }|. + rv_ddl = rv_ddl && serialize_field_foreign_key( + iv_fieldname = ls_dd03p-fieldname + is_data = is_data ). + rv_ddl = rv_ddl && serialize_value_help( + iv_fieldname = ls_dd03p-fieldname + is_data = is_data ). + rv_ddl = rv_ddl && |;\n|. + ENDLOOP. + rv_ddl = rv_ddl && |\n|. + + rv_ddl = rv_ddl && |\}|. + + ENDMETHOD. + METHOD serialize_adt. + + DATA ls_object_type TYPE wbobjtype. + DATA lv_object_key TYPE seu_objkey. + DATA li_object_data TYPE REF TO if_wb_object_data_model. + DATA lo_operator TYPE REF TO object. + ls_object_type-objtype_tr = 'TABL'. + ls_object_type-subtype_wb = 'DT'. + + lv_object_key = iv_name. + + CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') + EXPORTING + object_type = ls_object_type + object_key = lv_object_key + RECEIVING + result = lo_operator. + + CALL METHOD lo_operator->('IF_WB_OBJECT_OPERATOR~READ') + EXPORTING + version = 'A' + IMPORTING + eo_object_data = li_object_data. + + CALL METHOD li_object_data->('GET_CONTENT') IMPORTING p_data = rv_ddl. + + ENDMETHOD. + METHOD serialize_extend. + + DATA lv_index TYPE i. + DATA ls_dd03p LIKE LINE OF is_data-dd03p. + DATA lt_fields TYPE STANDARD TABLE OF string WITH DEFAULT KEY. + DATA lv_field LIKE LINE OF lt_fields. + DATA ls_dd08v LIKE LINE OF is_data-dd08v. + DATA ls_dd35v LIKE LINE OF is_data-dd35v. + READ TABLE is_data-dd03p TRANSPORTING NO FIELDS + WITH KEY fieldname = is_dd03p-fieldname precfield = is_dd03p-precfield. + ASSERT sy-subrc = 0. + lv_index = sy-tabix + 1. + +* the extended keys are not sorted by the fieldname positions + LOOP AT is_data-dd03p FROM lv_index INTO ls_dd03p. + IF ls_dd03p-adminfield = '0'. + EXIT. + ENDIF. + APPEND ls_dd03p-fieldname TO lt_fields. + ENDLOOP. + CLEAR ls_dd03p. + + LOOP AT is_data-dd08v INTO ls_dd08v + WHERE ( noinherit = 'Y' OR checktable = '*' ) AND noinherit <> 'N'. + READ TABLE lt_fields TRANSPORTING NO FIELDS + WITH KEY table_line = ls_dd08v-fieldname. + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + DELETE lt_fields WHERE table_line = ls_dd08v-fieldname. + + rv_ddl = rv_ddl && |\n|. + + IF ls_dd08v-checktable <> '*'. + rv_ddl = rv_ddl && serialize_fkey_annotations( + iv_fieldname = ls_dd08v-fieldname + is_data = is_data ). + ENDIF. + + rv_ddl = rv_ddl && | extend { to_lower( ls_dd08v-fieldname ) } :|. + + IF ls_dd08v-checktable = '*'. + rv_ddl = rv_ddl && |\n remove foreign key|. + ELSE. + rv_ddl = rv_ddl && serialize_field_foreign_key( + iv_fieldname = ls_dd08v-fieldname + is_data = is_data ). + ENDIF. + + READ TABLE is_data-dd35v INTO ls_dd35v WITH KEY fieldname = ls_dd08v-fieldname. + IF sy-subrc = 0. + IF ls_dd35v-shlpname = '*'. + rv_ddl = rv_ddl && |\n remove value help|. + ELSEIF ls_dd35v-shlpinher <> abap_true. + rv_ddl = rv_ddl && serialize_value_help( + iv_fieldname = ls_dd08v-fieldname + is_data = is_data ). + ENDIF. + ENDIF. + ENDLOOP. + + LOOP AT is_data-dd35v INTO ls_dd35v. + READ TABLE lt_fields INTO lv_field + WITH KEY table_line = ls_dd35v-fieldname. + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + + IF ls_dd35v-shlpname = '*'. + rv_ddl = rv_ddl && |\n|. + rv_ddl = rv_ddl && | extend { to_lower( lv_field ) } :|. + rv_ddl = rv_ddl && |\n remove value help|. + ELSEIF ls_dd35v-shlpinher <> abap_true. + rv_ddl = rv_ddl && |\n|. + rv_ddl = rv_ddl && | extend { to_lower( lv_field ) } :|. + rv_ddl = rv_ddl && serialize_value_help( + iv_fieldname = lv_field + is_data = is_data ). + ENDIF. + ENDLOOP. + + REPLACE ALL OCCURRENCES OF |\n | IN rv_ddl WITH |\n |. + + ENDMETHOD. + METHOD serialize_field_annotations. + + DATA ls_dd03p LIKE LINE OF is_data-dd03p. + READ TABLE is_data-dd03p INTO ls_dd03p WITH KEY fieldname = iv_fieldname. + IF sy-subrc = 0. + IF ( ls_dd03p-rollname IS INITIAL AND ls_dd03p-precfield IS INITIAL + OR ls_dd03p-comptype = 'R' AND ls_dd03p-reftype = 'B' ) + AND ls_dd03p-ddtext IS NOT INITIAL. + rv_ddl = rv_ddl && | @EndUserText.label : { escape_string( ls_dd03p-ddtext ) }\n|. + ENDIF. + + IF ls_dd03p-languflag = abap_true. + rv_ddl = rv_ddl && | @AbapCatalog.textLanguage\n|. + ENDIF. + + IF ls_dd03p-reftable IS NOT INITIAL AND ls_dd03p-reffield IS NOT INITIAL. +* this is not completely correct, it must lookup the type of the field in REFTABLE? + IF ls_dd03p-datatype = 'CURR' OR ls_dd03p-reffield = 'WAERS'. + rv_ddl = rv_ddl && | @Semantics.amount.currencyCode : '{ to_lower( ls_dd03p-reftable ) }.{ + to_lower( ls_dd03p-reffield ) }'\n|. + ELSE. + rv_ddl = rv_ddl && | @Semantics.quantity.unitOfMeasure : '{ to_lower( ls_dd03p-reftable ) }.{ + to_lower( ls_dd03p-reffield ) }'\n|. + ENDIF. + ENDIF. + + IF ls_dd03p-rollname IS INITIAL AND ( ls_dd03p-datatype(3) = 'D16' OR ls_dd03p-datatype(3) = 'D34' ). +* ls_dd03p-outputstyle + rv_ddl = rv_ddl && | @AbapCatalog.decfloat.outputStyle : #NORMAL\n|. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD serialize_field_foreign_key. + + DATA ls_dd08v LIKE LINE OF is_data-dd08v. + DATA ls_dd05m LIKE LINE OF is_data-dd05m. + DATA lv_pre TYPE string. + DATA lv_cardinality TYPE string. + + READ TABLE is_data-dd08v INTO ls_dd08v WITH KEY fieldname = iv_fieldname. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + IF ls_dd08v-cardleft = 'C' AND ls_dd08v-card = '1'. + lv_cardinality = | [1,0..1] |. + ELSEIF ls_dd08v-cardleft = '1' AND ls_dd08v-card = 'C'. + lv_cardinality = | [0..1,1] |. + ELSEIF ls_dd08v-cardleft = '1' AND ls_dd08v-card = '1'. + lv_cardinality = | [1,1] |. + ELSEIF ls_dd08v-cardleft = '1' AND ls_dd08v-card = 'N'. + lv_cardinality = | [1..*,1] |. + ELSEIF ls_dd08v-cardleft = '1' AND ls_dd08v-card = 'CN'. + lv_cardinality = | [0..*,1] |. + ELSEIF ls_dd08v-cardleft = 'C' AND ls_dd08v-card = 'CN'. + lv_cardinality = | [0..*,0..1] |. + ELSEIF ls_dd08v-cardleft = 'C' AND ls_dd08v-card = 'C'. + lv_cardinality = | [0..1,0..1] |. + ELSEIF ls_dd08v-cardleft = 'N' AND ls_dd08v-card = 'N'. + lv_cardinality = | [1..*,] |. + ELSEIF ls_dd08v-cardleft = 'C' AND ls_dd08v-card = 'N'. + lv_cardinality = | [1..*,0..1] |. + ELSEIF ls_dd08v-cardleft IS INITIAL OR ls_dd08v-card IS INITIAL. + lv_cardinality = | |. + ELSE. + ASSERT 1 = 'todo'. + ENDIF. + + rv_ddl = rv_ddl && |\n with foreign key{ lv_cardinality }{ to_lower( ls_dd08v-checktable ) }|. + +* assumption: dd05m table is sorted by PRIMPOS ascending + LOOP AT is_data-dd05m INTO ls_dd05m WHERE fieldname = iv_fieldname AND fortable <> '*'. + IF lv_pre IS INITIAL. + lv_pre = |\n where |. + ELSE. + lv_pre = |\n and |. + ENDIF. + IF ls_dd05m-fortable(1) = |'|. + rv_ddl = rv_ddl && |{ lv_pre }{ to_lower( ls_dd05m-checkfield ) } = { + ls_dd05m-fortable }|. + ELSE. + rv_ddl = rv_ddl && |{ lv_pre }{ to_lower( ls_dd05m-checkfield ) } = { + to_lower( ls_dd05m-fortable ) }.{ to_lower( ls_dd05m-forkey ) }|. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD serialize_fkey_annotations. + + DATA ls_dd08v LIKE LINE OF is_data-dd08v. + + READ TABLE is_data-dd08v INTO ls_dd08v WITH KEY fieldname = iv_fieldname. + IF sy-subrc = 0. + IF ls_dd08v-ddtext IS NOT INITIAL. + rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.label : { escape_string( ls_dd08v-ddtext ) }\n|. + ENDIF. + + IF ls_dd08v-frkart IS NOT INITIAL. + CASE ls_dd08v-frkart. + WHEN 'TEXT'. + rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.keyType : #TEXT_KEY\n|. + WHEN 'REF'. + rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.keyType : #NON_KEY\n|. + WHEN OTHERS. + rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.keyType : #{ ls_dd08v-frkart }\n|. + ENDCASE. + ENDIF. + + IF ls_dd08v-checkflag = abap_false OR ls_dd08v-checkflag = 'N'. + rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.screenCheck : true\n|. + ELSE. + rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.screenCheck : false\n|. + ENDIF. + + IF ls_dd08v-arbgb IS NOT INITIAL. + rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.messageClass : '{ ls_dd08v-arbgb }'\n|. + ENDIF. + IF ls_dd08v-msgnr IS NOT INITIAL. + rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.messageNumber : '{ ls_dd08v-msgnr }'\n|. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD serialize_top. + FIELD-SYMBOLS: TYPE c, " ddpk_is_invhash + TYPE abap_bool. + rv_ddl = rv_ddl && |@EndUserText.label : { escape_string( is_data-dd02v-ddtext ) }\n|. + + CASE is_data-dd02v-exclass. + WHEN '0'. + rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #NOT_CLASSIFIED\n|. + WHEN '1'. + rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE\n|. + WHEN '2'. + rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #EXTENSIBLE_CHARACTER\n|. + WHEN '3'. + rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #EXTENSIBLE_CHARACTER_NUMERIC\n|. + WHEN '4'. + rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #EXTENSIBLE_ANY\n|. + WHEN OTHERS. + ASSERT 1 = 'todo'. + ENDCASE. + + CASE is_data-dd02v-tabclass. + WHEN 'TRANSP'. + " doesn't exist on NW < 750 + ASSIGN COMPONENT 'IS_GTT' OF STRUCTURE is_data-dd02v TO . + IF sy-subrc = 0 AND = abap_true. + rv_ddl = rv_ddl && |@AbapCatalog.tableCategory : #GLOBAL_TEMPORARY\n|. + ELSE. + rv_ddl = rv_ddl && |@AbapCatalog.tableCategory : #TRANSPARENT\n|. + ENDIF. + WHEN OTHERS. + ASSERT 1 = 'todo'. + ENDCASE. + + IF is_data-dd02v-authclass = '01'. + rv_ddl = rv_ddl && |@AbapCatalog.activationType : #NAMETAB_GENERATION_OFFLINE\n|. + ELSEIF is_data-dd02v-authclass = '02'. + rv_ddl = rv_ddl && |@AbapCatalog.activationType : #ADAPT_C_STRUCTURES\n|. + ENDIF. + + rv_ddl = rv_ddl && |@AbapCatalog.deliveryClass : #{ is_data-dd02v-contflag }\n|. + + IF is_data-dd02v-mainflag = abap_true. + rv_ddl = rv_ddl && |@AbapCatalog.dataMaintenance : #ALLOWED\n|. + ELSEIF is_data-dd02v-mainflag = 'N'. + rv_ddl = rv_ddl && |@AbapCatalog.dataMaintenance : #NOT_ALLOWED\n|. + ELSEIF is_data-dd02v-mainflag IS INITIAL. + rv_ddl = rv_ddl && |@AbapCatalog.dataMaintenance : #LIMITED\n|. + ELSE. + rv_ddl = rv_ddl && |@AbapCatalog.dataMaintenance : \n|. + ENDIF. + + " doesn't exist on NW <= 750 + ASSIGN + COMPONENT 'PK_IS_INVHASH' + OF STRUCTURE is_data-dd02v + TO . + IF sy-subrc = 0 AND = abap_true. + rv_ddl = rv_ddl && |@AbapCatalog.primaryKey.invertedHashIndex : true\n|. + ENDIF. + + ENDMETHOD. + METHOD serialize_type. + + DATA lv_notnull TYPE string. + DATA lv_leng TYPE i. + DATA lv_decimals TYPE i. + + IF is_dd03p-notnull = abap_true. + lv_notnull = | not null|. + ENDIF. + + IF is_dd03p-rollname IS NOT INITIAL. + rv_type = |{ to_lower( is_dd03p-rollname ) }{ lv_notnull }|. + ELSE. + lv_leng = is_dd03p-leng. + lv_decimals = is_dd03p-decimals. + CASE is_dd03p-datatype. + WHEN 'STRG'. + rv_type = |abap.string({ lv_leng }){ lv_notnull }|. + WHEN 'RSTR'. + rv_type = |abap.rawstring({ lv_leng }){ lv_notnull }|. + WHEN 'INT4'. + rv_type = |abap.int4{ lv_notnull }|. + WHEN 'ACCP'. + rv_type = |abap.accp{ lv_notnull }|. + WHEN 'LANG'. + rv_type = |abap.lang{ lv_notnull }|. + WHEN 'DATN'. + rv_type = |abap.datn{ lv_notnull }|. + WHEN 'TIMN'. + rv_type = |abap.timn{ lv_notnull }|. + WHEN 'UTCL'. + rv_type = |abap.utcl{ lv_notnull }|. + WHEN 'INT8'. + rv_type = |abap.int8{ lv_notnull }|. + WHEN 'D16D'. + rv_type = |abap.df16_dec({ lv_leng },{ lv_decimals }){ lv_notnull }|. + WHEN 'D16R'. + rv_type = |abap.df16_raw{ lv_notnull }|. + WHEN 'D16S'. + rv_type = |abap.df16_scl{ lv_notnull }|. + WHEN 'D16N'. + rv_type = |abap.d16n{ lv_notnull }|. + WHEN 'D34S'. + rv_type = |abap.df34_scl{ lv_notnull }|. + WHEN 'D34D'. + rv_type = |abap.df34_dec({ lv_leng },{ lv_decimals }){ lv_notnull }|. + WHEN 'D34R'. + rv_type = |abap.df34_raw{ lv_notnull }|. + WHEN 'D34N'. + rv_type = |abap.d34n{ lv_notnull }|. + WHEN 'INT2'. + rv_type = |abap.int2{ lv_notnull }|. + WHEN 'INT1'. + rv_type = |abap.int1{ lv_notnull }|. + WHEN 'CUKY'. + rv_type = |abap.cuky{ lv_notnull }|. + WHEN 'DATS'. + rv_type = |abap.dats{ lv_notnull }|. + WHEN 'TIMS'. + rv_type = |abap.tims{ lv_notnull }|. + WHEN 'FLTP'. + rv_type = |abap.fltp{ lv_notnull }|. + WHEN 'CLNT'. + rv_type = |abap.clnt{ lv_notnull }|. + WHEN 'SSTR'. + rv_type = |abap.sstring({ lv_leng }){ lv_notnull }|. + WHEN 'QUAN'. + rv_type = |abap.quan({ lv_leng },{ lv_decimals }){ lv_notnull }|. + WHEN 'CURR'. + rv_type = |abap.curr({ lv_leng },{ lv_decimals }){ lv_notnull }|. + WHEN 'DEC'. + rv_type = |abap.dec({ lv_leng },{ lv_decimals }){ lv_notnull }|. + WHEN OTHERS. + rv_type = |abap.{ to_lower( is_dd03p-datatype ) }({ lv_leng }){ lv_notnull }|. + ENDCASE. + ENDIF. + + ENDMETHOD. + METHOD serialize_value_help. + + DATA ls_dd35v LIKE LINE OF is_data-dd35v. + DATA ls_dd36m LIKE LINE OF is_data-dd36m. + DATA lv_pre TYPE string. + + READ TABLE is_data-dd35v INTO ls_dd35v WITH KEY fieldname = iv_fieldname. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + rv_ddl = rv_ddl && |\n with value help { to_lower( ls_dd35v-shlpname ) }|. + + LOOP AT is_data-dd36m INTO ls_dd36m + WHERE fieldname = iv_fieldname + AND shlpname = ls_dd35v-shlpname + AND shtype <> 'G'. + IF lv_pre IS INITIAL. + lv_pre = |\n where |. + ELSE. + lv_pre = |\n and |. + ENDIF. + IF ls_dd36m-shtype = 'C'. + rv_ddl = rv_ddl && |{ lv_pre }{ to_lower( ls_dd36m-shlpfield ) } = { + ls_dd36m-shtable }|. + ELSE. + rv_ddl = rv_ddl && |{ lv_pre }{ to_lower( ls_dd36m-shlpfield ) } = { + to_lower( ls_dd36m-shtable ) }.{ to_lower( ls_dd36m-shfield ) }|. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD unescape_string. + rv_string = iv_string. + REPLACE FIRST OCCURRENCE OF REGEX |^'| IN rv_string WITH ||. + REPLACE FIRST OCCURRENCE OF REGEX |'$| IN rv_string WITH ||. + REPLACE ALL OCCURRENCES OF |''| IN rv_string WITH |'|. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_tabl_compar IMPLEMENTATION. + METHOD constructor. + + ms_item = is_item. + + ENDMETHOD. + METHOD get_where_used_recursive. + + DATA: lt_findstrings TYPE string_table, + lt_founds TYPE STANDARD TABLE OF rsfindlst, + lt_scope TYPE ty_seu_obj, + lv_findstring LIKE LINE OF lt_findstrings. + + FIELD-SYMBOLS: TYPE rsfindlst. + + IF iv_object_name IS INITIAL. + RETURN. + ENDIF. + + lt_scope = it_scope. + + lv_findstring = iv_object_name. + INSERT lv_findstring INTO TABLE lt_findstrings. + + DO iv_depth TIMES. + + CLEAR: lt_founds. + + CALL FUNCTION 'RS_EU_CROSSREF' + EXPORTING + i_find_obj_cls = iv_object_type + no_dialog = 'X' + TABLES + i_findstrings = lt_findstrings + o_founds = lt_founds + i_scope_object_cls = lt_scope + EXCEPTIONS + not_executed = 1 + not_found = 2 + illegal_object = 3 + no_cross_for_this_object = 4 + batch = 5 + batchjob_error = 6 + wrong_type = 7 + object_not_exist = 8 + OTHERS = 9. + + IF sy-subrc = 1 OR sy-subrc = 2 OR lines( lt_founds ) = 0. + EXIT. + ELSEIF sy-subrc > 2. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + INSERT LINES OF lt_founds INTO TABLE rt_founds_all. + + CLEAR: lt_findstrings. + + LOOP AT lt_founds ASSIGNING . + + lv_findstring = -object. + INSERT lv_findstring INTO TABLE lt_findstrings. + + ENDLOOP. + + ENDDO. + + ENDMETHOD. + METHOD is_structure_used_in_db_table. + + DATA: lt_scope TYPE ty_seu_obj, + lt_founds TYPE ty_founds. + + APPEND 'TABL' TO lt_scope. + APPEND 'STRU' TO lt_scope. + + lt_founds = get_where_used_recursive( iv_object_name = iv_object_name + iv_object_type = 'STRU' + it_scope = lt_scope + iv_depth = 5 ). + + DELETE lt_founds WHERE object_cls <> 'DT'. + + rv_is_structure_used_in_db_tab = boolc( lines( lt_founds ) > 0 ). + + ENDMETHOD. + METHOD validate. + + DATA: lt_previous_table_fields TYPE TABLE OF dd03p, + ls_previous_table_field LIKE LINE OF lt_previous_table_fields, + lt_current_table_fields TYPE TABLE OF dd03p, + ls_current_table_field LIKE LINE OF lt_current_table_fields, + ls_dd02v TYPE dd02v, + lv_inconsistent TYPE abap_bool. + + FIELD-SYMBOLS TYPE abap_bool. + + ii_remote_version->read( + EXPORTING + iv_name = 'DD02V' + CHANGING + cg_data = ls_dd02v ). + + " We only want to compare transparent tables, or structures used in transparent tables + IF ls_dd02v-tabclass <> 'TRANSP' AND is_structure_used_in_db_table( ls_dd02v-tabname ) = abap_false. + RETURN. + ENDIF. + + " No comparison for global temporary tables + ASSIGN COMPONENT 'IS_GTT' OF STRUCTURE ls_dd02v TO . + IF sy-subrc = 0 AND = abap_true. + RETURN. + ENDIF. + + ii_remote_version->read( + EXPORTING + iv_name = 'DD03P_TABLE' + CHANGING + cg_data = lt_previous_table_fields ). + + ii_local_version->read( + EXPORTING + iv_name = 'DD03P_TABLE' + CHANGING + cg_data = lt_current_table_fields ). + + LOOP AT lt_previous_table_fields INTO ls_previous_table_field. + READ TABLE lt_current_table_fields WITH KEY fieldname = ls_previous_table_field-fieldname + INTO ls_current_table_field. + IF sy-subrc = 0. + IF ls_current_table_field-rollname <> ls_previous_table_field-rollname. + IF ls_current_table_field-rollname IS NOT INITIAL AND ls_previous_table_field-rollname IS NOT INITIAL. + ii_log->add_info( + iv_msg = |Field { ls_previous_table_field-fieldname }: | & + |Data element changed from { ls_previous_table_field-rollname } | & + |to { ls_current_table_field-rollname }| + is_item = ms_item ). + ELSEIF ls_current_table_field-rollname IS NOT INITIAL. + ii_log->add_info( + iv_msg = |Field { ls_previous_table_field-fieldname }: | & + |Data type changed from internal type | & + |{ ls_previous_table_field-inttype }(length { ls_previous_table_field-intlen }) | & + |to data element { ls_current_table_field-rollname }| + is_item = ms_item ). + ELSEIF ls_previous_table_field-rollname IS NOT INITIAL. + ii_log->add_info( + iv_msg = |Field { ls_previous_table_field-fieldname }: | & + |Data type changed from date element { ls_previous_table_field-rollname } | & + |to internal type | & + |{ ls_current_table_field-inttype }(length { ls_current_table_field-intlen })| + is_item = ms_item ). + ENDIF. + "TODO: perform several other checks, e.g. field length truncated, ... + lv_inconsistent = abap_true. + ENDIF. + ELSE. + ii_log->add_info( iv_msg = |Field { ls_previous_table_field-fieldname } removed| + is_item = ms_item ). + lv_inconsistent = abap_true. + ENDIF. + ENDLOOP. + + IF lv_inconsistent = abap_true. + rv_message = 'Fields were changed!'. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_comparator~compare. + + IF zcl_abapgit_objects=>exists( ms_item ) = abap_false. + RETURN. + ENDIF. + + rs_result-text = validate( + ii_remote_version = ii_remote + ii_local_version = ii_local + ii_log = ii_log ). + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb DEFINITION DEFERRED. +* renamed: zcl_abapgit_object_tabl :: lcl_tabl_xml +CLASS kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb DEFINITION FINAL. + PUBLIC SECTION. + CLASS-METHODS add + IMPORTING + io_xml TYPE REF TO zif_abapgit_xml_output + is_internal TYPE zif_abapgit_object_tabl=>ty_internal + RAISING + zcx_abapgit_exception. + + CLASS-METHODS read + IMPORTING + io_xml TYPE REF TO zif_abapgit_xml_input + RETURNING + VALUE(rs_internal) TYPE zif_abapgit_object_tabl=>ty_internal + RAISING + zcx_abapgit_exception. +ENDCLASS. + +CLASS kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb IMPLEMENTATION. + METHOD add. + +* adding to xml must be done in the right sequence to avoid changes + io_xml->add( iv_name = 'DD02V' + ig_data = is_internal-dd02v ). + IF NOT is_internal-dd09l IS INITIAL. + io_xml->add( iv_name = 'DD09L' + ig_data = is_internal-dd09l ). + ENDIF. + io_xml->add( iv_name = 'DD03P_TABLE' + ig_data = is_internal-dd03p ). + io_xml->add( iv_name = 'DD05M_TABLE' + ig_data = is_internal-dd05m ). + io_xml->add( iv_name = 'DD08V_TABLE' + ig_data = is_internal-dd08v ). + io_xml->add( iv_name = 'DD12V' + ig_data = is_internal-dd12v ). + io_xml->add( iv_name = 'DD17V' + ig_data = is_internal-dd17v ). + io_xml->add( iv_name = 'DD35V_TALE' + ig_data = is_internal-dd35v ). + io_xml->add( iv_name = 'DD36M' + ig_data = is_internal-dd36m ). + + IF lines( is_internal-i18n_langs ) > 0. + io_xml->add( iv_name = 'I18N_LANGS' + ig_data = is_internal-i18n_langs ). + + io_xml->add( iv_name = 'DD02_TEXTS' + ig_data = is_internal-dd02_texts ). + ENDIF. + + io_xml->add( iv_name = 'LONGTEXTS' + ig_data = is_internal-longtexts ). + + io_xml->add( iv_name = zif_abapgit_object_tabl=>c_s_dataname-segment_definition + ig_data = is_internal-segment_definitions ). + + io_xml->add( iv_name = zif_abapgit_object_tabl=>c_s_dataname-tabl_extras + ig_data = is_internal-extras ). + + ENDMETHOD. + + METHOD read. + + io_xml->read( + EXPORTING iv_name = zif_abapgit_object_tabl=>c_s_dataname-segment_definition + CHANGING cg_data = rs_internal-segment_definitions ). + io_xml->read( + EXPORTING iv_name = 'DD02V' + CHANGING cg_data = rs_internal-dd02v ). + io_xml->read( + EXPORTING iv_name = 'DD09L' + CHANGING cg_data = rs_internal-dd09l ). + io_xml->read( + EXPORTING iv_name = 'DD03P_TABLE' + CHANGING cg_data = rs_internal-dd03p ). + io_xml->read( + EXPORTING iv_name = 'DD05M_TABLE' + CHANGING cg_data = rs_internal-dd05m ). + io_xml->read( + EXPORTING iv_name = 'DD08V_TABLE' + CHANGING cg_data = rs_internal-dd08v ). + io_xml->read( + EXPORTING iv_name = 'DD35V_TALE' + CHANGING cg_data = rs_internal-dd35v ). + io_xml->read( + EXPORTING iv_name = 'DD36M' + CHANGING cg_data = rs_internal-dd36m ). + io_xml->read( + EXPORTING iv_name = zif_abapgit_object_tabl=>c_s_dataname-tabl_extras + CHANGING cg_data = rs_internal-extras ). + io_xml->read( + EXPORTING iv_name = 'DD12V' + CHANGING cg_data = rs_internal-dd12v ). + io_xml->read( + EXPORTING iv_name = 'DD17V' + CHANGING cg_data = rs_internal-dd17v ). + io_xml->read( + EXPORTING iv_name = 'I18N_LANGS' + CHANGING cg_data = rs_internal-i18n_langs ). + io_xml->read( + EXPORTING iv_name = 'DD02_TEXTS' + CHANGING cg_data = rs_internal-dd02_texts ). + io_xml->read( + EXPORTING iv_name = 'LONGTEXTS' + CHANGING cg_data = rs_internal-longtexts ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_TABL IMPLEMENTATION. + METHOD clear_dd03p_fields. + + CONSTANTS lc_comptype_dataelement TYPE comptype VALUE 'E'. + + DATA: lv_masklen TYPE c LENGTH 4. + + FIELD-SYMBOLS: TYPE dd03p. + +* remove nested structures + DELETE ct_dd03p WHERE depth <> '00'. +* remove fields from .INCLUDEs + DELETE ct_dd03p WHERE adminfield <> '0'. + + LOOP AT ct_dd03p ASSIGNING WHERE NOT rollname IS INITIAL. + + clear_dd03p_fields_common( CHANGING cs_dd03p = ). + + lv_masklen = -masklen. + IF lv_masklen = '' OR NOT lv_masklen CO '0123456789'. +* make sure the field contains valid data, or the XML will dump + CLEAR -masklen. + ENDIF. + + IF -comptype = lc_comptype_dataelement. + clear_dd03p_fields_dataelement( CHANGING cs_dd03p = ). + ENDIF. + + IF -shlporigin = 'D'. +* search help from domain + CLEAR: -shlpfield, + -shlpname. + ENDIF. + +* XML output assumes correct field content + IF -routputlen = ' '. + CLEAR -routputlen. + ENDIF. + + ENDLOOP. + + " Clear position to avoid issues with include structures that contain different number of fields + LOOP AT ct_dd03p ASSIGNING . + CLEAR: -position, -tabname, -ddlanguage. + ENDLOOP. + + ENDMETHOD. + METHOD clear_dd03p_fields_common. + + CLEAR: cs_dd03p-ddlanguage, + cs_dd03p-dtelmaster, + cs_dd03p-logflag, + cs_dd03p-ddtext, + cs_dd03p-reservedte, + cs_dd03p-reptext, + cs_dd03p-scrtext_s, + cs_dd03p-scrtext_m, + cs_dd03p-scrtext_l. + + ENDMETHOD. + METHOD clear_dd03p_fields_dataelement. + +* type specified via data element + CLEAR: cs_dd03p-domname, + cs_dd03p-inttype, + cs_dd03p-intlen, + cs_dd03p-mask, + cs_dd03p-memoryid, + cs_dd03p-headlen, + cs_dd03p-scrlen1, + cs_dd03p-scrlen2, + cs_dd03p-scrlen3, + cs_dd03p-datatype, + cs_dd03p-leng, + cs_dd03p-outputlen, + cs_dd03p-deffdname, + cs_dd03p-convexit, + cs_dd03p-entitytab, + cs_dd03p-dommaster, + cs_dd03p-domname3l, + cs_dd03p-decimals, + cs_dd03p-lowercase, + cs_dd03p-signflag. + + ENDMETHOD. + METHOD delete_extras. + + DELETE FROM tddat WHERE tabname = iv_tabname. + + ENDMETHOD. + METHOD delete_idoc_segment. + + DATA lv_segment_type TYPE edilsegtyp. + DATA lv_result LIKE sy-subrc. + + IF is_idoc_segment( ) = abap_false. + rv_deleted = abap_false. + RETURN. "previous XML version or no IDoc segment + ENDIF. + + rv_deleted = abap_true. + lv_segment_type = ms_item-obj_name. + + CALL FUNCTION 'SEGMENT_DELETE' + EXPORTING + segmenttyp = lv_segment_type + IMPORTING + result = lv_result + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0 OR lv_result <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDMETHOD. + METHOD deserialize_idoc_segment. + + DATA lv_result LIKE sy-subrc. + DATA lv_package TYPE devclass. + DATA lv_transport TYPE trkorr. + DATA ls_edisdef TYPE edisdef. + DATA ls_segment_definition TYPE zif_abapgit_object_tabl=>ty_segment_definition. + FIELD-SYMBOLS TYPE zif_abapgit_object_tabl=>ty_segment_definition. + + rv_deserialized = abap_false. + + IF lines( is_internal-segment_definitions ) = 0. + RETURN. "no IDoc segment + ENDIF. + + rv_deserialized = abap_true. + + lv_package = iv_package. + lv_transport = iv_transport. + + LOOP AT is_internal-segment_definitions ASSIGNING . + ls_segment_definition = . + ls_segment_definition-segmentheader-presp = sy-uname. + ls_segment_definition-segmentheader-pwork = sy-uname. + + CALL FUNCTION 'SEGMENT_READ' + EXPORTING + segmenttyp = ls_segment_definition-segmentdefinition-segtyp + IMPORTING + result = lv_result + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0 OR lv_result <> 0. + CALL FUNCTION 'SEGMENT_CREATE' + IMPORTING + segmentdefinition = ls_segment_definition-segmentdefinition + TABLES + segmentstructure = ls_segment_definition-segmentstructures + CHANGING + segmentheader = ls_segment_definition-segmentheader + devclass = lv_package + EXCEPTIONS + OTHERS = 1. + ELSE. + + CALL FUNCTION 'SEGMENT_MODIFY' + CHANGING + segmentheader = ls_segment_definition-segmentheader + devclass = lv_package + EXCEPTIONS + OTHERS = 1. + IF sy-subrc = 0. + CALL FUNCTION 'SEGMENTDEFINITION_MODIFY' + TABLES + segmentstructure = ls_segment_definition-segmentstructures + CHANGING + segmentdefinition = ls_segment_definition-segmentdefinition + EXCEPTIONS + OTHERS = 1. + ENDIF. + ENDIF. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " Check status of segment as stored in repo (field-symbol) + IF -segmentdefinition-closed = abap_true. + IF lv_transport IS NOT INITIAL. + CALL FUNCTION 'SEGMENTDEFINITION_CLOSE' + EXPORTING + segmenttyp = ls_segment_definition-segmentdefinition-segtyp + CHANGING + order = lv_transport + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + " SEGMENTDEFINITION_CLOSE saves current release but it should be same as in repo + SELECT SINGLE * FROM edisdef INTO ls_edisdef + WHERE segtyp = ls_segment_definition-segmentdefinition-segtyp + AND version = ls_segment_definition-segmentdefinition-version. + ls_edisdef-released = -segmentdefinition-released. + ls_edisdef-applrel = -segmentdefinition-applrel. + ls_edisdef-closed = -segmentdefinition-closed. + UPDATE edisdef FROM ls_edisdef. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error updating IDOC segment { + ls_segment_definition-segmentdefinition-segtyp }| ). + ENDIF. + ENDIF. + ENDLOOP. + + zcl_abapgit_factory=>get_tadir( )->insert_single( + iv_object = ms_item-obj_type + iv_obj_name = ms_item-obj_name + iv_package = iv_package + iv_language = mv_language + iv_set_edtflag = abap_true ). + ENDMETHOD. + METHOD deserialize_indexes. + + DATA: + lv_name TYPE ddobjname, + lv_subrc TYPE sy-subrc, + lt_dd12v_db LIKE is_internal-dd12v, + ls_dd12v LIKE LINE OF is_internal-dd12v, + ls_dd17v LIKE LINE OF is_internal-dd17v, + lt_secondary LIKE is_internal-dd17v. + + lv_name = ms_item-obj_name. + + " Get existing indexes and drop the ones that are not included in remote + CALL FUNCTION 'DDIF_TABL_GET' + EXPORTING + name = lv_name + langu = mv_language + TABLES + dd12v_tab = lt_dd12v_db + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from DDIF_TABL_GET' ). + ENDIF. + + LOOP AT lt_dd12v_db INTO ls_dd12v. + READ TABLE is_internal-dd12v TRANSPORTING NO FIELDS WITH KEY + sqltab = ls_dd12v-sqltab + indexname = ls_dd12v-indexname. + IF sy-subrc <> 0. + CALL FUNCTION 'DD_INDX_DEL' + EXPORTING + sqltab = ls_dd12v-sqltab + indexname = ls_dd12v-indexname + del_state = 'M' "all states + IMPORTING + rc = lv_subrc. + IF lv_subrc <> 0. + zcx_abapgit_exception=>raise( |Error deleting index { ls_dd12v-sqltab }~{ ls_dd12v-indexname }| ). + ENDIF. + ENDIF. + ENDLOOP. + + " Create new or update existing indexes + LOOP AT is_internal-dd12v INTO ls_dd12v. + + CLEAR lt_secondary. + LOOP AT is_internal-dd17v INTO ls_dd17v + WHERE sqltab = ls_dd12v-sqltab AND indexname = ls_dd12v-indexname. + APPEND ls_dd17v TO lt_secondary. + ENDLOOP. + + CALL FUNCTION 'DDIF_INDX_PUT' + EXPORTING + name = ls_dd12v-sqltab + id = ls_dd12v-indexname + dd12v_wa = ls_dd12v + TABLES + dd17v_tab = lt_secondary + EXCEPTIONS + indx_not_found = 1 + name_inconsistent = 2 + indx_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " Secondary indexes are automatically activated as part of R3TR TABL + " So there's no need to add them to activation queue + ENDLOOP. + + ENDMETHOD. + METHOD deserialize_texts. + + DATA: lv_name TYPE ddobjname, + ls_dd02v_tmp TYPE dd02v. + + FIELD-SYMBOLS: LIKE LINE OF cs_internal-i18n_langs, + LIKE LINE OF cs_internal-dd02_texts. + + lv_name = ms_item-obj_name. + + mo_i18n_params->trim_saplang_list( CHANGING ct_sap_langs = cs_internal-i18n_langs ). + + SORT cs_internal-i18n_langs. + SORT cs_internal-dd02_texts BY ddlanguage. " Optimization + + LOOP AT cs_internal-i18n_langs ASSIGNING . + + " Table description + ls_dd02v_tmp = cs_internal-dd02v. + READ TABLE cs_internal-dd02_texts ASSIGNING WITH KEY ddlanguage = . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |DD02_TEXTS cannot find lang { } in XML| ). + ENDIF. + MOVE-CORRESPONDING TO ls_dd02v_tmp. + CALL FUNCTION 'DDIF_TABL_PUT' + EXPORTING + name = lv_name + dd02v_wa = ls_dd02v_tmp + EXCEPTIONS + tabl_not_found = 1 + name_inconsistent = 2 + tabl_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD is_db_table_category. + + " values from domain TABCLASS + rv_is_db_table_type = boolc( iv_tabclass = 'TRANSP' + OR iv_tabclass = 'CLUSTER' + OR iv_tabclass = 'POOL' ). + + ENDMETHOD. + METHOD is_idoc_segment. + + DATA lv_segment_type TYPE edilsegtyp. + + lv_segment_type = ms_item-obj_name. + + SELECT SINGLE segtyp + FROM edisegment + INTO lv_segment_type + WHERE segtyp = lv_segment_type. + rv_is_idoc_segment = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD read_extras. + + SELECT SINGLE * FROM tddat INTO rs_tabl_extras-tddat WHERE tabname = iv_tabname. + + rs_tabl_extras-abap_language_version = get_abap_language_version( ). + + ENDMETHOD. + METHOD serialize_idoc_segment. + + DATA lv_segment_type TYPE edilsegtyp. + DATA lv_result LIKE sy-subrc. + DATA lv_devclass TYPE devclass. + DATA lt_segmentdefinitions TYPE STANDARD TABLE OF edisegmdef. + DATA ls_segment_definition TYPE zif_abapgit_object_tabl=>ty_segment_definition. + + FIELD-SYMBOLS: TYPE edisegmdef. + + IF is_idoc_segment( ) = abap_false. + RETURN. + ENDIF. + + lv_segment_type = ms_item-obj_name. + CALL FUNCTION 'SEGMENT_READ' + EXPORTING + segmenttyp = lv_segment_type + IMPORTING + result = lv_result + TABLES + segmentdefinition = lt_segmentdefinitions + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0 OR lv_result <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + LOOP AT lt_segmentdefinitions ASSIGNING . + CLEAR ls_segment_definition. + CALL FUNCTION 'SEGMENTDEFINITION_READ' + EXPORTING + segmenttyp = -segtyp + IMPORTING + result = lv_result + devclass = lv_devclass + segmentheader = ls_segment_definition-segmentheader + segmentdefinition = ls_segment_definition-segmentdefinition + TABLES + segmentstructure = ls_segment_definition-segmentstructures + CHANGING + version = -version + EXCEPTIONS + no_authority = 1 + segment_not_existing = 2 + OTHERS = 3. + IF sy-subrc <> 0 OR lv_result <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + zcl_abapgit_object_idoc=>clear_idoc_segement_fields( + CHANGING cg_structure = ls_segment_definition-segmentdefinition ). + zcl_abapgit_object_idoc=>clear_idoc_segement_fields( + CHANGING cg_structure = ls_segment_definition-segmentheader ). + + APPEND ls_segment_definition TO cs_internal-segment_definitions. + ENDLOOP. + + ENDMETHOD. + METHOD serialize_texts. + + DATA: lv_name TYPE ddobjname, + lv_index TYPE i, + ls_dd02v TYPE dd02v, + lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. + + FIELD-SYMBOLS: LIKE LINE OF cs_internal-i18n_langs, + LIKE LINE OF cs_internal-dd02_texts. + + IF mo_i18n_params->ms_params-main_language_only = abap_true. + RETURN. + ENDIF. + + lv_name = ms_item-obj_name. + + " Collect additional languages, skip main lang - it was serialized already + lt_language_filter = mo_i18n_params->build_language_filter( ). + + SELECT DISTINCT ddlanguage AS langu INTO TABLE cs_internal-i18n_langs + FROM dd02v + WHERE tabname = lv_name + AND ddlanguage IN lt_language_filter + AND ddlanguage <> mv_language + ORDER BY langu. "#EC CI_SUBRC + + LOOP AT cs_internal-i18n_langs ASSIGNING . + lv_index = sy-tabix. + CALL FUNCTION 'DDIF_TABL_GET' + EXPORTING + name = lv_name + langu = + IMPORTING + dd02v_wa = ls_dd02v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0 OR ls_dd02v-ddlanguage IS INITIAL. + DELETE cs_internal-i18n_langs INDEX lv_index. " Don't save this lang + CONTINUE. + ENDIF. + + APPEND INITIAL LINE TO cs_internal-dd02_texts ASSIGNING . + MOVE-CORRESPONDING ls_dd02v TO . + ENDLOOP. + + SORT cs_internal-i18n_langs ASCENDING. + SORT cs_internal-dd02_texts BY ddlanguage ASCENDING. + + ENDMETHOD. + METHOD update_extras. + + DATA lv_abap_language_version TYPE uccheck. + + IF is_tabl_extras-tddat IS INITIAL. + delete_extras( iv_tabname ). + ELSE. + MODIFY tddat FROM is_tabl_extras-tddat. + ENDIF. + + " Fields that are not part of dd02v + TRY. + lv_abap_language_version = is_tabl_extras-abap_language_version. + + set_abap_language_version( CHANGING cv_abap_language_version = lv_abap_language_version ). + + UPDATE ('DD02L') SET abap_language_version = lv_abap_language_version WHERE tabname = iv_tabname. + CATCH cx_sy_dynamic_osql_semantics ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + TYPES: BEGIN OF ty_data, + as4user TYPE dd02l-as4user, + as4date TYPE dd02l-as4date, + as4time TYPE dd02l-as4time, + END OF ty_data. + + DATA: lt_data TYPE STANDARD TABLE OF ty_data WITH DEFAULT KEY, + ls_data LIKE LINE OF lt_data. + SELECT as4user as4date as4time + FROM dd02l INTO TABLE lt_data + WHERE tabname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000' + ORDER BY PRIMARY KEY. + + SELECT as4user as4date as4time + APPENDING TABLE lt_data + FROM dd09l + WHERE tabname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000' + ORDER BY PRIMARY KEY. + + SELECT as4user as4date as4time + APPENDING TABLE lt_data + FROM dd12l + WHERE sqltab = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000' + ORDER BY PRIMARY KEY. + + SORT lt_data BY as4date DESCENDING as4time DESCENDING. + + READ TABLE lt_data INDEX 1 INTO ls_data. + IF sy-subrc = 0. + rv_user = ls_data-as4user. + ELSE. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lv_objname TYPE rsedd0-ddobjname, + lv_no_ask TYPE abap_bool, + lv_subrc TYPE sy-subrc, + BEGIN OF ls_dd02l, + tabname TYPE dd02l-tabname, + tabclass TYPE dd02l-tabclass, + sqltab TYPE dd02l-sqltab, + END OF ls_dd02l. + + IF zif_abapgit_object~exists( ) = abap_false. + " Proxies e.g. delete on its own, nothing todo here then. + RETURN. + ENDIF. + + lv_objname = ms_item-obj_name. + + IF delete_idoc_segment( ) = abap_false. + + lv_no_ask = abap_true. + SELECT SINGLE tabname tabclass sqltab FROM dd02l + INTO CORRESPONDING FIELDS OF ls_dd02l + WHERE tabname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + IF sy-subrc = 0 AND is_db_table_category( ls_dd02l-tabclass ) = abap_true. + + CALL FUNCTION 'DD_EXISTS_DATA' + EXPORTING + reftab = ls_dd02l-sqltab + tabclass = ls_dd02l-tabclass + tabname = ls_dd02l-tabname + IMPORTING + subrc = lv_subrc + EXCEPTIONS + missing_reftab = 1 + sql_error = 2 + buffer_overflow = 3 + unknown_error = 4 + OTHERS = 5. + + IF sy-subrc = 0 AND lv_subrc = 0. + lv_no_ask = abap_false. + ENDIF. + + ENDIF. + + delete_ddic( iv_objtype = 'T' + iv_no_ask = lv_no_ask ). + + delete_longtexts( c_longtext_id_tabl ). + + delete_extras( lv_objname ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lv_name TYPE ddobjname, + ls_internal TYPE zif_abapgit_object_tabl=>ty_internal. + + FIELD-SYMBOLS: TYPE dd03p, + TYPE dd05m, + TYPE dd08v, + TYPE dd35v, + TYPE dd36m, + TYPE any. + + lv_name = ms_item-obj_name. " type conversion + + ls_internal = kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb=>read( io_xml ). + + IF deserialize_idoc_segment( is_internal = ls_internal + iv_transport = iv_transport + iv_package = iv_package ) = abap_false. + + ASSIGN COMPONENT 'ROWORCOLST' OF STRUCTURE ls_internal-dd09l TO . + IF sy-subrc = 0 AND IS INITIAL. + = 'C'. "Reverse fix from serialize + ENDIF. + + " Number fields sequentially and fill table name + LOOP AT ls_internal-dd03p ASSIGNING . + -position = sy-tabix. + -tabname = lv_name. + -ddlanguage = mv_language. + ENDLOOP. + + LOOP AT ls_internal-dd05m ASSIGNING . + -tabname = lv_name. + ENDLOOP. + LOOP AT ls_internal-dd08v ASSIGNING . + -tabname = lv_name. + -ddlanguage = mv_language. + ENDLOOP. + LOOP AT ls_internal-dd35v ASSIGNING . + -tabname = lv_name. + ENDLOOP. + LOOP AT ls_internal-dd36m ASSIGNING . + -tabname = lv_name. + ENDLOOP. + + corr_insert( iv_package = iv_package + ig_object_class = 'DICT' ). + + CALL FUNCTION 'DD_TABL_EXPAND' + EXPORTING + dd02v_wa = ls_internal-dd02v + TABLES + dd03p_tab = ls_internal-dd03p + dd05m_tab = ls_internal-dd05m + dd08v_tab = ls_internal-dd08v + dd35v_tab = ls_internal-dd35v + dd36m_tab = ls_internal-dd36m + EXCEPTIONS + illegal_parameter = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'DDIF_TABL_PUT' + EXPORTING + name = lv_name + dd02v_wa = ls_internal-dd02v + dd09l_wa = ls_internal-dd09l + TABLES + dd03p_tab = ls_internal-dd03p + dd05m_tab = ls_internal-dd05m + dd08v_tab = ls_internal-dd08v + dd35v_tab = ls_internal-dd35v + dd36m_tab = ls_internal-dd36m + EXCEPTIONS + tabl_not_found = 1 + name_inconsistent = 2 + tabl_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + zcl_abapgit_objects_activation=>add_item( ms_item ). + + deserialize_indexes( ls_internal ). + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + deserialize_texts( CHANGING cs_internal = ls_internal ). + ENDIF. + + deserialize_longtexts( ii_xml = io_xml + iv_longtext_id = c_longtext_id_tabl ). + + update_extras( iv_tabname = lv_name + is_tabl_extras = ls_internal-extras ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~exists. + + DATA lv_tabname TYPE dd02l-tabname. + DATA ls_x030l TYPE x030l. + + lv_tabname = ms_item-obj_name. + + " Check nametab because it's fast + CALL FUNCTION 'DD_GET_NAMETAB_HEADER' + EXPORTING + tabname = lv_tabname + IMPORTING + x030l_wa = ls_x030l + EXCEPTIONS + not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + " Check for new, inactive, or modified versions that might not be in nametab + SELECT SINGLE tabname FROM dd02l INTO lv_tabname + WHERE tabname = lv_tabname. "#EC CI_NOORDER + ENDIF. + rv_bool = boolc( sy-subrc = 0 ). + + " Skip TABL structures generated by CHDO + IF rv_bool = abap_true AND ( ls_x030l-tabtype = 'J' OR ls_x030l-tabtype IS INITIAL ). + SELECT SINGLE tabname FROM tcdrs INTO lv_tabname WHERE tabname = lv_tabname. + IF sy-subrc = 0. + rv_bool = abap_false. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + " Moved to zcl_abapgit_objects_compare + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + APPEND zif_abapgit_object=>gc_step_id-lxe TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' + iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). + + ENDMETHOD. + METHOD zif_abapgit_object~jump. + " Covered by ZCL_ABAPGIT_OBJECT=>JUMP + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + + DATA: lv_name TYPE ddobjname, + lv_state TYPE ddgotstate, + ls_internal TYPE zif_abapgit_object_tabl=>ty_internal, + lv_index LIKE sy-index. + + FIELD-SYMBOLS: LIKE LINE OF ls_internal-dd12v, + LIKE LINE OF ls_internal-dd05m, + LIKE LINE OF ls_internal-dd08v, + LIKE LINE OF ls_internal-dd35v, + LIKE LINE OF ls_internal-dd36m, + LIKE LINE OF ls_internal-dd03p, + TYPE any, + TYPE any. + + lv_name = ms_item-obj_name. + + CALL FUNCTION 'DDIF_TABL_GET' + EXPORTING + name = lv_name + langu = mv_language + IMPORTING + gotstate = lv_state + dd02v_wa = ls_internal-dd02v + dd09l_wa = ls_internal-dd09l + TABLES + dd03p_tab = ls_internal-dd03p + dd05m_tab = ls_internal-dd05m + dd08v_tab = ls_internal-dd08v + dd12v_tab = ls_internal-dd12v + dd17v_tab = ls_internal-dd17v + dd35v_tab = ls_internal-dd35v + dd36m_tab = ls_internal-dd36m + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from DDIF_TABL_GET' ). + ENDIF. + + " Check if any active version was returned + IF lv_state <> 'A'. + RETURN. + ENDIF. + + CLEAR: ls_internal-dd02v-as4user, + ls_internal-dd02v-as4date, + ls_internal-dd02v-as4time. + +* reset numeric field, so XML does not crash + IF ls_internal-dd02v-prozpuff = ''. + CLEAR ls_internal-dd02v-prozpuff. + ENDIF. + IF ls_internal-dd02v-datmin = ''. + CLEAR ls_internal-dd02v-datmin. + ENDIF. + IF ls_internal-dd02v-datmax = ''. + CLEAR ls_internal-dd02v-datmax. + ENDIF. + IF ls_internal-dd02v-datavg = ''. + CLEAR ls_internal-dd02v-datavg. + ENDIF. + + CLEAR: ls_internal-dd09l-as4user, + ls_internal-dd09l-as4date, + ls_internal-dd09l-as4time. + + ASSIGN COMPONENT 'ROWORCOLST' OF STRUCTURE ls_internal-dd09l TO . + IF sy-subrc = 0 AND = 'C'. + CLEAR . "To avoid diff errors. This field doesn't exist in all releases + ENDIF. + + LOOP AT ls_internal-dd03p ASSIGNING . + ASSIGN COMPONENT 'ACTFLAG' OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . "To avoid diffs. This field doesn't exist in all releases + ENDIF. + ENDLOOP. + + LOOP AT ls_internal-dd12v ASSIGNING . + CLEAR: -as4user, + -as4date, + -as4time, + -dbindex. + IF -dbstate IS INITIAL OR -dbstate = 'O'. + " These settings are only relevant if database-specific indexes are defined (dbstate = 'D') + CLEAR: + -dbinclexcl, + -dbsyssel1, + -dbsyssel2, + -dbsyssel3, + -dbsyssel4. + ENDIF. + ENDLOOP. + + clear_dd03p_fields( CHANGING ct_dd03p = ls_internal-dd03p ). + +* remove foreign keys inherited from .INCLUDEs + DELETE ls_internal-dd08v WHERE noinherit = 'N'. + LOOP AT ls_internal-dd05m ASSIGNING . + CLEAR -tabname. + CLEAR -leng. + lv_index = sy-tabix. + READ TABLE ls_internal-dd08v WITH KEY fieldname = -fieldname TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + DELETE ls_internal-dd05m INDEX lv_index. + ENDIF. + ENDLOOP. + + LOOP AT ls_internal-dd08v ASSIGNING . + CLEAR: -tabname, -ddlanguage. + ENDLOOP. + LOOP AT ls_internal-dd35v ASSIGNING . + CLEAR -tabname. + ENDLOOP. + +* remove inherited search helps + DELETE ls_internal-dd35v WHERE shlpinher = abap_true. + LOOP AT ls_internal-dd36m ASSIGNING . + CLEAR -tabname. + CLEAR -rollname. + CLEAR -domname. + CLEAR -datatype. + CLEAR -leng. + lv_index = sy-tabix. + READ TABLE ls_internal-dd35v WITH KEY fieldname = -fieldname TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + DELETE ls_internal-dd36m INDEX lv_index. + ENDIF. + ENDLOOP. + + SORT ls_internal-dd36m BY flposition. + + IF mo_i18n_params->is_lxe_applicable( ) = abap_false. + serialize_texts( CHANGING cs_internal = ls_internal ). + ENDIF. + + ls_internal-longtexts = zcl_abapgit_factory=>get_longtexts( )->serialize( + iv_object_name = ms_item-obj_name + iv_longtext_id = c_longtext_id_tabl + io_i18n_params = mo_i18n_params + ii_xml = io_xml ). + + serialize_idoc_segment( CHANGING cs_internal = ls_internal ). + + ls_internal-extras = read_extras( lv_name ). + + kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb=>add( + io_xml = io_xml + is_internal = ls_internal ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_sap_report IMPLEMENTATION. + METHOD authorization_check. + + IF is_item IS NOT INITIAL. + TRY. + CALL FUNCTION 'RS_ACCESS_PERMISSION' + EXPORTING + mode = iv_mode + object = is_item-obj_name + object_class = is_item-obj_type + suppress_corr_check = abap_true + suppress_language_check = abap_true + suppress_extend_dialog = abap_true + abap_langu_version_upon_insert = is_item-abap_language_version " does not exist on lower releases + EXCEPTIONS + canceled_in_corr = 1 + enqueued_by_user = 2 + enqueue_system_failure = 3 + illegal_parameter_values = 4 + locked_by_author = 5 + no_modify_permission = 6 + no_show_permission = 7 + permission_failure = 8 + request_language_denied = 9 + OTHERS = 10 ##FM_SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. + CALL FUNCTION 'RS_ACCESS_PERMISSION' + EXPORTING + mode = iv_mode + object = is_item-obj_name + object_class = is_item-obj_type + suppress_corr_check = abap_true + suppress_language_check = abap_true + suppress_extend_dialog = abap_true + EXCEPTIONS + canceled_in_corr = 1 + enqueued_by_user = 2 + enqueue_system_failure = 3 + illegal_parameter_values = 4 + locked_by_author = 5 + no_modify_permission = 6 + no_show_permission = 7 + permission_failure = 8 + request_language_denied = 9 + OTHERS = 10 ##FM_SUBRC_OK. + ENDTRY. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_sap_report~delete_report. + + authorization_check( + iv_mode = 'DELETE' + is_item = is_item ). + + DELETE REPORT iv_name. + + IF sy-subrc <> 0 AND iv_raise_error = abap_true. + zcx_abapgit_exception=>raise( |Error deleting report { iv_name }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_sap_report~insert_report. + + ASSERT iv_state CA ' AI'. + ASSERT iv_program_type CA ' 1FIJKMST'. + + authorization_check( + iv_mode = 'MODIFY' + is_item = is_item ). + + IF iv_state IS INITIAL. + INSERT REPORT iv_name FROM it_source. + ELSEIF iv_program_type IS INITIAL AND iv_extension_type IS INITIAL. + INSERT REPORT iv_name FROM it_source + STATE iv_state. + ELSEIF iv_extension_type IS INITIAL. + INSERT REPORT iv_name FROM it_source + STATE iv_state + PROGRAM TYPE iv_program_type. + ELSE. + INSERT REPORT iv_name FROM it_source + STATE iv_state + EXTENSION TYPE iv_extension_type + PROGRAM TYPE iv_program_type. + ENDIF. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error inserting report { iv_name }| ). + ENDIF. + + " In lower releases, INSERT REPORT does not support setting ABAP Language version (VERSION) + " Therefore, update the flag directly + UPDATE progdir SET uccheck = iv_version WHERE name = iv_name AND state = iv_state. + + ENDMETHOD. + METHOD zif_abapgit_sap_report~read_progdir. + + DATA ls_sapdir TYPE progdir. + + CALL FUNCTION 'READ_PROGDIR' + EXPORTING + i_progname = iv_name + i_state = iv_state + IMPORTING + e_progdir = ls_sapdir + EXCEPTIONS + not_exists = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + MOVE-CORRESPONDING ls_sapdir TO rs_progdir. + + CLEAR: rs_progdir-edtx, + rs_progdir-cnam, + rs_progdir-cdat, + rs_progdir-unam, + rs_progdir-udat, + rs_progdir-levl, + rs_progdir-vern, + rs_progdir-rmand, + rs_progdir-sdate, + rs_progdir-stime, + rs_progdir-idate, + rs_progdir-itime, + rs_progdir-varcl, + rs_progdir-state. + + ENDMETHOD. + METHOD zif_abapgit_sap_report~read_report. + + ASSERT iv_state CA ' AI'. + + authorization_check( + iv_mode = 'SHOW' + is_item = is_item ). + + IF iv_state IS INITIAL. + READ REPORT iv_name INTO rt_source. + ELSE. + READ REPORT iv_name INTO rt_source STATE iv_state. + ENDIF. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error reading report { iv_name }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_sap_report~update_progdir. + + DATA ls_progdir_new TYPE progdir. + + CALL FUNCTION 'READ_PROGDIR' + EXPORTING + i_progname = is_progdir-name + i_state = iv_state + IMPORTING + e_progdir = ls_progdir_new + EXCEPTIONS + not_exists = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error reading program directory' ). + ENDIF. + + ls_progdir_new-ldbname = is_progdir-ldbname. + ls_progdir_new-dbna = is_progdir-dbna. + ls_progdir_new-dbapl = is_progdir-dbapl. + ls_progdir_new-rload = is_progdir-rload. + ls_progdir_new-fixpt = is_progdir-fixpt. + ls_progdir_new-appl = is_progdir-appl. + ls_progdir_new-rstat = is_progdir-rstat. + ls_progdir_new-uccheck = is_progdir-uccheck. + ls_progdir_new-sqlx = is_progdir-sqlx. + ls_progdir_new-clas = is_progdir-clas. + ls_progdir_new-secu = is_progdir-secu. + + CALL FUNCTION 'UPDATE_PROGDIR' + EXPORTING + i_progdir = ls_progdir_new + i_progname = ls_progdir_new-name + i_state = ls_progdir_new-state + EXCEPTIONS + not_executed = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error updating program directory' ). + ENDIF. + + " Function UPDATE_PROGDIR does not update VARCL, so we do it here + SELECT SINGLE * FROM progdir INTO ls_progdir_new + WHERE name = ls_progdir_new-name + AND state = ls_progdir_new-state. + IF sy-subrc = 0 AND is_progdir-varcl <> ls_progdir_new-varcl. + UPDATE progdir SET varcl = is_progdir-varcl + WHERE name = ls_progdir_new-name + AND state = ls_progdir_new-state. "#EC CI_SUBRC + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_sap_report~update_report. + + DATA lt_new TYPE string_table. + DATA lt_old TYPE string_table. + + lt_new = it_source. + lt_old = zif_abapgit_sap_report~read_report( iv_name ). + + IF lt_old <> lt_new. + zif_abapgit_sap_report~insert_report( + iv_name = iv_name + it_source = it_source + iv_state = iv_state + iv_program_type = iv_program_type + iv_extension_type = iv_extension_type + iv_package = iv_package + iv_version = iv_version + is_item = is_item ). + + rv_updated = abap_true. + ELSE. + rv_updated = abap_false. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_sap_package IMPLEMENTATION. + METHOD constructor. + mv_package = iv_package. + ENDMETHOD. + METHOD zif_abapgit_sap_package~get_default_transport_layer. + + " Get default transport layer + TRY. + CALL FUNCTION 'TR_GET_TRANSPORT_TARGET' + EXPORTING + iv_use_default = abap_true + iv_get_layer_only = abap_true + IMPORTING + ev_layer = rv_transport_layer + EXCEPTIONS + wrong_call = 1 + invalid_input = 2 + cts_initialization_failure = 3 + OTHERS = 4. + IF sy-subrc <> 0. + " Return empty layer (i.e. "local workbench request" for the package) + CLEAR rv_transport_layer. + ENDIF. + CATCH cx_sy_dyn_call_illegal_func. +* the function module doesnt exist in open-abap + CLEAR rv_transport_layer. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_sap_package~are_changes_recorded_in_tr_req. + + DATA: li_package TYPE REF TO if_package. + + cl_package_factory=>load_package( + EXPORTING + i_package_name = mv_package + IMPORTING + e_package = li_package + EXCEPTIONS + object_not_existing = 1 + unexpected_error = 2 + intern_err = 3 + no_access = 4 + object_locked_and_modified = 5 + OTHERS = 6 ). + + CASE sy-subrc. + WHEN 0. + rv_are_changes_rec_in_tr_req = li_package->wbo_korr_flag. + WHEN 1. + " For new packages, derive from package name + rv_are_changes_rec_in_tr_req = boolc( mv_package(1) <> '$' AND mv_package(1) <> 'T' ). + WHEN OTHERS. + zcx_abapgit_exception=>raise_t100( ). + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_sap_package~create. + + DATA: lv_err TYPE string, + li_package TYPE REF TO if_package, + ls_package TYPE scompkdtln. + ASSERT NOT is_package-devclass IS INITIAL. + + cl_package_factory=>load_package( + EXPORTING + i_package_name = is_package-devclass + EXCEPTIONS + object_not_existing = 1 + unexpected_error = 2 + intern_err = 3 + no_access = 4 + object_locked_and_modified = 5 ). + IF sy-subrc = 0. + " Package already exists. We assume this is fine. Its properties might be changed later at + " DEVC deserialization. + RETURN. + ENDIF. + + MOVE-CORRESPONDING is_package TO ls_package. + + " Set software component to 'HOME' if none is set at this point. + " Otherwise SOFTWARE_COMPONENT_INVALID will be raised. + IF ls_package-dlvunit IS INITIAL. + ls_package-dlvunit = 'HOME'. + ENDIF. + + " For transportable packages, get default transport and layer + IF ls_package-devclass(1) <> '$' AND ls_package-pdevclass IS INITIAL. + ls_package-pdevclass = zif_abapgit_sap_package~get_default_transport_layer( ). + ENDIF. + + cl_package_factory=>create_new_package( + EXPORTING + i_reuse_deleted_object = abap_true +* i_suppress_dialog = abap_true " does not exist in 730 + IMPORTING + e_package = li_package + CHANGING + c_package_data = ls_package + EXCEPTIONS + object_already_existing = 1 + object_just_created = 2 + not_authorized = 3 + wrong_name_prefix = 4 + undefined_name = 5 + reserved_local_name = 6 + invalid_package_name = 7 + short_text_missing = 8 + software_component_invalid = 9 + layer_invalid = 10 + author_not_existing = 11 + component_not_existing = 12 + component_missing = 13 + prefix_in_use = 14 + unexpected_error = 15 + intern_err = 16 + no_access = 17 +* invalid_translation_depth = 18 +* wrong_mainpack_value = 19 +* superpackage_invalid = 20 +* error_in_cts_checks = 21 + OTHERS = 18 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + li_package->save( +* EXPORTING +* i_suppress_dialog = abap_true " Controls whether popups can be transmitted + EXCEPTIONS + object_invalid = 1 + object_not_changeable = 2 + cancelled_in_corr = 3 + permission_failure = 4 + unexpected_error = 5 + intern_err = 6 + OTHERS = 7 ). + IF sy-subrc <> 0. + + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_err. + + " Here we have to delete the package, + " otherwise it would remain in the memory + " and cannot created again in this session. + li_package->delete( + EXCEPTIONS + object_not_empty = 1 + object_not_changeable = 2 + object_invalid = 3 + intern_err = 4 + OTHERS = 5 ). + + zcx_abapgit_exception=>raise( lv_err ). + + ENDIF. + + li_package->set_changeable( abap_false ). + + ENDMETHOD. + METHOD zif_abapgit_sap_package~create_child. + + DATA: li_parent TYPE REF TO if_package, + ls_child TYPE zif_abapgit_sap_package=>ty_create. + cl_package_factory=>load_package( + EXPORTING + i_package_name = mv_package + IMPORTING + e_package = li_parent + EXCEPTIONS + object_not_existing = 1 + unexpected_error = 2 + intern_err = 3 + no_access = 4 + object_locked_and_modified = 5 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ls_child-devclass = iv_child. + ls_child-dlvunit = li_parent->software_component. + ls_child-component = li_parent->application_component. + ls_child-ctext = iv_child. + ls_child-parentcl = mv_package. + ls_child-pdevclass = li_parent->transport_layer. + ls_child-as4user = sy-uname. + + zif_abapgit_sap_package~create( ls_child ). + + ENDMETHOD. + METHOD zif_abapgit_sap_package~create_local. + + DATA: ls_package TYPE zif_abapgit_sap_package=>ty_create. + ls_package-devclass = mv_package. + ls_package-ctext = mv_package. + ls_package-parentcl = '$TMP'. + ls_package-dlvunit = 'LOCAL'. + ls_package-as4user = sy-uname. + + zif_abapgit_sap_package~create( ls_package ). + + ENDMETHOD. + METHOD zif_abapgit_sap_package~exists. + + cl_package_factory=>load_package( + EXPORTING + i_package_name = mv_package + EXCEPTIONS + object_not_existing = 1 + unexpected_error = 2 + intern_err = 3 + no_access = 4 + object_locked_and_modified = 5 ). + rv_bool = boolc( sy-subrc <> 1 ). + + ENDMETHOD. + METHOD zif_abapgit_sap_package~get. + + DATA li_package TYPE REF TO if_package. + + cl_package_factory=>load_package( + EXPORTING + i_package_name = mv_package + IMPORTING + e_package = li_package + EXCEPTIONS + object_not_existing = 1 + unexpected_error = 2 + intern_err = 3 + no_access = 4 + object_locked_and_modified = 5 + OTHERS = 6 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + rs_package-devclass = li_package->package_name. + rs_package-dlvunit = li_package->software_component. + rs_package-component = li_package->application_component. + rs_package-ctext = li_package->short_text. + rs_package-parentcl = li_package->super_package_name. + rs_package-pdevclass = li_package->transport_layer. + rs_package-as4user = li_package->changed_by. + + ENDMETHOD. + METHOD zif_abapgit_sap_package~get_transport_type. + + DATA: + lv_pkg_name TYPE e071-obj_name, + lv_obj_name TYPE tadir-obj_name, + lv_role TYPE trnrole. + + lv_pkg_name = mv_package. + lv_obj_name = mv_package. + + CALL FUNCTION 'TR_GET_REQUEST_TYPE' + EXPORTING + iv_pgmid = 'R3TR' + iv_object = 'DEVC' + iv_obj_name = lv_pkg_name + IMPORTING + ev_request_type = rs_transport_type-request + ev_task_type = rs_transport_type-task + EXCEPTIONS + no_request_needed = 1 + invalid_object = 2 + system_error = 3 + OTHERS = 4. + + CASE sy-subrc. + WHEN 0 OR 1. + RETURN. + WHEN 2. + " For new packages, set to workbench request + rs_transport_type-request = 'K'. + + CALL FUNCTION 'TR_GET_NAMESPACE_AND_ROLE' + EXPORTING + iv_pgmid = 'R3TR' + iv_object = 'DEVC' + iv_objname = lv_obj_name + IMPORTING + ev_role = lv_role + EXCEPTIONS + namespace_not_existing = 1 + invalid_object = 2 + namespace_not_determinable = 3 + OTHERS = 4. + IF sy-subrc = 0 AND lv_role = 'C'. + " Namespace with repair license requires repair task + rs_transport_type-task = 'R'. + ELSE. + " Otherwise use correction task + rs_transport_type-task = 'S'. + ENDIF. + WHEN OTHERS. + zcx_abapgit_exception=>raise_t100( ). + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_sap_package~list_subpackages. + + DATA: lt_list LIKE rt_list. + + SELECT devclass FROM tdevc + INTO TABLE lt_list + WHERE parentcl = mv_package + ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF + + rt_list = lt_list. + WHILE lines( lt_list ) > 0. + + SELECT devclass FROM tdevc + INTO TABLE lt_list + FOR ALL ENTRIES IN lt_list + WHERE parentcl = lt_list-table_line + ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF + APPEND LINES OF lt_list TO rt_list. + + ENDWHILE. + + ENDMETHOD. + METHOD zif_abapgit_sap_package~list_superpackages. + + DATA: lt_list LIKE rt_list, + lv_parent TYPE tdevc-parentcl. + APPEND mv_package TO rt_list. + + lv_parent = zif_abapgit_sap_package~read_parent( ). + + IF sy-subrc = 0 AND NOT lv_parent IS INITIAL. + lt_list = zcl_abapgit_factory=>get_sap_package( lv_parent )->list_superpackages( ). + APPEND LINES OF lt_list TO rt_list. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_sap_package~read_description. + DATA li_package TYPE REF TO if_package. + + cl_package_factory=>load_package( + EXPORTING + i_package_name = mv_package + i_force_reload = abap_true + IMPORTING + e_package = li_package + EXCEPTIONS + object_not_existing = 1 + unexpected_error = 2 + intern_err = 3 + no_access = 4 + object_locked_and_modified = 5 + OTHERS = 6 ). + IF sy-subrc <> 0. + RETURN. + ENDIF. + + rv_description = li_package->short_text. + ENDMETHOD. + METHOD zif_abapgit_sap_package~read_parent. + + SELECT SINGLE parentcl FROM tdevc INTO rv_parentcl + WHERE devclass = mv_package. "#EC CI_GENBUFF + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Inconsistent package structure! Cannot find parent for { mv_package }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_sap_package~read_responsible. + SELECT SINGLE as4user FROM tdevc + INTO rv_responsible + WHERE devclass = mv_package ##SUBRC_OK. "#EC CI_GENBUFF + ENDMETHOD. + METHOD zif_abapgit_sap_package~validate_name. + + IF mv_package IS INITIAL. + zcx_abapgit_exception=>raise( 'Package name must not be empty' ). + ENDIF. + + IF mv_package = '$TMP'. + zcx_abapgit_exception=>raise( 'It is not possible to use $TMP, use a different (local) package' ). + ENDIF. + + " Check if package name is allowed + cl_package_helper=>check_package_name( + EXPORTING + i_package_name = mv_package + EXCEPTIONS + undefined_name = 1 + wrong_name_prefix = 2 + reserved_local_name = 3 + invalid_package_name = 4 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Package name { mv_package } is not valid| ). + ENDIF. + + ENDMETHOD. + + METHOD zif_abapgit_sap_package~check_object_type. + + " check package restrictions, closed package, descriptive or + " functional package + cl_pak_object_types=>check_object_type( + EXPORTING + i_working_mode = 'I' + i_package_name = mv_package + i_pgmid = 'R3TR' + i_object_type = iv_obj_type + EXCEPTIONS + wrong_object_type = 1 + package_not_extensible = 2 + package_not_loaded = 3 + OTHERS = 4 ). + CASE sy-subrc. + WHEN 0. + RETURN. + WHEN 2. + zcx_abapgit_exception=>raise( |Object type { iv_obj_type } not allowed for package { mv_package }| ). + WHEN OTHERS. + zcx_abapgit_exception=>raise_t100( ). + ENDCASE. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_SAP_NAMESPACE IMPLEMENTATION. + METHOD zif_abapgit_sap_namespace~exists. + DATA lv_editflag TYPE trnspace-editflag. + DATA lo_obj TYPE REF TO object. + DATA lo_nsp TYPE REF TO object. + FIELD-SYMBOLS TYPE any. + TRY. + SELECT SINGLE editflag FROM ('TRNSPACE') INTO lv_editflag WHERE namespace = iv_namespace. + rv_yes = boolc( sy-subrc = 0 ). + CATCH cx_sy_dynamic_osql_error. + ASSIGN ('XCO_CP_SYSTEM=>NAMESPACE') TO . + lo_obj = . + CALL METHOD lo_obj->('IF_XCO_CP_NAMESPACE_FACTORY~FOR') + EXPORTING + iv_value = iv_namespace + RECEIVING + ro_namespace = lo_nsp. + CALL METHOD lo_nsp->('IF_XCO_CP_NAMESPACE~EXISTS') + RECEIVING + rv_exists = rv_yes. + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_sap_namespace~is_editable. + DATA lv_editflag TYPE trnspace-editflag. + DATA lo_obj TYPE REF TO object. + DATA lo_nsp TYPE REF TO object. + FIELD-SYMBOLS TYPE any. + TRY. + SELECT SINGLE editflag FROM ('TRNSPACE') INTO lv_editflag WHERE namespace = iv_namespace. + rv_yes = boolc( sy-subrc = 0 AND lv_editflag = 'X' ). + CATCH cx_sy_dynamic_osql_error. + ASSIGN ('XCO_CP_SYSTEM=>NAMESPACE') TO . + lo_obj = . + CALL METHOD lo_obj->('IF_XCO_CP_NAMESPACE_FACTORY~FOR') + EXPORTING + iv_value = iv_namespace + RECEIVING + ro_namespace = lo_nsp. + CALL METHOD lo_nsp->('IF_XCO_CP_NAMESPACE~IS_CHANGEABLE') + RECEIVING + rv_exists = rv_yes. + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_sap_namespace~split_by_name. +* use this method instead of function module RS_NAME_SPLIT_NAMESPACE + DATA lv_regex TYPE string. + DATA lv_length TYPE i. + DATA lr_ex TYPE REF TO cx_root. + + lv_regex = '^\/[^\/]{1,8}\/'. + + TRY. + FIND REGEX lv_regex IN iv_obj_with_namespace MATCH LENGTH lv_length. + CATCH cx_root INTO lr_ex. + zcx_abapgit_exception=>raise( lr_ex->get_text( ) ). + ENDTRY. + + IF sy-subrc = 0 AND lv_length > 1. + rs_obj_namespace-namespace = iv_obj_with_namespace(lv_length). + rs_obj_namespace-obj_without_namespace = iv_obj_with_namespace+lv_length. + ELSE. + IF iv_obj_with_namespace(1) = '/'. + zcx_abapgit_exception=>raise( |The object { iv_obj_with_namespace } has an invalid namespace| ). + ENDIF. + rs_obj_namespace-obj_without_namespace = iv_obj_with_namespace. + ENDIF. + + IF iv_allow_slash_in_name = abap_false AND rs_obj_namespace-obj_without_namespace CA '/'. + zcx_abapgit_exception=>raise( + |Object without namespace { rs_obj_namespace-obj_without_namespace } contains a '/'| ). + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_function_module IMPLEMENTATION. + METHOD zif_abapgit_function_module~function_exists. + + DATA lv_function_module_name TYPE c LENGTH 30. + DATA lv_exists TYPE string. + + lv_function_module_name = iv_function_module_name. + lv_exists = 'FUNCTION_EXISTS'. + + TRY. + CALL FUNCTION lv_exists + EXPORTING + funcname = lv_function_module_name + EXCEPTIONS + function_not_exist = 1 + OTHERS = 2. + rv_exists = boolc( sy-subrc = 0 ). + CATCH cx_sy_dyn_call_illegal_func. +* then its running in ABAP Cloud Programming Model, assume nothing is released +* I could not find any way to check for this -Hvam + rv_exists = abap_false. + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_field_rules IMPLEMENTATION. + METHOD create. + CREATE OBJECT ro_result TYPE zcl_abapgit_field_rules. + ENDMETHOD. + METHOD fill_value. + DATA lv_timestamp TYPE timestampl. + CASE iv_rule. + WHEN zif_abapgit_field_rules=>c_fill_rule-date. + cv_value = sy-datum. + WHEN zif_abapgit_field_rules=>c_fill_rule-time. + cv_value = sy-uzeit. + WHEN zif_abapgit_field_rules=>c_fill_rule-timestamp. + GET TIME STAMP FIELD lv_timestamp. + cv_value = lv_timestamp. + WHEN zif_abapgit_field_rules=>c_fill_rule-user. + cv_value = sy-uname. + WHEN zif_abapgit_field_rules=>c_fill_rule-client. + cv_value = sy-mandt. + WHEN zif_abapgit_field_rules=>c_fill_rule-package. + cv_value = iv_package. + WHEN zif_abapgit_field_rules=>c_fill_rule-abap_language_version. + cv_value = iv_abap_language_version. + ENDCASE. + ENDMETHOD. + METHOD zif_abapgit_field_rules~add. + DATA ls_item TYPE ty_item. + + ls_item-tabname = iv_table. + ls_item-fieldname = iv_field. + ls_item-fill_rule = iv_fill_rule. + INSERT ls_item INTO TABLE mt_item. + + ro_self = me. + ENDMETHOD. + METHOD zif_abapgit_field_rules~apply_clear_logic. + DATA ls_item TYPE ty_item. + + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + + IF mt_item IS INITIAL. + RETURN. + ENDIF. + + LOOP AT ct_data ASSIGNING . + LOOP AT mt_item INTO ls_item WHERE tabname = iv_table. + ASSIGN COMPONENT ls_item-fieldname OF STRUCTURE TO . + IF sy-subrc = 0. + CLEAR . + ENDIF. + ENDLOOP. + ENDLOOP. + ENDMETHOD. + METHOD zif_abapgit_field_rules~apply_fill_logic. + DATA ls_item TYPE ty_item. + + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + + IF mt_item IS INITIAL. + RETURN. + ENDIF. + + LOOP AT ct_data ASSIGNING . + LOOP AT mt_item INTO ls_item WHERE tabname = iv_table. + ASSIGN COMPONENT ls_item-fieldname OF STRUCTURE TO . + IF sy-subrc = 0. + fill_value( + EXPORTING + iv_rule = ls_item-fill_rule + iv_package = iv_package + iv_abap_language_version = iv_abap_language_version + CHANGING + cv_value = ). + ENDIF. + ENDLOOP. + ENDLOOP. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_oo_serializer IMPLEMENTATION. + METHOD are_test_classes_skipped. + rv_return = mv_skip_testclass. + ENDMETHOD. + METHOD calculate_skip_testclass. + + DATA: lv_line1 LIKE LINE OF it_source, + lv_line2 LIKE LINE OF it_source. + +* when creating classes in Eclipse it automatically generates the +* testclass include, but it is not needed, so skip to avoid +* creating an extra file in the repository. +* Also remove it if the content is manually removed, but +* the class still thinks it contains tests + + rv_skip_testclass = abap_false. + IF lines( it_source ) = 2. + READ TABLE it_source INDEX 1 INTO lv_line1. + ASSERT sy-subrc = 0. + READ TABLE it_source INDEX 2 INTO lv_line2. + ASSERT sy-subrc = 0. + IF strlen( lv_line1 ) >= 3 AND lv_line1(3) = '*"*' AND lv_line2 IS INITIAL. + rv_skip_testclass = abap_true. + ENDIF. + ELSEIF lines( it_source ) = 1. + READ TABLE it_source INDEX 1 INTO lv_line1. + ASSERT sy-subrc = 0. + IF lv_line1 IS INITIAL + OR ( strlen( lv_line1 ) >= 3 AND lv_line1(3) = '*"*' ) + OR ( strlen( lv_line1 ) = 1 AND lv_line1(1) = '*' ). + rv_skip_testclass = abap_true. + ENDIF. + ELSEIF lines( it_source ) = 0. + rv_skip_testclass = abap_true. + ENDIF. + + ENDMETHOD. + METHOD read_include. + + DATA ls_include TYPE progstruc. + DATA lv_program TYPE syrepid. + DATA lt_source TYPE abaptxt255_tab. + + ASSERT iv_type = seop_ext_class_locals_def + OR iv_type = seop_ext_class_locals_imp + OR iv_type = seop_ext_class_macros + OR iv_type = seop_ext_class_testclasses. + + ls_include-rootname = is_clskey-clsname. + TRANSLATE ls_include-rootname USING ' ='. + ls_include-categorya = iv_type(1). + ls_include-codea = iv_type+1(4). + +* it looks like there is an issue in function module SEO_CLASS_GET_INCLUDE_SOURCE +* on 750 kernels, where the READ REPORT without STATE addition does not +* return the active version, this method is a workaround for this issue + lv_program = ls_include. + TRY. + lt_source = zcl_abapgit_factory=>get_sap_report( )->read_report( lv_program ). + CATCH zcx_abapgit_exception ##NO_HANDLER. +* ignore if the report is not found, sometimes the CCDEF include does not exist + ENDTRY. + rt_source = lt_source. + + ENDMETHOD. + METHOD reduce. + + DATA: lv_source LIKE LINE OF ct_source, + lv_found TYPE abap_bool. +* skip files that only contain the standard comments + lv_found = abap_false. + LOOP AT ct_source INTO lv_source. + IF strlen( lv_source ) >= 3 AND lv_source(3) <> '*"*'. + lv_found = abap_true. + ENDIF. + ENDLOOP. + IF lv_found = abap_false. + CLEAR ct_source. + ENDIF. + + ENDMETHOD. + METHOD remove_signatures. + +* signatures messes up in CL_OO_SOURCE when deserializing and serializing +* within same session + + DATA: lv_begin TYPE string, + lv_end TYPE string, + lv_remove TYPE abap_bool, + lv_source LIKE LINE OF ct_source. + + "@TODO: Put under test + CONCATENATE '* ------------------------------------' + '---------------------------------------------------+' + INTO lv_begin. + + CONCATENATE '* +------------------------------------------------' + '--------------------------------------' + INTO lv_end. + + lv_remove = abap_false. + LOOP AT ct_source INTO lv_source. + IF lv_source = lv_begin. + lv_remove = abap_true. + ENDIF. + IF lv_remove = abap_true. + DELETE ct_source INDEX sy-tabix. + ENDIF. + IF lv_source = lv_end. + lv_remove = abap_false. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD serialize_abap_clif_source. + rt_source = zcl_abapgit_exit=>get_instance( )->custom_serialize_abap_clif( is_class_key ). + IF rt_source IS NOT INITIAL. + RETURN. + ENDIF. + + TRY. + rt_source = serialize_abap_new( is_class_key ). + CATCH cx_sy_dyn_call_error. + rt_source = serialize_abap_old( is_class_key ). + ENDTRY. + + " Call exit again for optional post-processing + rt_source = zcl_abapgit_exit=>get_instance( )->custom_serialize_abap_clif( + is_class_key = is_class_key + it_source = rt_source ). + ENDMETHOD. + METHOD serialize_abap_new. + + DATA: lo_source TYPE REF TO object, + lo_instance TYPE REF TO object. + +* do not call the class/methods statically, as it will +* give syntax errors on old versions + CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') + RECEIVING + result = lo_instance. + + CALL METHOD lo_instance->('CREATE_CLIF_SOURCE') + EXPORTING + clif_name = is_clskey-clsname + version = 'A' + RECEIVING + result = lo_source. + + CALL METHOD lo_source->('GET_SOURCE') + IMPORTING + source = rt_source. + + ENDMETHOD. + METHOD serialize_abap_old. +* for old ABAP AS versions + DATA: lo_source TYPE REF TO object. + + CREATE OBJECT lo_source TYPE ('CL_OO_SOURCE') + EXPORTING + clskey = is_clskey + EXCEPTIONS + class_not_existing = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL METHOD lo_source->('READ') + EXPORTING + version = 'A'. + CALL METHOD lo_source->('GET_OLD_SOURCE') + RECEIVING + old_source = rt_source. + remove_signatures( CHANGING ct_source = rt_source ). + + ENDMETHOD. + METHOD serialize_locals_def. + + rt_source = read_include( is_clskey = is_clskey + iv_type = seop_ext_class_locals_def ). + + reduce( CHANGING ct_source = rt_source ). + + ENDMETHOD. + METHOD serialize_locals_imp. + + rt_source = read_include( is_clskey = is_clskey + iv_type = seop_ext_class_locals_imp ). + + reduce( CHANGING ct_source = rt_source ). + + ENDMETHOD. + METHOD serialize_macros. + + rt_source = read_include( is_clskey = is_clskey + iv_type = seop_ext_class_macros ). + + reduce( CHANGING ct_source = rt_source ). + + ENDMETHOD. + METHOD serialize_testclasses. + + DATA ls_vseoclass TYPE vseoclass. + + CALL FUNCTION 'SEO_CLIF_GET' + EXPORTING + cifkey = is_clskey + version = seoc_version_active + IMPORTING + class = ls_vseoclass + EXCEPTIONS + not_existing = 1 + deleted = 2 + model_only = 3 + OTHERS = 4. + IF sy-subrc <> 0 OR ls_vseoclass-with_unit_tests = abap_false. + mv_skip_testclass = abap_true. + RETURN. + ENDIF. + + rt_source = read_include( is_clskey = is_clskey + iv_type = seop_ext_class_testclasses ). + + mv_skip_testclass = calculate_skip_testclass( rt_source ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_oo_interface IMPLEMENTATION. + METHOD init_scanner. + + DATA: lx_exc TYPE REF TO cx_root, + lv_message TYPE string, + lv_classname TYPE abap_abstypename. + + FIELD-SYMBOLS: TYPE i. + + TRY. + ro_scanner = cl_oo_source_scanner_interface=>create_interface_scanner( + clif_name = iv_name + source = it_source ). + ro_scanner->scan( ). + CATCH cx_clif_scan_error. + zcx_abapgit_exception=>raise( 'error initializing INTF scanner' ). + CATCH cx_root INTO lx_exc. + lv_classname = cl_abap_classdescr=>get_class_name( lx_exc ). + IF lv_classname = '\CLASS=CX_OO_CLIF_SCAN_ERROR_DETAIL'. + ASSIGN lx_exc->('SOURCE_POSITION-LINE') TO . + ASSERT sy-subrc = 0. + lv_message = |{ lx_exc->get_text( ) }, line { }|. + ELSE. + lv_message = lx_exc->get_text( ). + ENDIF. + zcx_abapgit_exception=>raise( lv_message ). + ENDTRY. + + ENDMETHOD. + METHOD update_meta. + + DATA: lo_update TYPE REF TO cl_oo_interface_section_source, + lx_error TYPE REF TO cx_oo_source_save_failure, + ls_clskey TYPE seoclskey, + lv_scan_error TYPE abap_bool. + ls_clskey-clsname = iv_name. + + TRY. + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + cifkey = ls_clskey + version = seoc_version_active. + CREATE OBJECT lo_update TYPE ('CL_OO_INTERFACE_SECTION_SOURCE') + EXPORTING + intkey = ls_clskey + state = 'A' + source = it_source + EXCEPTIONS + interface_not_existing = 1 + read_source_error = 2 + OTHERS = 3 ##SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. +* downport to 702, see https://github.com/abapGit/abapGit/issues/933 +* this will READ REPORT instead of using it_source, which should be okay + CREATE OBJECT lo_update TYPE cl_oo_interface_section_source + EXPORTING + intkey = ls_clskey + state = 'A' + EXCEPTIONS + interface_not_existing = 1 + read_source_error = 2 + OTHERS = 3. + ENDTRY. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + lo_update->set_dark_mode( abap_true ). + + lo_update->scan_section_source( + RECEIVING + scan_error = lv_scan_error + EXCEPTIONS + scan_abap_source_error = 1 + OTHERS = 2 ). + IF sy-subrc <> 0 OR lv_scan_error = abap_true. + zcx_abapgit_exception=>raise( |INTF, error while scanning source. Subrc = { sy-subrc }| ). + ENDIF. + +* this will update the SEO* database tables + TRY. + lo_update->revert_scan_result( ). + CATCH cx_oo_source_save_failure INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD update_report. + DATA lv_type TYPE c LENGTH 1. + + lv_type = zcl_abapgit_oo_base=>c_include_program_type. + + IF iv_program+30 = srext_ext_interface_pool. + lv_type = zcl_abapgit_oo_base=>c_ip_program_type. + ENDIF. + + rv_updated = zcl_abapgit_factory=>get_sap_report( )->update_report( + iv_name = iv_program + iv_package = iv_package + iv_version = iv_version + it_source = it_source + iv_program_type = lv_type ). + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~create. + + DATA: + lt_vseoattrib TYPE seoo_attributes_r, + ls_interface_key TYPE seoclskey, + ls_properties TYPE vseointerf. + + FIELD-SYMBOLS: TYPE seoclsname. + + ASSIGN COMPONENT 'CLSNAME' OF STRUCTURE cg_properties TO . + ASSERT sy-subrc = 0. + + " Get existing interface properties and check if the interface + " needs to be created/updated (or is the same) + IF iv_check = abap_true. + ls_interface_key-clsname = . + ls_properties = zif_abapgit_oo_object_fnc~get_interface_properties( ls_interface_key ). + + IF ls_properties = cg_properties. + RETURN. + ENDIF. + ENDIF. + + lt_vseoattrib = convert_attrib_to_vseoattrib( + iv_clsname = + it_attributes = it_attributes ). + + " Hardcode STATE (#2612) + ls_properties = cg_properties. + ls_properties-state = seoc_state_implemented. + + TRY. + CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' + EXPORTING + devclass = iv_package + overwrite = abap_true + version = seoc_version_active + suppress_dialog = abap_true " Parameter missing in 702 + CHANGING + interface = ls_properties + attributes = lt_vseoattrib + EXCEPTIONS + existing = 1 + is_class = 2 + db_error = 3 + component_error = 4 + no_access = 5 + other = 6 + OTHERS = 7 ##FM_SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. + CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' + EXPORTING + devclass = iv_package + overwrite = abap_true + version = seoc_version_active + CHANGING + interface = ls_properties + attributes = lt_vseoattrib + EXCEPTIONS + existing = 1 + is_class = 2 + db_error = 3 + component_error = 4 + no_access = 5 + other = 6 + OTHERS = 7 ##FM_SUBRC_OK. + ENDTRY. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~delete. + CALL FUNCTION 'SEO_INTERFACE_DELETE_COMPLETE' + EXPORTING + intkey = is_deletion_key + EXCEPTIONS + not_existing = 1 + is_class = 2 + db_error = 3 + no_access = 4 + other = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~deserialize_source. + + DATA: lv_updated TYPE abap_bool, + lv_program TYPE program, + lo_scanner TYPE REF TO cl_oo_source_scanner_interface, + lt_public TYPE seop_source_string. + + "Buffer needs to be refreshed, + "otherwise standard SAP CLIF_SOURCE reorder methods alphabetically + CALL FUNCTION 'SEO_BUFFER_INIT'. + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + cifkey = is_key + version = seoc_version_inactive. + + lo_scanner = init_scanner( + it_source = it_source + iv_name = is_key-clsname ). + + lt_public = lo_scanner->get_interface_section_source( ). + IF lt_public IS NOT INITIAL. + lv_program = cl_oo_classname_service=>get_intfsec_name( is_key-clsname ). + lv_updated = update_report( iv_program = lv_program + iv_package = iv_package + iv_version = iv_version + it_source = lt_public ). + IF lv_updated = abap_true. + update_meta( iv_name = is_key-clsname + it_source = lt_public ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~exists. + DATA ls_object_name TYPE seoclskey. + ls_object_name = iv_object_name. + CALL FUNCTION 'SEO_INTERFACE_EXISTENCE_CHECK' + EXPORTING + intkey = ls_object_name + EXCEPTIONS + not_specified = 1 + not_existing = 2 + is_class = 3 + no_text = 4 + inconsistent = 5 + OTHERS = 6. + rv_exists = boolc( sy-subrc = 0 OR sy-subrc = 4 ). + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~get_includes. + DATA lv_interface_name TYPE seoclsname. + lv_interface_name = iv_object_name. + APPEND cl_oo_classname_service=>get_interfacepool_name( lv_interface_name ) TO rt_includes. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~get_interface_properties. + CALL FUNCTION 'SEO_CLIF_GET' + EXPORTING + cifkey = is_interface_key + version = seoc_version_active + IMPORTING + interface = rs_interface_properties + EXCEPTIONS + not_existing = 1 + deleted = 2 + model_only = 3 + OTHERS = 4. + IF sy-subrc = 1. + RETURN. " in case only inactive version exists + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CLEAR: + " TODO 2023-08-01: Clear rs_interface_properties-state (#2612) + rs_interface_properties-uuid, + rs_interface_properties-author, + rs_interface_properties-createdon, + rs_interface_properties-changedby, + rs_interface_properties-changedon, + rs_interface_properties-chgdanyby, + rs_interface_properties-chgdanyon, + rs_interface_properties-r3release, + rs_interface_properties-version. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~syntax_check. + DATA: + ls_intkey TYPE seoclskey, + lv_syntaxerror TYPE abap_bool. + + ls_intkey-clsname = to_upper( iv_object_name ). + + CALL FUNCTION 'SEO_INTERFACE_CHECK_POOL' + EXPORTING + intkey = ls_intkey + suppress_error_popup = abap_true + IMPORTING + syntaxerror = lv_syntaxerror + EXCEPTIONS + error_message = 1 " suppress S-message + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF lv_syntaxerror = abap_true. + zcx_abapgit_exception=>raise( |Interface { ls_intkey-clsname } has syntax errors | ). + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OO_FACTORY IMPLEMENTATION. + METHOD get_by_type. + IF iv_object_type = 'CLAS'. + CREATE OBJECT ri_object_oriented_object TYPE zcl_abapgit_oo_class. + ELSEIF iv_object_type = 'INTF'. + CREATE OBJECT ri_object_oriented_object TYPE zcl_abapgit_oo_interface. + ENDIF. + ENDMETHOD. + METHOD get_by_name. + + DATA: + li_interface TYPE REF TO zif_abapgit_oo_object_fnc, + li_class TYPE REF TO zif_abapgit_oo_object_fnc, + ls_object_name TYPE seoclskey. + + ls_object_name-clsname = to_upper( iv_object_name ). + + CREATE OBJECT li_class TYPE zcl_abapgit_oo_class. + IF li_class->exists( ls_object_name-clsname ) = abap_true. + ri_object_oriented_object = li_class. + RETURN. + ENDIF. + + CREATE OBJECT li_interface TYPE zcl_abapgit_oo_interface. + IF li_interface->exists( ls_object_name-clsname ) = abap_true. + ri_object_oriented_object = li_interface. + RETURN. + ENDIF. + + zcx_abapgit_exception=>raise( |{ iv_object_name } is neither a class nor an interface| ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_oo_class IMPLEMENTATION. + METHOD create_report. + zcl_abapgit_factory=>get_sap_report( )->insert_report( + iv_name = iv_program + iv_package = iv_package + it_source = it_source + iv_state = iv_state + iv_version = iv_version + iv_program_type = iv_program_type + iv_extension_type = iv_extension ). + ENDMETHOD. + METHOD delete_report. + zcl_abapgit_factory=>get_sap_report( )->delete_report( iv_program ). + ENDMETHOD. + METHOD determine_method_include. + + DATA: ls_mtdkey TYPE seocpdkey. + ls_mtdkey-clsname = iv_name. + ls_mtdkey-cpdname = iv_method. + + cl_oo_classname_service=>get_method_include( + EXPORTING + mtdkey = ls_mtdkey + RECEIVING + result = rv_program + EXCEPTIONS + method_not_existing = 1 ). + IF sy-subrc = 0. + RETURN. + ENDIF. + + CALL FUNCTION 'SEO_METHOD_GENERATE_INCLUDE' + EXPORTING + suppress_mtdkey_check = abap_true + mtdkey = ls_mtdkey + EXCEPTIONS + not_existing = 1 + model_only = 2 + include_existing = 3 + method_imp_not_generated = 4 + method_imp_not_initialised = 5 + _internal_class_not_existing = 6 + _internal_method_overflow = 7 + cancelled = 8 + method_is_abstract_implemented = 9 + method_is_final_implemented = 10 + internal_error_insert_report = 11 + OTHERS = 12. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + rv_program = cl_oo_classname_service=>get_method_include( ls_mtdkey ). + + ENDMETHOD. + METHOD generate_classpool. + + DATA: ls_clskey TYPE seoclskey. + + ls_clskey-clsname = iv_name. + + CALL FUNCTION 'SEO_CLASS_GENERATE_CLASSPOOL' + EXPORTING + clskey = ls_clskey + suppress_corr = abap_true + EXCEPTIONS + not_existing = 1 + model_only = 2 + class_pool_not_generated = 3 + class_stment_not_generated = 4 + locals_not_generated = 5 + macros_not_generated = 6 + public_sec_not_generated = 7 + protected_sec_not_generated = 8 + private_sec_not_generated = 9 + typeref_not_generated = 10 + class_pool_not_initialised = 11 + class_stment_not_initialised = 12 + locals_not_initialised = 13 + macros_not_initialised = 14 + public_sec_not_initialised = 15 + protected_sec_not_initialised = 16 + private_sec_not_initialised = 17 + typeref_not_initialised = 18 + _internal_class_overflow = 19 + OTHERS = 20. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD get_method_includes. + " get method includes for implemented interfaces + " this will contain also leftover includes for deleted interface methods + rt_includes = cl_oo_classname_service=>get_all_method_includes( iv_classname ). + ENDMETHOD. + METHOD init_scanner. + + DATA: lx_exc TYPE REF TO cx_root, + lv_message TYPE string, + lv_classname TYPE abap_abstypename. + FIELD-SYMBOLS: TYPE i. + + TRY. + ro_scanner = cl_oo_source_scanner_class=>create_class_scanner( + clif_name = iv_name + source = it_source ). + ro_scanner->scan( ). + CATCH cx_clif_scan_error. + zcx_abapgit_exception=>raise( 'error initializing CLAS scanner' ). + CATCH cx_root INTO lx_exc. + lv_classname = cl_abap_classdescr=>get_class_name( lx_exc ). + IF lv_classname = '\CLASS=CX_OO_CLIF_SCAN_ERROR_DETAIL'. + ASSIGN lx_exc->('SOURCE_POSITION-LINE') TO . + ASSERT sy-subrc = 0. + lv_message = |{ lx_exc->get_text( ) }, line { }|. + ELSE. + lv_message = lx_exc->get_text( ). + ENDIF. + zcx_abapgit_exception=>raise( lv_message ). + ENDTRY. + + ENDMETHOD. + METHOD repair_classpool. + + CALL FUNCTION 'SEO_CLASS_REPAIR_CLASSPOOL' + EXPORTING + clskey = is_key + EXCEPTIONS + not_existing = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error repairing class { is_key-clsname }| ). + ENDIF. + + ENDMETHOD. + METHOD repair_redefinitions. + + " Same logic as SE24 > Utilities > Clean-up > Redefinitions (LSEODCCO) + + DATA: + lt_inheritance TYPE vseoextend, + lt_redefinitions TYPE seor_redefinitions_r, + ls_cpdkey TYPE seocpdkey, + lv_tabix TYPE sy-tabix, + lv_exposure TYPE n LENGTH 1, + lv_update TYPE abap_bool, + lv_local_component TYPE abap_bool. + + FIELD-SYMBOLS TYPE seoredef. + + CALL FUNCTION 'SEO_CLASS_TYPEINFO_GET' + EXPORTING + clskey = is_key + version = seoc_version_active + IMPORTING + inheritance = lt_inheritance + redefinitions = lt_redefinitions + EXCEPTIONS + not_existing = 1 + is_interface = 2 + model_only = 3 + OTHERS = 4. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + " check redefinitions validity + LOOP AT lt_redefinitions ASSIGNING . + lv_tabix = sy-tabix. + + ls_cpdkey-clsname = is_key-clsname. + ls_cpdkey-cpdname = -mtdname. + + CALL FUNCTION 'SEO_COMPONENT_BY_INHERITANCE' + EXPORTING + cpdkey = ls_cpdkey + version = seoc_version_active + IMPORTING + exposure = lv_exposure + is_local_component = lv_local_component + EXCEPTIONS + not_existing = 1 + model_only = 2 + OTHERS = 3. + IF sy-subrc <> 0. + DELETE lt_redefinitions INDEX lv_tabix. + lv_update = abap_true. + ELSEIF -exposure <> lv_exposure. + -exposure = lv_exposure. + lv_update = abap_true. + ELSEIF lv_local_component = abap_true AND -attvalue IS INITIAL AND + -mtdabstrct IS INITIAL AND -mtdfinal IS INITIAL. + DELETE lt_redefinitions INDEX lv_tabix. + lv_update = abap_true. + ENDIF. + ENDLOOP. + + IF lv_update = abap_true. + CALL FUNCTION 'SEO_INHERITANC_CHANGE_F_DATA' + EXPORTING + save = abap_false + CHANGING + inheritance = lt_inheritance + redefinitions = lt_redefinitions + EXCEPTIONS + not_existing = 1 + deleted = 2 + is_comprising = 3 + is_implementing = 4 + not_changed = 5 + db_error = 6 + OTHERS = 7. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error repairing redefinitions for { is_key-clsname }| ). + ENDIF. + + CALL FUNCTION 'SEO_CLIF_SAVE_ALL' + EXPORTING + cifkey = is_key + EXCEPTIONS + not_existing = 1 + nothing_to_do = 2 + access_error = 3 + db_error = 4 + error_in_code_generation = 5 + OTHERS = 6. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error repairing redefinitions for { is_key-clsname }| ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD update_cs_number_of_methods. + + " Indirect access to keep downward compatibility + DATA lr_cache_entry TYPE REF TO data. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + TRY. + CREATE DATA lr_cache_entry TYPE ('SEO_CS_CACHE'). + CATCH cx_sy_create_data_error. +* does not exist in some older systems + RETURN. + ENDTRY. + + ASSIGN lr_cache_entry->* TO . + ASSERT sy-subrc = 0. + + ASSIGN COMPONENT 'CLSNAME' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + = iv_classname. + + ASSIGN COMPONENT 'NO_OF_METHOD_IMPLS' OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + = iv_number_of_impl_methods. + + MODIFY ('SEO_CS_CACHE') FROM . + + ENDMETHOD. + METHOD update_full_class_include. + + CONSTANTS: lc_class_source_extension TYPE c LENGTH 2 VALUE 'CS', + lc_include_program_type TYPE c LENGTH 1 VALUE 'I', + lc_active_version TYPE r3state VALUE 'A'. + create_report( iv_program = cl_oo_classname_service=>get_cs_name( iv_classname ) + iv_package = iv_package + it_source = it_source + iv_extension = lc_class_source_extension + iv_program_type = lc_include_program_type + iv_state = lc_active_version + iv_version = iv_version ). + + " Assuming that all methods that were scanned are implemented + update_cs_number_of_methods( iv_classname = iv_classname + iv_number_of_impl_methods = lines( it_methods ) ). + + ENDMETHOD. + METHOD update_meta. + + DATA: lo_update TYPE REF TO cl_oo_class_section_source, + lx_error TYPE REF TO cx_oo_source_save_failure, + ls_clskey TYPE seoclskey, + lv_scan_error TYPE abap_bool. + ls_clskey-clsname = iv_name. + + TRY. + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + cifkey = ls_clskey + version = seoc_version_active. + CREATE OBJECT lo_update TYPE ('CL_OO_CLASS_SECTION_SOURCE') + EXPORTING + clskey = ls_clskey + exposure = iv_exposure + state = 'A' + source = it_source + suppress_constrctr_generation = abap_true + EXCEPTIONS + class_not_existing = 1 + read_source_error = 2 + OTHERS = 3 ##SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. +* downport to 702, see https://github.com/abapGit/abapGit/issues/933 +* this will READ REPORT instead of using it_source, which should be okay + CREATE OBJECT lo_update TYPE cl_oo_class_section_source + EXPORTING + clskey = ls_clskey + exposure = iv_exposure + state = 'A' + EXCEPTIONS + class_not_existing = 1 + read_source_error = 2 + OTHERS = 3. + ENDTRY. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + lo_update->set_dark_mode( abap_true ). + TRY. + CALL METHOD lo_update->('SET_AMDP_SUPPORT') + EXPORTING + enabled = abap_true. + CATCH cx_sy_dyn_call_illegal_method ##NO_HANDLER. +* AMDP not supported in this system, ignore error + ENDTRY. + lo_update->scan_section_source( + RECEIVING + scan_error = lv_scan_error + EXCEPTIONS + scan_abap_source_error = 1 + OTHERS = 2 ). + IF sy-subrc <> 0 OR lv_scan_error = abap_true. + zcx_abapgit_exception=>raise( |CLAS, error while scanning source. Subrc = { sy-subrc }| ). + ENDIF. + +* this will update the SEO* database tables + TRY. + lo_update->revert_scan_result( ). + CATCH cx_oo_source_save_failure INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + IF iv_exposure = seoc_exposure_public. + generate_classpool( iv_name ). + ENDIF. + + ENDMETHOD. + METHOD update_report. + DATA lv_type TYPE c LENGTH 1. + + lv_type = zcl_abapgit_oo_base=>c_include_program_type. + + IF iv_program+30 = srext_ext_class_pool. + lv_type = zcl_abapgit_oo_base=>c_cp_program_type. + ENDIF. + + rv_updated = zcl_abapgit_factory=>get_sap_report( )->update_report( + iv_name = iv_program + iv_package = iv_package + iv_version = iv_version + it_source = it_source + iv_program_type = lv_type ). + ENDMETHOD. + METHOD update_source_index. + + CONSTANTS: + lc_version_active TYPE r3state VALUE 'A', + lc_version_inactive TYPE r3state VALUE 'I'. + + " dynamic invocation, IF_OO_SOURCE_POS_INDEX_HELPER doesn't exist in 702. + DATA lo_index_helper TYPE REF TO object. + + TRY. + CREATE OBJECT lo_index_helper TYPE ('CL_OO_SOURCE_POS_INDEX_HELPER'). + + CALL METHOD lo_index_helper->('IF_OO_SOURCE_POS_INDEX_HELPER~CREATE_INDEX_WITH_SCANNER') + EXPORTING + class_name = iv_clsname + version = lc_version_active + scanner = io_scanner. + + CALL METHOD lo_index_helper->('IF_OO_SOURCE_POS_INDEX_HELPER~DELETE_INDEX') + EXPORTING + class_name = iv_clsname + version = lc_version_inactive. + + CATCH cx_root. + " it's probably okay to no update the index + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~create. + + DATA: + lt_vseoattrib TYPE seoo_attributes_r, + ls_class_key TYPE seoclskey, + ls_properties TYPE vseoclass, + lt_attributes TYPE zif_abapgit_oo_object_fnc=>ty_obj_attribute_tt. + + FIELD-SYMBOLS: TYPE seoclsname. + + ASSIGN COMPONENT 'CLSNAME' OF STRUCTURE cg_properties TO . + ASSERT sy-subrc = 0. + + " Get existing class properties and attributes and check if the class + " needs to be created/updated (or is the same) + IF iv_check = abap_true. + ls_class_key-clsname = . + ls_properties = zif_abapgit_oo_object_fnc~get_class_properties( ls_class_key ). + lt_attributes = zif_abapgit_oo_object_fnc~read_attributes( ). + + IF ls_properties = cg_properties AND lt_attributes = it_attributes. + RETURN. + ENDIF. + ENDIF. + + lt_vseoattrib = convert_attrib_to_vseoattrib( + iv_clsname = + it_attributes = it_attributes ). + + " Hardcode STATE (#2612) + ls_properties = cg_properties. + ls_properties-state = seoc_state_implemented. + + TRY. + CALL FUNCTION 'SEO_CLASS_CREATE_COMPLETE' + EXPORTING + devclass = iv_package + overwrite = abap_true + version = seoc_version_active + suppress_dialog = abap_true " Parameter missing in 702 + CHANGING + class = ls_properties + attributes = lt_vseoattrib + EXCEPTIONS + existing = 1 + is_interface = 2 + db_error = 3 + component_error = 4 + no_access = 5 + other = 6 + OTHERS = 7 ##FM_SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. + CALL FUNCTION 'SEO_CLASS_CREATE_COMPLETE' + EXPORTING + devclass = iv_package + overwrite = abap_true + version = seoc_version_active + CHANGING + class = ls_properties + attributes = lt_vseoattrib + EXCEPTIONS + existing = 1 + is_interface = 2 + db_error = 3 + component_error = 4 + no_access = 5 + other = 6 + OTHERS = 7 ##FM_SUBRC_OK. + ENDTRY. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~create_sotr. + zcl_abapgit_sotr_handler=>create_sotr( + iv_package = iv_package + io_xml = ii_xml ). + zcl_abapgit_sots_handler=>create_sots( + iv_package = iv_package + io_xml = ii_xml ). + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~delete. + + " SEO_CLASS_DELETE_COMPLETE deletes OTR usage, only + " Use handler to also delete OTR header and texts + zcl_abapgit_sotr_handler=>delete_sotr( + iv_pgmid = 'LIMU' + iv_object = 'CPUB' + iv_obj_name = is_deletion_key-clsname ). + zcl_abapgit_sots_handler=>delete_sots( + iv_pgmid = 'LIMU' + iv_object = 'CPUB' + iv_obj_name = is_deletion_key-clsname ). + + CALL FUNCTION 'SEO_CLASS_DELETE_COMPLETE' + EXPORTING + clskey = is_deletion_key + EXCEPTIONS + not_existing = 1 + is_interface = 2 + db_error = 3 + no_access = 4 + other = 5 + OTHERS = 6. + IF sy-subrc = 1. +* ignore deletion of objects that does not exist +* this can happen when the SXCI object is deleted before the implementing CLAS + RETURN. + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~deserialize_source. + + DATA: lv_updated TYPE abap_bool, + lv_program TYPE program, + lo_scanner TYPE REF TO cl_oo_source_scanner_class, + lt_methods TYPE cl_oo_source_scanner_class=>type_method_implementations, + lt_incls TYPE seop_methods_w_include, + lv_method LIKE LINE OF lt_methods, + lt_public TYPE seop_source_string, + lt_source TYPE seop_source_string. + + "Buffer needs to be refreshed, + "otherwise standard SAP CLIF_SOURCE reorder methods alphabetically + CALL FUNCTION 'SEO_BUFFER_INIT'. + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + cifkey = is_key + version = seoc_version_inactive. + + lo_scanner = init_scanner( + it_source = it_source + iv_name = is_key-clsname ). + +* public + lt_public = lo_scanner->get_public_section_source( ). + IF lt_public IS NOT INITIAL. + lv_program = cl_oo_classname_service=>get_pubsec_name( is_key-clsname ). + lv_updated = update_report( iv_program = lv_program + iv_package = iv_package + iv_version = iv_version + it_source = lt_public ). + IF lv_updated = abap_true. + update_meta( iv_name = is_key-clsname + iv_exposure = seoc_exposure_public + it_source = lt_public ). + ENDIF. + ENDIF. + +* protected + lt_source = lo_scanner->get_protected_section_source( ). + IF lt_source IS NOT INITIAL. + lv_program = cl_oo_classname_service=>get_prosec_name( is_key-clsname ). + lv_updated = update_report( iv_program = lv_program + iv_package = iv_package + iv_version = iv_version + it_source = lt_source ). + IF lv_updated = abap_true. + update_meta( iv_name = is_key-clsname + iv_exposure = seoc_exposure_protected + it_source = lt_source ). + ENDIF. + ENDIF. + +* private + lt_source = lo_scanner->get_private_section_source( ). + IF lt_source IS NOT INITIAL. + lv_program = cl_oo_classname_service=>get_prisec_name( is_key-clsname ). + lv_updated = update_report( iv_program = lv_program + iv_package = iv_package + iv_version = iv_version + it_source = lt_source ). + IF lv_updated = abap_true. + update_meta( iv_name = is_key-clsname + iv_exposure = seoc_exposure_private + it_source = lt_source ). + ENDIF. + ENDIF. + +* methods + lt_methods = lo_scanner->get_method_implementations( ). + + lt_incls = get_method_includes( is_key-clsname ). + + LOOP AT lt_methods INTO lv_method. + TRY. + lt_source = lo_scanner->get_method_impl_source( lv_method ). + CATCH cx_oo_clif_component. + zcx_abapgit_exception=>raise( 'error from GET_METHOD_IMPL_SOURCE' ). + ENDTRY. + lv_program = determine_method_include( + iv_name = is_key-clsname + iv_method = lv_method ). + + update_report( + iv_program = lv_program + iv_package = iv_package + iv_version = iv_version + it_source = lt_source ). + + " If method was implemented before, remove from list + DELETE lt_incls WHERE cpdkey-clsname = is_key-clsname AND cpdkey-cpdname = lv_method. + ENDLOOP. + +* full class include + update_full_class_include( iv_classname = is_key-clsname + iv_package = iv_package + iv_version = iv_version + it_source = it_source + it_methods = lt_methods ). + + " If there are leftover method includes, then class needs to be repaired + " which will delete the obsolete includes + IF lt_incls IS NOT INITIAL. + repair_classpool( is_key ). + repair_redefinitions( is_key ). + ENDIF. + + update_source_index( + iv_clsname = is_key-clsname + io_scanner = lo_scanner ). + + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~exists. + DATA ls_object_name TYPE seoclskey. + ls_object_name = iv_object_name. + CALL FUNCTION 'SEO_CLASS_EXISTENCE_CHECK' + EXPORTING + clskey = ls_object_name + EXCEPTIONS + not_specified = 1 + not_existing = 2 + is_interface = 3 + no_text = 4 + inconsistent = 5 + OTHERS = 6. + rv_exists = boolc( sy-subrc = 0 OR sy-subrc = 4 ). + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~generate_locals. + + DATA: lv_program TYPE syrepid. + + IF lines( it_local_definitions ) > 0. + lv_program = cl_oo_classname_service=>get_ccdef_name( is_key-clsname ). + update_report( iv_program = lv_program + iv_package = iv_package + iv_version = iv_version + it_source = it_local_definitions ). + ENDIF. + + IF lines( it_local_implementations ) > 0. + lv_program = cl_oo_classname_service=>get_ccimp_name( is_key-clsname ). + update_report( iv_program = lv_program + iv_package = iv_package + iv_version = iv_version + it_source = it_local_implementations ). + ENDIF. + + IF lines( it_local_macros ) > 0. + lv_program = cl_oo_classname_service=>get_ccmac_name( is_key-clsname ). + update_report( iv_program = lv_program + iv_package = iv_package + iv_version = iv_version + it_source = it_local_macros ). + ENDIF. + + lv_program = cl_oo_classname_service=>get_ccau_name( is_key-clsname ). + IF lines( it_local_test_classes ) > 0. + update_report( iv_program = lv_program + iv_package = iv_package + iv_version = iv_version + it_source = it_local_test_classes ). + ELSE. + " Drop the include to remove left-over test classes + delete_report( lv_program ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~get_class_properties. + CALL FUNCTION 'SEO_CLIF_GET' + EXPORTING + cifkey = is_class_key + version = seoc_version_active + IMPORTING + class = rs_class_properties + EXCEPTIONS + not_existing = 1 + deleted = 2 + model_only = 3 + OTHERS = 4. + IF sy-subrc = 1. + RETURN. " in case only inactive version exists + ELSEIF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CLEAR: + " TODO 2023-08-01: Clear rs_class_properties-state (#2612) + rs_class_properties-uuid, + rs_class_properties-author, + rs_class_properties-createdon, + rs_class_properties-changedby, + rs_class_properties-changedon, + rs_class_properties-r3release, + rs_class_properties-chgdanyby, + rs_class_properties-chgdanyon, + rs_class_properties-clsfinal, + rs_class_properties-clsabstrct, + rs_class_properties-exposure, + rs_class_properties-version. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~get_includes. +* note: includes returned might not exist +* method cl_oo_classname_service=>GET_ALL_CLASS_INCLUDES does not exist in 702 + + DATA: lv_class_name TYPE seoclsname, + lt_methods TYPE seop_methods_w_include. + + FIELD-SYMBOLS: LIKE LINE OF lt_methods. + + lv_class_name = iv_object_name. + + APPEND cl_oo_classname_service=>get_ccdef_name( lv_class_name ) TO rt_includes. + APPEND cl_oo_classname_service=>get_ccmac_name( lv_class_name ) TO rt_includes. + APPEND cl_oo_classname_service=>get_ccimp_name( lv_class_name ) TO rt_includes. + APPEND cl_oo_classname_service=>get_cl_name( lv_class_name ) TO rt_includes. + APPEND cl_oo_classname_service=>get_ccau_name( lv_class_name ) TO rt_includes. + APPEND cl_oo_classname_service=>get_pubsec_name( lv_class_name ) TO rt_includes. + APPEND cl_oo_classname_service=>get_prosec_name( lv_class_name ) TO rt_includes. + APPEND cl_oo_classname_service=>get_prisec_name( lv_class_name ) TO rt_includes. + APPEND cl_oo_classname_service=>get_classpool_name( lv_class_name ) TO rt_includes. + APPEND cl_oo_classname_service=>get_ct_name( lv_class_name ) TO rt_includes. + +* skip the CS include, as it is sometimes generated on the fly instead of +* when the methods are changed + + cl_oo_classname_service=>get_all_method_includes( + EXPORTING + clsname = lv_class_name + RECEIVING + result = lt_methods + EXCEPTIONS + class_not_existing = 1 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Class { lv_class_name } not existing| ). + ENDIF. + + LOOP AT lt_methods ASSIGNING . + APPEND -incname TO rt_includes. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~insert_text_pool. + DATA: lv_cp TYPE program. + + lv_cp = cl_oo_classname_service=>get_classpool_name( iv_class_name ). + + INSERT TEXTPOOL lv_cp + FROM it_text_pool + LANGUAGE iv_language + STATE iv_state. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from INSERT TEXTPOOL' ). + ENDIF. + + zcl_abapgit_objects_activation=>add( iv_type = 'REPT' + iv_name = lv_cp ). + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_sotr. + zcl_abapgit_sotr_handler=>read_sotr( + iv_pgmid = 'LIMU' + iv_object = 'CPUB' + iv_obj_name = iv_object_name + io_i18n_params = io_i18n_params + io_xml = ii_xml ). + zcl_abapgit_sots_handler=>read_sots( + iv_pgmid = 'LIMU' + iv_object = 'CPUB' + iv_obj_name = iv_object_name + io_i18n_params = io_i18n_params + io_xml = ii_xml ). + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_text_pool. + DATA: lv_cp TYPE program. + + lv_cp = cl_oo_classname_service=>get_classpool_name( iv_class_name ). + READ TEXTPOOL lv_cp INTO rt_text_pool LANGUAGE iv_language. "#EC CI_READ_REP + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~syntax_check. + DATA: + ls_clskey TYPE seoclskey, + lv_syntaxerror TYPE abap_bool. + + ls_clskey-clsname = to_upper( iv_object_name ). + + CALL FUNCTION 'SEO_CLASS_CHECK_CLASSPOOL' + EXPORTING + clskey = ls_clskey + suppress_error_popup = abap_true + IMPORTING + syntaxerror = lv_syntaxerror + EXCEPTIONS + _internal_class_not_existing = 1 + error_message = 2 " suppress S-message + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF lv_syntaxerror = abap_true. + zcx_abapgit_exception=>raise( |Class { ls_clskey-clsname } has syntax errors | ). + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OO_BASE IMPLEMENTATION. + METHOD convert_attrib_to_vseoattrib. + FIELD-SYMBOLS: LIKE LINE OF it_attributes, + LIKE LINE OF rt_vseoattrib. + + LOOP AT it_attributes ASSIGNING . + INSERT INITIAL LINE INTO TABLE rt_vseoattrib ASSIGNING . + MOVE-CORRESPONDING TO . + -clsname = iv_clsname. + -state = seoc_state_implemented. + -exposure = -exposure. + UNASSIGN . + ENDLOOP. + UNASSIGN . + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~add_to_activation_list. + zcl_abapgit_objects_activation=>add_item( is_item ). + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~create. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~create_documentation. + CALL FUNCTION 'DOCU_UPD' + EXPORTING + id = iv_id + langu = iv_language + object = iv_object_name + no_masterlang = iv_no_masterlang + state = c_docu_state_active + TABLES + line = it_lines + EXCEPTIONS + ret_code = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~create_sotr. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~delete. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~delete_documentation. + CALL FUNCTION 'DOCU_DEL' + EXPORTING + id = iv_id + langu = iv_language + object = iv_object_name + typ = 'E' + EXCEPTIONS + ret_code = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Error from DOCU_DEL' ). + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~deserialize_source. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~exists. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~generate_locals. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~get_class_properties. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~get_includes. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~get_interface_properties. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~get_skip_test_classes. + rv_skip = mv_skip_test_classes. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~insert_text_pool. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_attributes. + SELECT cmpname attbusobj attkeyfld exposure + FROM seocompodf + INTO CORRESPONDING FIELDS OF TABLE rt_attributes + WHERE clsname = iv_object_name + AND ( attbusobj <> space OR attkeyfld <> space ) + AND version = '1' + ORDER BY PRIMARY KEY. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_descriptions_class. + FIELD-SYMBOLS LIKE LINE OF rt_descriptions. + + " Only translations i.e. not the main language + SELECT * FROM seoclasstx INTO TABLE rt_descriptions + WHERE clsname = iv_object_name + AND langu <> iv_language + AND descript <> '' + ORDER BY PRIMARY KEY. "#EC CI_SUBRC + + LOOP AT rt_descriptions ASSIGNING . + CLEAR -clsname. + ENDLOOP. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_descriptions_compo. + FIELD-SYMBOLS LIKE LINE OF rt_descriptions. + + IF iv_language IS INITIAL. + " load all languages + SELECT * FROM seocompotx INTO TABLE rt_descriptions + WHERE clsname = iv_object_name + AND descript <> '' + ORDER BY PRIMARY KEY. "#EC CI_SUBRC + ELSE. + " load main language + SELECT * FROM seocompotx INTO TABLE rt_descriptions + WHERE clsname = iv_object_name + AND langu = iv_language + AND descript <> '' + ORDER BY PRIMARY KEY. "#EC CI_SUBRC + ENDIF. + + LOOP AT rt_descriptions ASSIGNING . + CLEAR -clsname. + ENDLOOP. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_descriptions_subco. + FIELD-SYMBOLS LIKE LINE OF rt_descriptions. + + IF iv_language IS INITIAL. + " load all languages + SELECT * FROM seosubcotx INTO TABLE rt_descriptions + WHERE clsname = iv_object_name + AND descript <> '' + ORDER BY PRIMARY KEY. "#EC CI_SUBRC + ELSE. + " load main language + SELECT * FROM seosubcotx INTO TABLE rt_descriptions + WHERE clsname = iv_object_name + AND langu = iv_language + AND descript <> '' + ORDER BY PRIMARY KEY. "#EC CI_SUBRC + ENDIF. + + LOOP AT rt_descriptions ASSIGNING . + CLEAR -clsname. + ENDLOOP. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_documentation. + DATA: lv_state TYPE dokstate, + lt_lines TYPE tlinetab. + + CALL FUNCTION 'DOCU_GET' + EXPORTING + id = iv_id + langu = iv_language + object = iv_object_name + version_active_or_last = space " retrieve active version + IMPORTING + dokstate = lv_state + TABLES + line = lt_lines + EXCEPTIONS + no_docu_on_screen = 1 + no_docu_self_def = 2 + no_docu_temp = 3 + ret_code = 4 + OTHERS = 5. + IF sy-subrc = 0 AND lv_state = c_docu_state_active. + rt_lines = lt_lines. + ELSE. + CLEAR rt_lines. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_sotr. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_superclass. + SELECT SINGLE refclsname FROM vseoextend INTO rv_superclass + WHERE clsname = iv_classname. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~read_text_pool. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~serialize_abap. + DATA lo_oo_serializer TYPE REF TO zcl_abapgit_oo_serializer. + CREATE OBJECT lo_oo_serializer. + CASE iv_type. + WHEN seop_ext_class_locals_def. + rt_source = lo_oo_serializer->serialize_locals_def( is_class_key ). + WHEN seop_ext_class_locals_imp. + rt_source = lo_oo_serializer->serialize_locals_imp( is_class_key ). + WHEN seop_ext_class_macros. + rt_source = lo_oo_serializer->serialize_macros( is_class_key ). + WHEN seop_ext_class_testclasses. + rt_source = lo_oo_serializer->serialize_testclasses( is_class_key ). + mv_skip_test_classes = lo_oo_serializer->are_test_classes_skipped( ). + WHEN OTHERS. + rt_source = lo_oo_serializer->serialize_abap_clif_source( is_class_key ). + ENDCASE. + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~syntax_check. + ASSERT 0 = 1. "Subclass responsibility + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~update_descriptions_class. + DATA lt_descriptions LIKE it_descriptions. + DATA ls_description LIKE LINE OF it_descriptions. + + " Make sure we keep main language + SELECT * FROM seoclasstx INTO TABLE lt_descriptions + WHERE clsname = is_key-clsname AND langu = iv_language + ORDER BY PRIMARY KEY. + + LOOP AT it_descriptions INTO ls_description WHERE langu <> iv_language. + ls_description-clsname = is_key-clsname. + INSERT ls_description INTO TABLE lt_descriptions. + ENDLOOP. + + DELETE FROM seoclasstx WHERE clsname = is_key-clsname. "#EC CI_SUBRC + INSERT seoclasstx FROM TABLE lt_descriptions. "#EC CI_SUBRC + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~update_descriptions_compo. + DATA lt_descriptions LIKE it_descriptions. + DATA lt_components TYPE seo_components. + DATA ls_description LIKE LINE OF it_descriptions. + DATA lv_lang TYPE tadir-masterlang. + + FIELD-SYMBOLS LIKE LINE OF it_descriptions. + FIELD-SYMBOLS TYPE vseocompdf. + + lt_descriptions = it_descriptions. + LOOP AT lt_descriptions ASSIGNING . + -clsname = is_key-clsname. + ENDLOOP. + + " make sure to not damage VSEO* views by deleting texts of all components - an empty text must be kept!! + SELECT * FROM vseocompdf INTO TABLE lt_components + WHERE clsname = is_key-clsname + AND version <> seoc_version_deleted + AND state = seoc_state_implemented + AND alias = seox_false ORDER BY clsname cmpname version. + + IF lt_components IS NOT INITIAL. + SELECT SINGLE masterlang FROM tadir INTO lv_lang + WHERE pgmid = 'R3TR' AND ( object = 'CLAS' OR object = 'INTF' ) + AND obj_name = is_key-clsname. "#EC CI_GENBUFF + IF sy-subrc <> 0. + lv_lang = sy-langu. + ENDIF. + + LOOP AT lt_components ASSIGNING . + READ TABLE lt_descriptions TRANSPORTING NO FIELDS WITH KEY + clsname = is_key-clsname + cmpname = -cmpname. + IF sy-subrc <> 0. + ls_description-clsname = is_key-clsname. + ls_description-cmpname = -cmpname. + ls_description-langu = lv_lang. + ls_description-descript = space. + APPEND ls_description TO lt_descriptions. + ENDIF. + ENDLOOP. + ENDIF. + + DELETE FROM seocompotx WHERE clsname = is_key-clsname. "#EC CI_SUBRC + INSERT seocompotx FROM TABLE lt_descriptions. "#EC CI_SUBRC + ENDMETHOD. + METHOD zif_abapgit_oo_object_fnc~update_descriptions_subco. + DATA lt_descriptions LIKE it_descriptions. + DATA lt_subcomponents TYPE seo_subcomponents. + DATA ls_description LIKE LINE OF it_descriptions. + DATA lv_lang TYPE tadir-masterlang. + + FIELD-SYMBOLS LIKE LINE OF it_descriptions. + FIELD-SYMBOLS TYPE vseosubcdf. + + lt_descriptions = it_descriptions. + LOOP AT lt_descriptions ASSIGNING . + -clsname = is_key-clsname. + ENDLOOP. + + " make sure to not damage VSEO* views by deleting texts of all subcomponents - an empty text must be kept!! + SELECT * FROM vseosubcdf INTO TABLE lt_subcomponents + WHERE clsname = is_key-clsname + AND version <> seoc_version_deleted ORDER BY clsname cmpname sconame version. + + IF lt_subcomponents IS NOT INITIAL. + SELECT SINGLE masterlang FROM tadir INTO lv_lang + WHERE pgmid = 'R3TR' AND ( object = 'CLAS' OR object = 'INTF' ) + AND obj_name = is_key-clsname. "#EC CI_GENBUFF + IF sy-subrc <> 0. + lv_lang = sy-langu. + ENDIF. + + LOOP AT lt_subcomponents ASSIGNING . + READ TABLE lt_descriptions TRANSPORTING NO FIELDS WITH KEY + clsname = is_key-clsname + cmpname = -cmpname + sconame = -sconame. + IF sy-subrc <> 0. + ls_description-clsname = is_key-clsname. + ls_description-cmpname = -cmpname. + ls_description-sconame = -sconame. + ls_description-langu = lv_lang. + ls_description-descript = space. + APPEND ls_description TO lt_descriptions. + ENDIF. + ENDLOOP. + ENDIF. + + DELETE FROM seosubcotx WHERE clsname = is_key-clsname. "#EC CI_SUBRC + INSERT seosubcotx FROM TABLE lt_descriptions. "#EC CI_SUBRC + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gui_jumper IMPLEMENTATION. + METHOD jump_bw. + + DATA: + lv_exit TYPE abap_bool, + lv_tlogo TYPE c LENGTH 4, "rstlogo + lv_objnm TYPE c LENGTH 40. "rsawbnobjnm + + lv_tlogo = is_item-obj_type. + lv_objnm = is_item-obj_name. + + TRY. + CALL METHOD ('CL_RSAWBN_AWB')=>('IS_SUPPORTED_NAVIGATION') + EXPORTING + i_tlogo = lv_tlogo + i_fcode = 'DISPLAY' + IMPORTING + re_is_supported_fcode = lv_exit. + + IF lv_exit = abap_false. + RETURN. + ENDIF. + CATCH cx_root. + " Not a BW system + RETURN. + ENDTRY. + + TRY. + CALL METHOD ('CL_RSAWBN_AWB')=>('NAVIGATE_FROM_APPLICATION') + EXPORTING + i_tlogo = lv_tlogo + i_objnm = lv_objnm + i_new_mode = iv_new_window + IMPORTING + e_exit_own_application = lv_exit. + + CATCH cx_root. + " Older release without i_new_mode + CALL METHOD ('CL_RSAWBN_AWB')=>('NAVIGATE_FROM_APPLICATION') + EXPORTING + i_tlogo = lv_tlogo + i_objnm = lv_objnm + IMPORTING + e_exit_own_application = lv_exit. + ENDTRY. + + rv_exit = lv_exit. + + ENDMETHOD. + METHOD jump_tr. + + DATA: + lv_e071_object TYPE e071-object, + lv_e071_obj_name TYPE e071-obj_name. + + lv_e071_object = is_item-obj_type. + lv_e071_obj_name = is_item-obj_name. + + CALL FUNCTION 'TR_OBJECT_JUMP_TO_TOOL' + EXPORTING + iv_action = 'SHOW' + iv_pgmid = 'R3TR' + iv_object = lv_e071_object + iv_obj_name = lv_e071_obj_name + EXCEPTIONS + jump_not_possible = 1 + OTHERS = 2. + + rv_exit = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD jump_wb. + + CALL FUNCTION 'RS_TOOL_ACCESS' + EXPORTING + operation = 'SHOW' + object_name = is_item-obj_name + object_type = is_item-obj_type + devclass = is_item-devclass + in_new_window = iv_new_window + EXCEPTIONS + not_executed = 1 + invalid_object_type = 2 + OTHERS = 3. + + rv_exit = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD jump_wb_line. + + IF iv_line_number IS NOT INITIAL AND iv_sub_obj_type IS NOT INITIAL AND iv_sub_obj_name IS NOT INITIAL. + + " For the line navigation we have to supply the sub object type (iv_sub_obj_type). + " If we use is_item-obj_type it navigates only to the object. + CALL FUNCTION 'RS_TOOL_ACCESS' + EXPORTING + operation = 'SHOW' + object_name = is_item-obj_name + object_type = iv_sub_obj_type + devclass = is_item-devclass + include = iv_sub_obj_name + position = iv_line_number + in_new_window = iv_new_window + EXCEPTIONS + not_executed = 1 + invalid_object_type = 2 + OTHERS = 3. + + rv_exit = boolc( sy-subrc = 0 ). + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_jumper~jump. + + " WebGUI cannot open windows or ADT + IF zcl_abapgit_ui_factory=>get_frontend_services( )->is_webgui( ) = abap_true. + zcx_abapgit_exception=>raise( |Jump not possible in WebGUI| ). + ENDIF. + + " Try all generic jump options + + " 1) ADT Jump + rv_exit = zif_abapgit_gui_jumper~jump_adt( + is_item = is_item + iv_sub_obj_name = is_sub_item-obj_name + iv_line_number = iv_line_number ). + + IF rv_exit = abap_true. + RETURN. + ENDIF. + + " 2) WB Jump with Line Number + rv_exit = jump_wb_line( + is_item = is_item + iv_sub_obj_name = is_sub_item-obj_name + iv_sub_obj_type = is_sub_item-obj_type + iv_line_number = iv_line_number + iv_new_window = iv_new_window ). + + IF rv_exit = abap_true. + RETURN. + ENDIF. + + " 3) WB Jump without Line Number + rv_exit = jump_wb( + is_item = is_item + iv_new_window = iv_new_window ). + + IF rv_exit = abap_true. + RETURN. + ENDIF. + + " 4) Transport Tool Jump + rv_exit = jump_tr( is_item ). + + IF rv_exit = abap_true. + RETURN. + ENDIF. + + " 5) BW Jump + rv_exit = jump_bw( + is_item = is_item + iv_new_window = iv_new_window ). + + ENDMETHOD. + METHOD zif_abapgit_gui_jumper~jump_abapgit. + + DATA lt_spagpa TYPE STANDARD TABLE OF rfc_spagpa. + DATA ls_spagpa LIKE LINE OF lt_spagpa. + DATA lv_save_sy_langu TYPE sy-langu. + DATA lv_subrc TYPE syst-subrc. + DATA lv_tcode TYPE tcode. + DATA lv_msg TYPE c LENGTH 200. + + " https://blogs.sap.com/2017/01/13/logon-language-sy-langu-and-rfc/ + + lv_tcode = zcl_abapgit_services_abapgit=>get_abapgit_tcode( ). + + lv_save_sy_langu = sy-langu. + SET LOCALE LANGUAGE iv_language. + + ls_spagpa-parid = zif_abapgit_definitions=>c_spagpa_param_repo_key. + ls_spagpa-parval = iv_key. + INSERT ls_spagpa INTO TABLE lt_spagpa. + + CALL FUNCTION 'ABAP4_CALL_TRANSACTION' + DESTINATION 'NONE' + STARTING NEW TASK 'ABAPGIT' + EXPORTING + tcode = lv_tcode + TABLES + spagpa_tab = lt_spagpa + EXCEPTIONS + communication_failure = 1 MESSAGE lv_msg + system_failure = 2 MESSAGE lv_msg + resource_failure = 3 + OTHERS = 4. + + lv_subrc = sy-subrc. + + SET LOCALE LANGUAGE lv_save_sy_langu. + + CASE lv_subrc. + WHEN 1. + lv_msg = |Communication error { lv_msg }|. + WHEN 2. + lv_msg = |Language { iv_language } ({ zcl_abapgit_convert=>language_sap1_to_text( iv_language ) })| + && | is not installed|. + WHEN 3. + lv_msg = |{ lv_subrc }|. + ENDCASE. + + IF lv_msg IS INITIAL. + MESSAGE 'Repository opened in a new window' TYPE 'S'. + ELSE. + zcx_abapgit_exception=>raise( |Error starting transaction { lv_tcode }: { lv_msg }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_jumper~jump_adt. + + " Open object in ADT (if enabled) + + DATA lv_adt_jump_enabled TYPE abap_bool. + + lv_adt_jump_enabled = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_adt_jump_enabled( ). + + IF lv_adt_jump_enabled = abap_true. + TRY. + zcl_abapgit_adt_link=>jump( + iv_obj_name = is_item-obj_name + iv_obj_type = is_item-obj_type + iv_sub_obj_name = iv_sub_obj_name + iv_line_number = iv_line_number ). + + rv_exit = abap_true. + CATCH zcx_abapgit_exception ##NO_HANDLER. + " Use fallback + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_gui_jumper~jump_batch_input. + + DATA lv_msg TYPE c LENGTH 80. + + IF iv_new_window = abap_true. + CALL FUNCTION 'ABAP4_CALL_TRANSACTION' + STARTING NEW TASK 'GIT' + EXPORTING + tcode = iv_tcode + mode_val = 'E' + TABLES + using_tab = it_bdcdata + EXCEPTIONS + system_failure = 1 MESSAGE lv_msg + communication_failure = 2 MESSAGE lv_msg + resource_failure = 3 + OTHERS = 4. + ELSE. + CALL FUNCTION 'ABAP4_CALL_TRANSACTION' + EXPORTING + tcode = iv_tcode + mode_val = 'E' + TABLES + using_tab = it_bdcdata + EXCEPTIONS + OTHERS = 4. + ENDIF. + + CASE sy-subrc. + WHEN 1 OR 2. + zcx_abapgit_exception=>raise( |Batch input error for transaction { iv_tcode }: { lv_msg }| ). + WHEN 3 OR 4. + zcx_abapgit_exception=>raise( |Batch input error for transaction { iv_tcode }| ). + ENDCASE. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_adt_link IMPLEMENTATION. + + METHOD link_transport. +* call to CL_CTS_ADT_TM_URI_BUILDER=>CREATE_ADT_URI replaced with logic that works on all systems, + rv_link = |adt://{ sy-sysid }/sap/bc/adt/cts/transportrequests/{ iv_transport }|. + ENDMETHOD. + + METHOD generate. + + DATA: lv_adt_link TYPE string. + DATA: lo_adt_uri_mapper TYPE REF TO object. + DATA: lo_adt_objref TYPE REF TO object. + DATA: lo_adt_sub_objref TYPE REF TO object. + DATA: lv_program TYPE progname. + DATA: lv_include TYPE progname. + + FIELD-SYMBOLS: TYPE string. + + get_adt_objects_and_names( + EXPORTING + iv_obj_name = iv_obj_name + iv_obj_type = iv_obj_type + IMPORTING + eo_adt_uri_mapper = lo_adt_uri_mapper + eo_adt_objectref = lo_adt_objref + ev_program = lv_program + ev_include = lv_include ). + + TRY. + IF iv_sub_obj_name IS NOT INITIAL. + + IF ( lv_program <> iv_obj_name AND lv_include IS INITIAL ) OR + ( lv_program = lv_include AND iv_sub_obj_name IS NOT INITIAL ). + lv_include = iv_sub_obj_name. + ENDIF. + + CALL METHOD lo_adt_uri_mapper->('IF_ADT_URI_MAPPER~MAP_INCLUDE_TO_OBJREF') + EXPORTING + program = lv_program + include = lv_include + line = iv_line_number + line_offset = 0 + end_line = iv_line_number + end_offset = 1 + RECEIVING + result = lo_adt_sub_objref. + IF lo_adt_sub_objref IS NOT INITIAL. + lo_adt_objref = lo_adt_sub_objref. + ENDIF. + + ENDIF. + + ASSIGN ('LO_ADT_OBJREF->REF_DATA-URI') TO . + ASSERT sy-subrc = 0. + + CONCATENATE 'adt://' sy-sysid INTO lv_adt_link. + + rv_result = lv_adt_link. + + CATCH cx_root. + zcx_abapgit_exception=>raise( 'ADT Jump Error' ). + ENDTRY. + + ENDMETHOD. + METHOD get_adt_objects_and_names. + + DATA lv_obj_type TYPE trobjtype. + DATA lv_obj_name TYPE trobj_name. + DATA lo_object TYPE REF TO cl_wb_object. + DATA lo_adt TYPE REF TO object. + + FIELD-SYMBOLS TYPE string. + + lv_obj_name = iv_obj_name. + lv_obj_type = iv_obj_type. + + TRY. + cl_wb_object=>create_from_transport_key( + EXPORTING + p_object = lv_obj_type + p_obj_name = lv_obj_name + RECEIVING + p_wb_object = lo_object + EXCEPTIONS + OTHERS = 1 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'ADT Jump Error' ). + ENDIF. + + CALL METHOD ('CL_ADT_TOOLS_CORE_FACTORY')=>('GET_INSTANCE') + RECEIVING + result = lo_adt. + + IF is_adt_jump_possible( io_object = lo_object + io_adt = lo_adt ) = abap_false. + zcx_abapgit_exception=>raise( 'ADT Jump Error' ). + ENDIF. + + CALL METHOD lo_adt->('IF_ADT_TOOLS_CORE_FACTORY~GET_URI_MAPPER') + RECEIVING + result = eo_adt_uri_mapper. + + CALL METHOD eo_adt_uri_mapper->('IF_ADT_URI_MAPPER~MAP_WB_OBJECT_TO_OBJREF') + EXPORTING + wb_object = lo_object + RECEIVING + result = eo_adt_objectref. + + ASSIGN ('EO_ADT_OBJECTREF->REF_DATA-URI') TO . + ASSERT sy-subrc = 0. + + CALL METHOD eo_adt_uri_mapper->('IF_ADT_URI_MAPPER~MAP_OBJREF_TO_INCLUDE') + EXPORTING + uri = + IMPORTING + program = ev_program + include = ev_include. + + CATCH cx_root. + zcx_abapgit_exception=>raise( 'ADT Jump Error' ). + ENDTRY. + + ENDMETHOD. + METHOD is_adt_jump_possible. + + DATA: lo_wb_request TYPE REF TO cl_wb_request, + lo_adt_uri_mapper_vit TYPE REF TO object, + lv_vit_wb_request TYPE abap_bool. + + cl_wb_request=>create_from_object_ref( + EXPORTING + p_wb_object = io_object + RECEIVING + p_wb_request = lo_wb_request + EXCEPTIONS + illegal_operation = 1 + cancelled = 2 + OTHERS = 3 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'ADT Jump Error' ). + ENDIF. + + TRY. + CALL METHOD io_adt->('IF_ADT_TOOLS_CORE_FACTORY~GET_URI_MAPPER_VIT') + RECEIVING + result = lo_adt_uri_mapper_vit. + + CALL METHOD lo_adt_uri_mapper_vit->('IF_ADT_URI_MAPPER_VIT~IS_VIT_WB_REQUEST') + EXPORTING + wb_request = lo_wb_request + RECEIVING + result = lv_vit_wb_request. + + rv_is_adt_jump_possible = boolc( NOT lv_vit_wb_request = abap_true ). + + CATCH cx_root. + zcx_abapgit_exception=>raise( 'ADT Jump Error' ). + ENDTRY. + + ENDMETHOD. + METHOD jump. + + DATA lv_adt_link TYPE string. + + TRY. + lv_adt_link = generate( + iv_obj_name = iv_obj_name + iv_obj_type = iv_obj_type + iv_sub_obj_name = iv_sub_obj_name + iv_line_number = iv_line_number ). + + zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = lv_adt_link ). + + CATCH cx_root. + zcx_abapgit_exception=>raise( 'ADT Jump Error' ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enhs_hook_d IMPLEMENTATION. + METHOD zif_abapgit_object_enhs~deserialize. + + DATA: lv_enh_shorttext TYPE string, + ls_enh_hook_definition TYPE enh_hook_def, + ls_hook_definition TYPE ty_hook_defifnition, + li_enh_object TYPE REF TO if_enh_object, + li_enh_object_docu TYPE REF TO if_enh_object_docu, + lo_hookdef_tool TYPE REF TO cl_enh_tool_hook_def, + lx_enh_root TYPE REF TO cx_enh_root. + + FIELD-SYMBOLS: TYPE enh_hook_def_ext. + + ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' + CHANGING cg_data = lv_enh_shorttext ). + + ii_xml->read( EXPORTING iv_name = 'BADI_DATA' + CHANGING cg_data = ls_hook_definition ). + + li_enh_object ?= ii_enh_spot_tool. + li_enh_object_docu ?= ii_enh_spot_tool. + + TRY. + li_enh_object_docu->set_shorttext( lv_enh_shorttext ). + + lo_hookdef_tool ?= ii_enh_spot_tool. + + lo_hookdef_tool->set_original_object( pgmid = ls_hook_definition-pgmid + obj_name = ls_hook_definition-obj_name + obj_type = ls_hook_definition-obj_type + program = ls_hook_definition-program + main_type = ls_hook_definition-main_type + main_name = ls_hook_definition-main_name ). + + LOOP AT ls_hook_definition-def_hooks ASSIGNING . + MOVE-CORRESPONDING TO ls_enh_hook_definition. + lo_hookdef_tool->add_hook_def( ls_enh_hook_definition ). + ENDLOOP. + + li_enh_object->save( ). + li_enh_object->activate( ). + li_enh_object->unlock( ). + + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object_enhs~serialize. + + DATA: lo_hookdef_tool TYPE REF TO cl_enh_tool_hook_def, + lv_enh_shorttext TYPE string, + li_enh_object_docu TYPE REF TO if_enh_object_docu, + ls_hook_definition TYPE ty_hook_defifnition. + + lo_hookdef_tool ?= ii_enh_spot_tool. + + li_enh_object_docu ?= ii_enh_spot_tool. + lv_enh_shorttext = li_enh_object_docu->get_shorttext( ). + + ls_hook_definition-def_hooks = lo_hookdef_tool->get_hook_defs( ). + + lo_hookdef_tool->get_original_object( + IMPORTING + pgmid = ls_hook_definition-pgmid + obj_name = ls_hook_definition-obj_name + obj_type = ls_hook_definition-obj_type + main_type = ls_hook_definition-main_type + main_name = ls_hook_definition-main_name + program = ls_hook_definition-program ). + + ii_xml->add( ig_data = ii_enh_spot_tool->get_tool( ) + iv_name = 'TOOL' ). + + ii_xml->add( ig_data = lv_enh_shorttext + iv_name = 'SHORTTEXT' ). + + ii_xml->add( ig_data = ls_hook_definition + iv_name = 'BADI_DATA' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enhs_badi_d IMPLEMENTATION. + METHOD zif_abapgit_object_enhs~deserialize. + + DATA: lv_parent TYPE enhspotcompositename, + lt_enh_badi TYPE enh_badi_data_it, + lo_badidef_tool TYPE REF TO cl_enh_tool_badi_def, + lv_enh_shorttext TYPE string, + li_enh_object TYPE REF TO if_enh_object, + li_enh_object_docu TYPE REF TO if_enh_object_docu, + lx_enh_root TYPE REF TO cx_enh_root. + + FIELD-SYMBOLS: LIKE LINE OF lt_enh_badi. + + ii_xml->read( EXPORTING iv_name = 'PARENT_COMP' + CHANGING cg_data = lv_parent ). + + ii_xml->read( EXPORTING iv_name = 'BADI_DATA' + CHANGING cg_data = lt_enh_badi ). + + ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' + CHANGING cg_data = lv_enh_shorttext ). + + li_enh_object ?= ii_enh_spot_tool. + li_enh_object_docu ?= ii_enh_spot_tool. + + TRY. + li_enh_object_docu->set_shorttext( lv_enh_shorttext ). + + lo_badidef_tool ?= ii_enh_spot_tool. + + LOOP AT lt_enh_badi ASSIGNING . + lo_badidef_tool->add_badi_def( ). + ENDLOOP. + + li_enh_object->save( ). + li_enh_object->activate( ). + li_enh_object->unlock( ). + + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object_enhs~serialize. + + DATA: lv_spot_name TYPE enhspotname, + lv_parent TYPE enhspotcompositename, + lt_enh_badi TYPE enh_badi_data_it, + lo_badidef_tool TYPE REF TO cl_enh_tool_badi_def, + lv_enh_shorttext TYPE string, + li_enh_object_docu TYPE REF TO if_enh_object_docu. + + lo_badidef_tool ?= ii_enh_spot_tool. + + li_enh_object_docu ?= ii_enh_spot_tool. + lv_enh_shorttext = li_enh_object_docu->get_shorttext( ). + + "get parent = composite enhs (ENHC) + lv_parent = cl_r3standard_persistence=>enh_find_parent_composite( lv_spot_name ). + "get subsequent BADI definitions + lt_enh_badi = lo_badidef_tool->get_badi_defs( ). + + ii_xml->add( ig_data = ii_enh_spot_tool->get_tool( ) + iv_name = 'TOOL' ). + + ii_xml->add( ig_data = lv_enh_shorttext + iv_name = 'SHORTTEXT' ). + + ii_xml->add( ig_data = lv_parent + iv_name = 'PARENT_COMP' ). + + ii_xml->add( ig_data = lt_enh_badi + iv_name = 'BADI_DATA' ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enho_wdyn IMPLEMENTATION. + METHOD constructor. + ms_item = is_item. + ENDMETHOD. + METHOD zif_abapgit_object_enho~deserialize. + + DATA: ls_enh_data TYPE enhwdyn, + li_tool TYPE REF TO if_enh_tool, + lo_wdyn TYPE REF TO cl_enh_tool_wdy, + lv_tool_type TYPE enhtooltype, + lv_package TYPE devclass. + + FIELD-SYMBOLS: TYPE enhwdyc, + TYPE enhwdyv. + ii_xml->read( + EXPORTING + iv_name = 'TOOL' + CHANGING + cg_data = lv_tool_type ). + + ii_xml->read( + EXPORTING + iv_name = 'COMPONENT_DATA' + CHANGING + cg_data = ls_enh_data ). + + lv_package = iv_package. + + TRY. + cl_enh_factory=>create_enhancement( + EXPORTING + enhname = |{ ms_item-obj_name }| + enhtype = '' + enhtooltype = lv_tool_type + IMPORTING + enhancement = li_tool + CHANGING + devclass = lv_package ). + + lo_wdyn ?= li_tool. + + lo_wdyn->initialize( ls_enh_data-component_name ). + + lo_wdyn->set_component_data( ls_enh_data-component_data ). + + LOOP AT ls_enh_data-controller_data ASSIGNING . + + lo_wdyn->set_controller_data( p_controller_name = -controller_name + p_enh_data = ). + + ENDLOOP. + + LOOP AT ls_enh_data-view_data ASSIGNING . + + lo_wdyn->set_view_data( p_view_name = -view_name + p_enh_data = ). + + ENDLOOP. + + lo_wdyn->if_enh_object~save( run_dark = abap_true ). + lo_wdyn->if_enh_object~unlock( ). + + CATCH cx_root. + TRY. + lo_wdyn->if_enh_object~unlock( ). + CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. + ENDTRY. + zcx_abapgit_exception=>raise( |error deserializing ENHO wdyn { ms_item-obj_name }| ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object_enho~serialize. + + DATA: lo_wdyn TYPE REF TO cl_enh_tool_wdy, + lv_component_name TYPE wdy_component_name, + ls_enh_data TYPE enhwdyn. + lo_wdyn ?= ii_enh_tool. + lv_component_name = lo_wdyn->get_component_name( ). + + TRY. + lo_wdyn->get_all_data_for_comp( + EXPORTING + p_component_name = lv_component_name + IMPORTING + p_enh_data = ls_enh_data ). + + ii_xml->add( iv_name = 'TOOL' + ig_data = ii_enh_tool->get_tool( ) ). + + ii_xml->add( iv_name = 'COMPONENT_DATA' + ig_data = ls_enh_data ). + + CATCH cx_enh_not_found. + zcx_abapgit_exception=>raise( |error serializing ENHO wdyn { ms_item-obj_name }| ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enho_wdyc IMPLEMENTATION. + METHOD constructor. + ms_item = is_item. + ENDMETHOD. + METHOD zif_abapgit_object_enho~deserialize. + + DATA: lv_enhname TYPE enhname, + lo_wdyconf TYPE REF TO cl_wdr_cfg_enhancement, + li_tool TYPE REF TO if_enh_tool, + ls_obj TYPE wdy_config_key, + lv_xml TYPE string, + lt_data TYPE wdy_cfg_expl_data_tab, + lv_package TYPE devclass. + + ii_xml->read( EXPORTING iv_name = 'ORIGINAL_OBJECT' + CHANGING cg_data = ls_obj ). + + ii_xml->read( EXPORTING iv_name = 'ENHANCEMENT_DATA' + CHANGING cg_data = lv_xml ). + + lv_enhname = ms_item-obj_name. + lv_package = iv_package. + TRY. + cl_enh_factory=>create_enhancement( + EXPORTING + enhname = lv_enhname + enhtype = '' + enhtooltype = cl_wdr_cfg_enhancement=>tooltype + IMPORTING + enhancement = li_tool + CHANGING + devclass = lv_package ). + + lo_wdyconf ?= li_tool. + + CALL METHOD cl_wdr_cfg_persistence_utils=>('COMP_XML_TO_TABLES') + EXPORTING + xml_content = lv_xml + IMPORTING + expl_data_tab = lt_data. + +* only works on new ABAP versions, parameters differ between versions + CALL METHOD lo_wdyconf->('SET_ENHANCEMENT_DATA') + EXPORTING + p_enh_data = lt_data. + + lo_wdyconf->if_enh_object~save( run_dark = abap_true ). + lo_wdyconf->if_enh_object~unlock( ). + CATCH cx_enh_root cx_static_check. + TRY. + lo_wdyconf->if_enh_object~unlock( ). + CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. + ENDTRY. + zcx_abapgit_exception=>raise( 'error deserializing ENHO wdyconf' ). + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_object_enho~serialize. + + DATA: lo_wdyconf TYPE REF TO cl_wdr_cfg_enhancement, + lt_data TYPE wdy_cfg_expl_data_tab, + ls_outline TYPE wdy_cfg_outline_data, + ls_obj TYPE wdy_config_key, + li_document TYPE REF TO if_ixml_document, + li_element TYPE REF TO if_ixml_element. + lo_wdyconf ?= ii_enh_tool. + + ls_obj = lo_wdyconf->get_original_object( ). + ii_xml->add( iv_name = 'TOOL' + ig_data = ii_enh_tool->get_tool( ) ). + ii_xml->add( iv_name = 'ORIGINAL_OBJECT' + ig_data = ls_obj ). + +* only works on new ABAP versions, parameters differ between versions + CALL METHOD lo_wdyconf->('GET_ENHANCEMENT_DATA') + EXPORTING + p_scope = 1 + IMPORTING + p_enh_data = lt_data. + + CALL METHOD cl_wdr_cfg_persistence_utils=>('COMP_TABLES_TO_XML') + EXPORTING + outline_data = ls_outline + expl_data_tab = lt_data + IMPORTING + element = li_element + CHANGING + document = li_document. + + ii_xml->add_xml( iv_name = 'ENHANCEMENT_DATA' + ii_xml = li_element ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enho_intf IMPLEMENTATION. + METHOD constructor. + ms_item = is_item. + mo_files = io_files. + ENDMETHOD. + METHOD zif_abapgit_object_enho~deserialize. + + DATA: lo_enh_intf TYPE REF TO cl_enh_tool_intf, + li_tool TYPE REF TO if_enh_tool, + lv_shorttext TYPE string, + lv_class TYPE seoclsname, + lv_enhname TYPE enhname, + lv_package TYPE devclass, + lx_enh_root TYPE REF TO cx_enh_root. + + ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' + CHANGING cg_data = lv_shorttext ). + ii_xml->read( EXPORTING iv_name = 'CLASS' + CHANGING cg_data = lv_class ). + + lv_enhname = ms_item-obj_name. + lv_package = iv_package. + TRY. + cl_enh_factory=>create_enhancement( + EXPORTING + enhname = lv_enhname + enhtype = '' + enhtooltype = cl_enh_tool_intf=>tooltype + IMPORTING + enhancement = li_tool + CHANGING + devclass = lv_package ). + lo_enh_intf ?= li_tool. + + lo_enh_intf->if_enh_object_docu~set_shorttext( lv_shorttext ). + lo_enh_intf->set_class( lv_class ). + + zcl_abapgit_object_enho_clif=>deserialize( + io_xml = ii_xml + io_clif = lo_enh_intf ). + + lo_enh_intf->if_enh_object~save( run_dark = abap_true ). + lo_enh_intf->if_enh_object~unlock( ). + CATCH cx_enh_root INTO lx_enh_root. + TRY. + lo_enh_intf->if_enh_object~unlock( ). + CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. + ENDTRY. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object_enho~serialize. + + DATA: lo_enh_intf TYPE REF TO cl_enh_tool_intf, + lv_class TYPE seoclsname, + lv_shorttext TYPE string. + lo_enh_intf ?= ii_enh_tool. + + lv_shorttext = lo_enh_intf->if_enh_object_docu~get_shorttext( ). + lo_enh_intf->get_class( IMPORTING class_name = lv_class ). + + ii_xml->add( iv_name = 'TOOL' + ig_data = ii_enh_tool->get_tool( ) ). + ii_xml->add( ig_data = lv_shorttext + iv_name = 'SHORTTEXT' ). + ii_xml->add( iv_name = 'CLASS' + ig_data = lv_class ). + + zcl_abapgit_object_enho_clif=>serialize( + io_xml = ii_xml + io_clif = lo_enh_intf ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_ENHO_HOOK IMPLEMENTATION. + METHOD add_sources. + + DATA lv_source TYPE string. + DATA ls_file LIKE LINE OF ct_files. + + FIELD-SYMBOLS LIKE LINE OF ct_enhancements. + + LOOP AT ct_enhancements ASSIGNING . + " Use hash as filename since full_name is very long + CLEAR ls_file. + ls_file-name = -full_name. + ls_file-file = substring( + val = zcl_abapgit_hash=>sha1_string( -full_name ) + len = 8 ). + INSERT ls_file INTO TABLE ct_files. + + " Add full name as comment and put code between enhancement statements + lv_source = c_enhancement. + REPLACE '*' IN lv_source WITH ms_item-obj_name. + INSERT lv_source INTO -source INDEX 1. + + lv_source = |"Name: { -full_name }|. + INSERT lv_source INTO -source INDEX 1. + + APPEND c_endenhancement TO -source. + + mo_files->add_abap( iv_extra = ls_file-file + it_abap = -source ). + + CLEAR -source. + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + ms_item = is_item. + mo_files = io_files. + ENDMETHOD. + METHOD hook_impl_deserialize. + + FIELD-SYMBOLS: LIKE LINE OF ct_impl, + TYPE string, + TYPE i, + LIKE LINE OF it_spaces. + LOOP AT ct_impl ASSIGNING . + READ TABLE it_spaces ASSIGNING WITH KEY full_name = -full_name. + IF sy-subrc = 0. + LOOP AT -source ASSIGNING . + READ TABLE -spaces ASSIGNING INDEX sy-tabix. + IF sy-subrc = 0 AND > 0. + DO TIMES. + CONCATENATE space INTO RESPECTING BLANKS. + ENDDO. + ENDIF. + ENDLOOP. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD read_sources. + + DATA lv_source TYPE string. + DATA ls_file LIKE LINE OF ct_files. + DATA lv_from TYPE i. + DATA lv_to TYPE i. + + FIELD-SYMBOLS LIKE LINE OF ct_enhancements. + + LOOP AT ct_enhancements ASSIGNING . + READ TABLE ct_files INTO ls_file WITH TABLE KEY name = -full_name. + IF sy-subrc = 0. + -source = mo_files->read_abap( iv_extra = ls_file-file ). + " Get code between enhancement statements + LOOP AT -source INTO lv_source. + IF lv_source CP c_enhancement. + lv_from = sy-tabix. + ENDIF. + IF lv_source CP c_endenhancement. + lv_to = sy-tabix. + ENDIF. + ENDLOOP. + DELETE -source FROM lv_to. + DELETE -source TO lv_from. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_object_enho~deserialize. + + DATA: lv_shorttext TYPE string, + lo_hook_impl TYPE REF TO cl_enh_tool_hook_impl, + li_tool TYPE REF TO if_enh_tool, + lv_enhname TYPE enhname, + lv_package TYPE devclass, + ls_original_object TYPE enh_hook_admin, + lt_spaces TYPE ty_spaces_tt, + lt_files TYPE ty_files, + lt_enhancements TYPE enh_hook_impl_it, + lx_enh_root TYPE REF TO cx_enh_root. + + FIELD-SYMBOLS: LIKE LINE OF lt_enhancements. + ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' + CHANGING cg_data = lv_shorttext ). + ii_xml->read( EXPORTING iv_name = 'ORIGINAL_OBJECT' + CHANGING cg_data = ls_original_object ). + ii_xml->read( EXPORTING iv_name = 'ENHANCEMENTS' + CHANGING cg_data = lt_enhancements ). + ii_xml->read( EXPORTING iv_name = 'FILES' + CHANGING cg_data = lt_files ). + ii_xml->read( EXPORTING iv_name = 'SPACES' + CHANGING cg_data = lt_spaces ). + + " todo: kept for compatibility, remove after grace period #3680 + hook_impl_deserialize( EXPORTING it_spaces = lt_spaces + CHANGING ct_impl = lt_enhancements ). + + read_sources( CHANGING ct_enhancements = lt_enhancements + ct_files = lt_files ). + + lv_enhname = ms_item-obj_name. + lv_package = iv_package. + TRY. + cl_enh_factory=>create_enhancement( + EXPORTING + enhname = lv_enhname + enhtype = cl_abstract_enh_tool_redef=>credefinition + enhtooltype = cl_enh_tool_hook_impl=>tooltype + IMPORTING + enhancement = li_tool + CHANGING + devclass = lv_package ). + lo_hook_impl ?= li_tool. + + lo_hook_impl->if_enh_object_docu~set_shorttext( lv_shorttext ). + lo_hook_impl->set_original_object( + pgmid = ls_original_object-pgmid + obj_name = ls_original_object-org_obj_name + obj_type = ls_original_object-org_obj_type + program = ls_original_object-programname + main_type = ls_original_object-org_main_type + main_name = ls_original_object-org_main_name ). + lo_hook_impl->set_include_bound( ls_original_object-include_bound ). + + LOOP AT lt_enhancements ASSIGNING . + lo_hook_impl->add_hook_impl( + overwrite = -overwrite + method = -method + enhmode = -enhmode + full_name = -full_name + source = -source + spot = -spotname + parent_full_name = -parent_full_name ). + ENDLOOP. + lo_hook_impl->if_enh_object~save( run_dark = abap_true ). + lo_hook_impl->if_enh_object~unlock( ). + CATCH cx_enh_root INTO lx_enh_root. + TRY. + lo_hook_impl->if_enh_object~unlock( ). + CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. + ENDTRY. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object_enho~serialize. + + DATA: lv_shorttext TYPE string, + lo_hook_impl TYPE REF TO cl_enh_tool_hook_impl, + ls_original_object TYPE enh_hook_admin, + lt_spaces TYPE ty_spaces_tt, + lt_files TYPE ty_files, + ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, + lt_enhancements TYPE enh_hook_impl_it. + + FIELD-SYMBOLS: LIKE LINE OF lt_enhancements. + + lo_hook_impl ?= ii_enh_tool. + + lv_shorttext = lo_hook_impl->if_enh_object_docu~get_shorttext( ). + lo_hook_impl->get_original_object( + IMPORTING + pgmid = ls_original_object-pgmid + obj_name = ls_original_object-org_obj_name + obj_type = ls_original_object-org_obj_type + main_type = ls_original_object-org_main_type + main_name = ls_original_object-org_main_name + program = ls_original_object-programname ). + +* dont call method lo_hook_impl->get_include_bound( ), it might dump +* if the PROG does not exists + IF ls_original_object-org_main_type = 'PROG' OR ls_original_object-org_main_type = 'REPS'. + TRY. + ls_progdir = zcl_abapgit_factory=>get_sap_report( )->read_progdir( ls_original_object-org_main_name ). + ls_original_object-include_bound = boolc( ls_progdir-subc = 'I' ). + CATCH zcx_abapgit_exception. + ls_original_object-include_bound = abap_false. + ENDTRY. + ENDIF. + + lt_enhancements = lo_hook_impl->get_hook_impls( ). + + LOOP AT lt_enhancements ASSIGNING . + CLEAR: -extid, + -id. + ENDLOOP. + + add_sources( CHANGING ct_enhancements = lt_enhancements + ct_files = lt_files ). + + ii_xml->add( iv_name = 'TOOL' + ig_data = ii_enh_tool->get_tool( ) ). + ii_xml->add( iv_name = 'SHORTTEXT' + ig_data = lv_shorttext ). + ii_xml->add( iv_name = 'ORIGINAL_OBJECT' + ig_data = ls_original_object ). + ii_xml->add( iv_name = 'ENHANCEMENTS' + ig_data = lt_enhancements ). + ii_xml->add( iv_name = 'FILES' + ig_data = lt_files ). + ii_xml->add( iv_name = 'SPACES' + ig_data = lt_spaces ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enho_fugr IMPLEMENTATION. + METHOD constructor. + ms_item = is_item. + mo_files = io_files. + ENDMETHOD. + METHOD zif_abapgit_object_enho~deserialize. + + DATA: lo_fugrdata TYPE REF TO cl_enh_tool_fugr, + ls_enha_data TYPE enhfugrdata, + li_tool TYPE REF TO if_enh_tool, + lv_tool TYPE enhtooltype, + lv_package TYPE devclass, + lx_enh_root TYPE REF TO cx_enh_root. + + FIELD-SYMBOLS: TYPE enhfugrfuncdata. + + ii_xml->read( + EXPORTING + iv_name = 'TOOL' + CHANGING + cg_data = lv_tool ). + + ii_xml->read( + EXPORTING + iv_name = 'FUGRDATA' + CHANGING + cg_data = ls_enha_data ). + + lv_package = iv_package. + + TRY. + cl_enh_factory=>create_enhancement( + EXPORTING + enhname = |{ ms_item-obj_name }| + enhtype = '' + enhtooltype = lv_tool + IMPORTING + enhancement = li_tool + CHANGING + devclass = lv_package ). + + lo_fugrdata ?= li_tool. + + lo_fugrdata->set_fugr( ls_enha_data-fugr ). + + LOOP AT ls_enha_data-enh_fubas ASSIGNING . + + lo_fugrdata->set_func_data( func_name = -fuba + func_enhadata = ). + + ENDLOOP. + + lo_fugrdata->if_enh_object~save( run_dark = abap_true ). + lo_fugrdata->if_enh_object~unlock( ). + CATCH cx_enh_root INTO lx_enh_root. + TRY. + lo_fugrdata->if_enh_object~unlock( ). + CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. + ENDTRY. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object_enho~serialize. + + DATA: lo_fugrdata TYPE REF TO cl_enh_tool_fugr, + lv_fugr_name TYPE rs38l-area, + ls_enha_data TYPE enhfugrdata. + + FIELD-SYMBOLS: TYPE enhfugrparamdocu. + lo_fugrdata ?= ii_enh_tool. + + lo_fugrdata->get_fugr( IMPORTING fugr_name = lv_fugr_name ). + + TRY. + lo_fugrdata->get_all_data_for_fugr( + EXPORTING + fugr_name = lv_fugr_name + IMPORTING + enha_data = ls_enha_data ). + + LOOP AT ls_enha_data-docuobjs ASSIGNING . + CLEAR: -shorttext, + -longtext. + ENDLOOP. + + CATCH cx_enh_not_found. + zcx_abapgit_exception=>raise( |error deserializing ENHO fugrdata { ms_item-obj_name }| ). + ENDTRY. + + ii_xml->add( iv_name = 'TOOL' + ig_data = lo_fugrdata->if_enh_tool~get_tool( ) ). + + ii_xml->add( iv_name = 'FUGRDATA' + ig_data = ls_enha_data ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enho_clif IMPLEMENTATION. + METHOD deserialize. + + DATA: lt_tab_attributes TYPE enhclasstabattrib, + lt_tab_types TYPE enhtype_tab, + lt_tab_methods TYPE enhnewmeth_tab, + ls_type_line TYPE vseotype, + ls_header TYPE vseomethod, + ls_param TYPE vseomepara, + ls_exc TYPE vseoexcep, + lt_tab_eventdata TYPE enhevent_tab, + ls_event_line TYPE vseoevent, + ls_event_param TYPE vseoeparam. + + FIELD-SYMBOLS: LIKE LINE OF lt_tab_types, + LIKE LINE OF lt_tab_methods, + LIKE LINE OF -meth_param, + LIKE LINE OF lt_tab_eventdata, + LIKE LINE OF -meth_exc, + LIKE LINE OF -event_param. + io_xml->read( EXPORTING iv_name = 'TAB_ATTRIBUTES' + CHANGING cg_data = lt_tab_attributes ). + io_xml->read( EXPORTING iv_name = 'TAB_TYPES' + CHANGING cg_data = lt_tab_types ). + io_xml->read( EXPORTING iv_name = 'TAB_METHODS' + CHANGING cg_data = lt_tab_methods ). + io_xml->read( EXPORTING iv_name = 'TAB_EVENTDATA' + CHANGING cg_data = lt_tab_eventdata ). + + LOOP AT lt_tab_types ASSIGNING . + MOVE-CORRESPONDING TO ls_type_line. + TRY. + io_clif->add_change_enha_type( type_line = ls_type_line ). + CATCH cx_enh_mod_not_allowed + cx_enh_is_not_enhanceable ##NO_HANDLER. + " TODO + ENDTRY. + ENDLOOP. + + io_clif->set_enhattributes( lt_tab_attributes ). + +* SAP standard SET_ENH_NEW_METHOS does not work + + LOOP AT lt_tab_methods ASSIGNING . + + MOVE-CORRESPONDING -meth_header TO ls_header. + + io_clif->add_change_new_enh_method( + methkey = -methkey + method_header = ls_header ). + +* parameters + LOOP AT -meth_param ASSIGNING . + MOVE-CORRESPONDING TO ls_param. + io_clif->add_change_enh_methparam( + methname = -methkey-cmpname + param_line = ls_param ). + ENDLOOP. + +* exceptions + LOOP AT -meth_exc ASSIGNING . + MOVE-CORRESPONDING TO ls_exc. + io_clif->add_change_enh_methexc( + methname = -methkey-cmpname + except_line = ls_exc ). + ENDLOOP. + + ENDLOOP. + + " events are renumbered based on + LOOP AT lt_tab_eventdata ASSIGNING . + + MOVE-CORRESPONDING -event_header TO ls_event_line. + + io_clif->add_change_enha_event( + event_key = -eventkey + event_line = ls_event_line ). + +* parameters + LOOP AT -event_param ASSIGNING . + MOVE-CORRESPONDING TO ls_event_param. + io_clif->add_change_enh_eventparam( + eventname = -eventkey-cmpname + event_param = ls_event_param ). + ENDLOOP. + + ENDLOOP. + + ENDMETHOD. + METHOD serialize. + + DATA: lt_tab_attributes TYPE enhclasstabattrib, + lt_tab_types TYPE enhtype_tab, + lt_tab_methods TYPE enhnewmeth_tab, + lt_tab_eventdata TYPE enhevent_tab, + lv_editorder TYPE i. + + FIELD-SYMBOLS: LIKE LINE OF lt_tab_attributes, + LIKE LINE OF lt_tab_types, + LIKE LINE OF lt_tab_methods, + LIKE LINE OF -meth_param, + LIKE LINE OF -meth_exc, + LIKE LINE OF lt_tab_eventdata, + LIKE LINE OF -event_param. + io_clif->get_enhattributes( IMPORTING tab_attributes = lt_tab_attributes ). + + io_clif->get_enhatypes( IMPORTING tab_types = lt_tab_types ). + + io_clif->get_enh_new_methodes( IMPORTING tab_methodes = lt_tab_methods ). + + io_clif->get_enhevents( IMPORTING tab_eventdata = lt_tab_eventdata ). + + LOOP AT lt_tab_attributes ASSIGNING . + CLEAR: -author, + -createdon, + -changedby, + -changedon, + -descript_id. + ENDLOOP. + + LOOP AT lt_tab_types ASSIGNING . + CLEAR: -author, + -createdon, + -changedby, + -changedon, + -descript_id. + ENDLOOP. + + lv_editorder = 0. + SORT lt_tab_methods BY meth_header-editorder. + LOOP AT lt_tab_methods ASSIGNING . + CLEAR: -meth_header-author, + -meth_header-createdon, + -meth_header-changedby, + -meth_header-changedon, + -meth_header-descript_id. + lv_editorder = lv_editorder + 1. + -meth_header-editorder = lv_editorder. + LOOP AT -meth_param ASSIGNING . + CLEAR: -author, + -createdon, + -changedby, + -changedon, + -descript_id. + ENDLOOP. + LOOP AT -meth_exc ASSIGNING . + CLEAR: -author, + -createdon, + -changedby, + -changedon, + -descript_id. + ENDLOOP. + ENDLOOP. + + LOOP AT lt_tab_eventdata ASSIGNING . + CLEAR: -event_header-author, + -event_header-createdon, + -event_header-changedby, + -event_header-changedon, + -event_header-descript_id. + LOOP AT -event_param ASSIGNING . + CLEAR: -author, + -createdon, + -changedby, + -changedon, + -descript_id. + ENDLOOP. + ENDLOOP. + + io_xml->add( iv_name = 'TAB_ATTRIBUTES' + ig_data = lt_tab_attributes ). + io_xml->add( iv_name = 'TAB_TYPES' + ig_data = lt_tab_types ). + io_xml->add( iv_name = 'TAB_METHODS' + ig_data = lt_tab_methods ). + io_xml->add( iv_name = 'TAB_EVENTDATA' + ig_data = lt_tab_eventdata ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enho_class IMPLEMENTATION. + METHOD adjust_generated_comments. + + FIELD-SYMBOLS LIKE LINE OF ct_source. + + " Enhancements contain comments that end in '.' or ' .' depending on release + " This routine replaces the space-dot with just dot + LOOP AT ct_source ASSIGNING . + IF strlen( ) > 2. + = replace( + val = + regex = '^(\*".*) \.$' + with = '$1.' ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + ms_item = is_item. + mo_files = io_files. + ENDMETHOD. + METHOD deserialize_includes. + + DATA: lt_tab_methods TYPE enhnewmeth_tab, + lv_editorder TYPE n LENGTH 3, + lv_methname TYPE seocpdname, + lt_abap TYPE rswsourcet, + lx_enh_root TYPE REF TO cx_enh_root, + lv_new_em TYPE abap_bool, + lt_files TYPE zif_abapgit_git_definitions=>ty_files_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_tab_methods, + TYPE zif_abapgit_git_definitions=>ty_file. + + ii_xml->read( EXPORTING iv_name = 'TAB_METHODS' + CHANGING cg_data = lt_tab_methods ). + + lv_new_em = abap_false. + lt_files = mo_files->get_files( ). + LOOP AT lt_files ASSIGNING + WHERE filename CS 'enho.em_'. + lv_new_em = abap_true. + EXIT. + ENDLOOP. + + SORT lt_tab_methods BY meth_header-editorder. + LOOP AT lt_tab_methods ASSIGNING . + + lv_methname = -methkey-cmpname. + IF lv_new_em = abap_true. + lt_abap = mo_files->read_abap( iv_extra = 'em_' && lv_methname ). + ELSE. + " old way + lv_editorder = -meth_header-editorder. + lt_abap = mo_files->read_abap( iv_extra = 'em' && lv_editorder ). + ENDIF. + + TRY. + io_class->add_change_new_method_source( + clsname = -methkey-clsname + methname = lv_methname + methsource = lt_abap ). + CATCH cx_enh_root INTO lx_enh_root. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDLOOP. + + ENDMETHOD. + METHOD serialize_includes. + + DATA: lt_includes TYPE enhnewmeth_tabincl_plus_enha, + lt_source TYPE TABLE OF abaptxt255, + lv_include TYPE syrepid. + + FIELD-SYMBOLS: LIKE LINE OF lt_includes. + lt_includes = io_class->get_enh_method_includes( ). + LOOP AT lt_includes ASSIGNING . + lv_include = io_class->if_enh_tool~get_name( ). + TRANSLATE lv_include USING ' ='. + lv_include+30 = 'EM'. + lv_include+32(8) = -includenr. + + CALL FUNCTION 'RPY_PROGRAM_READ' + EXPORTING + program_name = lv_include + with_includelist = abap_false + with_lowercase = abap_true + TABLES + source_extended = lt_source + EXCEPTIONS + cancelled = 1 + not_found = 2 + permission_error = 3 + OTHERS = 4. + IF sy-subrc = 0. + mo_files->add_abap( iv_extra = |EM_{ -cpdname }| + it_abap = lt_source ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_object_enho~deserialize. + + DATA: lo_enh_class TYPE REF TO cl_enh_tool_class, + lt_owr TYPE enhmeth_tabkeys, + lt_pre TYPE enhmeth_tabkeys, + lt_post TYPE enhmeth_tabkeys, + lt_source TYPE rswsourcet, + li_tool TYPE REF TO if_enh_tool, + lv_shorttext TYPE string, + lv_class TYPE seoclsname, + lv_enhname TYPE enhname, + lv_package TYPE devclass, + lx_enh_root TYPE REF TO cx_enh_root. + + ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' + CHANGING cg_data = lv_shorttext ). + ii_xml->read( EXPORTING iv_name = 'OWR_METHODS' + CHANGING cg_data = lt_owr ). + ii_xml->read( EXPORTING iv_name = 'PRE_METHODS' + CHANGING cg_data = lt_pre ). + ii_xml->read( EXPORTING iv_name = 'POST_METHODS' + CHANGING cg_data = lt_post ). + ii_xml->read( EXPORTING iv_name = 'CLASS' + CHANGING cg_data = lv_class ). + lt_source = mo_files->read_abap( ). + + lv_enhname = ms_item-obj_name. + lv_package = iv_package. + TRY. + cl_enh_factory=>create_enhancement( + EXPORTING + enhname = lv_enhname + enhtype = '' + enhtooltype = cl_enh_tool_class=>tooltype + IMPORTING + enhancement = li_tool + CHANGING + devclass = lv_package ). + lo_enh_class ?= li_tool. + + lo_enh_class->if_enh_object_docu~set_shorttext( lv_shorttext ). + lo_enh_class->set_class( lv_class ). + lo_enh_class->set_owr_methods( version = 'I' + owr_methods = lt_owr ). + lo_enh_class->set_pre_methods( version = 'I' + pre_methods = lt_pre ). + lo_enh_class->set_post_methods( version = 'I' + post_methods = lt_post ). + lo_enh_class->set_eimp_include( version = 'I' + eimp_source = lt_source ). + + zcl_abapgit_object_enho_clif=>deserialize( + io_xml = ii_xml + io_clif = lo_enh_class ). + + deserialize_includes( + ii_xml = ii_xml + io_class = lo_enh_class ). + + lo_enh_class->if_enh_object~save( run_dark = abap_true ). + lo_enh_class->if_enh_object~unlock( ). + CATCH cx_enh_root INTO lx_enh_root. + TRY. + lo_enh_class->if_enh_object~unlock( ). + CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. + ENDTRY. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object_enho~serialize. + + DATA: lo_enh_class TYPE REF TO cl_enh_tool_class, + lt_owr TYPE enhmeth_tabkeys, + lt_pre TYPE enhmeth_tabkeys, + lt_post TYPE enhmeth_tabkeys, + lt_source TYPE rswsourcet, + lv_class TYPE seoclsname, + lv_shorttext TYPE string. + lo_enh_class ?= ii_enh_tool. + + lv_shorttext = lo_enh_class->if_enh_object_docu~get_shorttext( ). + lt_owr = lo_enh_class->get_owr_methods( ). + lt_pre = lo_enh_class->get_pre_methods( ). + lt_post = lo_enh_class->get_post_methods( ). + lt_source = lo_enh_class->get_eimp_include( ). + lo_enh_class->get_class( IMPORTING class_name = lv_class ). + + ii_xml->add( iv_name = 'TOOL' + ig_data = ii_enh_tool->get_tool( ) ). + ii_xml->add( ig_data = lv_shorttext + iv_name = 'SHORTTEXT' ). + ii_xml->add( iv_name = 'CLASS' + ig_data = lv_class ). + ii_xml->add( iv_name = 'OWR_METHODS' + ig_data = lt_owr ). + ii_xml->add( iv_name = 'PRE_METHODS' + ig_data = lt_pre ). + ii_xml->add( iv_name = 'POST_METHODS' + ig_data = lt_post ). + + adjust_generated_comments( CHANGING ct_source = lt_source ). + + mo_files->add_abap( lt_source ). + + zcl_abapgit_object_enho_clif=>serialize( + io_xml = ii_xml + io_clif = lo_enh_class ). + + serialize_includes( lo_enh_class ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_enho_badi IMPLEMENTATION. + METHOD constructor. + ms_item = is_item. + ENDMETHOD. + METHOD zif_abapgit_object_enho~deserialize. + + DATA: lv_spot_name TYPE enhspotname, + lv_shorttext TYPE string, + lv_enhname TYPE enhname, + lo_badi TYPE REF TO cl_enh_tool_badi_impl, + li_tool TYPE REF TO if_enh_tool, + lv_package TYPE devclass, + lt_impl TYPE enh_badi_impl_data_it, + lx_enh_root TYPE REF TO cx_enh_root. + + FIELD-SYMBOLS: LIKE LINE OF lt_impl. + + ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' + CHANGING cg_data = lv_shorttext ). + ii_xml->read( EXPORTING iv_name = 'SPOT_NAME' + CHANGING cg_data = lv_spot_name ). + ii_xml->read( EXPORTING iv_name = 'IMPL' + CHANGING cg_data = lt_impl ). + + lv_enhname = ms_item-obj_name. + lv_package = iv_package. + TRY. + cl_enh_factory=>create_enhancement( + EXPORTING + enhname = lv_enhname + enhtype = cl_abstract_enh_tool_redef=>credefinition + enhtooltype = cl_enh_tool_badi_impl=>tooltype + IMPORTING + enhancement = li_tool + CHANGING + devclass = lv_package ). + lo_badi ?= li_tool. + + lo_badi->set_spot_name( lv_spot_name ). + lo_badi->if_enh_object_docu~set_shorttext( lv_shorttext ). + LOOP AT lt_impl ASSIGNING . + lo_badi->add_implementation( ). + ENDLOOP. + lo_badi->if_enh_object~save( run_dark = abap_true ). + lo_badi->if_enh_object~unlock( ). + CATCH cx_enh_root INTO lx_enh_root. + TRY. + lo_badi->if_enh_object~unlock( ). + CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. + ENDTRY. + zcx_abapgit_exception=>raise_with_text( lx_enh_root ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object_enho~serialize. + + DATA: lo_badi_impl TYPE REF TO cl_enh_tool_badi_impl, + lv_spot_name TYPE enhspotname, + lv_shorttext TYPE string, + lt_impl TYPE enh_badi_impl_data_it. + + FIELD-SYMBOLS: LIKE LINE OF lt_impl, + LIKE LINE OF -filter_values, + LIKE LINE OF -filters. + lo_badi_impl ?= ii_enh_tool. + + lv_shorttext = lo_badi_impl->if_enh_object_docu~get_shorttext( ). + lv_spot_name = lo_badi_impl->get_spot_name( ). + lt_impl = lo_badi_impl->get_implementations( ). + + LOOP AT lt_impl ASSIGNING . +* make sure the XML serialization does not dump, field type = N + LOOP AT -filter_values ASSIGNING . + IF -filter_numeric_value1 CA space. + CLEAR -filter_numeric_value1. + ENDIF. + ENDLOOP. + LOOP AT -filters ASSIGNING . + IF -filter_numeric_value1 CA space. + CLEAR -filter_numeric_value1. + ENDIF. + ENDLOOP. + ENDLOOP. + + ii_xml->add( iv_name = 'TOOL' + ig_data = ii_enh_tool->get_tool( ) ). + ii_xml->add( ig_data = lv_shorttext + iv_name = 'SHORTTEXT' ). + ii_xml->add( iv_name = 'SPOT_NAME' + ig_data = lv_spot_name ). + ii_xml->add( iv_name = 'IMPL' + ig_data = lt_impl ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_ecatt_val_obj_upl IMPLEMENTATION. + METHOD get_business_msgs_from_dom. + + " downport from CL_APL_ECATT_VO_UPLOAD + + DATA: li_section TYPE REF TO if_ixml_element, + lt_buss_msg_ref TYPE zif_abapgit_ecatt=>ty_bus_msgs, + lv_exception_occurred TYPE etonoff, + lo_ecatt_vo TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any. + + li_section = template_over_all->find_from_name_ns( 'ETVO_MSG' ). + + IF NOT li_section IS INITIAL. + CALL FUNCTION 'SDIXML_DOM_TO_DATA' + EXPORTING + data_as_dom = li_section + IMPORTING + dataobject = lt_buss_msg_ref + EXCEPTIONS + illegal_object = 1 + OTHERS = 2. + IF sy-subrc <> 0. + CLEAR lt_buss_msg_ref. + ENDIF. + ENDIF. + + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_vo = . + + TRY. + CALL METHOD lo_ecatt_vo->('SET_BUSSINESS_MSG') + EXPORTING + im_buss_msg_ref = lt_buss_msg_ref. + CATCH cx_ecatt_apl INTO exception_to_raise. + lv_exception_occurred = 'X'. + ENDTRY. + + IF lv_exception_occurred = 'X'. + raise_upload_exception( previous = exception_to_raise ). + ENDIF. + + ENDMETHOD. + METHOD get_impl_detail_from_dom. + + " downport from CL_APL_ECATT_VO_UPLOAD + + DATA: li_section TYPE REF TO if_ixml_element, + ls_impl_details TYPE zif_abapgit_ecatt=>ty_impl_det, + lv_exception_occurred TYPE etonoff, + lo_ecatt_vo TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any. + + li_section = template_over_all->find_from_name_ns( 'IMPL_DET' ). + + IF NOT li_section IS INITIAL. + CALL FUNCTION 'SDIXML_DOM_TO_DATA' + EXPORTING + data_as_dom = li_section + IMPORTING + dataobject = ls_impl_details + EXCEPTIONS + illegal_object = 1 + OTHERS = 2. + IF sy-subrc <> 0. + CLEAR ls_impl_details. + ENDIF. + ENDIF. + + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_vo = . + + TRY. + CALL METHOD lo_ecatt_vo->('SET_IMPL_DETAILS') + EXPORTING + im_impl_details = ls_impl_details. + CATCH cx_ecatt_apl INTO exception_to_raise. + lv_exception_occurred = 'X'. + ENDTRY. + + IF lv_exception_occurred = 'X'. + raise_upload_exception( previous = exception_to_raise ). + ENDIF. + + ENDMETHOD. + METHOD get_vo_flags_from_dom. + + " downport from CL_APL_ECATT_VO_UPLOAD + + DATA: li_section TYPE REF TO if_ixml_element, + lv_error_prio TYPE zif_abapgit_ecatt=>ty_error_prio, + lv_invert_validation TYPE zif_abapgit_ecatt=>ty_invert_validation, + lv_exception_occurred TYPE etonoff, + lo_ecatt_vo TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any. + + li_section = template_over_all->find_from_name_ns( 'INVERT_VALIDATION' ). + + IF NOT li_section IS INITIAL. + CALL FUNCTION 'SDIXML_DOM_TO_DATA' + EXPORTING + data_as_dom = li_section + IMPORTING + dataobject = lv_invert_validation + EXCEPTIONS + illegal_object = 1 + OTHERS = 2. + IF sy-subrc <> 0. + CLEAR lv_invert_validation. + ENDIF. + ENDIF. + + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_vo = . + + TRY. + CALL METHOD lo_ecatt_vo->('SET_INVERT_VALIDATION_FLAG') + EXPORTING + im_invert_validation = lv_invert_validation. + + CATCH cx_ecatt_apl INTO exception_to_raise. + lv_exception_occurred = 'X'. + ENDTRY. + + li_section = template_over_all->find_from_name_ns( 'ERROR_PRIORITY' ). + + IF NOT li_section IS INITIAL. + CALL FUNCTION 'SDIXML_DOM_TO_DATA' + EXPORTING + data_as_dom = li_section + IMPORTING + dataobject = lv_error_prio + EXCEPTIONS + illegal_object = 1 + OTHERS = 2. + IF sy-subrc <> 0. + CLEAR lv_invert_validation. + ENDIF. + ENDIF. + + TRY. + CALL METHOD lo_ecatt_vo->('SET_ERROR_PRIORITY') + EXPORTING + im_error_prio = lv_error_prio. + CATCH cx_ecatt_apl INTO exception_to_raise. + lv_exception_occurred = 'X'. + ENDTRY. + + IF lv_exception_occurred = 'X'. + raise_upload_exception( previous = exception_to_raise ). + ENDIF. + + ENDMETHOD. + METHOD upload. + + " We inherit from CL_APL_ECATT_UPLOAD because CL_APL_ECATT_VO_UPLOAD + " doesn't exist in 702 + + " downport from CL_APL_ECATT_VO_UPLOAD + + DATA: lx_ex TYPE REF TO cx_ecatt_apl, + lv_exists TYPE etonoff, + lv_exc_occ TYPE etonoff, + ls_tadir TYPE tadir, + lo_ecatt_vo TYPE REF TO object, + lo_params TYPE REF TO cl_apl_ecatt_params. + + FIELD-SYMBOLS: TYPE any, + TYPE data, + TYPE data, + TYPE data. + + TRY. + ch_object-i_devclass = ch_object-d_devclass. + + ASSIGN COMPONENT 'D_AKH' OF STRUCTURE ch_object + TO . " doesn't exist in 702 + ASSIGN COMPONENT 'I_AKH' OF STRUCTURE ch_object + TO . " doesn't exist in 702 + IF IS ASSIGNED AND IS ASSIGNED. + = . + ENDIF. + + super->upload( CHANGING ch_object = ch_object ). + + upload_data_from_stream( ch_object-filename ). + CATCH cx_ecatt_apl INTO lx_ex. + IF template_over_all IS INITIAL. + RAISE EXCEPTION lx_ex. + ELSE. + lv_exc_occ = 'X'. + ENDIF. + ENDTRY. + + TRY. + CALL METHOD ('GET_ATTRIBUTES_FROM_DOM_NEW') " doesn't exit in 702 + CHANGING + ch_object = ch_object. + CATCH cx_ecatt_apl INTO lx_ex. + lv_exc_occ = 'X'. + ENDTRY. + + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_vo = . + + ASSIGN lo_ecatt_vo->('PARAMS') TO . + ASSERT sy-subrc = 0. + + lo_params = . + + TRY. + get_impl_detail_from_dom( ). + CATCH cx_ecatt_apl INTO lx_ex. + lv_exc_occ = 'X'. + ENDTRY. + + TRY. + get_vo_flags_from_dom( ). + CATCH cx_ecatt_apl INTO lx_ex. + lv_exc_occ = 'X'. + ENDTRY. + + TRY. + get_business_msgs_from_dom( ). + CATCH cx_ecatt_apl INTO lx_ex. + lv_exc_occ = 'X'. + ENDTRY. + + TRY. + CALL METHOD ('GET_PARAMS_FROM_DOM_NEW') " doesn't exist in 702 + EXPORTING + im_params = lo_params. + CATCH cx_ecatt_apl INTO lx_ex. + lv_exc_occ = 'X'. + ENDTRY. + + TRY. + get_variants_from_dom( lo_params ). + CATCH cx_ecatt_apl INTO lx_ex. + lv_exc_occ = 'X'. + ENDTRY. + + TRY. + lv_exists = cl_apl_ecatt_object=>existence_check_object( + im_name = ch_object-d_obj_name + im_version = ch_object-d_obj_ver + im_obj_type = ch_object-s_obj_type + im_exists_any_version = 'X' ). + + IF lv_exists = space. + CALL METHOD lo_ecatt_vo->('SET_TADIR_FOR_NEW_OBJECT') + EXPORTING + im_tadir_for_new_object = tadir_preset. + ENDIF. + CATCH cx_ecatt. + CLEAR lv_exists. + ENDTRY. + + TRY. + CALL METHOD lo_ecatt_vo->('SAVE') + EXPORTING + im_do_commit = 'X'. + CATCH cx_ecatt_apl INTO lx_ex. + lv_exc_occ = 'X'. + ENDTRY. + +* get devclass from existing object + TRY. + cl_apl_ecatt_object=>get_tadir_entry( + EXPORTING im_obj_name = ch_object-d_obj_name + im_obj_type = ch_object-s_obj_type + IMPORTING ex_tadir = ls_tadir ). + + ch_object-d_devclass = ls_tadir-devclass. + + CATCH cx_ecatt. + CLEAR ls_tadir. + ENDTRY. + IF lv_exc_occ = 'X'. + raise_upload_exception( previous = lx_ex ). + ENDIF. + + ENDMETHOD. + METHOD upload_data_from_stream. + + " Downport + template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. + + " downport from CL_ABAPGIT_ECATT_DATA_UPLOAD SET_STREAM_FOR_UPLOAD + mv_external_xml = iv_xml. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ECATT_VAL_OBJ_DOWN IMPLEMENTATION. + METHOD download. + + " We inherit from CL_APL_ECATT_DOWNLOAD because CL_APL_ECATT_VO_DOWNLOAD + " doesn't exist in 702 + + " Downport + + DATA: lv_partyp TYPE string, + lo_ecatt_vo TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any, + TYPE REF TO cl_apl_ecatt_params. + + load_help = im_load_help. + typ = im_object_type. + + TRY. + cl_apl_ecatt_object=>show_object( + EXPORTING + im_obj_type = im_object_type + im_name = im_object_name + im_version = im_object_version + IMPORTING + re_object = ecatt_object ). + CATCH cx_ecatt INTO ex_ecatt. + RETURN. + ENDTRY. + + lv_partyp = cl_apl_ecatt_const=>params_type_par. + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_vo = . + + set_attributes_to_template( ). + set_ecatt_impl_detail( ). + set_ecatt_flags( ). + set_business_msgs( ). + + ASSIGN lo_ecatt_vo->('PARAMS') + TO . + ASSERT sy-subrc = 0. + + get_general_params_data( im_params = + im_ptyp = lv_partyp ). + LOOP AT parm INTO wa_parm. + set_general_params_data_to_dom( ). + IF NOT wa_parm-val_type IS INITIAL. + set_deep_stru_to_dom( ). + set_deep_data_to_dom( im_params = + im_pindex = wa_parm-pindex ). + ENDIF. + ENDLOOP. + + set_variants_to_dom( ). + + download_data( ). + + ENDMETHOD. + METHOD download_data. + + " Downport + + mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). + + ENDMETHOD. + METHOD set_business_msgs. + + DATA: + lt_buss_msg_ref TYPE zif_abapgit_ecatt=>ty_bus_msgs, + li_element TYPE REF TO if_ixml_element, + li_insert_objects TYPE REF TO if_ixml_element, + lo_ecatt_vo TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any. + + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_vo = . + + mi_objects_node = template_over_all->create_simple_element( + name = 'BUSINESS_MESSAGES' + parent = root_node ). + + CALL METHOD lo_ecatt_vo->('GET_BUSSINESS_MSG') + IMPORTING + ex_buss_msg_ref = lt_buss_msg_ref. + + CALL FUNCTION 'SDIXML_DATA_TO_DOM' + EXPORTING + name = 'ETVO_MSG' + dataobject = lt_buss_msg_ref + IMPORTING + data_as_dom = li_element + CHANGING + document = template_over_all + EXCEPTIONS + illegal_name = 1 + OTHERS = 2. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + li_insert_objects ?= template_over_all->find_from_name( 'BUSINESS_MESSAGES' ). + + li_insert_objects->append_child( li_element ). + + ENDMETHOD. + METHOD set_ecatt_flags. + + DATA: + lv_invert_validation TYPE zif_abapgit_ecatt=>ty_invert_validation, + lv_error_prio TYPE zif_abapgit_ecatt=>ty_error_prio, + li_element TYPE REF TO if_ixml_element, + li_insert_objects TYPE REF TO if_ixml_element, + lo_ecatt_vo TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any. + + mi_objects_node = template_over_all->create_simple_element( + name = 'VO_FLAGS' + parent = root_node ). + + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_vo = . + + CALL METHOD lo_ecatt_vo->('GET_INVERT_VALIDATION_FLAG') + RECEIVING + re_invert_validation = lv_invert_validation. + + CALL FUNCTION 'SDIXML_DATA_TO_DOM' + EXPORTING + name = 'INVERT_VALIDATION' + dataobject = lv_invert_validation + IMPORTING + data_as_dom = li_element + CHANGING + document = template_over_all + EXCEPTIONS + illegal_name = 1 + OTHERS = 2. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + li_insert_objects ?= template_over_all->find_from_name( 'VO_FLAGS' ). + + li_insert_objects->append_child( li_element ). + + CALL METHOD lo_ecatt_vo->('GET_ERROR_PRIORITY') + RECEIVING + re_error_prio = lv_error_prio. + + CALL FUNCTION 'SDIXML_DATA_TO_DOM' + EXPORTING + name = 'ERROR_PRIORITY' + dataobject = lv_error_prio + IMPORTING + data_as_dom = li_element + CHANGING + document = template_over_all + EXCEPTIONS + illegal_name = 1 + OTHERS = 2. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + li_insert_objects = template_over_all->find_from_name( 'VO_FLAGS' ). + + li_insert_objects->append_child( li_element ). + + ENDMETHOD. + METHOD set_ecatt_impl_detail. + + DATA: + ls_impl_details TYPE zif_abapgit_ecatt=>ty_impl_det, + li_element TYPE REF TO if_ixml_element, + li_insert_objects TYPE REF TO if_ixml_element, + lo_ecatt_vo TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any. + + mi_objects_node = template_over_all->create_simple_element( + name = 'IMPL_DETAILS' + parent = root_node ). + + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_vo = . + + CALL METHOD lo_ecatt_vo->('GET_IMPL_DETAILS') + RECEIVING + re_impl_details = ls_impl_details. + + CALL FUNCTION 'SDIXML_DATA_TO_DOM' + EXPORTING + name = 'IMPL_DET' + dataobject = ls_impl_details + IMPORTING + data_as_dom = li_element + CHANGING + document = template_over_all + EXCEPTIONS + illegal_name = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + li_insert_objects = template_over_all->find_from_name( 'IMPL_DETAILS' ). + + li_insert_objects->append_child( li_element ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_download~get_xml_stream. + + rv_xml_stream = mv_xml_stream. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ECATT_SYSTEM_UPL IMPLEMENTATION. + METHOD upload_data_from_stream. + + " Downport + template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. + + " downport from CL_APL_ECATT_SYSTEMS_UPLOAD SET_STREAM_FOR_UPLOAD + mv_external_xml = iv_xml. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_ecatt_system_downl IMPLEMENTATION. + METHOD download. + + " Downport + + load_help = im_load_help. + typ = im_object_type. + + TRY. + cl_apl_ecatt_object=>show_object( + EXPORTING + im_obj_type = im_object_type + im_name = im_object_name + im_version = im_object_version + IMPORTING + re_object = ecatt_object ). + CATCH cx_ecatt INTO ex_ecatt. + RETURN. + ENDTRY. + + set_attributes_to_template( ). + set_systems_data_to_template( ). + download_data( ). + + ENDMETHOD. + METHOD download_data. + + " Downport + + mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_download~get_xml_stream. + + rv_xml_stream = mv_xml_stream. + + ENDMETHOD. + METHOD set_systems_data_to_template. + + DATA: lo_ecatt_systems TYPE REF TO cl_apl_ecatt_system_data, + lt_sys_data TYPE etsys_def_tabtype, + ls_sys_data TYPE etsys_def, + li_item TYPE REF TO if_ixml_element, + li_sysdata_node TYPE REF TO if_ixml_element. + + lo_ecatt_systems ?= ecatt_object. + lt_sys_data = lo_ecatt_systems->get_system_data( ). + + li_sysdata_node = template_over_all->create_simple_element( + name = 'SYSTEMS_DATA' + parent = root_node ). + + etpar_node = template_over_all->create_simple_element( + name = 'ETSYS_DEF' + parent = li_sysdata_node ). + + LOOP AT lt_sys_data INTO ls_sys_data. + + CLEAR: ls_sys_data-sys_desc, ls_sys_data-instance. + + CALL FUNCTION 'SDIXML_DATA_TO_DOM' + EXPORTING + name = 'item' + dataobject = ls_sys_data + IMPORTING + data_as_dom = li_item + CHANGING + document = template_over_all + EXCEPTIONS + illegal_name = 1 + OTHERS = 2. + ASSERT sy-subrc = 0. + + etpar_node->append_child( li_item ). + + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_ecatt_sp_upload IMPLEMENTATION. + METHOD get_ecatt_sp. + + " downport + + DATA: li_ixml TYPE REF TO if_ixml, + li_section TYPE REF TO if_ixml_element, + li_dom TYPE REF TO if_ixml_document, + li_root TYPE REF TO if_ixml_node, + lv_start_profile TYPE etxml_line_str, + lv_exception_occurred TYPE etonoff, + lo_ecatt_sp TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any. + + TRY. + li_section = template_over_all->find_from_name_ns( 'START_PROFILE' ). + + IF NOT li_section IS INITIAL. + li_ixml = cl_ixml=>create( ). + li_dom = li_ixml->create_document( ). + li_root ?= li_section->clone( ). + li_dom->append_child( li_root ). + CALL FUNCTION 'SDIXML_DOM_TO_XML' + EXPORTING + document = li_dom + IMPORTING + xml_as_string = lv_start_profile. + + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_sp = . + + CALL METHOD lo_ecatt_sp->('SET_SP_ATTRIBUTES') + EXPORTING + i_sp_xml = lv_start_profile. + + ENDIF. + CATCH cx_ecatt_apl. + lv_exception_occurred = 'X'. + ENDTRY. + + IF lv_exception_occurred = 'X'. + raise_upload_exception( previous = exception_to_raise ). + ENDIF. + ENDMETHOD. + METHOD upload. + + " We inherit from CL_APL_ECATT_UPLOAD because CL_APL_ECATT_SP_UPLOAD + " doesn't exist in 702 + + " Downport + + "26.03.2013 + + DATA: lx_ecatt TYPE REF TO cx_ecatt_apl, + lv_exists TYPE etonoff, + lv_exc_occ TYPE etonoff, + ls_tadir TYPE tadir, + lo_ecatt_sp TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any, + TYPE data, + TYPE data. + + TRY. + ch_object-i_devclass = ch_object-d_devclass. + + ASSIGN COMPONENT 'D_AKH' OF STRUCTURE ch_object + TO . " doesn't exist in 702 + ASSIGN COMPONENT 'I_AKH' OF STRUCTURE ch_object + TO . " doesn't exist in 702 + IF IS ASSIGNED AND IS ASSIGNED. + = . + ENDIF. + + super->upload( CHANGING ch_object = ch_object ). + + upload_data_from_stream( ch_object-filename ). + + CATCH cx_ecatt_apl INTO lx_ecatt. + IF template_over_all IS INITIAL. + RAISE EXCEPTION lx_ecatt. + ELSE. + lv_exc_occ = 'X'. + ENDIF. + ENDTRY. + + TRY. + CALL METHOD ('GET_ATTRIBUTES_FROM_DOM_NEW') " doesn't exist in 720 + CHANGING + ch_object = ch_object. + CATCH cx_ecatt_apl INTO lx_ecatt. + lv_exc_occ = 'X'. + ENDTRY. + + ASSIGN ecatt_object TO . + + lo_ecatt_sp = . + + TRY. + get_ecatt_sp( ). + CATCH cx_ecatt_apl INTO lx_ecatt. + lv_exc_occ = 'X'. + ENDTRY. + + TRY. + lv_exists = cl_apl_ecatt_object=>existence_check_object( + im_name = ch_object-d_obj_name + im_version = ch_object-d_obj_ver + im_obj_type = ch_object-s_obj_type + im_exists_any_version = 'X' ). + + IF lv_exists = space. + CALL METHOD lo_ecatt_sp->('SET_TADIR_FOR_NEW_OBJECT') + EXPORTING + im_tadir_for_new_object = tadir_preset. + ENDIF. + CATCH cx_ecatt. + CLEAR lv_exists. + ENDTRY. + + TRY. + CALL METHOD lo_ecatt_sp->('SAVE') + EXPORTING + im_do_commit = 'X'. + CATCH cx_ecatt_apl INTO lx_ecatt. + lv_exc_occ = 'X'. + ENDTRY. + " Releasing enqueue after uploading + TRY. + ecatt_object->close_object( im_suppress_events = 'X' ). + CATCH cx_ecatt_apl INTO lx_ecatt ##NO_HANDLER. + ENDTRY. + +* get devclass from existing object + TRY. + cl_apl_ecatt_object=>get_tadir_entry( + EXPORTING im_obj_name = ch_object-d_obj_name + im_obj_type = ch_object-s_obj_type + IMPORTING ex_tadir = ls_tadir ). + + ch_object-d_devclass = ls_tadir-devclass. + + CATCH cx_ecatt. + CLEAR ls_tadir. + ENDTRY. + IF lv_exc_occ = 'X'. + raise_upload_exception( previous = lx_ecatt ). + ENDIF. + + ENDMETHOD. + METHOD upload_data_from_stream. + + " Downport + template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. + + " downport from CL_APL_ECATT_START_PROFIL SET_STREAM_FOR_UPLOAD + mv_external_xml = iv_xml. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_ecatt_sp_download IMPLEMENTATION. + METHOD download. + + " We inherit from CL_APL_ECATT_DOWNLOAD because CL_APL_ECATT_SP_DOWNLOAD + " doesn't exist in 702 + + " Downport + + load_help = im_load_help. + typ = im_object_type. + + TRY. + cl_apl_ecatt_object=>show_object( + EXPORTING + im_obj_type = im_object_type + im_name = im_object_name + im_version = im_object_version + IMPORTING + re_object = ecatt_object ). + CATCH cx_ecatt INTO ex_ecatt. + RETURN. + ENDTRY. + + set_attributes_to_template( ). + + set_sp_data_to_template( ). + + download_data( ). + + ENDMETHOD. + METHOD download_data. + + " Downport + + mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). + + ENDMETHOD. + METHOD set_sp_data_to_template. + + " downport + + DATA: li_dom TYPE REF TO if_ixml_document, + li_start_profile_data_node TYPE REF TO if_ixml_element, + li_element TYPE REF TO if_ixml_element, + lv_sp_xml TYPE etxml_line_str, + lo_ecatt_sp TYPE REF TO object. + + FIELD-SYMBOLS: TYPE data. + + li_start_profile_data_node = template_over_all->create_simple_element( + name = 'START_PROFILE' + parent = root_node ). + + ASSIGN ('ECATT_OBJECT') TO . + ASSERT sy-subrc = 0. + + lo_ecatt_sp = . + + TRY. + CALL METHOD lo_ecatt_sp->('GET_SP_ATTRIBUTES') + IMPORTING + e_sp_xml = lv_sp_xml. + CATCH cx_ecatt_apl ##NO_HANDLER. + ENDTRY. + + CALL FUNCTION 'SDIXML_XML_TO_DOM' + EXPORTING + xml = lv_sp_xml + IMPORTING + document = li_dom. + + li_element = li_dom->get_root_element( ). + li_start_profile_data_node->append_child( li_element ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_download~get_xml_stream. + + rv_xml_stream = mv_xml_stream. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ECATT_SCRIPT_UPL IMPLEMENTATION. + METHOD upload_data_from_stream. + + " Downport + template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. + + " downport from CL_ABAPGIT_ECATT_DATA_UPLOAD SET_STREAM_FOR_UPLOAD + mv_external_xml = iv_xml. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_ecatt_script_downl IMPLEMENTATION. + METHOD download. + + " Downport + + load_help = im_load_help. + typ = im_object_type. + + TRY. + cl_apl_ecatt_object=>show_object( + EXPORTING + im_obj_type = im_object_type + im_name = im_object_name + im_version = im_object_version + IMPORTING + re_object = ecatt_object ). + CATCH cx_ecatt INTO ex_ecatt. + RETURN. + ENDTRY. + + toolname = ecatt_object->attrib->get_tool_name( ). + set_attributes_to_template( ). + + IF toolname = cl_apl_ecatt_const=>toolname_ecatt. + + ecatt_script ?= ecatt_object. + + set_script_to_template( ). + + TRY. + get_general_params_data( ecatt_script->params ). + CATCH cx_ecatt_apl. "#EC NO_HANDLER +* proceed with download and report errors later + ENDTRY. + + LOOP AT parm INTO wa_parm. + TRY. + IF wa_parm-value = ''. + CLEAR wa_parm-value. + ENDIF. + set_general_params_data_to_dom( ). + IF NOT wa_parm-pstruc_typ IS INITIAL. + set_deep_stru_to_dom( ecatt_script->params ). + set_deep_data_to_dom( ecatt_script->params ). + IF wa_parm-xmlref_typ = cl_apl_ecatt_const=>ref_type_c_tcd. + set_control_data_for_tcd( is_param = wa_parm + io_params = ecatt_script->params ). + + ENDIF. + ENDIF. + CATCH cx_ecatt_apl. "#EC NO_HANDLER +* proceed with download and report errors later + ENDTRY. + ENDLOOP. + + ELSE. + + set_blob_to_template( ). + set_artmp_to_template( ). + + ENDIF. + + download_data( ). + + ENDMETHOD. + METHOD download_data. + + " Downport + + mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). + + ENDMETHOD. + METHOD escape_control_data. + + " Downport + + DATA: li_iter TYPE REF TO if_ixml_node_iterator, + li_textit TYPE REF TO if_ixml_node_iterator, + li_abapctrl TYPE REF TO if_ixml_node_collection, + li_text TYPE REF TO if_ixml_text, + li_filter TYPE REF TO if_ixml_node_filter, + li_list TYPE REF TO if_ixml_node_list, + lv_value TYPE etdom_name, + li_vars TYPE REF TO if_ixml_element, + li_elem TYPE REF TO if_ixml_element. + + li_vars = ii_element->find_from_name_ns( iv_tabname ). + li_filter = ii_element->create_filter_node_type( if_ixml_node=>co_node_text ). + IF li_vars IS NOT INITIAL. + li_abapctrl = ii_element->get_elements_by_tag_name_ns( iv_node ). + +* just for debugging + li_iter = li_abapctrl->create_iterator( ). + li_elem ?= li_iter->get_next( ). + WHILE li_elem IS NOT INITIAL. + li_list = li_elem->get_children( ). + + li_textit = li_list->create_rev_iterator_filtered( li_filter ). + li_text ?= li_textit->get_next( ). + IF li_text IS NOT INITIAL. + lv_value = li_text->get_data( ). + IF lv_value(1) = cl_abap_char_utilities=>minchar. + REPLACE SECTION OFFSET 0 LENGTH 1 OF lv_value WITH space. + li_text->set_value( value = lv_value ). + ENDIF. + ENDIF. + CLEAR: li_textit, li_list, li_elem, lv_value. + li_elem ?= li_iter->get_next( ). + ENDWHILE. + CLEAR: li_abapctrl, li_elem, li_iter. + + ENDIF. + + ENDMETHOD. + METHOD set_artmp_to_template. + + " Downport + + DATA: li_artmp_node TYPE REF TO if_ixml_element, + lv_rc TYPE sy-subrc, + lv_text TYPE string, + lv_rc_args_tmpl TYPE i, + lv_errmsg TYPE string. + + li_artmp_node = template_over_all->create_simple_element( + name = 'ECET_ARTMP' + parent = root_node ). + + ecatt_extprog->get_args_tmpl( + IMPORTING + ex_xml_arg_tmpl = lv_text + ex_rc = lv_rc_args_tmpl + ex_errmsg = lv_errmsg ). + + IF li_artmp_node IS INITIAL OR lv_rc_args_tmpl > 0. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt + called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_ARTMP_TO_TEMPLATE' + free_text = lv_errmsg ). + ENDIF. + + lv_rc = li_artmp_node->set_value( lv_text ). + IF lv_rc <> 0. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt + called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_ARTMP_TO_TEMPLATE' ). + ENDIF. + + ENDMETHOD. + METHOD set_blob_to_template. + + " Downport + + DATA: li_blob_node TYPE REF TO if_ixml_element, + lv_rc TYPE sy-subrc, + lv_text TYPE string. + + li_blob_node = template_over_all->create_simple_element( + name = 'ECET_BLOBS' + parent = root_node ). + + IF li_blob_node IS INITIAL. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt + called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_BLOB_TO_TEMPLATE' ). + ENDIF. + + ecatt_extprog->get_blob( + EXPORTING + im_whole_data = 1 + IMPORTING + ex_xml_blob = lv_text ). + + lv_rc = li_blob_node->set_value( lv_text ). + IF lv_rc <> 0. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt + called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_BLOB_TO_TEMPLATE' ). + ENDIF. + + ENDMETHOD. + METHOD set_control_data_for_tcd. + + " Downport + + DATA: lt_params TYPE ettcd_params_tabtype, + lt_verbs TYPE ettcd_verbs_tabtype, + lt_vars TYPE ettcd_vars_tabtype, + lt_dp_tab TYPE ettcd_dp_tab_tabtype, + lt_dp_for TYPE ettcd_dp_for_tabtype, + lt_dp_pro TYPE ettcd_dp_pro_tabtype, + lt_dp_fld TYPE ettcd_dp_fld_tabtype, + lt_svars TYPE ettcd_svars_tabtype. + + DATA: li_element TYPE REF TO if_ixml_element, + li_deep_tcd TYPE REF TO if_ixml_element, + lv_rc TYPE sy-subrc, + lv_name TYPE string, + lv_parname TYPE string, + lo_pval_xml TYPE REF TO cl_apl_ecatt_xml_data, + lo_ctrl_tabs TYPE REF TO cl_apl_ecatt_control_tables. + + FIELD-SYMBOLS: TYPE STANDARD TABLE. + + IF is_param-xmlref_typ <> cl_apl_ecatt_const=>ref_type_c_tcd OR io_params IS INITIAL. + RETURN. + ENDIF. + + lv_parname = is_param-pname. + + io_params->get_param_value( "TCD command interface + EXPORTING + im_var_id = cl_apl_ecatt_const=>varid_default_val + im_pname = lv_parname + im_pindex = is_param-pindex + IMPORTING + ex_pval_xml = lo_pval_xml ). + + lo_ctrl_tabs = lo_pval_xml->get_control_tables_ref( ). + IF lo_ctrl_tabs IS INITIAL. + RETURN. + ENDIF. + + lo_ctrl_tabs->get_control_tables( "Read 8 control tables + IMPORTING + ex_params = lt_params + ex_verbs = lt_verbs + ex_vars = lt_vars + ex_dp_tab = lt_dp_tab + ex_dp_for = lt_dp_for + ex_dp_pro = lt_dp_pro + ex_dp_fld = lt_dp_fld + ex_svars = lt_svars ). + + IF lt_params IS INITIAL OR + lt_verbs IS INITIAL OR + lt_vars IS INITIAL OR + lt_dp_tab IS INITIAL OR + lt_dp_for IS INITIAL OR + lt_dp_pro IS INITIAL OR + lt_dp_fld IS INITIAL OR + lt_svars IS INITIAL. + + RETURN. + ENDIF. + + li_deep_tcd = template_over_all->create_simple_element_ns( + name = cl_apl_xml_const=>upl_tcd_node + parent = ap_current_param ). + + IF li_deep_tcd IS INITIAL. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt ). + ENDIF. + + DO 8 TIMES. "Loop at 8 control tables + CASE sy-index. + WHEN 1. + lv_name = 'ETTCD_PARAMS_TABTYPE'. + ASSIGN lt_params TO . + WHEN 2. + lv_name = 'ETTCD_VERBS_TABTYPE'. + ASSIGN lt_verbs TO . + WHEN 3. + lv_name = 'ETTCD_VARS_TABTYPE'. + ASSIGN lt_vars TO . + WHEN 4. + lv_name = 'ETTCD_DP_TAB_TABTYPE'. + ASSIGN lt_dp_tab TO . + WHEN 5. + lv_name = 'ETTCD_DP_FOR_TABTYPE'. + ASSIGN lt_dp_for TO . + WHEN 6. + lv_name = 'ETTCD_DP_PRO_TABTYPE'. + ASSIGN lt_dp_pro TO . + WHEN 7. + lv_name = 'ETTCD_DP_FLD_TABTYPE'. + ASSIGN lt_dp_fld TO . + WHEN 8. + lv_name = 'ETTCD_SVARS_TABTYPE'. + ASSIGN lt_svars TO . + ENDCASE. + + CALL FUNCTION 'SDIXML_DATA_TO_DOM' "Generate branch + EXPORTING + name = lv_name + dataobject = + IMPORTING + data_as_dom = li_element + EXCEPTIONS + illegal_name = 1 + OTHERS = 2. + + IF sy-subrc <> 0. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt ). + ENDIF. + +* Hang a branch in the main tree + lv_rc = li_deep_tcd->append_child( li_element ). + + IF lv_rc <> 0. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt ). + ENDIF. + FREE li_element. + UNASSIGN . + ENDDO. + + escape_control_data( ii_element = li_deep_tcd + iv_tabname = 'ETTCD_VARS_TABTYPE' + iv_node = 'CB_INDEX' ). + + escape_control_data( + ii_element = li_deep_tcd + iv_tabname = 'ETTCD_VERBS_TABTYPE' + iv_node = 'NAME' ). + + FREE: lt_dp_tab, lt_dp_for, lt_dp_fld, lt_svars, + lt_params, lt_vars, lt_dp_pro, lt_verbs. + + ENDMETHOD. + METHOD set_script_to_template. + + " Downport + + DATA: + lt_text TYPE etxml_line_tabtype, + li_element TYPE REF TO if_ixml_element, + lv_rc TYPE sy-subrc. + + ecatt_script->get_script_text( CHANGING scripttext = lt_text ). + + mi_script_node = template_over_all->create_simple_element( + name = 'SCRIPT' + parent = root_node ). + + IF mi_script_node IS INITIAL. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt + called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_SCRIPT_TO_TEMPLATE' ). + ENDIF. + + CALL FUNCTION 'SDIXML_DATA_TO_DOM' + EXPORTING + name = 'ETXML_LINE_TABTYPE' + dataobject = lt_text + IMPORTING + data_as_dom = li_element + CHANGING + document = template_over_all + EXCEPTIONS + illegal_name = 1 + OTHERS = 2. + IF sy-subrc <> 0. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt + called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_SCRIPT_TO_TEMPLATE' ). + + ENDIF. + + lv_rc = mi_script_node->append_child( li_element ). + IF lv_rc <> 0. + raise_download_exception( + textid = cx_ecatt_apl_util=>download_processing + previous = ex_ecatt + called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_SCRIPT_TO_TEMPLATE' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ecatt_download~get_xml_stream. + + rv_xml_stream = mv_xml_stream. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_ecatt_helper IMPLEMENTATION. + METHOD build_xml_of_object. + + " downport of CL_APL_ECATT_DOWNLOAD=>BUILD_XML_OF_OBJECT + + DATA: lo_load_help_dummy TYPE REF TO cl_apl_ecatt_load_help, + lx_ecatt TYPE REF TO cx_ecatt_apl, + lv_text TYPE string, + li_download TYPE REF TO zif_abapgit_ecatt_download. + + "download method will create the xml stream + "note: it's the redefined download( ) of each object type specific download, which is called + TRY. + CREATE OBJECT lo_load_help_dummy + EXPORTING + im_maintain_function = ''. + + io_download->download( im_object_name = iv_object_name + im_object_version = iv_object_version + im_object_type = iv_object_type + im_load_help = lo_load_help_dummy ). + + CATCH cx_ecatt_apl INTO lx_ecatt. + lv_text = lx_ecatt->get_text( ). + zcx_abapgit_exception=>raise( lv_text ). + " note, exception cx_ecatt_ui_attachment doesn't exist in 702 + CATCH cx_ecatt ##NO_HANDLER. + "will never be raised from download, when called with mv_generate_xml_no_download = 'X'. + ENDTRY. + + li_download ?= io_download. + + rv_xml_stream = li_download->get_xml_stream( ). + + ENDMETHOD. + METHOD download_data. + + DATA: + lo_xml TYPE REF TO cl_apl_ecatt_xml. + + TRY. + CALL METHOD cl_apl_ecatt_xml=>('CREATE') " doesn't exist in 702 + EXPORTING + im_type = c_xml + RECEIVING + re_xml = lo_xml. + + lo_xml->set_attributes( im_dom = ii_template_over_all ). + + lo_xml->get_attributes( IMPORTING ex_xml = rv_xml_stream ). + + CATCH cx_ecatt_apl_xml. + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD upload_data_from_stream. + + DATA: + lo_xml TYPE REF TO cl_apl_ecatt_xml, + lv_xstr TYPE xstring, + li_nc_xmlref_typ TYPE REF TO if_ixml_node_collection, + li_n_xmlref_typ TYPE REF TO if_ixml_node, + lv_index TYPE i VALUE 0, + lv_count TYPE i. + + lv_xstr = iv_xml_stream. + + CALL METHOD cl_apl_ecatt_xml=>('CREATE') " doesn't exist in 702 + EXPORTING + im_type = c_xml + RECEIVING + re_xml = lo_xml. + +* whitespace stripping needs a namespace +* remove white spaces only at the time of upload + lo_xml->stream_to_dom( im_xstream = lv_xstr + im_ignore_white_space = 'X' + im_uri = cl_apl_xml_const=>schema_uri ). + + lo_xml->get_attributes( IMPORTING ex_dom = ri_template_over_all ). + +* MD: Workaround, because nodes starting with "XML" are not allowed + li_nc_xmlref_typ ?= ri_template_over_all->get_elements_by_tag_name_ns( 'XMLREF_TYP' ). + CALL METHOD li_nc_xmlref_typ->('GET_LENGTH') " downport + RECEIVING + rval = lv_count. + + WHILE lv_index < lv_count. + li_n_xmlref_typ = li_nc_xmlref_typ->get_item( lv_index ). + li_n_xmlref_typ->set_name( 'X-MLREF_TYP' ). + lv_index = lv_index + 1. + ENDWHILE. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_ecatt_data_upload IMPLEMENTATION. + METHOD upload. + SET HANDLER on_ev_object_saved FOR ALL INSTANCES. + + ms_current_object-s_obj_type = ch_object-s_obj_type. + ms_current_object-d_obj_name = ch_object-d_obj_name. + ms_current_object-d_obj_ver = ch_object-d_obj_ver. + + TRY. + super->upload( CHANGING ch_object = ch_object ). + SET HANDLER on_ev_object_saved FOR ALL INSTANCES ACTIVATION abap_false. + CLEANUP. + SET HANDLER on_ev_object_saved FOR ALL INSTANCES ACTIVATION abap_false. + ENDTRY. + + IF mx_ecatt_apl IS BOUND. + raise_upload_exception( previous = mx_ecatt_apl ). + ENDIF. + ENDMETHOD. + METHOD upload_data_from_stream. + + " Downport + template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. + + " downport from CL_ABAPGIT_ECATT_DATA_UPLOAD SET_STREAM_FOR_UPLOAD + mv_external_xml = iv_xml. + + ENDMETHOD. + METHOD on_ev_object_saved. + DATA lo_ecatt_td TYPE REF TO cl_apl_ecatt_test_data. + + " Trickery to remove any local variants that do not exist on the remote on pull. + + SET HANDLER on_ev_object_saved FOR ALL INSTANCES ACTIVATION abap_false. + + TRY. + IF ex_ecatt_object->object_type <> ms_current_object-s_obj_type OR + ex_ecatt_object->object_name <> ms_current_object-d_obj_name OR + ex_ecatt_object->object_version <> ms_current_object-d_obj_ver. + CREATE OBJECT mx_ecatt_apl + EXPORTING + textid = cx_ecatt_apl=>any_text + free_text = 'Unexpected object in save sequence'. + RETURN. + ENDIF. + + lo_ecatt_td ?= ex_ecatt_object. + lo_ecatt_td->params->delete_variants( '*' ). + TRY. + CALL METHOD ('GET_VARIANTS_FROM_DOM_NEW') + EXPORTING + im_params = lo_ecatt_td->params. + CATCH cx_sy_dyn_call_error. + get_variants_from_dom( lo_ecatt_td->params ). + ENDTRY. + lo_ecatt_td->save( ). + CATCH cx_ecatt_apl INTO mx_ecatt_apl. + RETURN. + ENDTRY. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ECATT_DATA_DOWNL IMPLEMENTATION. + METHOD download. + + " Downport + + DATA: lv_partyp TYPE string. + + load_help = im_load_help. + + TRY. + cl_apl_ecatt_object=>show_object( + EXPORTING + im_obj_type = im_object_type + im_name = im_object_name + im_version = im_object_version + IMPORTING + re_object = ecatt_object ). + CATCH cx_ecatt INTO ex_ecatt. + RETURN. + ENDTRY. + + typ = im_object_type. + + lv_partyp = cl_apl_ecatt_const=>params_type_par. + + ecatt_data ?= ecatt_object. + set_attributes_to_template( ). + get_general_params_data( im_params = ecatt_data->params + im_ptyp = lv_partyp ). + + LOOP AT parm INTO wa_parm. + set_general_params_data_to_dom( ). + IF NOT wa_parm-val_type IS INITIAL. + set_deep_stru_to_dom( ecatt_data->params ). + set_deep_data_to_dom( im_params = ecatt_data->params + im_pindex = wa_parm-pindex ). + ENDIF. + ENDLOOP. + +* MS180406 + set_var_mode_to_dom( ). +* ENDMS180406 + set_variants_to_dom( ecatt_data->params ). + + download_data( ). + + ENDMETHOD. + METHOD download_data. + + " Downport + + mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_download~get_xml_stream. + + rv_xml_stream = mv_xml_stream. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ECATT_CONFIG_UPL IMPLEMENTATION. + METHOD upload_data_from_stream. + + " Downport + template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. + + " downport from CL_ABAPGIT_ECATT_DATA_UPLOAD SET_STREAM_FOR_UPLOAD + mv_external_xml = iv_xml. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ECATT_CONFIG_DOWNL IMPLEMENTATION. + METHOD download. + + " Downport + + DATA: lv_partyp TYPE string. + + load_help = im_load_help. + typ = im_object_type. + + TRY. + cl_apl_ecatt_object=>show_object( + EXPORTING + im_obj_type = im_object_type + im_name = im_object_name + im_version = im_object_version + IMPORTING + re_object = ecatt_object ). + CATCH cx_ecatt INTO ex_ecatt. + RETURN. + ENDTRY. + + lv_partyp = cl_apl_ecatt_const=>params_type_par. + + set_attributes_to_template( ). + ecatt_config ?= ecatt_object. + + CALL METHOD ('SET_ECATT_OBJECTS_TO_TEMPLATE'). " doesn't exist in 702 + +* MS180406 + set_var_mode_to_dom( ). +* ENDMS180406 + get_general_params_data( im_params = ecatt_config->params + im_ptyp = lv_partyp ). + LOOP AT parm INTO wa_parm. + set_general_params_data_to_dom( ). + IF NOT wa_parm-val_type IS INITIAL. + set_deep_stru_to_dom( ecatt_config->params ). + set_deep_data_to_dom( im_params = ecatt_config->params + im_pindex = wa_parm-pindex ). + ENDIF. + ENDLOOP. + + set_variants_to_dom( ecatt_config->params ). + + download_data( ). + + ENDMETHOD. + METHOD download_data. + + " Downport + + mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). + + ENDMETHOD. + METHOD zif_abapgit_ecatt_download~get_xml_stream. + + rv_xml_stream = mv_xml_stream. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_tadir IMPLEMENTATION. + METHOD add_local_packages. + + FIELD-SYMBOLS: + LIKE LINE OF it_packages, + LIKE LINE OF ct_tadir. + + LOOP AT it_packages ASSIGNING . + + " Local packages are not in TADIR, only in TDEVC, act as if they were + IF CP '$*'. " OR CP 'T*' ). + APPEND INITIAL LINE TO ct_tadir ASSIGNING . + -pgmid = 'R3TR'. + -object = 'DEVC'. + -obj_name = . + -devclass = . + -srcsystem = sy-sysid. + -masterlang = sy-langu. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD add_namespace. + + DATA ls_tadir TYPE zif_abapgit_definitions=>ty_tadir. + DATA ls_obj_with_namespace TYPE zif_abapgit_definitions=>ty_obj_namespace. + + TRY. + ls_obj_with_namespace = zcl_abapgit_factory=>get_sap_namespace( )->split_by_name( iv_object ). + CATCH zcx_abapgit_exception. + "Ignore the exception like before the replacement of the FM RS_NAME_SPLIT_NAMESPACE + RETURN. + ENDTRY. + + IF ls_obj_with_namespace-namespace IS NOT INITIAL. + + READ TABLE ct_tadir_nspc TRANSPORTING NO FIELDS + WITH KEY pgmid = 'R3TR' object = 'NSPC' obj_name = ls_obj_with_namespace-namespace. + IF sy-subrc <> 0. + ls_tadir-pgmid = 'R3TR'. + ls_tadir-object = 'NSPC'. + ls_tadir-obj_name = ls_obj_with_namespace-namespace. + ls_tadir-devclass = iv_package. + ls_tadir-srcsystem = sy-sysid. + ls_tadir-masterlang = sy-langu. + INSERT ls_tadir INTO TABLE ct_tadir. + INSERT ls_tadir INTO TABLE ct_tadir_nspc. + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD add_namespaces. + + DATA lt_tadir_nspc TYPE zif_abapgit_definitions=>ty_tadir_tt. + + FIELD-SYMBOLS LIKE LINE OF ct_tadir. + + " Namespaces are not in TADIR, but are necessary for creating objects in transportable packages + LOOP AT ct_tadir ASSIGNING WHERE obj_name(1) = '/'. + add_namespace( + EXPORTING + iv_package = iv_package + iv_object = -obj_name + CHANGING + ct_tadir = ct_tadir + ct_tadir_nspc = lt_tadir_nspc ). + ENDLOOP. + + " Root package of repo might not exist yet but needs to be considered, too + IF iv_package CP '/*'. + add_namespace( + EXPORTING + iv_package = iv_package + iv_object = iv_package + CHANGING + ct_tadir = ct_tadir + ct_tadir_nspc = lt_tadir_nspc ). + ENDIF. + + ENDMETHOD. + METHOD build. + + DATA lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. + + select_objects( + EXPORTING + iv_package = iv_package + iv_ignore_subpackages = iv_ignore_subpackages + iv_only_local_objects = iv_only_local_objects + IMPORTING + et_tadir = rt_tadir + et_packages = lt_packages ). + + add_local_packages( + EXPORTING + it_packages = lt_packages + CHANGING + ct_tadir = rt_tadir ). + + add_namespaces( + EXPORTING + iv_package = iv_package + CHANGING + ct_tadir = rt_tadir ). + + determine_path( + EXPORTING + iv_package = iv_package + io_dot = io_dot + CHANGING + ct_tadir = rt_tadir ). + + ENDMETHOD. + METHOD check_exists. + + DATA: li_progress TYPE REF TO zif_abapgit_progress, + ls_item TYPE zif_abapgit_definitions=>ty_item. + + FIELD-SYMBOLS: LIKE LINE OF it_tadir. + li_progress = zcl_abapgit_progress=>get_instance( lines( it_tadir ) ). + +* rows from database table TADIR are not removed for +* transportable objects until the transport is released + LOOP AT it_tadir ASSIGNING . + IF sy-tabix MOD 200 = 0. + li_progress->show( + iv_current = sy-tabix + iv_text = |Check object exists { -object } { -obj_name }| ). + ENDIF. + + ls_item-obj_type = -object. + ls_item-obj_name = -obj_name. + ls_item-devclass = -devclass. + + IF zcl_abapgit_objects=>exists( ls_item ) = abap_true. + APPEND TO rt_tadir. + ENDIF. + ENDLOOP. + + li_progress->off( ). + + ENDMETHOD. + METHOD determine_path. + + DATA: + lv_path TYPE string, + lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic, + lv_last_package TYPE devclass VALUE cl_abap_char_utilities=>horizontal_tab. + + FIELD-SYMBOLS LIKE LINE OF ct_tadir. + + lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). + + LOOP AT ct_tadir ASSIGNING . + + IF lv_last_package <> -devclass. + "Change in Package + lv_last_package = -devclass. + + IF NOT io_dot IS INITIAL. + lv_path = lo_folder_logic->package_to_path( + iv_top = iv_package + io_dot = io_dot + iv_package = -devclass ). + ENDIF. + ENDIF. + + -path = lv_path. + -korrnum = ''. + ENDLOOP. + + ENDMETHOD. + METHOD select_objects. + + DATA: + lt_excludes TYPE RANGE OF trobjtype, + ls_exclude LIKE LINE OF lt_excludes, + lt_srcsystem TYPE RANGE OF tadir-srcsystem, + ls_srcsystem LIKE LINE OF lt_srcsystem. + + " Determine packages to read + IF iv_ignore_subpackages = abap_false. + et_packages = zcl_abapgit_factory=>get_sap_package( iv_package )->list_subpackages( ). + ENDIF. + INSERT iv_package INTO et_packages INDEX 1. + + " Exclude object types with tadir entries that are included elsewhere + ls_exclude-sign = 'I'. + ls_exclude-option = 'EQ'. + ls_exclude-low = 'SOTR'. " automatically created for SAP packages (DEVC) + APPEND ls_exclude TO lt_excludes. + ls_exclude-low = 'SOTS'. " automatically created for SAP packages (DEVC) + APPEND ls_exclude TO lt_excludes. + ls_exclude-low = 'SFB1'. " covered by business function sets (SFBS) + APPEND ls_exclude TO lt_excludes. + ls_exclude-low = 'SFB2'. " covered by business functions (SFBF) + APPEND ls_exclude TO lt_excludes. + ls_exclude-low = 'STOB'. " auto generated by core data services (DDLS) + APPEND ls_exclude TO lt_excludes. + + " Limit to objects belonging to this system + IF iv_only_local_objects = abap_true. + ls_srcsystem-sign = 'I'. + ls_srcsystem-option = 'EQ'. + ls_srcsystem-low = sy-sysid. + APPEND ls_srcsystem TO lt_srcsystem. + ENDIF. + + IF et_packages IS NOT INITIAL. + SELECT * FROM tadir INTO CORRESPONDING FIELDS OF TABLE et_tadir + FOR ALL ENTRIES IN et_packages + WHERE devclass = et_packages-table_line + AND pgmid = 'R3TR' + AND object NOT IN lt_excludes + AND delflag = abap_false + AND srcsystem IN lt_srcsystem + ORDER BY PRIMARY KEY ##TOO_MANY_ITAB_FIELDS. "#EC CI_GENBUFF "#EC CI_SUBRC + ENDIF. + + SORT et_tadir BY devclass pgmid object obj_name. + + ENDMETHOD. + METHOD zif_abapgit_tadir~delete_single. + + DATA ls_tadir TYPE tadir. + + " cast + ls_tadir-pgmid = iv_pgmid. + ls_tadir-object = iv_object. + ls_tadir-obj_name = iv_obj_name. + + CALL FUNCTION 'TR_TADIR_INTERFACE' + EXPORTING + wi_delete_tadir_entry = abap_true + wi_tadir_pgmid = ls_tadir-pgmid + wi_tadir_object = ls_tadir-object + wi_tadir_obj_name = ls_tadir-obj_name + wi_test_modus = abap_false + EXCEPTIONS + tadir_entry_not_existing = 1 + tadir_entry_ill_type = 2 + no_systemname = 3 + no_systemtype = 4 + original_system_conflict = 5 + object_reserved_for_devclass = 6 + object_exists_global = 7 + object_exists_local = 8 + object_is_distributed = 9 + obj_specification_not_unique = 10 + no_authorization_to_delete = 11 + devclass_not_existing = 12 + simultanious_set_remove_repair = 13 + order_missing = 14 + no_modification_of_head_syst = 15 + pgmid_object_not_allowed = 16 + masterlanguage_not_specified = 17 + devclass_not_specified = 18 + specify_owner_unique = 19 + loc_priv_objs_no_repair = 20 + gtadir_not_reached = 21 + object_locked_for_order = 22 + change_of_class_not_allowed = 23 + no_change_from_sap_to_tmp = 24 + OTHERS = 25. + IF sy-subrc > 1. + " No error if entry does not exist + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_tadir~get_object_package. + + DATA: ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, + ls_item TYPE zif_abapgit_definitions=>ty_item. + + ls_tadir = zif_abapgit_tadir~read_single( + iv_pgmid = iv_pgmid + iv_object = iv_object + iv_obj_name = iv_obj_name ). + + IF ls_tadir-delflag = abap_true. + RETURN. "Mark for deletion -> return nothing + ENDIF. + + ls_item-obj_type = ls_tadir-object. + ls_item-obj_name = ls_tadir-obj_name. + ls_item-devclass = ls_tadir-devclass. + + IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. + RETURN. + ENDIF. + + rv_devclass = ls_tadir-devclass. + + ENDMETHOD. + METHOD zif_abapgit_tadir~insert_single. + + DATA ls_tadir TYPE tadir. + + " cast + ls_tadir-pgmid = iv_pgmid. + ls_tadir-object = iv_object. + ls_tadir-obj_name = iv_obj_name. + ls_tadir-devclass = iv_package. + + CALL FUNCTION 'TR_TADIR_INTERFACE' + EXPORTING + wi_test_modus = abap_false + wi_tadir_pgmid = ls_tadir-pgmid + wi_tadir_object = ls_tadir-object + wi_tadir_obj_name = ls_tadir-obj_name + wi_tadir_author = sy-uname + wi_tadir_devclass = ls_tadir-devclass + wi_tadir_masterlang = iv_language + wi_tadir_srcsystem = iv_srcsystem + wi_set_genflag = iv_set_genflag + iv_set_edtflag = iv_set_edtflag + EXCEPTIONS + tadir_entry_not_existing = 1 + tadir_entry_ill_type = 2 + no_systemname = 3 + no_systemtype = 4 + original_system_conflict = 5 + object_reserved_for_devclass = 6 + object_exists_global = 7 + object_exists_local = 8 + object_is_distributed = 9 + obj_specification_not_unique = 10 + no_authorization_to_delete = 11 + devclass_not_existing = 12 + simultanious_set_remove_repair = 13 + order_missing = 14 + no_modification_of_head_syst = 15 + pgmid_object_not_allowed = 16 + masterlanguage_not_specified = 17 + devclass_not_specified = 18 + specify_owner_unique = 19 + loc_priv_objs_no_repair = 20 + gtadir_not_reached = 21 + object_locked_for_order = 22 + change_of_class_not_allowed = 23 + no_change_from_sap_to_tmp = 24 + OTHERS = 25. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_tadir~read. + + DATA li_exit TYPE REF TO zif_abapgit_exit. + DATA lr_tadir TYPE REF TO zif_abapgit_definitions=>ty_tadir. + DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA ls_dot_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit. + + ASSERT iv_package IS NOT INITIAL. + + " Start recursion + " hmm, some problems here, should TADIR also build path? + rt_tadir = build( + iv_package = iv_package + io_dot = io_dot + iv_ignore_subpackages = iv_ignore_subpackages + iv_only_local_objects = iv_only_local_objects ). + + IF io_dot IS NOT INITIAL. + ls_dot_data = io_dot->get_data( ). + ENDIF. + + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->change_tadir( + EXPORTING + iv_package = iv_package + ii_log = ii_log + is_dot_abapgit = ls_dot_data + iv_ignore_subpackages = iv_ignore_subpackages + iv_only_local_objects = iv_only_local_objects + CHANGING + ct_tadir = rt_tadir ). + + IF it_filter IS NOT INITIAL. + "Apply filter manually instead of calling zcl_abapgit_repo_filter->apply, + "so that we can execute a unit test. The method applies addition filtering + "and does therefore additional selects + lt_filter = it_filter. + SORT lt_filter BY object obj_name. + LOOP AT rt_tadir REFERENCE INTO lr_tadir. + READ TABLE lt_filter TRANSPORTING NO FIELDS + WITH KEY object = lr_tadir->object + obj_name = lr_tadir->obj_name + BINARY SEARCH. + IF sy-subrc <> 0. + DELETE rt_tadir. + ENDIF. + ENDLOOP. + ENDIF. + + IF iv_check_exists = abap_true. + rt_tadir = check_exists( rt_tadir ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_tadir~read_single. + + SELECT SINGLE * FROM tadir INTO CORRESPONDING FIELDS OF rs_tadir + WHERE pgmid = iv_pgmid + AND object = iv_object + AND obj_name = iv_obj_name. "#EC CI_SUBRC + CLEAR rs_tadir-korrnum. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_SERIALIZE IMPLEMENTATION. + METHOD add_apack. + + DATA ls_apack_file TYPE zif_abapgit_git_definitions=>ty_file. + + FIELD-SYMBOLS LIKE LINE OF ct_files. + ls_apack_file = zcl_abapgit_apack_helper=>to_file( iv_package ). + IF ls_apack_file IS NOT INITIAL. + APPEND INITIAL LINE TO ct_files ASSIGNING . + -file = ls_apack_file. + ENDIF. + + ENDMETHOD. + METHOD add_data. + + DATA lt_files TYPE zif_abapgit_git_definitions=>ty_files_tt. + DATA ls_file LIKE LINE OF lt_files. + + FIELD-SYMBOLS LIKE LINE OF ct_files. + + IF ii_data_config IS INITIAL. + RETURN. + ENDIF. + + lt_files = ii_data_config->to_json( ). + LOOP AT lt_files INTO ls_file. + APPEND INITIAL LINE TO ct_files ASSIGNING . + -file = ls_file. + + " Derive object from config filename (namespace + escaping) + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = -file-filename + iv_path = -file-path + io_dot = mo_dot_abapgit + IMPORTING + es_item = -item ). + + -item-obj_type = zif_abapgit_data_config=>c_data_type-tabu. " todo + ENDLOOP. + + lt_files = zcl_abapgit_data_factory=>get_serializer( )->serialize( ii_data_config ). + LOOP AT lt_files INTO ls_file. + APPEND INITIAL LINE TO ct_files ASSIGNING . + -file = ls_file. + + " Derive object from data filename (namespace + escaping) + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = -file-filename + iv_path = -file-path + io_dot = mo_dot_abapgit + IMPORTING + es_item = -item ). + ENDLOOP. + + ENDMETHOD. + METHOD add_dot_abapgit. + + FIELD-SYMBOLS: LIKE LINE OF ct_files. + + APPEND INITIAL LINE TO ct_files ASSIGNING . + -file = mo_dot_abapgit->to_file( ). + + ENDMETHOD. + METHOD add_objects. + + DATA: lo_filter TYPE REF TO zcl_abapgit_repo_filter, + lv_force TYPE abap_bool, + lt_found LIKE ct_files, + lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + + lt_tadir = zcl_abapgit_factory=>get_tadir( )->read( + iv_package = iv_package + iv_ignore_subpackages = ms_local_settings-ignore_subpackages + iv_only_local_objects = ms_local_settings-only_local_objects + io_dot = mo_dot_abapgit + ii_log = ii_log + it_filter = it_filter ). + + CREATE OBJECT lo_filter. + + lo_filter->apply( EXPORTING it_filter = it_filter + CHANGING ct_tadir = lt_tadir ). + +* if there are less than 10 objects run in single thread +* this helps a lot when debugging, plus performance gain +* with low number of objects does not matter much + lv_force = boolc( lines( lt_tadir ) < 10 ). + + lt_found = serialize( + iv_package = iv_package + it_tadir = lt_tadir + ii_log = ii_log + iv_force_sequential = lv_force ). + APPEND LINES OF lt_found TO ct_files. + + ENDMETHOD. + METHOD add_to_return. + + FIELD-SYMBOLS: LIKE LINE OF is_file_item-files, + LIKE LINE OF mt_files. + LOOP AT is_file_item-files ASSIGNING . + APPEND INITIAL LINE TO mt_files ASSIGNING . + -file = . + -file-path = iv_path. + -item = is_file_item-item. + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + + mv_group = determine_rfc_server_group( ). + + mo_dot_abapgit = io_dot_abapgit. + ms_local_settings = is_local_settings. + + IF io_dot_abapgit IS BOUND. + ms_i18n_params = io_dot_abapgit->determine_i18n_parameters( is_local_settings-main_language_only ). + mt_wo_translation_patterns = + zcl_abapgit_i18n_params=>normalize_obj_patterns( io_dot_abapgit->get_objs_without_translation( ) ). + ELSE. + ms_i18n_params-main_language = sy-langu. + ms_i18n_params-main_language_only = is_local_settings-main_language_only. + ENDIF. + ms_i18n_params-suppress_po_comments = is_local_settings-suppress_lxe_po_comments. + + IF mo_dot_abapgit IS NOT INITIAL. + CREATE OBJECT mo_abap_language_version + EXPORTING + io_dot_abapgit = mo_dot_abapgit. + ENDIF. + + ENDMETHOD. + METHOD determine_max_processes. + DATA: li_exit TYPE REF TO zif_abapgit_exit. + DATA lv_available_sessions TYPE i. + + IF iv_force_sequential = abap_true. + rv_processes = 1. + RETURN. + ENDIF. + + IF gv_max_processes IS INITIAL AND is_parallelization_possible( ) = abap_true. + + gv_max_processes = zcl_abapgit_factory=>get_environment( )->init_parallel_processing( mv_group ). + + IF gv_max_processes > 1. + gv_max_processes = gv_max_processes - 1. + ENDIF. + + IF gv_max_processes > 32. + " https://en.wikipedia.org/wiki/Amdahl%27s_law + gv_max_processes = 32. + ENDIF. + + ENDIF. + + IF gv_max_processes IS INITIAL. + " fallback to running sequentially. + gv_max_processes = 1. + ENDIF. + + rv_processes = gv_max_processes. + + ASSERT rv_processes >= 1. + + " Avoid going over the maximum available user sessions + IF sy-batch IS INITIAL. + lv_available_sessions = zcl_abapgit_factory=>get_environment( )->get_available_user_sessions( ). + + IF lv_available_sessions = 0. + " No available session -> disable parallel processing + rv_processes = 1. + ELSEIF rv_processes > lv_available_sessions. + rv_processes = lv_available_sessions. + ENDIF. + ENDIF. + + ASSERT rv_processes >= 1. + + " Exit setting has highest priority to change maximum sessions + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->change_max_parallel_processes( + EXPORTING + iv_package = iv_package + CHANGING + cv_max_processes = rv_processes ). + + ASSERT rv_processes >= 1. + + ENDMETHOD. + METHOD determine_rfc_server_group. + + DATA: + li_exit TYPE REF TO zif_abapgit_exit, + lv_exists TYPE abap_bool. + + " According to SAP Note 3215918 it's recommended NOT to use this group anymore. + " However, we keep it for compatibility. If it does not exist, we switch to the + " recommended DEFAULT behaviour. + rv_group = 'parallel_generators'. + + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->change_rfc_server_group( CHANGING cv_group = rv_group ). + + " Check if RFC server group exists and fallback to the default + lv_exists = zcl_abapgit_factory=>get_environment( )->check_parallel_processing( rv_group ). + IF lv_exists = abap_false. + rv_group = ''. + ENDIF. + + ENDMETHOD. + METHOD files_local. + +* serializes objects, including .abapgit.xml, apack, and takes into account local settings + + add_dot_abapgit( CHANGING ct_files = rt_files ). + + add_apack( + EXPORTING + iv_package = iv_package + CHANGING + ct_files = rt_files ). + + add_data( + EXPORTING + ii_data_config = ii_data_config + CHANGING + ct_files = rt_files ). + + add_objects( + EXPORTING + iv_package = iv_package + ii_log = ii_log + it_filter = it_filter + CHANGING + ct_files = rt_files ). + + ENDMETHOD. + METHOD filter_ignored_objects. + + DATA: + ls_ignored_count TYPE ty_unsupported_count, + lt_ignored_count TYPE ty_unsupported_count_tt, + lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic, + ls_item TYPE zif_abapgit_definitions=>ty_item, + lv_path TYPE string, + lv_filename TYPE string. + + FIELD-SYMBOLS: + LIKE LINE OF ct_tadir, + TYPE ty_unsupported_count. + + " Ignore logic requires .abapGit.xml + IF mo_dot_abapgit IS INITIAL OR iv_package IS INITIAL OR mi_log IS INITIAL. + RETURN. + ENDIF. + + lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). + + LOOP AT ct_tadir ASSIGNING . + CLEAR: ls_ignored_count. + + ls_item-obj_type = -object. + ls_item-obj_name = -obj_name. + + IF -devclass IS NOT INITIAL. + lv_path = lo_folder_logic->package_to_path( + iv_top = iv_package + io_dot = mo_dot_abapgit + iv_package = -devclass ). + ELSE. + lv_path = mo_dot_abapgit->get_starting_folder( ). + ENDIF. + + lv_filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ls_item + iv_ext = '*' ). + + IF mo_dot_abapgit->is_ignored( + iv_path = lv_path + iv_filename = lv_filename ) = abap_false. + CONTINUE. + ENDIF. + + READ TABLE lt_ignored_count ASSIGNING WITH TABLE KEY obj_type = -object. + IF sy-subrc <> 0. + ls_ignored_count-obj_type = -object. + ls_ignored_count-count = 1. + ls_ignored_count-obj_name = -obj_name. + INSERT ls_ignored_count INTO TABLE lt_ignored_count ASSIGNING . + ELSE. + CLEAR: -obj_name. + -count = -count + 1. + ENDIF. + " init object so we can remove these entries afterward + CLEAR -object. + ENDLOOP. + IF lt_ignored_count IS INITIAL. + RETURN. + ENDIF. + + " remove ignored objects + DELETE ct_tadir WHERE object IS INITIAL. + + LOOP AT lt_ignored_count ASSIGNING . + IF -count = 1. + mi_log->add_warning( |Object { -obj_type } { -obj_name } ignored| ). + ELSE. + mi_log->add_warning( |Object type { -obj_type } with | && + |{ -count } objects ignored| ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD filter_unsupported_objects. + + DATA: ls_unsupported_count TYPE ty_unsupported_count, + lt_supported_types TYPE zif_abapgit_objects=>ty_types_tt, + lt_unsupported_count TYPE ty_unsupported_count_tt. + + FIELD-SYMBOLS: LIKE LINE OF ct_tadir, + TYPE ty_unsupported_count. + + lt_supported_types = zcl_abapgit_objects=>supported_list( ). + LOOP AT ct_tadir ASSIGNING . + CLEAR: ls_unsupported_count. + READ TABLE lt_supported_types WITH KEY table_line = -object TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + CONTINUE. + ENDIF. + + READ TABLE lt_unsupported_count ASSIGNING + WITH TABLE KEY obj_type = -object. + IF sy-subrc <> 0. + ls_unsupported_count-obj_type = -object. + ls_unsupported_count-count = 1. + ls_unsupported_count-obj_name = -obj_name. + INSERT ls_unsupported_count INTO TABLE lt_unsupported_count ASSIGNING . + ELSE. + CLEAR: -obj_name. + -count = -count + 1. + ENDIF. + CLEAR: -object. + ENDLOOP. + IF lt_unsupported_count IS INITIAL. + RETURN. + ENDIF. + + DELETE ct_tadir WHERE object IS INITIAL. + IF mi_log IS BOUND. + LOOP AT lt_unsupported_count ASSIGNING . + IF -count = 1. + mi_log->add_error( |Object type { -obj_type } not supported, | && + |{ -obj_name } ignored| ). + ELSE. + mi_log->add_error( |Object type { -obj_type } not supported, | && + |{ -count } objects ignored| ). + ENDIF. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD is_no_parallel. + + " Currently know object types that do not support parallel processing: + " ECTC/ECTD - ECATT Test Config/Data (see #7148) + " Should this list become longer, it should become a flag of the object type serializer + IF iv_object_type = 'ECTC' OR iv_object_type = 'ECTD'. + rv_result = abap_true. + ENDIF. + + ENDMETHOD. + METHOD is_parallelization_possible. + + rv_result = boolc( zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false + AND zcl_abapgit_persist_factory=>get_settings( )->read( )->get_parallel_proc_disabled( ) = abap_false + " The function module below should always exist here as is_merged evaluated to false above. + " It does however not exist in the transpiled version which then causes unit tests to fail. + " Therefore the check needs to stay. + AND zcl_abapgit_factory=>get_function_module( + )->function_exists( 'Z_ABAPGIT_SERIALIZE_PARALLEL' ) = abap_true ). + + ENDMETHOD. + METHOD on_end_of_task. + +* this method will be called from the parallel processing, thus it must be public + + DATA: lv_result TYPE xstring, + lv_path TYPE string, + lv_mess TYPE c LENGTH 200, + ls_file_item TYPE zif_abapgit_objects=>ty_serialization. + RECEIVE RESULTS FROM FUNCTION 'Z_ABAPGIT_SERIALIZE_PARALLEL' + IMPORTING + ev_result = lv_result + ev_path = lv_path + EXCEPTIONS + error = 1 + system_failure = 2 MESSAGE lv_mess + communication_failure = 3 MESSAGE lv_mess + OTHERS = 4. + IF sy-subrc <> 0. + IF NOT mi_log IS INITIAL. + IF NOT lv_mess IS INITIAL. + mi_log->add_error( lv_mess ). + ELSE. + mi_log->add_error( |{ sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv3 }| ). + ENDIF. + ENDIF. + ELSE. + IMPORT data = ls_file_item FROM DATA BUFFER lv_result. "#EC CI_SUBRC + ASSERT sy-subrc = 0. + add_to_return( is_file_item = ls_file_item + iv_path = lv_path ). + ENDIF. + + mv_free = mv_free + 1. + + ENDMETHOD. + METHOD run_parallel. + + DATA: lv_msg TYPE c LENGTH 100, + lv_task TYPE c LENGTH 32, + lv_free LIKE mv_free. + DATA lv_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version. + DATA lv_main_language_only TYPE abap_bool. + + ASSERT mv_free > 0. + + IF mo_abap_language_version IS NOT INITIAL. + lv_abap_language_version = mo_abap_language_version->get_repo_abap_language_version( ). + ENDIF. + + lv_main_language_only = ms_i18n_params-main_language_only. + IF lv_main_language_only = abap_false AND mt_wo_translation_patterns IS NOT INITIAL. + lv_main_language_only = zcl_abapgit_i18n_params=>match_obj_patterns( + is_tadir = is_tadir + it_wo_translation_patterns = mt_wo_translation_patterns ). + ENDIF. + + DO. + lv_task = |{ iv_task }-{ sy-index }|. + " An initial server group is handled like DEFAULT meaning all instances are used + CALL FUNCTION 'Z_ABAPGIT_SERIALIZE_PARALLEL' + STARTING NEW TASK lv_task + DESTINATION IN GROUP mv_group + CALLING on_end_of_task ON END OF TASK + EXPORTING + iv_obj_type = is_tadir-object + iv_obj_name = is_tadir-obj_name + iv_devclass = is_tadir-devclass + iv_path = is_tadir-path + iv_srcsystem = is_tadir-srcsystem + iv_abap_language_vers = lv_abap_language_version + iv_language = ms_i18n_params-main_language + iv_main_language_only = lv_main_language_only + iv_suppress_po_comments = ms_i18n_params-suppress_po_comments + it_translation_langs = ms_i18n_params-translation_languages + iv_use_lxe = ms_i18n_params-use_lxe + EXCEPTIONS + system_failure = 1 MESSAGE lv_msg + communication_failure = 2 MESSAGE lv_msg + resource_failure = 3 + OTHERS = 4. + IF sy-subrc = 3. + lv_free = mv_free. + WAIT UNTIL mv_free <> lv_free UP TO 1 SECONDS. + CONTINUE. + ELSEIF sy-subrc <> 0. + ASSERT lv_msg = '' AND 0 = 1. + ENDIF. + EXIT. + ENDDO. + + mv_free = mv_free - 1. + + ENDMETHOD. + METHOD run_sequential. + + DATA: lx_error TYPE REF TO zcx_abapgit_exception, + ls_i18n_params LIKE ms_i18n_params, + ls_file_item TYPE zif_abapgit_objects=>ty_serialization. + + ls_file_item-item-obj_type = is_tadir-object. + ls_file_item-item-obj_name = is_tadir-obj_name. + ls_file_item-item-devclass = is_tadir-devclass. + ls_file_item-item-srcsystem = is_tadir-srcsystem. + IF mo_abap_language_version IS NOT INITIAL. + ls_file_item-item-abap_language_version = mo_abap_language_version->get_repo_abap_language_version( ). + ENDIF. + + ls_i18n_params = ms_i18n_params. + IF ls_i18n_params-main_language_only = abap_false AND mt_wo_translation_patterns IS NOT INITIAL. + ls_i18n_params-main_language_only = zcl_abapgit_i18n_params=>match_obj_patterns( + is_tadir = is_tadir + it_wo_translation_patterns = mt_wo_translation_patterns ). + ENDIF. + + TRY. + ls_file_item = zcl_abapgit_objects=>serialize( + is_item = ls_file_item-item + io_i18n_params = zcl_abapgit_i18n_params=>new( is_params = ls_i18n_params ) ). + + add_to_return( is_file_item = ls_file_item + iv_path = is_tadir-path ). + CATCH zcx_abapgit_exception INTO lx_error. + IF NOT mi_log IS INITIAL. + mi_log->add_exception( + ix_exc = lx_error + is_item = ls_file_item-item ). + ENDIF. + ENDTRY. + + ENDMETHOD. + METHOD serialize. + +* serializes only objects + + DATA: lv_max TYPE i, + lv_count TYPE i, + li_progress TYPE REF TO zif_abapgit_progress, + li_exit TYPE REF TO zif_abapgit_exit, + lo_timer TYPE REF TO zcl_abapgit_timer, + lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + + FIELD-SYMBOLS: LIKE LINE OF it_tadir. + CLEAR mt_files. + + lv_max = determine_max_processes( iv_force_sequential = iv_force_sequential + iv_package = iv_package ). + mv_free = lv_max. + mi_log = ii_log. + + lt_tadir = it_tadir. + filter_unsupported_objects( CHANGING ct_tadir = lt_tadir ). + + filter_ignored_objects( + EXPORTING + iv_package = iv_package + CHANGING + ct_tadir = lt_tadir ). + + lv_count = lines( lt_tadir ). + + li_progress = zcl_abapgit_progress=>get_instance( lv_count ). + + lo_timer = zcl_abapgit_timer=>create( + iv_text = 'Serialize:' + iv_count = lv_count )->start( ). + + LOOP AT lt_tadir ASSIGNING . + IF lv_max = 1 OR is_no_parallel( -object ) = abap_true. + li_progress->show( + iv_current = sy-tabix + iv_text = |Serialize { -obj_name }, { lv_max } thread| ). + run_sequential( ). + ELSE. + li_progress->show( + iv_current = sy-tabix + iv_text = |Serialize { -obj_name }, { lv_max } threads| ). + run_parallel( + is_tadir = + iv_task = |{ sy-tabix }| ). + WAIT UNTIL mv_free > 0 UP TO 120 SECONDS. + ENDIF. + ENDLOOP. + + li_progress->off( ). + + WAIT UNTIL mv_free = lv_max UP TO 120 SECONDS. + rt_files = mt_files. + FREE mt_files. + +* Call postprocessing + li_exit = zcl_abapgit_exit=>get_instance( ). + + li_exit->serialize_postprocess( + EXPORTING + iv_package = iv_package + ii_log = ii_log + CHANGING + ct_files = rt_files ). + + lo_timer->end( abap_true ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECTS_FILES IMPLEMENTATION. + METHOD add. + APPEND is_file TO mt_files. + ENDMETHOD. + METHOD add_abap. + + DATA: lv_source TYPE string, + ls_file TYPE zif_abapgit_git_definitions=>ty_file. + CONCATENATE LINES OF it_abap INTO lv_source SEPARATED BY cl_abap_char_utilities=>newline. +* when editing files via eg. GitHub web interface it adds a newline at end of file + lv_source = lv_source && cl_abap_char_utilities=>newline. + + ls_file-path = '/'. + ls_file-filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_extra = iv_extra + iv_ext = 'abap' ). + ls_file-data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_source ). + + APPEND ls_file TO mt_files. + + ENDMETHOD. + METHOD add_i18n_file. + + DATA ls_file TYPE zif_abapgit_git_definitions=>ty_file. + + ls_file-data = ii_i18n_file->render( ). + IF ls_file-data IS INITIAL. + RETURN. " Don't add empty files + ENDIF. + + ls_file-path = '/'. + ls_file-filename = zcl_abapgit_filename_logic=>object_to_i18n_file( + is_item = ms_item + iv_lang_suffix = ii_i18n_file->lang_suffix( ) + iv_ext = ii_i18n_file->ext( ) ). + + APPEND ls_file TO mt_files. + + ENDMETHOD. + METHOD add_raw. + + DATA: ls_file TYPE zif_abapgit_git_definitions=>ty_file. + + ls_file-path = '/'. + ls_file-data = iv_data. + ls_file-filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_extra = iv_extra + iv_ext = iv_ext ). + + APPEND ls_file TO mt_files. + + ENDMETHOD. + METHOD add_string. + + DATA: ls_file TYPE zif_abapgit_git_definitions=>ty_file. + + ls_file-path = '/'. + ls_file-filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_extra = iv_extra + iv_ext = iv_ext ). + ls_file-data = zcl_abapgit_convert=>string_to_xstring_utf8( iv_string ). + + APPEND ls_file TO mt_files. + + ENDMETHOD. + METHOD add_xml. + + DATA: lv_xml TYPE string, + ls_file TYPE zif_abapgit_git_definitions=>ty_file. + + lv_xml = ii_xml->render( iv_normalize = iv_normalize + is_metadata = is_metadata ). + ls_file-path = '/'. + + ls_file-filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_extra = iv_extra + iv_ext = 'xml' ). + + REPLACE FIRST OCCURRENCE + OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' + IN lv_xml + WITH ''. + ASSERT sy-subrc = 0. + + ls_file-data = zcl_abapgit_convert=>string_to_xstring_utf8_bom( lv_xml ). + + APPEND ls_file TO mt_files. + ENDMETHOD. + METHOD constructor. + ms_item = is_item. + mv_path = iv_path. + ENDMETHOD. + METHOD contains_file. + DATA: lv_filename TYPE string. + + lv_filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_extra = iv_extra + iv_ext = iv_ext ). + + IF mv_path IS NOT INITIAL. + READ TABLE mt_files TRANSPORTING NO FIELDS + WITH KEY file_path + COMPONENTS path = mv_path + filename = lv_filename. + ELSE. + READ TABLE mt_files TRANSPORTING NO FIELDS + WITH KEY file + COMPONENTS filename = lv_filename. + ENDIF. + + IF sy-subrc = 0. + rv_present = abap_true. + ENDIF. + ENDMETHOD. + METHOD get_accessed_files. + rt_files = mt_accessed_files. + ENDMETHOD. + METHOD get_files. + rt_files = mt_files. + ENDMETHOD. + METHOD get_file_pattern. + rv_pattern = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_ext = '*' ). + " Escape special characters for use with 'covers pattern' (CP) + REPLACE ALL OCCURRENCES OF '#' IN rv_pattern WITH '##'. + REPLACE ALL OCCURRENCES OF '+' IN rv_pattern WITH '#+'. + ENDMETHOD. + METHOD is_json_metadata. + + DATA lv_pattern TYPE string. + + FIELD-SYMBOLS LIKE LINE OF mt_files. + + lv_pattern = |*.{ to_lower( ms_item-obj_type ) }.json|. + + LOOP AT mt_files ASSIGNING WHERE filename CP lv_pattern. + rv_result = abap_true. + EXIT. + ENDLOOP. + + ENDMETHOD. + METHOD mark_accessed. + + FIELD-SYMBOLS LIKE LINE OF mt_accessed_files. + + READ TABLE mt_accessed_files TRANSPORTING NO FIELDS + WITH KEY path = iv_path filename = iv_file. + IF sy-subrc > 0. " Not found ? -> Add + APPEND INITIAL LINE TO mt_accessed_files ASSIGNING . + -path = iv_path. + -filename = iv_file. + -sha1 = iv_sha1. + ENDIF. + + ENDMETHOD. + METHOD new. + CREATE OBJECT ro_files + EXPORTING + is_item = is_item + iv_path = iv_path. + ENDMETHOD. + METHOD read_abap. + + DATA: lv_filename TYPE string, + lv_data TYPE xstring, + lv_abap TYPE string. + lv_filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_extra = iv_extra + iv_ext = 'abap' ). + + lv_data = read_file( iv_filename = lv_filename + iv_error = iv_error ). + + IF lv_data IS INITIAL. " Post-handling of iv_error = false + RETURN. + ENDIF. + + lv_abap = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). + + SPLIT lv_abap AT cl_abap_char_utilities=>newline INTO TABLE rt_abap. + + ENDMETHOD. + METHOD read_file. + + FIELD-SYMBOLS LIKE LINE OF mt_files. + + IF mv_path IS NOT INITIAL. + READ TABLE mt_files ASSIGNING + WITH KEY file_path + COMPONENTS path = mv_path + filename = iv_filename. + ELSE. + READ TABLE mt_files ASSIGNING + WITH KEY file + COMPONENTS filename = iv_filename. + ENDIF. + + IF sy-subrc <> 0. + IF iv_error = abap_true. + zcx_abapgit_exception=>raise( |File not found: { iv_filename }| ). + ELSE. + RETURN. + ENDIF. + ENDIF. + + " Update access table + mark_accessed( + iv_path = -path + iv_file = -filename + iv_sha1 = -sha1 ). + + rv_data = -data. + + ENDMETHOD. + METHOD read_i18n_files. + + DATA: + lv_lang TYPE laiso, + lv_ext TYPE string, + lo_po TYPE REF TO zcl_abapgit_po_file, + lo_properties TYPE REF TO zcl_abapgit_properties_file. + + FIELD-SYMBOLS LIKE LINE OF mt_files. + + LOOP AT mt_files ASSIGNING . + + CHECK find( val = -filename + sub = '.i18n.' ) > 0. " Only i18n files are relevant + + zcl_abapgit_filename_logic=>i18n_file_to_object( + EXPORTING + iv_path = -path + iv_filename = -filename + IMPORTING + ev_lang = lv_lang + ev_ext = lv_ext ). + + CASE lv_ext. + WHEN 'po'. + CREATE OBJECT lo_po EXPORTING iv_lang = lv_lang. + lo_po->parse( -data ). + APPEND lo_po TO rt_i18n_files. + WHEN 'properties'. + CREATE OBJECT lo_properties EXPORTING iv_lang = lv_lang. + lo_properties->parse( -data ). + APPEND lo_properties TO rt_i18n_files. + WHEN OTHERS. + CONTINUE. " Unsupported i18n file type + ENDCASE. + + mark_accessed( + iv_path = -path + iv_file = -filename + iv_sha1 = -sha1 ). + + ENDLOOP. + + ENDMETHOD. + METHOD read_raw. + + DATA: lv_filename TYPE string. + + lv_filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_extra = iv_extra + iv_ext = iv_ext ). + + rv_data = read_file( lv_filename ). + + ENDMETHOD. + METHOD read_string. + + DATA: lv_filename TYPE string, + lv_data TYPE xstring. + + lv_filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_extra = iv_extra + iv_ext = iv_ext ). + + lv_data = read_file( lv_filename ). + + rv_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). + + ENDMETHOD. + METHOD read_xml. + + DATA: lv_filename TYPE string, + lv_data TYPE xstring, + lv_xml TYPE string. + + lv_filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ms_item + iv_extra = iv_extra + iv_ext = 'xml' ). + + lv_data = read_file( lv_filename ). + + lv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). + + CREATE OBJECT ri_xml + TYPE zcl_abapgit_xml_input + EXPORTING + iv_xml = lv_xml + iv_filename = lv_filename. + + ENDMETHOD. + METHOD set_files. + + FIELD-SYMBOLS: LIKE LINE OF it_files. + + CLEAR mt_files. + + " Set only files matching the pattern for this object + " If a path has been defined in the constructor, then the path has to match, too + LOOP AT it_files ASSIGNING WHERE filename CP get_file_pattern( ). + IF mv_path IS INITIAL. + INSERT INTO TABLE mt_files. + ELSEIF mv_path = -path. + INSERT INTO TABLE mt_files. + ENDIF. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_objects_compare IMPLEMENTATION. + METHOD get_comparator. + + DATA lv_class_name TYPE seoclsname. + + CONCATENATE 'ZCL_ABAPGIT_OBJECT_' is_item-obj_type '_COMPAR' INTO lv_class_name. + + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. + " Prevent accidental usage of object handlers in the developer version + lv_class_name = |\\PROGRAM={ sy-repid }\\CLASS={ lv_class_name }|. + ENDIF. + + TRY. + CREATE OBJECT ri_comparator TYPE (lv_class_name) + EXPORTING + is_item = is_item. + CATCH cx_sy_create_object_error ##NO_HANDLER. + " No instance, no comparator for this object type + ENDTRY. + + ENDMETHOD. + METHOD get_result. + + " this method is used for comparing local with remote objects + " before pull, this is useful eg. when overwriting a TABL object. + " only the main XML file is used for comparison + + DATA: + ls_remote_file TYPE zif_abapgit_git_definitions=>ty_file, + ls_local_file TYPE zif_abapgit_definitions=>ty_file_item, + li_remote_version TYPE REF TO zif_abapgit_xml_input, + li_local_version TYPE REF TO zif_abapgit_xml_input, + li_log TYPE REF TO zif_abapgit_log, + ls_msg TYPE zif_abapgit_log=>ty_log_out, + lt_msg TYPE zif_abapgit_log=>ty_log_outs, + ls_result TYPE zif_abapgit_comparator=>ty_result. + + " REMOTE + " if file does not exist in remote, we don't need to validate + READ TABLE it_remote WITH KEY file COMPONENTS filename = iv_filename INTO ls_remote_file. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + CREATE OBJECT li_remote_version TYPE zcl_abapgit_xml_input + EXPORTING + iv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( ls_remote_file-data ) + iv_filename = iv_filename. + + " LOCAL + " if file does not exist locally, we don't need to validate + READ TABLE it_local WITH KEY file-filename = iv_filename INTO ls_local_file. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + CREATE OBJECT li_local_version TYPE zcl_abapgit_xml_input + EXPORTING + iv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( ls_local_file-file-data ) + iv_filename = iv_filename. + + " COMPARE + CREATE OBJECT li_log TYPE zcl_abapgit_log. + + ls_result = ii_comparator->compare( + ii_local = li_local_version + ii_remote = li_remote_version + ii_log = li_log ). + + rv_result = ls_result-text. + + " To keep it simple, append the log messages to the result + lt_msg = li_log->get_messages( ). + + LOOP AT lt_msg INTO ls_msg. + rv_result = |{ rv_result }, { ls_msg-text }|. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_objects_check IMPLEMENTATION. + METHOD adjust_result. + + DATA ls_overwrite TYPE zif_abapgit_definitions=>ty_overwrite. + + FIELD-SYMBOLS TYPE zif_abapgit_definitions=>ty_overwrite. + + LOOP AT it_overwrite_new ASSIGNING . + + READ TABLE it_overwrite_old INTO ls_overwrite WITH TABLE KEY object_type_and_name + COMPONENTS obj_type = -obj_type obj_name = -obj_name. + IF sy-subrc <> 0 OR ls_overwrite-decision IS INITIAL. + zcx_abapgit_exception=>raise( |{ iv_txt } { -obj_type } { -obj_name } undecided| ). + ENDIF. + + IF ls_overwrite-decision = zif_abapgit_definitions=>c_no. + DELETE ct_results WHERE obj_type = -obj_type AND obj_name = -obj_name. + ASSERT sy-subrc = 0. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD checks_adjust. + + " Make sure to get the current status, as something might have changed in the meanwhile + " - Remove objects from results that were deselected in confirmation popup + " - Raise exception if an object has no decision of what to do + + warning_overwrite_adjust( + EXPORTING + it_overwrite = is_checks-overwrite + CHANGING + ct_results = ct_results ). + + warning_package_adjust( + EXPORTING + ii_repo = ii_repo + it_overwrite = is_checks-warning_package + CHANGING + ct_results = ct_results ). + + warning_data_loss_adjust( + EXPORTING + ii_repo = ii_repo + it_overwrite = is_checks-data_loss + CHANGING + ct_results = ct_results ). + + ENDMETHOD. + METHOD check_multiple_files. + + DATA: + lv_msg TYPE string, + lv_lstate TYPE c LENGTH 2, + lv_rstate TYPE c LENGTH 2, + lt_res_sort LIKE it_results, + ls_result LIKE LINE OF it_results. + + FIELD-SYMBOLS LIKE LINE OF it_results. + + lt_res_sort = it_results. + SORT lt_res_sort BY filename ASCENDING. + + " Prevent pulling if there is more than one file with the same name + LOOP AT lt_res_sort ASSIGNING + WHERE obj_type <> 'DEVC' AND packmove = abap_false AND filename IS NOT INITIAL. + " Changing package and object at the same time is ok (state: Add + Delete) + CONCATENATE -lstate ls_result-lstate INTO lv_lstate RESPECTING BLANKS. + CONCATENATE -rstate ls_result-rstate INTO lv_rstate RESPECTING BLANKS. + IF -filename = ls_result-filename AND + lv_lstate <> 'AD' AND lv_lstate <> 'DA' AND lv_rstate <> 'AD' AND lv_rstate <> 'DA'. + lv_msg = |Pull not possible since there are multiple files with same filename, { -filename }.| + && | Keep one of the files and delete the other in the repository.|. + zcx_abapgit_exception=>raise( lv_msg ). + ENDIF. + MOVE-CORRESPONDING TO ls_result. + ENDLOOP. + + ENDMETHOD. + METHOD class_constructor. + + gi_exit = zcl_abapgit_exit=>get_instance( ). + + ENDMETHOD. + METHOD deserialize_checks. + + DATA: lt_results TYPE zif_abapgit_definitions=>ty_results_tt, + li_package TYPE REF TO zif_abapgit_sap_package. + + " get unfiltered status to evaluate properly which warnings are required + lt_results = zcl_abapgit_repo_status=>calculate( ii_repo ). + + check_multiple_files( lt_results ). + + rs_checks-overwrite = warning_overwrite_find( lt_results ). + + rs_checks-warning_package = warning_package_find( + ii_repo = ii_repo + it_results = lt_results ). + + rs_checks-data_loss = warning_data_loss_find( + ii_repo = ii_repo + it_results = lt_results ). + + IF lines( lt_results ) > 0. + li_package = zcl_abapgit_factory=>get_sap_package( ii_repo->get_package( ) ). + rs_checks-transport-required = li_package->are_changes_recorded_in_tr_req( ). + IF NOT rs_checks-transport-required IS INITIAL. + rs_checks-transport-type = li_package->get_transport_type( ). + rs_checks-transport-transport = determine_transport_request( + ii_repo = ii_repo + iv_transport_type = rs_checks-transport-type ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD determine_transport_request. + + " Use transport from repo settings if maintained, or determine via user exit. + " If transport keeps empty here, it'll requested later via popup. + rv_transport_request = ii_repo->get_local_settings( )-transport_request. + + gi_exit->determine_transport_request( + EXPORTING + ii_repo = ii_repo + iv_transport_type = iv_transport_type + CHANGING + cv_transport_request = rv_transport_request ). + + ENDMETHOD. + METHOD warning_data_loss_adjust. + + DATA lt_overwrite LIKE it_overwrite. + + lt_overwrite = warning_data_loss_find( + it_results = ct_results + ii_repo = ii_repo ). + + adjust_result( + EXPORTING + iv_txt = 'Potential data loss for' + it_overwrite_old = it_overwrite + it_overwrite_new = lt_overwrite + CHANGING + ct_results = ct_results ). + + ENDMETHOD. + METHOD warning_data_loss_find. + + DATA: + ls_item TYPE zif_abapgit_definitions=>ty_item, + li_comparator TYPE REF TO zif_abapgit_comparator, + ls_overwrite LIKE LINE OF rt_overwrite, + lv_result TYPE string. + + FIELD-SYMBOLS LIKE LINE OF it_results. + + " For optimal performance, we limit here by object type since we know that only TABL has a comparator + " If there are other object types in the future, extend the where clause or remove the check on object type. + LOOP AT it_results ASSIGNING + WHERE match IS INITIAL + AND packmove IS INITIAL + AND filename CP '*.xml' + AND obj_type = 'TABL' ##PRIMKEY[SEC_KEY]. + + CLEAR ls_item. + MOVE-CORRESPONDING TO ls_item. + + li_comparator = zcl_abapgit_objects_compare=>get_comparator( ls_item ). + IF NOT li_comparator IS BOUND. + RETURN. + ENDIF. + + lv_result = zcl_abapgit_objects_compare=>get_result( + ii_comparator = li_comparator + iv_filename = -filename + it_local = ii_repo->get_files_local( ) + it_remote = ii_repo->get_files_remote( iv_ignore_files = abap_true ) ). + + IF lv_result IS NOT INITIAL. + READ TABLE rt_overwrite TRANSPORTING NO FIELDS WITH KEY object_type_and_name COMPONENTS + obj_type = -obj_type + obj_name = -obj_name. + IF sy-subrc <> 0. + CLEAR ls_overwrite. + MOVE-CORRESPONDING TO ls_overwrite. + ls_overwrite-devclass = -package. + ls_overwrite-action = zif_abapgit_objects=>c_deserialize_action-data_loss. + ls_overwrite-icon = icon_warning. + ls_overwrite-text = lv_result. + INSERT ls_overwrite INTO TABLE rt_overwrite. + ENDIF. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD warning_overwrite_adjust. + + DATA lt_overwrite LIKE it_overwrite. + + lt_overwrite = warning_overwrite_find( ct_results ). + + adjust_result( + EXPORTING + iv_txt = 'Overwrite of object' + it_overwrite_old = it_overwrite + it_overwrite_new = lt_overwrite + CHANGING + ct_results = ct_results ). + + ENDMETHOD. + METHOD warning_overwrite_find. + + DATA: + ls_item TYPE zif_abapgit_definitions=>ty_item, + lv_status TYPE c LENGTH 2, + lt_changes TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_overwrite WITH DEFAULT KEY. + + FIELD-SYMBOLS: + LIKE LINE OF it_results, + LIKE LINE OF lt_changes. + + " collect all actions for object that have been changed + LOOP AT it_results ASSIGNING WHERE NOT obj_type IS INITIAL. + + APPEND INITIAL LINE TO lt_changes ASSIGNING . + MOVE-CORRESPONDING TO . + -devclass = -package. + MOVE-CORRESPONDING TO ls_item. + + IF -packmove = abap_true. + -action = zif_abapgit_objects=>c_deserialize_action-packmove. + -icon = icon_package_standard. + -text = 'Change package assignment'. + ELSEIF zcl_abapgit_objects=>is_supported( ls_item ) = abap_false + AND ls_item-obj_type <> zif_abapgit_data_config=>c_data_type-tabu. + -action = zif_abapgit_objects=>c_deserialize_action-no_support. + -icon = icon_no_status. + -text = 'Object type not supported'. + ELSE. + CONCATENATE -lstate -rstate INTO lv_status RESPECTING BLANKS. + -state = lv_status. + REPLACE ALL OCCURRENCES OF ` ` IN -state WITH '_'. + + CASE lv_status. + WHEN ' '. " no changes + -action = zif_abapgit_objects=>c_deserialize_action-none. + WHEN ' A' OR 'D ' OR 'DM'. " added remotely or deleted locally + -action = zif_abapgit_objects=>c_deserialize_action-add. + -icon = icon_create. + -text = 'Add local object'. + WHEN 'A ' OR ' D' OR 'MD'. " added locally or deleted remotely + -action = zif_abapgit_objects=>c_deserialize_action-delete. + -icon = icon_delete. + -text = 'Delete local object'. + WHEN 'M ' OR 'MM'. " modified locally + -action = zif_abapgit_objects=>c_deserialize_action-overwrite. + -icon = icon_change. + -text = 'Overwrite local object'. + WHEN ' M'. " modified only remotely + -action = zif_abapgit_objects=>c_deserialize_action-update. + -icon = icon_change. + -text = 'Update local object'. + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + ENDIF. + + ENDLOOP. + + " Remove duplicate actions + SORT lt_changes. + DELETE ADJACENT DUPLICATES FROM lt_changes. + + " Check if deletions are for complete object or just a part + LOOP AT lt_changes ASSIGNING WHERE action = zif_abapgit_objects=>c_deserialize_action-delete. + + LOOP AT lt_changes TRANSPORTING NO FIELDS + WHERE obj_type = -obj_type AND obj_name = -obj_name + AND action <> zif_abapgit_objects=>c_deserialize_action-delete. + EXIT. + ENDLOOP. + IF sy-subrc = 0. + " There's some other action, so object will be recreated after deletion + -action = zif_abapgit_objects=>c_deserialize_action-delete_add. + -icon = icon_adopt. + -text = 'Delete and recreate local object'. + ENDIF. + + ENDLOOP. + + DELETE lt_changes WHERE action = zif_abapgit_objects=>c_deserialize_action-none. + + " If there are multiple changes in an object, keep highest priority action + SORT lt_changes BY obj_type obj_name action DESCENDING. + DELETE ADJACENT DUPLICATES FROM lt_changes COMPARING obj_type obj_name. + + rt_overwrite = lt_changes. + + ENDMETHOD. + METHOD warning_package_adjust. + + DATA lt_overwrite LIKE it_overwrite. + + lt_overwrite = warning_package_find( + it_results = ct_results + ii_repo = ii_repo ). + + adjust_result( + EXPORTING + iv_txt = 'Overwrite of package' + it_overwrite_old = it_overwrite + it_overwrite_new = lt_overwrite + CHANGING + ct_results = ct_results ). + + ENDMETHOD. + METHOD warning_package_find. + + DATA: lv_package TYPE devclass, + lt_overwrite_unique TYPE HASHED TABLE OF zif_abapgit_definitions=>ty_overwrite + WITH UNIQUE KEY obj_type obj_name devclass, + ls_overwrite LIKE LINE OF rt_overwrite, + ls_tadir TYPE zif_abapgit_definitions=>ty_tadir. + + DATA: lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic. + + FIELD-SYMBOLS: LIKE LINE OF it_results. + + lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). + LOOP AT it_results ASSIGNING WHERE match IS INITIAL AND packmove IS INITIAL. + + lv_package = lo_folder_logic->path_to_package( + iv_top = ii_repo->get_package( ) + io_dot = ii_repo->get_dot_abapgit( ) + iv_path = -path + iv_create_if_not_exists = abap_false ). + + ls_tadir = zcl_abapgit_factory=>get_tadir( )->read_single( + iv_object = -obj_type + iv_obj_name = -obj_name ). + + IF NOT ls_tadir IS INITIAL AND ls_tadir-devclass <> lv_package. + " overwriting object from different package than expected + CLEAR ls_overwrite. + CONCATENATE -lstate -rstate INTO ls_overwrite-state RESPECTING BLANKS. + REPLACE ALL OCCURRENCES OF ` ` IN ls_overwrite-state WITH '_'. + ls_overwrite-obj_type = -obj_type. + ls_overwrite-obj_name = -obj_name. + ls_overwrite-devclass = ls_tadir-devclass. + ls_overwrite-action = zif_abapgit_objects=>c_deserialize_action-overwrite. + ls_overwrite-icon = icon_change. + ls_overwrite-text = 'Overwrite local object'. + INSERT ls_overwrite INTO TABLE lt_overwrite_unique. + ENDIF. + + ENDLOOP. + + rt_overwrite = lt_overwrite_unique. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_objects_activation IMPLEMENTATION. + METHOD activate. + + " Make sure that all changes are committed since any activation error will lead to a rollback + COMMIT WORK AND WAIT. + + IF use_new_activation_logic( ) = abap_true. + activate_new( + iv_ddic = iv_ddic + ii_log = ii_log ). + ELSE. + activate_old( + iv_ddic = iv_ddic + ii_log = ii_log ). + ENDIF. + + update_where_used( ii_log ). + + ENDMETHOD. + METHOD activate_ddic. + + DATA: lt_gentab TYPE STANDARD TABLE OF dcgentb, + lv_rc TYPE sy-subrc, + ls_gentab LIKE LINE OF lt_gentab, + lt_deltab TYPE STANDARD TABLE OF dcdeltb, + lt_action_tab TYPE STANDARD TABLE OF dctablres, + lv_logname TYPE ddmass-logname. + + FIELD-SYMBOLS: LIKE LINE OF gt_objects. + LOOP AT gt_objects ASSIGNING . + " Filter types supported by mass activation + IF is_ddic_type( -object ) = abap_false. + CONTINUE. + ENDIF. + ls_gentab-tabix = sy-tabix. + + get_ddic_type( + EXPORTING + iv_obj_type = -object + iv_obj_name = -obj_name + IMPORTING + ev_type = ls_gentab-type + ev_name = ls_gentab-name + ev_id = ls_gentab-indx ). + + INSERT ls_gentab INTO TABLE lt_gentab. + ENDLOOP. + + IF lt_gentab IS NOT INITIAL. + + lv_logname = |ABAPGIT_{ sy-datum }_{ sy-uzeit }|. + + IF lines( lt_gentab ) = 1. + ii_log->add_info( |> Mass activating 1 DDIC object| ). + ELSE. + ii_log->add_info( |> Mass activating { lines( lt_gentab ) } DDIC objects| ). + ENDIF. + ii_log->add_info( |Log name: { lv_logname }| ). + + CALL FUNCTION 'DD_MASS_ACT_C3' + EXPORTING + ddmode = 'O' " activate changes in Original System + frcact = abap_true " force Activation + medium = 'T' " transport order + device = 'T' " saves to table DDRPH? + version = 'M' " activate newest version + logname = lv_logname + write_log = abap_true + log_head_tail = abap_true + t_on = space + prid = 1 + IMPORTING + act_rc = lv_rc + TABLES + gentab = lt_gentab + deltab = lt_deltab + cnvtab = lt_action_tab + EXCEPTIONS + access_failure = 1 + no_objects = 2 + locked = 3 + internal_error = 4 + OTHERS = 5. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF lv_rc > 0. + add_errors_and_warnings_to_log( + iv_logname = lv_logname + ii_log = ii_log ). + ENDIF. + + IF lv_rc > 4. + zcx_abapgit_exception=>raise( 'Activation cancelled. Check the inactive objects.' ). + ENDIF. + + " Remove objects from activation queue to avoid double activation in activate_old + LOOP AT lt_gentab INTO ls_gentab. + DELETE gt_objects WHERE object = ls_gentab-type AND obj_name = ls_gentab-name. + ENDLOOP. + DELETE gt_objects WHERE object = 'INDX' OR object = 'XINX' OR object = 'MCID'. + + ENDIF. + + ENDMETHOD. + METHOD activate_new. + + IF gt_objects IS INITIAL. + RETURN. + ENDIF. + + IF iv_ddic = abap_true. + + activate_ddic( ii_log ). + + ELSE. + + activate_old( ii_log ). + + ENDIF. + + ENDMETHOD. + METHOD activate_old. + + DATA: + lv_popup TYPE abap_bool, + lv_no_ui TYPE abap_bool, + lv_try_again TYPE abap_bool, + lv_msg TYPE string, + lo_checklist TYPE REF TO cl_wb_checklist. + + IF gt_objects IS NOT INITIAL. + + IF zcl_abapgit_ui_factory=>get_frontend_services( )->gui_is_available( ) = abap_true. + IF zcl_abapgit_persist_factory=>get_settings( )->read( )->get_activate_wo_popup( ) = abap_true. + lv_popup = abap_false. + ELSE. + lv_popup = abap_true. + ENDIF. + ELSE. + lv_popup = abap_false. + ENDIF. + + lv_no_ui = boolc( lv_popup = abap_false ). + + IF iv_ddic = abap_true. + lv_msg = |(with DDIC)|. + ENDIF. + IF lines( gt_objects ) = 1. + ii_log->add_info( |> Activating 1 object { lv_msg }| ). + ELSE. + ii_log->add_info( |> Activating { lines( gt_objects ) } objects { lv_msg }| ). + ENDIF. + + TRY. + CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE' + EXPORTING + activate_ddic_objects = iv_ddic + with_popup = lv_popup + ui_decoupled = lv_no_ui + IMPORTING + p_checklist = lo_checklist + TABLES + objects = gt_objects + EXCEPTIONS + excecution_error = 1 + cancelled = 2 + insert_into_corr_error = 3 + OTHERS = 4 ##FM_SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. + CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE' + EXPORTING + activate_ddic_objects = iv_ddic + with_popup = lv_popup + IMPORTING + p_checklist = lo_checklist + TABLES + objects = gt_objects + EXCEPTIONS + excecution_error = 1 + cancelled = 2 + insert_into_corr_error = 3 + OTHERS = 4 ##FM_SUBRC_OK. + ENDTRY. + CASE sy-subrc. + WHEN 1 OR 3 OR 4. + zcx_abapgit_exception=>raise_t100( ). + WHEN 2. + lv_msg = 'Check the log and inactive objects.'. + IF lv_popup = abap_false. + lv_try_again = add_activation_errors_to_log( + ii_log = ii_log + io_checklist = lo_checklist ). + IF lv_try_again = abap_true. + lv_msg = 'Turn on "Activation Popup" in "Personal Settings" and try again'. + ENDIF. + ENDIF. + zcx_abapgit_exception=>raise( |Activation cancelled. { lv_msg }| ). + ENDCASE. + + ENDIF. + + ENDMETHOD. + METHOD add. + +* function group SEWORKINGAREA +* function module RS_INSERT_INTO_WORKING_AREA +* class CL_WB_ACTIVATION_WORK_AREA + + FIELD-SYMBOLS: TYPE dwinactiv, + LIKE LINE OF gt_classes. + + IF iv_type = 'CLAS' OR iv_type = 'INTF'. + APPEND INITIAL LINE TO gt_classes ASSIGNING . + -object = iv_type. + -clsname = iv_name. + ELSE. + APPEND INITIAL LINE TO gt_objects ASSIGNING . + -object = iv_type. + -obj_name = iv_name. + -delet_flag = iv_delete. + ENDIF. + + ENDMETHOD. + METHOD add_activation_errors_to_log. + + DATA: + ls_item TYPE zif_abapgit_definitions=>ty_item, + lt_message TYPE swbme_error_tab. + + FIELD-SYMBOLS: + TYPE string, + LIKE LINE OF lt_message. + + io_checklist->get_error_messages( IMPORTING p_error_tab = lt_message ). + + LOOP AT lt_message ASSIGNING WHERE mtype = 'E'. + " When activating without popup, includes used in multiple main programs cause error + " Run again WITH activation popup (see abapGit, Personal Settings) + IF -message-msgid = 'EU' AND -message-msgno = '404'. + rv_try_again = abap_true. + ENDIF. + CLEAR ls_item. + IF strlen( -object_text ) > 5. + ls_item-obj_type = -object_text(4). + ls_item-obj_name = -object_text+5(*). + ELSEIF -show_req IS NOT INITIAL. + ls_item-obj_name = -show_req->object_name. + SELECT SINGLE tadir FROM euobjedit INTO ls_item-obj_type + WHERE type = -show_req->object_type. + ENDIF. + LOOP AT -mtext ASSIGNING . + IF sy-tabix = 1. + ii_log->add( + iv_type = 'E' + iv_msg = + iv_class = -message-msgid + iv_number = -message-msgno + is_item = ls_item ). + ELSE. + ii_log->add_error( + iv_msg = + is_item = ls_item ). + ENDIF. + ENDLOOP. + ENDLOOP. + + ENDMETHOD. + METHOD add_errors_and_warnings_to_log. + + DATA: lt_lines TYPE STANDARD TABLE OF trlog, + lv_logname_db TYPE ddprh-protname. + + FIELD-SYMBOLS: LIKE LINE OF lt_lines. + lv_logname_db = iv_logname. + + CALL FUNCTION 'TR_READ_LOG' + EXPORTING + iv_log_type = 'DB' + iv_logname_db = lv_logname_db + TABLES + et_lines = lt_lines + EXCEPTIONS + invalid_input = 1 + access_error = 2 + OTHERS = 3. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + " Only error messages + DELETE lt_lines WHERE severity <> 'E' + AND severity <> 'W'. + " Remove "Return code..." message + DELETE lt_lines WHERE class = 'D0' AND number = '319'. + + LOOP AT lt_lines ASSIGNING . + ii_log->add( iv_msg = -line + iv_type = -severity + iv_class = -class + iv_number = |{ -number }| ). + ENDLOOP. + + ii_log->add_info( |View complete activation log in program RSPUTPRT (type D, log name { iv_logname })| ). + + ENDMETHOD. + METHOD add_item. + add( iv_type = is_item-obj_type + iv_name = is_item-obj_name ). + ENDMETHOD. + METHOD clear. + CLEAR gt_objects. + CLEAR gt_classes. + ENDMETHOD. + METHOD get_ddic_type. + + DATA lv_obj_name TYPE e071-obj_name. + + ev_type = iv_obj_type. + + IF ev_type = 'INDX' OR ev_type = 'XINX' OR ev_type = 'MCID'. + lv_obj_name = iv_obj_name. "cast + + CALL FUNCTION 'DD_E071_TO_DD' + EXPORTING + object = ev_type + obj_name = lv_obj_name + IMPORTING + name = ev_name + id = ev_id + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ELSE. + ev_name = iv_obj_name. + ENDIF. + + ENDMETHOD. + METHOD is_active. + + " Checks if object is active or not + " + " Note: If object does not exist, this method returns true + " is_not_inactive might be a better name but we avoid the double negative + + IF is_ddic_type( is_item-obj_type ) = abap_true + AND c_para NS is_item-obj_type + AND c_switches NS is_item-obj_type. + rv_active = is_ddic_active( is_item ). + ELSE. + rv_active = is_non_ddic_active( is_item ). + ENDIF. + + ENDMETHOD. + METHOD is_ddic_active. + + DATA: + lv_type TYPE ddobjtyp, + lv_name TYPE ddobjname, + lv_id TYPE ddobjectid, + lv_state TYPE ddgotstate. + + get_ddic_type( + EXPORTING + iv_obj_type = is_item-obj_type + iv_obj_name = is_item-obj_name + IMPORTING + ev_type = lv_type + ev_name = lv_name + ev_id = lv_id ). + + " Check if an inactive version of the DDIC object exists + " state = 'A' checks if an active version exists but does not detect new or modified objects + " state = 'M' checks for all possible versions so we can find out if an inactive one exists + " See documentation of the function module + CALL FUNCTION 'DDIF_STATE_GET' + EXPORTING + type = lv_type + name = lv_name + id = lv_id + state = 'M' + IMPORTING + gotstate = lv_state + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + + rv_active = boolc( sy-subrc = 0 AND ( lv_state = '' OR lv_state = 'A' ) ). + + ENDMETHOD. + METHOD is_ddic_type. + + " Determine if object can be handled by mass activation (see RADMASUTC form ma_tab_check) + + rv_result = abap_true. + + IF c_domain NS iv_obj_type AND c_types NS iv_obj_type AND + c_technset NS iv_obj_type AND c_f4_objects NS iv_obj_type AND + c_enqueue NS iv_obj_type AND c_sqsc NS iv_obj_type AND + c_stob NS iv_obj_type AND c_ntab NS iv_obj_type AND + c_ddls NS iv_obj_type AND c_para NS iv_obj_type AND + c_switches NS iv_obj_type AND iv_obj_type <> c_enhd AND + c_aspect NS iv_obj_type AND c_scalarfunc NS iv_obj_type. + rv_result = abap_false. + ENDIF. + + ENDMETHOD. + METHOD is_non_ddic_active. + + DATA: + lt_messages TYPE STANDARD TABLE OF sprot_u WITH DEFAULT KEY, + ls_e071 TYPE e071, + lt_e071 TYPE STANDARD TABLE OF e071 WITH DEFAULT KEY. + + ls_e071-object = is_item-obj_type. + ls_e071-obj_name = is_item-obj_name. + INSERT ls_e071 INTO TABLE lt_e071. + + CALL FUNCTION 'RS_INACTIVE_OBJECTS_WARNING' + EXPORTING + suppress_protocol = abap_false + with_program_includes = abap_false + suppress_dictionary_check = abap_false + TABLES + p_e071 = lt_e071 + p_xmsg = lt_messages. + + rv_active = boolc( lt_messages IS INITIAL ). + + ENDMETHOD. + METHOD update_where_used. + + DATA: ls_class LIKE LINE OF gt_classes, + lo_cross TYPE REF TO cl_wb_crossreference, + ls_item TYPE zif_abapgit_definitions=>ty_item, + lv_msg TYPE string, + lv_error TYPE c LENGTH 1, + lv_include TYPE syrepid. + + LOOP AT gt_classes INTO ls_class. + CASE ls_class-object. + WHEN 'CLAS'. + lv_include = cl_oo_classname_service=>get_classpool_name( ls_class-clsname ). + WHEN 'INTF'. + lv_include = cl_oo_classname_service=>get_interfacepool_name( ls_class-clsname ). + ENDCASE. + + CREATE OBJECT lo_cross + EXPORTING + p_name = lv_include + p_include = lv_include. + + lo_cross->index_actualize( IMPORTING p_error = lv_error ). + + IF lv_error = abap_true. + ls_item-obj_type = ls_class-object. + ls_item-obj_name = ls_class-clsname. + lv_msg = |Error updating where-used list for { ls_item-obj_type } { ls_item-obj_name }.| + && | Check for syntax errors|. + ii_log->add( + iv_msg = lv_msg + is_item = ls_item ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD use_new_activation_logic. + + IF zcl_abapgit_factory=>get_function_module( )->function_exists( 'DD_MASS_ACT_C3' ) = abap_true. + rv_use_new_activation_logic = abap_true. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ITEM_GRAPH IMPLEMENTATION. + METHOD add_edge. + DATA ls_edge LIKE LINE OF mt_edges. + ASSERT is_from IS NOT INITIAL. + ASSERT is_to IS NOT INITIAL. + ls_edge-from = is_from. + ls_edge-to = is_to. + APPEND ls_edge TO mt_edges. + ENDMETHOD. + METHOD constructor. + INSERT LINES OF it_items INTO TABLE mt_vertices. + ENDMETHOD. + METHOD get_next. +* find a vertex with no inbound edges, if it does not exist pick anything + + DATA ls_vertex LIKE LINE OF mt_vertices. + DATA lv_index TYPE i. + + LOOP AT mt_vertices INTO ls_vertex. + lv_index = sy-tabix. + READ TABLE mt_edges WITH KEY sec_to COMPONENTS + to-obj_type = ls_vertex-obj_type + to-obj_name = ls_vertex-obj_name + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + remove_vertex( lv_index ). + rs_item = ls_vertex. + RETURN. + ENDIF. + ENDLOOP. + + IF mv_warning = abap_false. +* only issue the warning once per graph + ii_log->add_warning( |Cycle detected in item graph| ). + mv_warning = abap_true. + ENDIF. + + READ TABLE mt_vertices INTO rs_item INDEX 1. + ASSERT sy-subrc = 0. + remove_vertex( 1 ). + + ENDMETHOD. + METHOD has_vertices. + rv_bool = boolc( lines( mt_vertices ) > 0 ). + ENDMETHOD. + METHOD remove_vertex. + DATA ls_vertex LIKE LINE OF mt_vertices. + + READ TABLE mt_vertices INDEX iv_index INTO ls_vertex. + ASSERT sy-subrc = 0. + + DELETE mt_vertices INDEX iv_index. + DELETE mt_edges USING KEY sec_from + WHERE from-obj_type = ls_vertex-obj_type + AND from-obj_name = ls_vertex-obj_name. + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlaQDITPzSYObMRZSJHBfBWcKfD DEFINITION DEFERRED. +CLASS kHGwlaQDITPzSYObMRZSnbsvjcJHPG DEFINITION DEFERRED. +* renamed: zcl_abapgit_folder_logic :: lcl_package_to_path +CLASS kHGwlaQDITPzSYObMRZSnbsvjcJHPG DEFINITION. + + PUBLIC SECTION. + + CLASS-METHODS get + IMPORTING + !iv_top TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !iv_package TYPE devclass + RETURNING + VALUE(rv_path) TYPE string. + + CLASS-METHODS add + IMPORTING + !iv_top TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !iv_package TYPE devclass + !iv_path TYPE string. + + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_buffer, + top TYPE devclass, + starting_folder TYPE string, + folder_logic TYPE string, + package TYPE devclass, + path TYPE string, + END OF ty_buffer. + + CLASS-DATA gt_buffer + TYPE HASHED TABLE OF ty_buffer + WITH UNIQUE KEY top starting_folder folder_logic package. + +ENDCLASS. + +CLASS kHGwlaQDITPzSYObMRZSnbsvjcJHPG IMPLEMENTATION. + + METHOD get. + + FIELD-SYMBOLS LIKE LINE OF gt_buffer. + + READ TABLE gt_buffer ASSIGNING WITH TABLE KEY + top = iv_top + starting_folder = io_dot->get_starting_folder( ) + folder_logic = io_dot->get_folder_logic( ) + package = iv_package. + IF sy-subrc = 0. + rv_path = -path. + ENDIF. + + ENDMETHOD. + + METHOD add. + + DATA ls_buffer LIKE LINE OF gt_buffer. + + CLEAR ls_buffer. + ls_buffer-top = iv_top. + ls_buffer-starting_folder = io_dot->get_starting_folder( ). + ls_buffer-folder_logic = io_dot->get_folder_logic( ). + ls_buffer-package = iv_package. + ls_buffer-path = iv_path. + INSERT ls_buffer INTO TABLE gt_buffer. + + ENDMETHOD. + +ENDCLASS. + +* renamed: zcl_abapgit_folder_logic :: lcl_path_to_package +CLASS kHGwlaQDITPzSYObMRZSJHBfBWcKfD DEFINITION. + + PUBLIC SECTION. + + CLASS-METHODS get + IMPORTING + !iv_top TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !iv_path TYPE string + RETURNING + VALUE(rv_package) TYPE devclass. + + CLASS-METHODS add + IMPORTING + !iv_top TYPE devclass + !io_dot TYPE REF TO zcl_abapgit_dot_abapgit + !iv_path TYPE string + !iv_package TYPE devclass. + + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_buffer, + top TYPE devclass, + starting_folder TYPE string, + folder_logic TYPE string, + path TYPE string, + package TYPE devclass, + END OF ty_buffer. + + CLASS-DATA gt_buffer + TYPE HASHED TABLE OF ty_buffer + WITH UNIQUE KEY top starting_folder folder_logic path. + +ENDCLASS. + +CLASS kHGwlaQDITPzSYObMRZSJHBfBWcKfD IMPLEMENTATION. + + METHOD get. + + FIELD-SYMBOLS LIKE LINE OF gt_buffer. + + READ TABLE gt_buffer ASSIGNING WITH TABLE KEY + top = iv_top + starting_folder = io_dot->get_starting_folder( ) + folder_logic = io_dot->get_folder_logic( ) + path = iv_path. + IF sy-subrc = 0. + rv_package = -package. + RETURN. + ENDIF. + + ENDMETHOD. + + METHOD add. + + DATA ls_buffer LIKE LINE OF gt_buffer. + + CLEAR ls_buffer. + ls_buffer-top = iv_top. + ls_buffer-starting_folder = io_dot->get_starting_folder( ). + ls_buffer-folder_logic = io_dot->get_folder_logic( ). + ls_buffer-path = iv_path. + ls_buffer-package = iv_package. + INSERT ls_buffer INTO TABLE gt_buffer. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_folder_logic IMPLEMENTATION. + METHOD get_instance. + CREATE OBJECT ro_instance. + ENDMETHOD. + METHOD get_parent. + DATA: ls_parent LIKE LINE OF mt_parent. + + " Check that package is included in the TOP package hierarchy + IF mt_top_subpackages IS INITIAL. + mt_top_subpackages = zcl_abapgit_factory=>get_sap_package( iv_top )->list_subpackages( ). + ENDIF. + + READ TABLE mt_top_subpackages TRANSPORTING NO FIELDS WITH KEY devclass = iv_package. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + "Determine Parent Package + READ TABLE mt_parent INTO ls_parent + WITH TABLE KEY devclass = iv_package. + IF sy-subrc <> 0. + rv_parent = zcl_abapgit_factory=>get_sap_package( iv_package )->read_parent( ). + ls_parent-devclass = iv_package. + ls_parent-parentcl = rv_parent. + INSERT ls_parent INTO TABLE mt_parent. + ELSE. + rv_parent = ls_parent-parentcl. + ENDIF. + ENDMETHOD. + METHOD package_to_path. + + DATA: lv_len TYPE i, + lv_path TYPE string, + lv_message TYPE string, + lv_parentcl TYPE tdevc-parentcl, + lv_folder_logic TYPE string. + + rv_path = kHGwlaQDITPzSYObMRZSnbsvjcJHPG=>get( + iv_top = iv_top + io_dot = io_dot + iv_package = iv_package ). + IF rv_path IS NOT INITIAL. + RETURN. + ENDIF. + + IF iv_top = iv_package. + rv_path = io_dot->get_starting_folder( ). + ELSE. + lv_parentcl = get_parent( + iv_top = iv_top + iv_package = iv_package ). + + " If the parent package can not be determined, we return an initial path and handle + " it outside of this class (in zcl_abapgit_file_status) + IF lv_parentcl IS NOT INITIAL. + lv_folder_logic = io_dot->get_folder_logic( ). + CASE lv_folder_logic. + WHEN zif_abapgit_dot_abapgit=>c_folder_logic-full. + lv_len = 0. + IF iv_package(1) = '$'. + lv_len = 1. + ENDIF. + WHEN zif_abapgit_dot_abapgit=>c_folder_logic-prefix. + lv_len = strlen( lv_parentcl ). + + IF iv_package(lv_len) <> lv_parentcl. + " If abapGit project is installed in package ZZZ, all subpackages should be named + " ZZZ_something. This will define the folder name in the zip file to be "something", + " similarly with online projects. Alternatively change to FULL folder logic + lv_message = |PREFIX: Unexpected package naming | + && |(top: { iv_top }, parent: { lv_parentcl }, child: { iv_package }). | + && |Try using the folder logic FULL|. + zcx_abapgit_exception=>raise( lv_message ). + ENDIF. + WHEN zif_abapgit_dot_abapgit=>c_folder_logic-mixed. + lv_len = strlen( iv_top ). + + IF iv_package(lv_len) <> iv_top. + lv_message = |MIXED: Unexpected package naming | + && |(top: { iv_top }, parent: { lv_parentcl }, child: { iv_package }). | + && |Try using the folder logic FULL|. + zcx_abapgit_exception=>raise( lv_message ). + ENDIF. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Invalid folder logic: { lv_folder_logic }| ). + ENDCASE. + + lv_path = iv_package+lv_len. + IF strlen( lv_path ) = 0. + zcx_abapgit_exception=>raise( |Folder logic: length = 0, parent: { + lv_parentcl }, child: { iv_package }| ). + ENDIF. + + IF lv_path(1) = '_'. + lv_path = lv_path+1. + ENDIF. + IF strlen( lv_path ) = 0. + zcx_abapgit_exception=>raise( |Folder logic: length = 0, parent: { + lv_parentcl }, child: { iv_package }| ). + ENDIF. + + TRANSLATE lv_path USING '/#'. + TRANSLATE lv_path TO LOWER CASE. + CONCATENATE lv_path '/' INTO lv_path. + + rv_path = package_to_path( iv_top = iv_top + io_dot = io_dot + iv_package = lv_parentcl ). + + CONCATENATE rv_path lv_path INTO rv_path. + ENDIF. + ENDIF. + + kHGwlaQDITPzSYObMRZSnbsvjcJHPG=>add( + iv_top = iv_top + io_dot = io_dot + iv_package = iv_package + iv_path = rv_path ). + + ENDMETHOD. + METHOD path_to_package. + + DATA: lv_length TYPE i, + lv_parent TYPE devclass, + ls_package TYPE zif_abapgit_sap_package=>ty_create, + lv_new TYPE string, + lv_path TYPE string, + lv_absolute_name TYPE string, + lv_folder_logic TYPE string, + lt_unique_package_names TYPE HASHED TABLE OF devclass WITH UNIQUE KEY table_line. + + lv_length = strlen( io_dot->get_starting_folder( ) ). + IF lv_length > strlen( iv_path ). +* treat as not existing locally + RETURN. + ENDIF. + + rv_package = kHGwlaQDITPzSYObMRZSJHBfBWcKfD=>get( + iv_top = iv_top + io_dot = io_dot + iv_path = iv_path ). + IF rv_package IS NOT INITIAL AND iv_create_if_not_exists = abap_false. + RETURN. + ENDIF. + + lv_path = iv_path+lv_length. + lv_parent = iv_top. + rv_package = iv_top. + + " Automatically create package using minimal properties + " Details will be updated during deserialization + IF iv_create_if_not_exists = abap_true. + IF iv_top(1) = '$'. + zcl_abapgit_factory=>get_sap_package( iv_top )->create_local( ). + ELSE. + ls_package-devclass = iv_top. + ls_package-ctext = iv_top. + ls_package-as4user = sy-uname. + zcl_abapgit_factory=>get_sap_package( iv_top )->create( ls_package ). + ENDIF. + ENDIF. + + INSERT iv_top INTO TABLE lt_unique_package_names. + + WHILE lv_path CA '/'. + SPLIT lv_path AT '/' INTO lv_new lv_path. + + lv_folder_logic = io_dot->get_folder_logic( ). + CASE lv_folder_logic. + WHEN zif_abapgit_dot_abapgit=>c_folder_logic-full. + lv_absolute_name = lv_new. + TRANSLATE lv_absolute_name USING '#/'. + IF iv_top(1) = '$'. + CONCATENATE '$' lv_absolute_name INTO lv_absolute_name. + ENDIF. + WHEN zif_abapgit_dot_abapgit=>c_folder_logic-prefix. + CONCATENATE rv_package '_' lv_new INTO lv_absolute_name. + WHEN zif_abapgit_dot_abapgit=>c_folder_logic-mixed. + CONCATENATE iv_top '_' lv_new INTO lv_absolute_name. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Invalid folder logic: { lv_folder_logic }| ). + ENDCASE. + + TRANSLATE lv_absolute_name TO UPPER CASE. + + IF strlen( lv_absolute_name ) > 30. + zcx_abapgit_exception=>raise( |Package { lv_absolute_name } exceeds ABAP 30-characters name limit| ). + ENDIF. + + rv_package = lv_absolute_name. + READ TABLE lt_unique_package_names TRANSPORTING NO FIELDS + WITH TABLE KEY table_line = rv_package. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( |Package { rv_package } has a subpackage with the same name| ). + ELSE. + INSERT rv_package INTO TABLE lt_unique_package_names. + ENDIF. + + IF zcl_abapgit_factory=>get_sap_package( rv_package )->exists( ) = abap_false AND + iv_create_if_not_exists = abap_true. + + zcl_abapgit_factory=>get_sap_package( lv_parent )->create_child( rv_package ). + ENDIF. + + lv_parent = rv_package. + ENDWHILE. + + kHGwlaQDITPzSYObMRZSJHBfBWcKfD=>add( + iv_top = iv_top + io_dot = io_dot + iv_path = iv_path + iv_package = rv_package ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_FILENAME_LOGIC IMPLEMENTATION. + METHOD detect_obj_definition. + + ev_is_xml = boolc( iv_ext = to_upper( c_package_file-extension ) AND strlen( iv_type ) = 4 ). + ev_is_json = boolc( iv_ext = to_upper( c_json_file-extension ) AND strlen( iv_type ) = 4 ). + + ENDMETHOD. + METHOD file_to_object. + + DATA: + lv_name TYPE string, + lv_type TYPE string, + lv_ext TYPE string. + + " Guess object type and name + SPLIT iv_filename AT '.' INTO lv_name lv_type lv_ext. + lv_type = to_upper( lv_type ). + lv_ext = to_upper( lv_ext ). + + " Handle namespaces + REPLACE ALL OCCURRENCES OF '#' IN lv_name WITH '/'. + REPLACE ALL OCCURRENCES OF '#' IN lv_type WITH '/'. + REPLACE ALL OCCURRENCES OF '#' IN lv_ext WITH '/'. + + " Assume AFF namespace convention + IF zcl_abapgit_aff_factory=>get_registry( )->is_supported_object_type( |{ lv_type }| ) = abap_true. + REPLACE ALL OCCURRENCES OF '(' IN lv_name WITH '/'. + REPLACE ALL OCCURRENCES OF ')' IN lv_name WITH '/'. + ENDIF. + + " Get original object name + lv_name = name_unescape( lv_name ). + + CLEAR es_item. + es_item-obj_type = lv_type. + es_item-obj_name = to_upper( lv_name ). + + " Get mapping specific to object type + map_filename_to_object( + EXPORTING + iv_item_part_of_filename = lv_name " original-cased object name part only + iv_path = iv_path + io_dot = io_dot + iv_package = iv_devclass + CHANGING + cs_item = es_item ). + + detect_obj_definition( + EXPORTING + iv_ext = lv_ext + iv_type = lv_type + IMPORTING + ev_is_xml = ev_is_xml + ev_is_json = ev_is_json ). + + ENDMETHOD. + METHOD get_lang_and_ext. + + DATA lt_filename_elements TYPE string_table. + DATA lv_lang_suffix TYPE string. + DATA lv_sap1 TYPE sy-langu. + + SPLIT iv_filename AT '.' INTO TABLE lt_filename_elements. + + READ TABLE lt_filename_elements INDEX lines( lt_filename_elements ) INTO ev_ext. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Could not derive file extension of file { iv_filename }| ). + ENDIF. + + READ TABLE lt_filename_elements WITH KEY table_line = `i18n` TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + READ TABLE lt_filename_elements INDEX ( sy-tabix + 1 ) INTO lv_lang_suffix. + IF sy-subrc = 0. + IF ev_ext = `po`. + ev_lang = to_lower( lv_lang_suffix ). + ELSEIF ev_ext = `properties`. + lv_sap1 = zcl_abapgit_convert=>language_bcp47_to_sap1( lv_lang_suffix ). + ev_lang = zcl_abapgit_convert=>language_sap1_to_sap2( lv_sap1 ). " actually it is to_upper( ISO-639 ) + ELSE. + zcx_abapgit_exception=>raise( |Unexpected translation file format { iv_filename }| ). + ENDIF. + ENDIF. + ENDIF. + + IF ev_lang IS INITIAL. + CLEAR ev_ext. + ENDIF. + + ENDMETHOD. + METHOD i18n_file_to_object. + + DATA lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. + + CLEAR: es_item, ev_lang, ev_ext. + lo_dot = zcl_abapgit_dot_abapgit=>build_default( ). + + file_to_object( + EXPORTING + iv_filename = iv_filename + iv_path = iv_path + io_dot = lo_dot + IMPORTING + es_item = es_item ). + + get_lang_and_ext( + EXPORTING + iv_filename = iv_filename + IMPORTING + ev_lang = ev_lang + ev_ext = ev_ext ). + + ENDMETHOD. + METHOD is_obj_definition_file. + + DATA: + lv_xml TYPE abap_bool, + lv_json TYPE abap_bool, + lv_name TYPE string, + lv_type TYPE string, + lv_ext TYPE string. + + SPLIT to_upper( iv_filename ) AT '.' INTO lv_name lv_type lv_ext. + + detect_obj_definition( + EXPORTING + iv_ext = lv_ext + iv_type = lv_type + IMPORTING + ev_is_xml = lv_xml + ev_is_json = lv_json ). + + rv_yes = boolc( lv_json = abap_true OR lv_xml = abap_true ). + + ENDMETHOD. + METHOD map_filename_to_object. + + DATA lv_class TYPE seoclsname. + + " TODO: Add check for supported object types to avoid calls to non-existing classes + " zcl_abapgit_objects=>is_type_supported( is_item-obj_type ) + " This will trigger class constructor of zcl_abapgit_objects_bridge reading table seometarel + " which is currently not supported by abaplint test runner + + TRY. + lv_class = 'ZCL_ABAPGIT_OBJECT_' && cs_item-obj_type. + + CALL METHOD (lv_class)=>('ZIF_ABAPGIT_OBJECT~MAP_FILENAME_TO_OBJECT') + EXPORTING + iv_item_part_of_filename = iv_item_part_of_filename + iv_path = iv_path + io_dot = io_dot + iv_package = iv_package + CHANGING + cs_item = cs_item. + CATCH cx_sy_dyn_call_illegal_class. + " Map data config to TABU object type + IF cs_item-obj_type = 'CONF'. + cs_item-obj_type = 'TABU'. + ENDIF. + ENDTRY. + + ENDMETHOD. + METHOD map_object_to_filename. + + DATA lv_class TYPE seoclsname. + + " TODO: Add check for supported object types to avoid calls to non-existing classes + " zcl_abapgit_objects=>is_type_supported( is_item-obj_type ) + " This will trigger class constructor of zcl_abapgit_objects_bridge reading table seometarel + " which is currently not supported by abaplint test runner + + " TODO: maybe refactor the logic, as currently only 2 object types have own naming + " the map_* methods are static, so they cannot reuse ms_item passed to the class + " and the "custom" naming is scattered among the large codebase + + TRY. + lv_class = 'ZCL_ABAPGIT_OBJECT_' && is_item-obj_type. + + CALL METHOD (lv_class)=>('ZIF_ABAPGIT_OBJECT~MAP_OBJECT_TO_FILENAME') + EXPORTING + is_item = is_item + iv_ext = iv_ext + iv_extra = iv_extra + CHANGING + cv_item_part_of_filename = cv_item_part_of_filename. + CATCH cx_sy_dyn_call_illegal_class ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD name_escape. + " Some characters in object names cause problems when identifying the object later + " -> we escape these characters here + " cl_http_utility=>escape_url doesn't do dots but escapes slash which we use for namespaces + " -> we escape just some selected characters + rv_name = iv_name. + REPLACE ALL OCCURRENCES OF `#` IN rv_name WITH '%23'. + REPLACE ALL OCCURRENCES OF `%` IN rv_name WITH '%25'. + REPLACE ALL OCCURRENCES OF `.` IN rv_name WITH '%2e'. + REPLACE ALL OCCURRENCES OF `<` IN rv_name WITH '%3c'. + REPLACE ALL OCCURRENCES OF `=` IN rv_name WITH '%3d'. + REPLACE ALL OCCURRENCES OF `>` IN rv_name WITH '%3e'. + REPLACE ALL OCCURRENCES OF `?` IN rv_name WITH '%3f'. + ENDMETHOD. + METHOD name_unescape. + " Replace all %xy with encoded character + rv_name = cl_http_utility=>unescape_url( iv_name ). + ENDMETHOD. + METHOD object_to_file. + + DATA lv_obj_name TYPE string. + DATA lv_obj_type TYPE string. + DATA lv_nb_of_slash TYPE string. + DATA lv_keep_case TYPE abap_bool. + + " Get escaped object name + lv_obj_name = to_lower( name_escape( is_item-obj_name ) ). + lv_obj_type = to_lower( is_item-obj_type ). + + rv_filename = lv_obj_name. + + " Get mapping specific to object type + TRY. + map_object_to_filename( + EXPORTING + is_item = is_item + iv_ext = iv_ext + iv_extra = iv_extra + CHANGING + cv_item_part_of_filename = rv_filename ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + CONCATENATE rv_filename '.' lv_obj_type INTO rv_filename. + + IF iv_extra IS NOT INITIAL. + CONCATENATE rv_filename '.' iv_extra INTO rv_filename. + ENDIF. + + IF iv_ext IS NOT INITIAL. + CONCATENATE rv_filename '.' iv_ext INTO rv_filename. + ENDIF. + + IF zcl_abapgit_aff_factory=>get_registry( )->is_supported_object_type( is_item-obj_type ) = abap_true. + FIND ALL OCCURRENCES OF `/` IN rv_filename MATCH COUNT lv_nb_of_slash. + IF lv_nb_of_slash = 2. + REPLACE FIRST OCCURRENCE OF `/` IN rv_filename WITH `(`. + REPLACE `/` IN rv_filename WITH `)`. + ENDIF. + ELSE. + REPLACE ALL OCCURRENCES OF '/' IN rv_filename WITH '#'. + ENDIF. + + IF iv_ext = 'properties'. + lv_keep_case = abap_true. + ENDIF. + + IF lv_keep_case = abap_false. " The default behavior is to lowercase all filenames + TRANSLATE rv_filename TO LOWER CASE. + ENDIF. + + ENDMETHOD. + METHOD object_to_i18n_file. + + rv_filename = object_to_file( + is_item = is_item + iv_extra = |i18n.{ iv_lang_suffix }| + iv_ext = iv_ext ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_file_deserialize IMPLEMENTATION. + METHOD filter_files_to_deserialize. + + DATA lt_objects LIKE rt_results. + DATA lr_object TYPE REF TO zif_abapgit_definitions=>ty_result. + DATA ls_item TYPE zif_abapgit_definitions=>ty_item. + DATA lv_tabix TYPE sy-tabix. + + rt_results = it_results. + + "preparation for object logging, sort all file entries by objects + IF ii_log IS BOUND. + lt_objects = rt_results. + SORT lt_objects + BY obj_type + obj_name. + DELETE ADJACENT DUPLICATES FROM lt_objects COMPARING obj_type obj_name. + DELETE lt_objects WHERE obj_type IS INITIAL AND obj_name IS INITIAL. + ENDIF. + + "ignore objects w/o changes + DELETE rt_results WHERE match = abap_true. " Full match + "log objects w/o changes + IF sy-subrc = 0 AND ii_log IS BOUND. + SORT rt_results BY obj_type obj_name. + LOOP AT lt_objects REFERENCE INTO lr_object. + lv_tabix = sy-tabix. + READ TABLE rt_results WITH KEY obj_type = lr_object->obj_type + obj_name = lr_object->obj_name + BINARY SEARCH TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + "all parts of the objects have not changed + ls_item-devclass = lr_object->package. + ls_item-obj_type = lr_object->obj_type. + ls_item-obj_name = lr_object->obj_name. + ii_log->add_success( + iv_msg = |Object { ls_item-obj_name } (type { ls_item-obj_type }) not changed; no import required| + is_item = ls_item ). + "ignore object for further messages + DELETE lt_objects INDEX lv_tabix. + ENDIF. + ENDLOOP. + ENDIF. + + "ignore objects w/o object type + DELETE rt_results WHERE obj_type IS INITIAL. + "log objects w/o object type + IF sy-subrc = 0 AND ii_log IS BOUND. + " Note: Moving the CHECK condition to the LOOP WHERE clause will lead to a + " syntax warning in higher releases and syntax error in 702 + LOOP AT lt_objects REFERENCE INTO lr_object. + CHECK lr_object->obj_type IS INITIAL AND lr_object->obj_name IS NOT INITIAL. + ls_item-devclass = lr_object->package. + ls_item-obj_type = lr_object->obj_type. + ls_item-obj_name = lr_object->obj_name. + ii_log->add_warning( + iv_msg = |Object type for { ls_item-obj_name } not defined - will be ignored by abapGit| + is_item = ls_item ). + ENDLOOP. + DELETE lt_objects WHERE obj_type IS INITIAL. + ENDIF. + + "ignore objects that exists only local + DELETE rt_results WHERE lstate = zif_abapgit_definitions=>c_state-added AND rstate IS INITIAL. + "ignore objects that where deleted remotely + DELETE rt_results WHERE rstate = zif_abapgit_definitions=>c_state-deleted. + "log objects that exists only local or where deleted remotely + IF sy-subrc = 0 AND ii_log IS BOUND. + SORT rt_results BY obj_type obj_name. + LOOP AT lt_objects REFERENCE INTO lr_object. + lv_tabix = sy-tabix. + READ TABLE rt_results WITH KEY obj_type = lr_object->obj_type + obj_name = lr_object->obj_name + BINARY SEARCH TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + "all parts exists only local + "no log message; ignore object for further messages + DELETE lt_objects INDEX lv_tabix. + ENDIF. + ENDLOOP. + ENDIF. + + "ignore table content + DELETE rt_results WHERE path = zif_abapgit_data_config=>c_default_path. + + SORT rt_results + BY obj_type ASCENDING + obj_name ASCENDING + rstate DESCENDING " ensures that non-empty rstate is kept + lstate DESCENDING. " ensures that non-empty lstate is kept + DELETE ADJACENT DUPLICATES FROM rt_results COMPARING obj_type obj_name. + + ENDMETHOD. + METHOD get_results. + + DATA lt_results TYPE zif_abapgit_definitions=>ty_results_tt. + + lt_results = filter_files_to_deserialize( + it_results = zcl_abapgit_repo_status=>calculate( ii_repo ) + ii_log = ii_log ). + + rt_results = prioritize_deser( + ii_log = ii_log + it_results = lt_results ). + + ENDMETHOD. + METHOD map_results_to_items. + + DATA ls_item LIKE LINE OF rt_items. + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_result. + + LOOP AT it_results ASSIGNING . + ls_item-devclass = -package. + ls_item-obj_type = -obj_type. + ls_item-obj_name = -obj_name. + INSERT ls_item INTO TABLE rt_items. + ENDLOOP. + + ENDMETHOD. + METHOD prioritize_deser. + + DATA lt_items TYPE zif_abapgit_definitions=>ty_items_tt. + DATA ls_item LIKE LINE OF lt_items. + DATA lt_requires TYPE zif_abapgit_definitions=>ty_items_tt. + DATA ls_require LIKE LINE OF lt_requires. + DATA ls_result LIKE LINE OF it_results. + DATA lo_graph TYPE REF TO zcl_abapgit_item_graph. + + lt_items = map_results_to_items( it_results ). + + CREATE OBJECT lo_graph EXPORTING it_items = lt_items. + + LOOP AT lt_items INTO ls_item. + CLEAR lt_requires. + +* TODO: BEGIN extract to object handler method in ZIF_ABAPGIT_OBJECT: +* METHODS get_deserialize_order +* IMPORTING +* it_items TYPE ty_items_tt +* RETURNING +* VALUE(rt_requries) TYPE ty_items_tt + + CASE ls_item-obj_type. + WHEN 'SPRX'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'WEBI'. + WHEN 'CLAS'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'SPRX' + AND obj_type <> 'INTF' + AND obj_type <> 'XSLT'. + WHEN 'PROG'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'XSLT'. + WHEN 'INTF'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'SPRX' + AND obj_type <> 'XSLT'. + WHEN 'HTTP'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'CLAS' AND obj_type <> 'INTF'. + WHEN 'TABL'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'SPRX'. + WHEN 'IARP'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'IASP'. + WHEN 'IATU' OR 'IAXU' OR 'IAMU'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'IASP' + AND obj_type <> 'PROG' + AND obj_type <> 'IARP'. + WHEN 'IDOC' OR 'IEXT'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'TABL'. + WHEN 'DCLS'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'DDLS'. + WHEN 'ODSO'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'IOBJ'. + WHEN 'SCP1'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'TOBJ'. + WHEN 'CHAR'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'OTGR'. + WHEN 'PINF'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'CLAS' + AND obj_type <> 'INTF' + AND obj_type <> 'TABL' + AND obj_type <> 'DOMA' + AND obj_type <> 'DTEL'. + WHEN 'DEVC'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'PINF'. + WHEN 'ENHC'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'ENHO'. + WHEN 'ENHO'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'ENSC' AND obj_type <> 'ENHS'. + WHEN 'ENSC'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'ENHS'. + WHEN 'IWMO' OR 'IWSV' OR 'IWVB'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'SRVB'. + WHEN 'SUSH'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'SRVB' AND obj_type <> 'HTTP'. + WHEN 'SRVB'. + lt_requires = lt_items. + DELETE lt_requires WHERE obj_type <> 'SRVD'. + ENDCASE. +* TODO: END extract to object handler method + + LOOP AT lt_requires INTO ls_require. + lo_graph->add_edge( + is_from = ls_require + is_to = ls_item ). + ENDLOOP. + ENDLOOP. + + WHILE lo_graph->has_vertices( ) = abap_true. + ls_item = lo_graph->get_next( ii_log ). + READ TABLE it_results INTO ls_result WITH KEY sec_key COMPONENTS + obj_name = ls_item-obj_name + obj_type = ls_item-obj_type. + ASSERT sy-subrc = 0. + APPEND ls_result TO rt_results. + ENDWHILE. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_dependencies IMPLEMENTATION. + METHOD get_ddls_dependencies. + + DATA: lt_ddls_name TYPE TABLE OF ddsymtab, + ls_ddls_name TYPE ddsymtab. + + ls_ddls_name-name = iv_ddls_name. + INSERT ls_ddls_name INTO TABLE lt_ddls_name. + + PERFORM ('DDLS_GET_DEP') IN PROGRAM ('RADMASDL') + TABLES lt_ddls_name rt_dependency ##PERF_NO_FORM. + + ENDMETHOD. + METHOD resolve. + + DATA: lv_tabclass TYPE dd02l-tabclass. + + FIELD-SYMBOLS: LIKE LINE OF ct_tadir. + + " misuse field KORRNUM to fix deletion sequence + " higher value means later deletion + + LOOP AT ct_tadir ASSIGNING . + CASE -object. + WHEN 'DEVC'. + " Packages last + -korrnum = '999000'. + WHEN 'DOMA'. + -korrnum = '900000'. + WHEN 'SPRX'. + -korrnum = '850000'. + WHEN 'WEBI'. + -korrnum = '840000'. + WHEN 'PARA'. + " PARA after DTEL + -korrnum = '810000'. + WHEN 'DTEL'. + -korrnum = '800000'. + WHEN 'SHLP'. + " SHLP after TABL + -korrnum = '760000'. + WHEN 'TTYP' OR 'TABL' OR 'VIEW'. + SELECT SINGLE tabclass FROM dd02l + INTO lv_tabclass + WHERE tabname = -obj_name + AND as4local = 'A' + AND as4vers = '0000'. + IF sy-subrc = 0 AND lv_tabclass = 'APPEND'. + " delete append structures before database tables + -korrnum = '730000'. + ELSE. + -korrnum = '750000'. + ENDIF. + WHEN 'ENQU'. + " ENQU before TABL + -korrnum = '725000'. + WHEN 'DDLS'. + " DDLS after DCLS but before other DDIC + -korrnum = '720000'. + WHEN 'DDLX'. + " DDLX before DDLS + -korrnum = '719000'. + WHEN 'AUTH'. + " AUTH after DCLS + -korrnum = '715000'. + WHEN 'SUSH'. + " SUSH after SUSC and SRVB + -korrnum = '712000'. + WHEN 'SUSC'. + " SUSC after SUSO + -korrnum = '711000'. + WHEN 'SUSO'. + " SUSO after DCLS + -korrnum = '710000'. + WHEN 'DCLS'. + " AUTH and SUSO after DCLS + -korrnum = '705000'. + WHEN 'G4BA' OR 'G4BS' OR 'IWMO' OR 'IWSV' OR 'IWVB'. + " after SRVB + -korrnum = '610000'. + WHEN 'SRVB'. + " after SRVD + -korrnum = '600500'. + WHEN 'SRVD'. + -korrnum = '600000'. + WHEN 'IASP'. + -korrnum = '552000'. + WHEN 'IARP'. + -korrnum = '551000'. + WHEN 'IATU'. + -korrnum = '550000'. + WHEN 'ACID'. + " ACID after PROG/FUGR/CLAS + -korrnum = '300000'. + WHEN 'FUGR'. + -korrnum = '260000'. + WHEN 'PROG'. + " delete includes after main programs + SELECT COUNT(*) FROM reposrc + WHERE progname = -obj_name + AND r3state = 'A' + AND subc = 'I'. + IF sy-subrc = 0. + -korrnum = '250000'. + ELSE. + -korrnum = '240000'. + ENDIF. + WHEN 'INTF'. + -korrnum = '230000'. + WHEN 'CLAS'. + -korrnum = '220000'. + WHEN 'IDOC'. + -korrnum = '200000'. + WHEN 'IOBJ'. + -korrnum = '195000'. + WHEN 'ODSO'. + -korrnum = '190000'. + WHEN 'WDCA'. + -korrnum = '174000'. + WHEN 'WDYA'. + -korrnum = '173000'. + WHEN 'WDCC'. + -korrnum = '172000'. + WHEN 'WDYN'. + -korrnum = '171000'. + WHEN 'IEXT'. + -korrnum = '150000'. + WHEN 'SAPC'. + " SAPC after SICF + -korrnum = '140000'. + WHEN 'PINF'. + " PINF before exposed objects + -korrnum = '130000'. + WHEN OTHERS. + -korrnum = '100000'. + ENDCASE. + ENDLOOP. + + resolve_ddic( CHANGING ct_tadir = ct_tadir ). + resolve_packages( CHANGING ct_tadir = ct_tadir ). + + SORT ct_tadir BY korrnum ASCENDING. + + ENDMETHOD. + METHOD resolve_ddic. +* this will make sure the deletion sequence of structures/tables work +* in case they have dependencies with .INCLUDE + + TYPES: BEGIN OF ty_edge, + from TYPE ty_item, + to TYPE ty_item, + END OF ty_edge. + + DATA: lt_nodes TYPE TABLE OF ty_item, + lt_edges TYPE TABLE OF ty_edge, + lt_findstrings TYPE TABLE OF rsfind, + lv_plus TYPE i VALUE 1, + lv_find_obj_cls TYPE euobj-id, + lv_index TYPE i, + lv_before TYPE i, + lt_founds TYPE TABLE OF rsfindlst, + lt_scope TYPE STANDARD TABLE OF seu_obj, + lt_dependency TYPE ty_dedenpencies. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_tadir, + TYPE ty_dependency, + TYPE zif_abapgit_definitions=>ty_tadir, + LIKE LINE OF ct_tadir, + LIKE LINE OF lt_edges, + LIKE LINE OF lt_founds, + LIKE LINE OF lt_nodes. + + " build nodes + LOOP AT ct_tadir ASSIGNING + WHERE object = 'TABL' + OR object = 'VIEW' + OR object = 'TTYP'. + APPEND INITIAL LINE TO lt_nodes ASSIGNING . + -obj_name = -obj_name. + -obj_type = -object. + ENDLOOP. + + APPEND 'TABL' TO lt_scope. + APPEND 'VIEW' TO lt_scope. + APPEND 'STRU' TO lt_scope. + APPEND 'TTYP' TO lt_scope. + + " build edges + LOOP AT lt_nodes ASSIGNING . + + CLEAR lt_findstrings. + APPEND -obj_name TO lt_findstrings. + lv_find_obj_cls = -obj_type. + + CALL FUNCTION 'RS_EU_CROSSREF' + EXPORTING + i_find_obj_cls = lv_find_obj_cls + TABLES + i_findstrings = lt_findstrings + o_founds = lt_founds + i_scope_object_cls = lt_scope + EXCEPTIONS + not_executed = 1 + not_found = 2 + illegal_object = 3 + no_cross_for_this_object = 4 + batch = 5 + batchjob_error = 6 + wrong_type = 7 + object_not_exist = 8 + OTHERS = 9. + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + + LOOP AT lt_founds ASSIGNING . + APPEND INITIAL LINE TO lt_edges ASSIGNING . + -from = . + + -to-obj_name = -object. + CASE -object_cls. + WHEN 'DS' + OR 'DT'. + -to-obj_type = 'TABL'. + WHEN 'DV'. + -to-obj_type = 'VIEW'. + WHEN 'DA'. + -to-obj_type = 'TTYP'. + WHEN OTHERS. + zcx_abapgit_exception=>raise( 'resolve_ddic, unknown object_cls' ). + ENDCASE. + ENDLOOP. + + ENDLOOP. + + " build DDLS edges + SORT ct_tadir. "binary search + LOOP AT ct_tadir ASSIGNING + WHERE object = 'DDLS'. + + CLEAR: lt_dependency. + + APPEND INITIAL LINE TO lt_nodes ASSIGNING . + -obj_name = -obj_name. + -obj_type = -object. + + lt_dependency = get_ddls_dependencies( -obj_name ). + + LOOP AT lt_dependency ASSIGNING + WHERE deptyp = 'DDLS' + AND refname = -obj_name. + + READ TABLE ct_tadir ASSIGNING + WITH KEY pgmid = 'R3TR' + object = 'DDLS' + obj_name = -depname + BINARY SEARCH. + CHECK sy-subrc = 0. + + APPEND INITIAL LINE TO lt_edges ASSIGNING . + -from = . + -to-obj_name = -depname. + -to-obj_type = 'DDLS'. + + ENDLOOP. + + ENDLOOP. + + DO. + lv_before = lines( lt_nodes ). + LOOP AT lt_nodes ASSIGNING . + lv_index = sy-tabix. + READ TABLE lt_edges WITH KEY + from-obj_name = -obj_name + from-obj_type = -obj_type + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + LOOP AT ct_tadir ASSIGNING + WHERE obj_name = -obj_name + AND object = -obj_type. + -korrnum = -korrnum + lv_plus. + CONDENSE -korrnum. + ENDLOOP. + DELETE lt_edges + WHERE to-obj_name = -obj_name + AND to-obj_type = -obj_type. + DELETE lt_nodes INDEX lv_index. + EXIT. " make sure the sequence is fixed + ENDIF. + ENDLOOP. + IF lv_before = lines( lt_nodes ). + EXIT. + ENDIF. + lv_plus = lv_plus + 1. + ENDDO. + + ENDMETHOD. + METHOD resolve_packages. + + DATA: lt_subpackages TYPE zif_abapgit_sap_package=>ty_devclass_tt. + + FIELD-SYMBOLS: LIKE LINE OF ct_tadir, + LIKE LINE OF lt_subpackages, + LIKE LINE OF ct_tadir. + + " List subpackage before corresponding superpackage + + LOOP AT ct_tadir ASSIGNING + WHERE object = 'DEVC'. + + lt_subpackages = zcl_abapgit_factory=>get_sap_package( |{ -obj_name }| )->list_subpackages( ). + + LOOP AT lt_subpackages ASSIGNING . + + READ TABLE ct_tadir ASSIGNING + WITH KEY object = 'DEVC' + obj_name = . + IF sy-subrc = 0. + -korrnum = condense( |{ -korrnum - 1 }| ). + ENDIF. + + ENDLOOP. + + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_uist IMPLEMENTATION. + + METHOD constructor. + + DATA: lo_db_api TYPE REF TO object, + lr_data TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE OBJECT lo_db_api TYPE ('/UI2/CL_UIST_SVAL_SQL'). + CREATE DATA lr_data TYPE ('CL_BLUE_AFF_WB_ACCESS=>TY_METADATA'). + CATCH cx_sy_create_object_error + cx_sy_create_data_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_db_api TYPE REF TO object, + lr_data TYPE REF TO data, + lv_object_key TYPE seu_objkey, + lx_root TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + TRY. + CREATE OBJECT lo_db_api TYPE ('/UI2/CL_UIST_SVAL_SQL'). + CREATE DATA lr_data TYPE ('CL_BLUE_AFF_WB_ACCESS=>TY_METADATA'). + ASSIGN lr_data->* TO . + CATCH cx_sy_create_object_error + cx_sy_create_data_error. + zcx_abapgit_exception=>raise( 'Object UIST not supported' ). + ENDTRY. + + TRY. + lv_object_key = ms_item-obj_name. + CALL METHOD lo_db_api->('/UI2/IF_UIST_SVAL~GET_METADATA') + EXPORTING + object_name = lv_object_key + version = 'A' + language = mv_language + RECEIVING + result = . + + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + rv_user = . + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_uipg IMPLEMENTATION. + + METHOD constructor. + + DATA: lo_db_api TYPE REF TO object, + lr_data TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CALL METHOD ('/UI2/CL_UIPG_DB_ACCESS')=>('GET_INSTANCE') + RECEIVING + ro_instance = lo_db_api. + CREATE DATA lr_data TYPE ('CL_BLUE_AFF_WB_ACCESS=>TY_METADATA'). + CATCH cx_sy_dyn_call_error + cx_sy_create_data_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_db_api TYPE REF TO object, + lr_data TYPE REF TO data, + lv_object_key TYPE c LENGTH 35, + lx_root TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + TRY. + CALL METHOD ('/UI2/CL_UIPG_DB_ACCESS')=>('GET_INSTANCE') + RECEIVING + ro_instance = lo_db_api. + CREATE DATA lr_data TYPE ('CL_BLUE_AFF_WB_ACCESS=>TY_METADATA'). + ASSIGN lr_data->* TO . + CATCH cx_sy_create_object_error + cx_sy_create_data_error. + zcx_abapgit_exception=>raise( 'Object UIPG not supported' ). + ENDTRY. + + TRY. + lv_object_key = ms_item-obj_name. + CALL METHOD lo_db_api->('/UI2/IF_UIPG_DB_ACCESS~READ_WB_METADATA') + EXPORTING + iv_page_id = lv_object_key + iv_version = 'A' + iv_language = mv_language + RECEIVING + rs_metadata = . + + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + rv_user = . + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_uiad IMPLEMENTATION. + + METHOD constructor. + + DATA: lo_db_api TYPE REF TO object, + lr_data TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CALL METHOD ('CL_SUI_UIAD_DB_ACCESS')=>('GET_INSTANCE') + RECEIVING + ro_instance = lo_db_api. + CREATE DATA lr_data TYPE ('CL_BLUE_AFF_WB_ACCESS=>TY_METADATA'). + CATCH cx_sy_dyn_call_error + cx_sy_create_data_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_db_api TYPE REF TO object, + lr_data TYPE REF TO data, + lv_object_key TYPE c LENGTH 32, + lx_root TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + CALL METHOD ('CL_SUI_UIAD_DB_ACCESS')=>('GET_INSTANCE') + RECEIVING + ro_instance = lo_db_api. + CREATE DATA lr_data TYPE ('CL_BLUE_AFF_WB_ACCESS=>TY_METADATA'). + ASSIGN lr_data->* TO . + + TRY. + lv_object_key = ms_item-obj_name. + CALL METHOD lo_db_api->('IF_SUI_UIAD_DB_ACCESS~READ_WB_METADATA') + EXPORTING + iv_id = lv_object_key + iv_version = 'A' + iv_language = mv_language + RECEIVING + rs_metadata = . + + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + rv_user = . + + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise_with_text( lx_root ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_swcr IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lr_data TYPE REF TO data, + lo_swcr_db_api TYPE REF TO object, + lv_name TYPE c LENGTH 30, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + TRY. + CALL METHOD ('CL_SCR_DB_ACCESS')=>('CREATE_INSTANCE') + RECEIVING + result = lo_swcr_db_api. + CREATE DATA lr_data TYPE ('IF_SCR_TYPES=>TY_S_HEADER'). + ASSIGN lr_data->* TO . + + lv_name = ms_item-obj_name. + + TRY. + CALL METHOD lo_swcr_db_api->('IF_SCR_DB_ACCESS~READ_HEADER') + EXPORTING + software_component = lv_name + version = 'A' + RECEIVING + result = . + CATCH cx_root. " no active version found, try to find an inactive version + CALL METHOD lo_swcr_db_api->('IF_SCR_DB_ACCESS~READ_HEADER') + EXPORTING + software_component = lv_name + version = 'I' + RECEIVING + result = . + ENDTRY. + + ASSIGN COMPONENT 'LAST_CHANGED_BY' OF STRUCTURE TO . + rv_user = . + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise( iv_text = lx_error->get_text( ) + ix_previous = lx_error ). + ENDTRY. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_object_smbc IMPLEMENTATION. + + METHOD constructor. + + DATA: lo_handler TYPE REF TO object, + lo_db_api TYPE REF TO object, + lr_data TYPE REF TO data. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + TRY. + CREATE OBJECT lo_handler TYPE ('CL_SMBC_AFF_OBJECT_HANDLER'). + CREATE OBJECT lo_db_api TYPE ('CL_MBC_BUSINESS_CONFIG_DB'). + CREATE DATA lr_data TYPE ('SMBC_CONFIG'). + CATCH cx_sy_create_object_error + cx_sy_create_data_error. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_handler TYPE REF TO object, + lo_db_api TYPE REF TO object, + lr_data TYPE REF TO data, + lv_technical_id TYPE c LENGTH 30. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + CREATE OBJECT lo_handler TYPE ('CL_SMBC_AFF_OBJECT_HANDLER'). + CREATE OBJECT lo_db_api TYPE ('CL_MBC_BUSINESS_CONFIG_DB'). + CREATE DATA lr_data TYPE ('SMBC_CONFIG'). + ASSIGN lr_data->* TO . + + lv_technical_id = ms_item-obj_name. + CALL METHOD lo_db_api->('IF_MBC_BUSINESS_CONFIG_DB~READ') + EXPORTING + iv_technical_id = lv_technical_id + version = 'I' + RECEIVING + rs_config = . + IF IS INITIAL. + CALL METHOD lo_db_api->('IF_MBC_BUSINESS_CONFIG_DB~READ') + EXPORTING + iv_technical_id = lv_technical_id + version = 'A' + RECEIVING + rs_config = . + ENDIF. + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + rv_user = . + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_sajt IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + CONSTANTS lc_table_name TYPE tabname VALUE 'APJ_W_JT_ROOT'. + + SELECT SINGLE lst_ch_user_acct + FROM (lc_table_name) + INTO rv_user + WHERE job_template_name = ms_item-obj_name + AND job_template_version = 'I'. + + IF rv_user IS INITIAL. + SELECT SINGLE lst_ch_user_acct + FROM (lc_table_name) + INTO rv_user + WHERE job_template_name = ms_item-obj_name + AND job_template_version = 'A'. + ENDIF. + + ENDMETHOD. + + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_SAJC IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + CONSTANTS lc_table_name TYPE tabname VALUE 'APJ_W_JCE_ROOT'. + + SELECT SINGLE lst_ch_user_acct + FROM (lc_table_name) + INTO rv_user + WHERE job_catalog_entry_name = ms_item-obj_name + AND job_catalog_entry_version = 'I'. + + IF rv_user IS INITIAL. + SELECT SINGLE lst_ch_user_acct + FROM (lc_table_name) + INTO rv_user + WHERE job_catalog_entry_name = ms_item-obj_name + AND job_catalog_entry_version = 'A'. + ENDIF. + ENDMETHOD. + + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_ront IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + DATA: lv_user TYPE string, + lx_error TYPE REF TO cx_root. + + TRY. + + SELECT SINGLE changed_by INTO lv_user + FROM (c_table_name) + WHERE ront_name = ms_item-obj_name AND version = 'I'. + + IF lv_user IS INITIAL. + SELECT SINGLE changed_by INTO lv_user + FROM (c_table_name) + WHERE ront_name = ms_item-obj_name AND version = 'A'. + ENDIF. + + rv_user = lv_user. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_nont IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + DATA: lv_user TYPE string, + lx_error TYPE REF TO cx_root. + + TRY. + + SELECT SINGLE changed_by INTO lv_user + FROM (c_table_name) + WHERE nont_name = ms_item-obj_name AND version = 'I'. + + IF lv_user IS INITIAL. + SELECT SINGLE changed_by INTO lv_user + FROM (c_table_name) + WHERE nont_name = ms_item-obj_name AND version = 'A'. + ENDIF. + + rv_user = lv_user. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_GSMP IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA lv_name TYPE c LENGTH 180. + DATA lv_user TYPE string. + DATA lx_root TYPE REF TO cx_root. + TRY. + lv_name = ms_item-obj_name. + + SELECT SINGLE changed_by INTO lv_user + FROM ('GSM_MD_PRV_W') + WHERE provider_id = lv_name AND version = 'I'. + + IF lv_user IS INITIAL. + SELECT SINGLE changed_by INTO lv_user + FROM ('GSM_MD_PRV_W') + WHERE provider_id = lv_name AND version = 'A'. + ENDIF. + + rv_user = lv_user. + CATCH cx_root INTO lx_root. + zcx_abapgit_exception=>raise( iv_text = lx_root->get_text( ) + ix_previous = lx_root ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_evtb IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_user TYPE string, + lx_error TYPE REF TO cx_root. + + TRY. + + SELECT SINGLE changed_by INTO lv_user + FROM (c_table_name) + WHERE evtb_name = ms_item-obj_name AND version = 'I'. + + IF lv_user IS INITIAL. + SELECT SINGLE changed_by INTO lv_user + FROM (c_table_name) + WHERE evtb_name = ms_item-obj_name AND version = 'A'. + ENDIF. + + rv_user = lv_user. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_eeec IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lr_data TYPE REF TO data, + lo_registry_adapter TYPE REF TO object, + lv_object_key TYPE seu_objkey, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + TRY. + CREATE OBJECT lo_registry_adapter TYPE ('/IWXBE/CL_EEEC_REG_ADAPTER'). + CREATE DATA lr_data TYPE ('/IWXBE/IF_REGISTRY_TYPES=>TY_S_CONSUMER'). + ASSIGN lr_data->* TO . + + lv_object_key = ms_item-obj_name. + + TRY. + CALL METHOD lo_registry_adapter->('/IWXBE/IF_EEEC_REG_ADAPTER_WB~GET_METADATA') + EXPORTING + iv_object_key = lv_object_key + iv_state = 'I' + RECEIVING + rs_consumer = . + + CATCH cx_root. + CALL METHOD lo_registry_adapter->('/IWXBE/IF_EEEC_REG_ADAPTER_WB~GET_METADATA') + EXPORTING + iv_object_key = lv_object_key + iv_state = 'A' + RECEIVING + rs_consumer = . + ENDTRY. + + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + rv_user = . + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise( iv_text = lx_error->get_text( ) + ix_previous = lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD get_object_handler. + + DATA lx_error TYPE REF TO cx_root. + + ro_object_handler = super->get_object_handler( ). + + IF ro_object_handler IS NOT BOUND. + TRY. + CREATE OBJECT ro_object_handler TYPE ('/IWXBE/CL_EEEC_AFF_OBJECTHANDL'). + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise( iv_text = lx_error->get_text( ) + ix_previous = lx_error ). + ENDTRY. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_dteb IMPLEMENTATION. + METHOD get_additional_extensions. + + DATA ls_additional_extension LIKE LINE OF rv_additional_extensions. + ls_additional_extension-extension = 'acds'. + CALL METHOD ('CL_CDS_AFF_FILE_NAME_MAPPER')=>for_cds + RECEIVING + result = ls_additional_extension-file_name_mapper. + APPEND ls_additional_extension TO rv_additional_extensions. + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_dteb_handler TYPE REF TO object, + lv_object_key TYPE seu_objkey, + lx_error TYPE REF TO cx_root. + + TRY. + lv_object_key = ms_item-obj_name. + CALL METHOD ('CL_DDIC_ADT_DT_UTILITY')=>('CREATE_DD_DTEB_HANDLER') + EXPORTING + object_key = lv_object_key + RECEIVING + handler = lo_dteb_handler. + + CALL METHOD lo_dteb_handler->('GET_CHANGED_BY') + RECEIVING + rv_changed_by = rv_user. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_dsfi IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_dsfi_handler TYPE REF TO object, + lo_dsfi_source_container TYPE REF TO object, + lv_object_key TYPE seu_objkey, + lv_exists TYPE abap_bool, + lx_error TYPE REF TO cx_root. + FIELD-SYMBOLS: TYPE any. + + TRY. + lv_object_key = ms_item-obj_name. + CALL METHOD ('CL_DSFI_AFF_OBJECT_HANDLER')=>('GET_DDIC_HANDLER') + EXPORTING + object_key = lv_object_key + RECEIVING + handler = lo_dsfi_handler. + + ASSIGN ('CE_DD_DSFI_AS4LOCAL=>EN_STATE-ACTIVE') + TO . + IF sy-subrc = 0. + CALL METHOD lo_dsfi_handler->('IF_DD_DSFI_WB_HANDLER~CHECK_EXISTENCE') + EXPORTING + iv_as4local = + RECEIVING + rv_exists = lv_exists. + + IF lv_exists = abap_true. + CALL METHOD lo_dsfi_handler->('IF_DD_DSFI_WB_HANDLER~GET_SOURCE_CONTAINER') + EXPORTING + iv_as4local = + RECEIVING + ro_result = lo_dsfi_source_container. + + CALL METHOD lo_dsfi_source_container->('IF_DD_DSFI_SRC_CONTAINER~GET_AS4USER') + RECEIVING + rv_result = rv_user. + ENDIF. + ENDIF. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. + + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_dsfd IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_dsfd_handler TYPE REF TO object, + lo_dsfd_source_container TYPE REF TO object, + lv_object_key TYPE seu_objkey, + lv_exists TYPE abap_bool, + lx_error TYPE REF TO cx_root. + + TRY. + lv_object_key = ms_item-obj_name. + CALL METHOD ('CL_DSFD_AFF_OBJECT_HANDLER')=>('GET_DDIC_HANDLER') + EXPORTING + object_key = lv_object_key + RECEIVING + handler = lo_dsfd_handler. + + CALL METHOD lo_dsfd_handler->('IF_DD_DSFD_WB_HANDLER~CHECK_EXISTENCE') + EXPORTING + iv_as4local = 'A' + RECEIVING + rv_exists = lv_exists. + + IF lv_exists = abap_true. + CALL METHOD lo_dsfd_handler->('IF_DD_DSFD_WB_HANDLER~GET_SOURCE_CONTAINER') +EXPORTING + iv_as4local = 'A' + RECEIVING + ro_result = lo_dsfd_source_container. + + CALL METHOD lo_dsfd_source_container->('IF_DD_DSFD_CONTAINER_SRC~GET_AS4USER') + RECEIVING + rv_as4user = rv_user. + ENDIF. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. + + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + ENDMETHOD. + + METHOD get_additional_extensions. + DATA ls_additional_extension LIKE LINE OF rv_additional_extensions. + ls_additional_extension-extension = 'acds'. + CALL METHOD ('CL_CDS_AFF_FILE_NAME_MAPPER')=>for_cds + RECEIVING + result = ls_additional_extension-file_name_mapper. + APPEND ls_additional_extension TO rv_additional_extensions. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_drty IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_drty_handler TYPE REF TO object, + lv_object_key TYPE seu_objkey, + lx_error TYPE REF TO cx_root. + + TRY. + lv_object_key = ms_item-obj_name. + CALL METHOD ('CL_DRTY_AFF_OBJECT_HANDLER')=>('GET_DDIC_HANDLER') + EXPORTING + object_key = lv_object_key + RECEIVING + handler = lo_drty_handler. + + CALL METHOD lo_drty_handler->('GET_CHANGED_BY') + RECEIVING + rv_changed_by = rv_user. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. + + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + ENDMETHOD. + + METHOD get_additional_extensions. + DATA ls_additional_extension LIKE LINE OF rv_additional_extensions. + ls_additional_extension-extension = 'acds'. + CALL METHOD ('CL_CDS_AFF_FILE_NAME_MAPPER')=>for_cds + RECEIVING + result = ls_additional_extension-file_name_mapper. + APPEND ls_additional_extension TO rv_additional_extensions. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_dras IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lo_dras_handler TYPE REF TO object, + lo_dras_source_container TYPE REF TO object, + lv_object_key TYPE seu_objkey, + lv_exists TYPE abap_bool, + lx_error TYPE REF TO cx_root. + + TRY. + lv_object_key = ms_item-obj_name. + CALL METHOD ('CL_DRAS_AFF_OBJECT_HANDLER')=>('GET_DDIC_HANDLER') + EXPORTING + object_key = lv_object_key + RECEIVING + handler = lo_dras_handler. + + CALL METHOD lo_dras_handler->('IF_DD_DRAS_WB_HANDLER~CHECK_EXISTENCE') + EXPORTING + iv_as4local = 'A' + RECEIVING + rv_exists = lv_exists. + + IF lv_exists = abap_true. + CALL METHOD lo_dras_handler->('IF_DD_DRAS_WB_HANDLER~GET_SOURCE_CONTAINER') + EXPORTING + iv_as4local = 'A' + RECEIVING + ro_result = lo_dras_source_container. + CALL METHOD lo_dras_source_container->('IF_DD_DRAS_SOURCE_CONTAINER~GET_AS4USER') + RECEIVING + rv_as4user = rv_user. + ENDIF. + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. + + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. + ENDMETHOD. + + METHOD get_additional_extensions. + DATA ls_additional_extension LIKE LINE OF rv_additional_extensions. + ls_additional_extension-extension = 'acds'. + CALL METHOD ('CL_CDS_AFF_FILE_NAME_MAPPER')=>for_cds + RECEIVING + result = ls_additional_extension-file_name_mapper. + APPEND ls_additional_extension TO rv_additional_extensions. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_cota IMPLEMENTATION. + + METHOD zif_abapgit_object~changed_by. + DATA lx_error TYPE REF TO cx_root. + TRY. + SELECT SINGLE changedby FROM ('sapcontargethead') INTO rv_user + WHERE id = ms_item-obj_name AND version = 'I'. + + IF rv_user IS INITIAL. + SELECT SINGLE changedby FROM ('sapcontargethead') INTO rv_user + WHERE id = ms_item-obj_name AND version = 'A'. + ENDIF. + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. + + METHOD zif_abapgit_object~delete. + DATA lx_error TYPE REF TO cx_root. + DATA lv_cota_name TYPE c LENGTH 30. + TRY. + lv_cota_name = ms_item-obj_name. + CALL METHOD ('CL_COTA_FACTORY')=>('DELETE_COTA') + EXPORTING + cota_name = lv_cota_name + korrnum = iv_transport. + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_common_aff IMPLEMENTATION. + METHOD constructor. + + DATA: + lv_is_supported TYPE abap_bool, + lo_handler TYPE REF TO object. + + super->constructor( + is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + + " Check if AFF handler exists and if object type is registered and supported + TRY. + lo_handler = get_object_handler( ). + + lv_is_supported = zcl_abapgit_aff_factory=>get_registry( )->is_supported_object_type( is_item-obj_type ). + CATCH cx_root. + lv_is_supported = abap_false. + ENDTRY. + + IF lv_is_supported IS INITIAL. + RAISE EXCEPTION TYPE zcx_abapgit_type_not_supported EXPORTING obj_type = is_item-obj_type. + ENDIF. + + ENDMETHOD. + METHOD create_aff_setting_deserialize. + IF ms_item-abap_language_version <> zcl_abapgit_abap_language_vers=>c_any_abap_language_version AND + ms_item-abap_language_version <> zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + TRY. + CREATE OBJECT ro_settings_deserialize TYPE ('CL_AFF_SETTINGS_DESERIALIZE') + EXPORTING + version = 'A' + language = mv_language + user = sy-uname + abap_language_version = ms_item-abap_language_version. + CATCH cx_root. + zcx_abapgit_exception=>raise( |System does not supported ABAP language version for AFF| ). + ENDTRY. + ELSE. + CREATE OBJECT ro_settings_deserialize TYPE ('CL_AFF_SETTINGS_DESERIALIZE') + EXPORTING + version = 'A' + language = mv_language + user = sy-uname. + ENDIF. + ENDMETHOD. + METHOD get_additional_extensions. + RETURN. + ENDMETHOD. + METHOD get_object_handler. + + DATA lo_handler_factory TYPE REF TO object. + + CREATE OBJECT lo_handler_factory TYPE ('CL_AFF_OBJECT_HANDLER_FACTORY'). + + CALL METHOD lo_handler_factory->('IF_AFF_OBJECT_HANDLER_FACTORY~GET_OBJECT_HANDLER') + EXPORTING + object_type = ms_item-obj_type + RECEIVING + result = ro_object_handler. + + ENDMETHOD. + METHOD is_file_empty. + + CALL METHOD io_object_json_file->('IF_AFF_FILE~IS_DELETION') + RECEIVING + result = rv_is_empty. + + ENDMETHOD. + METHOD remove_abap_language_version. + DATA lv_json TYPE string. + DATA lv_json_wo_alv TYPE string. + DATA li_json TYPE REF TO zif_abapgit_ajson. + + lv_json = zcl_abapgit_convert=>xstring_to_string_utf8( iv_json_as_xstring ). + + TRY. + li_json = zcl_abapgit_ajson=>parse( iv_json = lv_json + iv_keep_item_order = abap_true ). + li_json->delete( '/header/abapLanguageVersion' ). + lv_json_wo_alv = li_json->stringify( 2 ). + + rv_json_as_xstring_wo_alv = zcl_abapgit_convert=>string_to_xstring_utf8( lv_json_wo_alv ). + + CATCH zcx_abapgit_ajson_error. + rv_json_as_xstring_wo_alv = iv_json_as_xstring. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~delete. + + DATA: lr_intf_aff_obj TYPE REF TO data, + lr_intf_aff_log TYPE REF TO data, + lr_messages TYPE REF TO data, + lo_object_handler TYPE REF TO object, + lo_object_aff TYPE REF TO object, + lo_aff_factory TYPE REF TO object, + lv_name TYPE c LENGTH 120, + lx_error TYPE REF TO cx_root, + lo_aff_log TYPE REF TO object. + + FIELD-SYMBOLS: TYPE any, + TYPE any, + TYPE ANY TABLE, + TYPE any, + TYPE symsg. + + lv_name = ms_item-obj_name. + + TRY. + lo_object_handler = get_object_handler( ). + + CREATE OBJECT lo_object_aff TYPE ('CL_AFF_OBJ') + EXPORTING + package = iv_package + name = lv_name + type = ms_item-obj_type. + + CREATE DATA lr_intf_aff_obj TYPE REF TO ('IF_AFF_OBJ'). + ASSIGN lr_intf_aff_obj->* TO . + ?= lo_object_aff. + + CREATE OBJECT lo_aff_factory TYPE ('CL_AFF_FACTORY'). + CALL METHOD lo_aff_factory->('CREATE_LOG') + RECEIVING + result = lo_aff_log. + + CREATE DATA lr_intf_aff_log TYPE REF TO ('IF_AFF_LOG'). + ASSIGN lr_intf_aff_log->* TO . + ?= lo_aff_log. + + CALL METHOD lo_object_handler->('IF_AFF_OBJECT_HANDLER~DELETE') + EXPORTING + object = + log = . + + CREATE DATA lr_messages TYPE ('IF_AFF_LOG=>TT_LOG_OUT'). + ASSIGN lr_messages->* TO . + + CALL METHOD lo_aff_log->('IF_AFF_LOG~GET_MESSAGES') + RECEIVING + messages = . + + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE TO . + IF -msgty = 'E'. + zcx_abapgit_exception=>raise_t100( + iv_msgid = -msgid + iv_msgno = -msgno + iv_msgv1 = -msgv1 + iv_msgv2 = -msgv2 + iv_msgv3 = -msgv3 + iv_msgv4 = -msgv4 ). + ENDIF. + ENDLOOP. + + tadir_delete( ). + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_object~deserialize. + + DATA: lr_intf_aff_obj TYPE REF TO data, + lr_intf_aff_file TYPE REF TO data, + lr_intf_files_container TYPE REF TO data, + lr_intf_aff_log TYPE REF TO data, + lr_intf_aff_settings TYPE REF TO data, + lo_object_handler TYPE REF TO object, + lo_object_aff TYPE REF TO object, + lo_object_json_file TYPE REF TO object, + lo_object_file TYPE REF TO object, + lo_files_container TYPE REF TO object, + lo_settings TYPE REF TO object, + lo_aff_log TYPE REF TO object, + lo_aff_factory TYPE REF TO object, + lr_messages TYPE REF TO data, + lv_json_as_xstring TYPE xstring, + lx_exception TYPE REF TO cx_root, + lv_file_name TYPE string, + lo_file_name_mapper TYPE REF TO object, + lv_name TYPE c LENGTH 120, + lv_file_as_xstring TYPE xstring, + ls_additional_extensions TYPE ty_extension_mapper_pairs. + + FIELD-SYMBOLS: TYPE any, + TYPE any, + TYPE any, + TYPE any, + TYPE any, + TYPE ANY TABLE, + TYPE any, + TYPE any, + TYPE any, + TYPE symsg, + LIKE LINE OF ls_additional_extensions. + + lv_json_as_xstring = mo_files->read_raw( 'json' ). + lv_name = ms_item-obj_name. + + " beyond here there will be dragons.... + TRY. + lo_object_handler = get_object_handler( ). + + CREATE OBJECT lo_object_aff TYPE ('CL_AFF_OBJ') + EXPORTING + package = ms_item-devclass + name = lv_name + type = ms_item-obj_type. + + CREATE DATA lr_intf_aff_obj TYPE REF TO ('IF_AFF_OBJ'). + ASSIGN lr_intf_aff_obj->* TO . + ?= lo_object_aff. + + CREATE OBJECT lo_files_container TYPE ('CL_AFF_FILES_CONTAINER') + EXPORTING + object = . + + CALL METHOD ('CL_AFF_FILE_NAME_MAPPER')=>for_json + RECEIVING + result = lo_file_name_mapper. + + CALL METHOD lo_file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') + EXPORTING + object = + RECEIVING + result = lv_file_name. + + lo_settings = create_aff_setting_deserialize( ). + + CREATE OBJECT lo_object_json_file TYPE ('CL_AFF_FILE') + EXPORTING + name = lv_file_name + content = lv_json_as_xstring. + + CREATE DATA lr_intf_aff_file TYPE REF TO ('IF_AFF_FILE'). + ASSIGN lr_intf_aff_file->* TO . + ?= lo_object_json_file. + + CALL METHOD lo_files_container->('ADD_FILE') + EXPORTING + file = . + + ls_additional_extensions = get_additional_extensions( ). + + LOOP AT ls_additional_extensions ASSIGNING . + + lv_file_as_xstring = mo_files->read_raw( -extension ). + + CALL METHOD -file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') + EXPORTING + object = + RECEIVING + result = lv_file_name. + + CREATE OBJECT lo_object_file TYPE ('CL_AFF_FILE') + EXPORTING + name = lv_file_name + content = lv_file_as_xstring. + + CREATE DATA lr_intf_aff_file TYPE REF TO ('IF_AFF_FILE'). + ASSIGN lr_intf_aff_file->* TO . + ?= lo_object_file. + + CALL METHOD lo_files_container->('ADD_FILE') + EXPORTING + file = . + + ENDLOOP. + + CREATE OBJECT lo_aff_factory TYPE ('CL_AFF_FACTORY'). + CALL METHOD lo_aff_factory->('CREATE_LOG') + RECEIVING + result = lo_aff_log. + + CREATE DATA lr_intf_files_container TYPE REF TO ('IF_AFF_FILES_CONTAINER'). + ASSIGN lr_intf_files_container->* TO . + ?= lo_files_container. + + CREATE DATA lr_intf_aff_log TYPE REF TO ('IF_AFF_LOG'). + ASSIGN lr_intf_aff_log->* TO . + ?= lo_aff_log. + + CREATE DATA lr_intf_aff_settings TYPE REF TO ('IF_AFF_SETTINGS_DESERIALIZE'). + ASSIGN lr_intf_aff_settings->* TO . + ?= lo_settings. + + CALL METHOD lo_object_handler->('IF_AFF_OBJECT_HANDLER~DESERIALIZE') + EXPORTING + files_container = + log = + settings = . + + CREATE DATA lr_messages TYPE ('IF_AFF_LOG=>TT_LOG_OUT'). + ASSIGN lr_messages->* TO . + + CALL METHOD lo_aff_log->('IF_AFF_LOG~GET_MESSAGES') + RECEIVING + messages = . + + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE TO . + ASSIGN COMPONENT 'TEXT' OF STRUCTURE TO . + ASSIGN COMPONENT 'TYPE' OF STRUCTURE TO . + ii_log->add( + iv_msg = + iv_type = + is_item = ms_item ). + + IF -msgty = 'E'. + zcx_abapgit_exception=>raise_t100( + iv_msgid = -msgid + iv_msgno = -msgno + iv_msgv1 = -msgv1 + iv_msgv2 = -msgv2 + iv_msgv3 = -msgv3 + iv_msgv4 = -msgv4 ). + ENDIF. + ENDLOOP. + + IF is_active( ) = abap_false. + " as DDIC-object e.g. are not deserialized in active state, activation must be performed + zcl_abapgit_objects_activation=>add_item( ms_item ). + ENDIF. + + tadir_insert( ms_item-devclass ). + + CATCH cx_root INTO lx_exception. + ii_log->add_error( is_item = ms_item + iv_msg = 'Error at deserialize' ). + ii_log->add_exception( + ix_exc = lx_exception + is_item = ms_item ). + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_object~exists. + DATA: lr_intf_aff_obj TYPE REF TO data, + lo_object_handler TYPE REF TO object, + lo_object_aff TYPE REF TO object, + lv_name TYPE c LENGTH 120, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any. + + lv_name = ms_item-obj_name. + + TRY. + lo_object_handler = get_object_handler( ). + + CREATE OBJECT lo_object_aff TYPE ('CL_AFF_OBJ') + EXPORTING + package = ms_item-devclass + name = lv_name + type = ms_item-obj_type. + + CREATE DATA lr_intf_aff_obj TYPE REF TO ('IF_AFF_OBJ'). + ASSIGN lr_intf_aff_obj->* TO . + ?= lo_object_aff. + + CALL METHOD lo_object_handler->('IF_AFF_OBJECT_HANDLER~EXISTS') + EXPORTING + object = + RECEIVING + result = rv_bool. + + CATCH cx_root INTO lx_error. + " return false instead of raising exception, because abapGit assumes + " that raising exception = existing object + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_object~get_comparator. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_order. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~get_deserialize_steps. + APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. + ENDMETHOD. + METHOD zif_abapgit_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_active. + rv_active = is_active( ). + ENDMETHOD. + METHOD zif_abapgit_object~is_locked. + DATA lv_lock_object TYPE string. + DATA lv_argument TYPE seqg3-garg. + + lv_lock_object = |{ ms_item-obj_type }{ ms_item-obj_name }*|. + lv_argument = lv_lock_object. + + rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' + iv_argument = lv_argument ). + ENDMETHOD. + METHOD zif_abapgit_object~jump. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_filename_to_object. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~map_object_to_filename. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_object~serialize. + DATA: lr_intf_aff_obj TYPE REF TO data, + lr_intf_aff_log TYPE REF TO data, + lr_intf_aff_settings TYPE REF TO data, + lr_messages TYPE REF TO data, + lo_object_handler TYPE REF TO object, + lo_object_aff TYPE REF TO object, + lo_object_json_file TYPE REF TO object, + lo_files_container TYPE REF TO object, + lo_settings TYPE REF TO object, + lo_aff_log TYPE REF TO object, + lo_aff_factory TYPE REF TO object, + lo_object_file TYPE REF TO object, + lv_json_as_xstring TYPE xstring, + lv_json_as_xstring_wo_alv TYPE xstring, + lx_exception TYPE REF TO cx_root, + lv_name TYPE c LENGTH 120, + lv_file_name TYPE string, + lo_file_name_mapper TYPE REF TO object, + ls_additional_extensions TYPE ty_extension_mapper_pairs, + lv_file_as_xstring TYPE xstring. + + FIELD-SYMBOLS: TYPE any, + TYPE any, + TYPE any, + TYPE ANY TABLE, + TYPE any, + TYPE symsg, + LIKE LINE OF ls_additional_extensions. + + lv_name = ms_item-obj_name. + + TRY. + lo_object_handler = get_object_handler( ). + + CREATE OBJECT lo_object_aff TYPE ('CL_AFF_OBJ') + EXPORTING + package = ms_item-devclass + name = lv_name + type = ms_item-obj_type. + + CREATE OBJECT lo_settings TYPE ('CL_AFF_SETTINGS_SERIALIZE') + EXPORTING + version = 'A' + language = mv_language. + + CREATE OBJECT lo_aff_factory TYPE ('CL_AFF_FACTORY'). + CALL METHOD lo_aff_factory->('CREATE_LOG') + RECEIVING + result = lo_aff_log. + + CREATE DATA lr_intf_aff_log TYPE REF TO ('IF_AFF_LOG'). + ASSIGN lr_intf_aff_log->* TO . + ?= lo_aff_log. + + CREATE DATA lr_intf_aff_settings TYPE REF TO ('IF_AFF_SETTINGS_SERIALIZE'). + ASSIGN lr_intf_aff_settings->* TO . + ?= lo_settings. + + CREATE DATA lr_intf_aff_obj TYPE REF TO ('IF_AFF_OBJ'). + ASSIGN lr_intf_aff_obj->* TO . + ?= lo_object_aff. + + CALL METHOD lo_object_handler->('IF_AFF_OBJECT_HANDLER~SERIALIZE') + EXPORTING + object = + log = + settings = + RECEIVING + result = lo_files_container. + + CREATE DATA lr_messages TYPE ('IF_AFF_LOG=>TT_LOG_OUT'). + ASSIGN lr_messages->* TO . + + CALL METHOD lo_aff_log->('IF_AFF_LOG~GET_MESSAGES') + RECEIVING + messages = . + + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE TO . + IF -msgty = 'E'. + zcx_abapgit_exception=>raise_t100( + iv_msgid = -msgid + iv_msgno = -msgno + iv_msgv1 = -msgv1 + iv_msgv2 = -msgv2 + iv_msgv3 = -msgv3 + iv_msgv4 = -msgv4 ). + ENDIF. + ENDLOOP. + + CALL METHOD ('CL_AFF_FILE_NAME_MAPPER')=>for_json + RECEIVING + result = lo_file_name_mapper. + + CALL METHOD lo_file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') + EXPORTING + object = + RECEIVING + result = lv_file_name. + + CALL METHOD lo_files_container->('IF_AFF_FILES_CONTAINER~GET_FILE') + EXPORTING + name = lv_file_name + RECEIVING + result = lo_object_json_file. + + " avoid to serialize empty content (object was never activated, exists inactive only). + IF is_file_empty( lo_object_json_file ) = abap_true. + MESSAGE s821(eu) WITH lv_name INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL METHOD lo_object_json_file->('IF_AFF_FILE~GET_CONTENT') + RECEIVING + result = lv_json_as_xstring. + + " Only remove ABAP language version if repository is set to ignore it + IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. + lv_json_as_xstring_wo_alv = remove_abap_language_version( lv_json_as_xstring ). + mo_files->add_raw( + iv_ext = 'json' + iv_data = lv_json_as_xstring_wo_alv ). + ELSE. + mo_files->add_raw( + iv_ext = 'json' + iv_data = lv_json_as_xstring ). + ENDIF. + + ls_additional_extensions = get_additional_extensions( ). + + LOOP AT ls_additional_extensions ASSIGNING . + + CALL METHOD -file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') + EXPORTING + object = + RECEIVING + result = lv_file_name. + + CALL METHOD lo_files_container->('IF_AFF_FILES_CONTAINER~GET_FILE') + EXPORTING + name = lv_file_name + RECEIVING + result = lo_object_file. + + CALL METHOD lo_object_file->('IF_AFF_FILE~GET_CONTENT') + RECEIVING + result = lv_file_as_xstring. + + mo_files->add_raw( + iv_ext = -extension + iv_data = lv_file_as_xstring ). + + ENDLOOP. + + CATCH cx_root INTO lx_exception. + zcx_abapgit_exception=>raise_with_text( lx_exception ). + ENDTRY. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_CHKV IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lr_data TYPE REF TO data, + lo_chkv_db_api TYPE REF TO object, + lv_name TYPE c LENGTH 180, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + TRY. + CREATE OBJECT lo_chkv_db_api TYPE ('CL_CHKV_DB_API'). + CREATE DATA lr_data TYPE ('CL_CHKV_DB_API=>TY_HEADER'). + ASSIGN lr_data->* TO . + + lv_name = ms_item-obj_name. + + CALL METHOD lo_chkv_db_api->('GET_HEADER') + EXPORTING + object_key = lv_name + version = 'I' + RECEIVING + header = . + + IF IS INITIAL. + CALL METHOD lo_chkv_db_api->('GET_HEADER') + EXPORTING + object_key = lv_name + version = 'A' + RECEIVING + header = . + ENDIF. + + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + rv_user = . + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_CHKO IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lr_data TYPE REF TO data, + lo_chko_db_api TYPE REF TO object, + lv_name TYPE c LENGTH 30, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + TRY. + CREATE OBJECT lo_chko_db_api TYPE ('CL_CHKO_DB_API'). + CREATE DATA lr_data TYPE ('CL_CHKO_DB_API=>TY_HEADER'). + ASSIGN lr_data->* TO . + + lv_name = ms_item-obj_name. + + CALL METHOD lo_chko_db_api->('GET_HEADER') + EXPORTING + name = lv_name + version = 'I' + RECEIVING + header = . + + IF IS INITIAL. + CALL METHOD lo_chko_db_api->('GET_HEADER') + EXPORTING + name = lv_name + version = 'A' + RECEIVING + header = . + ENDIF. + + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + rv_user = . + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_CHKC IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + + DATA: lr_data TYPE REF TO data, + lo_chkc_db_api TYPE REF TO object, + lv_name TYPE c LENGTH 30, + lx_error TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any, + TYPE any. + + TRY. + CREATE OBJECT lo_chkc_db_api TYPE ('CL_CHKC_DB_API'). + CREATE DATA lr_data TYPE ('CL_CHKC_DB_API=>TY_HEADER'). + ASSIGN lr_data->* TO . + + lv_name = ms_item-obj_name. + + CALL METHOD lo_chkc_db_api->('GET_HEADER') + EXPORTING + name = lv_name + version = 'I' + RECEIVING + header = . + + IF IS INITIAL. + CALL METHOD lo_chkc_db_api->('GET_HEADER') + EXPORTING + name = lv_name + version = 'A' + RECEIVING + header = . + ENDIF. + + ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . + rv_user = . + + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_cdbo IMPLEMENTATION. + METHOD constructor. + + super->constructor( is_item = is_item + iv_language = iv_language + io_files = io_files + io_i18n_params = io_i18n_params ). + ENDMETHOD. + METHOD zif_abapgit_object~changed_by. + + DATA: lv_user TYPE string, + lx_error TYPE REF TO cx_root. + + TRY. + SELECT SINGLE changed_by FROM (c_table_name) INTO lv_user WHERE obj_name = ms_item-obj_name. + IF lv_user IS INITIAL. + SELECT SINGLE created_by FROM (c_table_name) INTO lv_user WHERE obj_name = ms_item-obj_name. + ENDIF. + rv_user = lv_user. + CATCH cx_root INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_object_bgqc IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + DATA lo_bgqc_wbi_p TYPE REF TO object. + DATA lv_ref_bgqc_name TYPE REF TO data. + DATA lv_changed_by TYPE syuname. + DATA lv_subrc TYPE sy-subrc. + DATA lx_root TYPE REF TO cx_root. + + FIELD-SYMBOLS: TYPE any. + + TRY. + + CREATE DATA lv_ref_bgqc_name TYPE (c_bgqc_name). + ASSIGN lv_ref_bgqc_name->* TO . + ASSERT sy-subrc = 0. + + me->ms_item-obj_name = . + + CREATE OBJECT lo_bgqc_wbi_p TYPE (c_bgqc_wbi_p). + + CALL METHOD lo_bgqc_wbi_p->(c_select_changed_by) + EXPORTING + iv_bgqc_name = + IMPORTING + ev_changed_by = lv_changed_by + ev_subrc = lv_subrc. + + IF lv_subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + rv_user = lv_changed_by. + + CATCH cx_root INTO lx_root. + + zcx_abapgit_exception=>raise_with_text( lx_root ). + + ENDTRY. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_OBJECT_APLO IMPLEMENTATION. + METHOD zif_abapgit_object~changed_by. + CLEAR rv_user. + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh DEFINITION DEFERRED. +*"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + +* renamed: zcl_abapgit_json_path :: lcl_json_path +CLASS kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh DEFINITION CREATE PUBLIC. + + PUBLIC SECTION. + METHODS: + serialize_rec + IMPORTING io_reader TYPE REF TO if_sxml_reader + it_path TYPE string_table + CHANGING ct_json_paths TYPE string_table. + + CLASS-METHODS: deserialize + IMPORTING it_json_path TYPE string_table + RETURNING VALUE(rv_result) TYPE string + RAISING zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + METHODS: + is_array + IMPORTING io_reader TYPE REF TO if_sxml_reader + RETURNING VALUE(rv_result) TYPE abap_bool. + METHODS: + is_string_open + IMPORTING io_reader TYPE REF TO if_sxml_reader + RETURNING VALUE(rv_result) TYPE abap_bool. + METHODS: + is_object + IMPORTING io_reader TYPE REF TO if_sxml_reader + RETURNING VALUE(rv_result) TYPE abap_bool. + METHODS: + serialize_rec_array + IMPORTING io_reader TYPE REF TO if_sxml_reader + it_path TYPE string_table + CHANGING ct_json_paths TYPE string_table. + METHODS: + get_json_path + IMPORTING it_path TYPE string_table + RETURNING VALUE(rv_result) TYPE string. + CLASS-METHODS get_path_elements + IMPORTING iv_path TYPE string + RETURNING VALUE(rt_result) TYPE string_table + RAISING zcx_abapgit_exception. + CLASS-METHODS build_json + IMPORTING it_path_elements TYPE string_table + iv_value TYPE string + CHANGING cv_json_string TYPE string. + CLASS-METHODS path_contains_array + IMPORTING iv_path TYPE string + RETURNING VALUE(rv_result) TYPE abap_bool. + CLASS-METHODS: to_json + IMPORTING iv_json_path TYPE string + RETURNING VALUE(ro_result) TYPE REF TO zcl_abapgit_ajson + RAISING zcx_abapgit_ajson_error + zcx_abapgit_exception. + CLASS-METHODS: is_primitiv + IMPORTING iv_string TYPE string + RETURNING VALUE(rv_result) TYPE abap_bool. + CLASS-METHODS: is_comment_or_empty_line + IMPORTING iv_line TYPE string + RETURNING VALUE(rv_result) TYPE abap_bool. + +ENDCLASS. + +CLASS kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh IMPLEMENTATION. + + METHOD to_json. + DATA: lv_path TYPE string, + lv_value TYPE string, + lt_path_elements TYPE string_table, + lv_json TYPE string. + + FIND REGEX `(.*)=(.*$)` IN iv_json_path SUBMATCHES lv_path lv_value. + + IF path_contains_array( lv_path ) = abap_true. + + lt_path_elements = get_path_elements( lv_path ). + + build_json( EXPORTING it_path_elements = lt_path_elements + iv_value = lv_value + CHANGING cv_json_string = lv_json ). + + ro_result = zcl_abapgit_ajson=>parse( lv_json ). + ELSE. + + REPLACE FIRST OCCURRENCE OF '$.' IN lv_path WITH ''. + REPLACE '.' IN lv_path WITH '/'. + ro_result = zcl_abapgit_ajson=>create_empty( iv_keep_item_order = abap_true ). + ro_result->set( iv_path = lv_path + iv_val = lv_value ). + ENDIF. + ENDMETHOD. + + METHOD path_contains_array. + DATA lv_array_pattern TYPE string VALUE `.*\[.*\].*`. + rv_result = boolc( matches( val = iv_path + regex = lv_array_pattern ) ). + ENDMETHOD. + + METHOD build_json. + DATA: lt_new_path_element TYPE string_table, + lv_sub_match TYPE string, + lv_key_name TYPE string, + lv_key_value TYPE string, + lv_name TYPE string, + lv_first_elem TYPE string. + + lt_new_path_element = it_path_elements. + + IF lines( lt_new_path_element ) = 0. + RETURN. + ENDIF. + + READ TABLE lt_new_path_element INTO lv_first_elem INDEX 1. + + IF lv_first_elem = `$`. " is root level + + DELETE lt_new_path_element INDEX 1. + build_json( EXPORTING it_path_elements = lt_new_path_element + iv_value = iv_value + CHANGING cv_json_string = cv_json_string ). + + ELSEIF is_primitiv( lv_first_elem ) = abap_true. + + cv_json_string = cv_json_string && | \{"{ lv_first_elem+1 }": |. + + DELETE lt_new_path_element INDEX 1. + + build_json( EXPORTING it_path_elements = lt_new_path_element + iv_value = iv_value + CHANGING cv_json_string = cv_json_string ). + + cv_json_string = cv_json_string && ` }`. + + ELSE. " is array + + FIND REGEX `\[(.*)\]` IN lv_first_elem SUBMATCHES lv_sub_match. + FIND REGEX `(\w+)(?==='([^']*)')` IN lv_sub_match SUBMATCHES lv_key_name lv_key_value. + READ TABLE lt_new_path_element INTO lv_name INDEX 2. + DELETE lt_new_path_element INDEX 1. + DELETE lt_new_path_element INDEX 1. + + IF lines( lt_new_path_element ) = 0. + + cv_json_string = cv_json_string && + |[ \{ "{ lv_key_name }": "{ lv_key_value }", "{ lv_name+1 }": "{ iv_value }"\} ]|. + + ELSE. + + cv_json_string = cv_json_string && |[ \{ "{ lv_key_name }": "{ lv_key_value }", "{ lv_name+1 }":|. + + build_json( EXPORTING it_path_elements = lt_new_path_element + iv_value = iv_value + CHANGING cv_json_string = cv_json_string ). + + cv_json_string = cv_json_string && `} ] `. + + ENDIF. + ENDIF. + + ENDMETHOD. + + METHOD is_primitiv. + + FIND REGEX `^.\w+` IN iv_string. " string start with . + rv_result = boolc( sy-subrc = 0 ). + + ENDMETHOD. + + METHOD get_path_elements. + DATA: lv_pcre_pattern TYPE string, + lt_match_result TYPE match_result_tab, + lv_match TYPE match_result, + lv_hit TYPE string, + lx_find TYPE REF TO cx_root. + + lv_pcre_pattern = `(^\$)|(\.\w+)|(\[[^\]]*\])`. + + TRY. + FIND ALL OCCURRENCES OF REGEX lv_pcre_pattern IN iv_path RESULTS lt_match_result. + CATCH cx_sy_find_infinite_loop cx_sy_range_out_of_bounds cx_sy_invalid_regex cx_sy_regex_too_complex INTO lx_find. + zcx_abapgit_exception=>raise_with_text( lx_find ). + ENDTRY. + LOOP AT lt_match_result INTO lv_match. + lv_hit = substring( val = iv_path + off = lv_match-offset + len = lv_match-length ). + APPEND lv_hit TO rt_result. + ENDLOOP. + + ENDMETHOD. + + METHOD is_array. + rv_result = boolc( io_reader->name = 'array' ). + ENDMETHOD. + + METHOD is_string_open. + rv_result = boolc( io_reader->name = 'str' AND io_reader->node_type = if_sxml_node=>co_nt_element_open ). + ENDMETHOD. + + METHOD is_object. + rv_result = boolc( io_reader->name = 'object' ). + ENDMETHOD. + + METHOD serialize_rec. + DATA: lt_new_path TYPE string_table, + lv_key TYPE string. + + lt_new_path = it_path. + + IF io_reader->read_next_node( ) IS INITIAL. + RETURN. + ENDIF. + + IF is_string_open( io_reader ) = abap_true. + + APPEND io_reader->value TO lt_new_path. + lv_key = get_json_path( lt_new_path ). + + io_reader->read_next_node( ). + lv_key = |{ lv_key }={ io_reader->value }|. + APPEND lv_key TO ct_json_paths. + + io_reader->read_next_node( ). + DELETE lt_new_path INDEX lines( lt_new_path ). + + serialize_rec( EXPORTING io_reader = io_reader + it_path = lt_new_path + CHANGING ct_json_paths = ct_json_paths ). + + ELSEIF is_object( io_reader ) = abap_true AND io_reader->node_type = if_sxml_node=>co_nt_element_open. + + APPEND io_reader->value TO lt_new_path. + serialize_rec( EXPORTING io_reader = io_reader + it_path = lt_new_path + CHANGING ct_json_paths = ct_json_paths ). + + ELSEIF is_array( io_reader ) = abap_true AND io_reader->node_type = if_sxml_node=>co_nt_element_open. + + APPEND io_reader->value TO lt_new_path. + serialize_rec_array( EXPORTING io_reader = io_reader + it_path = lt_new_path + CHANGING ct_json_paths = ct_json_paths ). + + ELSEIF ( is_object( io_reader ) = abap_true OR is_array( io_reader ) = abap_true ) + AND io_reader->node_type = if_sxml_node=>co_nt_element_close. + + DELETE lt_new_path INDEX lines( lt_new_path ). + serialize_rec( EXPORTING io_reader = io_reader + it_path = lt_new_path + CHANGING ct_json_paths = ct_json_paths ). + + ENDIF. + + ENDMETHOD. + METHOD serialize_rec_array. + DATA: lt_new_path TYPE string_table, + lv_json_path TYPE string, + lv_array_key TYPE string. + + lt_new_path = it_path. + + IF io_reader->read_next_node( ) IS INITIAL. + RETURN. + ENDIF. + + IF is_string_open( io_reader ) = abap_true. + + APPEND io_reader->value TO lt_new_path. + lv_json_path = get_json_path( lt_new_path ). + + io_reader->read_next_node( ). + lv_json_path = |{ lv_json_path }={ io_reader->value }|. + APPEND lv_json_path TO ct_json_paths. + io_reader->read_next_node( ). + + serialize_rec( EXPORTING io_reader = io_reader + it_path = lt_new_path + CHANGING ct_json_paths = ct_json_paths ). + + ELSEIF is_object( io_reader ) = abap_true AND io_reader->node_type = if_sxml_node=>co_nt_element_open. + + io_reader->read_next_node( ). + lv_array_key = io_reader->value. + io_reader->read_next_node( ). + lv_array_key = |[?(@.{ lv_array_key }=='{ io_reader->value }')]|. + APPEND lv_array_key TO lt_new_path. + io_reader->read_next_node( ). + + io_reader->read_next_node( ). + APPEND io_reader->value TO lt_new_path. + lv_json_path = get_json_path( lt_new_path ). + + io_reader->read_next_node( ). + lv_json_path = |{ lv_json_path }={ io_reader->value }|. + APPEND lv_json_path TO ct_json_paths. + io_reader->read_next_node( ). + + DELETE lt_new_path INDEX lines( lt_new_path ). + serialize_rec_array( EXPORTING io_reader = io_reader + it_path = lt_new_path + CHANGING ct_json_paths = ct_json_paths ). + + ELSEIF is_array( io_reader ) = abap_true AND io_reader->node_type = if_sxml_node=>co_nt_element_open. + + APPEND io_reader->value TO lt_new_path. + serialize_rec_array( EXPORTING io_reader = io_reader + it_path = lt_new_path + CHANGING ct_json_paths = ct_json_paths ). + + ELSEIF ( is_object( io_reader ) = abap_true OR is_array( io_reader ) = abap_true ) + AND io_reader->node_type = if_sxml_node=>co_nt_element_close. + + DELETE lt_new_path INDEX lines( lt_new_path ). + serialize_rec_array( EXPORTING io_reader = io_reader + it_path = lt_new_path + CHANGING ct_json_paths = ct_json_paths ). + + ENDIF. + + ENDMETHOD. + + METHOD get_json_path. + rv_result = concat_lines_of( table = it_path + sep = `.` ). + REPLACE ALL OCCURRENCES OF `.[` IN rv_result WITH `[`. + + ENDMETHOD. + + METHOD deserialize. + + DATA: lo_merged TYPE REF TO zif_abapgit_ajson, + lv_json_path TYPE string, + lo_deserialization_result TYPE REF TO zif_abapgit_ajson, + lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + + TRY. + lo_merged = zcl_abapgit_ajson=>parse( `{}` ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise_with_text( lx_ajson ). + ENDTRY. + + LOOP AT it_json_path INTO lv_json_path. + IF is_comment_or_empty_line( lv_json_path ) = abap_true. + CONTINUE. + ENDIF. + TRY. + lo_deserialization_result = to_json( lv_json_path ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise_with_text( lx_ajson ). + ENDTRY. + + TRY. + lo_merged = zcl_abapgit_ajson_utilities=>new( )->merge( io_json_a = lo_merged + io_json_b = lo_deserialization_result ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise_with_text( lx_ajson ). + ENDTRY. + + ENDLOOP. + + TRY. + rv_result = lo_merged->stringify( 2 ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise_with_text( lx_ajson ). + ENDTRY. + ENDMETHOD. + METHOD is_comment_or_empty_line. + + IF iv_line IS INITIAL. + rv_result = abap_true. + RETURN. + ENDIF. + + FIND REGEX `^!` IN iv_line. + IF sy-subrc = 0. + rv_result = abap_true. + RETURN. + ENDIF. + + FIND REGEX `^#` IN iv_line. + IF sy-subrc = 0. + rv_result = abap_true. + RETURN. + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_json_path IMPLEMENTATION. + METHOD deserialize. + + rv_result = kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh=>deserialize( it_json_path ). + + ENDMETHOD. + METHOD serialize. + DATA: lo_json_path TYPE REF TO kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh, + lv_json_xstring TYPE xstring, + lt_root_path TYPE string_table, + lo_reader TYPE REF TO if_sxml_reader, + lx_parse_error TYPE REF TO cx_sxml_parse_error. + + lv_json_xstring = zcl_abapgit_convert=>string_to_xstring_utf8( iv_json ). + lo_reader = cl_sxml_string_reader=>create( input = lv_json_xstring ). + + TRY. + IF lo_reader->read_next_node( ) IS INITIAL. + RETURN. + ENDIF. + CATCH cx_sxml_parse_error INTO lx_parse_error. + zcx_abapgit_exception=>raise_with_text( lx_parse_error ). + ENDTRY. + + APPEND `$` TO lt_root_path. + + CREATE OBJECT lo_json_path. + lo_json_path->serialize_rec( EXPORTING io_reader = lo_reader + it_path = lt_root_path + CHANGING ct_json_paths = rt_result ). + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlbVxgSjWYXcuzxmbrHxeswZCbe DEFINITION DEFERRED. +* renamed: zcl_abapgit_json_handler :: lcl_aff_filter +CLASS kHGwlbVxgSjWYXcuzxmbrHxeswZCbe DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_filter. + TYPES: + BEGIN OF ty_path_value_pair, + path TYPE string, + value TYPE string, + END OF ty_path_value_pair, + ty_skip_paths TYPE STANDARD TABLE OF ty_path_value_pair WITH KEY path. + + METHODS constructor + IMPORTING iv_skip_paths TYPE ty_skip_paths OPTIONAL + RAISING zcx_abapgit_ajson_error. + PRIVATE SECTION. + DATA mt_skip_paths TYPE ty_skip_paths. +ENDCLASS. + +CLASS kHGwlbVxgSjWYXcuzxmbrHxeswZCbe IMPLEMENTATION. + + METHOD zif_abapgit_ajson_filter~keep_node. + + DATA lv_path TYPE string. + + lv_path = is_node-path && is_node-name. + + READ TABLE mt_skip_paths WITH KEY path = lv_path value = is_node-value TRANSPORTING NO FIELDS. + IF boolc( sy-subrc = 0 ) = abap_true + AND iv_visit = zif_abapgit_ajson_filter=>visit_type-value. + rv_keep = abap_false. + RETURN. + ELSE. + READ TABLE mt_skip_paths WITH KEY path = lv_path TRANSPORTING NO FIELDS. + IF boolc( sy-subrc = 0 ) = abap_true + AND iv_visit = zif_abapgit_ajson_filter=>visit_type-value. + rv_keep = abap_true. + RETURN. + ENDIF. + ENDIF. + + IF is_node-type = 'bool' AND is_node-value = 'false' AND iv_visit = zif_abapgit_ajson_filter=>visit_type-value. + rv_keep = abap_false. + RETURN. + ENDIF. + + " AFF: if INTEGER type is initial (0) then is will be skipped + " However, if type is $required, it should be serialized. + IF NOT ( ( iv_visit = zif_abapgit_ajson_filter=>visit_type-value AND is_node-value IS NOT INITIAL ) OR + ( iv_visit <> zif_abapgit_ajson_filter=>visit_type-value AND is_node-children > 0 ) ). + rv_keep = abap_false. + RETURN. + ENDIF. + + rv_keep = abap_true. + + ENDMETHOD. + + METHOD constructor. + " extract annotations and build table for values to be skipped ( path/name | value ) + DATA lo_abap_language_pair TYPE ty_path_value_pair. + lo_abap_language_pair-path = `/header/abapLanguageVersion`. + lo_abap_language_pair-value = 'standard'. + + APPEND lo_abap_language_pair TO mt_skip_paths. + + IF iv_skip_paths IS NOT INITIAL. + APPEND LINES OF iv_skip_paths TO mt_skip_paths. + ENDIF. + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_json_handler IMPLEMENTATION. + METHOD deserialize. + DATA lo_ajson TYPE REF TO zif_abapgit_ajson. + + CLEAR ev_data. + + lo_ajson = zcl_abapgit_ajson=>parse( iv_content + )->map( zcl_abapgit_ajson_mapping=>create_to_snake_case( ) ). + + map2abap_original_language( CHANGING co_ajson = lo_ajson ). + set_defaults( EXPORTING it_defaults = iv_defaults + CHANGING co_ajson = lo_ajson ). + map2abap_abap_language_version( CHANGING co_ajson = lo_ajson ). + map2abap_custom_enum( EXPORTING it_enum_mappings = iv_enum_mappings + CHANGING co_ajson = lo_ajson ). + + lo_ajson->to_abap( IMPORTING ev_container = ev_data ). + + ENDMETHOD. + METHOD map2abap_abap_language_version. + DATA: + lv_enum_abap TYPE string, + lv_enum_json TYPE string. + lv_enum_json = co_ajson->get_string( '/header/abap_language_version' ). + IF lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-standard. + lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard. + ELSEIF lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development. + lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-cloud_development. + ELSEIF lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user. + lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-key_user. + ENDIF. + + co_ajson->set_string( iv_path = '/header/abap_language_version' + iv_val = lv_enum_abap ). + ENDMETHOD. + METHOD map2abap_custom_enum. + DATA: + lv_enum_json TYPE string, + ls_enum_mapping TYPE ty_enum_mapping, + ls_mapping TYPE ty_json_abap_mapping. + LOOP AT it_enum_mappings INTO ls_enum_mapping. + lv_enum_json = co_ajson->get_string( ls_enum_mapping-path ). + READ TABLE ls_enum_mapping-mappings WITH KEY json = lv_enum_json INTO ls_mapping. + IF sy-subrc = 0. + co_ajson->set_string( iv_path = ls_enum_mapping-path + iv_val = ls_mapping-abap ). + ENDIF. + ENDLOOP. + ENDMETHOD. + METHOD map2abap_original_language. + DATA: + lv_bcp47_language TYPE string, + lv_original_language TYPE sy-langu. + lv_bcp47_language = co_ajson->get_string( '/header/original_language' ). + + lv_original_language = zcl_abapgit_convert=>language_bcp47_to_sap1( lv_bcp47_language ). + + co_ajson->set_string( iv_path = '/header/original_language' + iv_val = lv_original_language ). + ENDMETHOD. + METHOD map2json_abap_language_version. + DATA: + lv_enum_abap TYPE string, + lv_enum_json TYPE string. + lv_enum_abap = co_ajson->get_string( '/header/abapLanguageVersion' ). + IF lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard + OR lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-standard. + lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-standard. + ELSEIF lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-cloud_development. + lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development. + ELSEIF lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-key_user. + lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user. + ENDIF. + + co_ajson->set_string( iv_path = '/header/abapLanguageVersion' + iv_val = lv_enum_json ). + ENDMETHOD. + METHOD map2json_custom_enum. + DATA: + lv_enum_abap TYPE string, + ls_enum_mapping TYPE ty_enum_mapping, + ls_mapping TYPE ty_json_abap_mapping. + LOOP AT it_enum_mappings INTO ls_enum_mapping. + lv_enum_abap = co_ajson->get_string( ls_enum_mapping-path ). + READ TABLE ls_enum_mapping-mappings WITH KEY abap = lv_enum_abap INTO ls_mapping. + IF sy-subrc = 0. + co_ajson->set_string( iv_path = ls_enum_mapping-path + iv_val = ls_mapping-json ). + ENDIF. + ENDLOOP. + ENDMETHOD. + METHOD map2json_original_language. + DATA: + lv_bcp47_language TYPE string, + lv_original_language TYPE sy-langu. + lv_original_language = co_ajson->get_string( '/header/originalLanguage' ). + + lv_bcp47_language = zcl_abapgit_convert=>language_sap1_to_bcp47( lv_original_language ). + + co_ajson->set_string( iv_path = '/header/originalLanguage' + iv_val = lv_bcp47_language ). + ENDMETHOD. + METHOD serialize. + DATA: lt_st_source TYPE abap_trans_srcbind_tab, + lv_json TYPE string, + lo_ajson TYPE REF TO zif_abapgit_ajson, + lo_filter TYPE REF TO kHGwlbVxgSjWYXcuzxmbrHxeswZCbe. + + FIELD-SYMBOLS: LIKE LINE OF lt_st_source. + + APPEND INITIAL LINE TO lt_st_source ASSIGNING . + GET REFERENCE OF iv_data INTO -value. + + lo_ajson = zcl_abapgit_ajson=>new( iv_keep_item_order = abap_true + )->set( iv_path = '/' + iv_val = iv_data + )->map( zcl_abapgit_ajson_mapping=>create_to_camel_case( ) ). + + map2json_original_language( CHANGING co_ajson = lo_ajson ). + map2json_abap_language_version( CHANGING co_ajson = lo_ajson ). + map2json_custom_enum( EXPORTING it_enum_mappings = iv_enum_mappings + CHANGING co_ajson = lo_ajson ). + + CREATE OBJECT lo_filter EXPORTING iv_skip_paths = iv_skip_paths. + + " files end with an empty line (EOF) + lv_json = lo_ajson->clone( )->filter( lo_filter )->stringify( 2 ) && cl_abap_char_utilities=>newline. + + rv_result = zcl_abapgit_convert=>string_to_xstring_utf8( lv_json ). + ENDMETHOD. + METHOD set_defaults. + DATA: + lv_enum_json TYPE string, + ls_default TYPE ty_path_value_pair. + LOOP AT it_defaults INTO ls_default. + lv_enum_json = co_ajson->get_string( ls_default-path ). + IF lv_enum_json = ``. + co_ajson->set_string( iv_path = ls_default-path + iv_val = ls_default-value ). + ENDIF. + ENDLOOP. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_AFF_REGISTRY IMPLEMENTATION. + METHOD constructor. + mv_aff_enabled = zcl_abapgit_feature=>is_enabled( c_aff_feature ). + ENDMETHOD. + METHOD initialize_registry_table. + register( 'APLO' ). + register( 'BGQC' ). + register( 'CDBO' ). + register( 'CHKC' ). + register( 'CHKO' ). + register( 'CHKV' ). + register( 'COTA' ). + register( 'DRTY' ). + register( 'DTEB' ). + register( 'DSFI' ). + register( 'DRAS' ). + register( 'DSFD' ). + register( 'EVTB' ). + register( 'EEEC' ). + register( 'GSMP' ). + register( iv_obj_type = 'INTF' + iv_experimental = abap_true ). + register( 'SAJT' ). + register( 'SAJC' ). + register( 'SMBC' ). + register( 'SWCR' ). + register( 'NONT' ). + register( 'RONT' ). + register( 'UIAD' ). + register( 'UIPG' ). + register( 'UIST' ). + ENDMETHOD. + METHOD register. + DATA ls_registry_entry TYPE ty_registry_entry. + + ls_registry_entry-obj_type = iv_obj_type. + ls_registry_entry-experimental = iv_experimental. + INSERT ls_registry_entry INTO TABLE gt_registry. + ENDMETHOD. + METHOD zif_abapgit_aff_registry~is_supported_object_type. + + DATA ls_registry_entry TYPE ty_registry_entry. + + IF gt_registry IS INITIAL. + initialize_registry_table( ). + ENDIF. + + READ TABLE gt_registry WITH TABLE KEY obj_type = iv_obj_type INTO ls_registry_entry. + IF sy-subrc = 0 AND ls_registry_entry-experimental = abap_false. + rv_result = abap_true. + ELSEIF sy-subrc = 0 AND mv_aff_enabled = abap_true. + rv_result = abap_true. + ELSE. + rv_result = abap_false. + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_aff_factory IMPLEMENTATION. + + METHOD get_registry. + IF gi_registry IS NOT BOUND. + CREATE OBJECT gi_registry TYPE zcl_abapgit_aff_registry. + ENDIF. + ri_registry = gi_registry. + ENDMETHOD. + +ENDCLASS. + +CLASS kHGwlzjElomncUxrYaqWUAJitpOMkj DEFINITION DEFERRED. +********************************************************************** +* ITERATOR +********************************************************************** + +* renamed: zcl_abapgit_ajson_utilities :: lcl_node_iterator +CLASS kHGwlzjElomncUxrYaqWUAJitpOMkj DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_iterator. + METHODS constructor + IMPORTING + ii_json TYPE REF TO zif_abapgit_ajson + iv_path TYPE string + iv_node_type TYPE zif_abapgit_ajson_types=>ty_node_type + RAISING + zcx_abapgit_ajson_error. + + PRIVATE SECTION. + DATA mi_json TYPE REF TO zif_abapgit_ajson. + DATA mv_node_type TYPE zif_abapgit_ajson_types=>ty_node_type. + DATA mv_base_path TYPE string. + DATA mr_cursor TYPE REF TO zif_abapgit_ajson_types=>ty_node. + DATA mv_tabix TYPE i. + DATA mv_has_next TYPE abap_bool. + METHODS find_first_node. + +ENDCLASS. + +CLASS kHGwlzjElomncUxrYaqWUAJitpOMkj IMPLEMENTATION. + + METHOD constructor. + + IF NOT ( iv_node_type = zif_abapgit_ajson_types=>node_type-array OR iv_node_type = zif_abapgit_ajson_types=>node_type-object ). + zcx_abapgit_ajson_error=>raise( |Iterator can iterate arrays or objects only ("{ iv_node_type }" passed)| ). + ENDIF. + + mv_base_path = zcl_abapgit_ajson=>normalize_path( iv_path ). + mv_node_type = iv_node_type. + mi_json = ii_json. + + DATA lv_node_type LIKE mv_node_type. + lv_node_type = ii_json->get_node_type( mv_base_path ). + + IF lv_node_type IS INITIAL. + zcx_abapgit_ajson_error=>raise( |Path not found: { iv_path }| ). + ELSEIF mv_node_type = zif_abapgit_ajson_types=>node_type-array AND lv_node_type <> mv_node_type. + zcx_abapgit_ajson_error=>raise( |Array expected at: { iv_path }| ). + ELSEIF mv_node_type = zif_abapgit_ajson_types=>node_type-object AND lv_node_type <> mv_node_type. + zcx_abapgit_ajson_error=>raise( |Object expected at: { iv_path }| ). + ENDIF. + + find_first_node( ). + + ENDMETHOD. + + METHOD find_first_node. + + CASE mv_node_type. + WHEN zif_abapgit_ajson_types=>node_type-array. + " path + array index key + LOOP AT mi_json->mt_json_tree REFERENCE INTO mr_cursor USING KEY array_index WHERE path = mv_base_path. + mv_has_next = abap_true. + mv_tabix = sy-tabix. + EXIT. " first found + ENDLOOP. + WHEN zif_abapgit_ajson_types=>node_type-object. + " regular path + name key + LOOP AT mi_json->mt_json_tree REFERENCE INTO mr_cursor WHERE path = mv_base_path. + mv_has_next = abap_true. + mv_tabix = sy-tabix. + EXIT. " first found + ENDLOOP. + WHEN OTHERS. + ASSERT 1 = 0. + ENDCASE. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_iterator~has_next. + rv_yes = mv_has_next. + ENDMETHOD. + + METHOD zif_abapgit_ajson_iterator~next. + + IF mv_has_next = abap_false. + RETURN. + ENDIF. + + ri_item = mi_json->slice( |{ mr_cursor->path }{ mr_cursor->name }| ). + " TODO: improve performance, see comment in slice, maybe reuse read only reference to node_tree + + mv_tabix = mv_tabix + 1. + CASE mv_node_type. + WHEN zif_abapgit_ajson_types=>node_type-array. + " path + array index key + READ TABLE mi_json->mt_json_tree + INDEX mv_tabix USING KEY array_index + REFERENCE INTO mr_cursor. + WHEN zif_abapgit_ajson_types=>node_type-object. + " regular path + name key + READ TABLE mi_json->mt_json_tree + INDEX mv_tabix + REFERENCE INTO mr_cursor. + WHEN OTHERS. + ASSERT 1 = 0. + ENDCASE. + mv_has_next = boolc( sy-subrc = 0 AND mr_cursor->path = mv_base_path ). + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_ajson_utilities IMPLEMENTATION. + METHOD delete_empty_nodes. + + DATA ls_json_tree LIKE LINE OF io_json->mt_json_tree. + DATA lv_done TYPE abap_bool. + + DO. + lv_done = abap_true. + + IF iv_keep_empty_arrays = abap_false. + LOOP AT io_json->mt_json_tree INTO ls_json_tree + WHERE type = zif_abapgit_ajson_types=>node_type-array AND children = 0. + + io_json->delete( ls_json_tree-path && ls_json_tree-name ). + + ENDLOOP. + IF sy-subrc = 0. + lv_done = abap_false. + ENDIF. + ENDIF. + + LOOP AT io_json->mt_json_tree INTO ls_json_tree + WHERE type = zif_abapgit_ajson_types=>node_type-object AND children = 0. + + io_json->delete( ls_json_tree-path && ls_json_tree-name ). + + ENDLOOP. + IF sy-subrc = 0. + lv_done = abap_false. + ENDIF. + + IF lv_done = abap_true. + EXIT. " nothing else to delete + ENDIF. + ENDDO. + + ENDMETHOD. + METHOD diff. + + mo_json_a = normalize_input( + iv_json = iv_json_a + io_json = io_json_a ). + + mo_json_b = normalize_input( + iv_json = iv_json_b + io_json = io_json_b ). + + mo_insert = zcl_abapgit_ajson=>create_empty( ). + mo_delete = zcl_abapgit_ajson=>create_empty( ). + mo_change = zcl_abapgit_ajson=>create_empty( ). + + diff_a_b( '/' ). + diff_b_a( '/' ). + + eo_insert ?= mo_insert. + eo_delete ?= mo_delete. + eo_change ?= mo_change. + + delete_empty_nodes( + io_json = eo_insert + iv_keep_empty_arrays = iv_keep_empty_arrays ). + delete_empty_nodes( + io_json = eo_delete + iv_keep_empty_arrays = iv_keep_empty_arrays ). + delete_empty_nodes( + io_json = eo_change + iv_keep_empty_arrays = iv_keep_empty_arrays ). + + ENDMETHOD. + METHOD diff_a_b. + + DATA: + lv_path_a TYPE string, + lv_path_b TYPE string. + + FIELD-SYMBOLS: + LIKE LINE OF mo_json_a->mt_json_tree, + LIKE LINE OF mo_json_a->mt_json_tree. + + LOOP AT mo_json_a->mt_json_tree ASSIGNING WHERE path = iv_path. + lv_path_a = -path && -name && '/'. + + READ TABLE mo_json_b->mt_json_tree ASSIGNING + WITH TABLE KEY path = -path name = -name. + IF sy-subrc = 0. + lv_path_b = -path && -name && '/'. + + IF -type = -type. + CASE -type. + WHEN zif_abapgit_ajson_types=>node_type-array. + mo_insert->touch_array( lv_path_a ). + mo_change->touch_array( lv_path_a ). + mo_delete->touch_array( lv_path_a ). + diff_a_b( lv_path_a ). + WHEN zif_abapgit_ajson_types=>node_type-object. + diff_a_b( lv_path_a ). + WHEN OTHERS. + IF -value <> -value. + " save as changed value + mo_change->set( + iv_path = lv_path_b + iv_val = -value + iv_node_type = -type ). + ENDIF. + ENDCASE. + ELSE. + " save changed type as delete + insert + CASE -type. + WHEN zif_abapgit_ajson_types=>node_type-array. + mo_delete->touch_array( lv_path_a ). + diff_a_b( lv_path_a ). + WHEN zif_abapgit_ajson_types=>node_type-object. + diff_a_b( lv_path_a ). + WHEN OTHERS. + mo_delete->set( + iv_path = lv_path_a + iv_val = -value + iv_node_type = -type ). + ENDCASE. + CASE -type. + WHEN zif_abapgit_ajson_types=>node_type-array. + mo_insert->touch_array( lv_path_b ). + diff_b_a( lv_path_b ). + WHEN zif_abapgit_ajson_types=>node_type-object. + diff_b_a( lv_path_b ). + WHEN OTHERS. + mo_insert->set( + iv_path = lv_path_b + iv_val = -value + iv_node_type = -type ). + ENDCASE. + ENDIF. + ELSE. + " save as delete + CASE -type. + WHEN zif_abapgit_ajson_types=>node_type-array. + mo_delete->touch_array( lv_path_a ). + diff_a_b( lv_path_a ). + WHEN zif_abapgit_ajson_types=>node_type-object. + diff_a_b( lv_path_a ). + WHEN OTHERS. + mo_delete->set( + iv_path = lv_path_a + iv_val = -value + iv_node_type = -type ). + ENDCASE. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD diff_b_a. + + DATA lv_path TYPE string. + + FIELD-SYMBOLS LIKE LINE OF mo_json_b->mt_json_tree. + + LOOP AT mo_json_b->mt_json_tree ASSIGNING WHERE path = iv_path. + lv_path = -path && -name && '/'. + + CASE -type. + WHEN zif_abapgit_ajson_types=>node_type-array. + mo_insert->touch_array( lv_path ). + diff_b_a( + iv_path = lv_path + iv_array = abap_true ). + WHEN zif_abapgit_ajson_types=>node_type-object. + diff_b_a( lv_path ). + WHEN OTHERS. + IF iv_array = abap_false. + READ TABLE mo_json_a->mt_json_tree TRANSPORTING NO FIELDS + WITH TABLE KEY path = -path name = -name. + IF sy-subrc <> 0. + " save as insert + mo_insert->set( + iv_path = lv_path + iv_val = -value + iv_node_type = -type ). + ENDIF. + ELSE. + READ TABLE mo_insert->mt_json_tree TRANSPORTING NO FIELDS + WITH KEY path = -path value = -value. + IF sy-subrc <> 0. + " save as new array value + mo_insert->push( + iv_path = iv_path + iv_val = -value ). + ENDIF. + ENDIF. + ENDCASE. + ENDLOOP. + + ENDMETHOD. + METHOD is_equal. + + DATA li_ins TYPE REF TO zif_abapgit_ajson. + DATA li_del TYPE REF TO zif_abapgit_ajson. + DATA li_mod TYPE REF TO zif_abapgit_ajson. + + diff( + EXPORTING + iv_json_a = iv_json_a + iv_json_b = iv_json_b + io_json_a = ii_json_a + io_json_b = ii_json_b + IMPORTING + eo_insert = li_ins + eo_delete = li_del + eo_change = li_mod ). + + rv_yes = boolc( + li_ins->is_empty( ) = abap_true AND + li_del->is_empty( ) = abap_true AND + li_mod->is_empty( ) = abap_true ). + + ENDMETHOD. + METHOD iterate_array. + + CREATE OBJECT ri_iterator TYPE kHGwlzjElomncUxrYaqWUAJitpOMkj + EXPORTING + iv_node_type = zif_abapgit_ajson_types=>node_type-array + ii_json = ii_json + iv_path = iv_path. + + ENDMETHOD. + METHOD iterate_object. + + CREATE OBJECT ri_iterator TYPE kHGwlzjElomncUxrYaqWUAJitpOMkj + EXPORTING + iv_node_type = zif_abapgit_ajson_types=>node_type-object + ii_json = ii_json + iv_path = iv_path. + + ENDMETHOD. + METHOD merge. + + mo_json_a = normalize_input( + iv_json = iv_json_a + io_json = io_json_a ). + + mo_json_b = normalize_input( + iv_json = iv_json_b + io_json = io_json_b ). + + " Start with first JSON... + mo_insert = mo_json_a. + + " ...and add all nodes from second JSON + diff_b_a( '/' ). + + ro_json ?= mo_insert. + + delete_empty_nodes( + io_json = ro_json + iv_keep_empty_arrays = iv_keep_empty_arrays ). + + ENDMETHOD. + METHOD new. + CREATE OBJECT ro_instance. + ENDMETHOD. + METHOD normalize_input. + + IF boolc( iv_json IS INITIAL ) = boolc( io_json IS INITIAL ). + zcx_abapgit_ajson_error=>raise( 'Either supply JSON string or instance, but not both' ). + ENDIF. + + IF iv_json IS NOT INITIAL. + ro_json = zcl_abapgit_ajson=>parse( iv_json ). + ELSEIF io_json IS NOT INITIAL. + ro_json = io_json. + ELSE. + zcx_abapgit_ajson_error=>raise( 'Supply either JSON string or instance' ). + ENDIF. + + ENDMETHOD. + METHOD sort. + + DATA lo_json TYPE REF TO zif_abapgit_ajson. + + lo_json = normalize_input( + iv_json = iv_json + io_json = io_json ). + + " Nodes are parsed into a sorted table, so no explicit sorting required + rv_sorted = lo_json->stringify( 2 ). + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlHDWSdIldBDGuoLDwnaXDwGzZm DEFINITION DEFERRED. +********************************************************************** +* INITIALIZE REFS BY PATH +********************************************************************** + +* renamed: zcl_abapgit_ajson_ref_init_lib :: lcl_path_refs_init +CLASS kHGwlHDWSdIldBDGuoLDwnaXDwGzZm DEFINITION. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_ref_init. + + METHODS constructor + IMPORTING + !it_data_refs TYPE zif_abapgit_ajson_ref_init~tty_data_refs. + + PRIVATE SECTION. + DATA mt_data_refs TYPE zif_abapgit_ajson_ref_init~tty_data_refs. +ENDCLASS. + +CLASS kHGwlHDWSdIldBDGuoLDwnaXDwGzZm IMPLEMENTATION. + + METHOD constructor. + mt_data_refs = it_data_refs. + ENDMETHOD. + + METHOD zif_abapgit_ajson_ref_init~get_data_ref. + + FIELD-SYMBOLS LIKE LINE OF mt_data_refs. + + READ TABLE mt_data_refs ASSIGNING + WITH KEY by_path COMPONENTS path = is_node-path name = is_node-name. + IF sy-subrc = 0. + ro_ref = -dref. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_ajson_ref_init_lib IMPLEMENTATION. + METHOD create_path_refs_init. + CREATE OBJECT ri_refs_init TYPE kHGwlHDWSdIldBDGuoLDwnaXDwGzZm + EXPORTING + it_data_refs = it_data_refs. + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlpuwVGRXmbkWZJMoTFhfUGDgXz IMPLEMENTATION. "DEPRECATED + METHOD constructor. + + DATA ls_mapping_field LIKE LINE OF mt_mapping_fields. + + LOOP AT it_mapping_fields INTO ls_mapping_field. + ls_mapping_field-abap = to_upper( ls_mapping_field-abap ). + INSERT ls_mapping_field INTO TABLE mt_mapping_fields. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~to_abap. + + DATA ls_mapping_field LIKE LINE OF mt_mapping_fields. + + READ TABLE mt_mapping_fields INTO ls_mapping_field + WITH KEY json COMPONENTS json = iv_name. + IF sy-subrc = 0. + rv_result = ls_mapping_field-abap. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~to_json. + + DATA lv_field TYPE string. + DATA ls_mapping_field LIKE LINE OF mt_mapping_fields. + + lv_field = to_upper( iv_name ). + + READ TABLE mt_mapping_fields INTO ls_mapping_field + WITH KEY abap COMPONENTS abap = lv_field. + IF sy-subrc = 0. + rv_result = ls_mapping_field-json. + ENDIF. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + ENDMETHOD. + +ENDCLASS. + +CLASS kHGwlpuwVGRXmbkWZJMocwrelrEIET IMPLEMENTATION. + + METHOD constructor. + mt_rename_map = it_rename_map. + mv_rename_by = iv_rename_by. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + DATA lv_full_path TYPE string. + DATA lv_pair_found TYPE abap_bool. + FIELD-SYMBOLS LIKE LINE OF mt_rename_map. + + CASE mv_rename_by. + WHEN zcl_abapgit_ajson_mapping=>rename_by-attr_name. + READ TABLE mt_rename_map ASSIGNING WITH TABLE KEY by_name COMPONENTS from = cv_name. + lv_pair_found = boolc( sy-subrc = 0 ). + WHEN zcl_abapgit_ajson_mapping=>rename_by-full_path. + lv_full_path = is_node-path && cv_name. + READ TABLE mt_rename_map ASSIGNING WITH TABLE KEY by_name COMPONENTS from = lv_full_path. + lv_pair_found = boolc( sy-subrc = 0 ). + WHEN zcl_abapgit_ajson_mapping=>rename_by-pattern. + lv_full_path = is_node-path && cv_name. + LOOP AT mt_rename_map ASSIGNING . + IF lv_full_path CP -from. + lv_pair_found = abap_true. + EXIT. + ENDIF. + ENDLOOP. + WHEN OTHERS. + lv_pair_found = abap_false. " No rename + ENDCASE. + + IF lv_pair_found = abap_true. + cv_name = -to. + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +CLASS kHGwlpuwVGRXmbkWZJMoayhtkOTSGN IMPLEMENTATION. + METHOD constructor. + + mi_mapping_fields = zcl_abapgit_ajson_mapping=>create_field_mapping( it_mapping_fields ). + + ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~to_abap. + + rv_result = mi_mapping_fields->to_abap( iv_path = iv_path + iv_name = iv_name ). + + ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~to_json. + + rv_result = mi_mapping_fields->to_json( iv_path = iv_path + iv_name = iv_name ). + + IF rv_result IS NOT INITIAL. " Mapping found + RETURN. + ENDIF. + + rv_result = to_upper( iv_name ). + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + cv_name = to_upper( cv_name ). + + ENDMETHOD. + +ENDCLASS. +CLASS kHGwlpuwVGRXmbkWZJMoIaLFAtEmIg IMPLEMENTATION. + METHOD constructor. + + mi_mapping_fields = zcl_abapgit_ajson_mapping=>create_field_mapping( it_mapping_fields ). + + ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~to_abap. + + rv_result = mi_mapping_fields->to_abap( iv_path = iv_path + iv_name = iv_name ). + + ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~to_json. + + rv_result = mi_mapping_fields->to_json( iv_path = iv_path + iv_name = iv_name ). + + IF rv_result IS NOT INITIAL. " Mapping found + RETURN. + ENDIF. + + rv_result = to_lower( iv_name ). + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + cv_name = to_lower( cv_name ). + + ENDMETHOD. + +ENDCLASS. +CLASS kHGwlpuwVGRXmbkWZJMoYWDnXPYsQA IMPLEMENTATION. "DEPRECATED + METHOD constructor. + + mi_mapping_fields = zcl_abapgit_ajson_mapping=>create_field_mapping( it_mapping_fields ). + mv_first_json_upper = iv_first_json_upper. + + ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~to_abap. + + rv_result = mi_mapping_fields->to_abap( iv_path = iv_path + iv_name = iv_name ). + + IF rv_result IS NOT INITIAL. " Mapping found + RETURN. + ENDIF. + + rv_result = iv_name. + + REPLACE ALL OCCURRENCES OF REGEX `([a-z])([A-Z])` IN rv_result WITH `$1_$2`. + + ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~to_json. + + TYPES ty_token TYPE c LENGTH 255. + DATA lt_tokens TYPE STANDARD TABLE OF ty_token. + DATA lv_from TYPE i. + FIELD-SYMBOLS LIKE LINE OF lt_tokens. + + rv_result = mi_mapping_fields->to_json( iv_path = iv_path + iv_name = iv_name ). + + IF rv_result IS NOT INITIAL. " Mapping found + RETURN. + ENDIF. + + rv_result = iv_name. + + REPLACE ALL OCCURRENCES OF `__` IN rv_result WITH `*`. + + TRANSLATE rv_result TO LOWER CASE. + TRANSLATE rv_result USING `/_:_~_`. + + IF mv_first_json_upper = abap_true. + lv_from = 1. + ELSE. + lv_from = 2. + ENDIF. + + SPLIT rv_result AT `_` INTO TABLE lt_tokens. + LOOP AT lt_tokens ASSIGNING FROM lv_from. + TRANSLATE (1) TO UPPER CASE. + ENDLOOP. + + CONCATENATE LINES OF lt_tokens INTO rv_result. + REPLACE ALL OCCURRENCES OF `*` IN rv_result WITH `_`. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + ENDMETHOD. + +ENDCLASS. + +CLASS kHGwlpuwVGRXmbkWZJMooAlevhaDMg IMPLEMENTATION. + + METHOD constructor. + mt_queue = it_queue. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + DATA ls_node LIKE is_node. + DATA li_mapper LIKE LINE OF mt_queue. + + ls_node = is_node. + + LOOP AT mt_queue INTO li_mapper. + li_mapper->rename_node( + EXPORTING + is_node = ls_node + CHANGING + cv_name = cv_name ). + ls_node-name = cv_name. + ENDLOOP. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + + ENDMETHOD. + +ENDCLASS. + +CLASS kHGwlpuwVGRXmbkWZJMorCLylKulMM IMPLEMENTATION. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + REPLACE ALL OCCURRENCES OF REGEX `([a-z])([A-Z])` IN cv_name WITH `$1_$2`. + cv_name = to_lower( cv_name ). + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + + ENDMETHOD. + +ENDCLASS. + +CLASS kHGwlpuwVGRXmbkWZJMoWRsLzEdjUi IMPLEMENTATION. + + METHOD constructor. + mv_first_json_upper = iv_first_json_upper. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + TYPES lty_token TYPE c LENGTH 255. + CONSTANTS lc_forced_underscore_marker TYPE c LENGTH 1 VALUE cl_abap_char_utilities=>horizontal_tab. + + DATA lt_tokens TYPE STANDARD TABLE OF lty_token. + DATA lv_from TYPE i. + FIELD-SYMBOLS LIKE LINE OF lt_tokens. + + IF mv_first_json_upper = abap_true. + lv_from = 1. + ELSE. + lv_from = 2. + ENDIF. + REPLACE ALL OCCURRENCES OF `__` IN cv_name WITH lc_forced_underscore_marker. " Force underscore + + SPLIT cv_name AT `_` INTO TABLE lt_tokens. + DELETE lt_tokens WHERE table_line IS INITIAL. + LOOP AT lt_tokens ASSIGNING FROM lv_from. + TRANSLATE +0(1) TO UPPER CASE. + ENDLOOP. + + CONCATENATE LINES OF lt_tokens INTO cv_name. + REPLACE ALL OCCURRENCES OF lc_forced_underscore_marker IN cv_name WITH `_`. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_ajson_mapping IMPLEMENTATION. + METHOD create_camel_case. + + CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoYWDnXPYsQA + EXPORTING + it_mapping_fields = it_mapping_fields + iv_first_json_upper = iv_first_json_upper. + + ENDMETHOD. + METHOD create_compound_mapper. + + DATA lt_queue TYPE zif_abapgit_ajson_mapping=>ty_table_of. + + APPEND ii_mapper1 TO lt_queue. + APPEND ii_mapper2 TO lt_queue. + APPEND ii_mapper3 TO lt_queue. + APPEND LINES OF it_more TO lt_queue. + DELETE lt_queue WHERE table_line IS INITIAL. + + CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMooAlevhaDMg + EXPORTING + it_queue = lt_queue. + + ENDMETHOD. + METHOD create_field_mapping. + + CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoTFhfUGDgXz + EXPORTING + it_mapping_fields = it_mapping_fields. + + ENDMETHOD. + METHOD create_lower_case. + + CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoIaLFAtEmIg + EXPORTING + it_mapping_fields = it_mapping_fields. + + ENDMETHOD. + METHOD create_rename. + + CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMocwrelrEIET + EXPORTING + it_rename_map = it_rename_map + iv_rename_by = iv_rename_by. + + ENDMETHOD. + METHOD create_to_camel_case. + + CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoWRsLzEdjUi + EXPORTING + iv_first_json_upper = iv_first_json_upper. + + ENDMETHOD. + METHOD create_to_snake_case. + + CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMorCLylKulMM. + + ENDMETHOD. + METHOD create_upper_case. + + CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoayhtkOTSGN + EXPORTING + it_mapping_fields = it_mapping_fields. + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlqZELdDwrxoEPdVyarIhEaaLQd DEFINITION DEFERRED. +CLASS kHGwlqZELdDwrxoEPdVyKlBZxFUUhA DEFINITION DEFERRED. +CLASS kHGwlqZELdDwrxoEPdVyHkqTfrNjtW DEFINITION DEFERRED. +********************************************************************** +* FILTER EMPTY VALUES +********************************************************************** + +* renamed: zcl_abapgit_ajson_filter_lib :: lcl_empty_filter +CLASS kHGwlqZELdDwrxoEPdVyHkqTfrNjtW DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_filter. +ENDCLASS. + +CLASS kHGwlqZELdDwrxoEPdVyHkqTfrNjtW IMPLEMENTATION. + METHOD zif_abapgit_ajson_filter~keep_node. + + rv_keep = boolc( + ( iv_visit = zif_abapgit_ajson_filter=>visit_type-value AND is_node-value IS NOT INITIAL ) OR + ( iv_visit <> zif_abapgit_ajson_filter=>visit_type-value AND is_node-children > 0 ) ). + " children = 0 on open for initially empty nodes and on close for filtered ones + + ENDMETHOD. +ENDCLASS. + +********************************************************************** +* FILTER PREDEFINED PATHS +********************************************************************** + +* renamed: zcl_abapgit_ajson_filter_lib :: lcl_paths_filter +CLASS kHGwlqZELdDwrxoEPdVyKlBZxFUUhA DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_filter. + METHODS constructor + IMPORTING + it_skip_paths TYPE string_table OPTIONAL + iv_skip_paths TYPE string OPTIONAL + iv_pattern_search TYPE abap_bool + RAISING + zcx_abapgit_ajson_error. + PRIVATE SECTION. + DATA mt_skip_paths TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line. + DATA mv_pattern_search TYPE abap_bool. +ENDCLASS. + +CLASS kHGwlqZELdDwrxoEPdVyKlBZxFUUhA IMPLEMENTATION. + + METHOD zif_abapgit_ajson_filter~keep_node. + + DATA lv_full_path TYPE string. + FIELD-SYMBOLS

LIKE LINE OF mt_skip_paths. + + lv_full_path = is_node-path && is_node-name. + + IF mv_pattern_search = abap_true. + rv_keep = abap_true. + LOOP AT mt_skip_paths ASSIGNING

. + IF lv_full_path CP

. + rv_keep = abap_false. + EXIT. + ENDIF. + ENDLOOP. + ELSE. + READ TABLE mt_skip_paths WITH KEY table_line = lv_full_path TRANSPORTING NO FIELDS. + rv_keep = boolc( sy-subrc <> 0 ). + ENDIF. + + ENDMETHOD. + + METHOD constructor. + + DATA lv_s TYPE string. + DATA lt_tab TYPE string_table. + FIELD-SYMBOLS TYPE string. + + IF boolc( iv_skip_paths IS INITIAL ) = boolc( it_skip_paths IS INITIAL ). " XOR + zcx_abapgit_ajson_error=>raise( 'no filter path specified' ). + ENDIF. + + LOOP AT it_skip_paths INTO lv_s. + lv_s = condense( lv_s ). + APPEND lv_s TO lt_tab. + ENDLOOP. + + IF iv_skip_paths IS NOT INITIAL. + SPLIT iv_skip_paths AT ',' INTO TABLE lt_tab. + LOOP AT lt_tab ASSIGNING . + IF IS INITIAL. + DELETE lt_tab INDEX sy-tabix. + CONTINUE. + ENDIF. + = condense( ). + ENDLOOP. + ENDIF. + + SORT lt_tab BY table_line. + DELETE ADJACENT DUPLICATES FROM lt_tab. + + mt_skip_paths = lt_tab. + mv_pattern_search = iv_pattern_search. + + ENDMETHOD. + +ENDCLASS. + +********************************************************************** +* MULTI FILTER +********************************************************************** + +* renamed: zcl_abapgit_ajson_filter_lib :: lcl_and_filter +CLASS kHGwlqZELdDwrxoEPdVyarIhEaaLQd DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_filter. + METHODS constructor + IMPORTING + it_filters TYPE zif_abapgit_ajson_filter=>ty_filter_tab + RAISING + zcx_abapgit_ajson_error. + PRIVATE SECTION. + DATA mt_filters TYPE zif_abapgit_ajson_filter=>ty_filter_tab. +ENDCLASS. + +CLASS kHGwlqZELdDwrxoEPdVyarIhEaaLQd IMPLEMENTATION. + + METHOD zif_abapgit_ajson_filter~keep_node. + + DATA li_filter LIKE LINE OF mt_filters. + + rv_keep = abap_true. + LOOP AT mt_filters INTO li_filter. + rv_keep = li_filter->keep_node( + is_node = is_node + iv_visit = iv_visit ). + IF rv_keep = abap_false. + RETURN. + ENDIF. + ENDLOOP. + + ENDMETHOD. + + METHOD constructor. + + DATA li_filter LIKE LINE OF it_filters. + + LOOP AT it_filters INTO li_filter WHERE table_line IS BOUND. + APPEND li_filter TO mt_filters. + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_ajson_filter_lib IMPLEMENTATION. + METHOD create_and_filter. + CREATE OBJECT ri_filter TYPE kHGwlqZELdDwrxoEPdVyarIhEaaLQd + EXPORTING + it_filters = it_filters. + ENDMETHOD. + METHOD create_empty_filter. + CREATE OBJECT ri_filter TYPE kHGwlqZELdDwrxoEPdVyHkqTfrNjtW. + ENDMETHOD. + METHOD create_path_filter. + CREATE OBJECT ri_filter TYPE kHGwlqZELdDwrxoEPdVyKlBZxFUUhA + EXPORTING + iv_pattern_search = iv_pattern_search + it_skip_paths = it_skip_paths + iv_skip_paths = iv_skip_paths. + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlMWhQrsNKkKXALnpucOpllUiAS DEFINITION DEFERRED. +CLASS kHGwlMWhQrsNKkKXALnphFTcRDbOtm DEFINITION DEFERRED. +CLASS kHGwlMWhQrsNKkKXALnplwblMIpVBS DEFINITION DEFERRED. +INTERFACE iUFTsMWhQrsNKkKXALnptzVIYRIbuu DEFERRED. +CLASS kHGwlMWhQrsNKkKXALnpeJqampzabz DEFINITION DEFERRED. +CLASS kHGwlMWhQrsNKkKXALnpXxNdxsjJjI DEFINITION DEFERRED. +CLASS kHGwlMWhQrsNKkKXALnpFgyFungUrS DEFINITION DEFERRED. +CLASS kHGwlMWhQrsNKkKXALnpfipvepHQnc DEFINITION DEFERRED. +CLASS kHGwlMWhQrsNKkKXALnpzByNvbZmNu DEFINITION DEFERRED. +INTERFACE iUFTsMWhQrsNKkKXALnpdAMURRqLkF DEFERRED. +********************************************************************** +* UTILS +********************************************************************** + +* renamed: zcl_abapgit_ajson :: lif_kind +INTERFACE iUFTsMWhQrsNKkKXALnpdAMURRqLkF. + + TYPES ty_kind TYPE c LENGTH 1. + + CONSTANTS: + any TYPE ty_kind VALUE cl_abap_typedescr=>typekind_any, + date TYPE ty_kind VALUE cl_abap_typedescr=>typekind_date, + time TYPE ty_kind VALUE cl_abap_typedescr=>typekind_time, + packed TYPE ty_kind VALUE cl_abap_typedescr=>typekind_packed, + table TYPE ty_kind VALUE cl_abap_typedescr=>typekind_table, + struct_flat TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct1, + struct_deep TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct2, + data_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_dref, + object_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_oref, + utclong TYPE ty_kind VALUE 'p', " cl_abap_typedescr=>typekind_utclong not in lower releases + enum TYPE ty_kind VALUE 'k'. " cl_abap_typedescr=>typekind_enum not in lower releases + + CONSTANTS: + BEGIN OF numeric, + int1 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_int1, + int2 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_int2, + int4 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_int, + int8 TYPE ty_kind VALUE '8', " cl_abap_typedescr=>typekind_int8 not in lower releases + float TYPE ty_kind VALUE cl_abap_typedescr=>typekind_float, + packed TYPE ty_kind VALUE cl_abap_typedescr=>typekind_packed, + decfloat16 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_decfloat16, + decfloat34 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_decfloat34, + END OF numeric. + + CONSTANTS: + BEGIN OF texts, + char TYPE ty_kind VALUE cl_abap_typedescr=>typekind_char, + numc TYPE ty_kind VALUE cl_abap_typedescr=>typekind_num, + string TYPE ty_kind VALUE cl_abap_typedescr=>typekind_string, + END OF texts. + + CONSTANTS: + BEGIN OF binary, + hex TYPE ty_kind VALUE cl_abap_typedescr=>typekind_hex, + xstring TYPE ty_kind VALUE cl_abap_typedescr=>typekind_xstring, + END OF binary. + + CONSTANTS: + BEGIN OF deep_targets, + table TYPE ty_kind VALUE cl_abap_typedescr=>typekind_table, + struct_flat TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct1, + struct_deep TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct2, + data_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_dref, + object_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_oref, + END OF deep_targets. + +ENDINTERFACE. + +* renamed: zcl_abapgit_ajson :: lcl_utils +CLASS kHGwlMWhQrsNKkKXALnpzByNvbZmNu DEFINITION FINAL. + PUBLIC SECTION. + + CLASS-METHODS normalize_path + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_path) TYPE string. + CLASS-METHODS split_path + IMPORTING + iv_path TYPE string + RETURNING + VALUE(rv_path_name) TYPE zif_abapgit_ajson_types=>ty_path_name. + CLASS-METHODS validate_array_index + IMPORTING + iv_path TYPE string + iv_index TYPE string + RETURNING + VALUE(rv_index) TYPE i + RAISING + zcx_abapgit_ajson_error. + CLASS-METHODS string_to_xstring_utf8 + IMPORTING + iv_str TYPE string + RETURNING + VALUE(rv_xstr) TYPE xstring. + CLASS-METHODS xstring_to_string_utf8 + IMPORTING + iv_xstr TYPE xstring + RETURNING + VALUE(rv_str) TYPE string. + CLASS-METHODS any_to_xstring + IMPORTING + iv_data TYPE any + RETURNING + VALUE(rv_xstr) TYPE xstring + RAISING + zcx_abapgit_ajson_error. + CLASS-METHODS any_to_string + IMPORTING + iv_data TYPE any + RETURNING + VALUE(rv_str) TYPE string + RAISING + zcx_abapgit_ajson_error. + CLASS-METHODS sanity_check + IMPORTING + iv_data TYPE csequence + RAISING + zcx_abapgit_ajson_error. + +ENDCLASS. + +CLASS kHGwlMWhQrsNKkKXALnpzByNvbZmNu IMPLEMENTATION. + + METHOD string_to_xstring_utf8. + + DATA lo_conv TYPE REF TO object. + DATA lv_out_ce TYPE string. + + lv_out_ce = 'CL_ABAP_CONV_OUT_CE'. + + TRY. + CALL METHOD ('CL_ABAP_CONV_CODEPAGE')=>create_out + RECEIVING + instance = lo_conv. + CALL METHOD lo_conv->('IF_ABAP_CONV_OUT~CONVERT') + EXPORTING + source = iv_str + RECEIVING + result = rv_xstr. + CATCH cx_sy_dyn_call_illegal_class. + CALL METHOD (lv_out_ce)=>create + EXPORTING + encoding = 'UTF-8' + RECEIVING + conv = lo_conv. + CALL METHOD lo_conv->('CONVERT') + EXPORTING + data = iv_str + IMPORTING + buffer = rv_xstr. + ENDTRY. + + ENDMETHOD. + + METHOD xstring_to_string_utf8. + + DATA lo_conv TYPE REF TO object. + DATA lv_in_ce TYPE string. + + lv_in_ce = 'CL_ABAP_CONV_IN_CE'. + + TRY. + CALL METHOD ('CL_ABAP_CONV_CODEPAGE')=>create_in + RECEIVING + instance = lo_conv. + CALL METHOD lo_conv->('IF_ABAP_CONV_IN~CONVERT') + EXPORTING + source = iv_xstr + RECEIVING + result = rv_str. + CATCH cx_sy_dyn_call_illegal_class. + CALL METHOD (lv_in_ce)=>create + EXPORTING + encoding = 'UTF-8' + RECEIVING + conv = lo_conv. + CALL METHOD lo_conv->('CONVERT') + EXPORTING + data = iv_xstr + IMPORTING + buffer = rv_str. + ENDTRY. + + ENDMETHOD. + + METHOD validate_array_index. + + IF NOT iv_index CO '0123456789'. + zcx_abapgit_ajson_error=>raise( |Cannot add non-numeric key [{ iv_index }] to array [{ iv_path }]| ). + ENDIF. + rv_index = iv_index. + IF rv_index = 0. + zcx_abapgit_ajson_error=>raise( |Cannot add zero key to array [{ iv_path }]| ). + ENDIF. + + ENDMETHOD. + + METHOD normalize_path. + + rv_path = iv_path. + IF strlen( rv_path ) = 0. + rv_path = '/'. + ENDIF. + IF rv_path+0(1) <> '/'. + rv_path = '/' && rv_path. + ENDIF. + IF substring( val = rv_path + off = strlen( rv_path ) - 1 ) <> '/'. + rv_path = rv_path && '/'. + ENDIF. + + ENDMETHOD. + + METHOD split_path. + + DATA lv_offs TYPE i. + DATA lv_len TYPE i. + DATA lv_trim_slash TYPE i. + + lv_len = strlen( iv_path ). + IF lv_len = 0 OR iv_path = '/'. + RETURN. " empty path is the alias for root item = '' + '' + ENDIF. + + IF substring( val = iv_path + off = lv_len - 1 ) = '/'. + lv_trim_slash = 1. " ignore last '/' + ENDIF. + + lv_offs = find( val = reverse( iv_path ) + sub = '/' + off = lv_trim_slash ). + IF lv_offs = -1. + lv_offs = lv_len. " treat whole string as the 'name' part + ENDIF. + lv_offs = lv_len - lv_offs. + + rv_path_name-path = normalize_path( substring( val = iv_path + len = lv_offs ) ). + rv_path_name-name = substring( val = iv_path + off = lv_offs + len = lv_len - lv_offs - lv_trim_slash ). + " Replace tabs with slash to get original value + rv_path_name-name = replace( + val = rv_path_name-name + sub = cl_abap_char_utilities=>horizontal_tab + with = '/' + occ = 0 ). + + ENDMETHOD. + + METHOD any_to_xstring. + " supports xstring, char, string, or string_table as input + + DATA lo_type TYPE REF TO cl_abap_typedescr. + DATA lo_table_type TYPE REF TO cl_abap_tabledescr. + DATA lv_str TYPE string. + + FIELD-SYMBOLS: TYPE STANDARD TABLE. + + lo_type = cl_abap_typedescr=>describe_by_data( iv_data ). + + CASE lo_type->type_kind. + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>binary-xstring. + " in case of binary data, skip the sanity check to have best performance + rv_xstr = iv_data. + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>texts-string OR iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>texts-char. + sanity_check( iv_data ). + rv_xstr = string_to_xstring_utf8( iv_data ). + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. + lo_table_type ?= lo_type. + IF lo_table_type->table_kind <> cl_abap_tabledescr=>tablekind_std. + zcx_abapgit_ajson_error=>raise( 'Unsupported type of input table (must be standard table)' ). + ENDIF. + TRY. + ASSIGN iv_data TO . + lv_str = concat_lines_of( table = + sep = cl_abap_char_utilities=>newline ). + sanity_check( lv_str ). + rv_xstr = string_to_xstring_utf8( lv_str ). + CATCH cx_root. + zcx_abapgit_ajson_error=>raise( 'Error converting input table (should be string_table)' ). + ENDTRY. + WHEN OTHERS. + zcx_abapgit_ajson_error=>raise( 'Unsupported type of input (must be char, string, string_table, or xstring)' ). + ENDCASE. + + ENDMETHOD. + + METHOD any_to_string. + " supports xstring, char, string, or string_table as input + + DATA lo_type TYPE REF TO cl_abap_typedescr. + DATA lo_table_type TYPE REF TO cl_abap_tabledescr. + + FIELD-SYMBOLS: TYPE STANDARD TABLE. + + lo_type = cl_abap_typedescr=>describe_by_data( iv_data ). + + CASE lo_type->type_kind. + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>binary-xstring. + rv_str = xstring_to_string_utf8( iv_data ). + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>texts-string OR iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>texts-char. + rv_str = iv_data. + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. + lo_table_type ?= lo_type. + IF lo_table_type->table_kind <> cl_abap_tabledescr=>tablekind_std. + zcx_abapgit_ajson_error=>raise( 'Unsupported type of input table (must be standard table)' ). + ENDIF. + TRY. + ASSIGN iv_data TO . + rv_str = concat_lines_of( table = + sep = cl_abap_char_utilities=>newline ). + CATCH cx_root. + zcx_abapgit_ajson_error=>raise( 'Error converting input table (should be string_table)' ). + ENDTRY. + WHEN OTHERS. + zcx_abapgit_ajson_error=>raise( 'Unsupported type of input (must be char, string, string_table, or xstring)' ). + ENDCASE. + + ENDMETHOD. + + METHOD sanity_check. + + " A lightweight check covering the top-level JSON value would look like this + " ^\s*(\{.*\}|\[.*\]|"(?:\\.|[^"\\])*"|true|false|null|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\s*$ + " Unfortunately, this is quite slow so we use a trivial check of the beginning of the JSON data + FIND REGEX '^\s*(true|false|null|-?\d|"|\{|\[)' IN iv_data. + IF sy-subrc <> 0. + zcx_abapgit_ajson_error=>raise( + iv_msg = |Json parsing error: Not JSON| + iv_location = 'Line 1, Offset 1' ). + ENDIF. + + ENDMETHOD. + +ENDCLASS. +********************************************************************** +* PARSER +********************************************************************** + +* renamed: zcl_abapgit_ajson :: lcl_json_parser +CLASS kHGwlMWhQrsNKkKXALnpfipvepHQnc DEFINITION FINAL. + PUBLIC SECTION. + + METHODS parse + IMPORTING + iv_json TYPE any + iv_keep_item_order TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_json_tree) TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + + PRIVATE SECTION. + + TYPES: + ty_stack_tt TYPE STANDARD TABLE OF REF TO zif_abapgit_ajson_types=>ty_node. + + DATA mt_stack TYPE ty_stack_tt. + DATA mv_stack_path TYPE string. + DATA mv_keep_item_order TYPE abap_bool. + + METHODS raise + IMPORTING + iv_error TYPE string + RAISING + zcx_abapgit_ajson_error. + + METHODS _parse + IMPORTING + iv_json TYPE xstring + RETURNING + VALUE(rt_json_tree) TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error cx_dynamic_check. " cx_sxml_error is not released on Steampunk #153 + + METHODS _get_location + IMPORTING + iv_json TYPE string + iv_offset TYPE i + RETURNING + VALUE(rv_location) TYPE string. + +ENDCLASS. + +CLASS kHGwlMWhQrsNKkKXALnpfipvepHQnc IMPLEMENTATION. + + METHOD parse. + DATA lx_sxml_parse TYPE REF TO cx_sxml_parse_error. + DATA lx_sxml TYPE REF TO cx_dynamic_check. + DATA lv_location TYPE string. + DATA lv_json TYPE xstring. + + mv_keep_item_order = iv_keep_item_order. + + " Includes lightweight sanity check (unless input is binary) + lv_json = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>any_to_xstring( iv_json ). + + TRY. + rt_json_tree = _parse( lv_json ). + CATCH cx_sxml_parse_error INTO lx_sxml_parse. + lv_location = _get_location( + iv_json = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>any_to_string( iv_json ) + iv_offset = lx_sxml_parse->xml_offset ). + zcx_abapgit_ajson_error=>raise( + iv_msg = |Json parsing error (SXML): { lx_sxml_parse->get_text( ) }| + iv_location = lv_location ). + CATCH cx_dynamic_check INTO lx_sxml. " cx_sxml_error + zcx_abapgit_ajson_error=>raise( + iv_msg = |Json parsing error (SXML): { lx_sxml->get_text( ) }| + iv_location = '@PARSER' ). + ENDTRY. + + ENDMETHOD. + + METHOD _get_location. + + DATA lv_json TYPE string. + DATA lv_offset TYPE i. + DATA lt_text TYPE TABLE OF string. + DATA lv_text TYPE string. + DATA lv_line TYPE i. + DATA lv_pos TYPE i. + + lv_offset = iv_offset. + IF lv_offset < 0. + lv_offset = 0. + ENDIF. + IF lv_offset > strlen( iv_json ). + lv_offset = strlen( iv_json ). + ENDIF. + + lv_json = iv_json(lv_offset). + + REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf + IN lv_json WITH cl_abap_char_utilities=>newline. + + SPLIT lv_json AT cl_abap_char_utilities=>newline INTO TABLE lt_text. + + lv_line = lines( lt_text ). + IF lv_line = 0. + lv_line = 1. + lv_pos = 1. + ELSE. + READ TABLE lt_text INDEX lv_line INTO lv_text. + lv_pos = strlen( lv_text ) + 1. + ENDIF. + + rv_location = |Line { lv_line }, Offset { lv_pos }|. + + ENDMETHOD. + + METHOD _parse. + + DATA lo_reader TYPE REF TO if_sxml_reader. + DATA lr_stack_top LIKE LINE OF mt_stack. + DATA lo_node TYPE REF TO if_sxml_node. + FIELD-SYMBOLS LIKE LINE OF rt_json_tree. + + CLEAR mt_stack. + CLEAR mv_stack_path. + IF iv_json IS INITIAL. + RETURN. + ENDIF. + lo_reader = cl_sxml_string_reader=>create( iv_json ). + + " TODO: self protection, check non-empty, check starting from object ... + + DO. + lo_node = lo_reader->read_next_node( ). + IF lo_node IS NOT BOUND. + EXIT. + ENDIF. + CASE lo_node->type. + WHEN if_sxml_node=>co_nt_element_open. + DATA lt_attributes TYPE if_sxml_attribute=>attributes. + DATA lo_attr LIKE LINE OF lt_attributes. + DATA lo_open TYPE REF TO if_sxml_open_element. + lo_open ?= lo_node. + + APPEND INITIAL LINE TO rt_json_tree ASSIGNING . + + -type = lo_open->qname-name. + + READ TABLE mt_stack INDEX 1 INTO lr_stack_top. + IF sy-subrc = 0. + " Using string is faster than rebuilding path from stack + -path = mv_stack_path. + lr_stack_top->children = lr_stack_top->children + 1. + + IF lr_stack_top->type = `array`. " This is parser type not ajson type + -name = |{ lr_stack_top->children }|. + -index = lr_stack_top->children. + ELSE. + lt_attributes = lo_open->get_attributes( ). + " JSON nodes always have one "name" attribute + READ TABLE lt_attributes INTO lo_attr INDEX 1. + ASSERT sy-subrc = 0 AND lo_attr->qname-name = 'name'. + -name = lo_attr->get_value( ). + IF mv_keep_item_order = abap_true. + -order = lr_stack_top->children. + ENDIF. + ENDIF. + IF -name IS INITIAL. + raise( 'Node without name (maybe not JSON)' ). + ENDIF. + ENDIF. + + GET REFERENCE OF INTO lr_stack_top. + INSERT lr_stack_top INTO mt_stack INDEX 1. + " add path component (avoid issues with names containing slashes) + mv_stack_path = mv_stack_path && replace( + val = -name + sub = '/' + with = cl_abap_char_utilities=>horizontal_tab + occ = 0 ) + && '/'. + + WHEN if_sxml_node=>co_nt_element_close. + DATA lo_close TYPE REF TO if_sxml_close_element. + lo_close ?= lo_node. + + READ TABLE mt_stack INDEX 1 INTO lr_stack_top. + DELETE mt_stack INDEX 1. + IF lo_close->qname-name <> lr_stack_top->type. + raise( 'Unexpected closing node type' ). + ENDIF. + + " remove last path component + mv_stack_path = substring( val = mv_stack_path + len = find( val = mv_stack_path sub = '/' occ = -2 ) + 1 ). + WHEN if_sxml_node=>co_nt_value. + DATA lo_value TYPE REF TO if_sxml_value_node. + lo_value ?= lo_node. + + -value = lo_value->get_value( ). + + WHEN OTHERS. + raise( 'Unexpected node type' ). + ENDCASE. + ENDDO. + + IF lines( mt_stack ) > 0. + raise( 'Unexpected end of data' ). + ENDIF. + + ENDMETHOD. + + METHOD raise. + + zcx_abapgit_ajson_error=>raise( + iv_location = mv_stack_path + iv_msg = |JSON PARSER: { iv_error } @ { mv_stack_path }| ). + + ENDMETHOD. + +ENDCLASS. + +********************************************************************** +* SERIALIZER +********************************************************************** + +* renamed: zcl_abapgit_ajson :: lcl_json_serializer +CLASS kHGwlMWhQrsNKkKXALnpFgyFungUrS DEFINITION FINAL CREATE PRIVATE. + PUBLIC SECTION. + + CLASS-METHODS stringify + IMPORTING + it_json_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts + iv_indent TYPE i DEFAULT 0 + iv_keep_item_order TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rv_json_string) TYPE string + RAISING + zcx_abapgit_ajson_error. + + CLASS-METHODS class_constructor. + + PRIVATE SECTION. + + CLASS-DATA gv_comma_with_lf TYPE string. + + DATA mt_json_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts. + DATA mv_keep_item_order TYPE abap_bool. + DATA mt_buffer TYPE string_table. + DATA mv_indent_step TYPE i. + DATA mv_level TYPE i. + + CLASS-METHODS escape_string + IMPORTING + iv_unescaped TYPE string + RETURNING + VALUE(rv_escaped) TYPE string. + + METHODS _stringify + RETURNING + VALUE(rv_json_string) TYPE string + RAISING + zcx_abapgit_ajson_error. + + METHODS stringify_node + IMPORTING + is_node TYPE zif_abapgit_ajson_types=>ty_node + RAISING + zcx_abapgit_ajson_error. + + METHODS stringify_set + IMPORTING + iv_parent_path TYPE string + iv_array TYPE abap_bool + RAISING + zcx_abapgit_ajson_error. + +ENDCLASS. + +CLASS kHGwlMWhQrsNKkKXALnpFgyFungUrS IMPLEMENTATION. + + METHOD class_constructor. + gv_comma_with_lf = ',' && cl_abap_char_utilities=>newline. + ENDMETHOD. + + METHOD stringify. + + DATA lo TYPE REF TO kHGwlMWhQrsNKkKXALnpFgyFungUrS. + CREATE OBJECT lo. + lo->mt_json_tree = it_json_tree. + lo->mv_indent_step = iv_indent. + lo->mv_keep_item_order = iv_keep_item_order. + rv_json_string = lo->_stringify( ). + + ENDMETHOD. + + METHOD _stringify. + + FIELD-SYMBOLS LIKE LINE OF mt_json_tree. + READ TABLE mt_json_tree ASSIGNING + WITH KEY + path = '' + name = ''. " Root + IF sy-subrc <> 0. + RETURN. + ENDIF. + + stringify_node( ). + + rv_json_string = concat_lines_of( table = mt_buffer ). + + ENDMETHOD. + + METHOD stringify_node. + + DATA lv_item TYPE string. + DATA lv_indent_prefix TYPE string. + + IF mv_indent_step > 0. + lv_indent_prefix = repeat( val = ` ` + occ = mv_indent_step * mv_level ). + lv_item = lv_indent_prefix. + ENDIF. + + IF is_node-name IS NOT INITIAL AND is_node-index IS INITIAL. " Not root, not array item + IF mv_indent_step > 0. + lv_item = lv_item && |"{ is_node-name }": |. + ELSE. + lv_item = |"{ is_node-name }":|. + ENDIF. + ENDIF. + + CASE is_node-type. + WHEN zif_abapgit_ajson_types=>node_type-array. + lv_item = lv_item && '['. + WHEN zif_abapgit_ajson_types=>node_type-object. + lv_item = lv_item && '{'. + WHEN zif_abapgit_ajson_types=>node_type-string. + lv_item = lv_item && |"{ escape_string( is_node-value ) }"|. + WHEN zif_abapgit_ajson_types=>node_type-boolean OR zif_abapgit_ajson_types=>node_type-number. + lv_item = lv_item && is_node-value. + WHEN zif_abapgit_ajson_types=>node_type-null. + lv_item = lv_item && 'null'. + WHEN OTHERS. + zcx_abapgit_ajson_error=>raise( + iv_msg = |Unexpected type [{ is_node-type }]| + iv_location = is_node-path && is_node-name ). + ENDCASE. + + IF mv_indent_step > 0 + AND ( is_node-type = zif_abapgit_ajson_types=>node_type-array OR is_node-type = zif_abapgit_ajson_types=>node_type-object ) + AND is_node-children > 0. + mv_level = mv_level + 1. + lv_item = lv_item && cl_abap_char_utilities=>newline. + ENDIF. + + APPEND lv_item TO mt_buffer. + + " finish complex item + + IF is_node-type = zif_abapgit_ajson_types=>node_type-array OR is_node-type = zif_abapgit_ajson_types=>node_type-object. + DATA lv_children_path TYPE string. + DATA lv_tail TYPE string. + + lv_children_path = is_node-path && is_node-name && '/'. " for root: path = '' and name = '', so result is '/' + + CASE is_node-type. + WHEN zif_abapgit_ajson_types=>node_type-array. + IF is_node-children > 0. + stringify_set( + iv_parent_path = lv_children_path + iv_array = abap_true ). + ENDIF. + lv_tail = ']'. + WHEN zif_abapgit_ajson_types=>node_type-object. + IF is_node-children > 0. + stringify_set( + iv_parent_path = lv_children_path + iv_array = abap_false ). + ENDIF. + lv_tail = '}'. + ENDCASE. + + IF mv_indent_step > 0 AND is_node-children > 0. + lv_tail = lv_indent_prefix && lv_tail. + mv_level = mv_level - 1. + ENDIF. + APPEND lv_tail TO mt_buffer. + ENDIF. + + ENDMETHOD. + + METHOD stringify_set. + + DATA lv_tab_key TYPE string. + DATA lv_first_done TYPE abap_bool. + FIELD-SYMBOLS LIKE LINE OF mt_json_tree. + + IF iv_array = abap_true. + lv_tab_key = 'array_index'. " path + index + ELSEIF mv_keep_item_order = abap_true. + lv_tab_key = 'item_order'. " path + order + ELSE. + lv_tab_key = 'primary_key'. " path + name + ENDIF. + + LOOP AT mt_json_tree ASSIGNING USING KEY (lv_tab_key) WHERE path = iv_parent_path. + IF lv_first_done = abap_false. + lv_first_done = abap_true. + ELSEIF mv_indent_step > 0. + APPEND gv_comma_with_lf TO mt_buffer. + ELSE. + APPEND ',' TO mt_buffer. + ENDIF. + stringify_node( ). + ENDLOOP. + + IF mv_indent_step > 0 AND lv_first_done = abap_true. " only of items were in the list + APPEND cl_abap_char_utilities=>newline TO mt_buffer. + ENDIF. + + ENDMETHOD. + + METHOD escape_string. + + rv_escaped = iv_unescaped. + IF rv_escaped CA |"\\\t\n\r|. + " TODO consider performance ... + " see also https://www.json.org/json-en.html + rv_escaped = replace( + val = rv_escaped + sub = '\' + with = '\\' + occ = 0 ). + rv_escaped = replace( + val = rv_escaped + sub = |\n| + with = '\n' + occ = 0 ). + rv_escaped = replace( + val = rv_escaped + sub = |\r| + with = '\r' + occ = 0 ). + rv_escaped = replace( + val = rv_escaped + sub = |\t| + with = '\t' + occ = 0 ). + rv_escaped = replace( + val = rv_escaped + sub = '"' + with = '\"' + occ = 0 ). + + ENDIF. + + ENDMETHOD. + +ENDCLASS. +********************************************************************** +* JSON_TO_ABAP +********************************************************************** + +* renamed: zcl_abapgit_ajson :: lcl_json_to_abap +CLASS kHGwlMWhQrsNKkKXALnpXxNdxsjJjI DEFINITION FINAL. + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !iv_corresponding TYPE abap_bool DEFAULT abap_false + !ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + !ii_refs_initiator TYPE REF TO zif_abapgit_ajson_ref_init OPTIONAL. + + METHODS to_abap + IMPORTING + it_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_ts + CHANGING + c_container TYPE any + RAISING + zcx_abapgit_ajson_error. + + METHODS to_timestamp + IMPORTING + iv_value TYPE zif_abapgit_ajson_types=>ty_node-value + RETURNING + VALUE(rv_result) TYPE timestamp + RAISING + zcx_abapgit_ajson_error. + + METHODS to_timestampl + IMPORTING + iv_value TYPE zif_abapgit_ajson_types=>ty_node-value + RETURNING + VALUE(rv_result) TYPE timestampl + RAISING + zcx_abapgit_ajson_error. + + METHODS to_date + IMPORTING + iv_value TYPE zif_abapgit_ajson_types=>ty_node-value + RETURNING + VALUE(rv_result) TYPE d + RAISING + zcx_abapgit_ajson_error. + + METHODS to_time + IMPORTING + iv_value TYPE zif_abapgit_ajson_types=>ty_node-value + RETURNING + VALUE(rv_result) TYPE t + RAISING + zcx_abapgit_ajson_error. + + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_type_cache, + type_path TYPE string, + target_field_name TYPE string, + dd TYPE REF TO cl_abap_datadescr, + type_kind LIKE iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>any, + tab_item_buf TYPE REF TO data, + END OF ty_type_cache. + DATA mt_node_type_cache TYPE HASHED TABLE OF ty_type_cache WITH UNIQUE KEY type_path. + + DATA mr_nodes TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. + DATA mi_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping. + DATA mi_refs_initiator TYPE REF TO zif_abapgit_ajson_ref_init. + DATA mv_corresponding TYPE abap_bool. + + METHODS any_to_abap + IMPORTING + iv_path TYPE string + is_parent_type TYPE ty_type_cache OPTIONAL + i_container_ref TYPE REF TO data + RAISING + zcx_abapgit_ajson_error. + + METHODS value_to_abap + IMPORTING + is_node TYPE zif_abapgit_ajson_types=>ty_node + is_node_type TYPE ty_type_cache + i_container_ref TYPE REF TO data + RAISING + zcx_abapgit_ajson_error + cx_sy_conversion_no_number. + + METHODS get_node_type + IMPORTING + is_node TYPE zif_abapgit_ajson_types=>ty_node OPTIONAL " Empty for root + is_parent_type TYPE ty_type_cache OPTIONAL + i_container_ref TYPE REF TO data OPTIONAL + RETURNING + VALUE(rs_node_type) TYPE ty_type_cache + RAISING + zcx_abapgit_ajson_error. + + METHODS get_data_ref + IMPORTING + is_node TYPE zif_abapgit_ajson_types=>ty_node + RETURNING + VALUE(ro_ref) TYPE REF TO data + RAISING + zcx_abapgit_ajson_error. + +ENDCLASS. + +CLASS kHGwlMWhQrsNKkKXALnpXxNdxsjJjI IMPLEMENTATION. + + METHOD constructor. + mi_custom_mapping = ii_custom_mapping. + mi_refs_initiator = ii_refs_initiator. + mv_corresponding = iv_corresponding. + ENDMETHOD. + + METHOD to_abap. + + DATA lr_ref TYPE REF TO data. + + CLEAR c_container. + + CLEAR mt_node_type_cache. + + GET REFERENCE OF c_container INTO lr_ref. + GET REFERENCE OF it_nodes INTO mr_nodes. + + get_node_type( i_container_ref = lr_ref ). " Pre-cache root node type + + any_to_abap( + iv_path = '' + i_container_ref = lr_ref ). + + ENDMETHOD. + + METHOD get_node_type. + + DATA lv_node_type_path TYPE string. + DATA lo_sdescr TYPE REF TO cl_abap_structdescr. + DATA lo_tdescr TYPE REF TO cl_abap_tabledescr. + DATA lo_ddescr TYPE REF TO cl_abap_datadescr. + + " Calculate type path + IF is_parent_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. + lv_node_type_path = is_parent_type-type_path && '/-'. " table item type + ELSEIF is_parent_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>data_ref. + lv_node_type_path = is_parent_type-type_path && '/+'. " data reference + ELSEIF is_parent_type-type_kind IS NOT INITIAL. + lv_node_type_path = is_parent_type-type_path && '/' && is_node-name. + ENDIF. " For root node lv_node_type_path remains '' + + " Get or create cached + READ TABLE mt_node_type_cache INTO rs_node_type WITH KEY type_path = lv_node_type_path. + IF sy-subrc <> 0. + + rs_node_type-type_path = lv_node_type_path. + + IF mi_custom_mapping IS BOUND. + rs_node_type-target_field_name = to_upper( mi_custom_mapping->to_abap( + iv_path = is_node-path + iv_name = is_node-name ) ). + IF rs_node_type-target_field_name IS INITIAL. + rs_node_type-target_field_name = to_upper( is_node-name ). + ENDIF. + ELSE. + rs_node_type-target_field_name = to_upper( is_node-name ). + ENDIF. + + CASE is_parent_type-type_kind. + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. + lo_tdescr ?= is_parent_type-dd. + rs_node_type-dd = lo_tdescr->get_table_line_type( ). + + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_flat OR iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_deep. + lo_sdescr ?= is_parent_type-dd. + lo_sdescr->get_component_type( + EXPORTING + p_name = rs_node_type-target_field_name + RECEIVING + p_descr_ref = rs_node_type-dd + EXCEPTIONS + component_not_found = 4 ). + IF sy-subrc <> 0. + IF mv_corresponding = abap_false. + zcx_abapgit_ajson_error=>raise( |Path not found| ). + ELSE. + CLEAR rs_node_type. + RETURN. + ENDIF. + ENDIF. + + WHEN '' OR iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>data_ref. " Root node or ref to data + rs_node_type-dd ?= cl_abap_typedescr=>describe_by_data_ref( i_container_ref ). + + WHEN OTHERS. + zcx_abapgit_ajson_error=>raise( |Unexpected parent type| ). + ENDCASE. + + rs_node_type-type_kind = rs_node_type-dd->type_kind. " for caching and cleaner uninitialized access + IF rs_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. + lo_tdescr ?= rs_node_type-dd. + IF lo_tdescr->table_kind <> cl_abap_tabledescr=>tablekind_std. + lo_ddescr = lo_tdescr->get_table_line_type( ). + CREATE DATA rs_node_type-tab_item_buf TYPE HANDLE lo_ddescr. + ENDIF. + ENDIF. + + INSERT rs_node_type INTO TABLE mt_node_type_cache. + ENDIF. + + ENDMETHOD. + + METHOD get_data_ref. + + IF mi_refs_initiator IS INITIAL. + zcx_abapgit_ajson_error=>raise( 'Missing ref initiator' ). + ENDIF. + + ro_ref = mi_refs_initiator->get_data_ref( is_node ). + + IF ro_ref IS INITIAL. + zcx_abapgit_ajson_error=>raise( 'Cannot use initial data ref' ). + ENDIF. + + ENDMETHOD. + + METHOD any_to_abap. + + DATA ls_node_type LIKE LINE OF mt_node_type_cache. + DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + DATA lx_root TYPE REF TO cx_root. + DATA lr_target_field TYPE REF TO data. + + FIELD-SYMBOLS TYPE zif_abapgit_ajson_types=>ty_node. + FIELD-SYMBOLS TYPE STANDARD TABLE. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + + " Assign container + CASE is_parent_type-type_kind. + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. + IF is_parent_type-tab_item_buf IS BOUND. " Indirect hint that table was sorted/hashed, see get_node_type. + ASSIGN i_container_ref->* TO . + ASSERT sy-subrc = 0. + + lr_target_field = is_parent_type-tab_item_buf. " For hashed/sorted table - same buffer for all children + ASSIGN is_parent_type-tab_item_buf->* TO . + ASSERT sy-subrc = 0. + + ELSE. + ASSIGN i_container_ref->* TO . + ASSERT sy-subrc = 0. + ENDIF. + + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_flat OR iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_deep. + ASSIGN i_container_ref->* TO . + ASSERT sy-subrc = 0. + ENDCASE. + + TRY. + + " array_index because stringified index goes in wrong order [1, 10, 2 ...] + LOOP AT mr_nodes->* ASSIGNING USING KEY array_index WHERE path = iv_path. + + " Get or create type cache record + IF is_parent_type-type_kind <> iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table OR ls_node_type-type_kind IS INITIAL. + " table records are the same, no need to refetch twice + + ls_node_type = get_node_type( + is_node = + is_parent_type = is_parent_type ). + + IF mv_corresponding = abap_true AND ls_node_type IS INITIAL. + CONTINUE. + ENDIF. + + ENDIF. + + " Validate node type + IF ls_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>object_ref. + " TODO maybe in future + zcx_abapgit_ajson_error=>raise( 'Cannot assign to ref' ). + ENDIF. + + " Find target field reference + CASE is_parent_type-type_kind. + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. + IF NOT ls_node_type-target_field_name CO '0123456789'. + " Does not affect anything actually but for integrity + zcx_abapgit_ajson_error=>raise( 'Need index to access tables' ). + ENDIF. + + IF is_parent_type-tab_item_buf IS NOT BOUND. " Indirect hint that table was srt/hsh, see get_node_type + APPEND INITIAL LINE TO REFERENCE INTO lr_target_field. + ASSERT sy-subrc = 0. + ELSE. + CLEAR . + ENDIF. + + WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_flat OR iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_deep. + ASSIGN COMPONENT ls_node_type-target_field_name OF STRUCTURE TO . + ASSERT sy-subrc = 0. + GET REFERENCE OF INTO lr_target_field. + + WHEN ''. " Root node + lr_target_field = i_container_ref. + + WHEN OTHERS. + zcx_abapgit_ajson_error=>raise( 'Unexpected parent type' ). + ENDCASE. + + " For data refs, get the type it is pointing to + IF ls_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>data_ref. + lr_target_field = get_data_ref( ). + + ls_node_type = get_node_type( + i_container_ref = lr_target_field + is_node = + is_parent_type = ls_node_type ). + ENDIF. + + " Process value assignment + CASE -type. + WHEN zif_abapgit_ajson_types=>node_type-object. + IF ls_node_type-type_kind <> iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_flat AND + ls_node_type-type_kind <> iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_deep. + zcx_abapgit_ajson_error=>raise( 'Expected structure' ). + ENDIF. + any_to_abap( + iv_path = -path && -name && '/' + is_parent_type = ls_node_type + i_container_ref = lr_target_field ). + + WHEN zif_abapgit_ajson_types=>node_type-array. + IF NOT ls_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. + zcx_abapgit_ajson_error=>raise( 'Expected table' ). + ENDIF. + any_to_abap( + iv_path = -path && -name && '/' + is_parent_type = ls_node_type + i_container_ref = lr_target_field ). + + WHEN OTHERS. + value_to_abap( + is_node = + is_node_type = ls_node_type + i_container_ref = lr_target_field ). + ENDCASE. + + IF is_parent_type-tab_item_buf IS BOUND. " Indirect hint that table was sorted/hashed, see get_node_type. + TRY. + INSERT INTO TABLE . + IF sy-subrc <> 0. + zcx_abapgit_ajson_error=>raise( 'Duplicate insertion' ). + ENDIF. + CATCH cx_sy_itab_duplicate_key. + zcx_abapgit_ajson_error=>raise( 'Duplicate insertion' ). + ENDTRY. + ENDIF. + + ENDLOOP. + + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + IF lx_ajson->location IS INITIAL. + lx_ajson->set_location( -path && -name ). + ENDIF. + RAISE EXCEPTION lx_ajson. + CATCH cx_sy_conversion_no_number. + zcx_abapgit_ajson_error=>raise( + iv_msg = 'Source is not a number' + iv_location = -path && -name ). + CATCH cx_root INTO lx_root. + zcx_abapgit_ajson_error=>raise( + iv_msg = lx_root->get_text( ) + iv_location = -path && -name ). + ENDTRY. + + ENDMETHOD. + + METHOD value_to_abap. + + FIELD-SYMBOLS TYPE any. + + IF is_node_type-type_kind CA iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>deep_targets. + zcx_abapgit_ajson_error=>raise( |Unsupported target for value [{ is_node_type-type_kind }]| ). + ENDIF. + + ASSIGN i_container_ref->* TO . + ASSERT sy-subrc = 0. + + CASE is_node-type. + WHEN zif_abapgit_ajson_types=>node_type-null. + " Do nothing + WHEN zif_abapgit_ajson_types=>node_type-boolean. + " TODO: check type ? + = boolc( is_node-value = 'true' ). + WHEN zif_abapgit_ajson_types=>node_type-number. + " TODO: check type ? + = is_node-value. + + WHEN zif_abapgit_ajson_types=>node_type-string. + " TODO: check type ? + IF is_node-value IS NOT INITIAL. + IF is_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>date. + = to_date( is_node-value ). + ELSEIF is_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>time. + = to_time( is_node-value ). + ELSEIF is_node_type-dd->absolute_name = '\TYPE=TIMESTAMP'. + = to_timestamp( is_node-value ). + ELSEIF is_node_type-dd->absolute_name = '\TYPE=TIMESTAMPL'. + = to_timestampl( is_node-value ). + ELSEIF is_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>packed. " Number as a string, but not a timestamp + = is_node-value. + ELSE. + = is_node-value. + ENDIF. + ELSE. + = is_node-value. + ENDIF. + WHEN OTHERS. + zcx_abapgit_ajson_error=>raise( |Unexpected JSON type [{ is_node-type }]| ). + ENDCASE. + + ENDMETHOD. + + METHOD to_date. + + DATA lv_y TYPE c LENGTH 4. + DATA lv_m TYPE c LENGTH 2. + DATA lv_d TYPE c LENGTH 2. + + FIND FIRST OCCURRENCE OF REGEX '^(\d{4})-(\d{2})-(\d{2})(T|$)' + IN iv_value + SUBMATCHES lv_y lv_m lv_d. + IF sy-subrc <> 0. + zcx_abapgit_ajson_error=>raise( 'Unexpected date format' ). + ENDIF. + CONCATENATE lv_y lv_m lv_d INTO rv_result. + + ENDMETHOD. + + METHOD to_timestamp. + + DATA lv_timestampl TYPE timestampl. + DATA lv_int_part TYPE string. + DATA lv_frac_part TYPE string. + + lv_timestampl = to_timestampl( iv_value ). + SPLIT |{ lv_timestampl }| AT '.' INTO lv_int_part lv_frac_part. + + " short timestamp must not have any fraction (.000 is acceptable) + IF lv_frac_part CA '123456789'. + zcx_abapgit_ajson_error=>raise( 'Unexpected timestamp format' ). + ENDIF. + + rv_result = lv_int_part. + + ENDMETHOD. + + METHOD to_timestampl. + + CONSTANTS lc_utc TYPE c LENGTH 6 VALUE 'UTC'. + CONSTANTS lc_regex_ts_with_hour TYPE string + VALUE `^(\d{4})-(\d{2})-(\d{2})(T)(\d{2}):(\d{2}):(\d{2})(\+)(\d{2}):(\d{2})`. + CONSTANTS lc_regex_ts_utc TYPE string + VALUE `^(\d{4})-(\d{2})-(\d{2})(T)(\d{2}):(\d{2}):(\d{2})(\.\d+)?(Z|$)`. + + DATA: + BEGIN OF ls_timestamp, + year TYPE c LENGTH 4, + month TYPE c LENGTH 2, + day TYPE c LENGTH 2, + t TYPE c LENGTH 1, + hour TYPE c LENGTH 2, + minute TYPE c LENGTH 2, + second TYPE c LENGTH 2, + frac TYPE c LENGTH 8, + local_sign TYPE c LENGTH 1, + local_hour TYPE c LENGTH 2, + local_minute TYPE c LENGTH 2, + END OF ls_timestamp. + + DATA lv_date TYPE d. + DATA lv_time TYPE t. + DATA lv_seconds_conv TYPE i. + DATA lv_timestamp TYPE timestampl. + + FIND FIRST OCCURRENCE OF REGEX lc_regex_ts_with_hour + IN iv_value SUBMATCHES + ls_timestamp-year ls_timestamp-month ls_timestamp-day ls_timestamp-t + ls_timestamp-hour ls_timestamp-minute ls_timestamp-second + ls_timestamp-local_sign ls_timestamp-local_hour ls_timestamp-local_minute. + + IF sy-subrc = 0. + + lv_seconds_conv = ( ls_timestamp-local_hour * 3600 ) + ( ls_timestamp-local_minute * 60 ). + + ELSE. + + FIND FIRST OCCURRENCE OF REGEX lc_regex_ts_utc + IN iv_value SUBMATCHES + ls_timestamp-year ls_timestamp-month ls_timestamp-day ls_timestamp-t + ls_timestamp-hour ls_timestamp-minute ls_timestamp-second ls_timestamp-frac. + + IF sy-subrc <> 0. + zcx_abapgit_ajson_error=>raise( 'Unexpected timestamp format' ). + ENDIF. + + ENDIF. + + CONCATENATE ls_timestamp-year ls_timestamp-month ls_timestamp-day INTO lv_date. + CONCATENATE ls_timestamp-hour ls_timestamp-minute ls_timestamp-second INTO lv_time. + + CONVERT DATE lv_date TIME lv_time INTO TIME STAMP lv_timestamp TIME ZONE lc_utc. + + " add fraction + IF ls_timestamp-frac IS NOT INITIAL. + ls_timestamp-frac = '0' && ls_timestamp-frac. + lv_timestamp = lv_timestamp + ls_timestamp-frac. + ENDIF. + + TRY. + + CASE ls_timestamp-local_sign. + WHEN '-'. + lv_timestamp = cl_abap_tstmp=>add( + tstmp = lv_timestamp + secs = lv_seconds_conv ). + WHEN '+'. + lv_timestamp = cl_abap_tstmp=>subtractsecs( + tstmp = lv_timestamp + secs = lv_seconds_conv ). + ENDCASE. + + CATCH cx_parameter_invalid_range cx_parameter_invalid_type. + zcx_abapgit_ajson_error=>raise( 'Unexpected error calculating timestamp' ). + ENDTRY. + + IF lv_timestamp IS NOT INITIAL. + cl_abap_tstmp=>move( + EXPORTING + tstmp_src = lv_timestamp + IMPORTING + tstmp_tgt = rv_result ). + ENDIF. + + ENDMETHOD. + + METHOD to_time. + + DATA lv_h TYPE c LENGTH 2. + DATA lv_m TYPE c LENGTH 2. + DATA lv_s TYPE c LENGTH 2. + + FIND FIRST OCCURRENCE OF REGEX '^(\d{2}):(\d{2}):(\d{2})(T|$)' + IN iv_value + SUBMATCHES lv_h lv_m lv_s. + IF sy-subrc <> 0. + zcx_abapgit_ajson_error=>raise( 'Unexpected time format' ). + ENDIF. + CONCATENATE lv_h lv_m lv_s INTO rv_result. + + ENDMETHOD. + +ENDCLASS. + +********************************************************************** +* ABAP_TO_JSON +********************************************************************** + +* renamed: zcl_abapgit_ajson :: lcl_abap_to_json +CLASS kHGwlMWhQrsNKkKXALnpeJqampzabz DEFINITION FINAL. + PUBLIC SECTION. + + CLASS-METHODS convert + IMPORTING + iv_data TYPE any + is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name OPTIONAL + iv_array_index TYPE i DEFAULT 0 + ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + is_opts TYPE zif_abapgit_ajson=>ty_opts OPTIONAL + iv_item_order TYPE i DEFAULT 0 + RETURNING + VALUE(rt_nodes) TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + + CLASS-METHODS insert_with_type + IMPORTING + iv_data TYPE any + iv_type TYPE zif_abapgit_ajson_types=>ty_node_type + is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name OPTIONAL + iv_array_index TYPE i DEFAULT 0 + ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + is_opts TYPE zif_abapgit_ajson=>ty_opts OPTIONAL + iv_item_order TYPE i DEFAULT 0 + RETURNING + VALUE(rt_nodes) TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + + CLASS-METHODS format_date + IMPORTING + iv_date TYPE d + RETURNING + VALUE(rv_str) TYPE string. + CLASS-METHODS format_time + IMPORTING + iv_time TYPE t + RETURNING + VALUE(rv_str) TYPE string. + CLASS-METHODS format_timestamp + IMPORTING + iv_ts TYPE timestamp + RETURNING + VALUE(rv_str) TYPE string. + CLASS-METHODS format_timestampl + IMPORTING + iv_ts TYPE timestampl + RETURNING + VALUE(rv_str) TYPE string. + + CLASS-METHODS class_constructor. + + PRIVATE SECTION. + + CLASS-DATA gv_ajson_absolute_type_name TYPE string. + DATA mi_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping. + DATA mv_keep_item_order TYPE abap_bool. + DATA mv_format_datetime TYPE abap_bool. + + METHODS convert_any + IMPORTING + iv_data TYPE any + io_type TYPE REF TO cl_abap_typedescr + is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name + iv_index TYPE i DEFAULT 0 + iv_item_order TYPE i DEFAULT 0 + CHANGING + ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + + METHODS convert_ajson + IMPORTING + io_json TYPE REF TO zif_abapgit_ajson + is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name + iv_index TYPE i DEFAULT 0 + iv_item_order TYPE i DEFAULT 0 + CHANGING + ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + + METHODS convert_value + IMPORTING + iv_data TYPE any + io_type TYPE REF TO cl_abap_typedescr + is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name + iv_index TYPE i DEFAULT 0 + iv_item_order TYPE i DEFAULT 0 + CHANGING + ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + + METHODS convert_ref + IMPORTING + iv_data TYPE any + is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name + iv_index TYPE i DEFAULT 0 + iv_item_order TYPE i DEFAULT 0 + CHANGING + ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + + METHODS convert_struc + IMPORTING + iv_data TYPE any + io_type TYPE REF TO cl_abap_typedescr + is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name + iv_index TYPE i DEFAULT 0 + iv_item_order TYPE i DEFAULT 0 + CHANGING + ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + + METHODS convert_table + IMPORTING + iv_data TYPE any + io_type TYPE REF TO cl_abap_typedescr + is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name + iv_index TYPE i DEFAULT 0 + iv_item_order TYPE i DEFAULT 0 + CHANGING + ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + + METHODS insert_value_with_type + IMPORTING + iv_data TYPE any + iv_type TYPE zif_abapgit_ajson_types=>ty_node_type + io_type TYPE REF TO cl_abap_typedescr + is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name + iv_index TYPE i DEFAULT 0 + iv_item_order TYPE i DEFAULT 0 + CHANGING + ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt + RAISING + zcx_abapgit_ajson_error. + +ENDCLASS. + +CLASS kHGwlMWhQrsNKkKXALnpeJqampzabz IMPLEMENTATION. + + METHOD class_constructor. + + DATA lo_dummy TYPE REF TO zcl_abapgit_ajson. + DATA lo_type TYPE REF TO cl_abap_refdescr. + lo_type ?= cl_abap_typedescr=>describe_by_data( lo_dummy ). + gv_ajson_absolute_type_name = lo_type->get_referenced_type( )->absolute_name. + + ENDMETHOD. + + METHOD convert. + + DATA lo_type TYPE REF TO cl_abap_typedescr. + DATA lo_converter TYPE REF TO kHGwlMWhQrsNKkKXALnpeJqampzabz. + + lo_type = cl_abap_typedescr=>describe_by_data( iv_data ). + + CREATE OBJECT lo_converter. + lo_converter->mi_custom_mapping = ii_custom_mapping. + lo_converter->mv_keep_item_order = is_opts-keep_item_order. + lo_converter->mv_format_datetime = is_opts-format_datetime. + + lo_converter->convert_any( + EXPORTING + iv_data = iv_data + io_type = lo_type + is_prefix = is_prefix + iv_index = iv_array_index + iv_item_order = iv_item_order + CHANGING + ct_nodes = rt_nodes ). + + ENDMETHOD. + + METHOD convert_any. + + CASE io_type->kind. + WHEN cl_abap_typedescr=>kind_elem. + convert_value( + EXPORTING + iv_data = iv_data + io_type = io_type + is_prefix = is_prefix + iv_index = iv_index + iv_item_order = iv_item_order + CHANGING + ct_nodes = ct_nodes ). + + WHEN cl_abap_typedescr=>kind_struct. + convert_struc( + EXPORTING + iv_data = iv_data + io_type = io_type + is_prefix = is_prefix + iv_index = iv_index + iv_item_order = iv_item_order + CHANGING + ct_nodes = ct_nodes ). + + WHEN cl_abap_typedescr=>kind_table. + convert_table( + EXPORTING + iv_data = iv_data + io_type = io_type + is_prefix = is_prefix + iv_index = iv_index + iv_item_order = iv_item_order + CHANGING + ct_nodes = ct_nodes ). + + WHEN OTHERS. + + IF io_type->type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>data_ref OR iv_data IS INITIAL. + " Convert data references and initial references to other types (like ref to class or interface) + " Initial references will result in "null" + convert_ref( + EXPORTING + iv_data = iv_data + is_prefix = is_prefix + iv_index = iv_index + iv_item_order = iv_item_order + CHANGING + ct_nodes = ct_nodes ). + + ELSEIF io_type->type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>object_ref + AND cl_abap_typedescr=>describe_by_object_ref( iv_data )->absolute_name = gv_ajson_absolute_type_name. + convert_ajson( + EXPORTING + io_json = iv_data + is_prefix = is_prefix + iv_index = iv_index + iv_item_order = iv_item_order + CHANGING + ct_nodes = ct_nodes ). + ELSE. + zcx_abapgit_ajson_error=>raise( |Unsupported type [{ io_type->type_kind + }] @{ is_prefix-path && is_prefix-name }| ). + ENDIF. + + ENDCASE. + + ENDMETHOD. + + METHOD convert_ajson. + + FIELD-SYMBOLS LIKE LINE OF ct_nodes. + FIELD-SYMBOLS LIKE LINE OF ct_nodes. + + IF io_json IS NOT BOUND. + RETURN. + ENDIF. + + LOOP AT io_json->mt_json_tree ASSIGNING . + APPEND TO ct_nodes ASSIGNING . + + IF -path IS INITIAL AND -name IS INITIAL. " root node + -path = is_prefix-path. + -name = is_prefix-name. + -index = iv_index. + -order = iv_item_order. + ELSE. + -path = is_prefix-path && is_prefix-name && -path. + ENDIF. + ENDLOOP. + + ENDMETHOD. + + METHOD format_date. + IF iv_date IS NOT INITIAL. + rv_str = iv_date+0(4) && '-' && iv_date+4(2) && '-' && iv_date+6(2). + ENDIF. + ENDMETHOD. + + METHOD format_time. + IF iv_time IS NOT INITIAL. + rv_str = iv_time+0(2) && ':' && iv_time+2(2) && ':' && iv_time+4(2). + ENDIF. + ENDMETHOD. + + METHOD format_timestamp. + + CONSTANTS lc_utc TYPE c LENGTH 6 VALUE 'UTC'. + + DATA lv_date TYPE d. + DATA lv_time TYPE t. + + CONVERT TIME STAMP iv_ts TIME ZONE lc_utc + INTO DATE lv_date TIME lv_time. + + rv_str = + lv_date+0(4) && '-' && lv_date+4(2) && '-' && lv_date+6(2) && + 'T' && + lv_time+0(2) && ':' && lv_time+2(2) && ':' && lv_time+4(2) && + 'Z'. + + ENDMETHOD. + + METHOD format_timestampl. + + CONSTANTS lc_utc TYPE c LENGTH 6 VALUE 'UTC'. + + DATA lv_date TYPE d. + DATA lv_time TYPE t. + DATA lv_frac TYPE string. + DATA lv_int TYPE string. + + CONVERT TIME STAMP iv_ts TIME ZONE lc_utc + INTO DATE lv_date TIME lv_time. + + SPLIT |{ iv_ts }| AT '.' INTO lv_int lv_frac. + SHIFT lv_frac RIGHT DELETING TRAILING '0'. + SHIFT lv_frac LEFT DELETING LEADING space. + IF lv_frac IS INITIAL. + lv_frac = '0'. + ENDIF. + + rv_str = + lv_date+0(4) && '-' && lv_date+4(2) && '-' && lv_date+6(2) && + 'T' && + lv_time+0(2) && ':' && lv_time+2(2) && ':' && lv_time+4(2) && + '.' && lv_frac && + 'Z'. + + ENDMETHOD. + + METHOD convert_value. + + DATA ls_node LIKE LINE OF ct_nodes. + DATA lv_timestamp TYPE string. + + ls_node-path = is_prefix-path. + ls_node-name = is_prefix-name. + ls_node-index = iv_index. + ls_node-order = iv_item_order. + + IF ls_node-name IS INITIAL. + ls_node-name = is_prefix-name. + ENDIF. + + IF io_type->absolute_name = '\TYPE-POOL=ABAP\TYPE=ABAP_BOOL' + OR io_type->absolute_name = '\TYPE=ABAP_BOOLEAN' + OR io_type->absolute_name = '\TYPE=XSDBOOLEAN' + OR io_type->absolute_name = '\TYPE=FLAG' + OR io_type->absolute_name = '\TYPE=XFELD'. + ls_node-type = zif_abapgit_ajson_types=>node_type-boolean. + IF iv_data IS NOT INITIAL. + ls_node-value = 'true'. + ELSE. + ls_node-value = 'false'. + ENDIF. + ELSEIF io_type->absolute_name = '\TYPE=TIMESTAMP'. + IF mv_format_datetime = abap_true. + ls_node-type = zif_abapgit_ajson_types=>node_type-string. + ls_node-value = format_timestamp( iv_data ). + ELSE. + ls_node-type = zif_abapgit_ajson_types=>node_type-number. + ls_node-value = |{ iv_data }|. + ENDIF. + ELSEIF io_type->absolute_name = '\TYPE=TIMESTAMPL'. + IF mv_format_datetime = abap_true. + ls_node-type = zif_abapgit_ajson_types=>node_type-string. + ls_node-value = format_timestampl( iv_data ). + ELSE. + ls_node-type = zif_abapgit_ajson_types=>node_type-number. + ls_node-value = |{ iv_data }|. + ENDIF. + ELSEIF io_type->type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>utclong. + lv_timestamp = replace( + val = iv_data + sub = ` ` + with = `T` ) && 'Z'. + ls_node-type = zif_abapgit_ajson_types=>node_type-string. + ls_node-value = lv_timestamp. + ELSEIF io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>texts OR + io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>binary OR + io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>enum. + ls_node-type = zif_abapgit_ajson_types=>node_type-string. + ls_node-value = |{ iv_data }|. + ELSEIF io_type->type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>date. + ls_node-type = zif_abapgit_ajson_types=>node_type-string. + IF mv_format_datetime = abap_true. + ls_node-value = format_date( iv_data ). + ELSE. + ls_node-value = |{ iv_data }|. + ENDIF. + ELSEIF io_type->type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>time. + ls_node-type = zif_abapgit_ajson_types=>node_type-string. + IF mv_format_datetime = abap_true. + ls_node-value = format_time( iv_data ). + ELSE. + ls_node-value = |{ iv_data }|. + ENDIF. + ELSEIF io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>numeric. + ls_node-type = zif_abapgit_ajson_types=>node_type-number. + ls_node-value = |{ iv_data }|. + ELSE. + zcx_abapgit_ajson_error=>raise( |Unexpected elementary type [{ + io_type->type_kind }] @{ is_prefix-path && is_prefix-name }| ). + ENDIF. + + APPEND ls_node TO ct_nodes. + + ENDMETHOD. + + METHOD convert_ref. + + DATA ls_node LIKE LINE OF ct_nodes. + DATA lo_type TYPE REF TO cl_abap_typedescr. + + FIELD-SYMBOLS TYPE any. + + ls_node-path = is_prefix-path. + ls_node-name = is_prefix-name. + ls_node-index = iv_index. + ls_node-order = iv_item_order. + + IF mi_custom_mapping IS BOUND. + ls_node-name = mi_custom_mapping->to_json( + iv_path = is_prefix-path + iv_name = is_prefix-name ). + ENDIF. + + IF ls_node-name IS INITIAL. + ls_node-name = is_prefix-name. + ENDIF. + + IF iv_data IS INITIAL. + ls_node-type = zif_abapgit_ajson_types=>node_type-null. + ls_node-value = 'null'. + APPEND ls_node TO ct_nodes. + ELSE. + ASSIGN iv_data->* TO . + lo_type = cl_abap_typedescr=>describe_by_data( ). + + convert_any( + EXPORTING + iv_data = + io_type = lo_type + is_prefix = is_prefix + iv_index = iv_index + iv_item_order = iv_item_order + CHANGING + ct_nodes = ct_nodes ). + ENDIF. + + ENDMETHOD. + + METHOD convert_struc. + + DATA lo_struc TYPE REF TO cl_abap_structdescr. + DATA lt_comps TYPE cl_abap_structdescr=>included_view. + DATA ls_next_prefix LIKE is_prefix. + DATA lv_mapping_prefix_name LIKE is_prefix-name. + DATA lv_item_order TYPE i. + DATA ls_root LIKE LINE OF ct_nodes. + + FIELD-SYMBOLS LIKE ls_root. + FIELD-SYMBOLS LIKE LINE OF lt_comps. + FIELD-SYMBOLS TYPE any. + + " Object root + + ls_root-path = is_prefix-path. + ls_root-name = is_prefix-name. + ls_root-type = zif_abapgit_ajson_types=>node_type-object. + ls_root-index = iv_index. + + IF mi_custom_mapping IS BOUND. + ls_root-name = mi_custom_mapping->to_json( + iv_path = is_prefix-path + iv_name = is_prefix-name ). + ENDIF. + + IF ls_root-name IS INITIAL. + ls_root-name = is_prefix-name. + ENDIF. + + ls_root-order = iv_item_order. + + APPEND ls_root TO ct_nodes ASSIGNING . + + " Object attributes + + lo_struc ?= io_type. + lt_comps = lo_struc->get_included_view( ). + " replaced call to get_components() with get_included_view() to avoid problems with suffixes in includes. + " get_components is potentially much slower than lo_struc->components + " but ! we still need it to identify booleans + " and rtti seems to cache type descriptions really well (https://github.com/sbcgua/benchmarks.git) + " the structures will be repeated in real life + + ls_next_prefix-path = is_prefix-path && -name && '/'. + + LOOP AT lt_comps ASSIGNING . + CLEAR lv_mapping_prefix_name. + + -children = -children + 1. + ls_next_prefix-name = to_lower( -name ). + ASSIGN COMPONENT -name OF STRUCTURE iv_data TO . + ASSERT sy-subrc = 0. + + IF mi_custom_mapping IS BOUND AND -type->kind = cl_abap_typedescr=>kind_elem. + lv_mapping_prefix_name = mi_custom_mapping->to_json( iv_path = ls_next_prefix-path + iv_name = ls_next_prefix-name ). + ENDIF. + + IF lv_mapping_prefix_name IS NOT INITIAL. + ls_next_prefix-name = lv_mapping_prefix_name. + ENDIF. + + IF mv_keep_item_order = abap_true. + lv_item_order = -children. + ENDIF. + + convert_any( + EXPORTING + iv_data = + io_type = -type + is_prefix = ls_next_prefix + iv_item_order = lv_item_order + CHANGING + ct_nodes = ct_nodes ). + + ENDLOOP. + + ENDMETHOD. + + METHOD convert_table. + + DATA lo_table TYPE REF TO cl_abap_tabledescr. + DATA lo_ltype TYPE REF TO cl_abap_typedescr. + DATA ls_next_prefix LIKE is_prefix. + DATA lv_tabix TYPE sy-tabix. + DATA ls_root LIKE LINE OF ct_nodes. + + FIELD-SYMBOLS LIKE ls_root. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + + " Array root + + ls_root-path = is_prefix-path. + ls_root-name = is_prefix-name. + ls_root-type = zif_abapgit_ajson_types=>node_type-array. + ls_root-index = iv_index. + ls_root-order = iv_item_order. + + IF mi_custom_mapping IS BOUND. + ls_root-name = mi_custom_mapping->to_json( + iv_path = is_prefix-path + iv_name = is_prefix-name ). + ENDIF. + + IF ls_root-name IS INITIAL. + ls_root-name = is_prefix-name. + ENDIF. + + APPEND ls_root TO ct_nodes ASSIGNING . + + " Array items + + lo_table ?= io_type. + lo_ltype = lo_table->get_table_line_type( ). + + ls_next_prefix-path = is_prefix-path && -name && '/'. + ASSIGN iv_data TO . + + lv_tabix = 1. + LOOP AT ASSIGNING . + ls_next_prefix-name = to_lower( |{ lv_tabix }| ). + + convert_any( + EXPORTING + iv_data = + io_type = lo_ltype + is_prefix = ls_next_prefix + iv_index = -children + 1 + CHANGING + ct_nodes = ct_nodes ). + + -children = -children + 1. + lv_tabix = lv_tabix + 1. + ENDLOOP. + + ENDMETHOD. + + METHOD insert_with_type. + + DATA lo_type TYPE REF TO cl_abap_typedescr. + DATA lo_converter TYPE REF TO kHGwlMWhQrsNKkKXALnpeJqampzabz. + + lo_type = cl_abap_typedescr=>describe_by_data( iv_data ). + + CREATE OBJECT lo_converter. + lo_converter->mi_custom_mapping = ii_custom_mapping. + lo_converter->mv_keep_item_order = is_opts-keep_item_order. + lo_converter->mv_format_datetime = is_opts-format_datetime. + + lo_converter->insert_value_with_type( + EXPORTING + iv_data = iv_data + iv_type = iv_type + io_type = lo_type + is_prefix = is_prefix + iv_index = iv_array_index + iv_item_order = iv_item_order + CHANGING + ct_nodes = rt_nodes ). + + ENDMETHOD. + + METHOD insert_value_with_type. + + DATA lv_prefix TYPE string. + DATA ls_node LIKE LINE OF ct_nodes. + + lv_prefix = is_prefix-path && is_prefix-name. + IF io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>texts OR + io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>date OR + io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>time. + IF iv_type = zif_abapgit_ajson_types=>node_type-boolean AND iv_data <> 'true' AND iv_data <> 'false'. + zcx_abapgit_ajson_error=>raise( |Unexpected boolean value [{ iv_data }] @{ lv_prefix }| ). + ELSEIF iv_type = zif_abapgit_ajson_types=>node_type-null AND iv_data IS NOT INITIAL. + zcx_abapgit_ajson_error=>raise( |Unexpected null value [{ iv_data }] @{ lv_prefix }| ). + ELSEIF iv_type = zif_abapgit_ajson_types=>node_type-number AND iv_data CN '0123456789. E+-'. + zcx_abapgit_ajson_error=>raise( |Unexpected numeric value [{ iv_data }] @{ lv_prefix }| ). + ELSEIF iv_type <> zif_abapgit_ajson_types=>node_type-string AND iv_type <> zif_abapgit_ajson_types=>node_type-boolean + AND iv_type <> zif_abapgit_ajson_types=>node_type-null AND iv_type <> zif_abapgit_ajson_types=>node_type-number. + zcx_abapgit_ajson_error=>raise( |Unexpected type for value [{ iv_type },{ iv_data }] @{ lv_prefix }| ). + ENDIF. + ELSEIF io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>numeric. + IF iv_type <> zif_abapgit_ajson_types=>node_type-number. + zcx_abapgit_ajson_error=>raise( |Unexpected value for numeric [{ iv_data }] @{ lv_prefix }| ). + ENDIF. + ELSE. + zcx_abapgit_ajson_error=>raise( |Unexpected type [{ io_type->type_kind }] @{ lv_prefix }| ). + ENDIF. + + ls_node-path = is_prefix-path. + ls_node-name = is_prefix-name. + ls_node-index = iv_index. + ls_node-value = iv_data. + ls_node-type = iv_type. + ls_node-order = iv_item_order. + + IF mi_custom_mapping IS BOUND. + ls_node-name = mi_custom_mapping->to_json( + iv_path = is_prefix-path + iv_name = is_prefix-name ). + ENDIF. + + IF ls_node-name IS INITIAL. + ls_node-name = is_prefix-name. + ENDIF. + + APPEND ls_node TO ct_nodes. + + ENDMETHOD. + +ENDCLASS. + +********************************************************************** +* MUTATOR INTERFACE +********************************************************************** + +* renamed: zcl_abapgit_ajson :: lif_mutator_runner +INTERFACE iUFTsMWhQrsNKkKXALnptzVIYRIbuu. + METHODS run + IMPORTING + it_source_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts + EXPORTING + et_dest_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts + RAISING + zcx_abapgit_ajson_error. +ENDINTERFACE. + +********************************************************************** +* FILTER RUNNER +********************************************************************** + +* renamed: zcl_abapgit_ajson :: lcl_filter_runner +CLASS kHGwlMWhQrsNKkKXALnplwblMIpVBS DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES iUFTsMWhQrsNKkKXALnptzVIYRIbuu. + CLASS-METHODS new + IMPORTING + ii_filter TYPE REF TO zif_abapgit_ajson_filter + RETURNING + VALUE(ro_instance) TYPE REF TO kHGwlMWhQrsNKkKXALnplwblMIpVBS. + METHODS constructor + IMPORTING + ii_filter TYPE REF TO zif_abapgit_ajson_filter. + + PRIVATE SECTION. + DATA mi_filter TYPE REF TO zif_abapgit_ajson_filter. + DATA mr_source_tree TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. + DATA mr_dest_tree TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. + + METHODS walk + IMPORTING + iv_path TYPE string + CHANGING + cs_parent TYPE zif_abapgit_ajson_types=>ty_node OPTIONAL + RAISING + zcx_abapgit_ajson_error. + +ENDCLASS. + +CLASS kHGwlMWhQrsNKkKXALnplwblMIpVBS IMPLEMENTATION. + + METHOD new. + CREATE OBJECT ro_instance EXPORTING ii_filter = ii_filter. + ENDMETHOD. + + METHOD constructor. + ASSERT ii_filter IS BOUND. + mi_filter = ii_filter. + ENDMETHOD. + + METHOD iUFTsMWhQrsNKkKXALnptzVIYRIbuu~run. + + CLEAR et_dest_tree. + GET REFERENCE OF it_source_tree INTO mr_source_tree. + GET REFERENCE OF et_dest_tree INTO mr_dest_tree. + + walk( iv_path = '' ). + + ENDMETHOD. + + METHOD walk. + + DATA ls_node TYPE zif_abapgit_ajson_types=>ty_node. + DATA lv_tab_key TYPE string. + + IF cs_parent-type = zif_abapgit_ajson_types=>node_type-array. + lv_tab_key = 'array_index'. " path + index + ENDIF. + + LOOP AT mr_source_tree->* INTO ls_node USING KEY (lv_tab_key) WHERE path = iv_path. + CASE ls_node-type. + WHEN zif_abapgit_ajson_types=>node_type-boolean OR zif_abapgit_ajson_types=>node_type-null + OR zif_abapgit_ajson_types=>node_type-number OR zif_abapgit_ajson_types=>node_type-string. + + IF mi_filter->keep_node( ls_node ) = abap_false. + CONTINUE. + ENDIF. + + WHEN zif_abapgit_ajson_types=>node_type-array OR zif_abapgit_ajson_types=>node_type-object. + + IF mi_filter->keep_node( + is_node = ls_node + iv_visit = zif_abapgit_ajson_filter=>visit_type-open ) = abap_false. + CONTINUE. + ENDIF. + + " Intentionally clear AFTER "open" + CLEAR ls_node-children. + + walk( + EXPORTING + iv_path = iv_path && ls_node-name && `/` + CHANGING + cs_parent = ls_node ). + + IF mi_filter->keep_node( + is_node = ls_node + iv_visit = zif_abapgit_ajson_filter=>visit_type-close ) = abap_false. + CONTINUE. + ENDIF. + + WHEN OTHERS. + zcx_abapgit_ajson_error=>raise( |Unexpected node type { ls_node-type }| ). + ENDCASE. + + IF cs_parent IS SUPPLIED. + cs_parent-children = cs_parent-children + 1. + IF cs_parent-type = zif_abapgit_ajson_types=>node_type-array. + ls_node-name = |{ cs_parent-children }|. + ls_node-index = cs_parent-children. + ENDIF. + ENDIF. + INSERT ls_node INTO TABLE mr_dest_tree->*. + + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +********************************************************************** +* MAPPER RUNNER +********************************************************************** + +* renamed: zcl_abapgit_ajson :: lcl_mapper_runner +CLASS kHGwlMWhQrsNKkKXALnphFTcRDbOtm DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES iUFTsMWhQrsNKkKXALnptzVIYRIbuu. + CLASS-METHODS new + IMPORTING + ii_mapper TYPE REF TO zif_abapgit_ajson_mapping + RETURNING + VALUE(ro_instance) TYPE REF TO kHGwlMWhQrsNKkKXALnphFTcRDbOtm. + METHODS constructor + IMPORTING + ii_mapper TYPE REF TO zif_abapgit_ajson_mapping. + + PRIVATE SECTION. + DATA mi_mapper TYPE REF TO zif_abapgit_ajson_mapping. + DATA mr_source_tree TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. + DATA mr_dest_tree TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. + + METHODS process_deep_node + IMPORTING + iv_path TYPE string + iv_renamed_path TYPE string + iv_node_type TYPE zif_abapgit_ajson_types=>ty_node-type + RAISING + zcx_abapgit_ajson_error. + +ENDCLASS. + +CLASS kHGwlMWhQrsNKkKXALnphFTcRDbOtm IMPLEMENTATION. + + METHOD new. + CREATE OBJECT ro_instance EXPORTING ii_mapper = ii_mapper. + ENDMETHOD. + + METHOD constructor. + ASSERT ii_mapper IS BOUND. + mi_mapper = ii_mapper. + ENDMETHOD. + + METHOD iUFTsMWhQrsNKkKXALnptzVIYRIbuu~run. + + FIELD-SYMBOLS LIKE LINE OF it_source_tree. + + READ TABLE it_source_tree WITH KEY path = `` name = `` ASSIGNING . + IF sy-subrc <> 0 + OR NOT ( -type = zif_abapgit_ajson_types=>node_type-array OR -type = zif_abapgit_ajson_types=>node_type-object ). + " empty or one-value-only tree + et_dest_tree = it_source_tree. + RETURN. + ENDIF. + + CLEAR et_dest_tree. + GET REFERENCE OF it_source_tree INTO mr_source_tree. + GET REFERENCE OF et_dest_tree INTO mr_dest_tree. + INSERT INTO TABLE et_dest_tree. + + process_deep_node( + iv_path = `/` + iv_renamed_path = `/` + iv_node_type = -type ). + + ENDMETHOD. + + METHOD process_deep_node. + FIELD-SYMBOLS LIKE LINE OF mr_source_tree->*. + DATA ls_renamed_node LIKE . + + LOOP AT mr_source_tree->* ASSIGNING WHERE path = iv_path. + ls_renamed_node = . + IF iv_node_type <> zif_abapgit_ajson_types=>node_type-array. + " don't rename array item names -> they are numeric index + mi_mapper->rename_node( + EXPORTING + is_node = + CHANGING + cv_name = ls_renamed_node-name ). + IF ls_renamed_node-name IS INITIAL. + zcx_abapgit_ajson_error=>raise( + iv_msg = 'Renamed node name cannot be empty' + is_node = ). + ENDIF. + ENDIF. + ls_renamed_node-path = iv_renamed_path. + + INSERT ls_renamed_node INTO TABLE mr_dest_tree->*. + IF sy-subrc <> 0. " = 4 ? + zcx_abapgit_ajson_error=>raise( + iv_msg = 'Renamed node has a duplicate' + is_node = ls_renamed_node ). + ENDIF. + + " maybe also catch CX_SY_ITAB_DUPLICATE_KEY but secondary keys are not changed here, so not for now + + IF -type = zif_abapgit_ajson_types=>node_type-array OR -type = zif_abapgit_ajson_types=>node_type-object. + process_deep_node( + iv_path = iv_path && -name && `/` + iv_renamed_path = iv_renamed_path && ls_renamed_node-name && `/` + iv_node_type = -type ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +********************************************************************** +* MUTATOR QUEUE +********************************************************************** + +* renamed: zcl_abapgit_ajson :: lcl_mutator_queue +CLASS kHGwlMWhQrsNKkKXALnpucOpllUiAS DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES iUFTsMWhQrsNKkKXALnptzVIYRIbuu. + CLASS-METHODS new + RETURNING + VALUE(ro_instance) TYPE REF TO kHGwlMWhQrsNKkKXALnpucOpllUiAS. + METHODS add + IMPORTING + ii_mutator TYPE REF TO iUFTsMWhQrsNKkKXALnptzVIYRIbuu + RETURNING + VALUE(ro_self) TYPE REF TO kHGwlMWhQrsNKkKXALnpucOpllUiAS. + + PRIVATE SECTION. + DATA mt_queue TYPE STANDARD TABLE OF REF TO iUFTsMWhQrsNKkKXALnptzVIYRIbuu. + +ENDCLASS. + +CLASS kHGwlMWhQrsNKkKXALnpucOpllUiAS IMPLEMENTATION. + + METHOD add. + IF ii_mutator IS BOUND. + APPEND ii_mutator TO mt_queue. + ENDIF. + ro_self = me. + ENDMETHOD. + + METHOD new. + CREATE OBJECT ro_instance. + ENDMETHOD. + + METHOD iUFTsMWhQrsNKkKXALnptzVIYRIbuu~run. + + DATA li_mutator TYPE REF TO iUFTsMWhQrsNKkKXALnptzVIYRIbuu. + DATA lv_qsize TYPE i. + FIELD-SYMBOLS LIKE it_source_tree. + FIELD-SYMBOLS LIKE it_source_tree. + DATA lr_buf TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. + + lv_qsize = lines( mt_queue ). + + IF lv_qsize = 0. + et_dest_tree = it_source_tree. + RETURN. + ENDIF. + + LOOP AT mt_queue INTO li_mutator. + IF sy-tabix = 1. + ASSIGN it_source_tree TO . + ELSE. + ASSIGN lr_buf->* TO . + ENDIF. + + IF sy-tabix = lv_qsize. + ASSIGN et_dest_tree TO . + ELSE. + CREATE DATA lr_buf. + ASSIGN lr_buf->* TO . + ENDIF. + + li_mutator->run( + EXPORTING + it_source_tree = + IMPORTING + et_dest_tree = ). + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_ajson IMPLEMENTATION. + METHOD constructor. + ms_opts-keep_item_order = iv_keep_item_order. + ms_opts-to_abap_corresponding_only = iv_to_abap_corresponding_only. + format_datetime( iv_format_datetime ). + ENDMETHOD. + METHOD create_empty. + CREATE OBJECT ro_instance + EXPORTING + iv_to_abap_corresponding_only = iv_to_abap_corresponding_only + iv_format_datetime = iv_format_datetime + iv_keep_item_order = iv_keep_item_order. + ro_instance->mi_custom_mapping = ii_custom_mapping. + ENDMETHOD. + METHOD create_from. + + DATA lo_mutator_queue TYPE REF TO kHGwlMWhQrsNKkKXALnpucOpllUiAS. + + IF ii_source_json IS NOT BOUND. + zcx_abapgit_ajson_error=>raise( 'Source not bound' ). + ENDIF. + + CREATE OBJECT ro_instance + EXPORTING + iv_to_abap_corresponding_only = ii_source_json->opts( )-to_abap_corresponding_only + iv_format_datetime = ii_source_json->opts( )-format_datetime + iv_keep_item_order = ii_source_json->opts( )-keep_item_order. + + IF ii_filter IS NOT BOUND AND ii_mapper IS NOT BOUND. + ro_instance->mt_json_tree = ii_source_json->mt_json_tree. + ELSE. + CREATE OBJECT lo_mutator_queue. + IF ii_mapper IS BOUND. + " Mapping goes first. But maybe it should be a freely definable queue of processors ? + lo_mutator_queue->add( kHGwlMWhQrsNKkKXALnphFTcRDbOtm=>new( ii_mapper ) ). + ENDIF. + IF ii_filter IS BOUND. + lo_mutator_queue->add( kHGwlMWhQrsNKkKXALnplwblMIpVBS=>new( ii_filter ) ). + ENDIF. + lo_mutator_queue->iUFTsMWhQrsNKkKXALnptzVIYRIbuu~run( + EXPORTING + it_source_tree = ii_source_json->mt_json_tree + IMPORTING + et_dest_tree = ro_instance->mt_json_tree ). + ENDIF. + + ENDMETHOD. + METHOD delete_subtree. + + DATA lv_parent_path TYPE string. + DATA lr_parent LIKE ir_parent. + + READ TABLE mt_json_tree INTO rs_top_node + WITH TABLE KEY + path = iv_path + name = iv_name. + IF sy-subrc <> 0. + RETURN. " Not found ? nothing to delete ! + ENDIF. + + DELETE mt_json_tree INDEX sy-tabix. " where path = iv_path and name = iv_name. + + IF rs_top_node-children > 0. " only for objects and arrays + lv_parent_path = iv_path && iv_name && '/*'. + DELETE mt_json_tree WHERE path CP lv_parent_path. + ENDIF. + + " decrement parent children + IF ir_parent IS SUPPLIED. + ir_parent->children = ir_parent->children - 1. + ELSE. + lr_parent = get_item( iv_path ). + IF lr_parent IS NOT INITIAL. + lr_parent->children = lr_parent->children - 1. + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD get_item. + + DATA ls_path_name TYPE zif_abapgit_ajson_types=>ty_path_name. + ls_path_name = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( iv_path ). + + READ TABLE mt_json_tree + REFERENCE INTO rv_item + WITH KEY + path = ls_path_name-path + name = ls_path_name-name. + + ENDMETHOD. + METHOD new. + CREATE OBJECT ro_instance + EXPORTING + iv_to_abap_corresponding_only = iv_to_abap_corresponding_only + iv_format_datetime = iv_format_datetime + iv_keep_item_order = iv_keep_item_order. + ENDMETHOD. + METHOD normalize_path. + rv_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>normalize_path( iv_path ). + ENDMETHOD. + METHOD parse. + + DATA lo_parser TYPE REF TO kHGwlMWhQrsNKkKXALnpfipvepHQnc. + + CREATE OBJECT ro_instance. + CREATE OBJECT lo_parser. + ro_instance->mt_json_tree = lo_parser->parse( + iv_json = iv_json + iv_keep_item_order = iv_keep_item_order ). + ro_instance->mi_custom_mapping = ii_custom_mapping. + ro_instance->ms_opts-keep_item_order = iv_keep_item_order. + + IF iv_freeze = abap_true. + ro_instance->freeze( ). + ENDIF. + + ENDMETHOD. + METHOD prove_path_exists. + + DATA lt_path TYPE string_table. + DATA lr_node_parent LIKE rr_end_node. + DATA lv_cur_path TYPE string. + DATA lv_cur_name TYPE string. + DATA ls_new_node LIKE LINE OF mt_json_tree. + + SPLIT iv_path AT '/' INTO TABLE lt_path. + DELETE lt_path WHERE table_line IS INITIAL. + + DO. + lr_node_parent = rr_end_node. + READ TABLE mt_json_tree REFERENCE INTO rr_end_node + WITH TABLE KEY + path = lv_cur_path + name = lv_cur_name. + IF sy-subrc <> 0. " New node, assume it is always object as it has a named child, use touch_array to init array + CLEAR ls_new_node. + IF lr_node_parent IS NOT INITIAL. " if has parent + lr_node_parent->children = lr_node_parent->children + 1. + IF lr_node_parent->type = zif_abapgit_ajson_types=>node_type-array. + ls_new_node-index = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>validate_array_index( + iv_path = lv_cur_path + iv_index = lv_cur_name ). + ENDIF. + ENDIF. + ls_new_node-path = lv_cur_path. + ls_new_node-name = lv_cur_name. + ls_new_node-type = zif_abapgit_ajson_types=>node_type-object. + INSERT ls_new_node INTO TABLE mt_json_tree REFERENCE INTO rr_end_node. + ENDIF. + lv_cur_path = lv_cur_path && lv_cur_name && '/'. + READ TABLE lt_path INDEX sy-index INTO lv_cur_name. + IF sy-subrc <> 0. + EXIT. " no more segments + ENDIF. + ENDDO. + + ENDMETHOD. + METHOD read_only_watchdog. + IF ms_opts-read_only = abap_true. + zcx_abapgit_ajson_error=>raise( 'This json instance is read only' ). + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_ajson~array_to_string_table. + + DATA lv_normalized_path TYPE string. + DATA lr_node TYPE REF TO zif_abapgit_ajson_types=>ty_node. + FIELD-SYMBOLS LIKE LINE OF mt_json_tree. + + lv_normalized_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>normalize_path( iv_path ). + lr_node = get_item( iv_path ). + + IF lr_node IS INITIAL. + zcx_abapgit_ajson_error=>raise( |Path not found: { iv_path }| ). + ENDIF. + IF lr_node->type <> zif_abapgit_ajson_types=>node_type-array. + zcx_abapgit_ajson_error=>raise( |Array expected at: { iv_path }| ). + ENDIF. + + LOOP AT mt_json_tree ASSIGNING WHERE path = lv_normalized_path. + CASE -type. + WHEN zif_abapgit_ajson_types=>node_type-number OR zif_abapgit_ajson_types=>node_type-string. + APPEND -value TO rt_string_table. + WHEN zif_abapgit_ajson_types=>node_type-null. + APPEND '' TO rt_string_table. + WHEN zif_abapgit_ajson_types=>node_type-boolean. + DATA lv_tmp TYPE string. + IF -value = 'true'. + lv_tmp = abap_true. + ELSE. + CLEAR lv_tmp. + ENDIF. + APPEND lv_tmp TO rt_string_table. + WHEN OTHERS. + zcx_abapgit_ajson_error=>raise( |Cannot convert [{ -type + }] to string at [{ -path }{ -name }]| ). + ENDCASE. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_ajson~clear. + + read_only_watchdog( ). + CLEAR mt_json_tree. + + ENDMETHOD. + METHOD zif_abapgit_ajson~clone. + ri_json = create_from( me ). + ENDMETHOD. + METHOD zif_abapgit_ajson~delete. + + read_only_watchdog( ). + + DATA ls_split_path TYPE zif_abapgit_ajson_types=>ty_path_name. + ls_split_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( iv_path ). + + delete_subtree( + iv_path = ls_split_path-path + iv_name = ls_split_path-name ). + + ri_json = me. + + ENDMETHOD. + METHOD zif_abapgit_ajson~exists. + rv_exists = boolc( get_item( iv_path ) IS NOT INITIAL ). + ENDMETHOD. + METHOD zif_abapgit_ajson~filter. + ri_json = create_from( + ii_source_json = me + ii_filter = ii_filter ). + ENDMETHOD. + METHOD zif_abapgit_ajson~format_datetime. + ms_opts-format_datetime = iv_use_iso. + ri_json = me. + ENDMETHOD. + METHOD zif_abapgit_ajson~freeze. + ms_opts-read_only = abap_true. + ENDMETHOD. + METHOD zif_abapgit_ajson~get. + + DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. + lr_item = get_item( iv_path ). + IF lr_item IS NOT INITIAL. + rv_value = lr_item->value. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ajson~get_boolean. + + DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. + lr_item = get_item( iv_path ). + IF lr_item IS INITIAL OR lr_item->type = zif_abapgit_ajson_types=>node_type-null. + RETURN. + ELSEIF lr_item->type = zif_abapgit_ajson_types=>node_type-boolean. + rv_value = boolc( lr_item->value = 'true' ). + ELSEIF lr_item->value IS NOT INITIAL. + rv_value = abap_true. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ajson~get_date. + + DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. + DATA lv_y TYPE c LENGTH 4. + DATA lv_m TYPE c LENGTH 2. + DATA lv_d TYPE c LENGTH 2. + + lr_item = get_item( iv_path ). + + IF lr_item IS NOT INITIAL AND lr_item->type = zif_abapgit_ajson_types=>node_type-string. + FIND FIRST OCCURRENCE OF REGEX '^(\d{4})-(\d{2})-(\d{2})(T|$)' + IN lr_item->value + SUBMATCHES lv_y lv_m lv_d. + CONCATENATE lv_y lv_m lv_d INTO rv_value. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ajson~get_integer. + + DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. + lr_item = get_item( iv_path ). + IF lr_item IS NOT INITIAL AND lr_item->type = zif_abapgit_ajson_types=>node_type-number. + rv_value = lr_item->value. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ajson~get_node_type. + + DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. + lr_item = get_item( iv_path ). + IF lr_item IS NOT INITIAL. + rv_node_type = lr_item->type. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ajson~get_number. + + DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. + lr_item = get_item( iv_path ). + IF lr_item IS NOT INITIAL AND lr_item->type = zif_abapgit_ajson_types=>node_type-number. + rv_value = lr_item->value. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ajson~get_string. + + DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. + lr_item = get_item( iv_path ). + IF lr_item IS NOT INITIAL AND lr_item->type <> zif_abapgit_ajson_types=>node_type-null. + rv_value = lr_item->value. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ajson~get_timestamp. + + DATA lo_to_abap TYPE REF TO kHGwlMWhQrsNKkKXALnpXxNdxsjJjI. + DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. + + lr_item = get_item( iv_path ). + + IF lr_item IS INITIAL. + RETURN. + ENDIF. + + CREATE OBJECT lo_to_abap. + + TRY. + rv_value = lo_to_abap->to_timestamp( lr_item->value ). + CATCH zcx_abapgit_ajson_error. + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_ajson~get_timestampl. + + DATA lo_to_abap TYPE REF TO kHGwlMWhQrsNKkKXALnpXxNdxsjJjI. + DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. + + lr_item = get_item( iv_path ). + + IF lr_item IS INITIAL. + RETURN. + ENDIF. + + CREATE OBJECT lo_to_abap. + + TRY. + rv_value = lo_to_abap->to_timestampl( lr_item->value ). + CATCH zcx_abapgit_ajson_error. + RETURN. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_ajson~is_empty. + rv_yes = boolc( lines( mt_json_tree ) = 0 ). + ENDMETHOD. + METHOD zif_abapgit_ajson~keep_item_order. + ms_opts-keep_item_order = abap_true. + ri_json = me. + ENDMETHOD. + METHOD zif_abapgit_ajson~map. + ri_json = create_from( + ii_source_json = me + ii_mapper = ii_mapper ). + ENDMETHOD. + METHOD zif_abapgit_ajson~members. + + DATA lv_normalized_path TYPE string. + FIELD-SYMBOLS LIKE LINE OF mt_json_tree. + + lv_normalized_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>normalize_path( iv_path ). + + LOOP AT mt_json_tree ASSIGNING WHERE path = lv_normalized_path. + APPEND -name TO rt_members. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_ajson~opts. + rs_opts = ms_opts. + ENDMETHOD. + METHOD zif_abapgit_ajson~push. + + DATA lr_parent TYPE REF TO zif_abapgit_ajson_types=>ty_node. + DATA lr_new_node TYPE REF TO zif_abapgit_ajson_types=>ty_node. + + read_only_watchdog( ). + + lr_parent = get_item( iv_path ). + + IF lr_parent IS INITIAL. + zcx_abapgit_ajson_error=>raise( |Path [{ iv_path }] does not exist| ). + ENDIF. + + IF lr_parent->type <> zif_abapgit_ajson_types=>node_type-array. + zcx_abapgit_ajson_error=>raise( |Path [{ iv_path }] is not array| ). + ENDIF. + + DATA lt_new_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt. + DATA ls_new_path TYPE zif_abapgit_ajson_types=>ty_path_name. + DATA lv_new_index TYPE i. + + lv_new_index = lr_parent->children + 1. + ls_new_path-path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>normalize_path( iv_path ). + ls_new_path-name = |{ lv_new_index }|. + + lt_new_nodes = kHGwlMWhQrsNKkKXALnpeJqampzabz=>convert( + is_opts = ms_opts + iv_data = iv_val + is_prefix = ls_new_path ). + READ TABLE lt_new_nodes INDEX 1 REFERENCE INTO lr_new_node. " assume first record is the array item - not ideal ! + ASSERT sy-subrc = 0. + lr_new_node->index = lv_new_index. + + " update data + lr_parent->children = lv_new_index. + INSERT LINES OF lt_new_nodes INTO TABLE mt_json_tree. + + ri_json = me. + + ENDMETHOD. + METHOD zif_abapgit_ajson~set. + + DATA ls_split_path TYPE zif_abapgit_ajson_types=>ty_path_name. + DATA lr_parent TYPE REF TO zif_abapgit_ajson_types=>ty_node. + DATA ls_deleted_node TYPE zif_abapgit_ajson_types=>ty_node. + DATA lv_item_order TYPE zif_abapgit_ajson_types=>ty_node-order. + + read_only_watchdog( ). + + ri_json = me. + + IF iv_val IS INITIAL AND iv_ignore_empty = abap_true AND iv_node_type IS INITIAL. + RETURN. " nothing to assign + ENDIF. + + IF iv_node_type IS NOT INITIAL + AND iv_node_type <> zif_abapgit_ajson_types=>node_type-boolean AND iv_node_type <> zif_abapgit_ajson_types=>node_type-null + AND iv_node_type <> zif_abapgit_ajson_types=>node_type-number AND iv_node_type <> zif_abapgit_ajson_types=>node_type-string. + zcx_abapgit_ajson_error=>raise( |Unexpected type { iv_node_type }| ). + ENDIF. + + ls_split_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( iv_path ). + IF ls_split_path IS INITIAL. " Assign root, exceptional processing + IF iv_node_type IS NOT INITIAL. + mt_json_tree = kHGwlMWhQrsNKkKXALnpeJqampzabz=>insert_with_type( + is_opts = ms_opts + iv_data = iv_val + iv_type = iv_node_type + is_prefix = ls_split_path + ii_custom_mapping = mi_custom_mapping ). + ELSE. + mt_json_tree = kHGwlMWhQrsNKkKXALnpeJqampzabz=>convert( + is_opts = ms_opts + iv_data = iv_val + is_prefix = ls_split_path + ii_custom_mapping = mi_custom_mapping ). + ENDIF. + RETURN. + ENDIF. + + " Ensure whole path exists + lr_parent = prove_path_exists( ls_split_path-path ). + ASSERT lr_parent IS NOT INITIAL. + + " delete if exists with subtree + ls_deleted_node = delete_subtree( + ir_parent = lr_parent + iv_path = ls_split_path-path + iv_name = ls_split_path-name ). + lv_item_order = ls_deleted_node-order. + + " convert to json + DATA lt_new_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt. + DATA lv_array_index TYPE i. + + IF lr_parent->type = zif_abapgit_ajson_types=>node_type-array. + lv_array_index = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>validate_array_index( + iv_path = ls_split_path-path + iv_index = ls_split_path-name ). + ELSEIF lr_parent->type = zif_abapgit_ajson_types=>node_type-object + AND lv_item_order = 0 AND ms_opts-keep_item_order = abap_true. + lv_item_order = lr_parent->children + 1. + ENDIF. + + IF iv_node_type IS NOT INITIAL. + lt_new_nodes = kHGwlMWhQrsNKkKXALnpeJqampzabz=>insert_with_type( + is_opts = ms_opts + iv_item_order = lv_item_order + iv_data = iv_val + iv_type = iv_node_type + iv_array_index = lv_array_index + is_prefix = ls_split_path + ii_custom_mapping = mi_custom_mapping ). + ELSE. + lt_new_nodes = kHGwlMWhQrsNKkKXALnpeJqampzabz=>convert( + is_opts = ms_opts + iv_item_order = lv_item_order + iv_data = iv_val + iv_array_index = lv_array_index + is_prefix = ls_split_path + ii_custom_mapping = mi_custom_mapping ). + ENDIF. + + " update nodes + IF lines( lt_new_nodes ) > 0. + lr_parent->children = lr_parent->children + 1. + INSERT LINES OF lt_new_nodes INTO TABLE mt_json_tree. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_ajson~setx. + + DATA lv_path TYPE string. + DATA lv_val TYPE string. + DATA lv_int TYPE i. + DATA lv_dec TYPE decfloat34. + DATA lv_last TYPE i. + + IF iv_param IS INITIAL. + ri_json = me. + RETURN. + ENDIF. + + SPLIT iv_param AT ':' INTO lv_path lv_val. + CONDENSE lv_path. + CONDENSE lv_val. + + IF lv_val IS INITIAL. + ri_json = me. + RETURN. " Hmm ? or empty string ? or null ? + ENDIF. + + IF go_float_regex IS NOT BOUND. + CREATE OBJECT go_float_regex EXPORTING pattern = '^([1-9][0-9]*|0)\.[0-9]+$'. + " expects fractional, because ints are detected separately + ENDIF. + + IF lv_val = 'null'. + zif_abapgit_ajson~set_null( lv_path ). + ELSEIF lv_val = 'true'. + zif_abapgit_ajson~set_boolean( + iv_path = lv_path + iv_val = abap_true ). + ELSEIF lv_val = 'false'. + zif_abapgit_ajson~set_boolean( + iv_path = lv_path + iv_val = abap_false ). + ELSEIF lv_val CO '0123456789'. + lv_int = lv_val. + zif_abapgit_ajson~set_integer( + iv_path = lv_path + iv_val = lv_int ). + ELSEIF lv_val CO '0123456789.' AND go_float_regex->create_matcher( text = lv_val )->match( ) = abap_true. + lv_dec = lv_val. + zif_abapgit_ajson~set( + iv_path = lv_path + iv_val = lv_dec ). + ELSEIF lv_val+0(1) = '{' OR lv_val+0(1) = '['. + "Expect object/array, but no further checks, parser will catch errors + zif_abapgit_ajson~set( + iv_path = lv_path + iv_val = parse( + iv_json = lv_val + iv_keep_item_order = ms_opts-keep_item_order ) ). + ELSE. " string + lv_last = strlen( lv_val ) - 1. + IF lv_val+0(1) = '"' AND lv_val+lv_last(1) = '"'. + lv_val = substring( + val = lv_val + off = 1 + len = lv_last - 1 ). + ENDIF. + zif_abapgit_ajson~set_string( + iv_path = lv_path + iv_val = lv_val ). + ENDIF. + + ri_json = me. + + ENDMETHOD. + METHOD zif_abapgit_ajson~set_boolean. + + ri_json = me. + + DATA lv_bool TYPE abap_bool. + lv_bool = boolc( iv_val IS NOT INITIAL ). + zif_abapgit_ajson~set( + iv_ignore_empty = abap_false + iv_path = iv_path + iv_val = lv_bool ). + + ENDMETHOD. + METHOD zif_abapgit_ajson~set_date. + + ri_json = me. + + DATA lv_val TYPE string. + lv_val = kHGwlMWhQrsNKkKXALnpeJqampzabz=>format_date( iv_val ). + + zif_abapgit_ajson~set( + iv_ignore_empty = abap_false + iv_path = iv_path + iv_val = lv_val ). + + ENDMETHOD. + METHOD zif_abapgit_ajson~set_integer. + + ri_json = me. + + zif_abapgit_ajson~set( + iv_ignore_empty = abap_false + iv_path = iv_path + iv_val = iv_val ). + + ENDMETHOD. + METHOD zif_abapgit_ajson~set_null. + + ri_json = me. + + DATA lv_null_ref TYPE REF TO data. + zif_abapgit_ajson~set( + iv_ignore_empty = abap_false + iv_path = iv_path + iv_val = lv_null_ref ). + + ENDMETHOD. + METHOD zif_abapgit_ajson~set_string. + + ri_json = me. + + DATA lv_val TYPE string. + lv_val = iv_val. + zif_abapgit_ajson~set( + iv_ignore_empty = abap_false + iv_path = iv_path + iv_val = lv_val ). + + ENDMETHOD. + METHOD zif_abapgit_ajson~set_timestamp. + + ri_json = me. + + DATA lv_timestamp_iso TYPE string. + lv_timestamp_iso = kHGwlMWhQrsNKkKXALnpeJqampzabz=>format_timestamp( iv_val ). + + zif_abapgit_ajson~set( + iv_ignore_empty = abap_false + iv_path = iv_path + iv_val = lv_timestamp_iso ). + + ENDMETHOD. + METHOD zif_abapgit_ajson~set_timestampl. + + ri_json = me. + + DATA lv_timestamp_iso TYPE string. + lv_timestamp_iso = kHGwlMWhQrsNKkKXALnpeJqampzabz=>format_timestampl( iv_val ). + + zif_abapgit_ajson~set( + iv_ignore_empty = abap_false + iv_path = iv_path + iv_val = lv_timestamp_iso ). + + ENDMETHOD. + METHOD zif_abapgit_ajson~slice. + + " TODO: idea + " read only mode (for read only jsons or a param) + " which would reuse the original tree, so copy a reference of the tree, presuming that it is not changed + " this will be faster, in particular for array iterations + + DATA lo_section TYPE REF TO zcl_abapgit_ajson. + DATA ls_item LIKE LINE OF mt_json_tree. + DATA lv_normalized_path TYPE string. + DATA ls_path_parts TYPE zif_abapgit_ajson_types=>ty_path_name. + DATA lv_path_len TYPE i. + DATA lv_path_pattern TYPE string. + + CREATE OBJECT lo_section. + lo_section->mi_custom_mapping = mi_custom_mapping. + + lv_normalized_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>normalize_path( iv_path ). + lv_path_len = strlen( lv_normalized_path ). + ls_path_parts = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( lv_normalized_path ). + + READ TABLE mt_json_tree INTO ls_item + WITH KEY path = ls_path_parts-path name = ls_path_parts-name. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + CLEAR: ls_item-path, ls_item-name, ls_item-order. " this becomes a new root + INSERT ls_item INTO TABLE lo_section->mt_json_tree. + + lv_path_pattern = lv_normalized_path && `*`. + + LOOP AT mt_json_tree INTO ls_item WHERE path CP lv_path_pattern. + + ls_item-path = substring( val = ls_item-path + off = lv_path_len - 1 ). " less closing '/' + INSERT ls_item INTO TABLE lo_section->mt_json_tree. + + ENDLOOP. + + ri_json = lo_section. + + ENDMETHOD. + METHOD zif_abapgit_ajson~stringify. + + rv_json = kHGwlMWhQrsNKkKXALnpFgyFungUrS=>stringify( + it_json_tree = mt_json_tree + iv_keep_item_order = ms_opts-keep_item_order + iv_indent = iv_indent ). + + ENDMETHOD. + METHOD zif_abapgit_ajson~touch_array. + + DATA lr_node TYPE REF TO zif_abapgit_ajson_types=>ty_node. + DATA ls_deleted_node TYPE zif_abapgit_ajson_types=>ty_node. + DATA ls_new_node LIKE LINE OF mt_json_tree. + DATA ls_split_path TYPE zif_abapgit_ajson_types=>ty_path_name. + + read_only_watchdog( ). + + ls_split_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( iv_path ). + IF ls_split_path IS INITIAL. " Assign root, exceptional processing + ls_new_node-path = ls_split_path-path. + ls_new_node-name = ls_split_path-name. + ls_new_node-type = zif_abapgit_ajson_types=>node_type-array. + INSERT ls_new_node INTO TABLE mt_json_tree. + RETURN. + ENDIF. + + IF iv_clear = abap_true. + ls_deleted_node = delete_subtree( + iv_path = ls_split_path-path + iv_name = ls_split_path-name ). + ELSE. + lr_node = get_item( iv_path ). + ENDIF. + + IF lr_node IS INITIAL. " Or node was cleared + + DATA lr_parent TYPE REF TO zif_abapgit_ajson_types=>ty_node. + lr_parent = prove_path_exists( ls_split_path-path ). + ASSERT lr_parent IS NOT INITIAL. + + lr_parent->children = lr_parent->children + 1. + + ls_new_node-path = ls_split_path-path. + ls_new_node-name = ls_split_path-name. + ls_new_node-type = zif_abapgit_ajson_types=>node_type-array. + + IF ms_opts-keep_item_order = abap_true. + IF ls_deleted_node IS NOT INITIAL. + ls_new_node-order = ls_deleted_node-order. + ELSE. + ls_new_node-order = lr_parent->children. + ENDIF. + ENDIF. + + INSERT ls_new_node INTO TABLE mt_json_tree. + + ELSEIF lr_node->type <> zif_abapgit_ajson_types=>node_type-array. + zcx_abapgit_ajson_error=>raise( |Path [{ iv_path }] already used and is not array| ). + ENDIF. + + ri_json = me. + + ENDMETHOD. + METHOD zif_abapgit_ajson~to_abap. + + DATA lo_to_abap TYPE REF TO kHGwlMWhQrsNKkKXALnpXxNdxsjJjI. + + CLEAR ev_container. + CREATE OBJECT lo_to_abap + EXPORTING + iv_corresponding = boolc( iv_corresponding = abap_true OR ms_opts-to_abap_corresponding_only = abap_true ) + ii_custom_mapping = mi_custom_mapping + ii_refs_initiator = ii_refs_initiator. + + lo_to_abap->to_abap( + EXPORTING + it_nodes = zif_abapgit_ajson~mt_json_tree + CHANGING + c_container = ev_container ). + + ENDMETHOD. + METHOD zif_abapgit_ajson~to_abap_corresponding_only. + ms_opts-to_abap_corresponding_only = iv_enable. + ri_json = me. + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_WHERE_USED_TOOLS IMPLEMENTATION. + METHOD build_package_scope. + + FIELD-SYMBOLS TYPE zif_abapgit_definitions=>ty_tadir. + FIELD-SYMBOLS LIKE LINE OF rt_package_scope. + + rt_package_scope = ir_package_scope. + LOOP AT it_tadir ASSIGNING . + CHECK -object = 'DEVC'. + APPEND INITIAL LINE TO rt_package_scope ASSIGNING . + -sign = 'E'. + -option = 'EQ'. + -low = -obj_name. + ENDLOOP. + + ENDMETHOD. + METHOD collect_where_used. + + DATA li_progress TYPE REF TO zif_abapgit_progress. + DATA lt_where_used TYPE ty_where_used_tt. + DATA lt_objs_portion LIKE rt_objs. + + FIELD-SYMBOLS TYPE zif_abapgit_definitions=>ty_tadir. + + li_progress = zcl_abapgit_progress=>get_instance( lines( it_tadir ) ). + + LOOP AT it_tadir ASSIGNING . + CHECK -object <> 'DEVC'. + + li_progress->show( + iv_current = sy-tabix + iv_text = |{ -object } { -obj_name }| ). + + lt_where_used = get_where_used( + iv_obj_type = |{ -object }| + iv_obj_name = -obj_name + ir_package_scope = ir_package_scope ). + + lt_objs_portion = convert_list( + iv_package = -devclass + iv_obj_type = -object + iv_obj_name = -obj_name + it_where_used = lt_where_used ). + + APPEND LINES OF lt_objs_portion TO rt_objs. + + ENDLOOP. + + li_progress->off( ). + + ENDMETHOD. + METHOD convert_list. + + " See also CL_FINB_GN_BBI=>GET_CROSSREF + + FIELD-SYMBOLS LIKE LINE OF rt_objs. + FIELD-SYMBOLS LIKE LINE OF it_where_used. + + LOOP AT it_where_used ASSIGNING . + + APPEND INITIAL LINE TO rt_objs ASSIGNING . + -dep_package = iv_package. + -dep_obj_type = iv_obj_type. + -dep_obj_name = iv_obj_name. + + -dep_used_obj = -used_obj. + -dep_used_cls = -used_cls. + + -obj_cls = -object_cls. + -obj_name = -encl_objec. + IF -obj_name IS INITIAL. + -obj_name = -object. + ENDIF. + + IF -object_cls = 'FF'. " Function module + -obj_type = 'FUNC'. + -package = get_func_package( -obj_name ). + + ELSE. + -obj_type = decode_obj_type( -object_cls ). + + -package = get_obj_package( + iv_obj_type = -obj_type + iv_obj_name = -obj_name ). + + IF -package IS INITIAL AND -obj_type = 'CLAS'. + -package = get_obj_package( + iv_obj_type = 'INTF' + iv_obj_name = -obj_name ). + IF -package IS NOT INITIAL. + -obj_type = 'INTF'. + ENDIF. + ENDIF. + ENDIF. + + IF -package IS INITIAL. + IF -obj_type = 'PROG'. " Maybe it is an include + + -package = get_incl_package( -obj_name ). + IF -package IS INITIAL. + SELECT SINGLE subc INTO -obj_prog_type FROM trdir WHERE name = -obj_name. + IF -obj_prog_type IS NOT INITIAL AND -obj_prog_type <> '1'. " Exec. prog + -obj_type = 'INCL'. + ENDIF. + ENDIF. + + ENDIF. + + IF -package IS INITIAL. + -package = '????'. + ENDIF. + ENDIF. + + ENDLOOP. + + " some includes are ENHO ... + " include detection TRDIR, D010INC ??? + " how to find connection with ENHO ? + " Useful: https://github.com/abaplint/abaplint-sci-client/blob/main/src/deps/zcl_abaplint_deps_find.clas.abap + " And cl_wb_manager->if_wb_manager~request_tool_access + " And discussions in https://github.com/abapGit/abapGit/pull/6897 + + ENDMETHOD. + METHOD decode_obj_type. + + FIELD-SYMBOLS LIKE LINE OF mt_dev_obj_cache. + + IF mt_dev_obj_cache IS INITIAL. + SELECT type tadir INTO TABLE mt_dev_obj_cache + FROM euobjedit. + ENDIF. + + READ TABLE mt_dev_obj_cache ASSIGNING WITH KEY type = iv_type. + IF sy-subrc = 0. + rv_type = -tadir. + ENDIF. + + ENDMETHOD. + METHOD find_root_packages. + + DATA: + BEGIN OF ls_root, + pkg TYPE devclass, + root TYPE devclass, + END OF ls_root, + lt_roots LIKE HASHED TABLE OF ls_root WITH UNIQUE KEY pkg. + DATA lv_pkg_tmp TYPE devclass. + + FIELD-SYMBOLS LIKE LINE OF ct_objs. + + LOOP AT ct_objs ASSIGNING . + READ TABLE lt_roots INTO ls_root WITH KEY pkg = -package. + IF sy-subrc <> 0. + ls_root-pkg = -package. + ls_root-root = -package. " Self by default + + DO 10 TIMES. " Actually should be safe to run infinitely ... + lv_pkg_tmp = zcl_abapgit_factory=>get_sap_package( -package )->read_parent( ). + IF lv_pkg_tmp IS INITIAL. + EXIT. + ELSE. + ls_root-root = lv_pkg_tmp. + ENDIF. + ENDDO. + + INSERT ls_root INTO TABLE lt_roots. + ENDIF. + + -root_package = ls_root-root. + ENDLOOP. + + ENDMETHOD. + METHOD get_func_package. + + " See also: FUNCTION_INCLUDE_INFO, TFDIR, find main program -> get its pkg + + DATA ls_obj_sig LIKE LINE OF mt_object_packages. + + READ TABLE mt_object_packages INTO ls_obj_sig WITH KEY obj_type = 'FUNC' obj_name = iv_func_name. + + IF sy-subrc <> 0. + SELECT SINGLE devclass INTO ls_obj_sig-package + FROM info_func + WHERE funcname = iv_func_name. + IF ls_obj_sig-package IS NOT INITIAL. + ls_obj_sig-obj_type = 'FUNC'. + ls_obj_sig-obj_name = iv_func_name. + INSERT ls_obj_sig INTO TABLE mt_object_packages. + ENDIF. + ENDIF. + + rv_package = ls_obj_sig-package. + + ENDMETHOD. + METHOD get_incl_package. + + DATA lv_program TYPE progname. + DATA lv_area TYPE rs38l_area. + + lv_program = iv_prog_name. + + CALL FUNCTION 'FUNCTION_INCLUDE_CONCATENATE' + CHANGING + program = lv_program + complete_area = lv_area + EXCEPTIONS + not_enough_input = 1 + no_function_pool = 2 + delimiter_wrong_position = 3 + OTHERS = 4 ##FM_SUBRC_OK. + + IF lv_area IS INITIAL. + SELECT SINGLE master FROM d010inc INTO lv_program + WHERE include = iv_prog_name. + + CALL FUNCTION 'FUNCTION_INCLUDE_CONCATENATE' + CHANGING + program = lv_program + complete_area = lv_area + EXCEPTIONS + not_enough_input = 1 + no_function_pool = 2 + delimiter_wrong_position = 3 + OTHERS = 4 ##FM_SUBRC_OK. + ENDIF. + + IF lv_area IS NOT INITIAL. + rv_package = get_obj_package( + iv_obj_type = 'FUGR' + iv_obj_name = |{ lv_area }| ). + RETURN. + ENDIF. + + " TODO more ... + + ENDMETHOD. + METHOD get_obj_package. + + " see also zcl_abapgit_tadir->get_object_package for checks + + DATA ls_obj_sig LIKE LINE OF mt_object_packages. + + READ TABLE mt_object_packages INTO ls_obj_sig WITH KEY obj_type = iv_obj_type obj_name = iv_obj_name. + + IF sy-subrc <> 0. + ls_obj_sig-package = zcl_abapgit_factory=>get_tadir( )->read_single( + iv_object = iv_obj_type + iv_obj_name = iv_obj_name )-devclass. + IF ls_obj_sig-package IS NOT INITIAL. + ls_obj_sig-obj_type = iv_obj_type. + ls_obj_sig-obj_name = iv_obj_name. + INSERT ls_obj_sig INTO TABLE mt_object_packages. + ENDIF. + ENDIF. + + rv_package = ls_obj_sig-package. + + ENDMETHOD. + METHOD get_where_used. + + DATA lt_findstrings TYPE string_table. + DATA lt_scope LIKE it_scope. + DATA lv_findstring LIKE LINE OF lt_findstrings. + + IF iv_obj_name IS INITIAL. + RETURN. + ENDIF. + + lt_scope = it_scope. + + lv_findstring = iv_obj_name. + INSERT lv_findstring INTO TABLE lt_findstrings. + + CALL FUNCTION 'RS_EU_CROSSREF' + EXPORTING + i_find_obj_cls = iv_obj_type + no_dialog = abap_true + without_text = abap_true + TABLES + i_findstrings = lt_findstrings + o_founds = rt_findings + i_scope_object_cls = lt_scope + i_scope_devclass = ir_package_scope + EXCEPTIONS + not_executed = 1 + not_found = 2 + illegal_object = 3 + no_cross_for_this_object = 4 + batch = 5 + batchjob_error = 6 + wrong_type = 7 + object_not_exist = 8 + OTHERS = 9. + + IF sy-subrc = 1 OR sy-subrc = 2 OR lines( rt_findings ) = 0. + RETURN. + ELSEIF sy-subrc > 2. + zcx_abapgit_exception=>raise( |RS_EU_CROSSREF({ sy-subrc }) for { iv_obj_type } { iv_obj_name }| ). + ENDIF. + + ENDMETHOD. + METHOD new. + CREATE OBJECT ro_instance. + ENDMETHOD. + METHOD select_external_usages. + + DATA lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lt_package_scope LIKE ir_package_scope. + + lt_tadir = zcl_abapgit_factory=>get_tadir( )->read( + iv_package = iv_package + iv_ignore_subpackages = iv_ignore_subpackages ). + + lt_package_scope = build_package_scope( + ir_package_scope = ir_package_scope + it_tadir = lt_tadir ). + + rt_objs = collect_where_used( + ir_package_scope = lt_package_scope + it_tadir = lt_tadir ). + + SORT rt_objs. + DELETE ADJACENT DUPLICATES FROM rt_objs. + " Duplicates happen e.g. because where-used is found by method. + " However here this functionality aggregates them to the object + " These are not true duplicates, so if ever the method name (or any other duplicate cause) + " will be extracted, this sort can be removed + + find_root_packages( CHANGING ct_objs = rt_objs ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_code_inspector IMPLEMENTATION. + METHOD cleanup. + + IF mo_inspection IS BOUND. + + mo_inspection->delete( + EXCEPTIONS + locked = 1 + error_in_enqueue = 2 + not_authorized = 3 + exceptn_appl_exists = 4 + OTHERS = 5 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Couldn't delete inspection. Subrc = { sy-subrc }| ). + ENDIF. + + ENDIF. + + io_set->delete( + EXCEPTIONS + exists_in_insp = 1 + locked = 2 + error_in_enqueue = 3 + not_authorized = 4 + exists_in_objs = 5 + OTHERS = 6 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Couldn't delete objectset. Subrc = { sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + IF iv_package IS INITIAL. + zcx_abapgit_exception=>raise( |Please supply package| ). + ENDIF. + + mv_package = iv_package. + + " We create the inspection and objectset with dummy names. + " Because we want to persist them so we can run it in parallel. + " Both are deleted afterwards. + mv_name = |{ sy-uname }_{ sy-datum }_{ sy-uzeit }|. + mv_run_mode = decide_run_mode( ). + + ENDMETHOD. + METHOD create_inspection. + + cl_ci_inspection=>create( + EXPORTING + p_user = sy-uname + p_name = mv_name + RECEIVING + p_ref = ro_inspection + EXCEPTIONS + locked = 1 + error_in_enqueue = 2 + not_authorized = 3 + OTHERS = 4 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Failed to create inspection. Subrc = { sy-subrc }| ). + ENDIF. + + ro_inspection->set( + p_chkv = io_variant + p_objs = io_set ). + + ro_inspection->save( + EXCEPTIONS + missing_information = 1 + insp_no_name = 2 + not_enqueued = 3 + OTHERS = 4 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Failed to save inspection. Subrc = { sy-subrc }| ). + ENDIF. + + ENDMETHOD. + METHOD create_objectset. + + DATA: lt_objs TYPE scit_objs, + ls_obj TYPE scir_objs, + lt_objs_check TYPE scit_objs, + ls_item TYPE zif_abapgit_definitions=>ty_item, + lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. + + lt_packages = zcl_abapgit_factory=>get_sap_package( mv_package )->list_subpackages( ). + INSERT mv_package INTO TABLE lt_packages. + + SELECT object AS objtype obj_name AS objname + FROM tadir + INTO CORRESPONDING FIELDS OF TABLE lt_objs + FOR ALL ENTRIES IN lt_packages + WHERE devclass = lt_packages-table_line + AND delflag = abap_false + AND pgmid = 'R3TR' ##TOO_MANY_ITAB_FIELDS. "#EC CI_GENBUFF + + LOOP AT lt_objs INTO ls_obj. + + IF skip_object( ls_obj ) = abap_true. + CONTINUE. + ENDIF. + + ls_item-obj_type = ls_obj-objtype. + ls_item-obj_name = ls_obj-objname. + + IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. + CONTINUE. + ENDIF. + + INSERT ls_obj INTO TABLE lt_objs_check. + + ENDLOOP. + + ro_set = cl_ci_objectset=>save_from_list( + p_name = mv_name + p_objects = lt_objs_check ). + + ENDMETHOD. + METHOD create_variant. + + IF iv_variant IS INITIAL. + zcx_abapgit_exception=>raise( |No check variant supplied.| ). + ENDIF. + + cl_ci_checkvariant=>get_ref( + EXPORTING + p_user = '' + p_name = iv_variant + RECEIVING + p_ref = ro_variant + EXCEPTIONS + chkv_not_exists = 1 + missing_parameter = 2 + OTHERS = 3 ). + + CASE sy-subrc. + WHEN 1. + zcx_abapgit_exception=>raise( |Check variant { iv_variant } doesn't exist| ). + WHEN 2. + zcx_abapgit_exception=>raise( |Parameter missing for check variant { iv_variant }| ). + ENDCASE. + + ENDMETHOD. + METHOD decide_run_mode. + + DATA lo_settings TYPE REF TO zcl_abapgit_settings. + lo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + + IF sy-batch = abap_true. + " We have to disable parallelization in batch because of lock errors. + rv_run_mode = co_run_mode-run_via_rfc. + ELSEIF lo_settings->get_parallel_proc_disabled( ) = abap_false. + rv_run_mode = co_run_mode-run_loc_parallel. + ELSE. + rv_run_mode = co_run_mode-run_via_rfc. + ENDIF. + + ENDMETHOD. + METHOD filter_inspection. + + " Remove findings in LSVIM* includes which are part of generated maintenance screens + DELETE ct_list WHERE sobjtype = 'PROG' AND sobjname CP 'LSVIM*'. + + ENDMETHOD. + METHOD get_code_inspector. + + DATA ls_code_inspector LIKE LINE OF gt_code_inspector. + + FIELD-SYMBOLS TYPE ty_code_inspector_pack. + + READ TABLE gt_code_inspector ASSIGNING WITH TABLE KEY package = iv_package. + IF sy-subrc <> 0. + ls_code_inspector-package = iv_package. + + CREATE OBJECT ls_code_inspector-instance TYPE zcl_abapgit_code_inspector + EXPORTING + iv_package = iv_package. + + INSERT ls_code_inspector INTO TABLE gt_code_inspector ASSIGNING . + ENDIF. + + ri_code_inspector = -instance. + + ENDMETHOD. + METHOD run_inspection. + + io_inspection->run( + EXPORTING + p_howtorun = mv_run_mode + EXCEPTIONS + invalid_check_version = 1 + OTHERS = 2 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Code inspector run failed. Subrc = { sy-subrc }| ). + ENDIF. + + io_inspection->plain_list( IMPORTING p_list = rt_list ). + + filter_inspection( CHANGING ct_list = rt_list ). + + SORT rt_list BY objtype objname test code sobjtype sobjname line col. + + DELETE ADJACENT DUPLICATES FROM rt_list. + + ENDMETHOD. + METHOD set_code_inspector. + + DATA ls_code_inspector LIKE LINE OF gt_code_inspector. + + FIELD-SYMBOLS LIKE LINE OF gt_code_inspector. + + READ TABLE gt_code_inspector ASSIGNING WITH TABLE KEY package = iv_package. + IF sy-subrc <> 0. + ls_code_inspector-package = iv_package. + + INSERT ls_code_inspector INTO TABLE gt_code_inspector ASSIGNING . + ENDIF. + + -instance = ii_code_inspector. + + ENDMETHOD. + METHOD skip_object. + + DATA ls_program_type TYPE subc. + + CASE is_obj-objtype. + WHEN 'PROG'. + + SELECT SINGLE subc + INTO ls_program_type + FROM trdir + WHERE name = is_obj-objname. + + rv_skip = boolc( ls_program_type = 'I' ). " Include program. + + WHEN OTHERS. + rv_skip = abap_false. + + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_code_inspector~get_summary. + rv_summary = mv_summary. + ENDMETHOD. + METHOD zif_abapgit_code_inspector~is_successful. + + rv_success = mv_success. + + ENDMETHOD. + METHOD zif_abapgit_code_inspector~list_global_variants. + + SELECT scichkv_hd~checkvname AS name + scichkv_tx~text AS description + INTO TABLE rt_list + FROM scichkv_hd + LEFT OUTER JOIN scichkv_tx + ON scichkv_hd~checkvid = scichkv_tx~checkvid + AND scichkv_hd~ciuser = scichkv_tx~ciuser + AND scichkv_tx~language = sy-langu + WHERE scichkv_hd~ciuser = space + ORDER BY name. + + ENDMETHOD. + METHOD zif_abapgit_code_inspector~run. + + DATA: lo_set TYPE REF TO cl_ci_objectset, + lo_variant TYPE REF TO cl_ci_checkvariant, + lv_count TYPE i, + lt_list TYPE scit_alvlist, + ls_list LIKE LINE OF lt_list, + ls_result LIKE LINE OF rt_list, + lo_timer TYPE REF TO zcl_abapgit_timer, + lx_error TYPE REF TO zcx_abapgit_exception. + + TRY. + lo_set = create_objectset( ). + + lv_count = lines( lo_set->iobjlst-objects ). + IF lv_count = 0. + " no objects, nothing to check + RETURN. + ENDIF. + + lo_timer = zcl_abapgit_timer=>create( iv_count = lv_count )->start( ). + + lo_variant = create_variant( iv_variant ). + + mo_inspection = create_inspection( + io_set = lo_set + io_variant = lo_variant ). + + lt_list = run_inspection( mo_inspection ). + + cleanup( lo_set ). + + LOOP AT lt_list INTO ls_list. + MOVE-CORRESPONDING ls_list TO ls_result. + INSERT ls_result INTO TABLE rt_list. + ENDLOOP. + + IF iv_save = abap_true. + READ TABLE rt_list TRANSPORTING NO FIELDS WITH KEY kind = 'E'. + mv_success = boolc( sy-subrc <> 0 ). + ENDIF. + + CATCH zcx_abapgit_exception INTO lx_error. + + " ensure cleanup + cleanup( lo_set ). + zcx_abapgit_exception=>raise_with_text( lx_error ). + + ENDTRY. + + mv_summary = lo_timer->end( ). + + ENDMETHOD. + METHOD zif_abapgit_code_inspector~validate_check_variant. + + cl_ci_checkvariant=>get_ref( + EXPORTING + p_user = '' + p_name = iv_check_variant_name + EXCEPTIONS + chkv_not_exists = 1 + missing_parameter = 2 + OTHERS = 3 ). + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |No valid check variant { iv_check_variant_name }| ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_url IMPLEMENTATION. + METHOD host. + + regex( EXPORTING iv_url = iv_url + IMPORTING ev_host = rv_host ). + + ENDMETHOD. + METHOD is_abapgit_repo. + + IF iv_url CS 'github.com' AND ( iv_url CP '*/abapGit' OR iv_url CP '*/abapGit.git' ). + rv_abapgit = abap_true. + ENDIF. + + ENDMETHOD. + METHOD name. + + DATA: lv_path TYPE string. + + TRY. + regex( EXPORTING iv_url = iv_url + IMPORTING ev_name = rv_name + ev_path = lv_path ). + + IF rv_name IS INITIAL. + FIND REGEX '([\w-]+)/$' IN lv_path SUBMATCHES rv_name. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Malformed URL' ). + ENDIF. + ENDIF. + + CATCH zcx_abapgit_exception. + IF iv_validate = abap_true. + zcx_abapgit_exception=>raise( 'Malformed URL' ). + ELSE. + rv_name = 'URL error (fix repo with "Advanced > Change Remote")'. + ENDIF. + ENDTRY. + + ENDMETHOD. + METHOD path_name. + + DATA: lv_host TYPE string ##NEEDED. + + FIND REGEX '(.*://[^/]*)(.*)' IN iv_url + SUBMATCHES lv_host rv_path_name. + + ENDMETHOD. + METHOD regex. + + FIND REGEX '^(https?://[^/]*)(.*/)(.*)\.git$' IN iv_url + SUBMATCHES ev_host ev_path ev_name. + IF sy-subrc <> 0. + FIND REGEX '^(https?://[^/]*)(.*/)(.*)$' IN iv_url + SUBMATCHES ev_host ev_path ev_name. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Malformed URL' ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD url_address. + + DATA: + lv_host TYPE string, + lv_path TYPE string, + lv_name TYPE string, + lv_len TYPE i. + + regex( EXPORTING iv_url = iv_url + IMPORTING ev_host = lv_host + ev_path = lv_path + ev_name = lv_name ). + + IF lv_path IS INITIAL AND lv_name IS INITIAL. + zcx_abapgit_exception=>raise( 'Malformed URL' ). + ELSEIF lv_name IS INITIAL. + lv_len = strlen( lv_path ) - 1. + IF lv_path+lv_len(1) = '/'. + lv_path = lv_path(lv_len). + ENDIF. + ENDIF. + + rv_adress = |{ lv_host }{ lv_path }{ lv_name }|. + + ENDMETHOD. + METHOD validate. + + name( iv_url = iv_url + iv_validate = abap_true ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_PROXY_CONFIG IMPLEMENTATION. + METHOD bypass_proxy. + + DATA lt_proxy_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url. + + lt_proxy_bypass = mo_settings->get_proxy_bypass( ). + + IF lt_proxy_bypass IS NOT INITIAL + AND iv_repo_url IN lt_proxy_bypass. + rv_bypass_proxy = abap_true. + ENDIF. + + ENDMETHOD. + METHOD constructor. + + mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + + mi_exit = zcl_abapgit_exit=>get_instance( ). + + ENDMETHOD. + METHOD get_proxy_authentication. + + IF bypass_proxy( iv_repo_url ) = abap_false. + rv_auth = mo_settings->get_proxy_authentication( ). + ENDIF. + + mi_exit->change_proxy_authentication( + EXPORTING + iv_repo_url = iv_repo_url + CHANGING + cv_proxy_authentication = rv_auth ). + + ENDMETHOD. + METHOD get_proxy_port. + + IF bypass_proxy( iv_repo_url ) = abap_false. + rv_port = mo_settings->get_proxy_port( ). + ENDIF. + + mi_exit->change_proxy_port( + EXPORTING + iv_repo_url = iv_repo_url + CHANGING + cv_proxy_port = rv_port ). + + CONDENSE rv_port. + + ENDMETHOD. + METHOD get_proxy_url. + + IF bypass_proxy( iv_repo_url ) = abap_false. + rv_proxy_url = mo_settings->get_proxy_url( ). + ENDIF. + + mi_exit->change_proxy_url( + EXPORTING + iv_repo_url = iv_repo_url + CHANGING + cv_proxy_url = rv_proxy_url ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_PROXY_AUTH IMPLEMENTATION. + METHOD enter. + + zcl_abapgit_password_dialog=>popup( + EXPORTING + iv_repo_url = 'Proxy Authentication' + CHANGING + cv_user = gv_username + cv_pass = gv_password ). + + IF gv_username IS INITIAL OR gv_password IS INITIAL. + zcx_abapgit_exception=>raise( 'Proxy auth failed' ). + ENDIF. + + ENDMETHOD. + METHOD run. + + IF gv_username IS INITIAL OR gv_password IS INITIAL. + enter( ). + ENDIF. + + ii_client->authenticate( + proxy_authentication = abap_true + username = gv_username + password = gv_password ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_login_manager IMPLEMENTATION. + METHOD append. + + FIELD-SYMBOLS: LIKE LINE OF gt_auth. + + READ TABLE gt_auth WITH KEY uri = zcl_abapgit_url=>host( iv_uri ) + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO gt_auth ASSIGNING . + -uri = zcl_abapgit_url=>host( iv_uri ). + -authorization = iv_auth. + ENDIF. + + ENDMETHOD. + METHOD clear. + + CLEAR gt_auth. + + ENDMETHOD. + METHOD get. + + DATA ls_auth LIKE LINE OF gt_auth. + + READ TABLE gt_auth INTO ls_auth WITH KEY uri = zcl_abapgit_url=>host( iv_uri ). + IF sy-subrc = 0. + rv_auth = ls_auth-authorization. + ENDIF. + + ENDMETHOD. + METHOD load. + + DATA ls_auth LIKE LINE OF gt_auth. + + READ TABLE gt_auth INTO ls_auth WITH KEY uri = zcl_abapgit_url=>host( iv_uri ). + IF sy-subrc = 0. + rv_authorization = ls_auth-authorization. + ENDIF. + + ENDMETHOD. + METHOD save. + + IF NOT iv_authorization IS INITIAL. + append( iv_uri = iv_uri + iv_auth = iv_authorization ). + ENDIF. + + ENDMETHOD. + METHOD set_basic. + + DATA: lv_concat TYPE string. + + ASSERT NOT iv_uri IS INITIAL. + + IF iv_username IS INITIAL OR iv_password IS INITIAL. + RETURN. + ENDIF. + + CONCATENATE iv_username ':' iv_password INTO lv_concat. + + rv_auth = cl_http_utility=>encode_base64( lv_concat ). + + CONCATENATE 'Basic' rv_auth INTO rv_auth SEPARATED BY space. + + append( iv_uri = iv_uri + iv_auth = rv_auth ). + + ENDMETHOD. + METHOD set_bearer. + + ASSERT NOT iv_uri IS INITIAL. + + IF iv_token IS INITIAL. + RETURN. + ENDIF. + + CONCATENATE 'Bearer' iv_token INTO rv_auth SEPARATED BY space. + + append( iv_uri = iv_uri + iv_auth = rv_auth ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_HTTP_DIGEST IMPLEMENTATION. + METHOD constructor. + + parse( ii_client ). + + mv_ha1 = md5( |{ iv_username }:{ mv_realm }:{ iv_password }| ). + + mv_username = iv_username. + + ENDMETHOD. + METHOD hash. + + DATA: lv_ha2 TYPE string. + lv_ha2 = md5( |{ iv_method }:{ iv_uri }| ). + + ASSERT NOT iv_cnonse IS INITIAL. + + rv_response = md5( |{ mv_ha1 }:{ iv_nonce }:{ gv_nc }:{ iv_cnonse }:{ iv_qop }:{ lv_ha2 }| ). + + ENDMETHOD. + METHOD md5. + + DATA lv_xstr TYPE xstring. + DATA lv_hash TYPE xstring. + DATA lv_empty TYPE xstring. + + lv_xstr = zcl_abapgit_convert=>string_to_xstring_utf8( iv_data ). + + TRY. + cl_abap_hmac=>calculate_hmac_for_raw( + EXPORTING + if_algorithm = 'MD5' + if_key = lv_empty + if_data = lv_xstr + IMPORTING + ef_hmacxstring = lv_hash ). + CATCH cx_abap_message_digest. + zcx_abapgit_exception=>raise( 'error calculating md5' ). + ENDTRY. + + rv_hash = lv_hash. + TRANSLATE rv_hash TO LOWER CASE. + + ENDMETHOD. + METHOD parse. + + DATA: lv_value TYPE string. + lv_value = ii_client->response->get_header_field( 'www-authenticate' ). + + FIND REGEX 'realm="([\w ]+)"' IN lv_value SUBMATCHES mv_realm. + FIND REGEX 'qop="(\w+)"' IN lv_value SUBMATCHES mv_qop. + FIND REGEX 'nonce="([\w=/+\$]+)"' IN lv_value SUBMATCHES mv_nonce. + + ENDMETHOD. + METHOD run. + + DATA: lv_response TYPE string, + lv_method TYPE string, + lv_cnonce TYPE string, + lv_uri TYPE string, + lv_auth TYPE string. + ASSERT NOT mv_nonce IS INITIAL. + + lv_method = ii_client->request->get_header_field( '~request_method' ). + lv_uri = ii_client->request->get_header_field( '~request_uri' ). + + CALL FUNCTION 'GENERAL_GET_RANDOM_STRING' + EXPORTING + number_chars = 24 + IMPORTING + random_string = lv_cnonce. + + lv_response = hash( + iv_qop = mv_qop + iv_nonce = mv_nonce + iv_uri = lv_uri + iv_method = lv_method + iv_cnonse = lv_cnonce ). + +* client response + lv_auth = |Digest username="{ mv_username + }", realm="{ mv_realm + }", nonce="{ mv_nonce + }", uri="{ lv_uri + }", qop={ mv_qop + }, nc={ gv_nc + }, cnonce="{ lv_cnonce + }", response="{ lv_response }"|. + + ii_client->request->set_header_field( + name = 'Authorization' + value = lv_auth ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_http_client IMPLEMENTATION. + METHOD check_http_200. + + DATA: lv_code TYPE i, + lv_text TYPE string. + + mi_client->response->get_status( IMPORTING code = lv_code ). + CASE lv_code. + WHEN 200. + RETURN. " Success, OK + WHEN 302. + zcx_abapgit_exception=>raise( 'Resource access temporarily redirected (HTTP 302). Check the URL' ). + WHEN 401. + zcx_abapgit_exception=>raise( 'Unauthorized access to resource (HTTP 401). Check your credentials' ). + WHEN 403. + zcx_abapgit_exception=>raise( 'Access to resource forbidden (HTTP 403)' ). + WHEN 404. + zcx_abapgit_exception=>raise( 'Resource not found (HTTP 404). Check the URL' ). + WHEN 407. + zcx_abapgit_exception=>raise( 'Proxy authentication required (HTTP 407). Check your credentials' ). + WHEN 408. + zcx_abapgit_exception=>raise( 'Request timeout (HTTP 408)' ). + WHEN 415. + zcx_abapgit_exception=>raise( 'Unsupported media type (HTTP 415)' ). + WHEN 422. + zcx_abapgit_exception=>raise( 'Unprocessable entity (HTTP 422). Check, if URL has to end with ".git"' ). + WHEN 426. + zcx_abapgit_exception=>raise( + iv_text = 'Upgrade Required (HTTP 426)' + iv_longtext = |The git server requires a different HTTP-protocol than which is sent. | + && |abapGit uses HTTP/1.1 as default. | + && |See more details in the abapGit online documentation.| ). + WHEN OTHERS. + lv_text = mi_client->response->get_cdata( ). + zcx_abapgit_exception=>raise( |(HTTP { lv_code }) { lv_text }| ). + ENDCASE. + + ENDMETHOD. + METHOD check_smart_response. + + DATA: lv_content_type TYPE string. + DATA: lv_data TYPE string. + + IF iv_expected_content_type IS NOT INITIAL. + lv_content_type = mi_client->response->get_content_type( ). + IF lv_content_type <> iv_expected_content_type. + zcx_abapgit_exception=>raise( 'Wrong Content-Type sent by server - no fallback to the dumb protocol!' ). + ENDIF. + ENDIF. + + IF iv_content_regex IS NOT INITIAL. + lv_data = mi_client->response->get_cdata( ). + FIND REGEX iv_content_regex IN lv_data. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Wrong Content sent by server' ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD close. + mi_client->close( ). + ENDMETHOD. + METHOD constructor. + mi_client = ii_client. + ENDMETHOD. + METHOD get_cdata. + rv_value = mi_client->response->get_cdata( ). + ENDMETHOD. + METHOD send_receive. + + DATA: lv_text TYPE string, + lv_code TYPE i, + lv_message TYPE string. + + mi_client->send( + EXCEPTIONS + http_communication_failure = 1 + http_invalid_state = 2 + http_processing_failed = 3 + http_invalid_timeout = 4 + OTHERS = 5 ). + + IF sy-subrc = 0. + mi_client->receive( + EXCEPTIONS + http_communication_failure = 1 + http_invalid_state = 2 + http_processing_failed = 3 + OTHERS = 4 ). + ENDIF. + + IF sy-subrc <> 0. + " in case of HTTP_COMMUNICATION_FAILURE + " make sure: + " a) SSL is setup properly in STRUST + " b) no firewalls + " check trace file in transaction SMICM + + mi_client->get_last_error( + IMPORTING + code = lv_code + message = lv_message ). + + lv_text = |HTTP error { lv_code } occurred: { lv_message }|. + + zcx_abapgit_exception=>raise( lv_text ). + ENDIF. + + ENDMETHOD. + METHOD send_receive_close. + +* do not use set_cdata as it modifies the Content-Type header field + mi_client->request->set_data( iv_data ). + send_receive( ). + check_http_200( ). + rv_data = mi_client->response->get_data( ). + mi_client->close( ). + + ENDMETHOD. + METHOD set_digest. + mo_digest = io_digest. + ENDMETHOD. + METHOD set_header. + mi_client->request->set_header_field( + name = iv_key + value = iv_value ). + ENDMETHOD. + METHOD set_headers. + + DATA: lv_value TYPE string. + mi_client->request->set_header_field( + name = '~request_method' + value = 'POST' ). + + lv_value = zcl_abapgit_url=>path_name( iv_url ) && + '/git-' && + iv_service && + '-pack'. + mi_client->request->set_header_field( + name = '~request_uri' + value = lv_value ). + + lv_value = 'application/x-git-' + && iv_service && '-pack-request'. + mi_client->request->set_header_field( + name = 'Content-Type' + value = lv_value ). + + lv_value = 'application/x-git-' + && iv_service && '-pack-result'. + mi_client->request->set_header_field( + name = 'Accept' + value = lv_value ). + + IF mo_digest IS BOUND. + mo_digest->run( mi_client ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlkOaymxFRlCWtlTOYvbNmJsakp DEFINITION DEFERRED. +* renamed: zcl_abapgit_http_agent :: lcl_http_response +CLASS kHGwlkOaymxFRlCWtlTOYvbNmJsakp DEFINITION FINAL. + PUBLIC SECTION. + + INTERFACES zif_abapgit_http_response. + + CLASS-METHODS create + IMPORTING + ii_client TYPE REF TO if_http_client + RETURNING + VALUE(ri_response) TYPE REF TO zif_abapgit_http_response. + + PRIVATE SECTION. + DATA mi_client TYPE REF TO if_http_client. + DATA mi_response TYPE REF TO if_http_response. +ENDCLASS. + +CLASS kHGwlkOaymxFRlCWtlTOYvbNmJsakp IMPLEMENTATION. + + METHOD create. + DATA lo_response TYPE REF TO kHGwlkOaymxFRlCWtlTOYvbNmJsakp. + CREATE OBJECT lo_response. + lo_response->mi_client = ii_client. + lo_response->mi_response = ii_client->response. + ri_response ?= lo_response. + ENDMETHOD. + + METHOD zif_abapgit_http_response~close. + mi_client->close( ). + ENDMETHOD. + + METHOD zif_abapgit_http_response~is_ok. + DATA lv_code TYPE i. + lv_code = zif_abapgit_http_response~code( ). + rv_yes = boolc( lv_code >= 200 AND lv_code < 300 ). + ENDMETHOD. + + METHOD zif_abapgit_http_response~data. + rv_data = mi_response->get_data( ). + ENDMETHOD. + + METHOD zif_abapgit_http_response~cdata. + rv_data = mi_response->get_cdata( ). + ENDMETHOD. + + METHOD zif_abapgit_http_response~code. + DATA lv_msg TYPE string ##NEEDED. + mi_response->get_status( + IMPORTING + reason = lv_msg " for debug + code = rv_code ). + ENDMETHOD. + + METHOD zif_abapgit_http_response~json. + + ri_json = zcl_abapgit_ajson=>parse( zif_abapgit_http_response~cdata( ) ). + + ENDMETHOD. + + METHOD zif_abapgit_http_response~error. + rv_message = mi_response->get_cdata( ). + ENDMETHOD. + + METHOD zif_abapgit_http_response~headers. + + DATA lt_headers TYPE tihttpnvp. + FIELD-SYMBOLS LIKE LINE OF lt_headers. + + CREATE OBJECT ro_headers. + + mi_response->get_header_fields( CHANGING fields = lt_headers ). + LOOP AT lt_headers ASSIGNING . + ro_headers->set( + iv_key = -name + iv_val = -value ). + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +CLASS ZCL_ABAPGIT_HTTP_AGENT IMPLEMENTATION. + METHOD attach_payload. + + DATA lo_type TYPE REF TO cl_abap_typedescr. + lo_type = cl_abap_typedescr=>describe_by_data( iv_payload ). + + IF lo_type->type_kind = cl_abap_typedescr=>typekind_xstring. + ii_request->set_data( iv_payload ). + + ELSEIF lo_type->type_kind = cl_abap_typedescr=>typekind_string. + ii_request->set_cdata( iv_payload ). + + ELSE. + zcx_abapgit_exception=>raise( |Unexpected payload type { lo_type->absolute_name }| ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + CREATE OBJECT mo_global_headers. + + ENDMETHOD. + METHOD create. + + CREATE OBJECT ri_instance TYPE zcl_abapgit_http_agent. + + ENDMETHOD. + METHOD zif_abapgit_http_agent~global_headers. + + ro_global_headers = mo_global_headers. + + ENDMETHOD. + METHOD zif_abapgit_http_agent~request. + + DATA li_client TYPE REF TO if_http_client. + DATA lo_proxy_configuration TYPE REF TO zcl_abapgit_proxy_config. + DATA lv_code TYPE i. + DATA lv_message TYPE string. + FIELD-SYMBOLS LIKE LINE OF io_query->mt_entries. + + CREATE OBJECT lo_proxy_configuration. + + cl_http_client=>create_by_url( + EXPORTING + url = iv_url + ssl_id = zcl_abapgit_exit=>get_instance( )->get_ssl_id( ) + proxy_host = lo_proxy_configuration->get_proxy_url( iv_url ) + proxy_service = lo_proxy_configuration->get_proxy_port( iv_url ) + IMPORTING + client = li_client ). + + li_client->request->set_version( if_http_request=>co_protocol_version_1_1 ). + li_client->request->set_method( iv_method ). + + IF io_query IS BOUND. + LOOP AT io_query->mt_entries ASSIGNING . + li_client->request->set_form_field( + name = -k + value = -v ). + ENDLOOP. + ENDIF. + + LOOP AT mo_global_headers->mt_entries ASSIGNING . + li_client->request->set_header_field( + name = to_lower( -k ) + value = -v ). + ENDLOOP. + + IF io_headers IS BOUND. + LOOP AT io_headers->mt_entries ASSIGNING . + li_client->request->set_header_field( + name = to_lower( -k ) + value = -v ). + ENDLOOP. + ENDIF. + + IF iv_method = zif_abapgit_http_agent=>c_methods-post + OR iv_method = zif_abapgit_http_agent=>c_methods-put + OR iv_method = zif_abapgit_http_agent=>c_methods-patch. + attach_payload( + ii_request = li_client->request + iv_payload = iv_payload ). + ENDIF. + + li_client->send( + EXCEPTIONS + http_communication_failure = 1 + http_invalid_state = 2 + http_processing_failed = 3 + http_invalid_timeout = 4 + OTHERS = 5 ). + IF sy-subrc = 0. + li_client->receive( + EXCEPTIONS + http_communication_failure = 1 + http_invalid_state = 2 + http_processing_failed = 3 + OTHERS = 4 ). + ENDIF. + + IF sy-subrc <> 0. + li_client->get_last_error( + IMPORTING + code = lv_code + message = lv_message ). + zcx_abapgit_exception=>raise( |HTTP error: [{ lv_code }] { lv_message }| ). + ENDIF. + + ri_response = kHGwlkOaymxFRlCWtlTOYvbNmJsakp=>create( li_client ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_http IMPLEMENTATION. + METHOD acquire_login_details. + + DATA: lv_default_user TYPE string, + lv_user TYPE string, + lv_pass TYPE string, + lo_digest TYPE REF TO zcl_abapgit_http_digest. + lv_default_user = zcl_abapgit_persist_factory=>get_user( )->get_repo_login( iv_url ). + lv_user = lv_default_user. + + zcl_abapgit_password_dialog=>popup( + EXPORTING + iv_repo_url = iv_url + CHANGING + cv_user = lv_user + cv_pass = lv_pass ). + + IF lv_user IS INITIAL. + zcx_abapgit_exception=>raise( 'Unauthorized access. Check your credentials' ). + ENDIF. + + IF lv_user <> lv_default_user. + zcl_abapgit_persist_factory=>get_user( )->set_repo_login( + iv_url = iv_url + iv_login = lv_user ). + ENDIF. + + rv_scheme = ii_client->response->get_header_field( 'www-authenticate' ). + FIND REGEX '^(\w+)' IN rv_scheme SUBMATCHES rv_scheme. + + CASE rv_scheme. + WHEN c_scheme-digest. +* https://en.wikipedia.org/wiki/Digest_access_authentication +* e.g. used by https://www.gerritcodereview.com/ + CREATE OBJECT lo_digest + EXPORTING + ii_client = ii_client + iv_username = lv_user + iv_password = lv_pass. + lo_digest->run( ii_client ). + io_client->set_digest( lo_digest ). + WHEN OTHERS. +* https://en.wikipedia.org/wiki/Basic_access_authentication + ii_client->authenticate( + username = lv_user + password = lv_pass ). + ENDCASE. + + ENDMETHOD. + METHOD check_auth_requested. + + DATA: lv_code TYPE i. + + ii_client->response->get_status( IMPORTING code = lv_code ). + IF lv_code = 401. + rv_auth_requested = abap_true. + ENDIF. + + ENDMETHOD. + METHOD check_connection. + " Check if a connection from this system to the git host is possible + " This will validate the general HTTP/HTTPS/SSL configuration and certificates + get_http_client( iv_url ). + ENDMETHOD. + METHOD create_by_url. + + DATA: lv_scheme TYPE string, + lv_authorization TYPE string, + li_client TYPE REF TO if_http_client, + ls_header LIKE LINE OF it_headers. + + li_client = get_http_client( iv_url ). + + CREATE OBJECT ro_client + EXPORTING + ii_client = li_client. + + IF is_local_system( iv_url ) = abap_true. + li_client->send_sap_logon_ticket( ). + ENDIF. + + li_client->request->set_cdata( '' ). + li_client->request->set_header_field( + name = '~request_method' + value = 'GET' ). + li_client->request->set_header_field( + name = 'user-agent' + value = get_agent( ) ). + + LOOP AT it_headers INTO ls_header. + li_client->request->set_header_field( + name = ls_header-key + value = ls_header-value ). + ENDLOOP. + + " Disable internal auth dialog (due to its unclarity) + li_client->propertytype_logon_popup = if_http_client=>co_disabled. + + lv_authorization = zcl_abapgit_login_manager=>load( iv_url ). + IF lv_authorization IS NOT INITIAL. + li_client->request->set_header_field( + name = 'authorization' + value = lv_authorization ). + li_client->propertytype_logon_popup = li_client->co_disabled. + ENDIF. + + li_client->request->set_version( if_http_request=>co_protocol_version_1_1 ). + + zcl_abapgit_exit=>get_instance( )->http_client( + iv_url = iv_url + ii_client = li_client ). + + ro_client->send_receive( ). + IF check_auth_requested( li_client ) = abap_true. + lv_scheme = acquire_login_details( ii_client = li_client + io_client = ro_client + iv_url = iv_url ). + ro_client->send_receive( ). + ENDIF. + ro_client->check_http_200( ). + + IF lv_scheme <> c_scheme-digest. + zcl_abapgit_login_manager=>save( + iv_uri = iv_url + iv_authorization = li_client->request->get_header_field( 'authorization' ) ). + ENDIF. + + ENDMETHOD. + METHOD get_agent. + +* bitbucket require agent prefix = "git/" +* also see https://github.com/abapGit/abapGit/issues/1432 + rv_agent = |git/2.0 (abapGit { zif_abapgit_version=>c_abap_version })|. + + ENDMETHOD. + METHOD get_connection_longtext. + + CONSTANTS lc_docs TYPE string VALUE 'https://docs.abapgit.org/user-guide/setup/ssl-setup.html'. + + DATA lv_proxy TYPE string. + + IF iv_proxy_host IS NOT INITIAL. + lv_proxy = | via proxy { iv_proxy_host }:{ iv_proxy_service }|. + ENDIF. + + rv_longtext = |abapGit is trying to connect to { iv_host } | + && |using SSL certificates under { iv_ssl_id }{ lv_proxy }. | + && |Check system parameters (transaction | + && zcl_abapgit_html=>create( )->a( + iv_txt = 'RZ10' + iv_act = |{ zif_abapgit_definitions=>c_action-jump_transaction }?transaction=RZ10| + iv_class = 'no-pad' ) + && |), SSL setup (transaction | + && zcl_abapgit_html=>create( )->a( + iv_txt = 'STRUST' + iv_act = |{ zif_abapgit_definitions=>c_action-jump_transaction }?transaction=STRUST| + iv_class = 'no-pad' ) + && |), Internet connection monitor (transaction | + && zcl_abapgit_html=>create( )->a( + iv_txt = 'SMICM' + iv_act = |{ zif_abapgit_definitions=>c_action-jump_transaction }?transaction=SMICM| + iv_class = 'no-pad' ) + && |)|. + + IF lv_proxy IS NOT INITIAL. + rv_longtext = rv_longtext + && |, and proxy configuration (| + && zcl_abapgit_html=>create( )->a( + iv_txt = 'global settings' + iv_act = |{ zif_abapgit_definitions=>c_action-go_settings }| + iv_class = 'no-pad' ) + && |)|. + ENDIF. + + rv_longtext = rv_longtext + && |. It's recommended to get your SAP Basis and network teams involved. | + && |For more information and troubleshooting, see the | + && zcl_abapgit_html=>create( )->a( + iv_txt = 'abapGit documentation' + iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ lc_docs }| + iv_class = 'no-pad' ) + && |.|. + + ENDMETHOD. + METHOD get_http_client. + + DATA: + lv_error TYPE string, + lv_longtext TYPE string, + lv_host TYPE string, + lv_ssl_id TYPE ssfapplssl, + lv_proxy_host TYPE string, + lv_proxy_service TYPE string, + lo_proxy_configuration TYPE REF TO zcl_abapgit_proxy_config. + + CREATE OBJECT lo_proxy_configuration. + + ri_client = zcl_abapgit_exit=>get_instance( )->create_http_client( iv_url ). + + IF ri_client IS INITIAL. + + lv_host = zcl_abapgit_url=>host( iv_url ). + lv_ssl_id = zcl_abapgit_exit=>get_instance( )->get_ssl_id( ). + lv_proxy_host = lo_proxy_configuration->get_proxy_url( iv_url ). + lv_proxy_service = lo_proxy_configuration->get_proxy_port( iv_url ). + + lv_longtext = get_connection_longtext( + iv_host = lv_host + iv_ssl_id = lv_ssl_id + iv_proxy_host = lv_proxy_host + iv_proxy_service = lv_proxy_service ). + + cl_http_client=>create_by_url( + EXPORTING + url = lv_host + ssl_id = lv_ssl_id + proxy_host = lv_proxy_host + proxy_service = lv_proxy_service + IMPORTING + client = ri_client + EXCEPTIONS + argument_not_found = 1 + plugin_not_active = 2 + internal_error = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + CASE sy-subrc. + WHEN 1. + lv_error = 'ARGUMENT_NOT_FOUND'. + WHEN 2. + lv_error = 'PLUGIN_NOT_ACTIVE'. + WHEN 3. + lv_error = 'INTERNAL_ERROR'. + WHEN OTHERS. + lv_error = |OTHER_ERROR_{ sy-subrc }|. + ENDCASE. + zcx_abapgit_exception=>raise( + iv_text = |Error { lv_error } creating HTTP connection. Check the configuration| + iv_longtext = lv_longtext ). + ENDIF. + + ENDIF. + + IF lo_proxy_configuration->get_proxy_authentication( iv_url ) = abap_true. + zcl_abapgit_proxy_auth=>run( ri_client ). + ENDIF. + + ENDMETHOD. + METHOD is_local_system. + + DATA: lv_host TYPE string, + lt_list TYPE zif_abapgit_definitions=>ty_string_tt, + li_exit TYPE REF TO zif_abapgit_exit. + cl_http_server=>get_location( IMPORTING host = lv_host ). + APPEND lv_host TO lt_list. + + APPEND 'localhost' TO lt_list. + + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->change_local_host( CHANGING ct_hosts = lt_list ). + + FIND REGEX 'https?://([^/^:]*)' IN iv_url SUBMATCHES lv_host. + + READ TABLE lt_list WITH KEY table_line = lv_host TRANSPORTING NO FIELDS. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_pr_enumerator IMPLEMENTATION. + METHOD constructor. + + mv_repo_url = iv_url. + TRY. + mi_enum_provider = create_provider( mv_repo_url ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD create_initial_branch. + + IF mi_enum_provider IS NOT BOUND. + RETURN. + ENDIF. + + rv_branch_name = mi_enum_provider->create_initial_branch( + iv_readme = iv_readme + iv_branch_name = iv_branch_name ). + + ENDMETHOD. + METHOD create_provider. + + DATA li_agent TYPE REF TO zif_abapgit_http_agent. + DATA lv_user TYPE string. + DATA lv_repo TYPE string. + + li_agent = zcl_abapgit_http_agent=>create( ). + + FIND ALL OCCURRENCES OF REGEX 'github\.com\/([^\/]+)\/([^\/]+)' + IN iv_repo_url + SUBMATCHES lv_user lv_repo. + IF sy-subrc = 0. + lv_repo = replace( + val = lv_repo + regex = '\.git$' + with = '' ). + CREATE OBJECT ri_provider TYPE zcl_abapgit_pr_enum_github + EXPORTING + iv_user_and_repo = |{ lv_user }/{ lv_repo }| + ii_http_agent = li_agent. + ENDIF. + +* used in integration testing, see /test/ folder + FIND ALL OCCURRENCES OF REGEX 'localhost:3050\/([^\/]+)\/([^\/]+)' + IN iv_repo_url + SUBMATCHES lv_user lv_repo. + IF sy-subrc = 0. + CREATE OBJECT ri_provider TYPE zcl_abapgit_pr_enum_gitea + EXPORTING + iv_user_and_repo = |{ lv_user }/{ lv_repo }| + ii_http_agent = li_agent. + ENDIF. + + " TODO somewhen more providers + + IF ri_provider IS NOT BOUND. + zcx_abapgit_exception=>raise( |PR enumeration is not supported for { iv_repo_url }| ). + ENDIF. + + ENDMETHOD. + METHOD create_repository. + + IF mi_enum_provider IS NOT BOUND. + RETURN. + ENDIF. + + mi_enum_provider->create_repository( + iv_description = iv_description + iv_is_org = iv_is_org + iv_private = iv_private + iv_auto_init = iv_auto_init ). + + ENDMETHOD. + METHOD get_pulls. + + IF mi_enum_provider IS NOT BOUND. + RETURN. + ENDIF. + + rt_pulls = mi_enum_provider->list_pull_requests( ). + + ENDMETHOD. + METHOD new. + CREATE OBJECT ro_instance EXPORTING iv_url = iv_url. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_pr_enum_github IMPLEMENTATION. + METHOD clean_url. + rv_url = replace( + val = iv_url + regex = '\{.*\}$' + with = '' ). + ENDMETHOD. + METHOD constructor. + + DATA lv_search TYPE string. + + mv_user_and_repo = iv_user_and_repo. + mv_repo_url = |https://api.github.com/repos/{ iv_user_and_repo }|. + mi_http_agent = ii_http_agent. + mi_http_agent->global_headers( )->set( + iv_key = 'Accept' + iv_val = 'application/vnd.github.v3+json' ). + + " https://docs.github.com/en/rest/about-the-rest-api/api-versions + mi_http_agent->global_headers( )->set( + iv_key = 'X-GitHub-Api-Version' + iv_val = '2022-11-28' ). + + IF zcl_abapgit_login_manager=>get( mv_repo_url ) IS NOT INITIAL. + mi_http_agent->global_headers( )->set( + iv_key = 'Authorization' + iv_val = zcl_abapgit_login_manager=>get( mv_repo_url ) ). + ELSE. +* fallback, try searching for the git credentials + lv_search = mv_repo_url. + REPLACE FIRST OCCURRENCE OF 'api.github.com/repos' IN lv_search WITH 'github.com'. + IF zcl_abapgit_login_manager=>get( lv_search ) IS NOT INITIAL. + mi_http_agent->global_headers( )->set( + iv_key = 'Authorization' + iv_val = zcl_abapgit_login_manager=>get( lv_search ) ). + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD convert_list. + + DATA lt_items TYPE string_table. + DATA lv_i TYPE string. + FIELD-SYMBOLS LIKE LINE OF rt_pulls. + + lt_items = ii_json->members( '/' ). + + LOOP AT lt_items INTO lv_i. + APPEND INITIAL LINE TO rt_pulls ASSIGNING . + -base_url = ii_json->get( |/{ lv_i }/base/repo/clone_url| ). + -number = ii_json->get( |/{ lv_i }/number| ). + -title = ii_json->get( |/{ lv_i }/title| ). + -user = ii_json->get( |/{ lv_i }/user/login| ). + -head_url = ii_json->get( |/{ lv_i }/head/repo/clone_url| ). + -head_branch = ii_json->get( |/{ lv_i }/head/ref| ). + -created_at = ii_json->get( |/{ lv_i }/created_at| ). + -draft = ii_json->get_boolean( |/{ lv_i }/draft| ). + -html_url = ii_json->get( |/{ lv_i }/html_url| ). + ENDLOOP. + + ENDMETHOD. + METHOD create_pull_request. +* https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#create-a-pull-request + + DATA lv_owner TYPE string. + DATA lv_repo TYPE string. + DATA lv_url TYPE string. + DATA lv_json TYPE string. + DATA li_response TYPE REF TO zif_abapgit_http_response. + + lv_url = mv_repo_url && '/pulls'. + SPLIT mv_user_and_repo AT '/' INTO lv_owner lv_repo. + + lv_json = |\{\n| && + | "owner": "{ lv_owner }",\n| && + | "repo": "{ lv_repo }",\n| && + | "title": "{ iv_title }",\n| && + | "head": "{ iv_head }",\n| && + | "body": "{ iv_body }",\n| && + | "maintainer_can_modify": true,\n| && + | "draft": true,\n| && + | "base": "{ iv_base }"\n| && + |\}|. + + li_response = mi_http_agent->request( + iv_url = lv_url + iv_method = zif_abapgit_http_agent=>c_methods-post + iv_payload = lv_json ). + + IF li_response->is_ok( ) = abap_false. + zcx_abapgit_exception=>raise( |Error creating pull request: { li_response->error( ) }| ). + ENDIF. + + ENDMETHOD. + METHOD fetch_repo_by_url. + + DATA li_pulls_json TYPE REF TO zif_abapgit_ajson. + DATA lv_pull_url TYPE string. + DATA li_response TYPE REF TO zif_abapgit_http_response. + DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + + li_response = mi_http_agent->request( iv_repo_url ). + + TRY. + rs_info-repo_json = li_response->json( ). + li_response->headers( ). " for debug + lv_pull_url = clean_url( rs_info-repo_json->get( '/pulls_url' ) ). + IF lv_pull_url IS INITIAL OR rs_info-repo_json->get( '/message' ) = 'Not Found'. + RETURN. + ENDIF. + li_pulls_json = mi_http_agent->request( lv_pull_url )->json( ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise_with_text( lx_ajson ). + ENDTRY. + + rs_info-pulls = convert_list( li_pulls_json ). + + ENDMETHOD. + METHOD merge_pull_request. +* https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#merge-a-pull-request + + DATA lv_url TYPE string. + DATA lv_json TYPE string. + DATA li_response TYPE REF TO zif_abapgit_http_response. + + lv_url = mv_repo_url && '/pulls/' && iv_pull_number && '/merge'. + + lv_json = |\{\n| && + | "commit_title": "Merge pull request #{ iv_pull_number }",\n| && + | "merge_method": "squash"\n| && + |\}|. + + li_response = mi_http_agent->request( + iv_url = lv_url + iv_method = zif_abapgit_http_agent=>c_methods-put + iv_payload = lv_json ). + + IF li_response->is_ok( ) = abap_false. + zcx_abapgit_exception=>raise( |Error merging pull request: { li_response->error( ) }| ). + ENDIF. + + ENDMETHOD. + METHOD ready_for_review. +* https://docs.github.com/en/graphql/reference/mutations#markpullrequestreadyforreview +* https://gist.github.com/jeromepl/02e70f3ea4a4e8103da6f96f14eb213c + + DATA lv_url TYPE string. + DATA lv_json TYPE string. + DATA li_response TYPE REF TO zif_abapgit_http_response. + DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + DATA lv_node_id TYPE string. + + lv_url = mv_repo_url && '/pulls/' && iv_pull_number. + + li_response = mi_http_agent->request( + iv_url = lv_url + iv_method = zif_abapgit_http_agent=>c_methods-get ). + + IF li_response->is_ok( ) = abap_false. + zcx_abapgit_exception=>raise( |Error getting pull request information: { li_response->error( ) }| ). + ENDIF. + + TRY. + lv_node_id = li_response->json( )->get( |/node_id| ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise_with_text( lx_ajson ). + ENDTRY. + + lv_json = |\{"query": "mutation \{ markPullRequestReadyForReview(input: | && + |\{ pullRequestId: \\"{ lv_node_id }\\" \}) \{ pullRequest \{ id \} \} \}" \}|. + + li_response = mi_http_agent->request( + iv_url = 'https://api.github.com/graphql' + iv_method = zif_abapgit_http_agent=>c_methods-post + iv_payload = lv_json ). + + IF li_response->is_ok( ) = abap_false. + zcx_abapgit_exception=>raise( |Error setting to ready: { li_response->error( ) }| ). + ENDIF. + + ENDMETHOD. + METHOD update_pull_request_branch. +* https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#update-a-pull-request-branch + + DATA lv_url TYPE string. + DATA lv_json TYPE string. + DATA li_response TYPE REF TO zif_abapgit_http_response. + + lv_url = mv_repo_url && '/pulls/' && iv_pull_number && '/update-branch'. + + lv_json = |\{\n| && + | "expected_head_sha": "{ to_lower( iv_expected_head_sha ) }"\n| && + |\}|. + + li_response = mi_http_agent->request( + iv_url = lv_url + iv_method = zif_abapgit_http_agent=>c_methods-put + iv_payload = lv_json ). + + IF li_response->is_ok( ) = abap_false. + zcx_abapgit_exception=>raise( |Error updating pull request branch: { li_response->error( ) }| ). + ENDIF. + + ENDMETHOD. + + METHOD get_check_runs. +* https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#get-the-combined-status-for-a-specific-reference + + DATA lv_url TYPE string. + DATA li_response TYPE REF TO zif_abapgit_http_response. + DATA li_json TYPE REF TO zif_abapgit_ajson. + DATA lt_statuses TYPE string_table. + DATA ls_status TYPE ty_status. + DATA lv_item LIKE LINE OF lt_statuses. + DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + lv_url = mv_repo_url && '/commits/' && iv_ref && '/check-runs'. + + li_response = mi_http_agent->request( + iv_url = lv_url + iv_method = zif_abapgit_http_agent=>c_methods-get ). + + IF li_response->is_ok( ) = abap_false. + zcx_abapgit_exception=>raise( |Error getting check-runs for ref { iv_ref }: { li_response->error( ) }| ). + ENDIF. + + TRY. + li_json = li_response->json( ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise_with_text( lx_ajson ). + ENDTRY. + + lt_statuses = li_json->members( '/check_runs' ). + LOOP AT lt_statuses INTO lv_item. + ls_status-name = li_json->get( |/check_runs/{ lv_item }/name| ). + ls_status-status = li_json->get( |/check_runs/{ lv_item }/status| ). + ls_status-conclusion = li_json->get( |/check_runs/{ lv_item }/conclusion| ). + ls_status-title = li_json->get( |/check_runs/{ lv_item }/output/title| ). + APPEND ls_status TO rt_status. + ENDLOOP. + + ENDMETHOD. + + METHOD zif_abapgit_pr_enum_provider~create_initial_branch. +* https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#create-or-update-file-contents--parameters + + DATA lv_owner TYPE string. + DATA lv_repo TYPE string. + DATA lv_url TYPE string. + DATA lv_contents TYPE string. + DATA lv_json TYPE string. + DATA li_response TYPE REF TO zif_abapgit_http_response. + + lv_url = mv_repo_url && '/contents/README.md'. + SPLIT mv_user_and_repo AT '/' INTO lv_owner lv_repo. + + lv_contents = iv_readme. + + IF lv_contents IS INITIAL. + lv_contents = |# { to_upper( lv_repo ) }|. + ENDIF. + + lv_json = |\{\n| && + | "message": "Initial commit",\n| && + | "content": "{ cl_http_utility=>encode_base64( lv_contents ) }",\n| && + | "branch": "{ iv_branch_name }"\n| && + |\}|. + + li_response = mi_http_agent->request( + iv_url = lv_url + iv_method = zif_abapgit_http_agent=>c_methods-put + iv_payload = lv_json ). + + IF li_response->is_ok( ) = abap_false. + zcx_abapgit_exception=>raise( |Error creating initial { iv_branch_name } branch: { li_response->error( ) }| ). + ENDIF. + + rv_branch_name = iv_branch_name. + + ENDMETHOD. + METHOD zif_abapgit_pr_enum_provider~create_repository. +* https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#create-an-organization-repository + + DATA lv_owner TYPE string. + DATA lv_repo TYPE string. + DATA lv_url TYPE string. + DATA lv_private TYPE string. + DATA lv_auto_init TYPE string. + DATA lv_json TYPE string. + DATA li_response TYPE REF TO zif_abapgit_http_response. + + SPLIT mv_user_and_repo AT '/' INTO lv_owner lv_repo. + + " repo for organization or authenticated user + IF iv_is_org = abap_true. + lv_url = |https://api.github.com/orgs/{ lv_owner }/repos|. + ELSE. + lv_url = |https://api.github.com/user/repos|. + ENDIF. + + IF iv_private = abap_true. + lv_private = 'true'. + ELSE. + lv_private = 'false'. + ENDIF. + + " create an initial commit with empty README + IF iv_auto_init = abap_true. + lv_auto_init = 'true'. + ELSE. + lv_auto_init = 'false'. + ENDIF. + + lv_json = |\{\n| && + | "name": "{ lv_repo }",\n| && + | "description": "{ iv_description }",\n| && + | "private": { lv_private },\n| && + | "auto_init": { lv_auto_init }\n| && + |\}|. + + li_response = mi_http_agent->request( + iv_url = lv_url + iv_method = zif_abapgit_http_agent=>c_methods-post + iv_payload = lv_json ). + + IF li_response->is_ok( ) = abap_false. + zcx_abapgit_exception=>raise( |Error creating repository { mv_user_and_repo }: { li_response->error( ) }| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_pr_enum_provider~list_pull_requests. + + DATA lv_upstream_url TYPE string. + DATA ls_repo_info TYPE ty_info. + FIELD-SYMBOLS LIKE LINE OF ls_repo_info-pulls. + + ls_repo_info = fetch_repo_by_url( mv_repo_url ). + APPEND LINES OF ls_repo_info-pulls TO rt_pulls. + + IF ls_repo_info-repo_json->get_boolean( '/fork' ) = abap_true. + lv_upstream_url = ls_repo_info-repo_json->get( '/source/url' ). " parent ? + ls_repo_info = fetch_repo_by_url( lv_upstream_url ). + LOOP AT ls_repo_info-pulls ASSIGNING . + -is_for_upstream = abap_true. + APPEND TO rt_pulls. + ENDLOOP. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_pr_enum_gitea IMPLEMENTATION. + METHOD clean_url. + rv_url = replace( + val = iv_url + regex = '\{.*\}$' + with = '' ). + ENDMETHOD. + METHOD constructor. +* https://docs.gitea.com/api/1.23/#tag/repository/operation/repoListPullRequests + + mv_repo_url = |http://localhost:3050/api/v1/repos/{ iv_user_and_repo }|. + mi_http_agent = ii_http_agent. + + IF zcl_abapgit_login_manager=>get( mv_repo_url ) IS NOT INITIAL. + mi_http_agent->global_headers( )->set( + iv_key = 'Authorization' + iv_val = zcl_abapgit_login_manager=>get( mv_repo_url ) ). + ENDIF. + + ENDMETHOD. + METHOD convert_list. + + DATA lt_items TYPE string_table. + DATA lv_i TYPE string. + FIELD-SYMBOLS LIKE LINE OF rt_pulls. + + lt_items = ii_json->members( '/' ). + + LOOP AT lt_items INTO lv_i. + APPEND INITIAL LINE TO rt_pulls ASSIGNING . + -base_url = ii_json->get( |/{ lv_i }/base/repo/clone_url| ). + -number = ii_json->get( |/{ lv_i }/number| ). + -title = ii_json->get( |/{ lv_i }/title| ). + -user = ii_json->get( |/{ lv_i }/user/login| ). + -head_url = ii_json->get( |/{ lv_i }/head/repo/clone_url| ). + -head_branch = ii_json->get( |/{ lv_i }/head/ref| ). + -created_at = ii_json->get( |/{ lv_i }/created_at| ). + -draft = ii_json->get_boolean( |/{ lv_i }/draft| ). + -html_url = ii_json->get( |/{ lv_i }/html_url| ). + ENDLOOP. + + ENDMETHOD. + METHOD fetch_repo_by_url. + + DATA li_pulls_json TYPE REF TO zif_abapgit_ajson. + DATA lv_pull_url TYPE string. + DATA li_response TYPE REF TO zif_abapgit_http_response. + DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + + li_response = mi_http_agent->request( iv_repo_url ). + + TRY. + rs_info-repo_json = li_response->json( ). + li_response->headers( ). " for debug + lv_pull_url = clean_url( rs_info-repo_json->get( '/pulls_url' ) ). + IF lv_pull_url IS INITIAL OR rs_info-repo_json->get( '/message' ) = 'Not Found'. + RETURN. + ENDIF. + li_pulls_json = mi_http_agent->request( lv_pull_url )->json( ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise_with_text( lx_ajson ). + ENDTRY. + + rs_info-pulls = convert_list( li_pulls_json ). + + ENDMETHOD. + METHOD zif_abapgit_pr_enum_provider~create_initial_branch. + zcx_abapgit_exception=>raise( 'Not implemented for Gitea' ). + ENDMETHOD. + METHOD zif_abapgit_pr_enum_provider~create_repository. + zcx_abapgit_exception=>raise( 'Not implemented for Gitea' ). + ENDMETHOD. + METHOD zif_abapgit_pr_enum_provider~list_pull_requests. + + DATA lv_upstream_url TYPE string. + DATA ls_repo_info TYPE ty_info. + FIELD-SYMBOLS LIKE LINE OF ls_repo_info-pulls. + + ls_repo_info = fetch_repo_by_url( mv_repo_url ). + APPEND LINES OF ls_repo_info-pulls TO rt_pulls. + + IF ls_repo_info-repo_json->get_boolean( '/fork' ) = abap_true. + lv_upstream_url = ls_repo_info-repo_json->get( '/source/url' ). " parent ? + ls_repo_info = fetch_repo_by_url( lv_upstream_url ). + LOOP AT ls_repo_info-pulls ASSIGNING . + -is_for_upstream = abap_true. + APPEND TO rt_pulls. + ENDLOOP. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_git_url IMPLEMENTATION. + METHOD get_commit_display_url. + + DATA li_exit TYPE REF TO zif_abapgit_exit. + DATA li_repo TYPE REF TO zif_abapgit_repo. + + li_repo = ii_repo_online. + + rv_url = get_default_commit_display_url( + iv_repo_url = ii_repo_online->get_url( ) + iv_hash = ii_repo_online->get_current_remote( ) ). + + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->adjust_display_commit_url( + EXPORTING + iv_repo_url = ii_repo_online->get_url( ) + iv_repo_name = li_repo->get_name( ) + iv_repo_key = li_repo->get_key( ) + iv_commit_hash = ii_repo_online->get_current_remote( ) + CHANGING + cv_display_url = rv_url ). + + IF rv_url IS INITIAL. + zcx_abapgit_exception=>raise( |provider not yet supported| ). + ENDIF. + + ENDMETHOD. + METHOD get_default_commit_display_url. + + DATA ls_result TYPE match_result. + FIELD-SYMBOLS TYPE submatch_result. + + rv_commit_url = iv_repo_url. + + FIND REGEX '^http(?:s)?:\/\/(?:www\.)?(github\.com|bitbucket\.org|gitlab\.com)\/' + IN rv_commit_url + RESULTS ls_result. + IF sy-subrc = 0. + READ TABLE ls_result-submatches INDEX 1 ASSIGNING . + CASE rv_commit_url+-offset(-length). + WHEN 'github.com'. + REPLACE REGEX '\.git$' IN rv_commit_url WITH space. + rv_commit_url = rv_commit_url && |/commit/| && iv_hash. + WHEN 'bitbucket.org'. + REPLACE REGEX '\.git$' IN rv_commit_url WITH space. + rv_commit_url = rv_commit_url && |/commits/| && iv_hash. + WHEN 'gitlab.com'. + REPLACE REGEX '\.git$' IN rv_commit_url WITH space. + rv_commit_url = rv_commit_url && |/-/commit/| && iv_hash. + ENDCASE. + ENDIF. + + ENDMETHOD. + METHOD validate_url. + + DATA lv_provider TYPE string. + + lv_provider = zcl_abapgit_url=>host( to_lower( iv_url ) ). + + " Provider-specific check for URLs that don't work + IF lv_provider CS 'gitlab.com'. + FIND REGEX '\.git$' IN iv_url IGNORING CASE. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Repo URL for GitLab must end in ".git"' ). + ENDIF. + ELSEIF lv_provider CS 'dev.azure.com'. + FIND REGEX '\.git$' IN iv_url IGNORING CASE. + IF sy-subrc = 0. + zcx_abapgit_exception=>raise( 'Repo URL for Azure DevOps must not end in ".git"' ). + ENDIF. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ZLIB_STREAM IMPLEMENTATION. + METHOD clear_bits. + CLEAR mv_bits. + ENDMETHOD. + METHOD constructor. + + mv_compressed = iv_data. + + ENDMETHOD. + METHOD remaining. + + rv_length = xstrlen( mv_compressed ) + 1. + + ENDMETHOD. + METHOD take_bits. + + DATA: lv_left TYPE i, + lv_index TYPE i, + lv_x TYPE x LENGTH 1. + WHILE strlen( rv_bits ) < iv_length. + IF mv_bits IS INITIAL. + lv_x = mv_compressed(1). + mv_bits = zcl_abapgit_zlib_convert=>hex_to_bits( lv_x ). + mv_compressed = mv_compressed+1. + ENDIF. + lv_left = iv_length - strlen( rv_bits ). + IF lv_left >= strlen( mv_bits ). + CONCATENATE mv_bits rv_bits INTO rv_bits. + CLEAR mv_bits. + ELSE. + lv_index = strlen( mv_bits ) - lv_left. + CONCATENATE mv_bits+lv_index(lv_left) rv_bits INTO rv_bits. + mv_bits = mv_bits(lv_index). + ENDIF. + + ENDWHILE. + + ENDMETHOD. + METHOD take_bytes. + + rv_bytes = mv_compressed(iv_length). + mv_compressed = mv_compressed+iv_length. + + ENDMETHOD. + METHOD take_int. + + rv_int = zcl_abapgit_zlib_convert=>bits_to_int( take_bits( iv_length ) ). + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ZLIB_HUFFMAN IMPLEMENTATION. + METHOD constructor. + + DATA: lv_index TYPE i, + lt_offset TYPE TABLE OF i, + lv_length LIKE LINE OF it_lengths, + lv_prev TYPE i, + lv_count LIKE LINE OF mt_count. + + FIELD-SYMBOLS: LIKE LINE OF lt_offset, + LIKE LINE OF mt_symbol, + LIKE LINE OF it_lengths. + DO c_maxbits TIMES. + APPEND 0 TO mt_count. + ENDDO. + LOOP AT it_lengths INTO lv_index. + IF lv_index = 0. + CONTINUE. + ENDIF. + READ TABLE mt_count INDEX lv_index ASSIGNING . + ASSERT sy-subrc = 0. + = + 1. + ENDLOOP. + +************ + + APPEND 0 TO lt_offset. + DO c_maxbits - 1 TIMES. + READ TABLE mt_count INDEX sy-index INTO lv_count. + ASSERT sy-subrc = 0. + lv_prev = lv_prev + lv_count. + APPEND lv_prev TO lt_offset. + ENDDO. + + DO lines( it_lengths ) TIMES. + APPEND 0 TO mt_symbol. + ENDDO. + DO lines( it_lengths ) TIMES. + lv_index = sy-index. + READ TABLE it_lengths INDEX lv_index INTO lv_length. + ASSERT sy-subrc = 0. + IF lv_length = 0. + CONTINUE. + ENDIF. + READ TABLE lt_offset INDEX lv_length ASSIGNING . + ASSERT sy-subrc = 0. + READ TABLE mt_symbol INDEX + 1 ASSIGNING . + ASSERT sy-subrc = 0. + = lv_index - 1. + = + 1. + ENDDO. + + ENDMETHOD. + METHOD get_count. + READ TABLE mt_count INDEX iv_index INTO rv_value. "#EC CI_SUBRC + ENDMETHOD. + METHOD get_symbol. + READ TABLE mt_symbol INDEX iv_index INTO rv_value. "#EC CI_SUBRC + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_ZLIB_CONVERT IMPLEMENTATION. + METHOD bits_to_int. + + DATA lv_i TYPE i. + DATA lv_offset TYPE i. + + DO strlen( iv_bits ) TIMES. + lv_i = iv_bits+lv_offset(1). + rv_int = rv_int * 2 + lv_i. + lv_offset = lv_offset + 1. + ENDDO. + + ENDMETHOD. + METHOD hex_to_bits. + + DATA: lv_x TYPE x LENGTH 1, + lv_c TYPE c LENGTH 1, + lv_hex TYPE xstring. + lv_hex = iv_hex. + WHILE NOT lv_hex IS INITIAL. + lv_x = lv_hex. + DO 8 TIMES. + GET BIT sy-index OF lv_x INTO lv_c. + CONCATENATE rv_bits lv_c INTO rv_bits. + ENDDO. + lv_hex = lv_hex+1. + ENDWHILE. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_zlib IMPLEMENTATION. + METHOD copy_out. + +* copy one byte at a time, it is not possible to copy using +* string offsets, as it might copy data that does not exist +* in mv_out yet + + DATA: lv_distance TYPE i, + lv_index TYPE i, + lv_x TYPE x LENGTH 1. + lv_distance = xstrlen( gv_out ) - is_pair-distance. + DO is_pair-length TIMES. + lv_index = sy-index - 1 + lv_distance. + lv_x = gv_out+lv_index(1). + CONCATENATE gv_out lv_x INTO gv_out IN BYTE MODE. + ENDDO. + + ENDMETHOD. + METHOD decode. + + DATA: lv_bit TYPE c LENGTH 1, + lv_len TYPE i, + lv_count TYPE i, + lv_code TYPE i, + lv_index TYPE i, + lv_first TYPE i. + DO zcl_abapgit_zlib_huffman=>c_maxbits TIMES. + lv_len = sy-index. + + lv_bit = go_stream->take_bits( 1 ). + lv_code = lv_bit + lv_code * 2. + lv_count = io_huffman->get_count( lv_len ). + + IF lv_code - lv_count < lv_first. + rv_symbol = io_huffman->get_symbol( lv_index + lv_code - lv_first + 1 ). + RETURN. + ENDIF. + lv_index = lv_index + lv_count. + lv_first = lv_first + lv_count. + lv_first = lv_first * 2. + ENDDO. + + ENDMETHOD. + METHOD decode_loop. + + DATA lv_x TYPE x. + DATA lv_symbol TYPE i. + + DO. + lv_symbol = decode( go_lencode ). + + IF lv_symbol < 256. + lv_x = lv_symbol. + CONCATENATE gv_out lv_x INTO gv_out IN BYTE MODE. + ELSEIF lv_symbol = 256. + EXIT. + ELSE. + copy_out( read_pair( lv_symbol ) ). + ENDIF. + + ENDDO. + + ENDMETHOD. + METHOD decompress. + + DATA: lv_bfinal TYPE c LENGTH 1, + lv_btype TYPE c LENGTH 2. + IF iv_compressed IS INITIAL. + RETURN. + ENDIF. + + CLEAR gv_out. + CREATE OBJECT go_stream + EXPORTING + iv_data = iv_compressed. + + DO. + lv_bfinal = go_stream->take_bits( 1 ). + + lv_btype = go_stream->take_bits( 2 ). + CASE lv_btype. + WHEN '00'. + not_compressed( ). + WHEN '01'. + fixed( ). + decode_loop( ). + WHEN '10'. + dynamic( ). + decode_loop( ). + WHEN OTHERS. + ASSERT 1 = 0. + ENDCASE. + + IF lv_bfinal = '1'. + EXIT. + ENDIF. + + ENDDO. + + rs_data-raw = gv_out. + rs_data-compressed_len = xstrlen( iv_compressed ) - go_stream->remaining( ). + + ENDMETHOD. + METHOD dynamic. + + DATA: lv_nlen TYPE i, + lv_ndist TYPE i, + lv_ncode TYPE i, + lv_index TYPE i, + lv_length TYPE i, + lv_symbol TYPE i, + lt_order TYPE TABLE OF i, + lt_lengths TYPE zcl_abapgit_zlib_huffman=>ty_lengths, + lt_dists TYPE zcl_abapgit_zlib_huffman=>ty_lengths. + + FIELD-SYMBOLS: LIKE LINE OF lt_lengths. + APPEND 16 TO lt_order. + APPEND 17 TO lt_order. + APPEND 18 TO lt_order. + APPEND 0 TO lt_order. + APPEND 8 TO lt_order. + APPEND 7 TO lt_order. + APPEND 9 TO lt_order. + APPEND 6 TO lt_order. + APPEND 10 TO lt_order. + APPEND 5 TO lt_order. + APPEND 11 TO lt_order. + APPEND 4 TO lt_order. + APPEND 12 TO lt_order. + APPEND 3 TO lt_order. + APPEND 13 TO lt_order. + APPEND 2 TO lt_order. + APPEND 14 TO lt_order. + APPEND 1 TO lt_order. + APPEND 15 TO lt_order. + + lv_nlen = go_stream->take_int( 5 ) + 257. + lv_ndist = go_stream->take_int( 5 ) + 1. + lv_ncode = go_stream->take_int( 4 ) + 4. + + DO 19 TIMES. + APPEND 0 TO lt_lengths. + ENDDO. + + DO lv_ncode TIMES. + READ TABLE lt_order INDEX sy-index INTO lv_index. + ASSERT sy-subrc = 0. + lv_index = lv_index + 1. + READ TABLE lt_lengths INDEX lv_index ASSIGNING . + ASSERT sy-subrc = 0. + = go_stream->take_int( 3 ). + ENDDO. + + CREATE OBJECT go_lencode + EXPORTING + it_lengths = lt_lengths. + + CLEAR lt_lengths. + WHILE lines( lt_lengths ) < lv_nlen + lv_ndist. + lv_symbol = decode( go_lencode ). + + IF lv_symbol < 16. + APPEND lv_symbol TO lt_lengths. + ELSE. + lv_length = 0. + IF lv_symbol = 16. + READ TABLE lt_lengths INDEX lines( lt_lengths ) INTO lv_length. + ASSERT sy-subrc = 0. + lv_symbol = go_stream->take_int( 2 ) + 3. + ELSEIF lv_symbol = 17. + lv_symbol = go_stream->take_int( 3 ) + 3. + ELSE. + lv_symbol = go_stream->take_int( 7 ) + 11. + ENDIF. + DO lv_symbol TIMES. + APPEND lv_length TO lt_lengths. + ENDDO. + ENDIF. + ENDWHILE. + + lt_dists = lt_lengths. + DELETE lt_lengths FROM lv_nlen + 1. + DELETE lt_dists TO lv_nlen. + + CREATE OBJECT go_lencode + EXPORTING + it_lengths = lt_lengths. + + CREATE OBJECT go_distcode + EXPORTING + it_lengths = lt_dists. + + ENDMETHOD. + METHOD fixed. + + DATA: lt_lengths TYPE zcl_abapgit_zlib_huffman=>ty_lengths. + DO 144 TIMES. + APPEND 8 TO lt_lengths. + ENDDO. + DO 112 TIMES. + APPEND 9 TO lt_lengths. + ENDDO. + DO 24 TIMES. + APPEND 7 TO lt_lengths. + ENDDO. + DO 8 TIMES. + APPEND 8 TO lt_lengths. + ENDDO. + + CREATE OBJECT go_lencode + EXPORTING + it_lengths = lt_lengths. + + CLEAR lt_lengths. + DO c_maxdcodes TIMES. + APPEND 5 TO lt_lengths. + ENDDO. + + CREATE OBJECT go_distcode + EXPORTING + it_lengths = lt_lengths. + + ENDMETHOD. + METHOD map_distance. + + CASE iv_code. + WHEN 0. + rv_distance = go_stream->take_int( 0 ) + 1. + WHEN 1. + rv_distance = go_stream->take_int( 0 ) + 2. + WHEN 2. + rv_distance = go_stream->take_int( 0 ) + 3. + WHEN 3. + rv_distance = go_stream->take_int( 0 ) + 4. + WHEN 4. + rv_distance = go_stream->take_int( 1 ) + 5. + WHEN 5. + rv_distance = go_stream->take_int( 1 ) + 7. + WHEN 6. + rv_distance = go_stream->take_int( 2 ) + 9. + WHEN 7. + rv_distance = go_stream->take_int( 2 ) + 13. + WHEN 8. + rv_distance = go_stream->take_int( 3 ) + 17. + WHEN 9. + rv_distance = go_stream->take_int( 3 ) + 25. + WHEN 10. + rv_distance = go_stream->take_int( 4 ) + 33. + WHEN 11. + rv_distance = go_stream->take_int( 4 ) + 49. + WHEN 12. + rv_distance = go_stream->take_int( 5 ) + 65. + WHEN 13. + rv_distance = go_stream->take_int( 5 ) + 97. + WHEN 14. + rv_distance = go_stream->take_int( 6 ) + 129. + WHEN 15. + rv_distance = go_stream->take_int( 6 ) + 193. + WHEN 16. + rv_distance = go_stream->take_int( 7 ) + 257. + WHEN 17. + rv_distance = go_stream->take_int( 7 ) + 385. + WHEN 18. + rv_distance = go_stream->take_int( 8 ) + 513. + WHEN 19. + rv_distance = go_stream->take_int( 8 ) + 769. + WHEN 20. + rv_distance = go_stream->take_int( 9 ) + 1025. + WHEN 21. + rv_distance = go_stream->take_int( 9 ) + 1537. + WHEN 22. + rv_distance = go_stream->take_int( 10 ) + 2049. + WHEN 23. + rv_distance = go_stream->take_int( 10 ) + 3073. + WHEN 24. + rv_distance = go_stream->take_int( 11 ) + 4097. + WHEN 25. + rv_distance = go_stream->take_int( 11 ) + 6145. + WHEN 26. + rv_distance = go_stream->take_int( 12 ) + 8193. + WHEN 27. + rv_distance = go_stream->take_int( 12 ) + 12289. + WHEN 28. + rv_distance = go_stream->take_int( 13 ) + 16385. + WHEN 29. + rv_distance = go_stream->take_int( 13 ) + 24577. + WHEN OTHERS. + ASSERT 1 = 0. + ENDCASE. + + ENDMETHOD. + METHOD map_length. + + CASE iv_code. + WHEN 257. + rv_length = go_stream->take_int( 0 ) + 3. + WHEN 258. + rv_length = go_stream->take_int( 0 ) + 4. + WHEN 259. + rv_length = go_stream->take_int( 0 ) + 5. + WHEN 260. + rv_length = go_stream->take_int( 0 ) + 6. + WHEN 261. + rv_length = go_stream->take_int( 0 ) + 7. + WHEN 262. + rv_length = go_stream->take_int( 0 ) + 8. + WHEN 263. + rv_length = go_stream->take_int( 0 ) + 9. + WHEN 264. + rv_length = go_stream->take_int( 0 ) + 10. + WHEN 265. + rv_length = go_stream->take_int( 1 ) + 11. + WHEN 266. + rv_length = go_stream->take_int( 1 ) + 13. + WHEN 267. + rv_length = go_stream->take_int( 1 ) + 15. + WHEN 268. + rv_length = go_stream->take_int( 1 ) + 17. + WHEN 269. + rv_length = go_stream->take_int( 2 ) + 19. + WHEN 270. + rv_length = go_stream->take_int( 2 ) + 23. + WHEN 271. + rv_length = go_stream->take_int( 2 ) + 27. + WHEN 272. + rv_length = go_stream->take_int( 2 ) + 31. + WHEN 273. + rv_length = go_stream->take_int( 3 ) + 35. + WHEN 274. + rv_length = go_stream->take_int( 3 ) + 43. + WHEN 275. + rv_length = go_stream->take_int( 3 ) + 51. + WHEN 276. + rv_length = go_stream->take_int( 3 ) + 59. + WHEN 277. + rv_length = go_stream->take_int( 4 ) + 67. + WHEN 278. + rv_length = go_stream->take_int( 4 ) + 83. + WHEN 279. + rv_length = go_stream->take_int( 4 ) + 99. + WHEN 280. + rv_length = go_stream->take_int( 4 ) + 115. + WHEN 281. + rv_length = go_stream->take_int( 5 ) + 131. + WHEN 282. + rv_length = go_stream->take_int( 5 ) + 163. + WHEN 283. + rv_length = go_stream->take_int( 5 ) + 195. + WHEN 284. + rv_length = go_stream->take_int( 5 ) + 227. + WHEN 285. + rv_length = go_stream->take_int( 0 ) + 258. + WHEN OTHERS. + ASSERT 1 = 0. + ENDCASE. + + ENDMETHOD. + METHOD not_compressed. + + DATA: lv_len TYPE i, + lv_nlen TYPE i ##NEEDED. + DATA lv_bytes TYPE xstring. + +* skip any remaining bits in current partially processed byte + go_stream->clear_bits( ). + + lv_len = go_stream->take_int( 16 ). + lv_nlen = go_stream->take_int( 16 ). + + lv_bytes = go_stream->take_bytes( lv_len ). + CONCATENATE gv_out lv_bytes INTO gv_out IN BYTE MODE. + + ENDMETHOD. + METHOD read_pair. + + DATA: lv_symbol TYPE i. + rs_pair-length = map_length( iv_length ). + + lv_symbol = decode( go_distcode ). + rs_pair-distance = map_distance( lv_symbol ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_hash IMPLEMENTATION. + METHOD adler32. + + CONSTANTS: lc_adler TYPE i VALUE 65521, + lc_max_b TYPE i VALUE 1800000000. + + DATA: lv_index TYPE i, + lv_a TYPE i VALUE 1, + lv_b TYPE i VALUE 0, + lv_x TYPE x LENGTH 2, + lv_ca TYPE c LENGTH 4, + lv_cb TYPE c LENGTH 4, + lv_char8 TYPE c LENGTH 8. + DO xstrlen( iv_xstring ) TIMES. + lv_index = sy-index - 1. + + lv_a = lv_a + iv_xstring+lv_index(1). + lv_b = lv_b + lv_a. + +* delay the MOD operation until the integer might overflow +* articles describe 5552 additions are allowed, but this assumes unsigned integers +* instead of allowing a fixed number of additions before running MOD, then +* just compare value of lv_b, this is 1 operation less than comparing and adding + IF lv_b > lc_max_b. + lv_a = lv_a MOD lc_adler. + lv_b = lv_b MOD lc_adler. + ENDIF. + ENDDO. + + lv_a = lv_a MOD lc_adler. + lv_b = lv_b MOD lc_adler. + + lv_x = lv_a. + lv_ca = lv_x. + + lv_x = lv_b. + lv_cb = lv_x. + + CONCATENATE lv_cb lv_ca INTO lv_char8. + + rv_checksum = lv_char8. + + ENDMETHOD. + METHOD sha1. + + DATA: lv_len TYPE i, + lv_char10 TYPE c LENGTH 10, + lv_string TYPE string, + lv_xstring TYPE xstring. + lv_len = xstrlen( iv_data ). + lv_char10 = lv_len. + CONDENSE lv_char10. + CONCATENATE iv_type lv_char10 INTO lv_string SEPARATED BY space. + lv_xstring = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). + + lv_string = lv_xstring. + CONCATENATE lv_string '00' INTO lv_string. + lv_xstring = lv_string. + + CONCATENATE lv_xstring iv_data INTO lv_xstring IN BYTE MODE. + + rv_sha1 = sha1_raw( lv_xstring ). + + ENDMETHOD. + METHOD sha1_blob. + rv_sha1 = sha1( iv_type = zif_abapgit_git_definitions=>c_type-blob + iv_data = iv_data ). + ENDMETHOD. + METHOD sha1_commit. + rv_sha1 = sha1( iv_type = zif_abapgit_git_definitions=>c_type-commit + iv_data = iv_data ). + ENDMETHOD. + METHOD sha1_raw. + + DATA: lv_hash TYPE string, + lv_key TYPE xstring, + lx_error TYPE REF TO cx_abap_message_digest. + TRY. + cl_abap_hmac=>calculate_hmac_for_raw( + EXPORTING + if_key = lv_key + if_data = iv_data + IMPORTING + ef_hmacstring = lv_hash ). + CATCH cx_abap_message_digest INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + rv_sha1 = lv_hash. + TRANSLATE rv_sha1 TO LOWER CASE. + + ENDMETHOD. + METHOD sha1_string. + + DATA: lv_hash TYPE string, + lv_key TYPE xstring, + lx_error TYPE REF TO cx_abap_message_digest. + TRY. + cl_abap_hmac=>calculate_hmac_for_char( + EXPORTING + if_key = lv_key + if_data = iv_data + IMPORTING + ef_hmacstring = lv_hash ). + CATCH cx_abap_message_digest INTO lx_error. + zcx_abapgit_exception=>raise_with_text( lx_error ). + ENDTRY. + + rv_sha1 = lv_hash. + TRANSLATE rv_sha1 TO LOWER CASE. + + ENDMETHOD. + METHOD sha1_tag. + rv_sha1 = sha1( iv_type = zif_abapgit_git_definitions=>c_type-tag + iv_data = iv_data ). + ENDMETHOD. + METHOD sha1_tree. + rv_sha1 = sha1( iv_type = zif_abapgit_git_definitions=>c_type-tree + iv_data = iv_data ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_git_utils IMPLEMENTATION. + METHOD get_null. + +* must be length 4, or it gives a syntax error on lower versions + DATA: lv_x TYPE x LENGTH 4 VALUE '00000000'. + FIELD-SYMBOLS TYPE c. + + ASSIGN lv_x TO CASTING. + rv_c = . + + ENDMETHOD. + METHOD length_utf8_hex. + + DATA: lv_xstring TYPE xstring, + lv_char4 TYPE c LENGTH 4, + lv_x TYPE x LENGTH 2. + + IF xstrlen( iv_data ) < 4. + zcx_abapgit_exception=>raise( 'error converting to hex, LENGTH_UTF8_HEX' ). + ENDIF. + + lv_xstring = iv_data(4). + + lv_char4 = zcl_abapgit_convert=>xstring_to_string_utf8( + iv_data = lv_xstring + iv_length = 4 ). + + TRANSLATE lv_char4 TO UPPER CASE. + lv_x = lv_char4. + rv_len = lv_x. + + ENDMETHOD. + METHOD pkt_string. + + DATA: lv_x TYPE x, + lv_len TYPE i. + lv_len = strlen( iv_string ). + + IF lv_len >= 255. + zcx_abapgit_exception=>raise( 'PKT, todo' ). + ENDIF. + + lv_x = lv_len + 4. + + rv_pkt = '00' && lv_x && iv_string. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_git_transport IMPLEMENTATION. + METHOD branches. + + " This method is kept for compatibility reasons + ri_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). + + ENDMETHOD. + METHOD branch_list. + + CONSTANTS lc_content_regex TYPE string VALUE '^[0-9a-f]{4}#'. + CONSTANTS lc_content_type TYPE string VALUE 'application/x-git--pack-advertisement'. + + DATA lv_data TYPE string. + DATA lv_expected_content_type TYPE string. + DATA lt_headers TYPE zcl_abapgit_http=>ty_headers. + DATA ls_header LIKE LINE OF lt_headers. + + ls_header-key = '~request_uri'. + ls_header-value = get_request_uri( iv_url = iv_url + iv_service = iv_service ). + APPEND ls_header TO lt_headers. + + eo_client = zcl_abapgit_http=>create_by_url( + iv_url = iv_url + it_headers = lt_headers ). + + lv_expected_content_type = lc_content_type. + REPLACE '' IN lv_expected_content_type WITH iv_service. + + eo_client->check_smart_response( + iv_expected_content_type = lv_expected_content_type + iv_content_regex = lc_content_regex ). + + lv_data = eo_client->get_cdata( ). + + CREATE OBJECT ei_branch_list TYPE zcl_abapgit_git_branch_list + EXPORTING + iv_data = lv_data. + + ENDMETHOD. + METHOD check_report_status. + + DATA: + lv_string TYPE string, + lv_error TYPE string, + lv_unpack_status TYPE string, + lv_unpack_code TYPE string, + lv_unpack_text TYPE string, + lv_commnd_status TYPE string, + lv_commnd_code TYPE string, + lv_commnd_text TYPE string. + + " Based on https://git-scm.com/docs/pack-protocol/2.2.3#_report_status + lv_string = iv_string. + + IF lv_string = ''. + lv_error = 'Unexpected empty reply'. + ELSEIF strlen( lv_string ) < 4. + lv_error = 'Missing pkt length for unpack status'. + ELSE. + lv_string = lv_string+4. + SPLIT lv_string AT cl_abap_char_utilities=>newline INTO lv_unpack_status lv_string. + SPLIT lv_unpack_status AT space INTO lv_unpack_text lv_unpack_code. + + IF lv_unpack_text <> 'unpack'. + lv_error = 'Unexpected unpack status'. + ELSEIF lv_unpack_code <> 'ok'. + lv_error = |Unpack not ok ({ lv_unpack_code })|. + ELSEIF lv_string = ''. + lv_error = 'Unexpected command status'. + ELSEIF strlen( lv_string ) < 4. + lv_error = 'Missing pkt length for command status'. + ELSE. + lv_string = lv_string+4. + SPLIT lv_string AT cl_abap_char_utilities=>newline INTO lv_commnd_status lv_string. + SPLIT lv_commnd_status AT space INTO lv_commnd_code lv_commnd_text. + + IF lv_commnd_code <> 'ok'. "=ng + " Some pre-defined error messages + IF lv_commnd_text CP '*pre-receive hook declined*'. + lv_error = 'Pre-receive hook declined'. + ELSEIF lv_commnd_text CP '*protected branch hook declined*'. + lv_error = 'Protected branch hook declined'. + ELSEIF lv_commnd_text CP '*push declined due to email privacy*'. + lv_error = 'Push declined due to email privacy'. + ELSEIF lv_commnd_text CP '*funny refname*'. + lv_error = 'Funny refname'. + ELSEIF lv_commnd_text CP '*failed to update ref*'. + lv_error = 'Failed to update ref'. + ELSEIF lv_commnd_text CP '*missing necessary objects*'. + lv_error = 'Missing necessary objects'. + ELSEIF lv_commnd_text CP '*refusing to delete the current branch*'. + lv_error = 'Branch delete not allowed'. + ELSEIF lv_commnd_text CP '*cannot lock ref*reference already exists*'. + lv_error = 'Branch already exists'. + ELSEIF lv_commnd_text CP '*cannot lock ref*but expected*'. + lv_error = 'Branch cannot be locked'. + ELSEIF lv_commnd_text CP '*invalid committer*'. + lv_error = 'Invalid committer'. + ELSE. + " Otherwise return full error message + lv_error = lv_commnd_text. + ENDIF. + ELSEIF strlen( lv_string ) < 4. + lv_error = 'Missing flush-pkt'. + ELSEIF lv_string <> '0000' AND lv_string <> '00000000'. + " We update only one reference at a time so this should be the end + lv_error = 'Unexpected end of status (flush-pkt)'. + ENDIF. + ENDIF. + ENDIF. + + IF lv_error IS NOT INITIAL. + zcx_abapgit_exception=>raise( |Git protocol error: { lv_error }| ). + ENDIF. + + ENDMETHOD. + METHOD find_branch. + + branch_list( + EXPORTING + iv_url = iv_url + iv_service = iv_service + IMPORTING + eo_client = eo_client + ei_branch_list = ei_branch_list ). + + IF ev_branch IS SUPPLIED. + ev_branch = ei_branch_list->find_by_name( iv_branch_name )-sha1. + ENDIF. + + ENDMETHOD. + METHOD get_request_uri. + rv_uri = zcl_abapgit_url=>path_name( iv_url ) && |/info/refs?service=git-{ iv_service }-pack|. + ENDMETHOD. + METHOD parse. + + CONSTANTS: lc_band1 TYPE x VALUE '01'. + + DATA: lv_len TYPE i, + lv_contents TYPE xstring, + lv_pack TYPE xstring. + WHILE xstrlen( cv_data ) >= 4. + lv_len = zcl_abapgit_git_utils=>length_utf8_hex( cv_data ). + + IF lv_len > xstrlen( cv_data ). + zcx_abapgit_exception=>raise( 'parse, string length too large' ). + ENDIF. + + lv_contents = cv_data(lv_len). + IF lv_len = 0. + cv_data = cv_data+4. + CONTINUE. + ELSE. + cv_data = cv_data+lv_len. + ENDIF. + + lv_contents = lv_contents+4. + + IF xstrlen( lv_contents ) > 1 AND lv_contents(1) = lc_band1. + CONCATENATE lv_pack lv_contents+1 INTO lv_pack IN BYTE MODE. + ENDIF. + + ENDWHILE. + + ev_pack = lv_pack. + + ENDMETHOD. + METHOD receive_pack. + + DATA: lo_client TYPE REF TO zcl_abapgit_http_client, + lv_cmd_pkt TYPE string, + lv_line TYPE string, + lv_tmp TYPE xstring, + lv_xstring TYPE xstring, + lv_string TYPE string, + lv_cap_list TYPE string, + lv_buffer TYPE string. + find_branch( + EXPORTING + iv_url = iv_url + iv_service = c_service-receive + iv_branch_name = iv_branch_name + IMPORTING + eo_client = lo_client ). + + lo_client->set_headers( + iv_url = iv_url + iv_service = c_service-receive ). + + lv_cap_list = 'report-status'. + + lv_line = iv_old && + ` ` && + iv_new && + ` ` && + iv_branch_name && + zcl_abapgit_git_utils=>get_null( ) && + ` ` && + lv_cap_list && + cl_abap_char_utilities=>newline. + lv_cmd_pkt = zcl_abapgit_git_utils=>pkt_string( lv_line ). + + lv_buffer = lv_cmd_pkt && '0000'. + lv_tmp = zcl_abapgit_convert=>string_to_xstring_utf8( lv_buffer ). + + CONCATENATE lv_tmp iv_pack INTO lv_xstring IN BYTE MODE. + + lv_xstring = lo_client->send_receive_close( lv_xstring ). + + lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xstring ). + + check_report_status( lv_string ). + + ENDMETHOD. + METHOD upload_pack. + + DATA: lv_capa TYPE string, + lv_line TYPE string, + lv_buffer TYPE string, + lv_xstring TYPE xstring, + lv_pack TYPE xstring. + + FIELD-SYMBOLS: LIKE LINE OF it_hashes. + io_client->set_headers( iv_url = iv_url + iv_service = c_service-upload ). + + LOOP AT it_hashes FROM 1 ASSIGNING . + IF sy-tabix = 1. + lv_capa = 'side-band-64k no-progress multi_ack'. + lv_line = 'want' && ` ` && + && ` ` && lv_capa && cl_abap_char_utilities=>newline. + ELSE. + lv_line = 'want' && ` ` && + && cl_abap_char_utilities=>newline. + ENDIF. + lv_buffer = lv_buffer && zcl_abapgit_git_utils=>pkt_string( lv_line ). + ENDLOOP. + + IF iv_deepen_level > 0. + lv_buffer = lv_buffer && zcl_abapgit_git_utils=>pkt_string( |deepen { iv_deepen_level }| && + cl_abap_char_utilities=>newline ). + ENDIF. + + lv_buffer = lv_buffer + && '0000' + && '0009done' && cl_abap_char_utilities=>newline. + + lv_xstring = io_client->send_receive_close( zcl_abapgit_convert=>string_to_xstring_utf8( lv_buffer ) ). + + parse( IMPORTING ev_pack = lv_pack + CHANGING cv_data = lv_xstring ). + + IF lv_pack IS INITIAL. + zcx_abapgit_exception=>raise( 'Response could not be parsed - empty pack returned.' ). + ENDIF. + + rt_objects = zcl_abapgit_git_pack=>decode( lv_pack ). + + ENDMETHOD. + METHOD upload_pack_by_branch. + + DATA: lo_client TYPE REF TO zcl_abapgit_http_client, + lt_hashes TYPE zif_abapgit_git_definitions=>ty_sha1_tt. + + FIELD-SYMBOLS: LIKE LINE OF it_branches. + CLEAR: et_objects, + ev_branch. + + find_branch( + EXPORTING + iv_url = iv_url + iv_service = c_service-upload + iv_branch_name = iv_branch_name + IMPORTING + eo_client = lo_client + ev_branch = ev_branch ). + + IF it_branches IS INITIAL. + APPEND ev_branch TO lt_hashes. + ELSE. + LOOP AT it_branches ASSIGNING . + APPEND -sha1 TO lt_hashes. + ENDLOOP. + ENDIF. + + et_objects = upload_pack( io_client = lo_client + iv_url = iv_url + iv_deepen_level = iv_deepen_level + it_hashes = lt_hashes ). + + ENDMETHOD. + METHOD upload_pack_by_commit. + + DATA: lo_client TYPE REF TO zcl_abapgit_http_client, + lt_hashes TYPE zif_abapgit_git_definitions=>ty_sha1_tt. + DATA lt_headers TYPE zcl_abapgit_http=>ty_headers. + DATA ls_header LIKE LINE OF lt_headers. + + CLEAR: et_objects, + ev_commit. + + APPEND iv_hash TO lt_hashes. + ev_commit = iv_hash. + + ls_header-key = '~request_uri'. + ls_header-value = get_request_uri( iv_url = iv_url + iv_service = c_service-upload ). + APPEND ls_header TO lt_headers. + + lo_client = zcl_abapgit_http=>create_by_url( + iv_url = iv_url + it_headers = lt_headers ). + + et_objects = upload_pack( io_client = lo_client + iv_url = iv_url + iv_deepen_level = iv_deepen_level + it_hashes = lt_hashes ). + + ENDMETHOD. + METHOD zif_abapgit_git_transport~branches. + + DATA: lo_client TYPE REF TO zcl_abapgit_http_client. + branch_list( + EXPORTING + iv_url = iv_url + iv_service = c_service-upload + IMPORTING + eo_client = lo_client + ei_branch_list = ri_branch_list ). + + lo_client->close( ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_git_time IMPLEMENTATION. + METHOD get_one_year_ago. +* https://www.epochconverter.com + CONSTANTS lc_epoch TYPE timestamp VALUE '19700101000000'. + DATA lv_time TYPE timestamp. + + GET TIME STAMP FIELD lv_time. + + rv_time = cl_abap_tstmp=>subtract( + tstmp1 = lv_time + tstmp2 = lc_epoch ). + + rv_time = rv_time - 31536000. + ENDMETHOD. + METHOD get_unix. +* returns seconds since Unix epoch, including timezone indicator + + CONSTANTS lc_epoch TYPE timestamp VALUE '19700101000000'. + DATA lv_time TYPE timestamp. + DATA lv_seconds TYPE i. + + GET TIME STAMP FIELD lv_time. + + lv_seconds = cl_abap_tstmp=>subtract( + tstmp1 = lv_time + tstmp2 = lc_epoch ). + + rv_time = lv_seconds. + CONDENSE rv_time. + rv_time+11 = '+000000'. + + ENDMETHOD. + METHOD get_utc. + + CONSTANTS lc_epoch TYPE d VALUE '19700101'. + + DATA: lv_i TYPE i, + lv_utcdiff TYPE t, + lv_utcsign TYPE c LENGTH 1. + lv_i = iv_unix(10). + lv_utcsign = iv_unix+11. + lv_utcdiff = iv_unix+12. + + " GMT + time-zone + CASE lv_utcsign. + WHEN '+'. + lv_i = lv_i + lv_utcdiff. + WHEN '-'. + lv_i = lv_i - lv_utcdiff. + ENDCASE. + + ev_time = lv_i MOD 86400. + lv_i = lv_i - ev_time. + lv_i = lv_i / 86400. + ev_date = lv_i + lc_epoch. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_git_tag IMPLEMENTATION. + METHOD add_peel. + + rv_text = iv_text && zif_abapgit_git_definitions=>c_git_branch-peel. + + ENDMETHOD. + METHOD add_tag_prefix. + + rv_text = zif_abapgit_git_definitions=>c_git_branch-tags_prefix && iv_text. + + ENDMETHOD. + METHOD remove_peel. + + rv_text = iv_text. + + REPLACE zif_abapgit_git_definitions=>c_git_branch-peel IN rv_text WITH ''. + + ENDMETHOD. + METHOD remove_tag_prefix. + + rv_text = iv_text. + + REPLACE FIRST OCCURRENCE OF zif_abapgit_git_definitions=>c_git_branch-tags_prefix + IN rv_text + WITH ''. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_git_porcelain IMPLEMENTATION. + METHOD build_trees. + + DATA: lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt, + ls_tree LIKE LINE OF rt_trees, + lv_len TYPE i, + lt_folders TYPE ty_folders_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_folders, + LIKE LINE OF lt_nodes, + LIKE LINE OF lt_folders, + LIKE LINE OF it_expanded. + lt_folders = find_folders( it_expanded ). + +* start with the deepest folders + SORT lt_folders BY count DESCENDING. + + LOOP AT lt_folders ASSIGNING . + CLEAR lt_nodes. + +* files + LOOP AT it_expanded ASSIGNING USING KEY path_name WHERE path = -path. + APPEND INITIAL LINE TO lt_nodes ASSIGNING . + -chmod = -chmod. + -name = -name. + -sha1 = -sha1. + ENDLOOP. + +* folders + LOOP AT lt_folders ASSIGNING WHERE count = -count + 1. + lv_len = strlen( -path ). + IF strlen( -path ) > lv_len AND -path(lv_len) = -path. + APPEND INITIAL LINE TO lt_nodes ASSIGNING . + -chmod = zif_abapgit_git_definitions=>c_chmod-dir. + +* extract folder name, this can probably be done easier using regular expressions + -name = -path+lv_len. + lv_len = strlen( -name ) - 1. + -name = -name(lv_len). + + -sha1 = -sha1. + ENDIF. + ENDLOOP. + + CLEAR ls_tree. + ls_tree-path = -path. + ls_tree-data = zcl_abapgit_git_pack=>encode_tree( lt_nodes ). + ls_tree-sha1 = zcl_abapgit_hash=>sha1_tree( ls_tree-data ). + APPEND ls_tree TO rt_trees. + + -sha1 = ls_tree-sha1. + ENDLOOP. + + ENDMETHOD. + METHOD create_annotated_tag. + + DATA: lv_tag TYPE xstring, + lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt, + lv_pack TYPE xstring, + ls_object LIKE LINE OF lt_objects, + ls_tag TYPE zcl_abapgit_git_pack=>ty_tag, + lv_new_tag_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1. + +* new tag + ls_tag-object = is_tag-sha1. + ls_tag-type = zif_abapgit_git_definitions=>c_type-commit. + ls_tag-tag = is_tag-name. + ls_tag-tagger_name = is_tag-tagger_name. + ls_tag-tagger_email = is_tag-tagger_email. + ls_tag-message = is_tag-message + && |{ cl_abap_char_utilities=>newline }| + && |{ cl_abap_char_utilities=>newline }| + && is_tag-body. + + lv_tag = zcl_abapgit_git_pack=>encode_tag( ls_tag ). + + lv_new_tag_sha1 = zcl_abapgit_hash=>sha1_tag( lv_tag ). + + ls_object-sha1 = lv_new_tag_sha1. + ls_object-type = zif_abapgit_git_definitions=>c_type-tag. + ls_object-data = lv_tag. + ls_object-index = 1. + APPEND ls_object TO lt_objects. + + lv_pack = zcl_abapgit_git_pack=>encode( lt_objects ). + + zcl_abapgit_git_transport=>receive_pack( + iv_url = iv_url + iv_old = c_zero + iv_new = lv_new_tag_sha1 + iv_branch_name = is_tag-name + iv_pack = lv_pack ). + + ENDMETHOD. + METHOD create_branch. + + IF iv_name CS ` `. + zcx_abapgit_exception=>raise( 'Branch name cannot contain blank spaces' ). + ENDIF. + + zcl_abapgit_git_transport=>receive_pack( + iv_url = iv_url + iv_old = c_zero + iv_new = iv_from + iv_branch_name = iv_name + iv_pack = empty_packfile( ) ). + + ENDMETHOD. + METHOD create_lightweight_tag. + + zcl_abapgit_git_transport=>receive_pack( + iv_url = iv_url + iv_old = c_zero + iv_new = is_tag-sha1 + iv_branch_name = is_tag-name + iv_pack = empty_packfile( ) ). + + ENDMETHOD. + METHOD create_tag. + + IF is_tag-name CS ` `. + zcx_abapgit_exception=>raise( 'Tag name cannot contain blank spaces' ). + ENDIF. + + CASE is_tag-type. + WHEN zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. + + create_annotated_tag( + is_tag = is_tag + iv_url = iv_url ). + + WHEN zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. + + create_lightweight_tag( + is_tag = is_tag + iv_url = iv_url ). + + WHEN OTHERS. + + zcx_abapgit_exception=>raise( |Invalid tag type: { is_tag-type }| ). + + ENDCASE. + + ENDMETHOD. + METHOD delete_annotated_tag. + + DATA: + li_branches TYPE REF TO zif_abapgit_git_branch_list, + lv_tag TYPE string, + ls_tag TYPE zif_abapgit_git_definitions=>ty_git_branch, + lt_tags TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. + + " For annotated tags, find the correct commit + li_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). + lt_tags = li_branches->get_tags_only( ). + lv_tag = zcl_abapgit_git_tag=>remove_peel( is_tag-name ). + + READ TABLE lt_tags INTO ls_tag WITH KEY name_key COMPONENTS name = lv_tag. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Annotated tag { lv_tag } not found| ). + ENDIF. + + zcl_abapgit_git_transport=>receive_pack( + iv_url = iv_url + iv_old = ls_tag-sha1 + iv_new = c_zero + iv_branch_name = ls_tag-name ). + + ENDMETHOD. + METHOD delete_branch. + + zcl_abapgit_git_transport=>receive_pack( + iv_url = iv_url + iv_old = is_branch-sha1 + iv_new = c_zero + iv_branch_name = is_branch-name ). + + ENDMETHOD. + METHOD delete_lightweight_tag. + + zcl_abapgit_git_transport=>receive_pack( + iv_url = iv_url + iv_old = is_tag-sha1 + iv_new = c_zero + iv_branch_name = is_tag-name ). + + ENDMETHOD. + METHOD delete_tag. + + IF is_tag-name CS zif_abapgit_git_definitions=>c_git_branch-peel. + + delete_annotated_tag( + is_tag = is_tag + iv_url = iv_url ). + + ELSE. + + delete_lightweight_tag( + is_tag = is_tag + iv_url = iv_url ). + + ENDIF. + + ENDMETHOD. + METHOD empty_packfile. + + " For avoiding "client MUST send an empty packfile" error + " https://github.com/git/git/blob/master/Documentation/gitprotocol-pack.txt#L595-L599 + + DATA lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + + rv_pack = zcl_abapgit_git_pack=>encode( lt_objects ). + + ENDMETHOD. + METHOD find_folders. + + DATA: lt_paths TYPE TABLE OF string, + lv_split TYPE string, + lv_path TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF rt_folders, + LIKE LINE OF rt_folders, + LIKE LINE OF it_expanded. + LOOP AT it_expanded ASSIGNING . + READ TABLE rt_folders WITH KEY path = -path TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO rt_folders ASSIGNING . + -path = -path. + ENDIF. + ENDLOOP. + +* add empty folders + LOOP AT rt_folders ASSIGNING . + SPLIT -path AT '/' INTO TABLE lt_paths. + + CLEAR lv_path. + LOOP AT lt_paths INTO lv_split. + CONCATENATE lv_path lv_split '/' INTO lv_path. + READ TABLE rt_folders WITH KEY path = lv_path TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO rt_folders ASSIGNING . + -path = lv_path. + ENDIF. + ENDLOOP. + ENDLOOP. + + LOOP AT rt_folders ASSIGNING . + FIND ALL OCCURRENCES OF '/' IN -path MATCH COUNT -count. + ENDLOOP. + + ENDMETHOD. + METHOD full_tree. + + DATA: ls_object LIKE LINE OF it_objects, + ls_commit TYPE zcl_abapgit_git_pack=>ty_commit. + + READ TABLE it_objects INTO ls_object + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-commit + sha1 = iv_parent. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'commit not found' ). + ENDIF. + ls_commit = zcl_abapgit_git_pack=>decode_commit( ls_object-data ). + + rt_expanded = walk_tree( it_objects = it_objects + iv_tree = ls_commit-tree + iv_base = '/' ). + + ENDMETHOD. + METHOD pull. + + DATA: ls_object TYPE zif_abapgit_definitions=>ty_object, + ls_commit TYPE zcl_abapgit_git_pack=>ty_commit. + + READ TABLE it_objects INTO ls_object + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-commit + sha1 = iv_commit. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Commit/Branch not found.' ). + ENDIF. + + ls_commit = zcl_abapgit_git_pack=>decode_commit( ls_object-data ). + + walk( EXPORTING it_objects = it_objects + iv_sha1 = ls_commit-tree + iv_path = '/' + CHANGING ct_files = rt_files ). + + ENDMETHOD. + METHOD pull_by_branch. + + zcl_abapgit_git_transport=>upload_pack_by_branch( + EXPORTING + iv_url = iv_url + iv_branch_name = iv_branch_name + iv_deepen_level = iv_deepen_level + IMPORTING + et_objects = rs_result-objects + ev_branch = rs_result-commit ). + + rs_result-files = pull( iv_commit = rs_result-commit + it_objects = rs_result-objects ). + + ENDMETHOD. + METHOD pull_by_commit. + + zcl_abapgit_git_transport=>upload_pack_by_commit( + EXPORTING + iv_url = iv_url + iv_hash = iv_commit_hash + iv_deepen_level = iv_deepen_level + IMPORTING + et_objects = rs_result-objects + ev_commit = rs_result-commit ). + + rs_result-files = pull( iv_commit = rs_result-commit + it_objects = rs_result-objects ). + + ENDMETHOD. + METHOD push. + + DATA: lt_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt, + lt_blobs TYPE zif_abapgit_git_definitions=>ty_files_tt, + lv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + lv_new_tree TYPE zif_abapgit_git_definitions=>ty_sha1, + lt_trees TYPE ty_trees_tt, + lt_stage TYPE zif_abapgit_definitions=>ty_stage_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_stage, + LIKE LINE OF rs_result-updated_files, + LIKE LINE OF lt_expanded. + + lt_expanded = full_tree( it_objects = it_old_objects + iv_parent = iv_parent ). + + lt_stage = io_stage->get_all( ). + LOOP AT lt_stage ASSIGNING . + + " Save file ref to updated files table + APPEND INITIAL LINE TO rs_result-updated_files ASSIGNING . + MOVE-CORRESPONDING -file TO . + + CASE -method. + WHEN zif_abapgit_definitions=>c_method-add. + + APPEND -file TO lt_blobs. + + READ TABLE lt_expanded ASSIGNING WITH TABLE KEY path_name COMPONENTS + name = -file-filename + path = -file-path. + IF sy-subrc <> 0. " new files + APPEND INITIAL LINE TO lt_expanded ASSIGNING . + -name = -file-filename. + -path = -file-path. + -chmod = zif_abapgit_git_definitions=>c_chmod-file. + ENDIF. + + lv_sha1 = zcl_abapgit_hash=>sha1_blob( -file-data ). + IF -sha1 <> lv_sha1. + -sha1 = lv_sha1. + ENDIF. + + -sha1 = lv_sha1. "New sha1 + + WHEN zif_abapgit_definitions=>c_method-rm. + READ TABLE lt_expanded ASSIGNING WITH TABLE KEY path_name COMPONENTS + name = -file-filename + path = -file-path. + ASSERT sy-subrc = 0. + + CLEAR -sha1. " Mark as deleted + CLEAR -sha1. " Mark as deleted + + WHEN OTHERS. + zcx_abapgit_exception=>raise( 'stage method not supported, todo' ). + ENDCASE. + ENDLOOP. + + DELETE lt_expanded WHERE sha1 IS INITIAL. + + lt_trees = build_trees( lt_expanded ). + + receive_pack_push( + EXPORTING + is_comment = is_comment + it_trees = lt_trees + iv_branch_name = iv_branch_name + iv_url = iv_url + iv_parent = iv_parent + iv_parent2 = io_stage->get_merge_source( ) + it_blobs = lt_blobs + IMPORTING + ev_new_commit = rs_result-branch + et_new_objects = rs_result-new_objects + ev_new_tree = lv_new_tree ). + + IF rs_result IS SUPPLIED. + APPEND LINES OF it_old_objects TO rs_result-new_objects. + + walk( EXPORTING it_objects = rs_result-new_objects + iv_sha1 = lv_new_tree + iv_path = '/' + CHANGING ct_files = rs_result-new_files ). + ENDIF. + + ENDMETHOD. + METHOD receive_pack_push. + + DATA: lv_time TYPE zcl_abapgit_git_time=>ty_unixtime, + lv_commit TYPE xstring, + lv_pack TYPE xstring, + ls_object LIKE LINE OF et_new_objects, + ls_commit TYPE zcl_abapgit_git_pack=>ty_commit, + lv_uindex TYPE sy-index. + + FIELD-SYMBOLS: LIKE LINE OF it_trees, + LIKE LINE OF it_blobs. + lv_time = zcl_abapgit_git_time=>get_unix( ). + + READ TABLE it_trees ASSIGNING WITH KEY path = '/'. + ASSERT sy-subrc = 0. + +* new commit + ls_commit-committer = |{ is_comment-committer-name + } <{ is_comment-committer-email }> { lv_time }|. + IF is_comment-author-name IS NOT INITIAL. + ls_commit-author = |{ is_comment-author-name + } <{ is_comment-author-email }> { lv_time }|. + ELSE. + ls_commit-author = ls_commit-committer. + ENDIF. + + ls_commit-tree = -sha1. + ls_commit-parent = iv_parent. + ls_commit-parent2 = iv_parent2. + ls_commit-body = is_comment-comment. + lv_commit = zcl_abapgit_git_pack=>encode_commit( ls_commit ). + + ls_object-sha1 = zcl_abapgit_hash=>sha1_commit( lv_commit ). + ls_object-type = zif_abapgit_git_definitions=>c_type-commit. + ls_object-data = lv_commit. + APPEND ls_object TO et_new_objects. + + LOOP AT it_trees ASSIGNING . + CLEAR ls_object. + ls_object-sha1 = -sha1. + + READ TABLE et_new_objects + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-tree + sha1 = ls_object-sha1 + TRANSPORTING NO FIELDS. + IF sy-subrc = 0. +* two identical trees added at the same time, only add one to the pack + CONTINUE. + ENDIF. + + ls_object-type = zif_abapgit_git_definitions=>c_type-tree. + ls_object-data = -data. + lv_uindex = lv_uindex + 1. + ls_object-index = lv_uindex. + APPEND ls_object TO et_new_objects. + ENDLOOP. + + LOOP AT it_blobs ASSIGNING . + CLEAR ls_object. + ls_object-sha1 = zcl_abapgit_hash=>sha1_blob( -data ). + + READ TABLE et_new_objects + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-blob + sha1 = ls_object-sha1 + TRANSPORTING NO FIELDS. + IF sy-subrc = 0. +* two identical files added at the same time, only add one blob to the pack + CONTINUE. + ENDIF. + + ls_object-type = zif_abapgit_git_definitions=>c_type-blob. +* note -data can be empty, #1857 allow empty files - some more checks needed? + ls_object-data = -data. + lv_uindex = lv_uindex + 1. + ls_object-index = lv_uindex. + APPEND ls_object TO et_new_objects. + ENDLOOP. + + lv_pack = zcl_abapgit_git_pack=>encode( et_new_objects ). + + ev_new_commit = zcl_abapgit_hash=>sha1_commit( lv_commit ). + + zcl_abapgit_git_transport=>receive_pack( + iv_url = iv_url + iv_old = iv_parent + iv_new = ev_new_commit + iv_branch_name = iv_branch_name + iv_pack = lv_pack ). + + ev_new_tree = ls_commit-tree. + + ENDMETHOD. + METHOD walk. + + DATA: lv_path TYPE string, + ls_file LIKE LINE OF ct_files, + lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt. + + FIELD-SYMBOLS: LIKE LINE OF it_objects, + LIKE LINE OF it_objects, + LIKE LINE OF lt_nodes. + READ TABLE it_objects ASSIGNING + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-tree + sha1 = iv_sha1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Walk, tree not found' ). + ENDIF. + + lt_nodes = zcl_abapgit_git_pack=>decode_tree( -data ). + + LOOP AT lt_nodes ASSIGNING . + IF -chmod = zif_abapgit_git_definitions=>c_chmod-file. + READ TABLE it_objects ASSIGNING + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-blob + sha1 = -sha1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Walk, blob not found' ). + ENDIF. + + CLEAR ls_file. + ls_file-path = iv_path. + ls_file-filename = -name. + ls_file-data = -data. + ls_file-sha1 = -sha1. + APPEND ls_file TO ct_files. + ENDIF. + ENDLOOP. + + LOOP AT lt_nodes ASSIGNING WHERE chmod = zif_abapgit_git_definitions=>c_chmod-dir. + CONCATENATE iv_path -name '/' INTO lv_path. + + walk( EXPORTING it_objects = it_objects + iv_sha1 = -sha1 + iv_path = lv_path + CHANGING ct_files = ct_files ). + ENDLOOP. + + ENDMETHOD. + METHOD walk_tree. + + DATA: ls_object LIKE LINE OF it_objects, + lt_expanded LIKE rt_expanded, + lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt. + + FIELD-SYMBOLS: LIKE LINE OF rt_expanded, + LIKE LINE OF lt_nodes. + READ TABLE it_objects INTO ls_object + WITH KEY type COMPONENTS + type = zif_abapgit_git_definitions=>c_type-tree + sha1 = iv_tree. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'tree not found' ). + ENDIF. + lt_nodes = zcl_abapgit_git_pack=>decode_tree( ls_object-data ). + + LOOP AT lt_nodes ASSIGNING . + CASE -chmod. + WHEN zif_abapgit_git_definitions=>c_chmod-file + OR zif_abapgit_git_definitions=>c_chmod-executable + OR zif_abapgit_git_definitions=>c_chmod-symbolic_link + OR zif_abapgit_git_definitions=>c_chmod-submodule. + APPEND INITIAL LINE TO rt_expanded ASSIGNING . + -path = iv_base. + -name = -name. + -sha1 = -sha1. + -chmod = -chmod. + WHEN zif_abapgit_git_definitions=>c_chmod-dir. + lt_expanded = walk_tree( + it_objects = it_objects + iv_tree = -sha1 + iv_base = iv_base && -name && '/' ). + APPEND LINES OF lt_expanded TO rt_expanded. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |walk_tree: unknown chmod { -chmod }| ). + ENDCASE. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_git_pack IMPLEMENTATION. + METHOD decode. + + DATA: lv_x TYPE x, + lv_data TYPE xstring, + lv_type TYPE c LENGTH 6, + lv_zlib TYPE x LENGTH 2, + lv_objects TYPE i, + lv_len TYPE i, + lv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + lv_ref_delta TYPE zif_abapgit_git_definitions=>ty_sha1, + lv_compressed_len TYPE i, + lv_compressed TYPE xstring, + lv_decompressed TYPE xstring, + lv_decompress_len TYPE i, + lv_xstring TYPE xstring, + lv_expected TYPE i, + ls_object LIKE LINE OF rt_objects, + lv_uindex TYPE sy-index. + lv_data = iv_data. + +* header + IF xstrlen( lv_data ) < 4. + zcx_abapgit_exception=>raise( |Unexpected pack header, short reply| ). + ENDIF. + + IF lv_data(4) <> c_pack_start. + zcx_abapgit_exception=>raise( |Unexpected pack header, { lv_data(4) }| ). + ENDIF. + lv_data = lv_data+4. + +* version + IF lv_data(4) <> c_version. + zcx_abapgit_exception=>raise( |Version not supported, { lv_data(4) }| ). + ENDIF. + lv_data = lv_data+4. + +* number of objects + lv_xstring = lv_data(4). + lv_objects = zcl_abapgit_convert=>xstring_to_int( lv_xstring ). + lv_data = lv_data+4. + DO lv_objects TIMES. + + lv_uindex = sy-index. + + lv_x = lv_data(1). + lv_type = get_type( lv_x ). + + get_length( IMPORTING ev_length = lv_expected + CHANGING cv_data = lv_data ). + + IF lv_type = zif_abapgit_git_definitions=>c_type-ref_d. + lv_ref_delta = lv_data(20). + lv_data = lv_data+20. + ENDIF. + +* strip header, '789C', CMF + FLG + lv_zlib = lv_data(2). + IF lv_zlib <> c_zlib AND lv_zlib <> c_zlib_hmm. + zcx_abapgit_exception=>raise( |Unexpected zlib header| ). + ENDIF. + lv_data = lv_data+2. + +******************************* + + IF lv_zlib = c_zlib. + cl_abap_gzip=>decompress_binary( + EXPORTING + gzip_in = lv_data + IMPORTING + raw_out = lv_decompressed + raw_out_len = lv_decompress_len ). + + IF lv_expected <> lv_decompress_len. + zcx_abapgit_exception=>raise( |Decompression failed| ). + ENDIF. + + cl_abap_gzip=>compress_binary( + EXPORTING + raw_in = lv_decompressed + IMPORTING + gzip_out = lv_compressed + gzip_out_len = lv_compressed_len ). + + IF xstrlen( lv_data ) <= lv_compressed_len OR + lv_compressed(lv_compressed_len) <> lv_data(lv_compressed_len). + "Lets try with zlib before error in out for good + "This fixes issues with TFS 2017 and visualstudio.com Git repos + zlib_decompress( CHANGING cv_data = lv_data + cv_decompressed = lv_decompressed ). + ELSE. + lv_data = lv_data+lv_compressed_len. + ENDIF. + + ELSEIF lv_zlib = c_zlib_hmm. +* cl_abap_gzip compression works for header '789C', but does not work for +* '7801', call custom implementation of DEFLATE algorithm. +* The custom implementation could handle both, but most likely the kernel +* implementation runs faster than the custom ABAP. + zlib_decompress( CHANGING cv_data = lv_data + cv_decompressed = lv_decompressed ). + ENDIF. + + CLEAR ls_object. + ls_object-adler32 = lv_data(4). + lv_data = lv_data+4. " skip adler checksum + + IF lv_type = zif_abapgit_git_definitions=>c_type-ref_d. + ls_object-sha1 = lv_ref_delta. + TRANSLATE ls_object-sha1 TO LOWER CASE. + ELSE. + ls_object-sha1 = zcl_abapgit_hash=>sha1( + iv_type = lv_type + iv_data = lv_decompressed ). + ENDIF. + ls_object-type = lv_type. + ls_object-data = lv_decompressed. + ls_object-index = lv_uindex. + APPEND ls_object TO rt_objects. + ENDDO. + +* check SHA1 at end of pack + lv_len = xstrlen( iv_data ) - 20. + lv_xstring = iv_data(lv_len). + lv_sha1 = zcl_abapgit_hash=>sha1_raw( lv_xstring ). + IF to_upper( lv_sha1 ) <> lv_data. + zcx_abapgit_exception=>raise( |SHA1 at end of pack doesn't match| ). + ENDIF. + + zcl_abapgit_git_delta=>decode_deltas( CHANGING ct_objects = rt_objects ). + + ENDMETHOD. + METHOD decode_commit. + + DATA: lv_string TYPE string, + lv_word TYPE string, + lv_offset TYPE i, + lv_length TYPE i, + lv_length_gpgsig TYPE i, + lv_trash TYPE string ##NEEDED, + lt_string TYPE TABLE OF string. + + FIELD-SYMBOLS: LIKE LINE OF lt_string. + lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( iv_data ). + + SPLIT lv_string AT cl_abap_char_utilities=>newline INTO TABLE lt_string. + + LOOP AT lt_string ASSIGNING . + lv_length = strlen( ) + 1. + lv_string = lv_string+lv_length. + + SPLIT AT space INTO lv_word lv_trash. + CASE lv_word. + WHEN 'tree'. + rs_commit-tree = +5. + WHEN 'parent'. + IF rs_commit-parent IS INITIAL. + rs_commit-parent = +7. + ELSE. + rs_commit-parent2 = +7. + ENDIF. + WHEN 'author'. + rs_commit-author = +7. + WHEN 'committer'. + rs_commit-committer = +10. + EXIT. " current loop + WHEN OTHERS. + ASSERT 1 = 0. + ENDCASE. + + ENDLOOP. + + lv_length = strlen( lv_string ). + IF lv_length >= 6 AND lv_string+0(6) = 'gpgsig'. + FIND REGEX |-----END PGP SIGNATURE-----[[:space:]]+| + IN lv_string + MATCH OFFSET lv_offset + MATCH LENGTH lv_length. + lv_length = lv_length - 1. + lv_length_gpgsig = lv_offset + lv_length - 7. + lv_length = lv_offset + lv_length. + rs_commit-gpgsig = lv_string+7(lv_length_gpgsig). + lv_string = lv_string+lv_length. + ENDIF. + + rs_commit-body = lv_string+1. + + IF rs_commit-author IS INITIAL + OR rs_commit-committer IS INITIAL + OR rs_commit-tree IS INITIAL. + zcx_abapgit_exception=>raise( |multiple parents? not supported| ). + ENDIF. + + ENDMETHOD. + METHOD decode_tag. + + DATA: lv_string TYPE string, + lv_word TYPE string, + lv_trash TYPE string ##NEEDED, + lt_string TYPE TABLE OF string. + + FIELD-SYMBOLS: LIKE LINE OF lt_string. + lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( iv_data ). + + SPLIT lv_string AT cl_abap_char_utilities=>newline INTO TABLE lt_string. + + LOOP AT lt_string ASSIGNING . + + SPLIT AT space INTO lv_word lv_trash. + + CASE lv_word. + WHEN 'object'. + rs_tag-object = lv_trash. + WHEN 'type'. + rs_tag-type = lv_trash. + WHEN 'tag'. + rs_tag-tag = lv_trash. + WHEN 'tagger'. + + FIND FIRST OCCURRENCE OF REGEX `(.*)<(.*)>` + IN lv_trash + SUBMATCHES rs_tag-tagger_name + rs_tag-tagger_email. + + rs_tag-tagger_name = condense( rs_tag-tagger_name ). + + WHEN ''. + " ignore blank lines + CONTINUE. + WHEN OTHERS. + + " these are the non empty line which don't start with a key word + " the first one is the message, the rest are cumulated to the body + + IF rs_tag-message IS INITIAL. + rs_tag-message = . + ELSE. + + IF rs_tag-body IS NOT INITIAL. + rs_tag-body = rs_tag-body && cl_abap_char_utilities=>newline. + ENDIF. + + rs_tag-body = rs_tag-body && . + + ENDIF. + + ENDCASE. + + ENDLOOP. + + ENDMETHOD. + METHOD decode_tree. + + CONSTANTS: lc_sha_length TYPE i VALUE 20, + lc_null TYPE x VALUE '00'. + + DATA: lv_xstring TYPE xstring, + lv_chmod TYPE zif_abapgit_git_definitions=>ty_chmod, + lv_name TYPE string, + lv_string TYPE string, + lv_len TYPE i, + lv_offset TYPE i, + lv_cursor TYPE i, + lv_match TYPE i, + ls_node TYPE ty_node. + DO. + FIND FIRST OCCURRENCE OF lc_null IN SECTION OFFSET lv_cursor OF iv_data + IN BYTE MODE MATCH OFFSET lv_match. + IF sy-subrc <> 0. + EXIT. + ENDIF. + + lv_len = lv_match - lv_cursor. + lv_xstring = iv_data+lv_cursor(lv_len). + + lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xstring ). + SPLIT lv_string AT space INTO lv_chmod lv_name. + + ls_node-chmod = lv_chmod. + IF ls_node-chmod <> zif_abapgit_git_definitions=>c_chmod-dir + AND ls_node-chmod <> zif_abapgit_git_definitions=>c_chmod-file + AND ls_node-chmod <> zif_abapgit_git_definitions=>c_chmod-symbolic_link + AND ls_node-chmod <> zif_abapgit_git_definitions=>c_chmod-executable + AND ls_node-chmod <> zif_abapgit_git_definitions=>c_chmod-submodule. + zcx_abapgit_exception=>raise( |Unknown chmod { ls_node-chmod }| ). + ENDIF. + + lv_offset = lv_match + 1. + ls_node-name = lv_name. + ls_node-sha1 = iv_data+lv_offset(lc_sha_length). + TRANSLATE ls_node-sha1 TO LOWER CASE. + APPEND ls_node TO rt_nodes. + + lv_cursor = lv_match + 1 + lc_sha_length. + ENDDO. + + ENDMETHOD. + + METHOD encode. + + DATA: lv_sha1 TYPE x LENGTH 20, + lv_adler32 TYPE zif_abapgit_git_definitions=>ty_adler32, + lv_compressed TYPE xstring, + lv_xstring TYPE xstring, + li_progress TYPE REF TO zif_abapgit_progress, + lv_objects_total TYPE i. + + FIELD-SYMBOLS: LIKE LINE OF it_objects. + rv_data = c_pack_start. + + CONCATENATE rv_data c_version INTO rv_data IN BYTE MODE. + + lv_xstring = zcl_abapgit_convert=>int_to_xstring4( lines( it_objects ) ). + CONCATENATE rv_data lv_xstring INTO rv_data IN BYTE MODE. + + lv_objects_total = lines( it_objects ). + + li_progress = zcl_abapgit_progress=>get_instance( lv_objects_total ). + + LOOP AT it_objects ASSIGNING . + li_progress->show( + iv_current = sy-tabix + iv_text = |Encoding objects ( { sy-tabix } of { lv_objects_total } )| ). + + lv_xstring = type_and_length( + iv_type = -type + iv_length = xstrlen( -data ) ). + CONCATENATE rv_data lv_xstring INTO rv_data IN BYTE MODE. + + cl_abap_gzip=>compress_binary( + EXPORTING + raw_in = -data + IMPORTING + gzip_out = lv_compressed ). + + CONCATENATE rv_data c_zlib lv_compressed INTO rv_data IN BYTE MODE. + + IF NOT -adler32 IS INITIAL. + lv_adler32 = -adler32. + ELSE. + lv_adler32 = zcl_abapgit_hash=>adler32( -data ). + ENDIF. + CONCATENATE rv_data lv_adler32 INTO rv_data IN BYTE MODE. + + ENDLOOP. + + lv_sha1 = to_upper( zcl_abapgit_hash=>sha1_raw( rv_data ) ). + CONCATENATE rv_data lv_sha1 INTO rv_data IN BYTE MODE. + + ENDMETHOD. + METHOD encode_commit. + + DATA: lv_string TYPE string, + lv_tmp TYPE string, + lv_tree_lower TYPE string, + lv_parent_lower TYPE string. + lv_tree_lower = is_commit-tree. + TRANSLATE lv_tree_lower TO LOWER CASE. + + lv_string = ''. + + CONCATENATE 'tree' lv_tree_lower INTO lv_tmp SEPARATED BY space. + CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. + + IF NOT is_commit-parent IS INITIAL. + lv_parent_lower = is_commit-parent. + TRANSLATE lv_parent_lower TO LOWER CASE. + + CONCATENATE 'parent' lv_parent_lower + INTO lv_tmp SEPARATED BY space. + CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. + ENDIF. + + IF NOT is_commit-parent2 IS INITIAL. + lv_parent_lower = is_commit-parent2. + TRANSLATE lv_parent_lower TO LOWER CASE. + + CONCATENATE 'parent' lv_parent_lower + INTO lv_tmp SEPARATED BY space. + CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. + ENDIF. + + CONCATENATE 'author' is_commit-author + INTO lv_tmp SEPARATED BY space. + CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. + + CONCATENATE 'committer' is_commit-committer + INTO lv_tmp SEPARATED BY space. + CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. + + IF NOT is_commit-gpgsig IS INITIAL. + CONCATENATE 'gpgsig' is_commit-gpgsig + INTO lv_tmp SEPARATED BY space. + CONCATENATE lv_string lv_tmp INTO lv_string. + ENDIF. + + CONCATENATE lv_string cl_abap_char_utilities=>newline is_commit-body INTO lv_string. + + rv_data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). + + ENDMETHOD. + METHOD encode_tag. + + DATA: lv_string TYPE string, + lv_time TYPE zcl_abapgit_git_time=>ty_unixtime. + + lv_time = zcl_abapgit_git_time=>get_unix( ). + + lv_string = |object { is_tag-object }{ cl_abap_char_utilities=>newline }| + && |type { is_tag-type }{ cl_abap_char_utilities=>newline }| + && |tag { zcl_abapgit_git_tag=>remove_tag_prefix( is_tag-tag ) }{ cl_abap_char_utilities=>newline }| + && |tagger { is_tag-tagger_name } <{ is_tag-tagger_email }> { lv_time }| + && |{ cl_abap_char_utilities=>newline }| + && |{ cl_abap_char_utilities=>newline }| + && |{ is_tag-message }|. + + rv_data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). + + ENDMETHOD. + METHOD encode_tree. + + CONSTANTS: lc_null TYPE x VALUE '00'. + + DATA: lv_string TYPE string, + lt_nodes LIKE it_nodes, + lv_hex20 TYPE x LENGTH 20, + lv_xstring TYPE xstring. + + FIELD-SYMBOLS: LIKE LINE OF it_nodes. + lt_nodes = sort_tree( it_nodes ). + + LOOP AT lt_nodes ASSIGNING . + ASSERT NOT -chmod IS INITIAL. + ASSERT NOT -name IS INITIAL. + ASSERT NOT -sha1 IS INITIAL. + + CONCATENATE -chmod -name INTO lv_string SEPARATED BY space. + lv_xstring = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). + + lv_hex20 = to_upper( -sha1 ). + CONCATENATE rv_data lv_xstring lc_null lv_hex20 INTO rv_data IN BYTE MODE. + ENDLOOP. + + ENDMETHOD. + METHOD get_length. + +* https://github.com/git/git/blob/master/Documentation/technical/pack-format.txt + +* n-byte sizeN (as long as MSB is set, each 7-bit) +* size0..sizeN form 4+7+7+..+7 bit integer, size0 +* is the least significant part, and sizeN is the +* most significant part. + + DATA: lv_x TYPE x, + lv_length_bits TYPE string, + lv_bitbyte TYPE zif_abapgit_git_definitions=>ty_bitbyte. + lv_x = cv_data(1). + lv_bitbyte = zcl_abapgit_convert=>x_to_bitbyte( lv_x ). + + cv_data = cv_data+1. + lv_length_bits = lv_bitbyte+4. + + WHILE lv_bitbyte(1) <> '0'. + lv_x = cv_data(1). + lv_bitbyte = zcl_abapgit_convert=>x_to_bitbyte( lv_x ). + cv_data = cv_data+1. + CONCATENATE lv_bitbyte+1 lv_length_bits INTO lv_length_bits. + ENDWHILE. + + ev_length = zcl_abapgit_convert=>bitbyte_to_int( lv_length_bits ). + + ENDMETHOD. + METHOD get_type. + + CONSTANTS: lc_mask TYPE x VALUE 112. + DATA: lv_xtype TYPE x. + + lv_xtype = iv_x BIT-AND lc_mask. + + CASE lv_xtype. + WHEN 16. + rv_type = zif_abapgit_git_definitions=>c_type-commit. + WHEN 32. + rv_type = zif_abapgit_git_definitions=>c_type-tree. + WHEN 48. + rv_type = zif_abapgit_git_definitions=>c_type-blob. + WHEN 64. + rv_type = zif_abapgit_git_definitions=>c_type-tag. + WHEN 112. + rv_type = zif_abapgit_git_definitions=>c_type-ref_d. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Todo, unknown git pack type| ). + ENDCASE. + + ENDMETHOD. + METHOD sort_tree. + + TYPES: BEGIN OF ty_sort, + sort TYPE string, + node TYPE ty_node, + END OF ty_sort. + + DATA: lt_sort TYPE STANDARD TABLE OF ty_sort WITH DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF lt_sort, + LIKE LINE OF it_nodes. + LOOP AT it_nodes ASSIGNING . + APPEND INITIAL LINE TO lt_sort ASSIGNING . + IF -chmod = zif_abapgit_git_definitions=>c_chmod-dir. + CONCATENATE -name '/' INTO -sort. + ELSE. + -sort = -name. + ENDIF. + -node = . + ENDLOOP. + +* following has to be done, or unpack will fail on server side + SORT lt_sort BY sort ASCENDING. + + LOOP AT lt_sort ASSIGNING . + APPEND -node TO rt_nodes. + ENDLOOP. + + ENDMETHOD. + METHOD type_and_length. + +* see http://stefan.saasen.me/articles/git-clone-in-haskell-from-the-bottom-up/#pack_file_objects + + DATA: lv_type TYPE i, + lv_length TYPE i, + lv_hex TYPE x LENGTH 1. + CASE iv_type. + WHEN zif_abapgit_git_definitions=>c_type-commit. + lv_type = 16. + WHEN zif_abapgit_git_definitions=>c_type-tree. + lv_type = 32. + WHEN zif_abapgit_git_definitions=>c_type-blob. + lv_type = 48. + WHEN zif_abapgit_git_definitions=>c_type-tag. + lv_type = 64. + WHEN zif_abapgit_git_definitions=>c_type-ref_d. + lv_type = 112. + WHEN OTHERS. + zcx_abapgit_exception=>raise( |Unexpected object type while encoding pack| ). + ENDCASE. + + lv_length = iv_length. + +* first byte + IF lv_length > 15. + lv_hex = 128. + ENDIF. + lv_hex = lv_hex + lv_type + lv_length MOD 16. + rv_xstring = lv_hex. + lv_length = lv_length DIV 16. + +* subsequent bytes + WHILE lv_length >= 128. + lv_hex = 128 + lv_length MOD 128. + CONCATENATE rv_xstring lv_hex INTO rv_xstring IN BYTE MODE. + lv_length = lv_length DIV 128. + ENDWHILE. + +* last byte + IF lv_length > 0. + lv_hex = lv_length. + CONCATENATE rv_xstring lv_hex INTO rv_xstring IN BYTE MODE. + ENDIF. + + ENDMETHOD. + METHOD zlib_decompress. + + DATA: ls_data TYPE zcl_abapgit_zlib=>ty_decompress, + lv_compressed_len TYPE i, + lv_adler32 TYPE zif_abapgit_git_definitions=>ty_adler32. + ls_data = zcl_abapgit_zlib=>decompress( cv_data ). + lv_compressed_len = ls_data-compressed_len. + cv_decompressed = ls_data-raw. + + IF lv_compressed_len IS INITIAL. + zcx_abapgit_exception=>raise( |Decompression failed :o/| ). + ENDIF. + + cv_data = cv_data+lv_compressed_len. + + lv_adler32 = zcl_abapgit_hash=>adler32( cv_decompressed ). + IF cv_data(4) <> lv_adler32. + cv_data = cv_data+1. + ENDIF. + IF cv_data(4) <> lv_adler32. + cv_data = cv_data+1. + ENDIF. + IF cv_data(4) <> lv_adler32. + zcx_abapgit_exception=>raise( |Wrong Adler checksum| ). + ENDIF. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_git_factory IMPLEMENTATION. + + METHOD get_v2_porcelain. + IF gi_v2 IS INITIAL. + CREATE OBJECT gi_v2 TYPE zcl_abapgit_gitv2_porcelain. + ENDIF. + ri_v2 = gi_v2. + ENDMETHOD. + METHOD get_git_transport. + IF gi_git_transport IS INITIAL. + CREATE OBJECT gi_git_transport TYPE zcl_abapgit_git_transport. + ENDIF. + ri_git_transport = gi_git_transport. + ENDMETHOD. + +ENDCLASS. + +CLASS kHGwlatytwTSETnzZMKotffscEwAXR IMPLEMENTATION. + + METHOD constructor. + mv_data = iv_data. + mv_position = 0. + mv_length = xstrlen( mv_data ). + ENDMETHOD. + + METHOD eat_byte. + rv_x = mv_data+mv_position(1). + mv_position = mv_position + 1. + ENDMETHOD. + + METHOD eat_bytes. + rv_x = mv_data+mv_position(iv_length). + mv_position = mv_position + iv_length. + ENDMETHOD. + + METHOD has_data. + rv_data = boolc( mv_position < mv_length ). + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_git_delta IMPLEMENTATION. + + METHOD decode_deltas. + + DATA: ls_object LIKE LINE OF ct_objects, + li_progress TYPE REF TO zif_abapgit_progress, + lt_deltas LIKE ct_objects. + LOOP AT ct_objects INTO ls_object + USING KEY type + WHERE type = zif_abapgit_git_definitions=>c_type-ref_d. + INSERT ls_object INTO TABLE lt_deltas. + ENDLOOP. + + DELETE ct_objects + USING KEY type + WHERE type = zif_abapgit_git_definitions=>c_type-ref_d. + + "Restore correct Delta Order + SORT lt_deltas BY index. + + IF iv_show_progress = abap_true. + li_progress = zcl_abapgit_progress=>get_instance( lines( lt_deltas ) ). + ENDIF. + + LOOP AT lt_deltas INTO ls_object. + IF li_progress IS NOT INITIAL. + li_progress->show( iv_current = sy-tabix + iv_text = 'Decode deltas' ). + ENDIF. + + delta( EXPORTING is_object = ls_object + CHANGING ct_objects = ct_objects ). + ENDLOOP. + + ENDMETHOD. + + METHOD delta. + + CONSTANTS: lc_1 TYPE x VALUE '01', + lc_2 TYPE x VALUE '02', + lc_4 TYPE x VALUE '04', + lc_8 TYPE x VALUE '08', + lc_16 TYPE x VALUE '10', + lc_32 TYPE x VALUE '20', + lc_64 TYPE x VALUE '40', + lc_128 TYPE x VALUE '80'. + + DATA: lv_base TYPE xstring, + lv_result TYPE xstring, + lv_offset TYPE i, + lo_stream TYPE REF TO kHGwlatytwTSETnzZMKotffscEwAXR, + lv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, + ls_object LIKE LINE OF ct_objects, + lv_len TYPE i, + lv_tmp TYPE xstring, + lv_org TYPE x. + + FIELD-SYMBOLS: LIKE LINE OF ct_objects. + CREATE OBJECT lo_stream + EXPORTING + iv_data = is_object-data. + +* find base + READ TABLE ct_objects ASSIGNING + WITH KEY sha COMPONENTS sha1 = is_object-sha1. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Base not found, { is_object-sha1 }| ). + ELSEIF -type = zif_abapgit_git_definitions=>c_type-ref_d. +* sanity check + zcx_abapgit_exception=>raise( |Delta, base eq delta| ). + ENDIF. + + lv_base = -data. + +* skip the 2 headers + delta_header( lo_stream ). + delta_header( lo_stream ). + + WHILE lo_stream->has_data( ) = abap_true. + + lv_org = lo_stream->eat_byte( ). + + IF lv_org BIT-AND lc_128 = lc_128. " MSB = 1 + + lv_offset = 0. + IF lv_org BIT-AND lc_1 = lc_1. + lv_offset = lo_stream->eat_byte( ). + ENDIF. + IF lv_org BIT-AND lc_2 = lc_2. + lv_offset = lv_offset + lo_stream->eat_byte( ) * 256. + ENDIF. + IF lv_org BIT-AND lc_4 = lc_4. + lv_offset = lv_offset + lo_stream->eat_byte( ) * 65536. + ENDIF. + IF lv_org BIT-AND lc_8 = lc_8. + lv_offset = lv_offset + lo_stream->eat_byte( ) * 16777216. " hmm, overflow? + ENDIF. + + lv_len = 0. + IF lv_org BIT-AND lc_16 = lc_16. + lv_len = lo_stream->eat_byte( ). + ENDIF. + IF lv_org BIT-AND lc_32 = lc_32. + lv_len = lv_len + lo_stream->eat_byte( ) * 256. + ENDIF. + IF lv_org BIT-AND lc_64 = lc_64. + lv_len = lv_len + lo_stream->eat_byte( ) * 65536. + ENDIF. + + IF lv_len = 0. + lv_len = 65536. + ENDIF. + + CONCATENATE lv_result lv_base+lv_offset(lv_len) INTO lv_result IN BYTE MODE. + ELSE. " lv_bitbyte(1) = '0' +* insert from delta + lv_len = lv_org. " convert to int + lv_tmp = lo_stream->eat_bytes( lv_len ). + CONCATENATE lv_result lv_tmp INTO lv_result IN BYTE MODE. + ENDIF. + + ENDWHILE. + + lv_sha1 = zcl_abapgit_hash=>sha1( iv_type = -type + iv_data = lv_result ). + + CLEAR ls_object. + ls_object-sha1 = lv_sha1. + ls_object-type = -type. + ls_object-data = lv_result. + ls_object-index = -index. "Retain sort index + APPEND ls_object TO ct_objects. + + ENDMETHOD. + METHOD delta_header. + + DATA lv_x TYPE x. + DATA lv_bit TYPE c LENGTH 1. + +* header is skipped for performance reasons + DO. + lv_x = io_stream->eat_byte( ). + GET BIT 1 OF lv_x INTO lv_bit. + IF lv_bit = '0'. + EXIT. " current loop + ENDIF. + ENDDO. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_git_commit IMPLEMENTATION. + + METHOD extract_author_data. + + " Unix time stamps are in same time zone, so ignore the zone + FIND REGEX zif_abapgit_definitions=>c_author_regex IN iv_author + SUBMATCHES + ev_author + ev_email + ev_time. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error author regex value='{ iv_author }'| ). + ENDIF. + + ENDMETHOD. + + METHOD clear_missing_parents. + + "Part of #4719 to handle cut commit sequences, todo + + FIELD-SYMBOLS: TYPE zif_abapgit_git_definitions=>ty_commit. + + LOOP AT ct_commits ASSIGNING . + + IF is_missing( it_commits = ct_commits + iv_sha1 = -parent1 ) = abap_true. + CLEAR -parent1. + ENDIF. + + IF is_missing( it_commits = ct_commits + iv_sha1 = -parent2 ) = abap_true. + CLEAR -parent2. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD get_1st_child_commit. + + DATA: lt_1stchild_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt, + ls_parent LIKE LINE OF it_commit_sha1s, + lt_commit_sha1s LIKE it_commit_sha1s. + + FIELD-SYMBOLS: TYPE zif_abapgit_git_definitions=>ty_commit. + + CLEAR: es_1st_commit. + +* get all reachable next commits + lt_commit_sha1s = it_commit_sha1s. + LOOP AT ct_commits ASSIGNING WHERE parent1 IN lt_commit_sha1s + OR parent2 IN lt_commit_sha1s. + INSERT INTO TABLE lt_1stchild_commits. + ENDLOOP. + +* return oldest one + SORT lt_1stchild_commits BY time ASCENDING. + READ TABLE lt_1stchild_commits INTO es_1st_commit INDEX 1. + +* remove from available commits + DELETE ct_commits WHERE sha1 = es_1st_commit-sha1. + +* set relevant parent commit sha1s + IF lines( lt_1stchild_commits ) = 1. + CLEAR et_commit_sha1s. + ELSE. + et_commit_sha1s = it_commit_sha1s. + ENDIF. + + ls_parent-sign = 'I'. + ls_parent-option = 'EQ'. + ls_parent-low = es_1st_commit-sha1. + INSERT ls_parent INTO TABLE et_commit_sha1s. + + ENDMETHOD. + METHOD get_by_branch. + + DATA: li_progress TYPE REF TO zif_abapgit_progress, + lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + + li_progress = zcl_abapgit_progress=>get_instance( 1 ). + + li_progress->show( + iv_current = 1 + iv_text = |Get git commits { iv_repo_url }| ). + + zcl_abapgit_git_transport=>upload_pack_by_branch( + EXPORTING + iv_url = iv_repo_url + iv_branch_name = iv_branch_name + iv_deepen_level = iv_deepen_level + IMPORTING + ev_branch = rs_pull_result-commit + et_objects = lt_objects ). + + DELETE lt_objects WHERE type <> zif_abapgit_git_definitions=>c_type-commit. + + rs_pull_result-commits = parse_commits( lt_objects ). + + IF iv_sorted = abap_true. + sort_commits( CHANGING ct_commits = rs_pull_result-commits ). + ENDIF. + + ENDMETHOD. + METHOD get_by_commit. + + DATA: li_progress TYPE REF TO zif_abapgit_progress, + lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + + li_progress = zcl_abapgit_progress=>get_instance( 1 ). + + li_progress->show( + iv_current = 1 + iv_text = |Get git commits { iv_repo_url }| ). + + zcl_abapgit_git_transport=>upload_pack_by_commit( + EXPORTING + iv_url = iv_repo_url + iv_deepen_level = iv_deepen_level + iv_hash = iv_commit_hash + IMPORTING + et_objects = lt_objects ). + + DELETE lt_objects WHERE type <> zif_abapgit_git_definitions=>c_type-commit. + + rt_commits = parse_commits( lt_objects ). + sort_commits( CHANGING ct_commits = rt_commits ). + + ENDMETHOD. + METHOD is_missing. + + IF iv_sha1 IS NOT INITIAL. + + READ TABLE it_commits + TRANSPORTING NO FIELDS + WITH KEY sha1 = iv_sha1. + rv_result = boolc( sy-subrc <> 0 ). + + ENDIF. + + ENDMETHOD. + METHOD parse_commits. + + DATA: ls_commit TYPE zif_abapgit_git_definitions=>ty_commit, + lt_body TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + ls_raw TYPE zcl_abapgit_git_pack=>ty_commit. + + FIELD-SYMBOLS: LIKE LINE OF it_objects, + TYPE string. + LOOP AT it_objects ASSIGNING USING KEY type + WHERE type = zif_abapgit_git_definitions=>c_type-commit. + ls_raw = zcl_abapgit_git_pack=>decode_commit( -data ). + + CLEAR ls_commit. + ls_commit-sha1 = -sha1. + ls_commit-parent1 = ls_raw-parent. + ls_commit-parent2 = ls_raw-parent2. + + SPLIT ls_raw-body AT cl_abap_char_utilities=>newline INTO TABLE lt_body. + + READ TABLE lt_body WITH KEY table_line = ' -----END PGP SIGNATURE-----' TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + DELETE lt_body TO sy-tabix. + DELETE lt_body TO 2. + ENDIF. + + READ TABLE lt_body INDEX 1 INTO ls_commit-message. "#EC CI_SUBRC + " The second line is always empty. Therefore we omit it. + LOOP AT lt_body ASSIGNING + FROM 3. + INSERT INTO TABLE ls_commit-body. + ENDLOOP. + + extract_author_data( + EXPORTING + iv_author = ls_raw-author + IMPORTING + ev_author = ls_commit-author + ev_email = ls_commit-email + ev_time = ls_commit-time ). + + APPEND ls_commit TO rt_commits. + + ENDLOOP. + + ENDMETHOD. + METHOD reverse_sort_order. + + DATA: lt_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt. + FIELD-SYMBOLS: TYPE zif_abapgit_git_definitions=>ty_commit. + + LOOP AT ct_commits ASSIGNING . + INSERT INTO lt_commits INDEX 1. + ENDLOOP. + ct_commits = lt_commits. + FREE lt_commits. + + ENDMETHOD. + METHOD sort_commits. + + DATA: lt_sorted_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt, + ls_next_commit TYPE zif_abapgit_git_definitions=>ty_commit, + lt_parents TYPE ty_sha1_range, + ls_parent LIKE LINE OF lt_parents. + + FIELD-SYMBOLS: TYPE zif_abapgit_git_definitions=>ty_commit. + + " find initial commit + READ TABLE ct_commits ASSIGNING WITH KEY parent1 = space. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Cannot find initial commit. Too many commits. Action not possible.| ). + ENDIF. + + ls_parent-sign = 'I'. + ls_parent-option = 'EQ'. + ls_parent-low = -sha1. + INSERT ls_parent INTO TABLE lt_parents. + + " first commit + INSERT INTO TABLE lt_sorted_commits. + + " remove from available commits + DELETE ct_commits WHERE sha1 = -sha1. + + DO. + get_1st_child_commit( EXPORTING it_commit_sha1s = lt_parents + IMPORTING et_commit_sha1s = lt_parents + es_1st_commit = ls_next_commit + CHANGING ct_commits = ct_commits ). + IF ls_next_commit IS INITIAL. + EXIT. "DO + ENDIF. + INSERT ls_next_commit INTO TABLE lt_sorted_commits. + ENDDO. + + ct_commits = lt_sorted_commits. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_git_branch_utils IMPLEMENTATION. + + METHOD complete_heads_branch_name. + IF iv_branch_name CP zif_abapgit_git_definitions=>c_git_branch-heads. + rv_name = iv_branch_name. + ELSE. + rv_name = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && iv_branch_name. + ENDIF. + ENDMETHOD. + + METHOD get_description. + + CASE get_type( iv_branch_name ). + WHEN zif_abapgit_git_definitions=>c_git_branch_type-branch. + rv_description = 'Branch'. + WHEN zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. + rv_description = 'Tag'. + WHEN zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. + rv_description = 'Annotated Tag'. + WHEN OTHERS. + rv_description = 'Branch'. + ENDCASE. + + rv_description = |{ rv_description } "{ get_display_name( iv_branch_name ) }"|. + + ENDMETHOD. + + METHOD get_display_name. + rv_display_name = iv_branch_name. + + IF rv_display_name CP zif_abapgit_git_definitions=>c_git_branch-heads. + REPLACE FIRST OCCURRENCE OF zif_abapgit_git_definitions=>c_git_branch-heads_prefix IN rv_display_name WITH ''. + ELSEIF rv_display_name CP zif_abapgit_git_definitions=>c_git_branch-tags. + rv_display_name = zcl_abapgit_git_tag=>remove_tag_prefix( zcl_abapgit_git_tag=>remove_peel( rv_display_name ) ). + ENDIF. + + ENDMETHOD. + + METHOD get_type. + + FIELD-SYMBOLS: TYPE LINE OF string_table. + + rv_type = zif_abapgit_git_definitions=>c_git_branch_type-other. + + IF iv_branch_name CP zif_abapgit_git_definitions=>c_git_branch-heads OR + iv_branch_name = zif_abapgit_git_definitions=>c_head_name. + rv_type = zif_abapgit_git_definitions=>c_git_branch_type-branch. + + ELSEIF iv_branch_name CP zif_abapgit_git_definitions=>c_git_branch-tags. + + READ TABLE it_result ASSIGNING + INDEX iv_current_row_index + 1. + IF sy-subrc = 0 AND CP '*' && zcl_abapgit_git_tag=>add_peel( iv_branch_name ). + rv_type = zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. + ELSE. + rv_type = zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD normalize_branch_name. + + rv_name = iv_branch_name. " Force convert to string + REPLACE ALL OCCURRENCES OF ` ` IN rv_name WITH '-'. " Disallow space in branch name + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_git_branch_list IMPLEMENTATION. + METHOD constructor. + + parse_branch_list( + EXPORTING + iv_data = iv_data + IMPORTING + et_list = mt_branches + ev_head_symref = mv_head_symref ). + + ENDMETHOD. + METHOD zif_abapgit_git_branch_list~find_by_name. + + IF iv_branch_name IS INITIAL. + zcx_abapgit_exception=>raise( 'Branch name empty' ). + ENDIF. + + IF iv_branch_name CP zif_abapgit_git_definitions=>c_git_branch-tags. + rs_branch = find_tag_by_name( iv_branch_name ). + ELSE. + + READ TABLE mt_branches INTO rs_branch + WITH TABLE KEY name_key + COMPONENTS name = iv_branch_name. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |{ zcl_abapgit_git_branch_utils=>get_description( iv_branch_name ) } not found| ). + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD find_tag_by_name. + + READ TABLE mt_branches INTO rs_branch + WITH TABLE KEY name_key + COMPONENTS name = zcl_abapgit_git_tag=>add_peel( iv_branch_name ). + IF sy-subrc <> 0. + + READ TABLE mt_branches INTO rs_branch + WITH TABLE KEY name_key + COMPONENTS name = iv_branch_name. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |{ zcl_abapgit_git_branch_utils=>get_description( iv_branch_name ) } not found| ). + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_git_branch_list~get_all. + + rt_branches = mt_branches. + + ENDMETHOD. + METHOD zif_abapgit_git_branch_list~get_branches_only. + FIELD-SYMBOLS LIKE LINE OF mt_branches. + + LOOP AT mt_branches ASSIGNING . + IF -type = zif_abapgit_git_definitions=>c_git_branch_type-branch. + APPEND TO rt_branches. + ENDIF. + ENDLOOP. + ENDMETHOD. + + METHOD zif_abapgit_git_branch_list~get_head_symref. + rv_head_symref = mv_head_symref. + ENDMETHOD. + METHOD zif_abapgit_git_branch_list~get_tags_only. + FIELD-SYMBOLS LIKE LINE OF mt_branches. + + LOOP AT mt_branches ASSIGNING + WHERE type = zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag + OR type = zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. + APPEND TO rt_tags. + ENDLOOP. + + ENDMETHOD. + METHOD parse_branch_list. + + DATA: lt_result TYPE TABLE OF string, + lv_hash TYPE zif_abapgit_git_definitions=>ty_sha1, + lv_name TYPE string, + lv_head_params TYPE string, + lv_char TYPE c, + lv_data LIKE LINE OF lt_result, + lv_current_row_index TYPE syst-tabix. + + FIELD-SYMBOLS: LIKE LINE OF et_list. + + CLEAR: et_list, ev_head_symref. + + lv_data = skip_first_pkt( iv_data ). + SPLIT lv_data AT cl_abap_char_utilities=>newline INTO TABLE lt_result. + + LOOP AT lt_result INTO lv_data. + lv_current_row_index = sy-tabix. + + IF sy-tabix = 1 AND strlen( lv_data ) > 12 AND lv_data(4) = '0000' AND lv_data+8(3) = 'ERR'. + lv_name = lv_data+8. + zcx_abapgit_exception=>raise( lv_name ). + ELSEIF sy-tabix = 1 AND strlen( lv_data ) > 49. + lv_hash = lv_data+8. + lv_name = lv_data+49. + lv_char = zcl_abapgit_git_utils=>get_null( ). + + SPLIT lv_name AT lv_char INTO lv_name lv_head_params. + ev_head_symref = parse_head_params( lv_head_params ). + IF ev_head_symref IS INITIAL AND lv_name CS 'refs/heads/'. + ev_head_symref = lv_name. + ENDIF. + ELSEIF sy-tabix > 1 AND strlen( lv_data ) > 45. + lv_hash = lv_data+4. + lv_name = lv_data+45. + ELSEIF sy-tabix = 1 AND strlen( lv_data ) = 8 AND lv_data(8) = '00000000'. + zcx_abapgit_exception=>raise( 'No branches, create branch manually by adding file' ). + ELSE. + CONTINUE. + ENDIF. + + ASSERT lv_name IS NOT INITIAL. + + APPEND INITIAL LINE TO et_list ASSIGNING . + -sha1 = lv_hash. + -name = lv_name. + -display_name = zcl_abapgit_git_branch_utils=>get_display_name( lv_name ). + -type = zcl_abapgit_git_branch_utils=>get_type( + iv_branch_name = lv_name + it_result = lt_result + iv_current_row_index = lv_current_row_index ). + IF -name = zif_abapgit_git_definitions=>c_head_name OR -name = ev_head_symref. + -is_head = abap_true. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD parse_head_params. + + DATA: ls_match TYPE match_result, + ls_submatch LIKE LINE OF ls_match-submatches. + + FIND FIRST OCCURRENCE OF REGEX '\ssymref=HEAD:([^\s]+)' IN iv_data RESULTS ls_match. + READ TABLE ls_match-submatches INTO ls_submatch INDEX 1. + IF sy-subrc IS INITIAL. + rv_head_symref = iv_data+ls_submatch-offset(ls_submatch-length). + ENDIF. + + ENDMETHOD. + METHOD skip_first_pkt. + + DATA: lv_hex TYPE x LENGTH 1, + lv_length TYPE i. + +* channel + ASSERT iv_data(2) = '00'. + + lv_hex = to_upper( iv_data+2(2) ). + lv_length = lv_hex. + + rv_data = iv_data+lv_length. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_GIT_ADD_PATCH IMPLEMENTATION. + METHOD calculate_patch. + + FIELD-SYMBOLS: LIKE LINE OF mt_diff. + + LOOP AT mt_diff ASSIGNING . + + CASE -result. + WHEN zif_abapgit_definitions=>c_diff-unchanged. + + INSERT -old INTO TABLE rt_patch. + + WHEN zif_abapgit_definitions=>c_diff-insert. + + IF -patch_flag = abap_true. + INSERT -new INTO TABLE rt_patch. + ENDIF. + + WHEN zif_abapgit_definitions=>c_diff-delete. + + IF -patch_flag = abap_false. + INSERT -old INTO TABLE rt_patch. + ENDIF. + + WHEN zif_abapgit_definitions=>c_diff-update. + + IF -patch_flag = abap_true. + INSERT -new INTO TABLE rt_patch. + ELSE. + INSERT -old INTO TABLE rt_patch. + ENDIF. + + WHEN OTHERS. + + zcx_abapgit_exception=>raise( |Unknown result| ). + + ENDCASE. + + ENDLOOP. + + ENDMETHOD. + METHOD constructor. + + mt_diff = it_diff. + + ENDMETHOD. + METHOD get_patch. + + IF mt_patch IS INITIAL. + mt_patch = calculate_patch( ). + ENDIF. + + rt_patch = mt_patch. + + ENDMETHOD. + METHOD get_patch_binary. + + DATA: lv_string TYPE string. + + IF mt_patch IS INITIAL. + mt_patch = calculate_patch( ). + ENDIF. + + CONCATENATE LINES OF mt_patch INTO lv_string SEPARATED BY cl_abap_char_utilities=>newline. + lv_string = lv_string && cl_abap_char_utilities=>newline. + + rv_patch_binary = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_gitv2_porcelain IMPLEMENTATION. + METHOD decode_pack. + + DATA lv_xstring TYPE xstring. + DATA lv_contents TYPE xstring. + DATA lv_pack TYPE xstring. + DATA lv_pktlen TYPE i. + DATA lv_hex4 TYPE xstring. + + lv_xstring = iv_xstring. + +* The data transfer of the packfile is always multiplexed, using the same semantics of the +* side-band-64k capability from protocol version 1 + WHILE xstrlen( lv_xstring ) > 0. + lv_hex4 = lv_xstring(4). + lv_pktlen = zcl_abapgit_git_utils=>length_utf8_hex( lv_hex4 ). + IF lv_pktlen = 0. + EXIT. + ELSEIF lv_pktlen = 1. +* its a delimiter package + lv_xstring = lv_xstring+4. + CONTINUE. + ENDIF. + lv_contents = lv_xstring(lv_pktlen). + IF lv_contents+4(1) = '01'. + CONCATENATE lv_pack lv_contents+5 INTO lv_pack IN BYTE MODE. + ENDIF. + lv_xstring = lv_xstring+lv_pktlen. + ENDWHILE. + + rt_objects = zcl_abapgit_git_pack=>decode( lv_pack ). + + ENDMETHOD. + METHOD get_request_uri. + rv_uri = zcl_abapgit_url=>path_name( iv_url ) && |/info/refs?service=git-{ iv_service }-pack|. + ENDMETHOD. + METHOD send_command. + + CONSTANTS lc_content_regex TYPE string VALUE '^[0-9a-f]{4}#'. + + DATA lo_client TYPE REF TO zcl_abapgit_http_client. + DATA lv_cmd_pkt TYPE string. + DATA lt_headers TYPE zcl_abapgit_http=>ty_headers. + DATA ls_header LIKE LINE OF lt_headers. + DATA lv_argument TYPE string. + ls_header-key = 'Git-Protocol'. + ls_header-value = 'version=2'. + APPEND ls_header TO lt_headers. + ls_header-key = '~request_uri'. + ls_header-value = get_request_uri( iv_url = iv_url + iv_service = iv_service ). + APPEND ls_header TO lt_headers. + + lo_client = zcl_abapgit_http=>create_by_url( + iv_url = iv_url + it_headers = lt_headers ). + + lo_client->check_smart_response( + iv_expected_content_type = |application/x-git-{ iv_service }-pack-advertisement| + iv_content_regex = lc_content_regex ). + + lv_cmd_pkt = zcl_abapgit_git_utils=>pkt_string( |command={ iv_command }\n| ) + && zcl_abapgit_git_utils=>pkt_string( |agent={ zcl_abapgit_http=>get_agent( ) }\n| ). + IF lines( it_arguments ) > 0. + lv_cmd_pkt = lv_cmd_pkt && c_delim_pkt. + LOOP AT it_arguments INTO lv_argument. + lv_cmd_pkt = lv_cmd_pkt && zcl_abapgit_git_utils=>pkt_string( lv_argument ). + ENDLOOP. + ENDIF. + lv_cmd_pkt = lv_cmd_pkt && c_flush_pkt. + + lo_client->set_header( + iv_key = '~request_uri' + iv_value = zcl_abapgit_url=>path_name( iv_url ) && |/git-{ iv_service }-pack| ). + + lo_client->set_header( + iv_key = '~request_method' + iv_value = 'POST' ). + + lo_client->set_header( + iv_key = 'Content-Type' + iv_value = |application/x-git-{ iv_service }-pack-request| ). + + lo_client->set_header( + iv_key = 'Accept' + iv_value = |application/x-git-{ iv_service }-pack-result| ). + + rv_response = lo_client->send_receive_close( zcl_abapgit_convert=>string_to_xstring_utf8( lv_cmd_pkt ) ). + + ENDMETHOD. + METHOD zif_abapgit_gitv2_porcelain~commits_last_year. +* including trees + DATA lv_xstring TYPE xstring. + DATA lt_arguments TYPE string_table. + DATA lv_argument TYPE string. + DATA lv_sha1 LIKE LINE OF it_sha1. + ASSERT lines( it_sha1 ) > 0. + + lv_argument = |deepen-since { zcl_abapgit_git_time=>get_one_year_ago( ) }|. + APPEND lv_argument TO lt_arguments. + LOOP AT it_sha1 INTO lv_sha1. + lv_argument = |want { lv_sha1 }|. + APPEND lv_argument TO lt_arguments. + ENDLOOP. +* 'filter object:type=commit' doesn't work on github + APPEND 'filter blob:none' TO lt_arguments. + APPEND 'no-progress' TO lt_arguments. + APPEND 'done' TO lt_arguments. + + lv_xstring = send_command( + iv_url = iv_url + iv_service = c_service-upload + iv_command = |fetch| + it_arguments = lt_arguments ). + + rt_objects = decode_pack( lv_xstring ). + + ENDMETHOD. + METHOD zif_abapgit_gitv2_porcelain~fetch_blob. + + DATA lv_xstring TYPE xstring. + DATA lt_arguments TYPE string_table. + DATA lv_argument TYPE string. + DATA lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + DATA ls_object LIKE LINE OF lt_objects. + ASSERT iv_sha1 IS NOT INITIAL. + + lv_argument = |want { iv_sha1 }|. + APPEND lv_argument TO lt_arguments. + APPEND 'no-progress' TO lt_arguments. + APPEND 'done' TO lt_arguments. + + lv_xstring = send_command( + iv_url = iv_url + iv_service = c_service-upload + iv_command = |fetch| + it_arguments = lt_arguments ). + + lt_objects = decode_pack( lv_xstring ). + IF lines( lt_objects ) <> 1. + zcx_abapgit_exception=>raise( |Blob { iv_sha1 } not found in response.| ). + ENDIF. + + READ TABLE lt_objects INTO ls_object INDEX 1. + ASSERT sy-subrc = 0. + rv_blob = ls_object-data. + + ENDMETHOD. + METHOD zif_abapgit_gitv2_porcelain~list_branches. + DATA lv_xstring TYPE xstring. + DATA lt_arguments TYPE string_table. + DATA lv_argument TYPE string. + DATA lv_data TYPE string. + + IF iv_prefix IS NOT INITIAL. + lv_argument = |ref-prefix { iv_prefix }|. + APPEND lv_argument TO lt_arguments. + ENDIF. + + lv_xstring = send_command( + iv_url = iv_url + iv_service = c_service-upload + iv_command = |ls-refs| + it_arguments = lt_arguments ). + + " add dummy packet so the v1 branch parsing can be reused + lv_data = |0004\n{ zcl_abapgit_convert=>xstring_to_string_utf8( lv_xstring ) }|. + + CREATE OBJECT ro_list TYPE zcl_abapgit_git_branch_list + EXPORTING + iv_data = lv_data. + + ENDMETHOD. + METHOD zif_abapgit_gitv2_porcelain~list_no_blobs. + + DATA lt_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt. + DATA lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. + + ASSERT iv_sha1 IS NOT INITIAL. + APPEND iv_sha1 TO lt_sha1. + + lt_objects = zif_abapgit_gitv2_porcelain~list_no_blobs_multi( + iv_url = iv_url + it_sha1 = lt_sha1 ). + + rt_expanded = zcl_abapgit_git_porcelain=>full_tree( + it_objects = lt_objects + iv_parent = iv_sha1 ). + + ENDMETHOD. + METHOD zif_abapgit_gitv2_porcelain~list_no_blobs_multi. + + DATA lv_xstring TYPE xstring. + DATA lt_arguments TYPE string_table. + DATA lv_argument TYPE string. + DATA lv_sha1 LIKE LINE OF it_sha1. + ASSERT lines( it_sha1 ) > 0. + + APPEND 'deepen 1' TO lt_arguments. + LOOP AT it_sha1 INTO lv_sha1. + lv_argument = |want { lv_sha1 }|. + APPEND lv_argument TO lt_arguments. + ENDLOOP. + APPEND 'filter blob:none' TO lt_arguments. + APPEND 'no-progress' TO lt_arguments. + APPEND 'done' TO lt_arguments. + + lv_xstring = send_command( + iv_url = iv_url + iv_service = c_service-upload + iv_command = |fetch| + it_arguments = lt_arguments ). + + rt_objects = decode_pack( lv_xstring ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_exit IMPLEMENTATION. + METHOD get_instance. + + DATA lv_class_name TYPE string. + + IF gi_global_exit IS NOT INITIAL. + ri_exit = gi_global_exit. + RETURN. + ENDIF. + + lv_class_name = 'ZCL_ABAPGIT_USER_EXIT'. + + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. + " Prevent accidental usage of exit handlers in the developer version + lv_class_name = |\\PROGRAM={ sy-repid }\\CLASS={ lv_class_name }|. + ENDIF. + + " Prevent non-mocked exit calls in unit tests + IF is_running_in_test_context( ) = abap_false. + TRY. + CREATE OBJECT gi_exit TYPE (lv_class_name). + CATCH cx_sy_create_object_error ##NO_HANDLER. + ENDTRY. + ENDIF. + + CREATE OBJECT gi_global_exit TYPE zcl_abapgit_exit. " this class + + ri_exit = gi_global_exit. + + ENDMETHOD. + METHOD is_running_in_test_context. + + IF sy-sysid = 'ABC'. + " always run on open-abap + rv_running_in_test_context = abap_true. + RETURN. + ENDIF. + + " Check if the local test class can be accessed by RTTI. If so the current process is running in a unit test. + " Note this approach only works for the developer version. The standalone version will always report not running in + " test context which should be fine as there are no unit tests delivered in it. + cl_abap_typedescr=>describe_by_name( + EXPORTING + p_name = |\\PROGRAM={ sy-repid }\\CLASS=LTCL_TEST| + EXCEPTIONS + type_not_found = 1 + OTHERS = 2 ). + rv_running_in_test_context = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD zif_abapgit_exit~adjust_display_commit_url. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->adjust_display_commit_url( + EXPORTING + iv_repo_url = iv_repo_url + iv_repo_name = iv_repo_name + iv_repo_key = iv_repo_key + iv_commit_hash = iv_commit_hash + CHANGING + cv_display_url = cv_display_url ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~adjust_display_filename. + + IF gi_exit IS NOT INITIAL. + TRY. + rv_filename = gi_exit->adjust_display_filename( + is_repo_meta = is_repo_meta + iv_filename = iv_filename ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + IF rv_filename IS INITIAL. + rv_filename = iv_filename. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~allow_sap_objects. + + IF gi_exit IS NOT INITIAL. + TRY. + rv_allowed = gi_exit->allow_sap_objects( ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~change_local_host. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_local_host( CHANGING ct_hosts = ct_hosts ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~change_max_parallel_processes. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_max_parallel_processes( + EXPORTING + iv_package = iv_package + CHANGING + cv_max_processes = cv_max_processes ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~change_proxy_authentication. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_proxy_authentication( + EXPORTING + iv_repo_url = iv_repo_url + CHANGING + cv_proxy_authentication = cv_proxy_authentication ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~change_proxy_port. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_proxy_port( + EXPORTING + iv_repo_url = iv_repo_url + CHANGING + cv_proxy_port = cv_proxy_port ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~change_proxy_url. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_proxy_url( + EXPORTING + iv_repo_url = iv_repo_url + CHANGING + cv_proxy_url = cv_proxy_url ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~change_rfc_server_group. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_rfc_server_group( CHANGING cv_group = cv_group ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~change_supported_data_objects. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_supported_data_objects( CHANGING ct_objects = ct_objects ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~change_supported_object_types. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_supported_object_types( CHANGING ct_types = ct_types ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~change_tadir. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_tadir( + EXPORTING + iv_package = iv_package + ii_log = ii_log + is_dot_abapgit = is_dot_abapgit + iv_ignore_subpackages = iv_ignore_subpackages + iv_only_local_objects = iv_only_local_objects + CHANGING + ct_tadir = ct_tadir ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~create_http_client. + + IF gi_exit IS NOT INITIAL. + TRY. + ri_client = gi_exit->create_http_client( iv_url ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~custom_serialize_abap_clif. + + " This exit might be called twice per object + " 1st call: it_source = initial + " Can be used for serializing complete source + " If source is returned, there will be no second call + " 2nd call: it_source = code as serialized by abapGit + " Can be used for post-processing of source + IF gi_exit IS NOT INITIAL. + TRY. + rt_source = gi_exit->custom_serialize_abap_clif( + is_class_key = is_class_key + it_source = it_source ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + IF rt_source IS INITIAL. + rt_source = it_source. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~deserialize_postprocess. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->deserialize_postprocess( is_step = is_step + ii_log = ii_log ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~determine_transport_request. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->determine_transport_request( + EXPORTING + ii_repo = ii_repo + iv_transport_type = iv_transport_type + CHANGING + cv_transport_request = cv_transport_request ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~enhance_any_toolbar. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->enhance_any_toolbar( io_menu ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~enhance_repo_toolbar. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->enhance_repo_toolbar( + io_menu = io_menu + iv_key = iv_key + iv_act = iv_act ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~get_ci_tests. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->get_ci_tests( + EXPORTING + iv_object = iv_object + CHANGING + ct_ci_repos = ct_ci_repos ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~get_ssl_id. + + IF gi_exit IS NOT INITIAL. + TRY. + rv_ssl_id = gi_exit->get_ssl_id( ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + IF rv_ssl_id IS INITIAL. + rv_ssl_id = 'ANONYM'. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~http_client. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->http_client( + iv_url = iv_url + ii_client = ii_client ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~on_event. + + IF gi_exit IS NOT INITIAL. + TRY. + rs_handled = gi_exit->on_event( ii_event ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~pre_calculate_repo_status. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->pre_calculate_repo_status( + EXPORTING + is_repo_meta = is_repo_meta + CHANGING + ct_local = ct_local + ct_remote = ct_remote ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~serialize_postprocess. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->serialize_postprocess( + EXPORTING + iv_package = iv_package + ii_log = ii_log + CHANGING + ct_files = ct_files ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~validate_before_push. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->validate_before_push( + is_comment = is_comment + io_stage = io_stage + ii_repo_online = ii_repo_online ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~wall_message_list. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->wall_message_list( ii_html ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_exit~wall_message_repo. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->wall_message_repo( + is_repo_meta = is_repo_meta + ii_html = ii_html ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. + + METHOD zif_abapgit_exit~change_committer_info. + + IF gi_exit IS NOT INITIAL. + TRY. + gi_exit->change_committer_info( + EXPORTING + iv_repo_url = iv_repo_url + CHANGING + cv_name = cv_name + cv_email = cv_email ). + CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. + ENDTRY. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_auth IMPLEMENTATION. + METHOD is_allowed. + + DATA: li_auth TYPE REF TO zif_abapgit_auth. + + TRY. + CREATE OBJECT li_auth TYPE ('ZCL_ABAPGIT_AUTH_EXIT'). + rv_allowed = li_auth->is_allowed( iv_authorization = iv_authorization + iv_param = iv_param ). + CATCH cx_sy_create_object_error. + rv_allowed = abap_true. + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS ZCL_ABAPGIT_USER_RECORD IMPLEMENTATION. + METHOD build_cache. + + " Get user details + TRY. + check_user_exists( + EXPORTING + iv_user = iv_user + IMPORTING + ev_fullname = rs_user-name + ev_email = rs_user-email ). + CATCH zcx_abapgit_exception. + " Could not find user, try to get from other clients + rs_user = get_user_dtls_from_other_clnt( iv_user ). + ENDTRY. + + rs_user-user = iv_user. + INSERT rs_user INTO TABLE gt_user. + + ENDMETHOD. + METHOD check_user_exists. + + DATA lt_return TYPE STANDARD TABLE OF bapiret2 WITH DEFAULT KEY. + DATA ls_address TYPE bapiaddr3. + DATA lt_smtp TYPE TABLE OF bapiadsmtp. + DATA ls_smtp LIKE LINE OF lt_smtp. + + CALL FUNCTION 'BAPI_USER_GET_DETAIL' + EXPORTING + username = iv_user + IMPORTING + address = ls_address + TABLES + return = lt_return + addsmtp = lt_smtp. + LOOP AT lt_return TRANSPORTING NO FIELDS WHERE type CA 'EA'. + zcx_abapgit_exception=>raise( |User: { iv_user } not found| ). + ENDLOOP. + + ev_fullname = ls_address-fullname. + + " Choose the first email from SU01 + SORT lt_smtp BY consnumber ASCENDING. + + LOOP AT lt_smtp INTO ls_smtp. + ev_email = ls_smtp-e_mail. + EXIT. + ENDLOOP. + + ENDMETHOD. + METHOD get_user_dtls_from_other_clnt. + + CONSTANTS lc_cc_category TYPE string VALUE 'C'. + TYPES ty_dev_clients TYPE SORTED TABLE OF sy-mandt WITH UNIQUE KEY table_line. + DATA lt_dev_clients TYPE ty_dev_clients. + FIELD-SYMBOLS LIKE LINE OF lt_dev_clients. + + " Could not find the user, try other development clients + SELECT mandt FROM t000 INTO TABLE lt_dev_clients + WHERE cccategory = lc_cc_category AND mandt <> sy-mandt + ORDER BY PRIMARY KEY. + + LOOP AT lt_dev_clients ASSIGNING . + SELECT SINGLE u~bname p~name_text a~smtp_addr INTO (rs_user-user, rs_user-name, rs_user-email) + FROM usr21 AS u + INNER JOIN adrp AS p ON p~persnumber = u~persnumber + AND p~client = u~mandt + INNER JOIN adr6 AS a ON a~persnumber = u~persnumber + AND a~addrnumber = u~addrnumber + AND a~client = u~mandt + CLIENT SPECIFIED + WHERE u~mandt = + AND u~bname = iv_user + AND p~date_from <= sy-datum + AND p~date_to >= sy-datum + AND a~date_from <= sy-datum. + IF sy-subrc = 0. + EXIT. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD read_cache. + + READ TABLE gt_user INTO rs_user WITH TABLE KEY user = iv_user. + IF sy-subrc <> 0. + rs_user = build_cache( iv_user ). + ENDIF. + + ENDMETHOD. + METHOD reset. + CLEAR gt_user. + ENDMETHOD. + METHOD zif_abapgit_user_record~get_email. + + rv_email = read_cache( iv_username )-email. + + ENDMETHOD. + METHOD zif_abapgit_user_record~get_name. + + rv_name = read_cache( iv_username )-name. + + ENDMETHOD. + METHOD zif_abapgit_user_record~get_title. +* the queried username might not exist, refactored for open-abap compatibility + + DATA lr_addr3 TYPE REF TO data. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE simple. + + TRY. + CREATE DATA lr_addr3 TYPE ('ADDR3_VAL'). + CATCH cx_sy_create_data_error. + RETURN. + ENDTRY. + ASSIGN lr_addr3->* TO . + + CALL FUNCTION 'SUSR_USER_ADDRESS_READ' + EXPORTING + user_name = iv_username + IMPORTING + user_address = + EXCEPTIONS + user_address_not_found = 1 + OTHERS = 2. + IF sy-subrc = 0. + ASSIGN COMPONENT 'NAME_TEXT' OF STRUCTURE TO . + rv_title = . + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_settings IMPLEMENTATION. + METHOD get_activate_wo_popup. + rv_act_wo_popup = ms_user_settings-activate_wo_popup. + ENDMETHOD. + METHOD get_adt_jump_enabled. + rv_adt_jump_enabled = ms_user_settings-adt_jump_enabled. + ENDMETHOD. + METHOD get_commitmsg_body_size. + rv_length = ms_settings-commitmsg_body_size. + ENDMETHOD. + METHOD get_commitmsg_comment_default. + rv_default = ms_settings-commitmsg_comment_deflt. + ENDMETHOD. + METHOD get_commitmsg_comment_length. + rv_length = ms_settings-commitmsg_comment_length. + ENDMETHOD. + METHOD get_commitmsg_hide_author. + rv_hide_author = ms_settings-commitmsg_hide_author. + ENDMETHOD. + METHOD get_experimental_features. + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. + rv_features = ms_settings-experimental_features. + ENDIF. + ENDMETHOD. + METHOD get_icon_scaling. + rv_scaling = ms_user_settings-icon_scaling. + ENDMETHOD. + METHOD get_link_hints_enabled. + rv_link_hints_enabled = ms_user_settings-link_hints_enabled. + ENDMETHOD. + METHOD get_link_hint_key. + rv_link_hint_key = ms_user_settings-link_hint_key. + ENDMETHOD. + METHOD get_max_lines. + rv_lines = ms_user_settings-max_lines. + ENDMETHOD. + METHOD get_parallel_proc_disabled. + rv_disable_parallel_proc = ms_user_settings-parallel_proc_disabled. + ENDMETHOD. + METHOD get_proxy_authentication. + rv_auth = ms_settings-proxy_auth. + ENDMETHOD. + METHOD get_proxy_bypass. + rt_bypass = ms_settings-proxy_bypass. + ENDMETHOD. + METHOD get_proxy_port. + rv_port = ms_settings-proxy_port. + ENDMETHOD. + METHOD get_proxy_url. + rv_proxy_url = ms_settings-proxy_url. + ENDMETHOD. + METHOD get_run_critical_tests. + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. + rv_run = ms_settings-run_critical_tests. + ENDIF. + ENDMETHOD. + METHOD get_settings_xml. + + DATA: li_output TYPE REF TO zif_abapgit_xml_output. + CREATE OBJECT li_output TYPE zcl_abapgit_xml_output. + + li_output->add( iv_name = zcl_abapgit_persistence_db=>c_type_settings + ig_data = ms_settings ). + + rv_settings_xml = li_output->render( ). + + ENDMETHOD. + METHOD get_show_default_repo. + rv_show_default_repo = ms_user_settings-show_default_repo. + ENDMETHOD. + METHOD get_ui_theme. + DATA lv_frontend_theme TYPE string. + DATA lv_cl_gui TYPE string. + + lv_cl_gui = 'CL_GUI_RESOURCES'. + + rv_ui_theme = ms_user_settings-ui_theme. + + IF rv_ui_theme = c_ui_theme-synced_with_gui AND iv_resolve_synced = abap_true. + TRY. + CALL METHOD (lv_cl_gui)=>get_themename + IMPORTING + themename = lv_frontend_theme + EXCEPTIONS + get_std_resource_error = 1 + OTHERS = 2. + IF sy-subrc <> 0. + rv_ui_theme = c_ui_theme-default. + RETURN. + ENDIF. + CATCH cx_sy_dyn_call_error. + rv_ui_theme = c_ui_theme-default. + RETURN. + ENDTRY. + + CASE lv_frontend_theme. + WHEN 'Belize'. + rv_ui_theme = c_ui_theme-belize. + WHEN OTHERS. + IF lv_frontend_theme CS 'dark'. + rv_ui_theme = c_ui_theme-dark. + ELSE. + rv_ui_theme = c_ui_theme-default. + ENDIF. + ENDCASE. + ENDIF. + ENDMETHOD. + METHOD get_user_settings. + rs_settings = ms_user_settings. + ENDMETHOD. + METHOD set_activate_wo_popup. + ms_user_settings-activate_wo_popup = iv_act_wo_popup. + ENDMETHOD. + METHOD set_adt_jump_enanbled. + ms_user_settings-adt_jump_enabled = iv_adt_jump_enabled. + ENDMETHOD. + METHOD set_commitmsg_body_size. + ms_settings-commitmsg_body_size = iv_length. + ENDMETHOD. + METHOD set_commitmsg_comment_default. + ms_settings-commitmsg_comment_deflt = iv_default. + ENDMETHOD. + METHOD set_commitmsg_comment_length. + ms_settings-commitmsg_comment_length = iv_length. + ENDMETHOD. + METHOD set_commitmsg_hide_author. + ms_settings-commitmsg_hide_author = iv_hide_author. + ENDMETHOD. + METHOD set_defaults. + + CLEAR ms_settings. + + set_proxy_authentication( abap_false ). + set_run_critical_tests( abap_false ). + set_experimental_features( '' ). + set_max_lines( 500 ). + set_adt_jump_enanbled( abap_true ). + set_show_default_repo( abap_false ). + set_commitmsg_comment_length( c_commitmsg_comment_length_dft ). + set_commitmsg_body_size( c_commitmsg_body_size_dft ). + set_default_link_hint_key( ). + set_icon_scaling( '' ). + + ENDMETHOD. + METHOD set_default_link_hint_key. + " Since #5859 'f' is used for "focus filter", we use 't' as the new default + set_link_hint_key( |t| ). + ENDMETHOD. + METHOD set_experimental_features. + ms_settings-experimental_features = iv_features. + ENDMETHOD. + METHOD set_icon_scaling. + ms_user_settings-icon_scaling = iv_scaling. + IF ms_user_settings-icon_scaling NA c_icon_scaling. + ms_user_settings-icon_scaling = ''. " Reset to default + ENDIF. + ENDMETHOD. + METHOD set_link_hints_enabled. + ms_user_settings-link_hints_enabled = iv_link_hints_enabled. + ENDMETHOD. + METHOD set_link_hint_key. + ms_user_settings-link_hint_key = iv_link_hint_key. + ENDMETHOD. + METHOD set_max_lines. + ms_user_settings-max_lines = iv_lines. + ENDMETHOD. + METHOD set_parallel_proc_disabled. + ms_user_settings-parallel_proc_disabled = iv_disable_parallel_proc. + ENDMETHOD. + METHOD set_proxy_authentication. + ms_settings-proxy_auth = iv_auth. + ENDMETHOD. + METHOD set_proxy_bypass. + ms_settings-proxy_bypass = it_bypass. + ENDMETHOD. + METHOD set_proxy_port. + ms_settings-proxy_port = iv_port. + ENDMETHOD. + METHOD set_proxy_url. + ms_settings-proxy_url = iv_url. + ENDMETHOD. + METHOD set_run_critical_tests. + ms_settings-run_critical_tests = iv_run. + ENDMETHOD. + METHOD set_show_default_repo. + ms_user_settings-show_default_repo = iv_show_default_repo. + ENDMETHOD. + METHOD set_ui_theme. + ms_user_settings-ui_theme = iv_ui_theme. + IF ms_user_settings-ui_theme <> c_ui_theme-default + AND ms_user_settings-ui_theme <> c_ui_theme-dark + AND ms_user_settings-ui_theme <> c_ui_theme-belize + AND ms_user_settings-ui_theme <> c_ui_theme-synced_with_gui. + ms_user_settings-ui_theme = c_ui_theme-default. " Reset to default + ENDIF. + ENDMETHOD. + METHOD set_user_settings. + ms_user_settings = is_user_settings. + + IF ms_user_settings-link_hint_key IS INITIAL. + set_default_link_hint_key( ). + ENDIF. + + ENDMETHOD. + METHOD set_xml_settings. + + DATA: lo_input TYPE REF TO zif_abapgit_xml_input. + CREATE OBJECT lo_input TYPE zcl_abapgit_xml_input EXPORTING iv_xml = iv_settings_xml. + + CLEAR ms_settings. + + lo_input->read( + EXPORTING + iv_name = zcl_abapgit_persistence_db=>c_type_settings + CHANGING + cg_data = ms_settings ). + + ENDMETHOD. + METHOD get_default_git_uname. + rv_default_git_uname = ms_user_settings-default_git_uname. + ENDMETHOD. + METHOD set_default_git_uname. + ms_user_settings-default_git_uname = iv_default_git_uname. + ENDMETHOD. + METHOD get_default_git_email. + rv_default_git_email = ms_user_settings-default_git_email. + ENDMETHOD. + METHOD set_default_git_email. + ms_user_settings-default_git_email = iv_default_git_email. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_language IMPLEMENTATION. + METHOD class_constructor. + + DATA lv_dummy TYPE string. + + GET LOCALE LANGUAGE gv_login_language COUNTRY lv_dummy MODIFIER lv_dummy. + + ENDMETHOD. + METHOD restore_login_language. + + SET LOCALE LANGUAGE gv_login_language. + + ENDMETHOD. + METHOD set_current_language. + + SET LOCALE LANGUAGE iv_language. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_feature IMPLEMENTATION. + METHOD is_enabled. + + DATA: + lv_features TYPE string, + lt_features TYPE string_table. + + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. + RETURN. + ENDIF. + + lv_features = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_experimental_features( ). + CONDENSE lv_features NO-GAPS. + + rv_run = boolc( lv_features = abap_true ). + + IF iv_feature IS NOT INITIAL. + SPLIT lv_features AT ',' INTO TABLE lt_features. + READ TABLE lt_features TRANSPORTING NO FIELDS WITH TABLE KEY table_line = iv_feature. + rv_run = boolc( rv_run = abap_true OR sy-subrc = 0 ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_environment IMPLEMENTATION. + METHOD is_system_changes_allowed. + + DATA: + lv_systemedit TYPE tadir-edtflag, + lv_sys_cliinddep_edit TYPE t000-ccnocliind, + lv_is_shadow TYPE abap_bool, + ls_upginfo TYPE uvers, + lv_is_upgrade TYPE abap_bool. + + CALL FUNCTION 'TR_SYS_PARAMS' + IMPORTING + systemedit = lv_systemedit + sys_cliinddep_edit = lv_sys_cliinddep_edit + EXCEPTIONS + no_systemname = 1 + no_systemtype = 2 + OTHERS = 3. + IF sy-subrc <> 0. + " Assume system can't be changed + RETURN. + ENDIF. + + CALL FUNCTION 'UPG_IS_SHADOW_SYSTEM' + IMPORTING + ev_shadow = lv_is_shadow. + + CALL FUNCTION 'UPG_GET_ACTIVE_COMP_UPGRADE' + EXPORTING + iv_component = 'SAP_BASIS' + iv_upgtype = 'A' + iv_buffered = abap_false + IMPORTING + ev_upginfo = ls_upginfo + EXCEPTIONS + OTHERS = 4. + IF sy-subrc = 0 AND ls_upginfo-putstatus NA 'ITU'. + lv_is_upgrade = abap_true. + ENDIF. + + " SAP system has status 'not modifiable' (TK 102) + " Changes to repository objects are not permitted in this client (TK 729) + " Shadow system + " Running upgrade + rv_result = boolc( + lv_systemedit <> 'N' AND + lv_sys_cliinddep_edit NA '23' AND + lv_is_shadow <> abap_true AND + lv_is_upgrade <> abap_true ). + + ENDMETHOD. + METHOD zif_abapgit_environment~check_parallel_processing. + + " If check fails, see transactions RZ12 + DATA: + lt_setup TYPE STANDARD TABLE OF rzllitab, + ls_setup LIKE LINE OF lt_setup, + lt_erfc_setup TYPE STANDARD TABLE OF rzlliclass, + lt_instances TYPE STANDARD TABLE OF msxxlist WITH DEFAULT KEY. + + " Check if server group for parallel processing exists + CALL FUNCTION 'SMLG_GET_SETUP' + EXPORTING + grouptype = 'S' + TABLES + setup = lt_setup + erfc_setup = lt_erfc_setup + EXCEPTIONS + foreign_lock = 1 + system_failure = 2 + invalid_group_type = 3 + OTHERS = 4. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + READ TABLE lt_setup INTO ls_setup WITH KEY classname = iv_group. + IF sy-subrc = 0 AND ls_setup-applserver IS NOT INITIAL. + + " Check if assigned server instance exists + CALL FUNCTION 'TH_SERVER_LIST' + TABLES + list = lt_instances. + + READ TABLE lt_instances TRANSPORTING NO FIELDS WITH KEY name = ls_setup-applserver. + IF sy-subrc = 0. + rv_checked = abap_true. + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_environment~compare_with_inactive. + rv_result = zif_abapgit_environment~is_sap_cloud_platform( ). + ENDMETHOD. + METHOD zif_abapgit_environment~get_available_user_sessions. + + DATA: + lv_act_sessions TYPE i, + lv_max_sessions TYPE i, + lv_subrc TYPE sy-subrc. + + CALL FUNCTION 'TH_USER_INFO' + IMPORTING + act_sessions = lv_act_sessions + max_sessions = lv_max_sessions + rc = lv_subrc. + + IF lv_subrc = 0. + rv_sessions = lv_max_sessions - lv_act_sessions. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_environment~get_basis_release. + + SELECT SINGLE release extrelease FROM cvers INTO (rs_result-release, rs_result-sp) + WHERE component = 'SAP_BASIS' ##SUBRC_OK. + + ENDMETHOD. + METHOD zif_abapgit_environment~get_system_language_filter. + DATA lv_translation_detective_lang TYPE spras. + DATA lv_pseudo_translation_language TYPE spras. + FIELD-SYMBOLS LIKE LINE OF rt_system_language_filter. + + " Translation Object Detective + " https://help.sap.com/docs/ABAP_PLATFORM_NEW/ceb25152cb0d4adba664cebea2bf4670/88a3d3cbccf64601975acabaccdfde45.html + CALL FUNCTION 'CONVERSION_EXIT_ISOLA_INPUT' + EXPORTING + input = '1Q' + IMPORTING + output = lv_translation_detective_lang + EXCEPTIONS + unknown_language = 1 + OTHERS = 2. + IF sy-subrc = 1. + " The language for Translation Object Detective was not setup + ENDIF. + IF NOT lv_translation_detective_lang IS INITIAL. + APPEND INITIAL LINE TO rt_system_language_filter ASSIGNING . + -sign = 'E'. + -option = 'EQ'. + -low = lv_translation_detective_lang. + ENDIF. + " 1943470 - Using technical language key 2Q to create pseudo-translations of ABAP developments + " https://launchpad.support.sap.com/#/notes/1943470 + CALL FUNCTION 'CONVERSION_EXIT_ISOLA_INPUT' + EXPORTING + input = '2Q' + IMPORTING + output = lv_pseudo_translation_language + EXCEPTIONS + unknown_language = 1 + OTHERS = 2. + IF sy-subrc = 1. + " The language for Pseudo Translation was not setup + ENDIF. + IF NOT lv_pseudo_translation_language IS INITIAL. + APPEND INITIAL LINE TO rt_system_language_filter ASSIGNING . + -sign = 'E'. + -option = 'EQ'. + -low = lv_pseudo_translation_language. + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_environment~init_parallel_processing. + + DATA: lv_group TYPE rzlli_apcl. + + lv_group = iv_group. + + " SPBT_INITIALIZE gives error PBT_ENV_ALREADY_INITIALIZED if called + " multiple times in same session + CALL FUNCTION 'SPBT_INITIALIZE' + EXPORTING + group_name = lv_group + IMPORTING + free_pbt_wps = rv_free_work_processes + EXCEPTIONS + invalid_group_name = 1 + internal_error = 2 + pbt_env_already_initialized = 3 + currently_no_resources_avail = 4 + no_pbt_resources_found = 5 + cant_init_different_pbt_groups = 6 + OTHERS = 7 ##FM_SUBRC_OK. + " If SPBT_INITIALIZE fails, check transactions RZ12, SM50, SM21, SARFC + + ENDMETHOD. + METHOD zif_abapgit_environment~is_merged. + DATA lr_marker TYPE REF TO data ##NEEDED. + + IF mv_is_merged = abap_undefined. + TRY. + CREATE DATA lr_marker TYPE REF TO ('LIF_ABAPMERGE_MARKER'). + "No exception --> marker found + mv_is_merged = abap_true. + + CATCH cx_sy_create_data_error. + mv_is_merged = abap_false. + ENDTRY. + ENDIF. + rv_result = mv_is_merged. + ENDMETHOD. + METHOD zif_abapgit_environment~is_repo_object_changes_allowed. + IF mv_modifiable = abap_undefined. + mv_modifiable = is_system_changes_allowed( ). + ENDIF. + rv_result = mv_modifiable. + ENDMETHOD. + METHOD zif_abapgit_environment~is_restart_required. + " This method will be used in the context of SAP Cloud Platform: + " Pull/Push operations are executed in background jobs. + " In case of the respective application server needs to be restarted, + " it is required to terminate the background job and reschedule again. + rv_result = abap_false. + TRY. + CALL METHOD ('CL_APJ_SCP_TOOLS')=>('IS_RESTART_REQUIRED') + RECEIVING + restart_required = rv_result. + CATCH cx_sy_dyn_call_illegal_method cx_sy_dyn_call_illegal_class. + rv_result = abap_false. + ENDTRY. + ENDMETHOD. + METHOD zif_abapgit_environment~is_sap_cloud_platform. + IF mv_cloud = abap_undefined. + TRY. + CALL METHOD ('CL_COS_UTILITIES')=>('IS_SAP_CLOUD_PLATFORM') + RECEIVING + rv_is_sap_cloud_platform = mv_cloud. + CATCH cx_sy_dyn_call_error. + mv_cloud = abap_false. + ENDTRY. + ENDIF. + rv_result = mv_cloud. + ENDMETHOD. + METHOD zif_abapgit_environment~is_sap_object_allowed. + + rv_allowed = cl_enh_badi_def_utility=>is_sap_system( ). + IF rv_allowed = abap_true. + RETURN. + ENDIF. + + rv_allowed = zcl_abapgit_exit=>get_instance( )->allow_sap_objects( ). + + ENDMETHOD. + METHOD zif_abapgit_environment~is_variant_maintenance. + + DATA: + lt_variscreens TYPE STANDARD TABLE OF rsdynnr + WITH NON-UNIQUE DEFAULT KEY. + + " Memory is set in LSVARF08 / EXPORT_SCREEN_TABLES. + IMPORT variscreens = lt_variscreens FROM MEMORY ID '%_SCRNR_%'. + + rv_is_variant_maintenance = boolc( lines( lt_variscreens ) > 0 ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_env_injector IMPLEMENTATION. + + METHOD set_user_record. + zcl_abapgit_env_factory=>gi_user_record = ii_user_record. + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_env_factory IMPLEMENTATION. + + METHOD get_user_record. + IF gi_user_record IS NOT BOUND. + CREATE OBJECT gi_user_record TYPE zcl_abapgit_user_record. + ENDIF. + + ri_user_record = gi_user_record. + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_abap_language_vers IMPLEMENTATION. + METHOD check_abap_language_version. + + " Check if ABAP language version matches repository setting + IF is_item-abap_language_version IS NOT INITIAL AND iv_abap_language_version <> is_item-abap_language_version. + zcx_abapgit_exception=>raise( + |Object { is_item-obj_type } { is_item-obj_name } has { get_description( iv_abap_language_version ) }| && + | but repository is set to { get_description( is_item-abap_language_version ) }| ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + mo_dot_abapgit = io_dot_abapgit. + + IF zcl_abapgit_feature=>is_enabled( c_feature_flag ) = abap_false. + mv_has_abap_language_vers = abap_undefined. + ELSEIF get_abap_language_vers_by_repo( ) = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. + mv_has_abap_language_vers = abap_undefined. + ELSEIF get_abap_language_vers_by_repo( ) = zif_abapgit_dot_abapgit=>c_abap_language_version-ignore. + mv_has_abap_language_vers = abap_false. + ELSE. + mv_has_abap_language_vers = abap_true. + ENDIF. + + ENDMETHOD. + METHOD get_abap_language_vers_by_devc. + + DATA lv_class TYPE string. + DATA lv_abap_lang_version_devc TYPE string. + DATA lo_abap_language_version_cfg TYPE REF TO object. + + lv_class = 'CL_ABAP_LANGUAGE_VERSION_CFG'. + + TRY. + CALL METHOD (lv_class)=>('GET_INSTANCE') + RECEIVING + ro_instance = lo_abap_language_version_cfg. + + " For non-existing packages, GET_PACKAGE_DEFAULT_VERSION returns "standard" + " but we want to return "undefined" in this case to allow any new packages + IF zcl_abapgit_factory=>get_sap_package( iv_package )->exists( ) = abap_true. + CALL METHOD lo_abap_language_version_cfg->('IF_ABAP_LANGUAGE_VERSION_CFG~GET_PACKAGE_DEFAULT_VERSION') + EXPORTING + iv_package_name = iv_package + RECEIVING + rv_default_language_version = lv_abap_lang_version_devc. + ELSE. + lv_abap_lang_version_devc = '-'. + ENDIF. + + CASE lv_abap_lang_version_devc. + WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-standard. + rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-standard. + WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-key_user. + rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user. + WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-cloud_development. + rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development. + WHEN OTHERS. + rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. + ENDCASE. + + CATCH cx_root. + rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. + ENDTRY. + + ENDMETHOD. + METHOD get_abap_language_vers_by_objt. + + DATA lv_class TYPE string. + DATA lo_abap_language_version TYPE REF TO object. + + IF mv_has_abap_language_vers = abap_undefined. + rv_allowed_abap_langu_version = c_any_abap_language_version. + ELSEIF mv_has_abap_language_vers = abap_false. + rv_allowed_abap_langu_version = c_no_abap_language_version. + ELSE. " abap_true + + lv_class = 'CL_ABAP_LANGUAGE_VERSION'. + + TRY. + CALL METHOD (lv_class)=>('GET_INSTANCE') + RECEIVING + ro_version_handler = lo_abap_language_version. + + CALL METHOD lo_abap_language_version->('IF_ABAP_LANGUAGE_VERSION~GET_DEFAULT_VERSION') + EXPORTING + iv_object_type = iv_object_type + iv_package = iv_package + RECEIVING + rv_default_version = rv_allowed_abap_langu_version. + + CATCH cx_root. + rv_allowed_abap_langu_version = get_default_abap_language_vers( iv_object_type ). + ENDTRY. + + ENDIF. + + ENDMETHOD. + METHOD get_abap_language_vers_by_repo. + rv_abap_language_version = mo_dot_abapgit->get_abap_language_version( ). + IF rv_abap_language_version IS INITIAL. + rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. + ENDIF. + ENDMETHOD. + METHOD get_default_abap_language_vers. + + IF zcl_abapgit_factory=>get_environment( )->is_sap_cloud_platform( ) = abap_true. + " On BTP, default to ABAP for Cloud Development + rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_cloud-cloud_development. + ELSE. + " Differentiate between source code object and non-source code objects + CASE iv_object_type. + WHEN 'BDEF' OR 'CLAS' OR 'FUGR' OR 'FUGS' OR 'INTF' OR 'PROG' OR 'TYPE'. + rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard. + WHEN OTHERS. + rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version-standard. + ENDCASE. + ENDIF. + + ENDMETHOD. + METHOD get_description. + + CASE iv_abap_language_version. + WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-standard + OR zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard. + rv_description = 'Standard ABAP'. + WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-key_user + OR zif_abapgit_aff_types_v1=>co_abap_language_version_src-key_user. + rv_description = 'ABAP for Key Users'. + WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-cloud_development + OR zif_abapgit_aff_types_v1=>co_abap_language_version_src-cloud_development. + rv_description = 'ABAP for Cloud Development'. + WHEN OTHERS. + rv_description = 'Undefined'. + ENDCASE. + + rv_description = |ABAP language version "{ rv_description }"|. + + ENDMETHOD. + METHOD get_repo_abap_language_version. + + DATA lv_abap_language_version TYPE string. + + IF mv_has_abap_language_vers <> abap_undefined. " abap_true or abap_false + lv_abap_language_version = mo_dot_abapgit->get_abap_language_version( ). + ENDIF. + + CASE lv_abap_language_version. + WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-standard. + rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard. + WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-key_user. + rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-key_user. + WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development. + rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-cloud_development. + WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-ignore. + rv_abap_language_version = c_no_abap_language_version. + WHEN OTHERS. " undefined or feature off + rv_abap_language_version = c_any_abap_language_version. + ENDCASE. + + ENDMETHOD. + METHOD is_import_allowed. + + DATA lv_package_version TYPE string. + + lv_package_version = get_abap_language_vers_by_devc( iv_package ). + + CASE get_abap_language_vers_by_repo( ). + WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-undefined + OR zif_abapgit_dot_abapgit=>c_abap_language_version-ignore. + rv_allowed = abap_true. + WHEN OTHERS. + IF get_abap_language_vers_by_repo( ) = lv_package_version. + " allow packages that match repo setting + rv_allowed = abap_true. + ELSEIF lv_package_version = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. + " always allow new packages + rv_allowed = abap_true. + ELSE. + rv_allowed = abap_false. + ENDIF. + ENDCASE. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_diff_std IMPLEMENTATION. + METHOD adjust_diff. + + " ABAP kernel diff traverses files from bottom up which leads to odd display of diffs + " SAP won't adjust this kernel service so we will do it here + " https://github.com/abapGit/abapGit/issues/4395 + + TYPES: + BEGIN OF ty_diff_block, + start TYPE i, + len TYPE i, + END OF ty_diff_block. + + DATA: + lv_block_begin TYPE i, + lv_block_end TYPE i, + ls_diff_block TYPE ty_diff_block, + lt_diff_block TYPE STANDARD TABLE OF ty_diff_block WITH DEFAULT KEY. + + FIELD-SYMBOLS: + LIKE LINE OF gt_diff, + LIKE LINE OF gt_diff, + LIKE LINE OF gt_diff. + + " Determine start and length of diff blocks + LOOP AT gt_diff ASSIGNING . + IF -result = zif_abapgit_definitions=>c_diff-insert OR + -result = zif_abapgit_definitions=>c_diff-delete. + IF ls_diff_block IS INITIAL. + ls_diff_block-start = sy-tabix. + ENDIF. + ls_diff_block-len = ls_diff_block-len + 1. + ELSEIF ls_diff_block-start IS NOT INITIAL. + APPEND ls_diff_block TO lt_diff_block. + CLEAR ls_diff_block. + ENDIF. + ENDLOOP. + + " For each diff block, check if beginning is same as end of block + " If yes, move diff block down + LOOP AT lt_diff_block INTO ls_diff_block. + DO ls_diff_block-len TIMES. + lv_block_begin = ls_diff_block-start + sy-index - 1. + READ TABLE gt_diff ASSIGNING INDEX lv_block_begin. + IF sy-subrc <> 0. + EXIT. + ENDIF. + lv_block_end = ls_diff_block-start + ls_diff_block-len + sy-index - 1. + READ TABLE gt_diff ASSIGNING INDEX lv_block_end. + IF sy-subrc <> 0. + EXIT. + ENDIF. + CASE -result. + WHEN zif_abapgit_definitions=>c_diff-insert. + IF -new = -new. + -old_num = -old_num. + -old = -old. + -result = -result. + CLEAR: -result, -old_num, -old. + ELSE. + EXIT. + ENDIF. + WHEN zif_abapgit_definitions=>c_diff-delete. + IF -old = -old. + -new_num = -new_num. + -new = -new. + -result = -result. + CLEAR: -result, -new_num, -new. + ELSE. + EXIT. + ENDIF. + WHEN OTHERS. + EXIT. + ENDCASE. + ENDDO. + ENDLOOP. + + ENDMETHOD. + + METHOD unpack. + + DATA: lv_new TYPE string, + lv_old TYPE string, + lv_new_last TYPE c LENGTH 1, + lv_old_last TYPE c LENGTH 1. + + lv_new = zcl_abapgit_convert=>xstring_to_string_utf8( iv_new ). + lv_old = zcl_abapgit_convert=>xstring_to_string_utf8( iv_old ). + + " Check if one value contains a final newline but the other not + " If yes, add a special character that's visible in diff render + IF lv_new IS NOT INITIAL. + lv_new_last = substring( + val = lv_new + off = strlen( lv_new ) - 1 ). + ENDIF. + IF lv_old IS NOT INITIAL. + lv_old_last = substring( + val = lv_old + off = strlen( lv_old ) - 1 ). + ENDIF. + + IF lv_new_last = cl_abap_char_utilities=>newline AND lv_old_last <> cl_abap_char_utilities=>newline + AND lv_old IS NOT INITIAL. + lv_old = lv_old && cl_abap_char_utilities=>form_feed. + ELSEIF lv_new_last <> cl_abap_char_utilities=>newline AND lv_old_last = cl_abap_char_utilities=>newline + AND lv_new IS NOT INITIAL. + lv_new = lv_new && cl_abap_char_utilities=>form_feed. + ENDIF. + + SPLIT lv_new AT cl_abap_char_utilities=>newline INTO TABLE et_new. + SPLIT lv_old AT cl_abap_char_utilities=>newline INTO TABLE et_old. + + ENDMETHOD. + + METHOD compute. + DATA: lt_new TYPE rswsourcet, + lt_old TYPE rswsourcet. + + gv_compare_mode = 1. + IF iv_ignore_indentation = abap_true. + gv_compare_mode = gv_compare_mode + 1. + ENDIF. + IF iv_ignore_comments = abap_true. + gv_compare_mode = gv_compare_mode + 2. + ENDIF. + gv_ignore_case = iv_ignore_case. + + unpack( EXPORTING iv_new = iv_new + iv_old = iv_old + IMPORTING et_new = lt_new + et_old = lt_old ). + + gt_diff = compute_diff( it_new = lt_new + it_old = lt_old ). + + adjust_diff( ). + + rt_diff = gt_diff. + + ENDMETHOD. + + METHOD compute_diff. + + DATA: + lv_i TYPE i, + ls_diff LIKE LINE OF rt_diff, + lt_delta TYPE STANDARD TABLE OF rsedcresul WITH DEFAULT KEY. + + FIELD-SYMBOLS LIKE LINE OF lt_delta. + + " Note: Ignore case is for keywords, variables, types etc, but not for literals + CALL FUNCTION 'RS_CMP_COMPUTE_DELTA' + EXPORTING + compare_mode = gv_compare_mode + ignore_case_differences = gv_ignore_case + TABLES + text_tab1 = it_new + text_tab2 = it_old + text_tab_res = lt_delta + EXCEPTIONS + parameter_invalid = 1 + difference_not_found = 2 + OTHERS = 3. + + IF sy-subrc = 0. + " Process delta + LOOP AT lt_delta ASSIGNING . + CLEAR ls_diff. + IF -line1 > 0. + lv_i = -line1. + ls_diff-old_num = lv_i. + ls_diff-old = -text1. + ENDIF. + IF -line2 > 0. + lv_i = -line2. + ls_diff-new_num = lv_i. + ls_diff-new = -text2. + ENDIF. + IF -flag1 = 'D'. + ls_diff-result = zif_abapgit_definitions=>c_diff-delete. + ELSEIF -flag2 = 'I'. + ls_diff-result = zif_abapgit_definitions=>c_diff-insert. + ELSEIF -flag1 = 'M' AND -flag2 = 'M'. + ls_diff-result = zif_abapgit_definitions=>c_diff-update. + ELSEIF -flag1 = '' AND -flag2 = ''. + ls_diff-result = zif_abapgit_definitions=>c_diff-unchanged. + ELSEIF -flag1 = '' AND -flag2 = 'E'. " ignore comment + ls_diff-result = zif_abapgit_definitions=>c_diff-unchanged. + ELSEIF -flag1 = 'E' AND -flag2 = ''. " ignore comment + ls_diff-result = zif_abapgit_definitions=>c_diff-unchanged. + ELSE. + ASSERT 0 = 1. " unknown comparison result + ENDIF. + APPEND ls_diff TO rt_diff. + ENDLOOP. + ELSEIF sy-subrc = 2. + " The function doesn't find all diffs... + rt_diff = compute_diff_extra( it_new = it_new + it_old = it_old ). + ELSE. + ASSERT 0 = 1. " incorrect function call + ENDIF. + + ENDMETHOD. + METHOD compute_diff_extra. + + DATA: + ls_diff LIKE LINE OF rt_diff. + + FIELD-SYMBOLS: + LIKE LINE OF it_old, + LIKE LINE OF it_new. + + LOOP AT it_old ASSIGNING . + CLEAR ls_diff. + ls_diff-old_num = sy-tabix. + ls_diff-old = . + READ TABLE it_new ASSIGNING INDEX sy-tabix. + IF sy-subrc <> 0. + EXIT. + ENDIF. + ls_diff-new_num = sy-tabix. + ls_diff-new = . + + IF ( gv_compare_mode = 1 OR gv_compare_mode = 3 ) + AND has_line_diff( iv_old = + iv_new = ) = abap_true. + ls_diff-result = zif_abapgit_definitions=>c_diff-update. + ENDIF. + APPEND ls_diff TO rt_diff. + ENDLOOP. + + ENDMETHOD. + + METHOD has_line_diff. + + " SAP function ignores lines that contain only whitespace so we compare directly + " Also check if length differs and implicitly if one line has trailing space(s) + rv_has_diff = boolc( iv_old <> iv_new + AND ( strlen( condense( iv_old ) ) = 0 + OR strlen( condense( iv_new ) ) = 0 + OR strlen( iv_old ) <> strlen( iv_new ) ) ). + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_diff_factory IMPLEMENTATION. + + METHOD get. + CREATE OBJECT ri_diff TYPE zcl_abapgit_diff. + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_diff_diff3 IMPLEMENTATION. + METHOD compute. +* Beware: this is AI generated code -Hvam 2025-09-29 + DATA: lv_new TYPE string, + lv_old TYPE string, + lv_new_last TYPE c LENGTH 1, + lv_old_last TYPE c LENGTH 1, + lt_new TYPE string_table, + lt_old TYPE string_table, + lt_comm TYPE zif_abapgit_diff3=>ty_comm_result_t, + lo_diff3 TYPE REF TO zif_abapgit_diff3, + ls_comm LIKE LINE OF lt_comm, + ls_diff TYPE zif_abapgit_definitions=>ty_diff, + lt_ins TYPE string_table, + lt_del TYPE string_table, + lv_line TYPE string, + lv_max TYPE i, + lv_new_idx TYPE i VALUE 0, + lv_old_idx TYPE i VALUE 0, + lv_i TYPE i. + + CLEAR rt_diff. + + lv_new = zcl_abapgit_convert=>xstring_to_string_utf8( iv_new ). + lv_old = zcl_abapgit_convert=>xstring_to_string_utf8( iv_old ). + + IF lv_new IS NOT INITIAL. + lv_new_last = substring( + val = lv_new + off = strlen( lv_new ) - 1 ). + ENDIF. + IF lv_old IS NOT INITIAL. + lv_old_last = substring( + val = lv_old + off = strlen( lv_old ) - 1 ). + ENDIF. + IF lv_new_last = cl_abap_char_utilities=>newline + AND lv_old_last <> cl_abap_char_utilities=>newline + AND lv_old IS NOT INITIAL. + lv_old = lv_old && cl_abap_char_utilities=>form_feed. + ELSEIF lv_new_last <> cl_abap_char_utilities=>newline + AND lv_old_last = cl_abap_char_utilities=>newline + AND lv_new IS NOT INITIAL. + lv_new = lv_new && cl_abap_char_utilities=>form_feed. + ENDIF. + + SPLIT lv_new AT cl_abap_char_utilities=>newline INTO TABLE lt_new. + SPLIT lv_old AT cl_abap_char_utilities=>newline INTO TABLE lt_old. + + lo_diff3 = zcl_abapgit_diff3=>create( ). + lt_comm = lo_diff3->diff_comm( + it_buffer1 = lt_new + it_buffer2 = lt_old ). + + LOOP AT lt_comm INTO ls_comm. + IF ls_comm-common IS NOT INITIAL. + LOOP AT ls_comm-common INTO lv_line. + lv_new_idx = lv_new_idx + 1. + lv_old_idx = lv_old_idx + 1. + CLEAR ls_diff. + lv_i = lv_new_idx. + ls_diff-new_num = lv_i. + lv_i = lv_old_idx. + ls_diff-old_num = lv_i. + ls_diff-new = lv_line. + ls_diff-old = lv_line. + ls_diff-result = zif_abapgit_definitions=>c_diff-unchanged. + APPEND ls_diff TO rt_diff. + ENDLOOP. + ELSE. + lt_ins = ls_comm-diff-buffer1. + lt_del = ls_comm-diff-buffer2. + lv_max = lines( lt_ins ). + IF lines( lt_del ) > lv_max. + lv_max = lines( lt_del ). + ENDIF. + DO lv_max TIMES. + CLEAR ls_diff. + IF sy-index <= lines( lt_del ) AND sy-index <= lines( lt_ins ). + lv_old_idx = lv_old_idx + 1. + lv_new_idx = lv_new_idx + 1. + lv_i = lv_new_idx. + ls_diff-new_num = lv_i. + lv_i = lv_old_idx. + ls_diff-old_num = lv_i. + READ TABLE lt_ins INDEX sy-index INTO lv_line. + IF sy-subrc = 0. + ls_diff-new = lv_line. + ENDIF. + READ TABLE lt_del INDEX sy-index INTO lv_line. + IF sy-subrc = 0. + ls_diff-old = lv_line. + ENDIF. + ls_diff-result = zif_abapgit_definitions=>c_diff-update. + ELSEIF sy-index <= lines( lt_del ). + lv_old_idx = lv_old_idx + 1. + READ TABLE lt_del INDEX sy-index INTO lv_line. + IF sy-subrc = 0. + ls_diff-old = lv_line. + ENDIF. + ls_diff-old_num = lv_old_idx. + ls_diff-result = zif_abapgit_definitions=>c_diff-delete. + ELSEIF sy-index <= lines( lt_ins ). + lv_new_idx = lv_new_idx + 1. + READ TABLE lt_ins INDEX sy-index INTO lv_line. + IF sy-subrc = 0. + ls_diff-new = lv_line. + ENDIF. + ls_diff-new_num = lv_new_idx. + ls_diff-result = zif_abapgit_definitions=>c_diff-insert. + ENDIF. + APPEND ls_diff TO rt_diff. + ENDDO. + ENDIF. + ENDLOOP. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_diff IMPLEMENTATION. + + METHOD calculate_stats. + + FIELD-SYMBOLS LIKE LINE OF mt_diff. + + LOOP AT mt_diff ASSIGNING . + CASE -result. + WHEN zif_abapgit_definitions=>c_diff-insert. + ms_stats-insert = ms_stats-insert + 1. + WHEN zif_abapgit_definitions=>c_diff-delete. + ms_stats-delete = ms_stats-delete + 1. + WHEN zif_abapgit_definitions=>c_diff-update. + ms_stats-update = ms_stats-update + 1. + ENDCASE. + ENDLOOP. + + ENDMETHOD. + + METHOD zif_abapgit_diff~create. + + IF zcl_abapgit_factory=>get_function_module( )->function_exists( 'RS_CMP_COMPUTE_DELTA' ) = abap_true. + mt_diff = zcl_abapgit_diff_std=>compute( + iv_new = iv_new + iv_old = iv_old + iv_ignore_indentation = iv_ignore_indentation + iv_ignore_comments = iv_ignore_comments + iv_ignore_case = iv_ignore_case ). + ELSE. + mt_diff = zcl_abapgit_diff_diff3=>compute( + iv_new = iv_new + iv_old = iv_old ). + " iv_ignore_indentation = iv_ignore_indentation + " iv_ignore_comments = iv_ignore_comments + " iv_ignore_case = iv_ignore_case + ENDIF. + + calculate_stats( ). + map_beacons( ). + shortlist( ). + + ri_diff = me. + + ENDMETHOD. + METHOD create_regex_set. + + DATA: lo_regex TYPE REF TO cl_abap_regex, + lt_regex TYPE zif_abapgit_definitions=>ty_string_tt, + lv_regex LIKE LINE OF lt_regex. + + APPEND '^\s*(CLASS|FORM|MODULE|REPORT|METHOD|INTERFACE|FUNCTION)\s[^=]' TO lt_regex. + APPEND '^\s*(PUBLIC|PROTECTED|PRIVATE)\sSECTION(\s|\.)' TO lt_regex. + APPEND '^\s*(CLASS|INTERFACE|FUNCTION|TYPE)-POOL\s' TO lt_regex. + APPEND '^\s*(START|END)-OF-SELECTION(\s|\.)' TO lt_regex. + APPEND '^\s*INITIALIZATION(\s|\.)' TO lt_regex. + APPEND '^\s*(TOP-OF-PAGE|END-OF-PAGE)(\s|\.)' TO lt_regex. + APPEND '^\s*AT\s*(SELECTION-SCREEN|LINE-SELECTION|USER-COMMAND|PF\d+)(\s|\.)' TO lt_regex. + APPEND '^\s*(DEFINE|ENHANCEMENT)\s' TO lt_regex. + + LOOP AT lt_regex INTO lv_regex. + CREATE OBJECT lo_regex + EXPORTING + pattern = lv_regex + ignore_case = abap_true. + APPEND lo_regex TO rt_regex_set. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_diff~get. + rt_diff = mt_diff. + ENDMETHOD. + METHOD zif_abapgit_diff~get_beacons. + rt_beacons = mt_beacons. + ENDMETHOD. + METHOD zif_abapgit_diff~is_line_patched. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. + + READ TABLE mt_diff INDEX iv_index + ASSIGNING . + IF sy-subrc = 0. + rv_patched = -patch_flag. + ELSE. + zcx_abapgit_exception=>raise( |Diff line not found { iv_index }| ). + ENDIF. + + ENDMETHOD. + METHOD map_beacons. + + DATA: lv_beacon_idx TYPE i VALUE c_starting_beacon, + lv_offs TYPE i, + lv_beacon_str TYPE string, + lv_beacon_2lev TYPE string, + lv_submatch TYPE string, + lo_regex TYPE REF TO cl_abap_regex, + lt_regex TYPE ty_regexset_tt. + + FIELD-SYMBOLS: LIKE LINE OF mt_diff. + + lt_regex = create_regex_set( ). + LOOP AT mt_diff ASSIGNING . + + CLEAR lv_offs. + -beacon = lv_beacon_idx. + + LOOP AT lt_regex INTO lo_regex. + FIND FIRST OCCURRENCE OF REGEX lo_regex IN -new SUBMATCHES lv_submatch. + IF sy-subrc = 0. " Match + lv_beacon_str = -new. + lv_submatch = to_upper( lv_submatch ). + + " Get rid of comments and end of line + FIND FIRST OCCURRENCE OF '.' IN lv_beacon_str MATCH OFFSET lv_offs. + IF sy-subrc <> 0. + FIND FIRST OCCURRENCE OF '"' IN lv_beacon_str MATCH OFFSET lv_offs. + ENDIF. + + IF lv_offs > 0. + lv_beacon_str = lv_beacon_str(lv_offs). + ENDIF. + lv_beacon_str = condense( val = lv_beacon_str + del = ` ` ). + + IF lv_submatch = 'CLASS'. + lv_beacon_2lev = replace( val = lv_beacon_str + regex = '\s+(DEFINITION|IMPLEMENTATION)' + with = '' + occ = 0 ). + ELSEIF lv_submatch = 'METHOD'. + lv_beacon_str = lv_beacon_2lev && ` => ` && lv_beacon_str. + ELSEIF lv_submatch = 'PUBLIC' OR lv_submatch = 'PROTECTED' OR lv_submatch = 'PRIVATE'. + lv_beacon_str = lv_beacon_2lev && ` ` && lv_beacon_str. + ENDIF. + + APPEND lv_beacon_str TO mt_beacons. + lv_beacon_idx = sy-tabix. + -beacon = lv_beacon_idx. + EXIT. "Loop + ENDIF. + ENDLOOP. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_diff~set_patch_by_old_diff. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. + + LOOP AT mt_diff ASSIGNING + USING KEY new_num + WHERE old = is_diff_old-old + AND new = is_diff_old-new + AND new_num = is_diff_old-new_num + AND old_num = is_diff_old-old_num. + + -patch_flag = iv_patch_flag. + EXIT. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_diff~set_patch_new. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. + + READ TABLE mt_diff WITH TABLE KEY new_num + COMPONENTS new_num = iv_line_new + ASSIGNING . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Invalid new line number { iv_line_new }| ). + ENDIF. + + -patch_flag = iv_patch_flag. + + ENDMETHOD. + METHOD zif_abapgit_diff~set_patch_old. + + FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. + + READ TABLE mt_diff WITH TABLE KEY old_num + COMPONENTS old_num = iv_line_old + ASSIGNING . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Invalid old line number { iv_line_old }| ). + ENDIF. + + -patch_flag = iv_patch_flag. + + ENDMETHOD. + METHOD shortlist. + + DATA: lv_index TYPE i. + + FIELD-SYMBOLS: LIKE LINE OF mt_diff. + + IF lines( mt_diff ) < 20. + LOOP AT mt_diff ASSIGNING . + -short = abap_true. + ENDLOOP. + ELSE. + LOOP AT mt_diff TRANSPORTING NO FIELDS + WHERE NOT result IS INITIAL AND short = abap_false. + lv_index = sy-tabix. + + DO 8 TIMES. " Backward + READ TABLE mt_diff INDEX ( lv_index - sy-index ) ASSIGNING . + IF sy-subrc <> 0 OR -short = abap_true. " tab bound or prev marker + EXIT. + ENDIF. + -short = abap_true. + ENDDO. + + DO 8 TIMES. " Forward + READ TABLE mt_diff INDEX ( lv_index + sy-index - 1 ) ASSIGNING . + IF sy-subrc <> 0. " tab bound reached + EXIT. + ENDIF. + CHECK -short = abap_false. " skip marked + -short = abap_true. + ENDDO. + + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_diff~stats. + rs_count = ms_stats. + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_diff3 IMPLEMENTATION. + METHOD add_hunk. + " hunks are array subsets where `a` or `b` are different from `o` + " https://www.gnu.org/software/diffutils/manual/html_node/diff3-Hunks.html + + DATA ls_hunk LIKE LINE OF ct_hunks. + + FIELD-SYMBOLS LIKE LINE OF it_buffer. + LOOP AT it_buffer ASSIGNING . + ls_hunk-ab = iv_ab. + ls_hunk-o_start = -buffer1-key. + ls_hunk-o_length = -buffer1-len. + ls_hunk-ab_start = -buffer2-key. + ls_hunk-ab_length = -buffer2-len. + INSERT ls_hunk INTO TABLE ct_hunks. + ENDLOOP. + + ENDMETHOD. + METHOD advance_to. + + DATA ls_result LIKE LINE OF ct_results. + + IF iv_end_offset > cv_curr_offset. + ls_result-stable = abap_true. + CLEAR ls_result-stable_region. + ls_result-stable_region-buffer = 'o'. + ls_result-stable_region-buffer_start = cv_curr_offset. + ls_result-stable_region-buffer_length = iv_end_offset - cv_curr_offset. + ls_result-stable_region-buffer_content = _slice( +it_data = it_o +iv_start = cv_curr_offset +iv_end = iv_end_offset ). + INSERT ls_result INTO TABLE ct_results. + cv_curr_offset = iv_end_offset. + ENDIF. + + ENDMETHOD. + METHOD chunk_description. + DATA temp1 LIKE LINE OF it_buffer. + DATA temp2 LIKE sy-tabix. + + rs_result-offset = iv_offset. + rs_result-length = iv_length. + + DO iv_length TIMES. + temp2 = sy-tabix. + READ TABLE it_buffer INDEX iv_offset + sy-index INTO temp1. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + APPEND temp1 TO rs_result-chunk. + ENDDO. + + ENDMETHOD. + METHOD convert_to_abap_indices. + + FIELD-SYMBOLS LIKE LINE OF ct_diff_indices. + LOOP AT ct_diff_indices ASSIGNING . + -buffer1-key = -buffer1-key + 1. + -buffer2-key = -buffer2-key + 1. + ENDLOOP. + + ENDMETHOD. + METHOD create. + + CREATE OBJECT ri_result TYPE zcl_abapgit_diff3. + + ENDMETHOD. + METHOD flush_ok. + + DATA ls_result LIKE LINE OF ct_result. + + IF ct_buffer IS NOT INITIAL. + INSERT LINES OF ct_buffer INTO TABLE ls_result-ok. + INSERT ls_result INTO TABLE ct_result. + CLEAR ct_buffer. + ENDIF. + + ENDMETHOD. + METHOD get_labels. + + CLEAR rs_labels. + rs_labels-a = `<<<<<<<`. + rs_labels-o = `|||||||`. + rs_labels-x = `=======`. + rs_labels-b = `>>>>>>>`. + + IF is_labels-a IS NOT INITIAL. + rs_labels-a = rs_labels-a && | { is_labels-a }|. + ENDIF. + IF is_labels-o IS NOT INITIAL. + rs_labels-o = rs_labels-o && | { is_labels-o }|. + ENDIF. + IF is_labels-b IS NOT INITIAL. + rs_labels-b = rs_labels-b && | { is_labels-b }|. + ENDIF. + + ENDMETHOD. + METHOD process_common. + DATA temp3 TYPE zif_abapgit_diff3=>ty_comm_result. + DATA ls_res LIKE temp3. + + IF ct_common IS NOT INITIAL. + + CLEAR temp3. + temp3-common = _reverse( ct_common ). + + ls_res = temp3. + INSERT ls_res INTO ct_result INDEX 1. + CLEAR ct_common. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_diff3~diff3_merge. + " Applies the output of diff3MergeRegions to actually + " construct the merged buffer; the returned result alternates + " between 'ok' and 'conflict' blocks. + " A "false conflict" is where `a` and `b` both change the same from `o` + + DATA ls_result LIKE LINE OF rt_result. + DATA lt_ok_buffer TYPE string_table. + + DATA lt_regions TYPE zif_abapgit_diff3=>ty_region_t. + FIELD-SYMBOLS LIKE LINE OF lt_regions. + lt_regions = zif_abapgit_diff3~diff3_merge_regions( + it_a = it_a + it_o = it_o + it_b = it_b ). + LOOP AT lt_regions ASSIGNING . + IF -stable = abap_true. + INSERT LINES OF -stable_region-buffer_content INTO TABLE lt_ok_buffer. + ELSE. + IF iv_exclude_false_conflicts = abap_true AND + -unstable_region-a_length = -unstable_region-b_length AND + -unstable_region-a_content = -unstable_region-b_content. + INSERT LINES OF -unstable_region-a_content INTO TABLE lt_ok_buffer. + ELSE. + flush_ok( + CHANGING + ct_buffer = lt_ok_buffer + ct_result = rt_result ). + + CLEAR ls_result. + CLEAR ls_result-conflict. + ls_result-conflict-a = -unstable_region-a_content. + ls_result-conflict-a_index = -unstable_region-a_start. + ls_result-conflict-o = -unstable_region-o_content. + ls_result-conflict-o_index = -unstable_region-o_start. + ls_result-conflict-b = -unstable_region-b_content. + ls_result-conflict-b_index = -unstable_region-b_start. + INSERT ls_result INTO TABLE rt_result. + ENDIF. + ENDIF. + ENDLOOP. + + flush_ok( + CHANGING + ct_buffer = lt_ok_buffer + ct_result = rt_result ). + + ENDMETHOD. + METHOD zif_abapgit_diff3~diff3_merge_regions. + " Given three buffers, A, O, and B, where both A and B are + " independently derived from O, returns a fairly complicated + " internal representation of merge decisions it's taken. The + " interested reader may wish to consult + " + " Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. + " 'A Formal Investigation of ' In Arvind and Prasad, + " editors, Foundations of Software Technology and Theoretical + " Computer Science (FSTTCS), December 2007. + " + " (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf) + + TYPES: + BEGIN OF ty_bound, + n0 TYPE zif_abapgit_diff3=>ty_number, + n1 TYPE zif_abapgit_diff3=>ty_number, + n2 TYPE zif_abapgit_diff3=>ty_number, + n3 TYPE zif_abapgit_diff3=>ty_number, + END OF ty_bound. + + DATA: + ls_result LIKE LINE OF rt_result, + lt_hunks TYPE STANDARD TABLE OF ty_hunk WITH DEFAULT KEY, + lt_region_hunks TYPE STANDARD TABLE OF ty_hunk WITH DEFAULT KEY. + + DATA: + BEGIN OF ls_bounds, + a TYPE ty_bound, + b TYPE ty_bound, + END OF ls_bounds. + DATA lv_curr_offset TYPE i. + DATA lv_hunk TYPE i. + DATA ls_hunk LIKE LINE OF lt_hunks. + DATA temp1 LIKE LINE OF lt_hunks. + DATA temp2 LIKE sy-tabix. + DATA lv_region_start LIKE ls_hunk-o_start. + DATA lv_region_end TYPE zif_abapgit_diff3=>ty_number. + DATA ls_next_hunk LIKE LINE OF lt_hunks. + DATA temp3 LIKE LINE OF lt_hunks. + DATA temp7 LIKE sy-tabix. + DATA lv_next_hunk_start LIKE ls_next_hunk-o_start. + FIELD-SYMBOLS TYPE string_table. + DATA lv_region_hunk TYPE i. + DATA temp4 LIKE LINE OF lt_region_hunks. + DATA temp5 LIKE sy-tabix. + DATA lv_o_start LIKE ls_hunk-o_start. + DATA lv_o_end TYPE zif_abapgit_diff3=>ty_number. + DATA lv_ab_start LIKE ls_hunk-ab_start. + DATA lv_ab_end TYPE zif_abapgit_diff3=>ty_number. + FIELD-SYMBOLS TYPE ty_bound. + DATA temp6 TYPE ty_bound. + DATA ls_b LIKE temp6. + DATA lv_a_start TYPE zif_abapgit_diff3=>ty_number. + DATA lv_a_end TYPE zif_abapgit_diff3=>ty_number. + DATA lv_b_start TYPE zif_abapgit_diff3=>ty_number. + DATA lv_b_end TYPE zif_abapgit_diff3=>ty_number. + + add_hunk( + EXPORTING + it_buffer = zif_abapgit_diff3~diff_indices( + it_buffer1 = it_o + it_buffer2 = it_a ) + iv_ab = 'a' + CHANGING + ct_hunks = lt_hunks ). + + add_hunk( + EXPORTING + it_buffer = zif_abapgit_diff3~diff_indices( + it_buffer1 = it_o + it_buffer2 = it_b ) + iv_ab = 'b' + CHANGING + ct_hunks = lt_hunks ). + + SORT lt_hunks BY o_start ab. + lv_curr_offset = 0. + lv_hunk = 0. + WHILE lv_hunk < lines( lt_hunks ). + + temp2 = sy-tabix. + READ TABLE lt_hunks INDEX lv_hunk + 1 INTO temp1. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_hunk = temp1. + lv_hunk = lv_hunk + 1. + lv_region_start = ls_hunk-o_start. + + lv_region_end = ls_hunk-o_start + ls_hunk-o_length. + + CLEAR lt_region_hunks. + INSERT ls_hunk INTO TABLE lt_region_hunks. + + advance_to( + EXPORTING + iv_end_offset = lv_region_start + it_o = it_o + CHANGING + cv_curr_offset = lv_curr_offset + ct_results = rt_result ). + + " Try to pull next overlapping hunk into this region + WHILE lv_hunk < lines( lt_hunks ). + + temp7 = sy-tabix. + READ TABLE lt_hunks INDEX lv_hunk + 1 INTO temp3. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_next_hunk = temp3. + + lv_next_hunk_start = ls_next_hunk-o_start. + + IF lv_next_hunk_start > lv_region_end. + EXIT. " no overlap + ENDIF. + + lv_region_end = nmax( + val1 = lv_region_end + val2 = lv_next_hunk_start + ls_next_hunk-o_length ). + + INSERT ls_next_hunk INTO TABLE lt_region_hunks. + lv_hunk = lv_hunk + 1. + ENDWHILE. + + IF lines( lt_region_hunks ) = 1. + " Only one hunk touches this region, meaning that there is no conflict here. + " either `a` or `b` is inserting into a region of `o` unchanged by the other. + IF ls_hunk-ab_length > 0. + IF ls_hunk-ab = 'a'. + + ASSIGN it_a TO . + ASSERT sy-subrc = 0. + ELSE. + ASSIGN it_b TO . + ASSERT sy-subrc = 0. + ENDIF. + CLEAR ls_result. + ls_result-stable = abap_true. + CLEAR ls_result-stable_region. + ls_result-stable_region-buffer = ls_hunk-ab. + ls_result-stable_region-buffer_start = ls_hunk-ab_start. + ls_result-stable_region-buffer_length = ls_hunk-ab_length. + ls_result-stable_region-buffer_content = _slice( +it_data = +iv_start = ls_hunk-ab_start +iv_end = ls_hunk-ab_start + ls_hunk-ab_length ). + INSERT ls_result INTO TABLE rt_result. + ENDIF. + ELSE. + " a true a/b conflict. determine the bounds involved from `a`, `o`, and `b`. + " effectively merge all the `a` hunks into one giant hunk, then do the + " same for the `b` hunks. then, correct for skew in the regions of `o` + " that each side changed, and report appropriate spans for the three sides. + CLEAR ls_bounds. + CLEAR ls_bounds-a. + ls_bounds-a-n0 = lines( it_a ). + ls_bounds-a-n1 = -1. + ls_bounds-a-n2 = lines( it_o ). + ls_bounds-a-n3 = -1. + CLEAR ls_bounds-b. + ls_bounds-b-n0 = lines( it_b ). + ls_bounds-b-n1 = -1. + ls_bounds-b-n2 = lines( it_o ). + ls_bounds-b-n3 = -1. + lv_region_hunk = 0. + WHILE lv_region_hunk < lines( lt_region_hunks ). + temp5 = sy-tabix. + READ TABLE lt_region_hunks INDEX lv_region_hunk + 1 INTO temp4. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_hunk = temp4. + lv_region_hunk = lv_region_hunk + 1. + lv_o_start = ls_hunk-o_start. + + lv_o_end = lv_o_start + ls_hunk-o_length. + + lv_ab_start = ls_hunk-ab_start. + + lv_ab_end = lv_ab_start + ls_hunk-ab_length. + + IF ls_hunk-ab = 'a'. + + ASSIGN ls_bounds-a TO . + ASSERT sy-subrc = 0. + ELSE. + ASSIGN ls_bounds-b TO . + ASSERT sy-subrc = 0. + ENDIF. + CLEAR temp6. + temp6-n0 = nmin( val1 = lv_ab_start + val2 = -n0 ). + temp6-n1 = nmax( val1 = lv_ab_end + val2 = -n1 ). + temp6-n2 = nmin( val1 = lv_o_start + val2 = -n2 ). + temp6-n3 = nmax( val1 = lv_o_end + val2 = -n3 ). + + ls_b = temp6. + = ls_b. + ENDWHILE. + lv_a_start = ls_bounds-a-n0 + lv_region_start - ls_bounds-a-n2. + + lv_a_end = ls_bounds-a-n1 + lv_region_end - ls_bounds-a-n3. + + lv_b_start = ls_bounds-b-n0 + lv_region_start - ls_bounds-b-n2. + + lv_b_end = ls_bounds-b-n1 + lv_region_end - ls_bounds-b-n3. + + CLEAR ls_result. + ls_result-stable = abap_false. + CLEAR ls_result-unstable_region. + ls_result-unstable_region-a_start = lv_a_start. + ls_result-unstable_region-a_length = lv_a_end - lv_a_start. + ls_result-unstable_region-a_content = _slice( +it_data = it_a +iv_start = lv_a_start +iv_end = lv_a_end ). + ls_result-unstable_region-o_start = lv_region_start. + ls_result-unstable_region-o_length = lv_region_end - lv_region_start. + ls_result-unstable_region-o_content = _slice( +it_data = it_o +iv_start = lv_region_start +iv_end = lv_region_end ). + ls_result-unstable_region-b_start = lv_b_start. + ls_result-unstable_region-b_length = lv_b_end - lv_b_start. + ls_result-unstable_region-b_content = _slice( +it_data = it_b +iv_start = lv_b_start +iv_end = lv_b_end ). + INSERT ls_result INTO TABLE rt_result. + ENDIF. + + lv_curr_offset = lv_region_end. + ENDWHILE. + + advance_to( + EXPORTING + iv_end_offset = lines( it_o ) + it_o = it_o + CHANGING + cv_curr_offset = lv_curr_offset + ct_results = rt_result ). + + ENDMETHOD. + METHOD zif_abapgit_diff3~diff_comm. + " We apply the LCS to build a 'comm'-style picture of the + " differences between buffer1 and buffer2. + + DATA: + ls_res LIKE LINE OF rt_result, + ls_different TYPE zif_abapgit_diff3=>ty_comm_result-diff, + lt_common TYPE zif_abapgit_diff3=>ty_comm_result-common. + + DATA lt_lcs TYPE zif_abapgit_diff3=>ty_lcs_result_t. + DATA lv_tail1 TYPE i. + DATA lv_tail2 TYPE i. + DATA ls_candidate LIKE LINE OF lt_lcs. + DATA temp15 LIKE LINE OF lt_lcs. + DATA temp16 LIKE sy-tabix. + DATA temp7 LIKE LINE OF it_buffer1. + DATA temp8 LIKE sy-tabix. + DATA temp9 LIKE LINE OF it_buffer2. + DATA temp10 LIKE sy-tabix. + DATA temp11 LIKE LINE OF it_buffer1. + DATA temp12 LIKE sy-tabix. + DATA temp13 LIKE LINE OF lt_lcs. + DATA temp14 LIKE sy-tabix. + DATA lv_key TYPE i. + lt_lcs = zif_abapgit_diff3~lcs( it_buffer1 = it_buffer1 + it_buffer2 = it_buffer2 ). + lv_tail1 = lines( it_buffer1 ). + + lv_tail2 = lines( it_buffer2 ). + + temp16 = sy-tabix. + lv_key = lines( lt_lcs ) - 1. + READ TABLE lt_lcs WITH KEY key = lv_key INTO temp15. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_candidate = temp15. + DO. + CLEAR ls_different. + + DO. + lv_tail1 = lv_tail1 - 1. + IF lv_tail1 <= ls_candidate-buffer1index. + EXIT. + ENDIF. + temp8 = sy-tabix. + READ TABLE it_buffer1 INDEX lv_tail1 + 1 INTO temp7. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + INSERT temp7 INTO TABLE ls_different-buffer1. + ENDDO. + + DO. + lv_tail2 = lv_tail2 - 1. + IF lv_tail2 <= ls_candidate-buffer2index. + EXIT. + ENDIF. + temp10 = sy-tabix. + READ TABLE it_buffer2 INDEX lv_tail2 + 1 INTO temp9. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + INSERT temp9 INTO TABLE ls_different-buffer2. + ENDDO. + + IF lines( ls_different-buffer1 ) > 0 OR lines( ls_different-buffer2 ) > 0. + process_common( + CHANGING + ct_common = lt_common + ct_result = rt_result ). + + CLEAR ls_res. + ls_res-diff-buffer1 = _reverse( ls_different-buffer1 ). + ls_res-diff-buffer2 = _reverse( ls_different-buffer2 ). + INSERT ls_res INTO rt_result INDEX 1. + ENDIF. + + IF lv_tail1 >= 0. + temp12 = sy-tabix. + READ TABLE it_buffer1 INDEX lv_tail1 + 1 INTO temp11. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + INSERT temp11 INTO TABLE lt_common. + ENDIF. + + IF ls_candidate-chain = -1. + EXIT. + ENDIF. + + temp14 = sy-tabix. + READ TABLE lt_lcs WITH KEY key = ls_candidate-chain INTO temp13. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_candidate = temp13. + ENDDO. + + process_common( + CHANGING + ct_common = lt_common + ct_result = rt_result ). + + ENDMETHOD. + METHOD zif_abapgit_diff3~diff_indices. + " We apply the LCS to give a simple representation of the + " offsets and lengths of mismatched chunks in the input + " buffers. This is used by diff3MergeRegions. + + DATA lt_lcs TYPE zif_abapgit_diff3=>ty_lcs_result_t. + DATA lv_tail1 TYPE i. + DATA lv_tail2 TYPE i. + DATA ls_candidate LIKE LINE OF lt_lcs. + DATA temp18 LIKE LINE OF lt_lcs. + DATA temp19 LIKE sy-tabix. + DATA lv_mismatch_length1 TYPE i. + DATA lv_mismatch_length2 TYPE i. + DATA temp15 TYPE zif_abapgit_diff3=>ty_diff_indices_result. + DATA ls_result LIKE temp15. + DATA temp16 LIKE LINE OF lt_lcs. + DATA temp17 LIKE sy-tabix. + DATA lv_key TYPE i. + lt_lcs = zif_abapgit_diff3~lcs( + it_buffer1 = it_buffer1 + it_buffer2 = it_buffer2 ). + lv_tail1 = lines( it_buffer1 ). + + lv_tail2 = lines( it_buffer2 ). + + temp19 = sy-tabix. + lv_key = lines( lt_lcs ) - 1. + READ TABLE lt_lcs WITH KEY key = lv_key INTO temp18. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_candidate = temp18. + DO. + IF ls_candidate-chain = -1. + EXIT. + ENDIF. + lv_mismatch_length1 = lv_tail1 - ls_candidate-buffer1index - 1. + + lv_mismatch_length2 = lv_tail2 - ls_candidate-buffer2index - 1. + lv_tail1 = ls_candidate-buffer1index. + lv_tail2 = ls_candidate-buffer2index. + + IF lv_mismatch_length1 > 0 OR lv_mismatch_length2 > 0. + + CLEAR temp15. + temp15-buffer1-key = lv_tail1 + 1. + temp15-buffer1-len = lv_mismatch_length1. + temp15-buffer1content = _slice( it_data = it_buffer1 + iv_start = lv_tail1 + 1 + iv_end = lv_tail1 + 1 + lv_mismatch_length1 ). + temp15-buffer2-key = lv_tail2 + 1. + temp15-buffer2-len = lv_mismatch_length2. + temp15-buffer2content = _slice( it_data = it_buffer2 + iv_start = lv_tail2 + 1 + iv_end = lv_tail2 + 1 + lv_mismatch_length2 ). + + ls_result = temp15. + INSERT ls_result INTO rt_result INDEX 1. + ENDIF. + + temp17 = sy-tabix. + READ TABLE lt_lcs WITH KEY key = ls_candidate-chain INTO temp16. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_candidate = temp16. + ENDDO. + + ENDMETHOD. + METHOD zif_abapgit_diff3~diff_patch. + " We apply the LCS to build a JSON representation of a + " diff(1)-style patch. + + DATA ls_result LIKE LINE OF rt_result. + + DATA lt_lcs TYPE zif_abapgit_diff3=>ty_lcs_result_t. + DATA lv_tail1 TYPE i. + DATA lv_tail2 TYPE i. + DATA ls_candidate LIKE LINE OF lt_lcs. + DATA temp20 LIKE LINE OF lt_lcs. + DATA temp21 LIKE sy-tabix. + DATA lv_mismatchlength1 TYPE i. + DATA lv_mismatchlength2 TYPE i. + DATA temp18 LIKE LINE OF lt_lcs. + DATA temp19 LIKE sy-tabix. + DATA lv_key TYPE i. + lt_lcs = zif_abapgit_diff3~lcs( it_buffer1 = it_buffer1 + it_buffer2 = it_buffer2 ). + lv_tail1 = lines( it_buffer1 ). + + lv_tail2 = lines( it_buffer2 ). + + temp21 = sy-tabix. + lv_key = lines( lt_lcs ) - 1. + READ TABLE lt_lcs WITH KEY key = lv_key INTO temp20. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_candidate = temp20. + DO. + IF ls_candidate-chain = -1. + EXIT. + ENDIF. + lv_mismatchlength1 = lv_tail1 - ls_candidate-buffer1index - 1. + + lv_mismatchlength2 = lv_tail2 - ls_candidate-buffer2index - 1. + lv_tail1 = ls_candidate-buffer1index. + lv_tail2 = ls_candidate-buffer2index. + + IF lv_mismatchlength1 > 0 OR lv_mismatchlength2 > 0. + CLEAR ls_result. + ls_result-buffer1 = chunk_description( it_buffer = it_buffer1 + iv_offset = lv_tail1 + 1 + iv_length = lv_mismatchlength1 ). + ls_result-buffer2 = chunk_description( it_buffer = it_buffer2 + iv_offset = lv_tail2 + 1 + iv_length = lv_mismatchlength2 ). + INSERT ls_result INTO rt_result INDEX 1. + ENDIF. + + temp19 = sy-tabix. + READ TABLE lt_lcs WITH KEY key = ls_candidate-chain INTO temp18. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_candidate = temp18. + ENDDO. + + ENDMETHOD. + METHOD zif_abapgit_diff3~invert_patch. + " Takes the output of diffPatch(), and inverts the sense of it, so that it + " can be applied to buffer2 to give buffer1 rather than the other way around. + + DATA ls_result LIKE LINE OF rt_result. + + FIELD-SYMBOLS LIKE LINE OF it_patchres. + LOOP AT it_patchres ASSIGNING . + CLEAR ls_result. + ls_result-buffer1 = -buffer2. + ls_result-buffer2 = -buffer1. + INSERT ls_result INTO TABLE rt_result. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_diff3~lcs. + " Text diff algorithm following Hunt and McIlroy 1976. + " J. W. Hunt and M. D. McIlroy, An algorithm for differential buffer + " comparison, Bell Telephone Laboratories CSTR #41 (1976) + " http:"www.cs.dartmouth.edu/~doug/ + " https:"en.wikipedia.org/wiki/Longest_common_subsequence_problem + " + " Expects two arrays, finds longest common sequence + + TYPES: + BEGIN OF ty_equivalenceclass, + key TYPE string, + values TYPE zif_abapgit_diff3=>ty_numbers, + END OF ty_equivalenceclass. + + DATA: + lt_equivalenceclasses TYPE HASHED TABLE OF ty_equivalenceclass WITH UNIQUE KEY key, + lt_candidates TYPE zif_abapgit_diff3=>ty_lcs_result_t, + ls_newcandidate TYPE zif_abapgit_diff3=>ty_lcs_result. + + DATA lv_j TYPE i. + FIELD-SYMBOLS LIKE LINE OF it_buffer2. + FIELD-SYMBOLS TYPE ty_equivalenceclass. + DATA temp20 TYPE ty_equivalenceclass. + DATA ls_equivalenceclass LIKE temp20. + DATA temp21 TYPE zif_abapgit_diff3=>ty_lcs_result. + DATA ls_nullresult LIKE temp21. + DATA lv_i TYPE i. + FIELD-SYMBOLS LIKE LINE OF it_buffer1. + DATA temp22 LIKE sy-subrc. + DATA lt_buffer2indices TYPE zif_abapgit_diff3=>ty_numbers. + DATA temp27 LIKE LINE OF lt_equivalenceclasses. + DATA temp29 LIKE sy-tabix. + DATA lv_r TYPE i. + DATA ls_c LIKE LINE OF lt_candidates. + DATA temp31 LIKE LINE OF lt_candidates. + DATA temp34 LIKE sy-tabix. + DATA lv_s LIKE lv_r. + DATA temp23 LIKE LINE OF lt_candidates. + DATA temp24 LIKE sy-tabix. + DATA temp25 LIKE LINE OF lt_candidates. + DATA temp26 LIKE sy-tabix. + FIELD-SYMBOLS LIKE LINE OF lt_candidates. + DATA temp28 LIKE sy-tabix. + FIELD-SYMBOLS LIKE LINE OF lt_candidates. + DATA temp30 LIKE sy-tabix. + FIELD-SYMBOLS LIKE LINE OF lt_candidates. + DATA temp32 LIKE sy-tabix. + DATA temp33 LIKE sy-subrc. + FIELD-SYMBOLS LIKE LINE OF lt_candidates. + DATA temp35 LIKE sy-tabix. + FIELD-SYMBOLS LIKE LINE OF lt_candidates. + DATA temp37 LIKE sy-tabix. + FIELD-SYMBOLS LIKE LINE OF lt_candidates. + DATA temp39 LIKE sy-tabix. + DATA lv_key TYPE i. + lv_j = 0. + + LOOP AT it_buffer2 ASSIGNING . + + READ TABLE lt_equivalenceclasses ASSIGNING + WITH TABLE KEY key = . + IF sy-subrc <> 0. + + CLEAR temp20. + temp20-key = . + + ls_equivalenceclass = temp20. + INSERT ls_equivalenceclass INTO TABLE lt_equivalenceclasses ASSIGNING . + ENDIF. + INSERT lv_j INTO TABLE -values. + lv_j = lv_j + 1. + ENDLOOP. + CLEAR temp21. + temp21-key = 0. + temp21-buffer1index = -1. + temp21-buffer2index = -1. + temp21-chain = -1. + + ls_nullresult = temp21. + INSERT ls_nullresult INTO TABLE lt_candidates. + lv_i = 0. + + LOOP AT it_buffer1 ASSIGNING . + + READ TABLE lt_equivalenceclasses WITH KEY key = TRANSPORTING NO FIELDS. + temp22 = sy-subrc. + IF temp22 = 0. + + temp29 = sy-tabix. + READ TABLE lt_equivalenceclasses WITH KEY key = INTO temp27. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + lt_buffer2indices = temp27-values. + ELSE. + CLEAR lt_buffer2indices. + ENDIF. + lv_r = 0. + + temp34 = sy-tabix. + READ TABLE lt_candidates WITH KEY key = 0 INTO temp31. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + ls_c = temp31. + LOOP AT lt_buffer2indices INTO lv_j. + lv_s = lv_r. + DO. + IF lv_s < lines( lt_candidates ). + temp24 = sy-tabix. + READ TABLE lt_candidates WITH KEY key = lv_s INTO temp23. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + IF temp23-buffer2index < lv_j. + IF lv_s = lines( lt_candidates ) - 1. + EXIT. + ENDIF. + temp26 = sy-tabix. + lv_key = lv_s + 1. + READ TABLE lt_candidates WITH KEY key = lv_key INTO temp25. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + IF temp25-buffer2index > lv_j. + EXIT. + ENDIF. + ENDIF. + ELSE. + EXIT. + ENDIF. + lv_s = lv_s + 1. + ENDDO. + + IF lv_s < lines( lt_candidates ). + ls_newcandidate-buffer1index = lv_i. + ls_newcandidate-buffer2index = lv_j. + ls_newcandidate-chain = lv_s. + + IF lv_r = lines( lt_candidates ). + ls_c-key = lines( lt_candidates ) + 1. + INSERT ls_c INTO TABLE lt_candidates. + ELSE. + temp28 = sy-tabix. + READ TABLE lt_candidates WITH KEY key = lv_r ASSIGNING . + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + -buffer1index = ls_c-buffer1index. + temp30 = sy-tabix. + READ TABLE lt_candidates WITH KEY key = lv_r ASSIGNING . + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + -buffer2index = ls_c-buffer2index. + temp32 = sy-tabix. + READ TABLE lt_candidates WITH KEY key = lv_r ASSIGNING . + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + -chain = ls_c-chain. + ENDIF. + + lv_r = lv_s + 1. + ls_c = ls_newcandidate. + + IF lv_r = lines( lt_candidates ). + EXIT. " no point in examining further (j)s + ENDIF. + ENDIF. + ENDLOOP. + READ TABLE lt_candidates WITH KEY key = lv_r TRANSPORTING NO FIELDS. + temp33 = sy-subrc. + IF temp33 = 0. + temp35 = sy-tabix. + READ TABLE lt_candidates WITH KEY key = lv_r ASSIGNING . + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + -buffer1index = ls_c-buffer1index. + temp37 = sy-tabix. + READ TABLE lt_candidates WITH KEY key = lv_r ASSIGNING . + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + -buffer2index = ls_c-buffer2index. + temp39 = sy-tabix. + READ TABLE lt_candidates WITH KEY key = lv_r ASSIGNING . + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + -chain = ls_c-chain. + ELSE. + ls_c-key = lv_r. + INSERT ls_c INTO TABLE lt_candidates. + ENDIF. + + lv_i = lv_i + 1. + ENDLOOP. + + " At this point, we know the LCS: it's in the reverse of the + " linked-list through chain of candidates[ lines( candidates ) - 1 ]. + + rt_result = lt_candidates. + + ENDMETHOD. + METHOD zif_abapgit_diff3~merge. + + DATA ls_labels TYPE zif_abapgit_diff3=>ty_labels. + DATA lt_regions TYPE zif_abapgit_diff3=>ty_merge_region_t. + FIELD-SYMBOLS LIKE LINE OF lt_regions. + ls_labels = get_labels( is_labels ). + lt_regions = zif_abapgit_diff3~diff3_merge( + it_a = it_a + it_o = it_o + it_b = it_b + iv_exclude_false_conflicts = iv_exclude_false_conflicts ). + LOOP AT lt_regions ASSIGNING . + IF -ok IS NOT INITIAL. + INSERT LINES OF -ok INTO TABLE rs_result-result. + ELSEIF -conflict IS NOT INITIAL. + rs_result-conflict = abap_true. + INSERT ls_labels-a INTO TABLE rs_result-result. + INSERT LINES OF -conflict-a INTO TABLE rs_result-result. + INSERT ls_labels-x INTO TABLE rs_result-result. + INSERT LINES OF -conflict-b INTO TABLE rs_result-result. + INSERT ls_labels-b INTO TABLE rs_result-result. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_diff3~merge_diff3. + + DATA ls_labels TYPE zif_abapgit_diff3=>ty_labels. + DATA lt_regions TYPE zif_abapgit_diff3=>ty_merge_region_t. + FIELD-SYMBOLS LIKE LINE OF lt_regions. + ls_labels = get_labels( is_labels ). + lt_regions = zif_abapgit_diff3~diff3_merge( + it_a = it_a + it_o = it_o + it_b = it_b + iv_exclude_false_conflicts = iv_exclude_false_conflicts ). + LOOP AT lt_regions ASSIGNING . + IF -ok IS NOT INITIAL. + INSERT LINES OF -ok INTO TABLE rs_result-result. + ELSEIF -conflict IS NOT INITIAL. + rs_result-conflict = abap_true. + INSERT ls_labels-a INTO TABLE rs_result-result. + INSERT LINES OF -conflict-a INTO TABLE rs_result-result. + INSERT ls_labels-o INTO TABLE rs_result-result. + INSERT LINES OF -conflict-o INTO TABLE rs_result-result. + INSERT ls_labels-x INTO TABLE rs_result-result. + INSERT LINES OF -conflict-b INTO TABLE rs_result-result. + INSERT ls_labels-b INTO TABLE rs_result-result. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_diff3~merge_dig_in. + + DATA ls_labels TYPE zif_abapgit_diff3=>ty_labels. + DATA lt_regions TYPE zif_abapgit_diff3=>ty_merge_region_t. + FIELD-SYMBOLS LIKE LINE OF lt_regions. + DATA lt_c TYPE zif_abapgit_diff3=>ty_comm_result_t. + FIELD-SYMBOLS LIKE LINE OF lt_c. + ls_labels = get_labels( is_labels ). + lt_regions = zif_abapgit_diff3~diff3_merge( + it_a = it_a + it_o = it_o + it_b = it_b + iv_exclude_false_conflicts = iv_exclude_false_conflicts ). + LOOP AT lt_regions ASSIGNING . + IF -ok IS NOT INITIAL. + INSERT LINES OF -ok INTO TABLE rs_result-result. + ELSE. + + lt_c = zif_abapgit_diff3~diff_comm( + it_buffer1 = -conflict-a + it_buffer2 = -conflict-b ). + LOOP AT lt_c ASSIGNING . + IF -common IS NOT INITIAL. + INSERT LINES OF -common INTO TABLE rs_result-result. + ELSE. + rs_result-conflict = abap_true. + INSERT ls_labels-a INTO TABLE rs_result-result. + INSERT LINES OF -diff-buffer1 INTO TABLE rs_result-result. + INSERT ls_labels-x INTO TABLE rs_result-result. + INSERT LINES OF -diff-buffer2 INTO TABLE rs_result-result. + INSERT ls_labels-b INTO TABLE rs_result-result. + ENDIF. + ENDLOOP. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_diff3~patch. + " Applies a patch to a buffer. + " Given buffer1 and buffer2, `patch(buffer1, diffPatch(buffer1, buffer2))` should give buffer2. + + DATA lv_curroffset TYPE i. + FIELD-SYMBOLS LIKE LINE OF it_patchres. + DATA temp40 LIKE LINE OF it_buffer. + DATA temp41 LIKE sy-tabix. + DATA temp42 LIKE LINE OF -buffer2-chunk. + DATA temp43 LIKE sy-tabix. + DATA temp44 LIKE LINE OF it_buffer. + DATA temp45 LIKE sy-tabix. + lv_curroffset = 0. + LOOP AT it_patchres ASSIGNING . + WHILE lv_curroffset < -buffer1-offset. + temp41 = sy-tabix. + READ TABLE it_buffer INDEX lv_curroffset + 1 INTO temp40. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + APPEND temp40 TO rt_result. + lv_curroffset = lv_curroffset + 1. + ENDWHILE. + + DO lines( -buffer2-chunk ) TIMES. + temp43 = sy-tabix. + READ TABLE -buffer2-chunk INDEX sy-index INTO temp42. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + APPEND temp42 TO rt_result. + ENDDO. + + lv_curroffset = lv_curroffset + -buffer1-length. + ENDLOOP. + + WHILE lv_curroffset < lines( it_buffer ). + temp45 = sy-tabix. + READ TABLE it_buffer INDEX lv_curroffset + 1 INTO temp44. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + APPEND temp44 TO rt_result. + lv_curroffset = lv_curroffset + 1. + ENDWHILE. + + ENDMETHOD. + METHOD zif_abapgit_diff3~strip_patch. + " Takes the output of diffPatch(), and removes extra information from it. + " It can still be used by patch(), below, but can no longer be inverted. + + DATA ls_result LIKE LINE OF rt_result. + + FIELD-SYMBOLS LIKE LINE OF it_patchres. + LOOP AT it_patchres ASSIGNING . + CLEAR ls_result. + ls_result-buffer1-offset = -buffer1-offset. + ls_result-buffer1-length = -buffer1-length. + ls_result-buffer2-chunk = -buffer2-chunk. + INSERT ls_result INTO TABLE rt_result. + ENDLOOP. + + ENDMETHOD. + METHOD _reverse. + + DATA lv_line TYPE i. + DATA temp46 LIKE LINE OF it_data. + DATA temp47 LIKE sy-tabix. + lv_line = lines( it_data ). + + DO lines( it_data ) TIMES. + temp47 = sy-tabix. + READ TABLE it_data INDEX lv_line INTO temp46. + + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE cx_sy_itab_error. + ENDIF. + INSERT temp46 INTO TABLE rt_result. + lv_line = lv_line - 1. + ENDDO. + + ENDMETHOD. + METHOD _slice. + + " select from start to end (end not included!) + FIELD-SYMBOLS LIKE LINE OF it_data. + LOOP AT it_data ASSIGNING FROM iv_start + 1 TO iv_end. + APPEND TO rt_result. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_data_utils IMPLEMENTATION. + METHOD build_config_filename. + + rv_filename = to_lower( |{ is_config-name }.{ zif_abapgit_data_config=>c_config }| + && |.{ zif_abapgit_data_config=>c_default_format }| ). + + REPLACE ALL OCCURRENCES OF '/' IN rv_filename WITH '#'. + + ENDMETHOD. + METHOD build_data_filename. + + rv_filename = to_lower( |{ is_config-name }.{ is_config-type }| + && |.{ zif_abapgit_data_config=>c_default_format }| ). + + REPLACE ALL OCCURRENCES OF '/' IN rv_filename WITH '#'. + + ENDMETHOD. + METHOD build_table_itab. + + DATA lo_type TYPE REF TO cl_abap_typedescr. + DATA lo_data TYPE REF TO cl_abap_structdescr. + DATA lo_table TYPE REF TO cl_abap_tabledescr. + DATA lt_keys TYPE abap_table_keydescr_tab. + DATA lt_names TYPE ty_names. + + FIELD-SYMBOLS LIKE LINE OF lt_names. + FIELD-SYMBOLS LIKE LINE OF lt_keys. + FIELD-SYMBOLS LIKE LINE OF -components. + + cl_abap_structdescr=>describe_by_name( + EXPORTING + p_name = iv_name + RECEIVING + p_descr_ref = lo_type + EXCEPTIONS + type_not_found = 1 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Table { iv_name } not found for data serialization| ). + ENDIF. + + TRY. + lo_data ?= lo_type. + + " Get primary key to ensure unique entries + IF lo_data->is_ddic_type( ) = abap_true. + lt_names = list_key_fields( iv_name ). + + APPEND INITIAL LINE TO lt_keys ASSIGNING . + -access_kind = cl_abap_tabledescr=>tablekind_hashed. + -key_kind = cl_abap_tabledescr=>keydefkind_user. + -is_primary = abap_true. + -is_unique = abap_true. + + LOOP AT lt_names ASSIGNING . + APPEND INITIAL LINE TO -components ASSIGNING . + -name = . + ENDLOOP. + ENDIF. + + IF lines( lt_names ) = 0. + lo_table = cl_abap_tabledescr=>get( lo_data ). + ELSE. + lo_table = cl_abap_tabledescr=>get_with_keys( + p_line_type = lo_data + p_keys = lt_keys ). + ENDIF. + + CREATE DATA rr_data TYPE HANDLE lo_table. + + CATCH cx_root. + zcx_abapgit_exception=>raise( |Error creating internal table for data serialization| ). + ENDTRY. + + ENDMETHOD. + METHOD does_table_exist. + + " This is slow but ensures that the table actually exists and is not just buffered by RTTI + " If we just rely on RTTI, uninstalling and reinstalling a table in the same session will lead to dumps + TRY. + build_table_itab( iv_name ). + rv_exists = abap_true. + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + METHOD get_table_contflag. + + DATA lo_table TYPE REF TO object. + DATA lo_content TYPE REF TO object. + DATA lo_delivery_class TYPE REF TO object. + FIELD-SYMBOLS TYPE any. + + TRY. + CALL METHOD ('XCO_CP_ABAP_DICTIONARY')=>database_table + EXPORTING + iv_name = iv_name(16) + RECEIVING + ro_database_table = lo_table. + CALL METHOD lo_table->('IF_XCO_DATABASE_TABLE~CONTENT') + RECEIVING + ro_content = lo_content. + CALL METHOD lo_content->('IF_XCO_DBT_CONTENT~GET_DELIVERY_CLASS') + RECEIVING + ro_delivery_class = lo_delivery_class. + ASSIGN lo_delivery_class->('VALUE') TO . + rv_contflag = . + CATCH cx_sy_dyn_call_illegal_class cx_no_check. + " Catching SAP standard exception CX_NO_CHECK, + " because of the expected exception CX_XCO_RUNTIME_EXCEPTION + " could not be used here directly to keep the indirect usage approach. + SELECT SINGLE contflag FROM ('DD02L') INTO rv_contflag WHERE tabname = iv_name. + ENDTRY. + + ENDMETHOD. + METHOD is_application_table. + + DATA lv_contflag TYPE ty_contflag. + + lv_contflag = get_table_contflag( iv_name ). + + IF lv_contflag CA 'AEL'. + rv_application = abap_true. + ELSEIF lv_contflag IS NOT INITIAL. + rv_application = abap_false. + ELSE. + rv_application = abap_undefined. " table does not exist + ENDIF. + + ENDMETHOD. + METHOD is_customizing_table. + + DATA lv_contflag TYPE ty_contflag. + + lv_contflag = get_table_contflag( iv_name ). + + IF lv_contflag = 'C'. + rv_customizing = abap_true. + ELSEIF lv_contflag IS NOT INITIAL. + rv_customizing = abap_false. + ELSE. + rv_customizing = abap_undefined. " table does not exist + ENDIF. + + ENDMETHOD. + METHOD jump. + + " Run SE16 with authorization check + CALL FUNCTION 'RS_TABLE_LIST_CREATE' + EXPORTING + table_name = is_item-obj_name + EXCEPTIONS + table_is_structure = 1 + table_not_exists = 2 + db_not_exists = 3 + no_permission = 4 + no_change_allowed = 5 +* table_is_gtt = 6 " not in lower releases + OTHERS = 7. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Table { is_item-obj_name } cannot be displayed| ). + ENDIF. + + ENDMETHOD. + METHOD list_key_fields. + DATA lo_obj TYPE REF TO object. + DATA lv_tabname TYPE c LENGTH 16. + DATA lr_ddfields TYPE REF TO data. + DATA lv_workaround TYPE c LENGTH 20. + DATA lr_struct TYPE REF TO cl_abap_structdescr. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE simple. + FIELD-SYMBOLS TYPE ANY TABLE. + +* convert to correct type, + lv_tabname = iv_name. + + TRY. + CALL METHOD ('XCO_CP_ABAP_DICTIONARY')=>database_table + EXPORTING + iv_name = lv_tabname + RECEIVING + ro_database_table = lo_obj. + ASSIGN lo_obj->('IF_XCO_DATABASE_TABLE~FIELDS->IF_XCO_DBT_FIELDS_FACTORY~KEY') TO . + IF sy-subrc <> 0. +* fallback to RTTI, KEY field does not exist in S/4 2020 + RAISE EXCEPTION TYPE cx_sy_dyn_call_illegal_class. + ENDIF. + lo_obj = . + CALL METHOD lo_obj->('IF_XCO_DBT_FIELDS~GET_NAMES') + RECEIVING + rt_names = rt_names. + CATCH cx_sy_dyn_call_illegal_class cx_no_check. + lv_workaround = 'DDFIELDS'. + CREATE DATA lr_ddfields TYPE (lv_workaround). + ASSIGN lr_ddfields->* TO . + ASSERT sy-subrc = 0. + lr_struct ?= cl_abap_typedescr=>describe_by_name( lv_tabname ). + lr_struct->get_ddic_field_list( + RECEIVING + p_field_list = + EXCEPTIONS + not_found = 1 + no_ddic_type = 2 ). + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Table { iv_name } not found| ). + ENDIF. + LOOP AT ASSIGNING . + ASSIGN COMPONENT 'KEYFLAG' OF STRUCTURE TO . + IF sy-subrc <> 0 OR <> abap_true. + CONTINUE. + ENDIF. + ASSIGN COMPONENT 'FIELDNAME' OF STRUCTURE TO . + ASSERT sy-subrc = 0. + APPEND TO rt_names. + ENDLOOP. + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_data_supporter IMPLEMENTATION. + METHOD get_supported_objects. + + DATA: + lt_tables TYPE STANDARD TABLE OF tabname, + lv_tabname TYPE tabname, + ls_object LIKE LINE OF mt_supported_objects, + li_exit TYPE REF TO zif_abapgit_exit. + + " For safety reasons, by default only customer-defined customizing tables are supported + SELECT dd02l~tabname + FROM dd09l JOIN dd02l + ON dd09l~tabname = dd02l~tabname + AND dd09l~as4local = dd02l~as4local + AND dd09l~as4vers = dd02l~as4vers + INTO TABLE lt_tables + WHERE dd02l~tabclass = 'TRANSP' + AND dd09l~tabart = 'APPL2' + AND dd09l~as4user <> 'SAP' + AND dd09l~as4local = 'A' "Only active tables + AND dd02l~contflag = 'C' "Only customizing tables + ORDER BY dd02l~tabname. + + LOOP AT lt_tables INTO lv_tabname. + ls_object-type = zif_abapgit_data_config=>c_data_type-tabu. + ls_object-name = lv_tabname. + INSERT ls_object INTO TABLE mt_supported_objects. + ENDLOOP. + + " The list of supported objects can be enhanced using an exit + " Name patterns are allowed. For example, TABU T009* + li_exit = zcl_abapgit_exit=>get_instance( ). + li_exit->change_supported_data_objects( CHANGING ct_objects = mt_supported_objects ). + + ENDMETHOD. + METHOD zif_abapgit_data_supporter~is_object_supported. + + FIELD-SYMBOLS LIKE LINE OF mt_supported_objects. + + IF mt_supported_objects IS INITIAL. + get_supported_objects( ). + ENDIF. + + READ TABLE mt_supported_objects TRANSPORTING NO FIELDS + WITH TABLE KEY type = iv_type name = iv_name. + IF sy-subrc = 0. + rv_supported = abap_true. + ELSE. + " Check if object name matches pattern + LOOP AT mt_supported_objects ASSIGNING WHERE type = iv_type. + IF iv_name CP -name. + rv_supported = abap_true. + RETURN. + ENDIF. + ENDLOOP. + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_data_serializer IMPLEMENTATION. + METHOD convert_itab_to_json. + + DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. + DATA lv_string TYPE string. + DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + + FIELD-SYMBOLS TYPE ANY TABLE. + + ASSIGN ir_data->* TO . + + TRY. + lo_ajson = zcl_abapgit_ajson=>create_empty( ). + lo_ajson->keep_item_order( ). + lo_ajson->set( + iv_path = '/' + iv_val = ). + + IF iv_skip_initial = abap_true. + lo_ajson = zcl_abapgit_ajson=>create_from( + ii_source_json = lo_ajson + ii_filter = zcl_abapgit_ajson_filter_lib=>create_empty_filter( ) ). + ENDIF. + + lv_string = lo_ajson->stringify( 2 ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise( lx_ajson->get_text( ) ). + ENDTRY. + + rv_data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). + + ENDMETHOD. + METHOD read_database_table. + + DATA lv_records TYPE i. + DATA lv_where LIKE LINE OF it_where. + DATA lx_sql TYPE REF TO cx_sy_sql_error. + + FIELD-SYMBOLS TYPE ANY TABLE. + + rr_data = zcl_abapgit_data_utils=>build_table_itab( iv_name ). + ASSIGN rr_data->* TO . + + TRY. + LOOP AT it_where INTO lv_where. + SELECT * FROM (iv_name) APPENDING TABLE WHERE (lv_where) ORDER BY PRIMARY KEY. + ENDLOOP. + IF lines( it_where ) = 0. + SELECT * FROM (iv_name) INTO TABLE ORDER BY PRIMARY KEY. + ENDIF. + CATCH cx_sy_sql_error INTO lx_sql. + zcx_abapgit_exception=>raise( + iv_text = lx_sql->get_text( ) + ix_previous = lx_sql ). + ENDTRY. + + lv_records = lines( ). + IF lv_records > c_max_records. + zcx_abapgit_exception=>raise( |Too many records selected from table { iv_name + } (selected { lv_records }, max { c_max_records })| ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_data_serializer~serialize. + + DATA lt_configs TYPE zif_abapgit_data_config=>ty_config_tt. + DATA ls_config LIKE LINE OF lt_configs. + DATA ls_file LIKE LINE OF rt_files. + DATA lr_data TYPE REF TO data. + + ls_file-path = zif_abapgit_data_config=>c_default_path. + lt_configs = ii_config->get_configs( ). + + LOOP AT lt_configs INTO ls_config. + ASSERT ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. " todo + ASSERT ls_config-name IS NOT INITIAL. + + IF zcl_abapgit_data_utils=>does_table_exist( ls_config-name ) = abap_true. + lr_data = read_database_table( + iv_name = ls_config-name + it_where = ls_config-where ). + + ls_file-data = convert_itab_to_json( + ir_data = lr_data + iv_skip_initial = ls_config-skip_initial ). + ELSE. + ls_file-data = zcl_abapgit_convert=>string_to_xstring_utf8( '[]' ). + ENDIF. + + ls_file-filename = zcl_abapgit_data_utils=>build_data_filename( ls_config ). + ls_file-sha1 = zcl_abapgit_hash=>sha1_blob( ls_file-data ). + APPEND ls_file TO rt_files. + ENDLOOP. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_data_injector IMPLEMENTATION. + METHOD set_deserializer. + zcl_abapgit_data_factory=>gi_deserializer = ii_deserializer. + ENDMETHOD. + METHOD set_serializer. + zcl_abapgit_data_factory=>gi_serializer = ii_serializer. + ENDMETHOD. + METHOD set_supporter. + zcl_abapgit_data_factory=>gi_supporter = ii_supporter. + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_data_factory IMPLEMENTATION. + METHOD get_config. + CREATE OBJECT ri_config TYPE zcl_abapgit_data_config. + ENDMETHOD. + METHOD get_deserializer. + + IF gi_deserializer IS INITIAL. + CREATE OBJECT gi_deserializer TYPE zcl_abapgit_data_deserializer. + ENDIF. + + ri_deserializer = gi_deserializer. + + ENDMETHOD. + METHOD get_serializer. + + IF gi_serializer IS INITIAL. + CREATE OBJECT gi_serializer TYPE zcl_abapgit_data_serializer. + ENDIF. + + ri_serializer = gi_serializer. + + ENDMETHOD. + METHOD get_supporter. + + IF gi_supporter IS INITIAL. + CREATE OBJECT gi_supporter TYPE zcl_abapgit_data_supporter. + ENDIF. + + ri_supporter = gi_supporter. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_data_deserializer IMPLEMENTATION. + METHOD convert_json_to_itab. + + DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. + DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + + FIELD-SYMBOLS TYPE ANY TABLE. + + ASSIGN ir_data->* TO . + + TRY. + lo_ajson = zcl_abapgit_ajson=>parse( zcl_abapgit_convert=>xstring_to_string_utf8( is_file-data ) ). + lo_ajson->to_abap_corresponding_only( ). + lo_ajson->zif_abapgit_ajson~to_abap( IMPORTING ev_container = ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise( lx_ajson->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD determine_transport_request. + + DATA li_exit TYPE REF TO zif_abapgit_exit. + + li_exit = zcl_abapgit_exit=>get_instance( ). + + " Use transport from repo settings if maintained, or determine via user exit. + " If transport keeps empty here, it'll requested later via popup. + rv_transport_request = ii_repo->get_local_settings( )-customizing_request. + + li_exit->determine_transport_request( + EXPORTING + ii_repo = ii_repo + iv_transport_type = iv_transport_type + CHANGING + cv_transport_request = rv_transport_request ). + + ENDMETHOD. + METHOD is_table_allowed_to_edit. + + " Is the object supported (by default or based on exit)? + rv_allowed_to_edit = zcl_abapgit_data_factory=>get_supporter( )->is_object_supported( + iv_type = is_result-type + iv_name = is_result-name ). + + ENDMETHOD. + METHOD is_table_included_in_repo. + + DATA: + lt_packages TYPE STANDARD TABLE OF devclass WITH DEFAULT KEY, + lv_package TYPE devclass. + + lt_packages = zcl_abapgit_factory=>get_sap_package( iv_package )->list_subpackages( ). + INSERT iv_package INTO TABLE lt_packages. + + lv_package = zcl_abapgit_factory=>get_tadir( )->get_object_package( + iv_object = 'TABL' + iv_obj_name = |{ iv_tabname }| ). + + READ TABLE lt_packages TRANSPORTING NO FIELDS WITH TABLE KEY table_line = lv_package. + rv_is_included = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD preview_database_changes. + +* method currently distinguishes between records be deleted and inserted (comparison of complete record) + + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE ANY TABLE. + + ASSIGN ir_db_data->* TO . + ASSIGN ir_lc_data->* TO . + + rs_result-type = zif_abapgit_data_config=>c_data_type-tabu. + rs_result-name = iv_name. + rs_result-deletes = zcl_abapgit_data_utils=>build_table_itab( iv_name ). + rs_result-inserts = zcl_abapgit_data_utils=>build_table_itab( iv_name ). + rs_result-updates = zcl_abapgit_data_utils=>build_table_itab( iv_name ). + ASSIGN rs_result-deletes->* TO . + ASSIGN rs_result-inserts->* TO . + ASSIGN rs_result-updates->* TO . + + = . + = . + + " Remove identical records + LOOP AT ASSIGNING . + READ TABLE ASSIGNING FROM . + IF sy-subrc = 0. + IF <> . + " Identical key but not identical component values + INSERT INTO TABLE . + ENDIF. + DELETE TABLE FROM . + DELETE TABLE FROM . + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD read_database_table. + + DATA lv_where LIKE LINE OF it_where. + + FIELD-SYMBOLS TYPE ANY TABLE. + + rr_data = zcl_abapgit_data_utils=>build_table_itab( iv_name ). + ASSIGN rr_data->* TO . + + LOOP AT it_where INTO lv_where. + SELECT * FROM (iv_name) APPENDING TABLE WHERE (lv_where) ORDER BY PRIMARY KEY. + ENDLOOP. + IF lines( it_where ) = 0. + SELECT * FROM (iv_name) INTO TABLE ORDER BY PRIMARY KEY. + ENDIF. + + ENDMETHOD. + METHOD write_database_table. + + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE ANY TABLE. + FIELD-SYMBOLS TYPE ANY TABLE. + + IF zcl_abapgit_data_utils=>does_table_exist( iv_name ) = abap_false. + zcx_abapgit_exception=>raise( |Table { iv_name } not found for data deserialization| ). + ENDIF. + + ASSIGN ir_del->* TO . + ASSIGN ir_ins->* TO . + ASSIGN ir_upd->* TO . + + IF lines( ) > 0. + DELETE (iv_name) FROM TABLE . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error deleting { lines( ) } records from table { iv_name }| ). + ENDIF. + ENDIF. + + IF lines( ) > 0. + INSERT (iv_name) FROM TABLE . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error inserting { lines( ) } records into table { iv_name }| ). + ENDIF. + ENDIF. + + IF lines( ) > 0. + UPDATE (iv_name) FROM TABLE . + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Error updating { lines( ) } records into table { iv_name }| ). + ENDIF. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_data_deserializer~actualize. + +* this method updates the database + + DATA ls_result LIKE LINE OF it_result. + DATA li_cts_api TYPE REF TO zif_abapgit_cts_api. + + FIELD-SYMBOLS: + TYPE ANY TABLE, + TYPE ANY TABLE, + TYPE ANY TABLE. + + li_cts_api = zcl_abapgit_factory=>get_cts_api( ). + + LOOP AT it_result INTO ls_result. + ASSERT ls_result-type = zif_abapgit_data_config=>c_data_type-tabu. " todo + ASSERT ls_result-name IS NOT INITIAL. + + " Did the user flagged this object for update? + READ TABLE is_checks-overwrite TRANSPORTING NO FIELDS + WITH KEY object_type_and_name + COMPONENTS + obj_type = ls_result-type + obj_name = ls_result-name + decision = zif_abapgit_definitions=>c_yes. + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + + IF is_table_allowed_to_edit( ls_result ) = abap_false AND ls_result-in_repo = abap_false. + zcx_abapgit_exception=>raise( |Table { ls_result-name } not supported for updating data| ). + ENDIF. + + write_database_table( + iv_name = ls_result-name + ir_del = ls_result-deletes + ir_ins = ls_result-inserts + ir_upd = ls_result-updates ). + + ASSIGN ls_result-inserts->* TO . + ASSIGN ls_result-deletes->* TO . + ASSIGN ls_result-updates->* TO . + + IF zcl_abapgit_data_utils=>is_customizing_table( ls_result-name ) = abap_true. + li_cts_api->create_transport_entries( + iv_transport = is_checks-customizing-transport + it_table_ins = + it_table_upd = + it_table_del = + iv_tabname = |{ ls_result-name }| ). + ELSEIF zcl_abapgit_data_utils=>is_application_table( ls_result-name ) = abap_true. + li_cts_api->create_transport_entries( + iv_transport = is_checks-transport-transport + it_table_ins = + it_table_upd = + it_table_del = + iv_tabname = |{ ls_result-name }| ). + ENDIF. + + INSERT ls_result-file INTO TABLE rt_accessed_files. " data file + INSERT ls_result-config INTO TABLE rt_accessed_files. " config file + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_data_deserializer~deserialize. + +* this method does not persist any changes to the database + + DATA lt_configs TYPE zif_abapgit_data_config=>ty_config_tt. + DATA ls_config LIKE LINE OF lt_configs. + DATA lr_lc_data TYPE REF TO data. + DATA lr_db_data TYPE REF TO data. + DATA ls_file LIKE LINE OF it_files. + DATA ls_result LIKE LINE OF rt_result. + DATA lv_tabname TYPE tabname. + + lt_configs = ii_config->get_configs( ). + + LOOP AT lt_configs INTO ls_config. + ASSERT ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. " todo + ASSERT ls_config-name IS NOT INITIAL. + + lr_lc_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ). + + READ TABLE it_files INTO ls_file + WITH KEY file_path + COMPONENTS path = zif_abapgit_data_config=>c_default_path + filename = zcl_abapgit_data_utils=>build_data_filename( ls_config ). + IF sy-subrc = 0. + convert_json_to_itab( + ir_data = lr_lc_data + is_file = ls_file ). + + lr_db_data = read_database_table( + iv_name = ls_config-name + it_where = ls_config-where ). + + ls_result = preview_database_changes( + iv_name = ls_config-name + ir_lc_data = lr_lc_data + ir_db_data = lr_db_data ). + + MOVE-CORRESPONDING ls_file TO ls_result-file. " data file + + READ TABLE it_files INTO ls_file + WITH KEY file_path + COMPONENTS path = zif_abapgit_data_config=>c_default_path + filename = zcl_abapgit_data_utils=>build_config_filename( ls_config ). + ASSERT sy-subrc = 0. + + MOVE-CORRESPONDING ls_file TO ls_result-config. " config file + + " Check if table is included in repo + lv_tabname = ls_config-name. + + ls_result-in_repo = is_table_included_in_repo( + iv_package = iv_package + iv_tabname = lv_tabname ). + + INSERT ls_result INTO TABLE rt_result. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_data_deserializer~deserialize_check. + + DATA lt_configs TYPE zif_abapgit_data_config=>ty_config_tt. + + lt_configs = ii_config->get_configs( ). + + IF lt_configs IS NOT INITIAL. + rs_checks-required = abap_true. + rs_checks-type-request = zif_abapgit_cts_api=>c_transport_type-cust_request. + rs_checks-type-task = zif_abapgit_cts_api=>c_transport_type-cust_task. + rs_checks-transport = determine_transport_request( + ii_repo = ii_repo + iv_transport_type = rs_checks-type ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_data_config IMPLEMENTATION. + METHOD dump. + + DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. + DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + + TRY. + lo_ajson = zcl_abapgit_ajson=>create_empty( ). + lo_ajson->zif_abapgit_ajson~set( + iv_path = '/' + iv_val = is_config ). + rv_json = zcl_abapgit_convert=>string_to_xstring_utf8( lo_ajson->stringify( 2 ) ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise( lx_ajson->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_data_config~add_config. + + DATA lv_where TYPE string. + + FIELD-SYMBOLS LIKE LINE OF mt_config. + + ASSERT is_config-type IS NOT INITIAL. + ASSERT is_config-name IS NOT INITIAL. + ASSERT is_config-name = to_upper( is_config-name ). + + INSERT is_config INTO TABLE mt_config. + IF sy-subrc <> 0. +* append to existing + READ TABLE mt_config ASSIGNING WITH KEY type = is_config-type name = is_config-name. + ASSERT sy-subrc = 0. + LOOP AT is_config-where INTO lv_where. + READ TABLE -where TRANSPORTING NO FIELDS WITH KEY table_line = lv_where. + IF sy-subrc <> 0. + INSERT lv_where INTO TABLE -where. + ENDIF. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_data_config~from_json. + + DATA ls_file LIKE LINE OF it_files. + DATA ls_config TYPE zif_abapgit_data_config=>ty_config. + DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. + DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. + + CLEAR mt_config. + LOOP AT it_files INTO ls_file + USING KEY file_path + WHERE path = zif_abapgit_data_config=>c_default_path + AND filename CP |*.{ zif_abapgit_data_config=>c_config }.{ zif_abapgit_data_config=>c_default_format }|. + TRY. + lo_ajson = zcl_abapgit_ajson=>parse( zcl_abapgit_convert=>xstring_to_string_utf8( ls_file-data ) ). + lo_ajson->zif_abapgit_ajson~to_abap( IMPORTING ev_container = ls_config ). + CATCH zcx_abapgit_ajson_error INTO lx_ajson. + zcx_abapgit_exception=>raise( lx_ajson->get_text( ) ). + ENDTRY. + + zif_abapgit_data_config~add_config( ls_config ). + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_data_config~get_configs. + rt_configs = mt_config. + ENDMETHOD. + METHOD zif_abapgit_data_config~remove_config. + + ASSERT is_config-type IS NOT INITIAL. + ASSERT is_config-name IS NOT INITIAL. + ASSERT is_config-name = to_upper( is_config-name ). + + DELETE mt_config WHERE name = is_config-name AND type = is_config-type. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'Not found' ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_data_config~to_json. + + DATA ls_config LIKE LINE OF mt_config. + DATA ls_file LIKE LINE OF rt_files. + + ls_file-path = zif_abapgit_data_config=>c_default_path. + + LOOP AT mt_config INTO ls_config. + ls_file-data = dump( ls_config ). + ls_file-sha1 = zcl_abapgit_hash=>sha1_blob( ls_file-data ). + ls_config-type = zif_abapgit_data_config=>c_config. + ls_file-filename = zcl_abapgit_data_utils=>build_data_filename( ls_config ). + APPEND ls_file TO rt_files. + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_data_config~update_config. + + zif_abapgit_data_config~remove_config( is_config ). + zif_abapgit_data_config~add_config( is_config ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_transport_objects IMPLEMENTATION. + METHOD constructor. + mt_transport_objects = it_transport_objects. + ENDMETHOD. + METHOD to_stage. + DATA: ls_transport_object LIKE LINE OF mt_transport_objects, + ls_local_file TYPE zif_abapgit_definitions=>ty_file_item, + ls_object_status TYPE zif_abapgit_definitions=>ty_result. + + LOOP AT mt_transport_objects INTO ls_transport_object. + LOOP AT it_object_statuses INTO ls_object_status + " USING KEY sec_key " syntax error in 754 + WHERE obj_name = ls_transport_object-obj_name + AND obj_type = ls_transport_object-object + AND NOT lstate IS INITIAL ##PRIMKEY[SEC_KEY]. + + CASE ls_object_status-lstate. + WHEN zif_abapgit_definitions=>c_state-added OR zif_abapgit_definitions=>c_state-modified. + IF ls_transport_object-delflag = abap_true. + zcx_abapgit_exception=>raise( |Object { ls_transport_object-object }| + && | { ls_transport_object-obj_name } should be added/modified,| + && | but has deletion flag in transport| ). + ENDIF. + + READ TABLE is_stage_objects-local + INTO ls_local_file + WITH KEY item-obj_name = ls_transport_object-obj_name + item-obj_type = ls_transport_object-object + file-filename = ls_object_status-filename. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( |Object { ls_transport_object-object }| + && | { ls_transport_object-obj_name } not found in the local repository files| ). + ELSE. + io_stage->add( + iv_path = ls_local_file-file-path + iv_filename = ls_local_file-file-filename + iv_data = ls_local_file-file-data ). + ENDIF. + WHEN zif_abapgit_definitions=>c_state-deleted. + io_stage->rm( + iv_path = ls_object_status-path + iv_filename = ls_object_status-filename ). + WHEN OTHERS. + ASSERT 0 = 1. "Unexpected state + ENDCASE. + ENDLOOP. + IF sy-subrc <> 0. + " Since not all objects in a transport might be in the local repo + " i.e. generated SADL objects, we don't add these objects to + " the stage. + ENDIF. + ENDLOOP. + ENDMETHOD. +ENDCLASS. + +CLASS kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr DEFINITION DEFERRED. +CLASS kHGwlFZZSwYWAxVpEdIbTqkphOFmih DEFINITION DEFERRED. +* renamed: zcl_abapgit_transport_mass :: lcl_gui +CLASS kHGwlFZZSwYWAxVpEdIbTqkphOFmih DEFINITION FINAL. + PUBLIC SECTION. + CLASS-METHODS f4_folder + RETURNING + VALUE(rv_folder) TYPE string + RAISING + zcx_abapgit_exception. + CLASS-METHODS open_folder_frontend + IMPORTING + iv_folder TYPE string + RAISING + zcx_abapgit_exception. + CLASS-METHODS select_tr_requests + RETURNING + VALUE(rt_trkorr) TYPE trwbo_request_headers. +ENDCLASS. + +CLASS kHGwlFZZSwYWAxVpEdIbTqkphOFmih IMPLEMENTATION. + + METHOD f4_folder. + + DATA: lv_title TYPE string, + lo_fe_serv TYPE REF TO zif_abapgit_frontend_services. + + lo_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + lv_title = 'Choose the destination folder for the ZIP files'. + + lo_fe_serv->directory_browse( + EXPORTING + iv_window_title = lv_title + CHANGING + cv_selected_folder = rv_folder ). + + ENDMETHOD. + + METHOD open_folder_frontend. + IF iv_folder IS INITIAL. + RETURN. + ENDIF. + + zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = iv_folder ). + ENDMETHOD. + + METHOD select_tr_requests. + + DATA: ls_popup TYPE strhi_popup, + ls_selection TYPE trwbo_selection. + + ls_popup-start_column = 5. + ls_popup-start_row = 5. + + " Prepare the selection + ls_selection-trkorrpattern = space. + ls_selection-client = space. + ls_selection-stdrequest = space. + ls_selection-reqfunctions = 'K'. + ls_selection-reqstatus = 'RNODL'. + + " Call transport selection popup + CALL FUNCTION 'TRINT_SELECT_REQUESTS' + EXPORTING + iv_username_pattern = '*' + iv_via_selscreen = 'X' + is_selection = ls_selection + iv_complete_projects = space + iv_title = 'abapGit Transport Mass Downloader' + is_popup = ls_popup + IMPORTING + et_requests = rt_trkorr + EXCEPTIONS + action_aborted_by_user = 1 + OTHERS = 2. + IF sy-subrc <> 0. + CLEAR rt_trkorr. + ELSE. + SORT rt_trkorr BY trkorr. + DELETE ADJACENT DUPLICATES FROM rt_trkorr COMPARING trkorr. + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +* renamed: zcl_abapgit_transport_mass :: lcl_transport_zipper +CLASS kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr DEFINITION FINAL. + PUBLIC SECTION. + TYPES ty_folder TYPE string. + TYPES ty_filename TYPE string. + + CONSTANTS c_zip_ext TYPE string VALUE '.zip'. + + METHODS constructor + IMPORTING + iv_folder TYPE ty_folder + RAISING + zcx_abapgit_exception. + + METHODS generate_files + IMPORTING + it_trkorr TYPE trwbo_request_headers + ig_logic TYPE any + RAISING + zcx_abapgit_exception. + + METHODS get_folder + RETURNING + VALUE(rv_full_folder) TYPE ty_folder. + + CLASS-METHODS does_folder_exist + IMPORTING + iv_folder TYPE string + RETURNING + VALUE(rv_folder_exist) TYPE abap_bool + RAISING + zcx_abapgit_exception. + + PRIVATE SECTION. + DATA: mv_timestamp TYPE string, + mv_separator TYPE c, + mv_full_folder TYPE ty_folder. + + METHODS get_full_folder + IMPORTING + iv_folder TYPE ty_folder + RETURNING + VALUE(rv_full_folder) TYPE ty_folder + RAISING + zcx_abapgit_exception. + + METHODS get_filename + IMPORTING + is_trkorr TYPE trwbo_request_header + RETURNING + VALUE(rv_filename) TYPE ty_filename. + +ENDCLASS. + +CLASS kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr IMPLEMENTATION. + + METHOD constructor. + DATA lo_fe_serv TYPE REF TO zif_abapgit_frontend_services. + + lo_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + + mv_timestamp = |{ sy-datlo }_{ sy-timlo }|. + mv_full_folder = get_full_folder( iv_folder ). + + TRY. + lo_fe_serv->get_file_separator( CHANGING cv_file_separator = mv_separator ). + CATCH zcx_abapgit_exception. + "Default MS Windows separator + mv_separator = '\'. + ENDTRY. + ENDMETHOD. + + METHOD get_folder. + rv_full_folder = mv_full_folder. + ENDMETHOD. + + METHOD does_folder_exist. + rv_folder_exist = zcl_abapgit_ui_factory=>get_frontend_services( )->directory_exist( iv_folder ). + ENDMETHOD. + + METHOD get_full_folder. + + DATA: lv_sep TYPE c, + lv_rc TYPE i, + lo_fe_serv TYPE REF TO zif_abapgit_frontend_services. + + lo_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). + + lo_fe_serv->get_file_separator( CHANGING cv_file_separator = lv_sep ). + rv_full_folder = |{ iv_folder }{ lv_sep }{ mv_timestamp }|. + + IF does_folder_exist( rv_full_folder ) = abap_false. + lo_fe_serv->directory_create( + EXPORTING + iv_directory = rv_full_folder + CHANGING + cv_rc = lv_rc ). + ENDIF. + ENDMETHOD. + + METHOD get_filename. + + " Generate filename + rv_filename = |{ is_trkorr-trkorr }_{ is_trkorr-as4text }_{ mv_timestamp }{ c_zip_ext }|. + + " Remove reserved characters (for Windows based systems) + TRANSLATE rv_filename USING '/ \ : " * > < ? | '. + + rv_filename = |{ mv_full_folder }{ mv_separator }{ rv_filename }|. + + ENDMETHOD. + + METHOD generate_files. + + DATA: ls_trkorr LIKE LINE OF it_trkorr, + lv_zipbinstring TYPE xstring. + + LOOP AT it_trkorr INTO ls_trkorr. + + lv_zipbinstring = zcl_abapgit_transport_mass=>zip( is_trkorr = ls_trkorr + iv_logic = ig_logic + iv_show_log_popup = abap_false ). + + zcl_abapgit_zip=>save_binstring_to_localfile( iv_binstring = lv_zipbinstring + iv_filename = get_filename( ls_trkorr ) ). + + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +CLASS zcl_abapgit_transport_mass IMPLEMENTATION. + METHOD run. + + DATA: + lt_trkorr TYPE trwbo_request_headers, + lo_transport_zipper TYPE REF TO kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr, + lx_except TYPE REF TO cx_root, + lv_folder TYPE string, + lv_text TYPE string. + + TRY. + + lt_trkorr = kHGwlFZZSwYWAxVpEdIbTqkphOFmih=>select_tr_requests( ). + + IF lt_trkorr[] IS NOT INITIAL. + + lv_folder = kHGwlFZZSwYWAxVpEdIbTqkphOFmih=>f4_folder( ). + + IF lv_folder IS INITIAL. +* Empty folder + zcx_abapgit_exception=>raise( 'Empty destination folder' ). + ENDIF. + +* Instantiate transport zipper object that will also create the timestamped output folder + CREATE OBJECT lo_transport_zipper TYPE kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr + EXPORTING + iv_folder = lv_folder. + +* Generate the local zip files from the given list of transport requests + lo_transport_zipper->generate_files( + it_trkorr = lt_trkorr + ig_logic = zcl_abapgit_ui_factory=>get_popups( )->popup_folder_logic( ) ). + +* Open output folder if user asked it + kHGwlFZZSwYWAxVpEdIbTqkphOFmih=>open_folder_frontend( lo_transport_zipper->get_folder( ) ). + + ELSE. +* No data found for the provided selection criteria + zcx_abapgit_exception=>raise( 'No transport requests selected' ). + ENDIF. + + CATCH zcx_abapgit_exception INTO lx_except. + + lv_text = lx_except->get_text( ). + MESSAGE lv_text TYPE 'S' DISPLAY LIKE 'E'. + + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_transport_2_branch IMPLEMENTATION. + METHOD create. + DATA: + lv_branch_name TYPE string, + ls_comment TYPE zif_abapgit_git_definitions=>ty_comment, + lo_stage TYPE REF TO zcl_abapgit_stage, + ls_stage_objects TYPE zif_abapgit_definitions=>ty_stage_files, + lt_object_statuses TYPE zif_abapgit_definitions=>ty_results_tt. + + lv_branch_name = zcl_abapgit_git_branch_utils=>complete_heads_branch_name( + zcl_abapgit_git_branch_utils=>normalize_branch_name( is_transport_to_branch-branch_name ) ). + + ii_repo_online->create_branch( lv_branch_name ). + + CREATE OBJECT lo_stage. + + ls_stage_objects = zcl_abapgit_stage_logic=>get_stage_logic( )->get( ii_repo_online ). + + lt_object_statuses = zcl_abapgit_repo_status=>calculate( ii_repo_online ). + + stage_transport_objects( + it_transport_objects = it_transport_objects + io_stage = lo_stage + is_stage_objects = ls_stage_objects + it_object_statuses = lt_object_statuses ). + + ls_comment = generate_commit_message( is_transport_to_branch ). + + ii_repo_online->push( is_comment = ls_comment + io_stage = lo_stage ). + ENDMETHOD. + METHOD generate_commit_message. + rs_comment-committer-name = sy-uname. + rs_comment-committer-email = |{ rs_comment-committer-name }@localhost|. + rs_comment-comment = is_transport_to_branch-commit_text. + ENDMETHOD. + METHOD stage_transport_objects. + DATA lo_transport_objects TYPE REF TO zcl_abapgit_transport_objects. + CREATE OBJECT lo_transport_objects + EXPORTING + it_transport_objects = it_transport_objects. + + lo_transport_objects->to_stage( + io_stage = io_stage + is_stage_objects = is_stage_objects + it_object_statuses = it_object_statuses ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_transport IMPLEMENTATION. + METHOD add_all_objects_to_trans_req. + + DATA: + ls_request TYPE trwbo_request_header, + lt_e071 TYPE tr_objects, + lv_text TYPE string, + lv_answer TYPE c LENGTH 1, + lv_lock_objects TYPE trparflag, + lt_log TYPE sprot_u_tab. + + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_titlebar = `Lock objects?` + iv_text_question = `Shall all objects be locked in the transport request?` + iv_display_cancel_button = abap_true ). + + CASE lv_answer. + WHEN '1'. + lv_lock_objects = abap_true. + WHEN '2'. + lv_lock_objects = abap_false. + WHEN OTHERS. + RETURN. + ENDCASE. + + lt_e071 = collect_all_objects( iv_key ). + + " We used TR_REQUEST_CHOICE before, but it issues its error log with + " write lists which are not compatible with abapGit. + " There we user TRINT_REQUEST_CHOICE which returns the error log + " and display the log ourselves. + CALL FUNCTION 'TRINT_REQUEST_CHOICE' + EXPORTING + iv_request_types = 'FTCOK' + iv_lock_objects = lv_lock_objects + iv_with_error_log = abap_false + IMPORTING + es_request = ls_request + et_log = lt_log + TABLES + it_e071 = lt_e071 + EXCEPTIONS + invalid_request = 1 + invalid_request_type = 2 + user_not_owner = 3 + no_objects_appended = 4 + enqueue_error = 5 + cancelled_by_user = 6 + recursive_call = 7 + OTHERS = 8. + IF sy-subrc = 0. + lv_text = |Objects successfully added to { ls_request-trkorr }|. + MESSAGE lv_text TYPE 'S'. + RETURN. + ENDIF. + + IF lines( lt_log ) > 0. + show_log( + it_log = lt_log + iv_title = `Error log` ). + ELSE. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD collect_all_objects. + + DATA: + lt_objects TYPE scts_tadir, + lt_objects_all LIKE lt_objects, + ls_e071 LIKE LINE OF rt_objects, + li_repo TYPE REF TO zif_abapgit_repo, + lv_package TYPE zif_abapgit_persistence=>ty_repo-package, + lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. + + FIELD-SYMBOLS: + TYPE devclass, + TYPE tadir. + + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). + lv_package = li_repo->get_package( ). + lt_packages = zcl_abapgit_factory=>get_sap_package( lv_package )->list_subpackages( ). + INSERT lv_package INTO TABLE lt_packages. + + LOOP AT lt_packages ASSIGNING . + + CLEAR: lt_objects. + + CALL FUNCTION 'TRINT_SELECT_OBJECTS' + EXPORTING + iv_devclass = + iv_via_selscreen = abap_false + IMPORTING + et_objects_tadir = lt_objects + EXCEPTIONS + cancelled_by_user = 1 + invalid_input = 2 + OTHERS = 3. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + INSERT LINES OF lt_objects INTO TABLE lt_objects_all. + + ENDLOOP. + + IF lines( lt_objects_all ) = 0. + zcx_abapgit_exception=>raise( |No objects found| ). + ENDIF. + + LOOP AT lt_objects_all ASSIGNING . + + CLEAR: ls_e071. + + MOVE-CORRESPONDING TO ls_e071. + INSERT ls_e071 INTO TABLE rt_objects. + + ENDLOOP. + + ENDMETHOD. + METHOD find_top_package. +* assumption: all objects in transport share a common super package + + DATA: lt_obj TYPE zif_abapgit_sap_package=>ty_devclass_tt, + lt_super TYPE zif_abapgit_sap_package=>ty_devclass_tt, + lv_super LIKE LINE OF lt_super, + lv_index TYPE i. + + FIELD-SYMBOLS: LIKE LINE OF it_tadir. + READ TABLE it_tadir INDEX 1 ASSIGNING . + ASSERT sy-subrc = 0. + lt_super = zcl_abapgit_factory=>get_sap_package( -devclass )->list_superpackages( ). + + LOOP AT it_tadir ASSIGNING . + lt_obj = zcl_abapgit_factory=>get_sap_package( -devclass )->list_superpackages( ). + +* filter out possibilities from lt_super + LOOP AT lt_super INTO lv_super. + lv_index = sy-tabix. + READ TABLE lt_obj FROM lv_super TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + DELETE lt_super INDEX lv_index. + ENDIF. + ENDLOOP. + ENDLOOP. + + READ TABLE lt_super INDEX lines( lt_super ) INTO rv_package. + ENDMETHOD. + METHOD read_requests. + DATA lt_requests LIKE rt_requests. + FIELD-SYMBOLS LIKE LINE OF it_trkorr. + + LOOP AT it_trkorr ASSIGNING . + CALL FUNCTION 'TR_READ_REQUEST_WITH_TASKS' + EXPORTING + iv_trkorr = + IMPORTING + et_requests = lt_requests + EXCEPTIONS + invalid_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + APPEND LINES OF lt_requests TO rt_requests. + ENDLOOP. + ENDMETHOD. + METHOD resolve. + DATA: lv_object TYPE tadir-object, + lv_obj_name TYPE tadir-obj_name, + ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, + lv_result TYPE trpari-s_checked, + ls_tadir_sap TYPE tadir. + + FIELD-SYMBOLS: LIKE LINE OF it_requests, + LIKE LINE OF -objects. + LOOP AT it_requests ASSIGNING . + LOOP AT -objects ASSIGNING . + " VARX, see https://github.com/abapGit/abapGit/issues/3107 + IF -pgmid = 'LIMU' AND -object <> 'VARX'. + CALL FUNCTION 'TR_CHECK_TYPE' + EXPORTING + wi_e071 = + IMPORTING + we_tadir = ls_tadir_sap + pe_result = lv_result. + IF lv_result NA 'TL' OR ls_tadir_sap IS INITIAL. + zcx_abapgit_exception=>raise( 'error from TR_CHECK_TYPE' ). + ENDIF. + lv_object = ls_tadir_sap-object. + lv_obj_name = ls_tadir_sap-obj_name. + ELSE. + lv_object = -object. + lv_obj_name = -obj_name. + ENDIF. + + ls_tadir = zcl_abapgit_factory=>get_tadir( )->read_single( + iv_object = lv_object + iv_obj_name = lv_obj_name ). + + IF ls_tadir-delflag IS INITIAL OR iv_deleted_objects = abap_true. + APPEND ls_tadir TO rt_tadir. + ENDIF. + ENDLOOP. + ENDLOOP. + + SORT rt_tadir BY object ASCENDING obj_name ASCENDING. + DELETE ADJACENT DUPLICATES FROM rt_tadir COMPARING object obj_name. + DELETE rt_tadir WHERE table_line IS INITIAL. + ENDMETHOD. + METHOD show_log. + + DATA: li_log TYPE REF TO zif_abapgit_log, + lv_message TYPE string. + FIELD-SYMBOLS: TYPE sprot_u. + + CREATE OBJECT li_log TYPE zcl_abapgit_log + EXPORTING + iv_title = iv_title. + + LOOP AT it_log ASSIGNING . + + MESSAGE ID -ag TYPE -severity NUMBER -msgnr + WITH -var1 -var2 -var3 -var4 + INTO lv_message. + + li_log->add( + iv_msg = lv_message + iv_type = -severity ). + + ENDLOOP. + + zcl_abapgit_log_viewer=>show_log( li_log ). + + ENDMETHOD. + METHOD to_tadir. + DATA lt_requests TYPE trwbo_requests. + DATA lt_trkorr TYPE ty_trkorr_tt. + IF iv_trkorr IS INITIAL. + RETURN. + ENDIF. + + INSERT iv_trkorr INTO TABLE lt_trkorr. + + lt_requests = read_requests( lt_trkorr ). + rt_tadir = resolve( + it_requests = lt_requests + iv_deleted_objects = iv_deleted_objects ). + + ENDMETHOD. + METHOD zip. + + DATA: lt_requests TYPE trwbo_requests, + lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, + lv_package TYPE devclass, + lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit, + ls_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings, + lt_trkorr TYPE ty_trkorr_tt, + lv_trkorr TYPE trkorr. + IF is_trkorr IS SUPPLIED. + APPEND is_trkorr-trkorr TO lt_trkorr. + ELSE. + lv_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_transport( ). + IF lv_trkorr IS NOT INITIAL. + APPEND lv_trkorr TO lt_trkorr. + ENDIF. + ENDIF. + + IF lines( lt_trkorr ) = 0. + RETURN. + ENDIF. + + lt_requests = read_requests( lt_trkorr ). + lt_tadir = resolve( lt_requests ). + IF lines( lt_tadir ) = 0. + zcx_abapgit_exception=>raise( 'empty transport' ). + ENDIF. + + lv_package = find_top_package( lt_tadir ). + IF lv_package IS INITIAL. + zcx_abapgit_exception=>raise( 'error finding super package' ). + ENDIF. + + lo_dot_abapgit = zcl_abapgit_dot_abapgit=>build_default( ). + IF iv_logic IS SUPPLIED AND iv_logic IS NOT INITIAL. + lo_dot_abapgit->set_folder_logic( iv_logic ). + ELSE. + lo_dot_abapgit->set_folder_logic( zcl_abapgit_ui_factory=>get_popups( )->popup_folder_logic( ) ). + ENDIF. + + rv_xstr = zcl_abapgit_zip=>export( + iv_package = lv_package + io_dot_abapgit = lo_dot_abapgit + is_local_settings = ls_local_settings + it_filter = lt_tadir + iv_show_log = iv_show_log_popup ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_default_transport IMPLEMENTATION. + METHOD clear. + + CALL FUNCTION 'TR_TASK_RESET' + EXPORTING + iv_username = is_default_task-username + iv_order = is_default_task-ordernum + iv_task = is_default_task-tasknum + iv_dialog = abap_false + EXCEPTIONS + invalid_username = 1 + invalid_order = 2 + invalid_task = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD constructor. + + store( ). + + ENDMETHOD. + METHOD restore. + + IF ms_save IS INITIAL. + " There wasn't a default transport request before + " so we needn't restore anything. + RETURN. + ENDIF. + + CALL FUNCTION 'TR_TASK_SET' + EXPORTING + iv_order = ms_save-ordernum + iv_task = ms_save-tasknum + EXCEPTIONS + invalid_username = 1 + invalid_category = 2 + invalid_client = 3 + invalid_validdays = 4 + invalid_order = 5 + invalid_task = 6 + OTHERS = 7. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD set_internal. + + CALL FUNCTION 'TR_TASK_SET' + EXPORTING + iv_order = iv_transport + iv_validdays = 1 + EXCEPTIONS + invalid_username = 1 + invalid_category = 2 + invalid_client = 3 + invalid_validdays = 4 + invalid_order = 5 + invalid_task = 6 + OTHERS = 7. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD store. + + TRY. + ms_save = zif_abapgit_default_transport~get( ). + CATCH zcx_abapgit_exception. + CLEAR ms_save. + ENDTRY. + + ENDMETHOD. + METHOD zif_abapgit_default_transport~get. + + DATA lt_e070use TYPE STANDARD TABLE OF e070use WITH DEFAULT KEY. + DATA ls_line LIKE LINE OF lt_e070use. + + CALL FUNCTION 'TR_TASK_GET' + TABLES + tt_e070use = lt_e070use + EXCEPTIONS + invalid_username = 1 + invalid_category = 2 + invalid_client = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + READ TABLE lt_e070use INTO ls_line INDEX 1. + IF sy-subrc = 0. + MOVE-CORRESPONDING ls_line TO rs_default_task. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_default_transport~reset. + + DATA: ls_default_task TYPE e070use. + + IF mv_is_set_by_abapgit = abap_false. + " if the default transport request task isn't set + " by us there is nothing to do. + RETURN. + ENDIF. + + CLEAR mv_is_set_by_abapgit. + + ls_default_task = zif_abapgit_default_transport~get( ). + + IF ls_default_task IS NOT INITIAL. + + clear( ls_default_task ). + + ENDIF. + + restore( ). + + ENDMETHOD. + METHOD zif_abapgit_default_transport~set. + + " checks whether object changes of the package are reordered in transport + " requests. If true then we set the default task, so that no annoying + " transport request popups are shown while deserializing. + + IF mv_is_set_by_abapgit = abap_true. + " the default transport request task is already set by us + " -> no reason to do it again. + RETURN. + ENDIF. + + IF iv_transport IS INITIAL. + zcx_abapgit_exception=>raise( |No transport request was supplied| ). + ENDIF. + + set_internal( iv_transport ). + + mv_is_set_by_abapgit = abap_true. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_cts_api IMPLEMENTATION. + METHOD get_current_transport_for_obj. + DATA: lv_object_lockable TYPE abap_bool, + lv_locked TYPE abap_bool, + lv_transport_request TYPE trkorr, + ls_tlock TYPE tlock, + lt_tlock TYPE STANDARD TABLE OF tlock WITH DEFAULT KEY, + lt_transports TYPE STANDARD TABLE OF trkorr WITH DEFAULT KEY, + lv_task TYPE trkorr, + lv_tr_object_name TYPE trobj_name. + + lv_tr_object_name = iv_object_name. + + CALL FUNCTION 'TR_CHECK_OBJECT_LOCK' + EXPORTING + wi_pgmid = iv_program_id + wi_object = iv_object_type + wi_objname = lv_tr_object_name + IMPORTING + we_lockable_object = lv_object_lockable + we_locked = lv_locked + we_lock_order = lv_transport_request + we_lock_task = lv_task + TABLES + wt_tlock = lt_tlock + EXCEPTIONS + empty_key = 1 + no_systemname = 2 + no_systemtype = 3 + unallowed_lock_order = 4 + OTHERS = 5. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF lv_locked = abap_false. + zcx_abapgit_exception=>raise( |Object { iv_program_id }-{ iv_object_type }-{ iv_object_name } is not locked| ). + ENDIF. + + IF lv_object_lockable = abap_false. + zcx_abapgit_exception=>raise( |Object type { iv_program_id }-{ iv_object_type } not lockable| ). + ENDIF. + + LOOP AT lt_tlock INTO ls_tlock. + COLLECT ls_tlock-trkorr INTO lt_transports. + ENDLOOP. + + IF lines( lt_transports ) = 1. + rv_transport = lv_transport_request. + ELSE. + rv_transport = zif_abapgit_definitions=>c_multiple_transports. + ENDIF. + + ENDMETHOD. + METHOD get_current_transport_from_db. + + " This method is used for objects that are included in transports but not locked + " for example, namespaces (NSPC) or table entries (TABU) + " Ignore unreleased SAP piece lists + SELECT SINGLE a~trkorr FROM e070 AS a JOIN e071 AS b ON a~trkorr = b~trkorr + INTO rv_transport + WHERE ( a~trstatus = 'D' OR a~trstatus = 'L' ) + AND a~trfunction <> 'G' + AND NOT ( a~trfunction = 'F' AND ( a~tarsystem = '' OR a~tarsystem = 'SAP' ) ) + AND b~pgmid = iv_program_id AND b~object = iv_object_type AND b~obj_name = iv_object_name. + + ENDMETHOD. + METHOD is_object_locked_in_transport. + DATA: ls_object_key TYPE e071, + lv_type_check_result TYPE c LENGTH 1, + ls_lock_key TYPE tlock_int, + lv_lock_flag TYPE c LENGTH 1. + + ls_object_key-pgmid = iv_program_id. + ls_object_key-object = iv_object_type. + ls_object_key-obj_name = iv_object_name. + + CALL FUNCTION 'TR_CHECK_TYPE' + EXPORTING + wi_e071 = ls_object_key + IMPORTING + pe_result = lv_type_check_result + we_lock_key = ls_lock_key. + + IF lv_type_check_result <> 'L'. + zcx_abapgit_exception=>raise( |Object type { iv_program_id }-{ iv_object_type } not lockable| ). + ENDIF. + + CALL FUNCTION 'TRINT_CHECK_LOCKS' + EXPORTING + wi_lock_key = ls_lock_key + IMPORTING + we_lockflag = lv_lock_flag + EXCEPTIONS + empty_key = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + rv_locked = boolc( lv_lock_flag <> space ). + ENDMETHOD. + METHOD is_object_type_lockable. + DATA: ls_object_key TYPE e071, + lv_type_check_result TYPE c LENGTH 1. + + ls_object_key-pgmid = iv_program_id. + ls_object_key-object = iv_object_type. + ls_object_key-obj_name = '_'. " Dummy value #2071 + + CALL FUNCTION 'TR_CHECK_TYPE' + EXPORTING + wi_e071 = ls_object_key + IMPORTING + pe_result = lv_type_check_result. + + rv_lockable = boolc( lv_type_check_result = 'L' ). + ENDMETHOD. + METHOD is_object_type_transportable. + DATA: ls_object_key TYPE e071, + lv_type_check_result TYPE c LENGTH 1. + + ls_object_key-pgmid = iv_program_id. + ls_object_key-object = iv_object_type. + ls_object_key-obj_name = '_'. " Dummy value #2071 + + CALL FUNCTION 'TR_CHECK_TYPE' + EXPORTING + wi_e071 = ls_object_key + IMPORTING + pe_result = lv_type_check_result. + + rv_transportable = boolc( lv_type_check_result CA 'RTL' OR iv_object_type = 'TABU' ). + ENDMETHOD. + METHOD zif_abapgit_cts_api~change_transport_type. + + DATA: + ls_request_header TYPE trwbo_request_header, + lt_request_headers TYPE trwbo_request_headers. + + CALL FUNCTION 'ENQUEUE_E_TRKORR' + EXPORTING + trkorr = iv_transport_request + EXCEPTIONS + foreign_lock = 1 + system_failure = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'TR_READ_REQUEST_WITH_TASKS' + EXPORTING + iv_trkorr = iv_transport_request + IMPORTING + et_request_headers = lt_request_headers + EXCEPTIONS + invalid_input = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + LOOP AT lt_request_headers INTO ls_request_header WHERE trfunction = iv_transport_type_from. + + CALL FUNCTION 'TRINT_READ_REQUEST_HEADER' + EXPORTING + iv_read_e070 = abap_true + iv_read_e070c = abap_true + CHANGING + cs_request = ls_request_header + EXCEPTIONS + empty_trkorr = 1 + not_exist_e070 = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + CALL FUNCTION 'TRINT_CHANGE_TRFUNCTION' + EXPORTING + iv_new_trfunction = iv_transport_type_to + CHANGING + cs_request_header = ls_request_header + EXCEPTIONS + action_aborted_by_user = 1 + change_not_allowed = 2 + db_access_error = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDLOOP. + + CALL FUNCTION 'DEQUEUE_E_TRKORR' + EXPORTING + trkorr = iv_transport_request. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~confirm_transport_messages. + + TYPES: BEGIN OF ty_s_message, + id TYPE symsgid, + ty TYPE symsgty, + no TYPE symsgno, + v1 TYPE symsgv, + v2 TYPE symsgv, + v3 TYPE symsgv, + v4 TYPE symsgv, + END OF ty_s_message. + + DATA ls_message TYPE ty_s_message. + + FIELD-SYMBOLS: TYPE STANDARD TABLE. + + IF mv_confirm_transp_msgs_called = abap_true. + RETURN. + ENDIF. + + " remember the call to avoid duplicates in GT_CONFIRMED_MESSAGES + mv_confirm_transp_msgs_called = abap_true. + " Auto-confirm certain messages (requires SAP Note 1609940) + PERFORM dummy IN PROGRAM saplstrd IF FOUND. "load function group STRD once into memory + + ASSIGN ('(SAPLSTRD)GT_CONFIRMED_MESSAGES') TO . + + IF sy-subrc <> 0. + RETURN. + ENDIF. + + " Object can only be created in package of namespace + ls_message-id = 'TR'. + ls_message-no = '007'. + INSERT ls_message INTO TABLE . + + " Original system set to "SAP" + ls_message-id = 'TR'. + ls_message-no = '013'. + INSERT ls_message INTO TABLE . + + " Make repairs in foreign namespaces only if they are urgent + ls_message-id = 'TR'. + ls_message-no = '852'. + INSERT ls_message INTO TABLE . + + " Make repairs in foreign namespaces only if they are urgent + ls_message-id = 'TK'. + ls_message-no = '016'. + INSERT ls_message INTO TABLE . + + rv_messages_confirmed = abap_true. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~create_transport_entries. + + DATA lt_tables TYPE tredt_objects. + DATA lt_table_keys TYPE STANDARD TABLE OF e071k. + DATA lv_with_dialog TYPE abap_bool. + + FIELD-SYMBOLS LIKE LINE OF lt_tables. + FIELD-SYMBOLS LIKE LINE OF lt_table_keys. + + cl_table_utilities_brf=>create_transport_entries( + EXPORTING + it_table_ins = it_table_ins + it_table_upd = it_table_upd + it_table_del = it_table_del + iv_tabname = iv_tabname + CHANGING + ct_e071 = lt_tables + ct_e071k = lt_table_keys ). + + " cl_table_utilities_brf=>write_transport_entries does not allow passing a request + + CALL FUNCTION 'TR_OBJECTS_CHECK' + TABLES + wt_ko200 = lt_tables + wt_e071k = lt_table_keys + EXCEPTIONS + cancel_edit_other_error = 1 + show_only_other_error = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + IF iv_transport IS INITIAL. + lv_with_dialog = abap_true. + ENDIF. + + READ TABLE lt_tables ASSIGNING INDEX 1. + ASSERT sy-subrc = 0. + + LOOP AT lt_table_keys ASSIGNING . + -objfunc = -objfunc. + ENDLOOP. + + CALL FUNCTION 'TR_OBJECT_INSERT' + EXPORTING + wi_order = iv_transport + wi_ko200 = + iv_no_show_option = abap_true + TABLES + wt_e071k = lt_table_keys + EXCEPTIONS + cancel_edit_other_error = 1 + show_only_other_error = 2 + OTHERS = 3. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~get_r3tr_obj_for_limu_obj. + + CLEAR ev_object. + CLEAR ev_obj_name. + + CASE iv_object. + WHEN 'MESS'. + ev_object = 'MSAG'. + ev_obj_name = substring( val = iv_obj_name + len = strlen( iv_obj_name ) - 3 ). + WHEN 'TABT'. +* Technical Attributes of a Table + ev_object = 'TABL'. + ev_obj_name = iv_obj_name. + WHEN 'DTED'. +* Data Element Definition + ev_object = 'DTEL'. + ev_obj_name = iv_obj_name. + WHEN 'DOMD'. +* Domain Definition + ev_object = 'DOMA'. + ev_obj_name = iv_obj_name. + WHEN OTHERS. + CALL FUNCTION 'GET_R3TR_OBJECT_FROM_LIMU_OBJ' + EXPORTING + p_limu_objtype = iv_object + p_limu_objname = iv_obj_name + IMPORTING + p_r3tr_objtype = ev_object + p_r3tr_objname = ev_obj_name + EXCEPTIONS + no_mapping = 1 + OTHERS = 2. + IF sy-subrc <> 0 OR ev_obj_name IS INITIAL. + zcx_abapgit_exception=>raise( |No R3TR Object found for { iv_object } { iv_obj_name }| ). + ENDIF. + ENDCASE. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~get_transports_for_list. + + DATA lv_request TYPE trkorr. + DATA lt_tlock TYPE SORTED TABLE OF tlock WITH NON-UNIQUE KEY object hikey. + DATA ls_object_key TYPE e071. + DATA lv_type_check_result TYPE c LENGTH 1. + DATA ls_lock_key TYPE tlock_int. + DATA ls_transport LIKE LINE OF rt_transports. + + FIELD-SYMBOLS LIKE LINE OF it_items. + FIELD-SYMBOLS LIKE LINE OF lt_tlock. + +* Workarounds to improve performance, note that IT_ITEMS might +* contain 1000s of rows, see standard logic in function module +* TR_CHECK_OBJECT_LOCK + +* avoid database lookups in TLOCK for each item, + SELECT * FROM tlock INTO TABLE lt_tlock. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + LOOP AT it_items ASSIGNING . + CLEAR lv_request. + + ls_object_key-pgmid = 'R3TR'. + ls_object_key-object = -obj_type. + ls_object_key-obj_name = -obj_name. + + CALL FUNCTION 'TR_CHECK_TYPE' + EXPORTING + wi_e071 = ls_object_key + IMPORTING + we_lock_key = ls_lock_key + pe_result = lv_type_check_result. + + IF lv_type_check_result = 'L'. + LOOP AT lt_tlock ASSIGNING + WHERE object = ls_lock_key-obj + AND hikey >= ls_lock_key-low + AND lokey <= ls_lock_key-hi. "#EC PORTABLE + IF lv_request IS INITIAL. + lv_request = -trkorr. + ELSE. + lv_request = zif_abapgit_definitions=>c_multiple_transports. + EXIT. + ENDIF. + ENDLOOP. + ELSEIF is_object_type_transportable( -obj_type ) = abap_true. + lv_request = get_current_transport_from_db( + iv_object_type = -obj_type + iv_object_name = -obj_name ). + ENDIF. + + IF lv_request IS NOT INITIAL. + ls_transport-obj_type = -obj_type. + ls_transport-obj_name = -obj_name. + ls_transport-trkorr = lv_request. + INSERT ls_transport INTO TABLE rt_transports. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~get_transport_for_object. + + IF is_item-obj_type IS NOT INITIAL AND is_item-obj_name IS NOT INITIAL. + + IF is_object_type_lockable( is_item-obj_type ) = abap_true AND + is_object_locked_in_transport( + iv_object_type = is_item-obj_type + iv_object_name = is_item-obj_name ) = abap_true. + + rv_transport = get_current_transport_for_obj( + iv_object_type = is_item-obj_type + iv_object_name = is_item-obj_name ). + + ELSEIF is_object_type_transportable( is_item-obj_type ) = abap_true. + + rv_transport = get_current_transport_from_db( + iv_object_type = is_item-obj_type + iv_object_name = is_item-obj_name ). + + ENDIF. + + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~insert_transport_object. + + CALL FUNCTION 'RS_CORR_INSERT' + EXPORTING + object = iv_obj_name + object_class = iv_object + devclass = iv_package + master_language = iv_language + korrnum = iv_transport + mode = iv_mode + global_lock = abap_true + suppress_dialog = abap_true + EXCEPTIONS + cancelled = 1 + permission_failure = 2 + unknown_objectclass = 3 + OTHERS = 4. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~is_chrec_possible_for_package. + IF iv_package IS NOT INITIAL. + rv_possible = zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ). + ENDIF. + ENDMETHOD. + METHOD zif_abapgit_cts_api~list_open_requests. + + TYPES: BEGIN OF ty_e070, + trkorr TYPE e070-trkorr, + trfunction TYPE e070-trfunction, + strkorr TYPE e070-strkorr, + END OF ty_e070. + DATA lt_e070 TYPE STANDARD TABLE OF ty_e070 WITH DEFAULT KEY. + +* find all tasks first + SELECT trkorr trfunction strkorr + FROM e070 INTO TABLE lt_e070 + WHERE trstatus = zif_abapgit_cts_api=>c_transport_status-modifiable + AND as4user IN it_user + AND as4date IN it_date + AND strkorr <> '' + ORDER BY PRIMARY KEY. + + IF lines( lt_e070 ) > 0. + SELECT trkorr FROM e070 + INTO TABLE rt_trkorr + FOR ALL ENTRIES IN lt_e070 + WHERE trkorr = lt_e070-strkorr + AND trfunction = zif_abapgit_cts_api=>c_transport_type-wb_request. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~list_r3tr_by_request. + + TYPES: BEGIN OF ty_contents, + trkorr TYPE e071-trkorr, + as4pos TYPE e071-as4pos, + pgmid TYPE e071-pgmid, + object TYPE e071-object, + obj_name TYPE e071-obj_name, + END OF ty_contents. + + DATA lt_tasks TYPE STANDARD TABLE OF trkorr WITH DEFAULT KEY. + DATA lt_contents TYPE STANDARD TABLE OF ty_contents WITH DEFAULT KEY. + DATA ls_contents LIKE LINE OF lt_contents. + DATA ls_list LIKE LINE OF rt_list. + SELECT trkorr FROM e070 INTO TABLE lt_tasks + WHERE strkorr = iv_request + ORDER BY PRIMARY KEY. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + SELECT trkorr as4pos pgmid object obj_name FROM e071 + INTO TABLE lt_contents + FOR ALL ENTRIES IN lt_tasks + WHERE trkorr = lt_tasks-table_line + ORDER BY PRIMARY KEY. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + LOOP AT lt_contents INTO ls_contents. + CASE ls_contents-pgmid. + WHEN 'R3TR'. + ls_list-object = ls_contents-object. + ls_list-obj_name = ls_contents-obj_name. + INSERT ls_list INTO TABLE rt_list. + WHEN 'LIMU'. + TRY. + zif_abapgit_cts_api~get_r3tr_obj_for_limu_obj( + EXPORTING + iv_object = ls_contents-object + iv_obj_name = ls_contents-obj_name + IMPORTING + ev_object = ls_list-object + ev_obj_name = ls_list-obj_name ). + INSERT ls_list INTO TABLE rt_list. + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + ENDCASE. + ENDLOOP. + + SORT rt_list BY object obj_name. + DELETE ADJACENT DUPLICATES FROM rt_list COMPARING object obj_name. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~read. + + DATA ls_request TYPE trwbo_request. + DATA ls_key LIKE LINE OF ls_request-keys. + + FIELD-SYMBOLS LIKE LINE OF rs_request-keys. + ls_request-h-trkorr = iv_trkorr. + + CALL FUNCTION 'TRINT_READ_REQUEST' + EXPORTING + iv_read_e070 = abap_true + iv_read_e07t = abap_true + iv_read_e070c = abap_true + iv_read_e070m = abap_true + iv_read_objs_keys = abap_true + iv_read_objs = abap_true + iv_read_attributes = abap_true + CHANGING + cs_request = ls_request + EXCEPTIONS + error_occured = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + +* move to output structure + rs_request-trstatus = ls_request-h-trstatus. + rs_request-as4date = ls_request-h-as4date. + LOOP AT ls_request-keys INTO ls_key. + APPEND INITIAL LINE TO rs_request-keys ASSIGNING . + MOVE-CORRESPONDING ls_key TO . + ENDLOOP. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~read_description. + + SELECT SINGLE as4text FROM e07t + INTO rv_description + WHERE trkorr = iv_trkorr + AND langu = sy-langu. + IF sy-subrc <> 0. +* fallback to any language + SELECT SINGLE as4text FROM e07t + INTO rv_description + WHERE trkorr = iv_trkorr ##SUBRC_OK. "#EC CI_NOORDER + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~read_user. + + SELECT SINGLE as4user FROM e070 INTO rv_uname + WHERE trkorr = iv_trkorr ##SUBRC_OK. + + ENDMETHOD. + METHOD zif_abapgit_cts_api~validate_transport_request. + + CONSTANTS: + BEGIN OF c_tr_status, + modifiable TYPE trstatus VALUE 'D', + modifiable_protected TYPE trstatus VALUE 'L', + END OF c_tr_status. + + DATA ls_request TYPE zif_abapgit_cts_api=>ty_transport_data. + + ls_request = zif_abapgit_cts_api~read( iv_transport_request ). + + IF ls_request-trstatus <> c_tr_status-modifiable + AND ls_request-trstatus <> c_tr_status-modifiable_protected. + " Task/request &1 has already been released + MESSAGE e064(tk) WITH iv_transport_request INTO zcx_abapgit_exception=>null. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_background_push_fi IMPLEMENTATION. + METHOD build_comment. + + DATA: lt_objects TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + lv_str TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF is_files-local. + LOOP AT is_files-local ASSIGNING . + lv_str = |{ -item-obj_type } { -item-obj_name }|. + APPEND lv_str TO lt_objects. + ENDLOOP. + + SORT lt_objects AS TEXT. + DELETE ADJACENT DUPLICATES FROM lt_objects. + + IF lines( lt_objects ) = 1. + rv_comment = |BG: { lv_str }|. + ELSE. + rv_comment = 'BG: Multiple objects'. + LOOP AT lt_objects INTO lv_str. + CONCATENATE rv_comment cl_abap_char_utilities=>newline lv_str INTO rv_comment. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD push_fixed. + + DATA: ls_comment TYPE zif_abapgit_git_definitions=>ty_comment, + ls_files TYPE zif_abapgit_definitions=>ty_stage_files, + lo_stage TYPE REF TO zcl_abapgit_stage. + + FIELD-SYMBOLS: LIKE LINE OF ls_files-local, + LIKE LINE OF ls_files-remote. + ls_files = zcl_abapgit_stage_logic=>get_stage_logic( )->get( ii_repo_online ). + ASSERT lines( ls_files-local ) > 0 + OR lines( ls_files-remote ) > 0. + + CREATE OBJECT lo_stage. + + LOOP AT ls_files-local ASSIGNING . + mi_log->add_info( |stage: { -file-path } { -file-filename }| ). + lo_stage->add( iv_path = -file-path + iv_filename = -file-filename + iv_data = -file-data ). + ENDLOOP. + + LOOP AT ls_files-remote ASSIGNING . + + mi_log->add_info( |removed: { -path } { -filename }| ). + + lo_stage->rm( iv_path = -path + iv_filename = -filename ). + + ENDLOOP. + + ls_comment-committer-name = iv_name. + ls_comment-committer-email = iv_email. + ls_comment-comment = build_comment( ls_files ). + + ii_repo_online->push( is_comment = ls_comment + io_stage = lo_stage ). + + ENDMETHOD. + METHOD zif_abapgit_background~get_description. + + rv_description = 'Automatic push, fixed author'. + + ENDMETHOD. + METHOD zif_abapgit_background~get_settings. + + DATA: ls_setting LIKE LINE OF ct_settings. + READ TABLE ct_settings WITH KEY key = c_settings-name INTO ls_setting. + IF sy-subrc <> 0. + ls_setting-key = c_settings-name. + ls_setting-value = 'foobar'. + APPEND ls_setting TO ct_settings. + ENDIF. + + READ TABLE ct_settings WITH KEY key = c_settings-email INTO ls_setting. + IF sy-subrc <> 0. + ls_setting-key = c_settings-email. + ls_setting-value = 'foobar@localhost'. + APPEND ls_setting TO ct_settings. + ENDIF. + + ENDMETHOD. + METHOD zif_abapgit_background~run. + + DATA: ls_files TYPE zif_abapgit_definitions=>ty_stage_files, + ls_setting LIKE LINE OF it_settings, + lv_name TYPE string, + lv_email TYPE string. + + mi_log = ii_log. + ls_files = zcl_abapgit_stage_logic=>get_stage_logic( )->get( ii_repo_online ). + + IF lines( ls_files-local ) = 0 AND lines( ls_files-remote ) = 0. + ii_log->add_info( 'Nothing to stage' ). + RETURN. + ENDIF. + + READ TABLE it_settings WITH KEY key = c_settings-name INTO ls_setting. "#EC CI_SUBRC + lv_name = ls_setting-value. + + READ TABLE it_settings WITH KEY key = c_settings-email INTO ls_setting. "#EC CI_SUBRC + lv_email = ls_setting-value. + + push_fixed( + ii_repo_online = ii_repo_online + iv_name = lv_name + iv_email = lv_email ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_background_push_au IMPLEMENTATION. + METHOD build_comment. + + DATA: lt_objects TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + lv_str TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF is_files-local. + LOOP AT is_files-local ASSIGNING . + lv_str = |{ -item-obj_type } { -item-obj_name }|. + APPEND lv_str TO lt_objects. + ENDLOOP. + + SORT lt_objects AS TEXT. + DELETE ADJACENT DUPLICATES FROM lt_objects. + + IF lines( lt_objects ) = 1. + rv_comment = |BG: { lv_str }|. + ELSE. + rv_comment = 'BG: Multiple objects'. + LOOP AT lt_objects INTO lv_str. + CONCATENATE rv_comment cl_abap_char_utilities=>newline lv_str INTO rv_comment. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD determine_user_details. + + DATA li_user_record TYPE REF TO zif_abapgit_user_record. + li_user_record = zcl_abapgit_env_factory=>get_user_record( ). + rs_user-name = li_user_record->get_name( iv_changed_by ). + rs_user-email = li_user_record->get_email( iv_changed_by ). + +* If no email, fall back to localhost/default email + IF rs_user-email IS INITIAL. + rs_user-email = |{ iv_changed_by }@localhost|. + ENDIF. + +* If no full name maintained, just use changed by user name + IF rs_user-name IS INITIAL. + rs_user-name = iv_changed_by. + ENDIF. + + ENDMETHOD. + METHOD push_auto. + + TYPES: BEGIN OF ty_changed, + filename TYPE string, + path TYPE string, + changed_by TYPE syuname, + END OF ty_changed. + + DATA: ls_comment TYPE zif_abapgit_git_definitions=>ty_comment, + ls_files TYPE zif_abapgit_definitions=>ty_stage_files, + lt_changed TYPE HASHED TABLE OF ty_changed WITH UNIQUE KEY filename path changed_by, + ls_changed TYPE ty_changed, + lt_users TYPE STANDARD TABLE OF syuname WITH DEFAULT KEY, + ls_user_files LIKE ls_files, + lv_changed_by LIKE LINE OF lt_users, + lo_stage TYPE REF TO zcl_abapgit_stage. + + FIELD-SYMBOLS: + LIKE LINE OF ls_files-remote, + LIKE LINE OF ls_files-local. + ls_files = zcl_abapgit_stage_logic=>get_stage_logic( )->get( ii_repo_online ). + + LOOP AT ls_files-local ASSIGNING . + lv_changed_by = zcl_abapgit_objects=>changed_by( + is_item = -item + iv_filename = -file-filename ). + APPEND lv_changed_by TO lt_users. + + CLEAR ls_changed. + ls_changed-changed_by = lv_changed_by. + ls_changed-filename = -file-filename. + ls_changed-path = -file-path. + INSERT ls_changed INTO TABLE lt_changed. + ENDLOOP. + + SORT lt_users ASCENDING. + DELETE ADJACENT DUPLICATES FROM lt_users. + + LOOP AT lt_users INTO lv_changed_by. + CLEAR: ls_comment. + +* Fill user details + ls_comment-committer = determine_user_details( lv_changed_by ). + + CREATE OBJECT lo_stage. + + CLEAR ls_user_files. + + LOOP AT ls_files-local ASSIGNING . + READ TABLE lt_changed WITH KEY + path = -file-path + filename = -file-filename + changed_by = lv_changed_by + TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + mi_log->add_info( |stage: { + ls_comment-committer-name } { + -file-path } { + -file-filename }| ). + + lo_stage->add( iv_path = -file-path + iv_filename = -file-filename + iv_data = -file-data ). + + APPEND TO ls_user_files-local. + + LOOP AT ls_files-remote ASSIGNING + USING KEY file + WHERE filename = -file-filename + AND path <> -file-path + AND filename <> 'package.devc.xml'. + mi_log->add_info( |rm: { -path } { -filename }| ). + +* rm old file when object has moved + lo_stage->rm( + iv_path = -path + iv_filename = -filename ). + EXIT. " assumption: only one file + ENDLOOP. + ENDIF. + ENDLOOP. + + ls_comment-comment = build_comment( ls_user_files ). + + ii_repo_online->push( is_comment = ls_comment + io_stage = lo_stage ). + ENDLOOP. + + IF lines( ls_files-remote ) > 0. + push_deletions( ii_repo_online = ii_repo_online + is_files = ls_files ). + ENDIF. + + ENDMETHOD. + METHOD push_deletions. + + DATA: lo_stage TYPE REF TO zcl_abapgit_stage, + ls_comment TYPE zif_abapgit_git_definitions=>ty_comment. + + FIELD-SYMBOLS: LIKE LINE OF is_files-remote. + + ASSERT lines( is_files-remote ) > 0. + + CREATE OBJECT lo_stage. + + ls_comment-comment = 'BG: Deletion'. + + LOOP AT is_files-remote ASSIGNING . + + mi_log->add_info( |removed: { -path } { -filename }| ). + + lo_stage->rm( iv_path = -path + iv_filename = -filename ). + + CONCATENATE ls_comment-comment cl_abap_char_utilities=>newline -filename + INTO ls_comment-comment. + + ENDLOOP. + + ls_comment-committer-name = 'Deletion'. + ls_comment-committer-email = 'deletion@localhost'. + + ii_repo_online->push( is_comment = ls_comment + io_stage = lo_stage ). + + ENDMETHOD. + METHOD zif_abapgit_background~get_description. + + rv_description = 'Automatic push, auto author'. + + ENDMETHOD. + METHOD zif_abapgit_background~get_settings. + + RETURN. + + ENDMETHOD. + METHOD zif_abapgit_background~run. + + DATA: ls_files TYPE zif_abapgit_definitions=>ty_stage_files. + + mi_log = ii_log. + ls_files = zcl_abapgit_stage_logic=>get_stage_logic( )->get( ii_repo_online ). + + IF lines( ls_files-local ) = 0 AND lines( ls_files-remote ) = 0. + ii_log->add_info( 'Nothing to stage' ). + RETURN. + ENDIF. + + push_auto( ii_repo_online ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_background_pull IMPLEMENTATION. + METHOD zif_abapgit_background~get_description. + + rv_description = 'Automatic pull'. + + ENDMETHOD. + METHOD zif_abapgit_background~get_settings. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_background~run. + + DATA: ls_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks, + lo_settings TYPE REF TO zcl_abapgit_settings, + li_repo TYPE REF TO zif_abapgit_repo, + lv_activation_setting TYPE zif_abapgit_persist_user=>ty_s_user_settings-activate_wo_popup. + + FIELD-SYMBOLS: LIKE LINE OF ls_checks-overwrite. + + li_repo = ii_repo_online. + + ls_checks = li_repo->deserialize_checks( ). + + LOOP AT ls_checks-overwrite ASSIGNING . + -decision = zif_abapgit_definitions=>c_yes. + ENDLOOP. + + lo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + lv_activation_setting = lo_settings->get_activate_wo_popup( ). + + lo_settings->set_activate_wo_popup( abap_true ). + " pass decisions to delete + zcl_abapgit_services_repo=>delete_unnecessary_objects( + ii_repo = li_repo + is_checks = ls_checks + ii_log = ii_log ). + + li_repo->deserialize( is_checks = ls_checks + ii_log = ii_log ). + + lo_settings->set_activate_wo_popup( lv_activation_setting ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_background IMPLEMENTATION. + METHOD dequeue. + CALL FUNCTION 'DEQUEUE_EZABAPGIT' + EXPORTING + type = c_enq_type. + ENDMETHOD. + METHOD enqueue. + CALL FUNCTION 'ENQUEUE_EZABAPGIT' + EXPORTING + mode_zabapgit = 'E' + type = c_enq_type + _scope = '3' + EXCEPTIONS + foreign_lock = 1 + system_failure = 2 + OTHERS = 3. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + ENDMETHOD. + METHOD list_methods. + + DATA: ls_method LIKE LINE OF rt_methods, + lt_implementing TYPE seor_implementing_keys, + ls_implementing LIKE LINE OF lt_implementing, + lt_interf TYPE abap_intfdescr_tab, + lt_local_classes TYPE STANDARD TABLE OF scompo, + lv_classname TYPE string, + lr_typedescr TYPE REF TO cl_abap_typedescr, + lr_typedescr_class TYPE REF TO cl_abap_classdescr. + + FIELD-SYMBOLS: LIKE LINE OF lt_local_classes, + LIKE LINE OF rt_methods. + + IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. + " Assume the standalone version runs. + CALL FUNCTION 'WB_TREE_GET_OBJECTS' + EXPORTING + include = ' ' + otype = 'L' + program = sy-repid + TABLES + olist = lt_local_classes. + + LOOP AT lt_local_classes ASSIGNING . + lv_classname = |\\PROGRAM={ sy-repid }\\CLASS={ -name }|. + cl_abap_typedescr=>describe_by_name( + EXPORTING + p_name = lv_classname + RECEIVING + p_descr_ref = lr_typedescr + EXCEPTIONS + type_not_found = 1 + OTHERS = 2 ). + + IF sy-subrc = 0 AND lr_typedescr IS BOUND. + lr_typedescr_class ?= lr_typedescr. + IF lr_typedescr_class IS BOUND. + lt_interf = lr_typedescr_class->interfaces. + READ TABLE lt_interf WITH TABLE KEY name = c_interface TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + ls_method-class = -name. + INSERT ls_method INTO TABLE rt_methods. + ENDIF. + ENDIF. + ENDIF. + ENDLOOP. + + ELSE. + " Assume the developer version runs. + CALL FUNCTION 'SEO_INTERFACE_IMPLEM_GET_ALL' + EXPORTING + intkey = c_interface + IMPORTING + impkeys = lt_implementing + EXCEPTIONS + not_existing = 1 + OTHERS = 2. + IF sy-subrc = 0. + LOOP AT lt_implementing INTO ls_implementing. + ls_method-class = ls_implementing-clsname. + INSERT ls_method INTO TABLE rt_methods. + ENDLOOP. + ENDIF. + ENDIF. + + LOOP AT rt_methods ASSIGNING . + CALL METHOD (-class)=>zif_abapgit_background~get_description + RECEIVING + rv_description = -description. + ENDLOOP. + + ENDMETHOD. + METHOD run. + + DATA: + li_repo TYPE REF TO zif_abapgit_repo, + li_repo_online TYPE REF TO zif_abapgit_repo_online, + lt_list TYPE zif_abapgit_persist_background=>ty_background_keys, + li_background TYPE REF TO zif_abapgit_background, + li_log TYPE REF TO zif_abapgit_log, + lx_error TYPE REF TO zcx_abapgit_exception, + lv_repo_name TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF lt_list. + + TRY. + enqueue( ). + CATCH zcx_abapgit_exception. + WRITE: / 'Another instance of the program is already running'. + RETURN. + ENDTRY. + + lt_list = zcl_abapgit_persist_factory=>get_background( )->list( ). + + WRITE: / 'Background mode'. + + LOOP AT lt_list ASSIGNING . + CREATE OBJECT li_log TYPE zcl_abapgit_log. + + TRY. + li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( -key ). + li_repo_online ?= li_repo. + lv_repo_name = li_repo->get_name( ). + WRITE: / -method, lv_repo_name. + + zcl_abapgit_login_manager=>set_basic( + iv_uri = li_repo_online->get_url( ) + iv_username = -username + iv_password = -password ). + + TRY. + CREATE OBJECT li_background TYPE (-method). + + li_background->run( + ii_repo_online = li_repo_online + ii_log = li_log + it_settings = -settings ). + CATCH cx_sy_create_object_error. + li_log->add_warning( |{ -method } could not be executed,| + & | as it is not accessible (local/global class).| ). + ENDTRY. + + " Decrease memory usage for repository already processed (but keep log) + li_repo->refresh( + iv_drop_cache = abap_true + iv_drop_log = abap_false ). + CATCH zcx_abapgit_exception INTO lx_error. + li_log->add_exception( lx_error ). + ENDTRY. + + " Clear auth buffer to allow different user/password per repository in background mode + zcl_abapgit_login_manager=>clear( ). + + zcl_abapgit_log_viewer=>write_log( li_log ). + ENDLOOP. + + IF lines( lt_list ) = 0. + WRITE: / 'Nothing configured'. + ENDIF. + + dequeue( ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_apack_writer IMPLEMENTATION. + METHOD constructor. + ms_manifest_descriptor = is_apack_manifest_descriptor. + ENDMETHOD. + METHOD create_instance. + CREATE OBJECT ro_manifest_writer EXPORTING is_apack_manifest_descriptor = is_apack_manifest_descriptor. + ENDMETHOD. + METHOD serialize. + + DATA: ls_manifest_descriptor LIKE ms_manifest_descriptor. + FIELD-SYMBOLS: LIKE LINE OF ls_manifest_descriptor-dependencies. + + " Setting repository type automatically to 'abapGit' as there is no other one right now + ms_manifest_descriptor-repository_type = zif_abapgit_apack_definitions=>c_repository_type_abapgit. + + ls_manifest_descriptor = ms_manifest_descriptor. + CLEAR: ls_manifest_descriptor-sem_version. + + LOOP AT ls_manifest_descriptor-dependencies ASSIGNING . + CLEAR: -sem_version. + ENDLOOP. + + CALL TRANSFORMATION id + OPTIONS initial_components = 'suppress' + SOURCE data = ls_manifest_descriptor + RESULT XML rv_xml. + + rv_xml = zcl_abapgit_xml_pretty=>print( rv_xml ). + + REPLACE FIRST OCCURRENCE + OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' + IN rv_xml + WITH ''. + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_apack_reader IMPLEMENTATION. + METHOD constructor. + ASSERT iv_package_name IS NOT INITIAL. + mv_package_name = iv_package_name. + ENDMETHOD. + METHOD copy_manifest_descriptor. + + DATA: ls_my_manifest_wo_deps TYPE zif_abapgit_apack_definitions=>ty_descriptor_wo_dependencies, + ls_my_dependency TYPE zif_abapgit_apack_definitions=>ty_dependency, + ls_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor, + lv_descriptor_cust TYPE string, + lv_descriptor_sap TYPE string, + lv_descriptor_nspc TYPE string, + lv_class_name TYPE abap_abstypename, + lv_empty TYPE string, + ls_namespace TYPE zif_abapgit_definitions=>ty_obj_namespace. + + FIELD-SYMBOLS: TYPE any, + TYPE ANY TABLE, + TYPE any. + + lv_descriptor_cust = zif_abapgit_apack_definitions=>c_apack_interface_cust && '~DESCRIPTOR'. + lv_descriptor_sap = zif_abapgit_apack_definitions=>c_apack_interface_sap && '~DESCRIPTOR'. + + lv_class_name = cl_abap_classdescr=>get_class_name( io_manifest_provider ). + SPLIT lv_class_name AT '\CLASS=' INTO lv_empty lv_class_name. + ls_namespace = zcl_abapgit_factory=>get_sap_namespace( )->split_by_name( lv_class_name ). + + IF ls_namespace-namespace IS NOT INITIAL. + lv_descriptor_nspc = |{ ls_namespace-namespace }{ lv_descriptor_sap }|. + ENDIF. + + ASSIGN io_manifest_provider->(lv_descriptor_cust) TO . + IF IS NOT ASSIGNED. + ASSIGN io_manifest_provider->(lv_descriptor_sap) TO . + IF IS NOT ASSIGNED AND lv_descriptor_nspc IS NOT INITIAL. + ASSIGN io_manifest_provider->(lv_descriptor_nspc) TO . + ENDIF. + ENDIF. + IF IS ASSIGNED. + " A little more complex than a normal MOVE-CORRSPONDING + " to avoid dumps in case of future updates to the dependencies table structure + ASSIGN COMPONENT 'DEPENDENCIES' OF STRUCTURE TO . + IF IS ASSIGNED. + LOOP AT ASSIGNING . + MOVE-CORRESPONDING TO ls_my_dependency. + INSERT ls_my_dependency INTO TABLE ls_descriptor-dependencies. + ENDLOOP. + MOVE-CORRESPONDING TO ls_my_manifest_wo_deps. + MOVE-CORRESPONDING ls_my_manifest_wo_deps TO ls_descriptor. + ENDIF. + ENDIF. + + set_manifest_descriptor( ls_descriptor ). + + ENDMETHOD. + METHOD create_instance. + + DATA ls_instance TYPE ty_instance. + + " One instance per package + READ TABLE gt_instances INTO ls_instance WITH TABLE KEY package = iv_package_name. + IF sy-subrc <> 0. + ls_instance-package = iv_package_name. + + CREATE OBJECT ls_instance-instance + EXPORTING + iv_package_name = iv_package_name. + + INSERT ls_instance INTO TABLE gt_instances. + ENDIF. + + ro_manifest_reader = ls_instance-instance. + + ENDMETHOD. + METHOD deserialize. + + DATA: lv_xml TYPE string, + ls_data TYPE zif_abapgit_apack_definitions=>ty_descriptor. + + lv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( iv_xstr ). + + ls_data = from_xml( lv_xml ). + + ro_manifest_reader = create_instance( iv_package_name ). + ro_manifest_reader->set_manifest_descriptor( ls_data ). + + ENDMETHOD. + METHOD format_version. + + FIELD-SYMBOLS: TYPE zif_abapgit_apack_definitions=>ty_dependency. + + TRANSLATE ms_cached_descriptor-version TO LOWER CASE. + ms_cached_descriptor-sem_version = zcl_abapgit_version=>conv_str_to_version( ms_cached_descriptor-version ). + + LOOP AT ms_cached_descriptor-dependencies ASSIGNING . + TRANSLATE -version TO LOWER CASE. + -sem_version = zcl_abapgit_version=>conv_str_to_version( -version ). + ENDLOOP. + + ENDMETHOD. + METHOD from_xml. + + DATA: lv_xml TYPE string. + + lv_xml = iv_xml. + + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML lv_xml + RESULT data = rs_data. + + ENDMETHOD. + METHOD get_manifest_descriptor. + + DATA: lo_manifest_provider TYPE REF TO object, + lv_package TYPE devclass, + lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt, + ls_manifest_implementation TYPE zif_abapgit_apack_definitions=>ty_manifest_declaration, + lt_manifest_implementation TYPE zif_abapgit_apack_definitions=>ty_manifest_declarations. + + IF mv_is_cached IS INITIAL. + + lt_packages = zcl_abapgit_factory=>get_sap_package( mv_package_name )->list_subpackages( ). + INSERT mv_package_name INTO TABLE lt_packages. + + lt_manifest_implementation = zcl_abapgit_apack_helper=>get_manifest_implementations( ). + + LOOP AT lt_packages INTO lv_package. + READ TABLE lt_manifest_implementation INTO ls_manifest_implementation WITH KEY devclass = lv_package. + IF sy-subrc = 0. + EXIT. + ENDIF. + ENDLOOP. + IF ls_manifest_implementation IS NOT INITIAL. + TRY. + CREATE OBJECT lo_manifest_provider TYPE (ls_manifest_implementation-clsname). + CATCH cx_sy_create_object_error. + CLEAR: rs_manifest_descriptor. + ENDTRY. + IF lo_manifest_provider IS BOUND. + copy_manifest_descriptor( lo_manifest_provider ). + ENDIF. + ENDIF. + + mv_is_cached = abap_true. + + ENDIF. + + rs_manifest_descriptor = ms_cached_descriptor. + ENDMETHOD. + METHOD has_manifest. + + DATA: ls_returned_manifest TYPE zif_abapgit_apack_definitions=>ty_descriptor. + + ls_returned_manifest = get_manifest_descriptor( ). + + rv_has_manifest = boolc( ls_returned_manifest IS NOT INITIAL ). + + ENDMETHOD. + METHOD refresh. + CLEAR: mv_is_cached, ms_cached_descriptor. + ENDMETHOD. + METHOD set_manifest_descriptor. + mv_is_cached = abap_true. + ms_cached_descriptor = is_manifest_descriptor. + format_version( ). + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_apack_migration IMPLEMENTATION. + METHOD add_interface_source. + DATA: lo_factory TYPE REF TO object, + lo_source TYPE REF TO object, + lt_source_code TYPE zif_abapgit_definitions=>ty_string_tt. + + "Buffer needs to be refreshed, + "otherwise standard SAP CLIF_SOURCE reorder methods alphabetically + CALL FUNCTION 'SEO_BUFFER_INIT'. + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + cifkey = is_clskey + version = seoc_version_inactive. + + TRY. + CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') + RECEIVING + result = lo_factory. + + CALL METHOD lo_factory->('CREATE_CLIF_SOURCE') + EXPORTING + clif_name = is_clskey-clsname + RECEIVING + result = lo_source. + + TRY. + CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~LOCK'). + CATCH cx_oo_access_permission. + zcx_abapgit_exception=>raise( 'source_new, access permission exception' ). + ENDTRY. + + lt_source_code = get_interface_source( ). + + CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~SET_SOURCE') + EXPORTING + source = lt_source_code. + + CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~SAVE'). + CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~UNLOCK'). + + CATCH cx_sy_dyn_call_error. + add_interface_source_classic( is_clskey ). + ENDTRY. + + ENDMETHOD. + METHOD add_interface_source_classic. + DATA: lo_source TYPE REF TO object, + lt_source_code TYPE zif_abapgit_definitions=>ty_string_tt. + + CREATE OBJECT lo_source TYPE ('CL_OO_SOURCE') + EXPORTING + clskey = is_clskey + EXCEPTIONS + class_not_existing = 1 + OTHERS = 2. + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise( 'error from CL_OO_SOURCE' ). + ENDIF. + + TRY. + CALL METHOD lo_source->('ACCESS_PERMISSION') + EXPORTING + access_mode = seok_access_modify. + lt_source_code = get_interface_source( ). + CALL METHOD lo_source->('SET_SOURCE') + EXPORTING + i_source = lt_source_code. + CALL METHOD lo_source->('SAVE'). + CALL METHOD lo_source->('ACCESS_PERMISSION') + EXPORTING + access_mode = seok_access_free. + CATCH cx_oo_access_permission. + zcx_abapgit_exception=>raise( 'permission error' ). + CATCH cx_oo_source_save_failure. + zcx_abapgit_exception=>raise( 'save failure' ). + ENDTRY. + ENDMETHOD. + METHOD add_intf_source_and_activate. + + DATA: ls_clskey TYPE seoclskey, + ls_inactive_object TYPE dwinactiv, + lt_inactive_objects TYPE TABLE OF dwinactiv. + + ls_clskey-clsname = zif_abapgit_apack_definitions=>c_apack_interface_cust. + + add_interface_source( ls_clskey ). + + ls_inactive_object-object = 'INTF'. + ls_inactive_object-obj_name = zif_abapgit_apack_definitions=>c_apack_interface_cust. + INSERT ls_inactive_object INTO TABLE lt_inactive_objects. + + CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE' + TABLES + objects = lt_inactive_objects + EXCEPTIONS + excecution_error = 1 + cancelled = 2 + insert_into_corr_error = 3 + OTHERS = 4. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + ENDMETHOD. + METHOD create_interface. + + DATA: ls_interface_properties TYPE vseointerf. + + ls_interface_properties-clsname = zif_abapgit_apack_definitions=>c_apack_interface_cust. + ls_interface_properties-version = '1'. + ls_interface_properties-langu = 'E'. + ls_interface_properties-descript = 'APACK: Manifest interface'. + ls_interface_properties-exposure = '2'. + ls_interface_properties-state = '1'. + ls_interface_properties-unicode = abap_true. + + TRY. + CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' + EXPORTING + devclass = '$TMP' + suppress_dialog = abap_true " Parameter missing in 702 + CHANGING + interface = ls_interface_properties + EXCEPTIONS + existing = 1 + is_class = 2 + db_error = 3 + component_error = 4 + no_access = 5 + other = 6 + OTHERS = 7 ##FM_SUBRC_OK. + CATCH cx_sy_dyn_call_param_not_found. + CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' + EXPORTING + devclass = '$TMP' + CHANGING + interface = ls_interface_properties + EXCEPTIONS + existing = 1 + is_class = 2 + db_error = 3 + component_error = 4 + no_access = 5 + other = 6 + OTHERS = 7. + ENDTRY. + + IF sy-subrc <> 0. + zcx_abapgit_exception=>raise_t100( ). + ENDIF. + + add_intf_source_and_activate( ). + + ENDMETHOD. + METHOD get_interface_source. + + INSERT `INTERFACE zif_apack_manifest PUBLIC.` INTO TABLE rt_source. + INSERT `` INTO TABLE rt_source. + INSERT ` TYPES: BEGIN OF ty_dependency,` INTO TABLE rt_source. + INSERT ` group_id TYPE string,` INTO TABLE rt_source. + INSERT ` artifact_id TYPE string,` INTO TABLE rt_source. + INSERT ` version TYPE string,` INTO TABLE rt_source. + INSERT ` git_url TYPE string,` INTO TABLE rt_source. + INSERT ` target_package TYPE devclass,` INTO TABLE rt_source. + INSERT ` END OF ty_dependency,` INTO TABLE rt_source. + INSERT ` ty_dependencies TYPE STANDARD TABLE OF ty_dependency` INTO TABLE rt_source. + INSERT ` WITH NON-UNIQUE DEFAULT KEY,` INTO TABLE rt_source. + INSERT ` ty_repository_type TYPE string,` INTO TABLE rt_source. + INSERT ` BEGIN OF ty_descriptor,` INTO TABLE rt_source. + INSERT ` group_id TYPE string,` INTO TABLE rt_source. + INSERT ` artifact_id TYPE string,` INTO TABLE rt_source. + INSERT ` version TYPE string,` INTO TABLE rt_source. + INSERT ` repository_type TYPE ty_repository_type,` INTO TABLE rt_source. + INSERT ` git_url TYPE string,` INTO TABLE rt_source. + INSERT ` dependencies TYPE ty_dependencies,` INTO TABLE rt_source. + INSERT ` END OF ty_descriptor.` INTO TABLE rt_source. + INSERT `` INTO TABLE rt_source. + INSERT ` CONSTANTS: co_file_name TYPE string VALUE '.apack-manifest.xml',` INTO TABLE rt_source. + INSERT ` co_abap_git TYPE ty_repository_type VALUE 'abapGit',` INTO TABLE rt_source. + INSERT ` co_interface_version TYPE i VALUE 1.` INTO TABLE rt_source. + INSERT `` INTO TABLE rt_source. + INSERT ` DATA: descriptor TYPE ty_descriptor READ-ONLY.` INTO TABLE rt_source. + INSERT `` INTO TABLE rt_source. + INSERT `ENDINTERFACE.` INTO TABLE rt_source. + + ENDMETHOD. + METHOD interface_exists. + + DATA: lv_interface_name TYPE seoclsname. + + SELECT SINGLE clsname FROM seoclass INTO lv_interface_name + WHERE clsname = zif_abapgit_apack_definitions=>c_apack_interface_cust. + rv_interface_exists = boolc( sy-subrc = 0 ). + + ENDMETHOD. + METHOD interface_valid. + + FIELD-SYMBOLS: TYPE i. + + ASSIGN (zif_abapgit_apack_definitions=>c_apack_interface_cust)=>('CO_INTERFACE_VERSION') TO . + rv_interface_valid = boolc( IS ASSIGNED + AND >= c_apack_interface_version ). + + ENDMETHOD. + METHOD perform_migration. + + IF interface_exists( ) = abap_false. + create_interface( ). + ELSEIF interface_valid( ) = abap_false. + add_intf_source_and_activate( ). + ENDIF. + + ENDMETHOD. + METHOD run. + + DATA: lo_apack_migration TYPE REF TO zcl_abapgit_apack_migration. + + CREATE OBJECT lo_apack_migration. + lo_apack_migration->perform_migration( ). + + ENDMETHOD. +ENDCLASS. + +CLASS zcl_abapgit_apack_helper IMPLEMENTATION. + METHOD are_dependencies_met. + + DATA: lt_dependencies_status TYPE ty_dependency_statuses. + + IF it_dependencies IS INITIAL. + rv_status = zif_abapgit_definitions=>c_yes. + RETURN. + ENDIF. + + lt_dependencies_status = get_dependencies_met_status( it_dependencies ). + + LOOP AT lt_dependencies_status TRANSPORTING NO FIELDS WHERE met <> zif_abapgit_definitions=>c_yes. + EXIT. + ENDLOOP. + + IF sy-subrc = 0. + rv_status = zif_abapgit_definitions=>c_no. + ELSE. + rv_status = zif_abapgit_definitions=>c_yes. + ENDIF. + + ENDMETHOD. + METHOD dependencies_popup. + + DATA: lt_met_status TYPE ty_dependency_statuses, + lv_answer TYPE c LENGTH 1. + + lt_met_status = get_dependencies_met_status( it_dependencies ). + + show_dependencies_popup( lt_met_status ). + + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_titlebar = 'Warning' + iv_text_question = 'The project has unmet dependencies. Do you want to continue?' ). + + IF lv_answer <> '1'. + zcx_abapgit_exception=>raise( 'Cancelling because of unmet dependencies.' ). + ENDIF. + + ENDMETHOD. + METHOD get_color_table. + + DATA: + lo_functional_settings TYPE REF TO cl_salv_functional_settings, + lo_hyperlinks TYPE REF TO cl_salv_hyperlinks, + lt_color_negative TYPE lvc_t_scol, + lt_color_normal TYPE lvc_t_scol, + lt_color_positive TYPE lvc_t_scol, + ls_color TYPE lvc_s_scol, + lv_handle TYPE i, + ls_hyperlink TYPE salv_s_int4_column, + lv_hyperlink TYPE service_rl. + + FIELD-SYMBOLS: + TYPE ty_color_line, + LIKE LINE OF it_dependencies. + + CLEAR: ls_color. + ls_color-color-col = col_negative. + APPEND ls_color TO lt_color_negative. + + CLEAR: ls_color. + ls_color-color-col = col_normal. + APPEND ls_color TO lt_color_normal. + + CLEAR: ls_color. + ls_color-color-col = col_positive. + APPEND ls_color TO lt_color_positive. + + lo_functional_settings = io_alv->get_functional_settings( ). + lo_hyperlinks = lo_functional_settings->get_hyperlinks( ). + + CLEAR: lv_handle, ls_color. + LOOP AT it_dependencies ASSIGNING . + lv_handle = lv_handle + 1. + + APPEND INITIAL LINE TO ct_color_table ASSIGNING . + MOVE-CORRESPONDING TO . + + CASE -met. + WHEN zif_abapgit_definitions=>c_yes. + -color = lt_color_positive. + -exception = '3'. + WHEN zif_abapgit_definitions=>c_partial. + -color = lt_color_normal. + -exception = '2'. + WHEN zif_abapgit_definitions=>c_no. + -color = lt_color_negative. + -exception = '1'. + ENDCASE. + + CLEAR: ls_hyperlink. + ls_hyperlink-columnname = 'GIT_URL'. + ls_hyperlink-value = lv_handle. + APPEND ls_hyperlink TO -t_hyperlink. + + lv_hyperlink = -git_url. + lo_hyperlinks->add_hyperlink( handle = lv_handle + hyperlink = lv_hyperlink ). + + ENDLOOP. + + ENDMETHOD. + METHOD get_dependencies_met_status. + + DATA: lt_installed_packages TYPE zif_abapgit_apack_definitions=>ty_descriptors, + ls_installed_package TYPE zif_abapgit_apack_definitions=>ty_descriptor, + ls_dependecy TYPE zif_abapgit_apack_definitions=>ty_dependency, + ls_dependecy_popup TYPE ty_dependency_status. + + IF it_dependencies IS INITIAL. + RETURN. + ENDIF. + + lt_installed_packages = get_installed_packages( ). + + LOOP AT it_dependencies INTO ls_dependecy. + CLEAR: ls_dependecy_popup. + + MOVE-CORRESPONDING ls_dependecy TO ls_dependecy_popup. + + READ TABLE lt_installed_packages INTO ls_installed_package + WITH KEY group_id = ls_dependecy-group_id + artifact_id = ls_dependecy-artifact_id. + IF sy-subrc <> 0. + ls_dependecy_popup-met = zif_abapgit_definitions=>c_no. + ELSE. + TRY. + zcl_abapgit_version=>check_dependant_version( is_current = ls_installed_package-sem_version + is_dependant = ls_dependecy-sem_version ). + ls_dependecy_popup-met = zif_abapgit_definitions=>c_yes. + CATCH zcx_abapgit_exception. + ls_dependecy_popup-met = zif_abapgit_definitions=>c_partial. + ENDTRY. + ENDIF. + + INSERT ls_dependecy_popup INTO TABLE rt_status. + + ENDLOOP. + + ENDMETHOD. + METHOD get_installed_packages. + + DATA: lo_apack_reader TYPE REF TO zcl_abapgit_apack_reader, + lt_manifest_implementation TYPE zif_abapgit_apack_definitions=>ty_manifest_declarations, + ls_manifest_implementation TYPE zif_abapgit_apack_definitions=>ty_manifest_declaration, + lo_manifest_provider TYPE REF TO object, + ls_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor. + + lt_manifest_implementation = get_manifest_implementations( ). + + LOOP AT lt_manifest_implementation INTO ls_manifest_implementation. + CLEAR: lo_manifest_provider, lo_apack_reader. + + TRY. + CREATE OBJECT lo_manifest_provider TYPE (ls_manifest_implementation-clsname). + CATCH cx_sy_create_object_error. + CLEAR: lo_manifest_provider. + ENDTRY. + + IF lo_manifest_provider IS NOT BOUND. + CONTINUE. + ENDIF. + + lo_apack_reader = zcl_abapgit_apack_reader=>create_instance( ls_manifest_implementation-devclass ). + lo_apack_reader->copy_manifest_descriptor( lo_manifest_provider ). + ls_descriptor = lo_apack_reader->get_manifest_descriptor( ). + + IF ls_descriptor IS NOT INITIAL. + INSERT ls_descriptor INTO TABLE rt_packages. + ENDIF. + + ENDLOOP. + + ENDMETHOD. + METHOD get_manifest_implementations. + + DATA lt_refclsname TYPE RANGE OF abap_classname. + DATA ls_refclsname LIKE LINE OF lt_refclsname. + + ls_refclsname-sign = 'I'. + ls_refclsname-option = 'EQ'. + ls_refclsname-low = zif_abapgit_apack_definitions=>c_apack_interface_cust. + INSERT ls_refclsname INTO TABLE lt_refclsname. + + ls_refclsname-sign = 'I'. + ls_refclsname-option = 'EQ'. + ls_refclsname-low = zif_abapgit_apack_definitions=>c_apack_interface_sap. + INSERT ls_refclsname INTO TABLE lt_refclsname. + + ls_refclsname-sign = 'I'. + ls_refclsname-option = 'CP'. + ls_refclsname-low = zif_abapgit_apack_definitions=>c_apack_interface_nspc. + INSERT ls_refclsname INTO TABLE lt_refclsname. + + " Find all classes that implement customer or SAP version of APACK interface + SELECT seometarel~clsname tadir~devclass FROM seometarel "#EC CI_NOORDER + INNER JOIN tadir ON seometarel~clsname = tadir~obj_name "#EC CI_BUFFJOIN + INTO TABLE rt_manifest_implementations + WHERE tadir~pgmid = 'R3TR' + AND tadir~object = 'CLAS' + AND seometarel~version = '1' + AND seometarel~refclsname IN lt_refclsname + ORDER BY clsname devclass ##SUBRC_OK. + + ENDMETHOD. + METHOD show_dependencies_popup. + + DATA: lo_alv TYPE REF TO cl_salv_table, + lo_column TYPE REF TO cl_salv_column, + lo_column_table TYPE REF TO cl_salv_column_table, + lo_columns TYPE REF TO cl_salv_columns_table, + lt_columns TYPE salv_t_column_ref, + ls_column LIKE LINE OF lt_columns, + lt_color_table TYPE ty_color_tab, + ls_position TYPE zif_abapgit_popups=>ty_popup_position, + lx_ex TYPE REF TO cx_root. + + IF it_dependencies IS INITIAL. + RETURN. + ENDIF. + + TRY. + cl_salv_table=>factory( IMPORTING r_salv_table = lo_alv + CHANGING t_table = lt_color_table ). + + lo_columns = lo_alv->get_columns( ). + lt_columns = lo_columns->get( ). + LOOP AT lt_columns INTO ls_column WHERE columnname CP 'SEM_VERSION-*'. + ls_column-r_column->set_technical( ). + ENDLOOP. + + lo_column = lo_columns->get_column( 'MET' ). + lo_column->set_technical( ). + + lo_column = lo_columns->get_column( 'GROUP_ID' ). + lo_column->set_short_text( 'Org/ProjId' ). + + lo_columns->set_color_column( 'COLOR' ). + lo_columns->set_exception_column( 'EXCEPTION' ). + lo_columns->set_hyperlink_entry_column( 'T_HYPERLINK' ). + lo_columns->set_optimize( ). + + lo_column = lo_columns->get_column( 'GROUP_ID' ). + lo_column->set_short_text( 'Org/ProjId' ). + + lo_column = lo_columns->get_column( 'ARTIFACT_ID' ). + lo_column->set_short_text( 'Proj. Name' ). + + lo_column = lo_columns->get_column( 'GIT_URL' ). + lo_column->set_short_text( 'Git URL' ). + + lo_column_table ?= lo_column. + lo_column_table->set_cell_type( if_salv_c_cell_type=>link ). + + lo_column = lo_columns->get_column( 'VERSION' ). + lo_column->set_short_text( 'Version' ). + + lo_column = lo_columns->get_column( 'TARGET_PACKAGE' ). + lo_column->set_technical( ). + + get_color_table( + EXPORTING + io_alv = lo_alv + it_dependencies = it_dependencies + CHANGING + ct_color_table = lt_color_table ). + + ls_position = zcl_abapgit_popups=>center( + iv_width = 90 + iv_height = 10 ). + + lo_alv->set_screen_popup( start_column = ls_position-start_column + end_column = ls_position-end_column + start_line = ls_position-start_row + end_line = ls_position-end_row ). + + lo_alv->get_display_settings( )->set_list_header( 'APACK dependencies' ). + lo_alv->display( ). + + CATCH cx_salv_msg cx_salv_not_found cx_salv_data_error cx_salv_existing INTO lx_ex. + zcx_abapgit_exception=>raise( lx_ex->get_text( ) ). + ENDTRY. + + ENDMETHOD. + METHOD to_file. + + DATA: lo_manifest_reader TYPE REF TO zcl_abapgit_apack_reader, + ls_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor, + lo_manifest_writer TYPE REF TO zcl_abapgit_apack_writer. + + lo_manifest_reader = zcl_abapgit_apack_reader=>create_instance( iv_package ). + IF lo_manifest_reader->has_manifest( ) = abap_true. + ls_descriptor = lo_manifest_reader->get_manifest_descriptor( ). + lo_manifest_writer = zcl_abapgit_apack_writer=>create_instance( ls_descriptor ). + rs_file-path = zif_abapgit_definitions=>c_root_dir. + rs_file-filename = zif_abapgit_apack_definitions=>c_dot_apack_manifest. + rs_file-data = zcl_abapgit_convert=>string_to_xstring_utf8( lo_manifest_writer->serialize( ) ). + rs_file-sha1 = zcl_abapgit_hash=>sha1_blob( rs_file-data ). + ENDIF. + + ENDMETHOD. +ENDCLASS. + +SELECTION-SCREEN BEGIN OF SCREEN 1001. +* dummy for triggering screen on Java SAP GUI +SELECTION-SCREEN END OF SCREEN 1001. + +TABLES sscrfields. + +**************************************************** +* abapmerge - ZABAPGIT_PASSWORD_DIALOG +**************************************************** +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_PASSWORD_DIALOG +*&---------------------------------------------------------------------* + +SELECTION-SCREEN BEGIN OF SCREEN 1002 TITLE sc_title. +SELECTION-SCREEN SKIP. +SELECTION-SCREEN BEGIN OF LINE. +SELECTION-SCREEN COMMENT 1(18) sc_url FOR FIELD p_url. +PARAMETERS: p_url TYPE string LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG. +SELECTION-SCREEN END OF LINE. +SELECTION-SCREEN SKIP. +SELECTION-SCREEN BEGIN OF LINE. +SELECTION-SCREEN COMMENT 1(18) sc_user FOR FIELD p_user. +PARAMETERS: p_user TYPE string LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG. +SELECTION-SCREEN END OF LINE. +SELECTION-SCREEN BEGIN OF LINE. +SELECTION-SCREEN COMMENT 1(18) sc_pass FOR FIELD p_pass. +PARAMETERS: p_pass TYPE c LENGTH 255 LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG. +SELECTION-SCREEN END OF LINE. +SELECTION-SCREEN SKIP. +SELECTION-SCREEN BEGIN OF LINE. +SELECTION-SCREEN COMMENT 1(18) sc_cmnt FOR FIELD p_cmnt. +PARAMETERS: p_cmnt TYPE c LENGTH 255 LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG. +SELECTION-SCREEN END OF LINE. +SELECTION-SCREEN END OF SCREEN 1002. + +*----------------------------------------------------------------------- +* LCL_PASSWORD_DIALOG +*----------------------------------------------------------------------- +CLASS lcl_password_dialog DEFINITION FINAL. + +************** +* This class will remain local in the report +************** + + PUBLIC SECTION. + + CONSTANTS c_dynnr TYPE c LENGTH 4 VALUE '1002'. + + CLASS-METHODS popup + IMPORTING + iv_repo_url TYPE string + CHANGING + cv_user TYPE string + cv_pass TYPE string. + + CLASS-METHODS on_screen_init. + CLASS-METHODS on_screen_output. + CLASS-METHODS on_screen_event + IMPORTING + iv_ucomm TYPE sy-ucomm. + + PRIVATE SECTION. + + CLASS-DATA gv_confirm TYPE abap_bool. + CLASS-METHODS enrich_title_by_hostname + IMPORTING + iv_repo_url TYPE string. + +ENDCLASS. + +CLASS lcl_password_dialog IMPLEMENTATION. + + METHOD popup. + + DATA ls_position TYPE zif_abapgit_popups=>ty_popup_position. + + CLEAR p_pass. + p_url = iv_repo_url. + p_user = cv_user. + gv_confirm = abap_false. + + p_cmnt = 'Press F1 for Help'. + + enrich_title_by_hostname( iv_repo_url ). + + ls_position = zcl_abapgit_popups=>center( + iv_width = 65 + iv_height = 7 ). + + CALL SELECTION-SCREEN c_dynnr + STARTING AT ls_position-start_column ls_position-start_row + ENDING AT ls_position-end_column ls_position-end_row. + + IF gv_confirm = abap_true. + cv_user = p_user. + cv_pass = p_pass. + ELSE. + CLEAR: cv_user, cv_pass. + ENDIF. + + CLEAR: p_url, p_user, p_pass. + + ENDMETHOD. + + METHOD on_screen_init. + sc_title = 'Login'. + sc_url = 'Repo URL'. + sc_user = 'User'. + sc_pass = 'Password or Token'. + sc_cmnt = 'Note'. + ENDMETHOD. + + METHOD on_screen_output. + + DATA lt_ucomm TYPE TABLE OF sy-ucomm. + + ASSERT sy-dynnr = c_dynnr. + + LOOP AT SCREEN. + IF screen-name = 'P_URL' OR screen-name = 'P_CMNT'. + screen-input = '0'. + screen-intensified = '1'. + screen-display_3d = '0'. + MODIFY SCREEN. + ENDIF. + IF screen-name = 'P_CMNT' OR screen-name = 'SC_CMNT'. + screen-active = '1'. + screen-invisible = '0'. + MODIFY SCREEN. + ENDIF. + IF screen-name = 'P_PASS'. + screen-invisible = '1'. + MODIFY SCREEN. + ENDIF. + ENDLOOP. + + APPEND 'PICK' TO lt_ucomm. + + CALL FUNCTION 'RS_SET_SELSCREEN_STATUS' + EXPORTING + p_status = 'DETL' + p_program = 'RSPFPAR' + TABLES + p_exclude = lt_ucomm. + + IF p_user IS NOT INITIAL. + SET CURSOR FIELD 'P_PASS'. + ENDIF. + + ENDMETHOD. + + METHOD on_screen_event. + + ASSERT sy-dynnr = c_dynnr. + + CASE iv_ucomm. + WHEN 'OK'. " Enter + gv_confirm = abap_true. + LEAVE TO SCREEN 0. + WHEN 'HELP'. " F1 + TRY. + zcl_abapgit_services_abapgit=>open_abapgit_wikipage( 'guide-authentication.html' ). + CATCH zcx_abapgit_exception ##NO_HANDLER. + ENDTRY. + WHEN OTHERS. " Escape + gv_confirm = abap_false. + LEAVE TO SCREEN 0. + ENDCASE. + + ENDMETHOD. + METHOD enrich_title_by_hostname. + + DATA lv_host TYPE string. + + FIND REGEX 'https?://([^/^:]*)' IN iv_repo_url SUBMATCHES lv_host. + IF lv_host IS NOT INITIAL AND lv_host <> space. + CLEAR sc_title. + CONCATENATE 'Login:' lv_host INTO sc_title IN CHARACTER MODE SEPARATED BY space. + ENDIF. + + ENDMETHOD. + +ENDCLASS. +FORM password_popup + USING + pv_repo_url TYPE string + CHANGING + cv_user TYPE string + cv_pass TYPE string ##CALLED. + + lcl_password_dialog=>popup( + EXPORTING + iv_repo_url = pv_repo_url + CHANGING + cv_user = cv_user + cv_pass = cv_pass ). + +ENDFORM. +* create class ZCL_ABAPGIT_AUTH_EXIT implementing ZIF_ABAPGIT_AUTH in following include, +* if using the development version of abapGit create a global class instead +* place the object in a different package than ZABAPGIT +INCLUDE zabapgit_authorizations_exit IF FOUND. + +* create class ZCL_ABAPGIT_USER_EXIT implementing ZIF_ABAPGIT_EXIT in following include, +* if using the development version of abapGit create a global class instead +* place the object in a different package than ZABAPGIT +INCLUDE zabapgit_user_exit IF FOUND. + +* place all implementations of ZIF_ABAPGIT_BACKGROUND in following include, +* if using the development version of abapGit create a global classes instead +* place the object in a different package than ZABAPGIT +INCLUDE zabapgit_background_user_exit IF FOUND. + +INCLUDE zabapgit_gui_pages_userexit IF FOUND. + +**************************************************** +* abapmerge - ZABAPGIT_FORMS +**************************************************** +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_FORMS +*&---------------------------------------------------------------------* + +CLASS lcl_startup DEFINITION FINAL. + PUBLIC SECTION. + CLASS-METHODS prepare_gui_startup + RAISING + zcx_abapgit_exception. + PRIVATE SECTION. + CLASS-METHODS set_start_repo_from_package + IMPORTING + !iv_package TYPE devclass + RAISING + zcx_abapgit_exception. + + CLASS-METHODS get_package_from_adt + RETURNING + VALUE(rv_package) TYPE devclass. + + CLASS-METHODS check_sapgui + RAISING + zcx_abapgit_exception. +ENDCLASS. + +CLASS lcl_startup IMPLEMENTATION. + + METHOD check_sapgui. + + CONSTANTS: + lc_hide_sapgui_hint TYPE string VALUE '2'. + + DATA: + lv_answer TYPE char1, + ls_settings TYPE zif_abapgit_persist_user=>ty_s_user_settings, + li_user_persistence TYPE REF TO zif_abapgit_persist_user. + + li_user_persistence = zcl_abapgit_persist_factory=>get_user( ). + + ls_settings = li_user_persistence->get_settings( ). + + IF ls_settings-hide_sapgui_hint = abap_true. + RETURN. + ENDIF. + + IF zcl_abapgit_ui_factory=>get_frontend_services( )->is_sapgui_for_java( ) = abap_false. + RETURN. + ENDIF. + + lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( + iv_titlebar = 'Not supported SAPGUI' + iv_text_question = 'SAPGUI for Java is not supported! There might be some issues.' + iv_text_button_1 = 'Got it' + iv_icon_button_1 = |{ icon_okay }| + iv_text_button_2 = 'Hide' + iv_icon_button_2 = |{ icon_set_state }| + iv_display_cancel_button = abap_false ). + + IF lv_answer = lc_hide_sapgui_hint. + ls_settings-hide_sapgui_hint = abap_true. + li_user_persistence->set_settings( ls_settings ). + ENDIF. + + ENDMETHOD. + + METHOD prepare_gui_startup. + DATA: lv_repo_key TYPE zif_abapgit_persistence=>ty_value, + lv_package TYPE devclass, + lv_package_adt TYPE devclass. + + check_sapgui( ). + + IF zcl_abapgit_persist_factory=>get_settings( )->read( )->get_show_default_repo( ) = abap_false. + " Don't show the last seen repo at startup + zcl_abapgit_persist_factory=>get_user( )->set_repo_show( || ). + ENDIF. + + " We have three special cases for gui startup + " - open a specific repo by repo key + " - open a specific repo by package name + " - open a specific repo by package name provided by ADT + " These overrule the last shown repo + + GET PARAMETER ID zif_abapgit_definitions=>c_spagpa_param_repo_key FIELD lv_repo_key ##EXISTS. + GET PARAMETER ID zif_abapgit_definitions=>c_spagpa_param_package FIELD lv_package ##EXISTS. + lv_package_adt = get_package_from_adt( ). + + IF lv_repo_key IS NOT INITIAL. + + SET PARAMETER ID zif_abapgit_definitions=>c_spagpa_param_repo_key FIELD '' ##EXISTS. + zcl_abapgit_persist_factory=>get_user( )->set_repo_show( lv_repo_key ). + + ELSEIF lv_package IS NOT INITIAL. + + SET PARAMETER ID zif_abapgit_definitions=>c_spagpa_param_package FIELD '' ##EXISTS. + set_start_repo_from_package( lv_package ). + + ELSEIF lv_package_adt IS NOT INITIAL. + + set_start_repo_from_package( lv_package_adt ). + + ENDIF. + ENDMETHOD. + + METHOD set_start_repo_from_package. + DATA: li_repo TYPE REF TO zif_abapgit_repo, + lt_r_package TYPE RANGE OF devclass, + ls_r_package LIKE LINE OF lt_r_package, + lt_superpackages TYPE zif_abapgit_sap_package=>ty_devclass_tt, + li_package TYPE REF TO zif_abapgit_sap_package, + lt_repo_list TYPE zif_abapgit_repo_srv=>ty_repo_list. + + FIELD-SYMBOLS: TYPE LINE OF zif_abapgit_repo_srv=>ty_repo_list, + LIKE LINE OF lt_superpackages. + + li_package = zcl_abapgit_factory=>get_sap_package( iv_package ). + + IF li_package->exists( ) = abap_false. + RETURN. + ENDIF. + + ls_r_package-sign = 'I'. + ls_r_package-option = 'EQ'. + ls_r_package-low = iv_package. + INSERT ls_r_package INTO TABLE lt_r_package. + + " Also consider superpackages. E.g. when some open $abapgit_ui, abapGit repo + " should be found via package $abapgit + lt_superpackages = li_package->list_superpackages( ). + LOOP AT lt_superpackages ASSIGNING . + ls_r_package-low = . + INSERT ls_r_package INTO TABLE lt_r_package. + ENDLOOP. + + lt_repo_list = zcl_abapgit_repo_srv=>get_instance( )->list( ). + + LOOP AT lt_repo_list ASSIGNING . + + IF ->get_package( ) IN lt_r_package. + li_repo = . + EXIT. + ENDIF. + + ENDLOOP. + + IF li_repo IS BOUND. + zcl_abapgit_persist_factory=>get_user( )->set_repo_show( li_repo->get_key( ) ). + ENDIF. + ENDMETHOD. + + METHOD get_package_from_adt. + + DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, + lr_context TYPE REF TO data, + lt_fields TYPE tihttpnvp. + + FIELD-SYMBOLS: TYPE any, + TYPE string, + LIKE LINE OF lt_fields. + ls_item-obj_type = 'CLAS'. + ls_item-obj_name = 'CL_ADT_GUI_INTEGRATION_CONTEXT'. + + IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. + " ADT is not supported in this NW release + RETURN. + ENDIF. + + TRY. + CREATE DATA lr_context TYPE ('CL_ADT_GUI_INTEGRATION_CONTEXT=>TY_CONTEXT_INFO'). + + ASSIGN lr_context->* TO . + ASSERT sy-subrc = 0. + + CALL METHOD (ls_item-obj_name)=>read_context + RECEIVING + result = . + + ASSIGN COMPONENT 'PARAMETERS' + OF STRUCTURE + TO . + ASSERT sy-subrc = 0. + + lt_fields = cl_http_utility=>string_to_fields( cl_http_utility=>unescape_url( ) ). + + READ TABLE lt_fields ASSIGNING + WITH KEY name = 'p_package_name'. + IF sy-subrc = 0. + rv_package = -value. + + " We want to open the repo just once. Therefore we delete the parameters + " and initialize the ADT context. + CLEAR . + CALL METHOD (ls_item-obj_name)=>initialize_instance + EXPORTING + context_info = . + + ENDIF. + + CATCH cx_root ##NO_HANDLER. + " Some problems with dynamic ADT access. + " Let's ignore it for now and fail silently + ENDTRY. + + ENDMETHOD. +ENDCLASS. + +******************************************************* + +FORM run. + + DATA lx_exception TYPE REF TO zcx_abapgit_exception. + DATA lx_not_found TYPE REF TO zcx_abapgit_not_found. + + TRY. + IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-startup ) = abap_false. + zcx_abapgit_exception=>raise( 'No authorization to start abapGit' ). + ENDIF. + + zcl_abapgit_migrations=>run( ). + PERFORM open_gui. + CATCH zcx_abapgit_exception INTO lx_exception. + MESSAGE lx_exception TYPE 'E'. + CATCH zcx_abapgit_not_found INTO lx_not_found. + MESSAGE lx_not_found TYPE 'E'. + ENDTRY. + +ENDFORM. "run + +FORM open_gui RAISING zcx_abapgit_exception. + + DATA lv_action TYPE string. + DATA lv_mode TYPE tabname. + + IF sy-batch = abap_true. + zcl_abapgit_background=>run( ). + ELSE. + +* https://docs.abapgit.org/user-guide/reference/database-util.html#emergency-mode + GET PARAMETER ID 'DBT' FIELD lv_mode. + CASE lv_mode. + WHEN 'ZABAPGIT'. + lv_action = zif_abapgit_definitions=>c_action-go_db. + WHEN OTHERS. + lv_action = zif_abapgit_definitions=>c_action-go_home. + ENDCASE. + + zcl_abapgit_html=>set_debug_mode( boolc( lv_mode = 'HREF' ) ). + + lcl_startup=>prepare_gui_startup( ). + zcl_abapgit_ui_factory=>get_gui( )->go_home( lv_action ). + CALL SELECTION-SCREEN 1001. " trigger screen + + ENDIF. + +ENDFORM. + +FORM output. + + DATA: lx_error TYPE REF TO zcx_abapgit_exception, + lt_ucomm TYPE TABLE OF sy-ucomm. + + PERFORM set_pf_status IN PROGRAM rsdbrunt IF FOUND. + + APPEND 'CRET' TO lt_ucomm. "Button Execute + APPEND 'SPOS' TO lt_ucomm. "Button Save + + CALL FUNCTION 'RS_SET_SELSCREEN_STATUS' + EXPORTING + p_status = sy-pfkey + TABLES + p_exclude = lt_ucomm. + + " For variant maintenance we have to omit this because + " it instantiates controls and hides maintenance screens. + IF zcl_abapgit_factory=>get_environment( )->is_variant_maintenance( ) = abap_false. + TRY. + zcl_abapgit_ui_factory=>get_gui( )->set_focus( ). + CATCH zcx_abapgit_exception INTO lx_error. + MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. + ENDTRY. + ENDIF. + +ENDFORM. + +FORM exit. + + DATA lx_error TYPE REF TO zcx_abapgit_exception. + + " The exit logic should only be applied for our 'main' selection screen 1001. + " All other selection-screens are called as popups and shouldn't influence + " the gui navigation as it would lead to unpredictable behaviour like dumps. + IF sy-dynnr <> 1001. + RETURN. + ENDIF. + + TRY. + CASE sy-ucomm. + WHEN 'CBAC' OR 'CCAN'. "Back & Escape + IF zcl_abapgit_ui_factory=>get_gui( )->back( iv_graceful = abap_true ) = abap_true. " end of stack + zcl_abapgit_ui_factory=>get_gui( )->free( ). " Graceful shutdown + ELSE. + LEAVE TO SCREEN 1001. + ENDIF. + ENDCASE. + CATCH zcx_abapgit_exception INTO lx_error. + MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. + ENDTRY. + +ENDFORM. + +FORM adjust_toolbar USING pv_dynnr TYPE sy-dynnr. + + DATA: ls_header TYPE rpy_dyhead, + lt_containers TYPE dycatt_tab, + lt_fields_to_containers TYPE dyfatc_tab, + lt_flow_logic TYPE swydyflow, + lv_no_toolbar LIKE ls_header-no_toolbar. + + CALL FUNCTION 'RPY_DYNPRO_READ' + EXPORTING + progname = sy-cprog + dynnr = pv_dynnr + IMPORTING + header = ls_header + TABLES + containers = lt_containers + fields_to_containers = lt_fields_to_containers + flow_logic = lt_flow_logic + EXCEPTIONS + cancelled = 1 + not_found = 2 + permission_error = 3 + OTHERS = 4. + IF sy-subrc IS NOT INITIAL. + RETURN. " Ignore errors, just exit + ENDIF. + + " Remove toolbar on html screen but re-insert toolbar for variant maintenance. + " Because otherwise important buttons are missing and variant maintenance is not possible. + lv_no_toolbar = boolc( zcl_abapgit_factory=>get_environment( + )->is_variant_maintenance( ) = abap_false ). + + IF ls_header-no_toolbar = lv_no_toolbar. + RETURN. " No change required + ENDIF. + + ls_header-no_toolbar = lv_no_toolbar. + + CALL FUNCTION 'RPY_DYNPRO_INSERT' + EXPORTING + header = ls_header + suppress_exist_checks = abap_true + TABLES + containers = lt_containers + fields_to_containers = lt_fields_to_containers + flow_logic = lt_flow_logic + EXCEPTIONS + cancelled = 1 + already_exists = 2 + program_not_exists = 3 + not_executed = 4 + missing_required_field = 5 + illegal_field_value = 6 + field_not_allowed = 7 + not_generated = 8 + illegal_field_position = 9 + OTHERS = 10. + IF sy-subrc <> 2 AND sy-subrc <> 0. + RETURN. " Ignore errors, just exit + ENDIF. + +ENDFORM. +********************************************************************** +INITIALIZATION. + PERFORM adjust_toolbar USING '1001'. + lcl_password_dialog=>on_screen_init( ). + +START-OF-SELECTION. + PERFORM run. + +* Hide Execute button from screen +AT SELECTION-SCREEN OUTPUT. + IF sy-dynnr = lcl_password_dialog=>c_dynnr. + lcl_password_dialog=>on_screen_output( ). + ELSE. + PERFORM output. + ENDIF. + +* SAP back command re-direction +AT SELECTION-SCREEN ON EXIT-COMMAND. + PERFORM exit. + +AT SELECTION-SCREEN. + IF sy-dynnr = lcl_password_dialog=>c_dynnr. + lcl_password_dialog=>on_screen_event( sscrfields-ucomm ). + ENDIF. + +**************************************************** +INTERFACE lif_abapmerge_marker. +* abapmerge 0.16.6 - 2025-11-06T00:17:45.725Z + CONSTANTS c_merge_timestamp TYPE string VALUE `2025-11-06T00:17:45.725Z`. + CONSTANTS c_abapmerge_version TYPE string VALUE `0.16.6`. +ENDINTERFACE. +**************************************************** diff --git a/agentic-sap-workflows/abapgitexported/src/zabapgit_standalone.prog.xml b/agentic-sap-workflows/abapgitexported/src/zabapgit_standalone.prog.xml new file mode 100644 index 0000000..d1d2c9a --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zabapgit_standalone.prog.xml @@ -0,0 +1,329 @@ + + + + + + ZABAPGIT_STANDALONE + 1 + E + X + X + + + + 000001 + + + + DECIDE_DIALOG + P + 000001 + 0001 + Object list decide dialog toolbar + + + + + &ILD + 001 + S + ICON_FILTER_UNDO + @GD@ + Reset filter + + + &ILT + 001 + S + ICON_FILTER + @4G@ + Set Filter + F + + + &ODN + 001 + S + ICON_SORT_DOWN + @3F@ + Sort in Descending Order + O + + + &OUP + 001 + S + ICON_SORT_UP + @3E@ + Sort in Ascending Order + I + + + CANCEL + 001 + E + S + ICON_CANCEL + @0W@ + Cancel + Cancel + A + + + OK + 001 + S + ICON_OKAY + @0V@ + Continue + Continue + + + SEL_ALL + 001 + S + ICON_SELECT_ALL + @4B@ + Select All Visible + + + SEL_CAT + 001 + S + ICON_WD_TOOLBAR + @TF@ + Select category + + + SEL_DEL + 001 + S + ICON_DESELECT_ALL + @4D@ + Deselect All Visible + + + SEL_KEY + 001 + S + ICON_SELECT_BLOCK + @4C@ + Mark/Toggle Selected + + + + + 000001 + 0001 + 01 + 00 + + + 000001 + 0001 + 02 + S + + + 000001 + 0001 + 03 + 13 + + + 000001 + 0001 + 04 + 17 + + + 000001 + 0001 + 05 + 14 + + + 000001 + 0001 + 06 + 16 + + + 000001 + 0001 + 07 + S + + + 000001 + 0001 + 08 + 05 + + + 000001 + 0001 + 09 + 06 + + + 000001 + 0001 + 10 + 07 + + + 000001 + 0001 + 11 + 08 + + + 000001 + 0001 + 12 + S + + + 000001 + 0001 + 13 + 12 + + + + + 000001 + 00 + OK + 001 + + + 000001 + 05 + SEL_ALL + 001 + + + 000001 + 06 + SEL_DEL + 001 + + + 000001 + 07 + SEL_KEY + 001 + + + 000001 + 08 + SEL_CAT + 001 + + + 000001 + 11 + OK + 001 + + + 000001 + 12 + CANCEL + 001 + + + 000001 + 13 + &ILT + 001 + + + 000001 + 14 + &OUP + 001 + + + 000001 + 16 + &ODN + 001 + + + 000001 + 17 + &ILD + 001 + + + + + DECIDE_DIALOG + &ILD + + + DECIDE_DIALOG + &ILT + + + DECIDE_DIALOG + &ODN + + + DECIDE_DIALOG + &OUP + + + DECIDE_DIALOG + CANCEL + + + DECIDE_DIALOG + OK + + + DECIDE_DIALOG + SEL_ALL + + + DECIDE_DIALOG + SEL_CAT + + + DECIDE_DIALOG + SEL_DEL + + + DECIDE_DIALOG + SEL_KEY + + + + + P + 000001 + P + Object list decide dialog FK settings + + + B + 000001 + 0001 + P + Object list decide dialog PB settings + + + + + + R + ZABAPGIT_STANDALONE + 19 + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zchar1000.doma.xml b/agentic-sap-workflows/abapgitexported/src/zchar1000.doma.xml new file mode 100644 index 0000000..f759be4 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zchar1000.doma.xml @@ -0,0 +1,15 @@ + + + + + + ZCHAR1000 + E + CHAR + 001000 + 001000 + Domain for large fixed size string + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zchar1000.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zchar1000.dtel.xml new file mode 100644 index 0000000..c8e5178 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zchar1000.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZCHAR1000 + E + ZCHAR1000 + large fixed-size string + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_coupon_code.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_coupon_code.dtel.xml new file mode 100644 index 0000000..2af81dd --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_coupon_code.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_COUPON_CODE + E + ZDOM_COUPON_CODE + Coupon Code + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_customer_id.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_customer_id.dtel.xml new file mode 100644 index 0000000..b3f0f3e --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_customer_id.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_CUSTOMER_ID + E + ZDOM_CUSTOMER_ID + Customer ID + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_items_in_cart.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_items_in_cart.dtel.xml new file mode 100644 index 0000000..1206222 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_items_in_cart.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_ITEMS_IN_CART + E + ZDOM_ITEMS_IN_CART + Items in Cart + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_order_date.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_order_date.dtel.xml new file mode 100644 index 0000000..419128b --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_order_date.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_ORDER_DATE + E + ZDOM_ORDER_DATE + Order Date + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_order_id.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_order_id.dtel.xml new file mode 100644 index 0000000..475963b --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_order_id.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_ORDER_ID + E + ZDOM_ORDER_ID + Order ID + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_order_status.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_order_status.dtel.xml new file mode 100644 index 0000000..38d34d2 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_order_status.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_ORDER_STATUS + E + ZDOM_ORDER_STATUS + Order Status + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_payment_method.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_payment_method.dtel.xml new file mode 100644 index 0000000..84b8454 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_payment_method.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_PAYMENT_METHOD + E + ZDOM_PAYMENT_METHOD + Payment Method + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_product.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_product.dtel.xml new file mode 100644 index 0000000..0070609 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_product.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_PRODUCT + E + ZDOM_PRODUCT + Product Code + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_quantity.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_quantity.dtel.xml new file mode 100644 index 0000000..0212983 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_quantity.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_QUANTITY + E + ZDOM_QUANTITY + Quantity + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_referral_source.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_referral_source.dtel.xml new file mode 100644 index 0000000..392848a --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_referral_source.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_REFERRAL_SOURCE + E + ZDOM_REFERRAL_SOURCE + Referral Source + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_ship_address.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_ship_address.dtel.xml new file mode 100644 index 0000000..66cf823 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_ship_address.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_SHIP_ADDRESS + E + ZDOM_SHIP_ADDRESS + Shipping Address + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_total_price.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_total_price.dtel.xml new file mode 100644 index 0000000..40de767 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_total_price.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_TOTAL_PRICE + E + ZDOM_TOTAL_PRICE + Total Price + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_tracking_number.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_tracking_number.dtel.xml new file mode 100644 index 0000000..dcf5c54 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_tracking_number.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_TRACKING_NUMBER + E + ZDOM_TRACKING_NUMBER + Tracking Number + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zde_unit_price.dtel.xml b/agentic-sap-workflows/abapgitexported/src/zde_unit_price.dtel.xml new file mode 100644 index 0000000..317f5e6 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zde_unit_price.dtel.xml @@ -0,0 +1,15 @@ + + + + + + ZDE_UNIT_PRICE + E + ZDOM_UNIT_PRICE + Unit Price + E + D + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zinvoic_header_ext.tabl.xml b/agentic-sap-workflows/abapgitexported/src/zinvoic_header_ext.tabl.xml new file mode 100644 index 0000000..6643517 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zinvoic_header_ext.tabl.xml @@ -0,0 +1,49 @@ + + + + + + ZINVOIC_HEADER_EXT + E + INTTAB + Invoice header extension + E + 1 + + + + SWIFT + 0 + C + 000022 + CHAR + 000011 + CHAR + + + + + + ZINVOIC_HEADER_EXT + Invoice header extension + + + ZINVOIC_HEADER_EXT + ZINVOIC_HEADER_EXT000 + 0001 + 0011 + + + + ZINVOIC_HEADER_EXT + 0001 + SWIFT + CHAR11 + 0011 + + + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zonlineorder.tabl.xml b/agentic-sap-workflows/abapgitexported/src/zonlineorder.tabl.xml new file mode 100644 index 0000000..a292348 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zonlineorder.tabl.xml @@ -0,0 +1,257 @@ + + + + + + ZONLINEORDER + E + INTTAB + E + 1 + + + + ORDER_ID + 0 + C + 000070 + CHAR + 000035 + CHAR + + + ORDER_DATE + 0 + C + 000016 + CHAR + 000008 + CHAR + + + CUSTOMER_ID + 0 + C + 000040 + CHAR + 000020 + CHAR + + + PRODUCT + 0 + C + 000080 + CHAR + 000040 + CHAR + + + QUANTITY + 0 + C + 000030 + CHAR + 000015 + CHAR + + + UNIT_PRICE + 0 + C + 000034 + CHAR + 000017 + CHAR + + + SHIP_ADDRESS + 0 + C + 000510 + CHAR + 000255 + CHAR + + + PAYMENT_METHOD + 0 + C + 000040 + CHAR + 000020 + CHAR + + + ORDER_STATUS + 0 + C + 000040 + CHAR + 000020 + CHAR + + + TRACKING_NUMBER + 0 + C + 000100 + CHAR + 000050 + CHAR + + + ITEMS_IN_CART + 0 + C + 000022 + CHAR + 000011 + CHAR + + + COUPON_CODE + 0 + C + 000060 + CHAR + 000030 + CHAR + + + REFERRAL_SOURCE + 0 + C + 000100 + CHAR + 000050 + CHAR + + + TOTAL_PRICE + 0 + C + 000034 + CHAR + 000017 + CHAR + + + + + + ZONLINEORDER + + + ZONLINEORDER + ZONLINEORDER000 + 750 + X + 0014 + 0588 + + + + ZONLINEORDER + 0001 + ORDER_ID + ZDE_ORDER_ID + 0035 + + + ZONLINEORDER + 0002 + ORDER_DATE + ZDE_ORDER_DATE + 0008 + + + ZONLINEORDER + 0003 + CUSTOMER_ID + ZDE_CUSTOMER_ID + 0020 + + + ZONLINEORDER + 0004 + PRODUCT + ZDE_PRODUCT + 0040 + + + ZONLINEORDER + 0005 + QUANTITY + ZDE_QUANTITY + 0015 + + + ZONLINEORDER + 0006 + UNIT_PRICE + ZDE_UNIT_PRICE + 0017 + + + ZONLINEORDER + 0007 + SHIP_ADDRESS + ZDE_SHIP_ADDRESS + 0255 + + + ZONLINEORDER + 0008 + PAYMENT_METHOD + ZDE_PAYMENT_METHOD + 0020 + + + ZONLINEORDER + 0009 + ORDER_STATUS + ZDE_ORDER_STATUS + 0020 + + + ZONLINEORDER + 0010 + TRACKING_NUMBER + ZDE_TRACKING_NUMBER + 0050 + + + ZONLINEORDER + 0011 + ITEMS_IN_CART + ZDE_ITEMS_IN_CART + 0011 + + + ZONLINEORDER + 0012 + COUPON_CODE + ZDE_COUPON_CODE + 0030 + + + ZONLINEORDER + 0013 + REFERRAL_SOURCE + ZDE_REFERRAL_SOURCE + 0050 + + + ZONLINEORDER + 0014 + TOTAL_PRICE + ZDE_TOTAL_PRICE + 0017 + + + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zonlineorderidoc.idoc.xml b/agentic-sap-workflows/abapgitexported/src/zonlineorderidoc.idoc.xml new file mode 100644 index 0000000..4964157 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zonlineorderidoc.idoc.xml @@ -0,0 +1,24 @@ + + + + + + + Custom IDoc for online orders + ZONLINEORDERIDOC + ZONLINEORDERIDOC + + + + 0001 + ZONLINEORDER + X + 0000000001 + 0000000001 + 01 + + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zpeppol_header.tabl.xml b/agentic-sap-workflows/abapgitexported/src/zpeppol_header.tabl.xml new file mode 100644 index 0000000..2512f0d --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zpeppol_header.tabl.xml @@ -0,0 +1,49 @@ + + + + + + ZPEPPOL_HEADER + E + INTTAB + Peppol header info + E + 1 + + + + BUYER_REFERENCE + 0 + C + 000160 + CHAR + 000080 + CHAR + + + + + + ZPEPPOL_HEADER + Peppol header info + + + ZPEPPOL_HEADER + ZPEPPOL_HEADER000 + 0001 + 0080 + + + + ZPEPPOL_HEADER + 0001 + BUYER_REFERENCE + CHAR80 + 0080 + + + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zru_item.tabl.xml b/agentic-sap-workflows/abapgitexported/src/zru_item.tabl.xml new file mode 100644 index 0000000..f5a6031 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zru_item.tabl.xml @@ -0,0 +1,49 @@ + + + + + + ZRU_ITEM + E + INTTAB + Russia invoice item details + E + 1 + + + + ITEM_NO + 0 + C + 000012 + CHAR + 000006 + CHAR + + + + + + ZRU_ITEM + Russia invoice item details + + + ZRU_ITEM + ZRU_ITEM000 + 0001 + 0006 + + + + ZRU_ITEM + 0001 + ITEM_NO + CHAR6 + 0006 + + + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zsorder_csv.tabl.xml b/agentic-sap-workflows/abapgitexported/src/zsorder_csv.tabl.xml new file mode 100644 index 0000000..d377185 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zsorder_csv.tabl.xml @@ -0,0 +1,100 @@ + + + + + + ZSORDER_CSV + E + INTTAB + ZSORDER_CSV + + + + ORDER_ID + ZDE_ORDER_ID + 0 + E + + + ORDER_DATE + ZDE_ORDER_DATE + 0 + T + E + + + CUSTOMER_ID + ZDE_CUSTOMER_ID + 0 + E + + + PRODUCT + ZDE_PRODUCT + 0 + E + + + QUANTITY + ZDE_QUANTITY + 0 + E + + + UNIT_PRICE + ZDE_UNIT_PRICE + 0 + E + + + SHIP_ADDRESS + ZDE_SHIP_ADDRESS + 0 + E + + + PAYMENT_METHOD + ZDE_PAYMENT_METHOD + 0 + E + + + ORDER_STATUS + ZDE_ORDER_STATUS + 0 + E + + + TRACKING_NUMBER + ZDE_TRACKING_NUMBER + 0 + E + + + ITEMS_IN_CART + ZDE_ITEMS_IN_CART + 0 + E + + + COUPON_CODE + ZDE_COUPON_CODE + 0 + E + + + REFERRAL_SOURCE + ZDE_REFERRAL_SOURCE + 0 + E + + + TOTAL_PRICE + ZDE_TOTAL_PRICE + 0 + E + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zstruct_idocnum.tabl.xml b/agentic-sap-workflows/abapgitexported/src/zstruct_idocnum.tabl.xml new file mode 100644 index 0000000..ab496d2 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zstruct_idocnum.tabl.xml @@ -0,0 +1,21 @@ + + + + + + ZSTRUCT_IDOCNUM + E + INTTAB + flat line structure for DOCNUM + + + + DOCNUM + EDI_DOCNUM + 0 + E + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zty_csv_line.tabl.xml b/agentic-sap-workflows/abapgitexported/src/zty_csv_line.tabl.xml new file mode 100644 index 0000000..415d916 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zty_csv_line.tabl.xml @@ -0,0 +1,21 @@ + + + + + + ZTY_CSV_LINE + E + INTTAB + Structure for CSV lines + + + + LINE + CHAR2048 + 0 + E + + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zty_docnum_tt.ttyp.xml b/agentic-sap-workflows/abapgitexported/src/zty_docnum_tt.ttyp.xml new file mode 100644 index 0000000..2b32a68 --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zty_docnum_tt.ttyp.xml @@ -0,0 +1,18 @@ + + + + + + ZTY_DOCNUM_TT + E + ZSTRUCT_IDOCNUM + S + STRU + T + D + N + standard table of EDI_DOCNUM + + + + diff --git a/agentic-sap-workflows/abapgitexported/src/zus_partner.tabl.xml b/agentic-sap-workflows/abapgitexported/src/zus_partner.tabl.xml new file mode 100644 index 0000000..7ab9d2a --- /dev/null +++ b/agentic-sap-workflows/abapgitexported/src/zus_partner.tabl.xml @@ -0,0 +1,51 @@ + + + + + + ZUS_PARTNER + E + INTTAB + US partner + E + 1 + + + + COUNTRY_ISO + 0 + C + 000020 + CHAR + 000010 + CHAR + + + + + + ZUS_PARTNER + US partner + + + ZUS_PARTNER + ZUS_PARTNER000 + 750 + X + 0001 + 0010 + + + + ZUS_PARTNER + 0001 + COUNTRY_ISO + CHAR10 + 0010 + + + + + + +