From 5ee49e33e8d907d4f7a3bc9969e0da606ac55872 Mon Sep 17 00:00:00 2001 From: Marc Bernard <59966492+mbtools@users.noreply.github.com> Date: Mon, 4 Nov 2024 04:11:38 -0500 Subject: [PATCH 1/3] PROG: Store flow logic as separate ABAP files (#7066) Co-authored-by: Lars Hvam Co-authored-by: Marc Bernard --- .../zcl_abapgit_objects_program.clas.abap | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/objects/zcl_abapgit_objects_program.clas.abap b/src/objects/zcl_abapgit_objects_program.clas.abap index 093c1fa19..fc75e7f71 100644 --- a/src/objects/zcl_abapgit_objects_program.clas.abap +++ b/src/objects/zcl_abapgit_objects_program.clas.abap @@ -131,6 +131,8 @@ CLASS zcl_abapgit_objects_program DEFINITION 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 @@ -359,6 +361,9 @@ CLASS zcl_abapgit_objects_program IMPLEMENTATION. 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 @@ -390,7 +395,7 @@ CLASS zcl_abapgit_objects_program IMPLEMENTATION. ENDLOOP. - IF ls_dynpro-header-type = 'N' AND ls_dynpro-nat_header IS NOT INITIAL. + 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. @@ -913,11 +918,15 @@ CLASS zcl_abapgit_objects_program IMPLEMENTATION. ENDLOOP. APPEND INITIAL LINE TO rt_dynpro ASSIGNING . - -header = ls_header. - -flow_logic = lt_flow_logic. + -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 = 'N' AND sy-subrc = 0. + 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. From 996d26ac3ab900df756a375c7f091da4e80fbf4e Mon Sep 17 00:00:00 2001 From: Marc Bernard <59966492+mbtools@users.noreply.github.com> Date: Mon, 4 Nov 2024 04:19:56 -0500 Subject: [PATCH 2/3] WDYN: Store controller code as separate ABAP files (#7069) Co-authored-by: Lars Hvam --- src/objects/zcl_abapgit_object_wdyn.clas.abap | 112 +++++++++++++++++- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/src/objects/zcl_abapgit_object_wdyn.clas.abap b/src/objects/zcl_abapgit_object_wdyn.clas.abap index 129543cad..a0ffd2f4c 100644 --- a/src/objects/zcl_abapgit_object_wdyn.clas.abap +++ b/src/objects/zcl_abapgit_object_wdyn.clas.abap @@ -59,6 +59,12 @@ CLASS zcl_abapgit_object_wdyn DEFINITION 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 @@ -79,7 +85,7 @@ ENDCLASS. -CLASS ZCL_ABAPGIT_OBJECT_WDYN IMPLEMENTATION. +CLASS zcl_abapgit_object_wdyn IMPLEMENTATION. METHOD add_fm_exception. @@ -382,6 +388,61 @@ CLASS ZCL_ABAPGIT_OBJECT_WDYN IMPLEMENTATION. 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. @@ -786,6 +847,47 @@ CLASS ZCL_ABAPGIT_OBJECT_WDYN IMPLEMENTATION. 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'. @@ -831,8 +933,8 @@ CLASS ZCL_ABAPGIT_OBJECT_WDYN IMPLEMENTATION. CHANGING cg_data = ls_component ). io_xml->read( EXPORTING iv_name = 'COMPONENTS' CHANGING cg_data = mt_components ). - io_xml->read( EXPORTING iv_name = 'SOURCES' - CHANGING cg_data = mt_sources ). + + deserialize_sources( io_xml ). ls_component-comp_metadata-definition-author = sy-uname. ls_component-comp_metadata-definition-createdon = sy-datum. @@ -944,8 +1046,8 @@ CLASS ZCL_ABAPGIT_OBJECT_WDYN IMPLEMENTATION. ig_data = ls_component ). io_xml->add( ig_data = mt_components iv_name = 'COMPONENTS' ). - io_xml->add( ig_data = mt_sources - iv_name = 'SOURCES' ). + + serialize_sources( io_xml ). READ TABLE ls_component-comp_metadata-descriptions INTO ls_description INDEX 1. IF sy-subrc = 0. From c83ebbe82c784124662784ec13040b03b0408770 Mon Sep 17 00:00:00 2001 From: Marc Bernard <59966492+mbtools@users.noreply.github.com> Date: Mon, 4 Nov 2024 04:23:51 -0500 Subject: [PATCH 3/3] SSFO: Store smartform code as separate ABAP files (#7071) Co-authored-by: Lars Hvam --- src/objects/zcl_abapgit_object_ssfo.clas.abap | 177 +++++++++++------- 1 file changed, 114 insertions(+), 63 deletions(-) diff --git a/src/objects/zcl_abapgit_object_ssfo.clas.abap b/src/objects/zcl_abapgit_object_ssfo.clas.abap index 3416b487d..156005782 100644 --- a/src/objects/zcl_abapgit_object_ssfo.clas.abap +++ b/src/objects/zcl_abapgit_object_ssfo.clas.abap @@ -7,6 +7,7 @@ CLASS zcl_abapgit_object_ssfo DEFINITION PUBLIC SECTION. INTERFACES zif_abapgit_object. + PROTECTED SECTION. PRIVATE SECTION. @@ -14,7 +15,7 @@ CLASS zcl_abapgit_object_ssfo DEFINITION ty_string_range TYPE RANGE OF string . CLASS-DATA gt_range_node_codes TYPE ty_string_range . - CONSTANTS c_attrib_abapgit_leadig_spaces TYPE string VALUE 'abapgit-leadig-spaces' ##NO_TEXT. + CONSTANTS c_prefix TYPE string VALUE 'File:'. METHODS fix_ids IMPORTING @@ -24,25 +25,26 @@ CLASS zcl_abapgit_object_ssfo DEFINITION !ii_xml_doc TYPE REF TO if_ixml_document RAISING zcx_abapgit_exception . - METHODS handle_attrib_leading_spaces - IMPORTING - !iv_name TYPE string - !ii_node TYPE REF TO if_ixml_node - CHANGING - !cv_within_code_section TYPE abap_bool . METHODS get_range_node_codes RETURNING VALUE(rt_range_node_codes) TYPE ty_string_range . - METHODS code_item_section_handling + METHODS deserialize_sources IMPORTING - !iv_name TYPE string - !ii_node TYPE REF TO if_ixml_node - EXPORTING - !ei_code_item_element TYPE REF TO if_ixml_element - CHANGING - !cv_within_code_section TYPE abap_bool + !ii_node TYPE REF TO if_ixml_node RAISING - zcx_abapgit_exception . + 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. @@ -50,29 +52,36 @@ ENDCLASS. CLASS zcl_abapgit_object_ssfo IMPLEMENTATION. - METHOD code_item_section_handling. - CONSTANTS: lc_node_item TYPE string VALUE 'item'. - CONSTANTS: lc_node_text TYPE string VALUE '#text'. + METHOD deserialize_sources. - IF iv_name IN get_range_node_codes( ). - cv_within_code_section = abap_true. + 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. - IF cv_within_code_section = abap_true. - IF iv_name = lc_node_item. - TRY. - ei_code_item_element ?= ii_node. - RETURN. - CATCH cx_sy_move_cast_error ##NO_HANDLER. - ENDTRY. + " New format + lv_extra = lv_extra+5(*). - ELSEIF iv_name NOT IN get_range_node_codes( ) AND - iv_name <> lc_node_text. - cv_within_code_section = abap_false. - ENDIF. - ENDIF. + lt_abap = mo_files->read_abap( iv_extra = lv_extra ). - RAISE EXCEPTION TYPE zcx_abapgit_exception. + 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. @@ -150,6 +159,35 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION. 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. @@ -172,28 +210,36 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION. ENDMETHOD. - METHOD handle_attrib_leading_spaces. + METHOD serialize_sources. - DATA li_element TYPE REF TO if_ixml_element. - DATA lv_leading_spaces TYPE string. - DATA lv_coding_line TYPE string. + 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. - TRY. - code_item_section_handling( EXPORTING iv_name = iv_name - ii_node = ii_node - IMPORTING ei_code_item_element = li_element - CHANGING cv_within_code_section = cv_within_code_section ). + " 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. -* for downwards compatibility, this code can be removed sometime in the future - lv_leading_spaces = li_element->get_attribute_ns( c_attrib_abapgit_leadig_spaces ). + li_node = li_iterator->get_next( ). + ENDWHILE. - lv_coding_line = li_element->get_value( ). - IF strlen( lv_coding_line ) >= 1 AND lv_coding_line(1) <> | |. - SHIFT lv_coding_line RIGHT BY lv_leading_spaces PLACES. - li_element->set_value( lv_coding_line ). - ENDIF. - CATCH zcx_abapgit_exception ##NO_HANDLER. - ENDTRY. + " 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. @@ -303,15 +349,15 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION. 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, - lv_within_code_section TYPE abap_bool. + 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. @@ -330,9 +376,9 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION. ENDCASE. - handle_attrib_leading_spaces( EXPORTING iv_name = lv_name - ii_node = li_node - CHANGING cv_within_code_section = lv_within_code_section ). + 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. @@ -530,6 +576,11 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION. 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.