CLASS zcl_abapgit_persistence_db DEFINITION
  PUBLIC
  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 .
  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_db IMPLEMENTATION.

  METHOD add.

    DATA ls_table TYPE zif_abapgit_persistence=>ty_content.

    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.

    DATA lv_data TYPE string.

    lock( iv_type  = iv_type
          iv_value = iv_value ).

    DELETE FROM (c_tabname)
      WHERE type = iv_type
      AND value = iv_value.
    IF sy-subrc <> 0.
      " If entry is still there? That's an error, otherwise ignore
      SELECT SINGLE data_str FROM (c_tabname) INTO lv_data
        WHERE type = iv_type
        AND value = iv_value.
      IF sy-subrc = 0.
        zcx_abapgit_exception=>raise( 'DB Delete failed' ).
      ENDIF.
    ENDIF.

  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'.
      CALL FUNCTION 'FUNCTION_EXISTS'
        EXPORTING
          funcname = mv_update_function
        EXCEPTIONS
          OTHERS   = 2.

      IF sy-subrc <> 0.
        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: <ls_key> LIKE LINE OF it_keys.
    LOOP AT it_keys ASSIGNING <ls_key>.
      SELECT * FROM (c_tabname)
      APPENDING TABLE rt_contents
      WHERE value = <ls_key> 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.

    lv_data = validate_and_unprettify_xml( iv_data ).

    lock( iv_type  = iv_type
          iv_value = iv_value ).

    UPDATE (c_tabname) SET data_str = lv_data
      WHERE type  = iv_type
      AND value = iv_value.
    IF sy-subrc <> 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.
ENDCLASS.

CLASS zcl_abapgit_persistence_db DEFINITION
  PUBLIC
  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 .
  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_db IMPLEMENTATION.

  METHOD add.

    DATA ls_table TYPE zif_abapgit_persistence=>ty_content.

    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.

    DATA lv_data TYPE string.

    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'.
      CALL FUNCTION 'FUNCTION_EXISTS'
        EXPORTING
          funcname = mv_update_function
        EXCEPTIONS
          OTHERS   = 2.

      IF sy-subrc <> 0.
        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: <ls_key> LIKE LINE OF it_keys.
    LOOP AT it_keys ASSIGNING <ls_key>.
      SELECT * FROM (c_tabname)
      APPENDING TABLE rt_contents
      WHERE value = <ls_key> 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.

    lv_data = validate_and_unprettify_xml( iv_data ).

    lock( iv_type  = iv_type
          iv_value = iv_value ).

    UPDATE (c_tabname) SET data_str = lv_data
      WHERE type  = iv_type
      AND value = iv_value.
    IF sy-subrc <> 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.
ENDCLASS.

Fix "DB delete failed" (#5534)

Fix "DB delete failed" (#5534)


CLASS zcl_abapgit_gui_page_codi_base DEFINITION PUBLIC ABSTRACT INHERITING FROM zcl_abapgit_gui_page.
  PUBLIC SECTION.
    METHODS:
      zif_abapgit_gui_event_handler~on_event
        REDEFINITION.

  PROTECTED SECTION.

    CONSTANTS:
      BEGIN OF c_actions,
        rerun  TYPE string VALUE 'rerun' ##NO_TEXT,
        sort_1 TYPE string VALUE 'sort_1'  ##NO_TEXT,
        sort_2 TYPE string VALUE 'sort_2'  ##NO_TEXT,
        sort_3 TYPE string VALUE 'sort_3'  ##NO_TEXT,
        stage  TYPE string VALUE 'stage' ##NO_TEXT,
        commit TYPE string VALUE 'commit' ##NO_TEXT,
      END OF c_actions.

    DATA mo_repo TYPE REF TO zcl_abapgit_repo .
    DATA mt_result TYPE scit_alvlist .

    METHODS render_result
      IMPORTING
        !ii_html   TYPE REF TO zif_abapgit_html
        !it_result TYPE scit_alvlist .
    METHODS render_result_line
      IMPORTING
        !ii_html   TYPE REF TO zif_abapgit_html
        !is_result TYPE scir_alvlist .
    METHODS build_nav_link
      IMPORTING
        !is_result     TYPE scir_alvlist
      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 build_base_menu
      RETURNING
        VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar .
  PRIVATE SECTION.
    CONSTANTS c_object_separator TYPE char1 VALUE '|'.
    CONSTANTS c_ci_sig TYPE string VALUE 'cinav:'.
ENDCLASS.

CLASS ZCL_ABAPGIT_GUI_PAGE_CODI_BASE IMPLEMENTATION.

  METHOD build_base_menu.

    DATA:
      lo_sort_menu TYPE REF TO zcl_abapgit_html_toolbar.

    CREATE OBJECT lo_sort_menu.

    lo_sort_menu->add(
      iv_txt = 'By Object, Check, Sub-object'
      iv_act = c_actions-sort_1
    )->add(
      iv_txt = 'By Object, Sub-object, Line'
      iv_act = c_actions-sort_2
    )->add(
      iv_txt = 'By Check, Object, Sub-object'
      iv_act = c_actions-sort_3 ).

    CREATE OBJECT ro_menu.

    ro_menu->add( iv_txt = 'Sort'
                  io_sub = lo_sort_menu ) ##NO_TEXT.

    ro_menu->add( iv_txt = 'Re-Run'
                  iv_act = c_actions-rerun
                  iv_cur = abap_false ) ##NO_TEXT.

  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 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: <ls_result> TYPE scir_alvlist.

    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 <ls_result>.
    ELSE.
      READ TABLE mt_result WITH KEY objtype = is_item-obj_type
                                    objname = is_item-obj_name
                                    line    = iv_line_number
                           ASSIGNING <ls_result>.
    ENDIF.
    ASSERT <ls_result> IS ASSIGNED.
    ls_item-obj_name = <ls_result>-objname.
    ls_item-obj_type = <ls_result>-objtype.

    ls_sub_item-obj_name = <ls_result>-sobjname.
    ls_sub_item-obj_type = <ls_result>-sobjtype.

    " see SCI_LCL_DYNP_530 / HANDLE_DOUBLE_CLICK

    lv_adt_jump_enabled = zcl_abapgit_persist_settings=>get_instance( )->read( )->get_adt_jump_enabled( ).

    TRY.
        IF lv_adt_jump_enabled = abap_true.

          lv_line_number = <ls_result>-line.

          zcl_abapgit_objects_super=>jump_adt( iv_obj_name     = ls_item-obj_name
                                               iv_obj_type     = ls_item-obj_type
                                               iv_sub_obj_name = ls_sub_item-obj_name
                                               iv_sub_obj_type = ls_sub_item-obj_type
                                               iv_line_number  = lv_line_number ).
          RETURN.

        ENDIF.
      CATCH zcx_abapgit_exception.
    ENDTRY.

    TRY.
        CALL METHOD ('CL_CI_TESTS')=>('GET_TEST_REF')
          EXPORTING
            p_test   = <ls_result>-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( <ls_result>-kind ).

    MOVE-CORRESPONDING <ls_result> TO ls_info.

    lo_result->set_info( ls_info ).
    lo_result->if_ci_test~navigate( ).

  ENDMETHOD.

  METHOD render_result.

    CONSTANTS: lc_limit TYPE i VALUE 500.
    FIELD-SYMBOLS: <ls_result> TYPE scir_alvlist.

    ii_html->add( '
' ).

    LOOP AT it_result ASSIGNING <ls_result> TO lc_limit.
      render_result_line(
        ii_html = ii_html
        is_result = <ls_result> ).
    ENDLOOP.

    ii_html->add( '
' ).

    IF lines( it_result ) > lc_limit.
      ii_html->add( '
' ).
      ii_html->add( zcl_abapgit_html=>icon( 'exclamation-triangle' ) ).
      ii_html->add( |Only first { lc_limit } findings shown in list!| ).
      ii_html->add( '
' ).
    ENDIF.

  ENDMETHOD.

  METHOD render_result_line.

    DATA: lv_class   TYPE string,
          lv_obj_txt TYPE string,
          lv_msg     TYPE string,
          ls_mtdkey  TYPE seocpdkey.

    CASE is_result-kind.
      WHEN 'E'.
        lv_class = 'ci-error'.
      WHEN 'W'.
        lv_class = 'ci-warning'.
      WHEN OTHERS.
        lv_class = 'ci-info'.
    ENDCASE.

    lv_msg = escape( val = is_result-text
                     format = cl_abap_format=>e_html_attr ).

    IF is_result-sobjname IS INITIAL OR
       ( is_result-sobjname = is_result-objname AND
         is_result-sobjtype = is_result-sobjtype ).
      lv_obj_txt = |{ is_result-objtype } { is_result-objname }|.
    ELSEIF is_result-objtype = 'CLAS'.
      TRY.
          CASE is_result-sobjname+30(*).
            WHEN seop_incextapp_definition.
              lv_obj_txt = |{ is_result-objname } : Local Definitions|.
            WHEN seop_incextapp_implementation.
              lv_obj_txt = |{ is_result-objname } : Local Implementations|.
            WHEN seop_incextapp_macros.
              lv_obj_txt = |{ is_result-objname } : Macros|.
            WHEN seop_incextapp_testclasses.
              lv_obj_txt = |{ is_result-objname } : Test Classes|.
            WHEN OTHERS.
              ls_mtdkey = cl_oo_classname_service=>get_method_by_include( is_result-sobjname ).
              lv_obj_txt = |{ ls_mtdkey-clsname }->{ ls_mtdkey-cpdname }|.
          ENDCASE.
        CATCH cx_root.
          lv_obj_txt = ''. "use default below
      ENDTRY.
    ENDIF.
    IF lv_obj_txt IS INITIAL.
      lv_obj_txt = |{ is_result-objtype } { is_result-objname } > { is_result-sobjtype } { is_result-sobjname }|.
    ENDIF.
    lv_obj_txt = |{ lv_obj_txt } [ @{ zcl_abapgit_convert=>alpha_output( is_result-line ) } ]|.

    ii_html->add( |
| ).
    ii_html->add_a(
      iv_txt = lv_obj_txt
      iv_act = build_nav_link( is_result )
      iv_typ = zif_abapgit_html=>c_action_type-sapevent ).
    ii_html->add( |{ lv_msg }| ).
    ii_html->add( '
' ).

  ENDMETHOD.

  METHOD zif_abapgit_gui_event_handler~on_event.
    DATA: ls_item          TYPE zif_abapgit_definitions=>ty_item,
          ls_sub_item      TYPE zif_abapgit_definitions=>ty_item,
          lv_temp          TYPE string,
          lv_main_object   TYPE string,
          lv_sub_object    TYPE string,
          lv_line_number_s TYPE string,
          lv_line_number   TYPE i.

    lv_temp = replace( val   = iv_action
                       regex = |^{ c_ci_sig }|
                       with  = `` ).

    IF lv_temp <> iv_action. " CI navigation request detected

      SPLIT lv_temp AT c_object_separator INTO lv_main_object lv_sub_object lv_line_number_s.
      ls_item-obj_type = lv_main_object(4).
      ls_item-obj_name = lv_main_object+4(*).

      IF lv_sub_object IS NOT INITIAL.
        ls_sub_item-obj_type = lv_sub_object(4).
        ls_sub_item-obj_name = 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 ).

      ev_state = zcl_abapgit_gui=>c_event_state-no_more_act.

    ENDIF.

    CASE iv_action.

      WHEN c_actions-sort_1.
        SORT mt_result BY objtype objname test code sobjtype sobjname line col.
        ei_page = me.
        ev_state = zcl_abapgit_gui=>c_event_state-re_render.
      WHEN c_actions-sort_2.
        SORT mt_result BY objtype objname sobjtype sobjname line col test code.
        ei_page = me.
        ev_state = zcl_abapgit_gui=>c_event_state-re_render.
      WHEN c_actions-sort_3.
        SORT mt_result BY test code objtype objname sobjtype sobjname line col.
        ei_page = me.
        ev_state = zcl_abapgit_gui=>c_event_state-re_render.

    ENDCASE.

  ENDMETHOD.
ENDCLASS.

CLASS zcl_abapgit_gui_page_codi_base DEFINITION PUBLIC ABSTRACT INHERITING FROM zcl_abapgit_gui_page.
  PUBLIC SECTION.
    METHODS:
      zif_abapgit_gui_event_handler~on_event
        REDEFINITION.

  PROTECTED SECTION.

    CONSTANTS:
      BEGIN OF c_actions,
        rerun  TYPE string VALUE 'rerun' ##NO_TEXT,
        sort_1 TYPE string VALUE 'sort_1'  ##NO_TEXT,
        sort_2 TYPE string VALUE 'sort_2'  ##NO_TEXT,
        sort_3 TYPE string VALUE 'sort_3'  ##NO_TEXT,
        stage  TYPE string VALUE 'stage' ##NO_TEXT,
        commit TYPE string VALUE 'commit' ##NO_TEXT,
      END OF c_actions.

    DATA mo_repo TYPE REF TO zcl_abapgit_repo .
    DATA mt_result TYPE scit_alvlist .

    METHODS render_result
      IMPORTING
        !ii_html   TYPE REF TO zif_abapgit_html
        !it_result TYPE scit_alvlist .
    METHODS render_result_line
      IMPORTING
        !ii_html   TYPE REF TO zif_abapgit_html
        !is_result TYPE scir_alvlist .
    METHODS build_nav_link
      IMPORTING
        !is_result     TYPE scir_alvlist
      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 build_base_menu
      RETURNING
        VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar .
  PRIVATE SECTION.
    CONSTANTS c_object_separator TYPE char1 VALUE '|'.
    CONSTANTS c_ci_sig TYPE string VALUE 'cinav:'.
ENDCLASS.

CLASS ZCL_ABAPGIT_GUI_PAGE_CODI_BASE IMPLEMENTATION.

  METHOD build_base_menu.

    DATA:
      lo_sort_menu TYPE REF TO zcl_abapgit_html_toolbar.

    CREATE OBJECT lo_sort_menu.

    lo_sort_menu->add(
      iv_txt = 'By Object, Check, Sub-object'
      iv_act = c_actions-sort_1
    )->add(
      iv_txt = 'By Object, Sub-object, Line'
      iv_act = c_actions-sort_2
    )->add(
      iv_txt = 'By Check, Object, Sub-object'
      iv_act = c_actions-sort_3 ).

    CREATE OBJECT ro_menu.

    ro_menu->add( iv_txt = 'Sort'
                  io_sub = lo_sort_menu ) ##NO_TEXT.

    ro_menu->add( iv_txt = 'Re-Run'
                  iv_act = c_actions-rerun
                  iv_cur = abap_false ) ##NO_TEXT.

  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 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: <ls_result> TYPE scir_alvlist.

    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 <ls_result>.
    ELSE.
      READ TABLE mt_result WITH KEY objtype = is_item-obj_type
                                    objname = is_item-obj_name
                                    line    = iv_line_number
                           ASSIGNING <ls_result>.
    ENDIF.
    ASSERT <ls_result> IS ASSIGNED.
    ls_item-obj_name = <ls_result>-objname.
    ls_item-obj_type = <ls_result>-objtype.

    ls_sub_item-obj_name = <ls_result>-sobjname.
    ls_sub_item-obj_type = <ls_result>-sobjtype.

    " see SCI_LCL_DYNP_530 / HANDLE_DOUBLE_CLICK

    lv_adt_jump_enabled = zcl_abapgit_persist_settings=>get_instance( )->read( )->get_adt_jump_enabled( ).

    TRY.
        IF lv_adt_jump_enabled = abap_true.

          lv_line_number = <ls_result>-line.

          zcl_abapgit_objects_super=>jump_adt( iv_obj_name     = ls_item-obj_name
                                               iv_obj_type     = ls_item-obj_type
                                               iv_sub_obj_name = ls_sub_item-obj_name
                                               iv_sub_obj_type = ls_sub_item-obj_type
                                               iv_line_number  = lv_line_number ).
          RETURN.

        ENDIF.
      CATCH zcx_abapgit_exception.
    ENDTRY.

    TRY.
        CALL METHOD ('CL_CI_TESTS')=>('GET_TEST_REF')
          EXPORTING
            p_test   = <ls_result>-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( <ls_result>-kind ).

    MOVE-CORRESPONDING <ls_result> TO ls_info.

    lo_result->set_info( ls_info ).
    lo_result->if_ci_test~navigate( ).

  ENDMETHOD.

  METHOD render_result.

    CONSTANTS: lc_limit TYPE i VALUE 500.
    FIELD-SYMBOLS: <ls_result> TYPE scir_alvlist.

    ii_html->add( '
' ).

    LOOP AT it_result ASSIGNING <ls_result> TO lc_limit.
      render_result_line(
        ii_html = ii_html
        is_result = <ls_result> ).
    ENDLOOP.

    ii_html->add( '
' ).

    IF lines( it_result ) > lc_limit.
      ii_html->add( '
' ).
      ii_html->add( zcl_abapgit_html=>icon( 'exclamation-triangle' ) ).
      ii_html->add( |Only first { lc_limit } findings shown in list!| ).
      ii_html->add( '
' ).
    ENDIF.

  ENDMETHOD.

  METHOD render_result_line.

    DATA: lv_class   TYPE string,
          lv_obj_txt TYPE string,
          lv_msg     TYPE string,
          ls_mtdkey  TYPE seocpdkey.

    CASE is_result-kind.
      WHEN 'E'.
        lv_class = 'ci-error'.
      WHEN 'W'.
        lv_class = 'ci-warning'.
      WHEN OTHERS.
        lv_class = 'ci-info'.
    ENDCASE.

    lv_msg = escape( val = is_result-text
                     format = cl_abap_format=>e_html_attr ).

    IF is_result-sobjname IS INITIAL OR
       ( is_result-sobjname = is_result-objname AND
         is_result-sobjtype = is_result-sobjtype ).
      lv_obj_txt = |{ is_result-objtype } { is_result-objname }|.
    ELSEIF is_result-objtype = 'CLAS'.
      TRY.
          CASE is_result-sobjname+30(*).
            WHEN seop_incextapp_definition.
              lv_obj_txt = |{ is_result-objname } : Local Definitions|.
            WHEN seop_incextapp_implementation.
              lv_obj_txt = |{ is_result-objname } : Local Implementations|.
            WHEN seop_incextapp_macros.
              lv_obj_txt = |{ is_result-objname } : Macros|.
            WHEN seop_incextapp_testclasses.
              lv_obj_txt = |{ is_result-objname } : Test Classes|.
            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.
                lv_obj_txt = |{ ls_mtdkey-clsname }->{ ls_mtdkey-cpdname }|.
              ELSE.
                lv_obj_txt = is_result-sobjname.
              ENDIF.

          ENDCASE.
        CATCH cx_root.
          lv_obj_txt = ''. "use default below
      ENDTRY.
    ENDIF.
    IF lv_obj_txt IS INITIAL.
      lv_obj_txt = |{ is_result-objtype } { is_result-objname } > { is_result-sobjtype } { is_result-sobjname }|.
    ENDIF.
    lv_obj_txt = |{ lv_obj_txt } [ @{ zcl_abapgit_convert=>alpha_output( is_result-line ) } ]|.

    ii_html->add( |
| ).
    ii_html->add_a(
      iv_txt = lv_obj_txt
      iv_act = build_nav_link( is_result )
      iv_typ = zif_abapgit_html=>c_action_type-sapevent ).
    ii_html->add( |{ lv_msg }| ).
    ii_html->add( '
' ).

  ENDMETHOD.

  METHOD zif_abapgit_gui_event_handler~on_event.
    DATA: ls_item          TYPE zif_abapgit_definitions=>ty_item,
          ls_sub_item      TYPE zif_abapgit_definitions=>ty_item,
          lv_temp          TYPE string,
          lv_main_object   TYPE string,
          lv_sub_object    TYPE string,
          lv_line_number_s TYPE string,
          lv_line_number   TYPE i.

    lv_temp = replace( val   = iv_action
                       regex = |^{ c_ci_sig }|
                       with  = `` ).

    IF lv_temp <> iv_action. " CI navigation request detected

      SPLIT lv_temp AT c_object_separator INTO lv_main_object lv_sub_object lv_line_number_s.
      ls_item-obj_type = lv_main_object(4).
      ls_item-obj_name = lv_main_object+4(*).

      IF lv_sub_object IS NOT INITIAL.
        ls_sub_item-obj_type = lv_sub_object(4).
        ls_sub_item-obj_name = 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 ).

      ev_state = zcl_abapgit_gui=>c_event_state-no_more_act.

    ENDIF.

    CASE iv_action.

      WHEN c_actions-sort_1.
        SORT mt_result BY objtype objname test code sobjtype sobjname line col.
        ei_page = me.
        ev_state = zcl_abapgit_gui=>c_event_state-re_render.
      WHEN c_actions-sort_2.
        SORT mt_result BY objtype objname sobjtype sobjname line col test code.
        ei_page = me.
        ev_state = zcl_abapgit_gui=>c_event_state-re_render.
      WHEN c_actions-sort_3.
        SORT mt_result BY test code objtype objname sobjtype sobjname line col.
        ei_page = me.
        ev_state = zcl_abapgit_gui=>c_event_state-re_render.

    ENDCASE.

  ENDMETHOD.
ENDCLASS.

Fix dump in Code Insp. Display for exception class (#3724)


CLASS zcl_abapgit_object_form DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.

  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.

    TYPES: BEGIN OF tys_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 tys_form_data,
           tyt_form_data   TYPE STANDARD TABLE OF tys_form_data WITH DEFAULT KEY,
           tyt_form_header TYPE STANDARD TABLE OF itcta WITH DEFAULT KEY,
           tys_form_header TYPE LINE OF tyt_form_header,
           tyt_text_header TYPE STANDARD TABLE OF thead WITH DEFAULT KEY,
           tys_text_header TYPE LINE OF tyt_text_header,
           tyt_lines       TYPE tline_tab.

    METHODS _get_last_changes
      IMPORTING
        iv_form_name           TYPE zif_abapgit_definitions=>ty_item-obj_name
      RETURNING
        VALUE(es_last_changed) TYPE tys_form_header.

    METHODS _build_extra_from_header
      IMPORTING
        ls_header       TYPE tys_form_header
      RETURNING
        VALUE(r_result) TYPE string.

    METHODS _save_form
      IMPORTING
        it_lines     TYPE zcl_abapgit_object_form=>tyt_lines
      CHANGING
        cs_form_data TYPE zcl_abapgit_object_form=>tys_form_data.

    METHODS _extract_tdlines
      IMPORTING
        is_form_data    TYPE zcl_abapgit_object_form=>tys_form_data
      RETURNING
        VALUE(et_lines) TYPE zcl_abapgit_object_form=>tyt_lines
      RAISING
        zcx_abapgit_exception.

    METHODS _clear_changed_fields
      CHANGING
        cs_form_data TYPE zcl_abapgit_object_form=>tys_form_data.

    METHODS _compress_lines
      IMPORTING
        is_form_data TYPE zcl_abapgit_object_form=>tys_form_data
        it_lines     TYPE zcl_abapgit_object_form=>tyt_lines
      RAISING
        zcx_abapgit_exception.

    METHODS _find_form
      IMPORTING
        iv_object_name        TYPE zif_abapgit_definitions=>ty_item-obj_name
      RETURNING
        VALUE(et_text_header) TYPE zcl_abapgit_object_form=>tyt_text_header.

    METHODS _read_form
      IMPORTING
        is_text_header TYPE zcl_abapgit_object_form=>tys_text_header
      EXPORTING
        ev_form_found  TYPE flag
        es_form_data   TYPE zcl_abapgit_object_form=>tys_form_data
        et_lines       TYPE zcl_abapgit_object_form=>tyt_lines.

ENDCLASS.

CLASS zcl_abapgit_object_form IMPLEMENTATION.

  METHOD zif_abapgit_object~has_changed_since.

    DATA: ls_last_changed    TYPE tys_form_header.
    DATA: lv_last_changed_ts TYPE timestamp.

    ls_last_changed = _get_last_changes( ms_item-obj_name ).

    CONVERT DATE ls_last_changed-tdldate TIME ls_last_changed-tdltime
            INTO TIME STAMP lv_last_changed_ts TIME ZONE sy-zonlo.

    rv_changed = boolc( sy-subrc <> 0 OR lv_last_changed_ts > iv_timestamp ).

  ENDMETHOD.

  METHOD zif_abapgit_object~changed_by.

    DATA: ls_last_changed TYPE tys_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~get_metadata.

    rs_metadata = get_metadata( ).
    rs_metadata-delete_tadir = abap_true.

  ENDMETHOD.

  METHOD zif_abapgit_object~exists.

    DATA: lv_form_name TYPE thead-tdform.

    lv_form_name = ms_item-obj_name.

    CALL FUNCTION 'READ_FORM'
      EXPORTING
        form             = lv_form_name
        read_only_header = abap_true
      IMPORTING
        found            = rv_bool.

  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    DATA: lt_bdcdata TYPE TABLE OF bdcdata.

    FIELD-SYMBOLS: <ls_bdcdata> LIKE LINE OF lt_bdcdata.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-program  = 'SAPMSSCF' ##NO_TEXT.
    <ls_bdcdata>-dynpro   = '1102' ##NO_TEXT.
    <ls_bdcdata>-dynbegin = abap_true.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'BDC_OKCODE' ##NO_TEXT.
    <ls_bdcdata>-fval = '=SHOW' ##NO_TEXT.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'RSSCF-TDFORM' ##NO_TEXT.
    <ls_bdcdata>-fval = ms_item-obj_name.

    CALL FUNCTION 'ABAP4_CALL_TRANSACTION'
      STARTING NEW TASK 'GIT'
      EXPORTING
        tcode     = 'SE71'
        mode_val  = 'E'
      TABLES
        using_tab = lt_bdcdata
      EXCEPTIONS
        OTHERS    = 1
        ##fm_subrc_ok.                                                   "#EC CI_SUBRC

  ENDMETHOD.

  METHOD zif_abapgit_object~delete.

    DATA: lv_name TYPE itcta-tdform.

    lv_name = ms_item-obj_name.

    CALL FUNCTION 'DELETE_FORM'
      EXPORTING
        form     = lv_name
        language = '*'.

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA: lt_form_data              TYPE tyt_form_data.
    DATA: ls_form_data              TYPE tys_form_data.
    DATA: lt_text_header            TYPE tyt_text_header.
    DATA: lt_lines                  TYPE tyt_lines.
*    DATA: lo_xml                    TYPE REF TO zcl_abapgit_xml_output.
    DATA: lv_form_found             TYPE flag.
    FIELD-SYMBOLS: <ls_text_header> LIKE LINE OF lt_text_header.

    lt_text_header = _find_form( ms_item-obj_name ).

    LOOP AT lt_text_header ASSIGNING <ls_text_header>.
      CLEAR lt_lines.
      CLEAR ls_form_data.
*      FREE lo_xml.

      _read_form( EXPORTING is_text_header = <ls_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 zif_abapgit_object~deserialize.

    DATA: lt_form_data            TYPE tyt_form_data.
    DATA: lt_lines                TYPE tyt_lines.
    FIELD-SYMBOLS: <ls_form_data> TYPE LINE OF tyt_form_data.

    io_xml->read( EXPORTING iv_name = c_objectname_form
                  CHANGING  cg_data = lt_form_data ).

    LOOP AT lt_form_data ASSIGNING <ls_form_data>.

      lt_lines = _extract_tdlines( <ls_form_data> ).

      _save_form( EXPORTING it_lines     = lt_lines
                  CHANGING  cs_form_data = <ls_form_data> ).

    ENDLOOP.

    CALL FUNCTION 'SAPSCRIPT_DELETE_LOAD'
      EXPORTING
        delete = abap_true
        form   = '*'
        write  = space.

    tadir_insert( iv_package ).

  ENDMETHOD.

  METHOD zif_abapgit_object~compare_to_remote_version.
    CREATE OBJECT ro_comparison_result TYPE zcl_abapgit_comparison_null.
  ENDMETHOD.

  METHOD _build_extra_from_header.

    DATA: lv_tdspras type laiso.

    CALL FUNCTION 'CONVERSION_EXIT_ISOLA_OUTPUT'
      EXPORTING
        input  = ls_header-tdspras
      IMPORTING
        output = lv_tdspras.

    r_result = c_objectname_tdlines && '_' && lv_tdspras.

  ENDMETHOD.

  METHOD _get_last_changes.

    DATA: lv_form_name         TYPE thead-tdform.

    CLEAR es_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      = es_last_changed.

  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 _extract_tdlines.

    DATA lv_string TYPE string.
    DATA lo_xml TYPE REF TO zcl_abapgit_xml_input.

    lv_string = mo_files->read_string( iv_extra =
                               _build_extra_from_header( is_form_data-form_header )
                                       iv_ext   = c_extension_xml ).

    CREATE OBJECT lo_xml EXPORTING iv_xml = lv_string.
    lo_xml->read( EXPORTING iv_name = c_objectname_tdlines
                  CHANGING  cg_data = et_lines ).

  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 _compress_lines.

    DATA lv_string TYPE string.
    DATA lo_xml TYPE REF TO zcl_abapgit_xml_output.

    CREATE OBJECT lo_xml.
    lo_xml->add( iv_name = c_objectname_tdlines
                 ig_data = it_lines ).
    lv_string = lo_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 _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    = et_text_header
      EXCEPTIONS
        OTHERS        = 1
        ##fm_subrc_ok ##NO_TEXT.  "#EC CI_SUBRC

  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.

  ENDMETHOD.

ENDCLASS.                    "zcl_abapgit_object_FORM IMPLEMENTATION

CLASS zcl_abapgit_object_form DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.

  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.

    TYPES: BEGIN OF tys_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 tys_form_data,
           tyt_form_data   TYPE STANDARD TABLE OF tys_form_data WITH DEFAULT KEY,
           tyt_form_header TYPE STANDARD TABLE OF itcta WITH DEFAULT KEY,
           tys_form_header TYPE LINE OF tyt_form_header,
           tyt_text_header TYPE STANDARD TABLE OF thead WITH DEFAULT KEY,
           tys_text_header TYPE LINE OF tyt_text_header,
           tyt_lines       TYPE tline_tab.

    METHODS _get_last_changes
      IMPORTING
        iv_form_name           TYPE zif_abapgit_definitions=>ty_item-obj_name
      RETURNING
        VALUE(es_last_changed) TYPE tys_form_header.

    METHODS _build_extra_from_header
      IMPORTING
        ls_header       TYPE tys_form_header
      RETURNING
        VALUE(r_result) TYPE string.

    METHODS _build_extra_from_header_old
      IMPORTING
        ls_header       TYPE tys_form_header
      RETURNING
        VALUE(r_result) TYPE string.

    METHODS _save_form
      IMPORTING
        it_lines     TYPE zcl_abapgit_object_form=>tyt_lines
      CHANGING
        cs_form_data TYPE zcl_abapgit_object_form=>tys_form_data.

    METHODS _extract_tdlines
      IMPORTING
        is_form_data    TYPE zcl_abapgit_object_form=>tys_form_data
      RETURNING
        VALUE(et_lines) TYPE zcl_abapgit_object_form=>tyt_lines
      RAISING
        zcx_abapgit_exception.

    METHODS _clear_changed_fields
      CHANGING
        cs_form_data TYPE zcl_abapgit_object_form=>tys_form_data.

    METHODS _compress_lines
      IMPORTING
        is_form_data TYPE zcl_abapgit_object_form=>tys_form_data
        it_lines     TYPE zcl_abapgit_object_form=>tyt_lines
      RAISING
        zcx_abapgit_exception.

    METHODS _find_form
      IMPORTING
        iv_object_name        TYPE zif_abapgit_definitions=>ty_item-obj_name
      RETURNING
        VALUE(et_text_header) TYPE zcl_abapgit_object_form=>tyt_text_header.

    METHODS _read_form
      IMPORTING
        is_text_header TYPE zcl_abapgit_object_form=>tys_text_header
      EXPORTING
        ev_form_found  TYPE flag
        es_form_data   TYPE zcl_abapgit_object_form=>tys_form_data
        et_lines       TYPE zcl_abapgit_object_form=>tyt_lines.

ENDCLASS.

CLASS zcl_abapgit_object_form IMPLEMENTATION.

  METHOD zif_abapgit_object~has_changed_since.

    DATA: ls_last_changed    TYPE tys_form_header.
    DATA: lv_last_changed_ts TYPE timestamp.

    ls_last_changed = _get_last_changes( ms_item-obj_name ).

    CONVERT DATE ls_last_changed-tdldate TIME ls_last_changed-tdltime
            INTO TIME STAMP lv_last_changed_ts TIME ZONE sy-zonlo.

    rv_changed = boolc( sy-subrc <> 0 OR lv_last_changed_ts > iv_timestamp ).

  ENDMETHOD.

  METHOD zif_abapgit_object~changed_by.

    DATA: ls_last_changed TYPE tys_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~get_metadata.

    rs_metadata = get_metadata( ).
    rs_metadata-delete_tadir = abap_true.

  ENDMETHOD.

  METHOD zif_abapgit_object~exists.

    DATA: lv_form_name TYPE thead-tdform.

    lv_form_name = ms_item-obj_name.

    CALL FUNCTION 'READ_FORM'
      EXPORTING
        form             = lv_form_name
        read_only_header = abap_true
      IMPORTING
        found            = rv_bool.

  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    DATA: lt_bdcdata TYPE TABLE OF bdcdata.

    FIELD-SYMBOLS: <ls_bdcdata> LIKE LINE OF lt_bdcdata.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-program  = 'SAPMSSCF' ##NO_TEXT.
    <ls_bdcdata>-dynpro   = '1102' ##NO_TEXT.
    <ls_bdcdata>-dynbegin = abap_true.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'BDC_OKCODE' ##NO_TEXT.
    <ls_bdcdata>-fval = '=SHOW' ##NO_TEXT.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'RSSCF-TDFORM' ##NO_TEXT.
    <ls_bdcdata>-fval = ms_item-obj_name.

    CALL FUNCTION 'ABAP4_CALL_TRANSACTION'
      STARTING NEW TASK 'GIT'
      EXPORTING
        tcode     = 'SE71'
        mode_val  = 'E'
      TABLES
        using_tab = lt_bdcdata
      EXCEPTIONS
        OTHERS    = 1
        ##fm_subrc_ok.                                                   "#EC CI_SUBRC

  ENDMETHOD.

  METHOD zif_abapgit_object~delete.

    DATA: lv_name TYPE itcta-tdform.

    lv_name = ms_item-obj_name.

    CALL FUNCTION 'DELETE_FORM'
      EXPORTING
        form     = lv_name
        language = '*'.

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA: lt_form_data              TYPE tyt_form_data.
    DATA: ls_form_data              TYPE tys_form_data.
    DATA: lt_text_header            TYPE tyt_text_header.
    DATA: lt_lines                  TYPE tyt_lines.
*    DATA: lo_xml                    TYPE REF TO zcl_abapgit_xml_output.
    DATA: lv_form_found             TYPE flag.
    FIELD-SYMBOLS: <ls_text_header> LIKE LINE OF lt_text_header.

    lt_text_header = _find_form( ms_item-obj_name ).

    LOOP AT lt_text_header ASSIGNING <ls_text_header>.
      CLEAR lt_lines.
      CLEAR ls_form_data.
*      FREE lo_xml.

      _read_form( EXPORTING is_text_header = <ls_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 zif_abapgit_object~deserialize.

    DATA: lt_form_data            TYPE tyt_form_data.
    DATA: lt_lines                TYPE tyt_lines.
    FIELD-SYMBOLS: <ls_form_data> TYPE LINE OF tyt_form_data.

    io_xml->read( EXPORTING iv_name = c_objectname_form
                  CHANGING  cg_data = lt_form_data ).

    LOOP AT lt_form_data ASSIGNING <ls_form_data>.

      lt_lines = _extract_tdlines( <ls_form_data> ).

      _save_form( EXPORTING it_lines     = lt_lines
                  CHANGING  cs_form_data = <ls_form_data> ).

    ENDLOOP.

    CALL FUNCTION 'SAPSCRIPT_DELETE_LOAD'
      EXPORTING
        delete = abap_true
        form   = '*'
        write  = space.

    tadir_insert( iv_package ).

  ENDMETHOD.

  METHOD zif_abapgit_object~compare_to_remote_version.
    CREATE OBJECT ro_comparison_result TYPE zcl_abapgit_comparison_null.
  ENDMETHOD.

  METHOD _build_extra_from_header.

    DATA: lv_tdspras type laiso.

    CALL FUNCTION 'CONVERSION_EXIT_ISOLA_OUTPUT'
      EXPORTING
        input  = ls_header-tdspras
      IMPORTING
        output = lv_tdspras.

    r_result = c_objectname_tdlines && '_' && lv_tdspras.

  ENDMETHOD.

  METHOD _build_extra_from_header_old.
    r_result = c_objectname_tdlines && '_' && ls_header-tdspras.
  ENDMETHOD.

  METHOD _get_last_changes.

    DATA: lv_form_name         TYPE thead-tdform.

    CLEAR es_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      = es_last_changed.

  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 _extract_tdlines.

    DATA lv_string TYPE string.
    DATA lo_xml TYPE REF TO zcl_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 lo_xml EXPORTING iv_xml = lv_string.
    lo_xml->read( EXPORTING iv_name = c_objectname_tdlines
                  CHANGING  cg_data = et_lines ).

  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 _compress_lines.

    DATA lv_string TYPE string.
    DATA lo_xml TYPE REF TO zcl_abapgit_xml_output.

    CREATE OBJECT lo_xml.
    lo_xml->add( iv_name = c_objectname_tdlines
                 ig_data = it_lines ).
    lv_string = lo_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 _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    = et_text_header
      EXCEPTIONS
        OTHERS        = 1
        ##fm_subrc_ok ##NO_TEXT.  "#EC CI_SUBRC

  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.

  ENDMETHOD.

ENDCLASS.                    "zcl_abapgit_object_FORM IMPLEMENTATION

Use the 2-character code for language. Downwards compatibility.

Check first the new 2-character file name, if fail, use the old name.


CLASS ltcl_folder_logic_helper DEFINITION FOR TESTING FINAL.

  PUBLIC SECTION.
    CLASS-METHODS: test
      IMPORTING
                iv_starting TYPE string
                iv_top      TYPE devclass
                iv_logic    TYPE string
                iv_package  TYPE devclass
                iv_path     TYPE string
      RAISING   zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_folder_logic_helper IMPLEMENTATION.

  METHOD test.

    DATA: lv_path    TYPE string,
          lv_package TYPE devclass,
          lo_dot     TYPE REF TO zcl_abapgit_dot_abapgit.

    lo_dot = zcl_abapgit_dot_abapgit=>build_default( ).
    lo_dot->set_starting_folder( iv_starting ).
    lo_dot->set_folder_logic( iv_logic ).

    lv_package = zcl_abapgit_folder_logic=>path_to_package(
      iv_top  = iv_top
      io_dot  = lo_dot
      iv_path = iv_path ).

    lv_path = zcl_abapgit_folder_logic=>package_to_path(
      iv_top     = iv_top
      io_dot     = lo_dot
      iv_package = iv_package ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_package
      exp = iv_package ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_path
      exp = iv_path ).

  ENDMETHOD.

ENDCLASS.

CLASS ltcl_folder_logic DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL.

  PUBLIC SECTION.
    INTERFACES: zif_abapgit_sap_package.

  PRIVATE SECTION.
    CONSTANTS: c_top TYPE devclass VALUE '$TOP',
               c_src TYPE string VALUE '/src/'.

    METHODS:
      setup,
      teardown,
      prefix1 FOR TESTING RAISING zcx_abapgit_exception,
      prefix2 FOR TESTING RAISING zcx_abapgit_exception,
      prefix_error1 FOR TESTING RAISING zcx_abapgit_exception,
      full1 FOR TESTING RAISING zcx_abapgit_exception,
      full2 FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.                    "ltcl_convert DEFINITION

CLASS ltcl_folder_logic IMPLEMENTATION.

  METHOD zif_abapgit_sap_package~list_subpackages.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~list_superpackages.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~read_parent.
    rv_parentcl = '$TOP'.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~create_child.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~exists.
    rv_bool = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~are_changes_recorded_in_tr_req.
    RETURN.
  ENDMETHOD.

  METHOD setup.
    FIELD-SYMBOLS: <ls_inject> LIKE LINE OF zcl_abapgit_sap_package=>gt_injected.

    CLEAR zcl_abapgit_sap_package=>gt_injected.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '$TOP'.
    <ls_inject>-object  = me.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '$TOP_FOO'.
    <ls_inject>-object  = me.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '$FOOBAR'.
    <ls_inject>-object  = me.
  ENDMETHOD.

  METHOD teardown.
    CLEAR zcl_abapgit_sap_package=>gt_injected.
  ENDMETHOD.

  METHOD prefix1.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_package  = c_top
      iv_path     = c_src ).
  ENDMETHOD.

  METHOD prefix2.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_package  = '$TOP_FOO'
      iv_path     = '/src/foo/' ).
  ENDMETHOD.

  METHOD prefix_error1.
* PREFIX mode, top package is $TOP, so all subpackages should be named $TOP_something
    TRY.
        ltcl_folder_logic_helper=>test(
          iv_starting = c_src
          iv_top      = c_top
          iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
          iv_package  = '$FOOBAR'
          iv_path     = '/src/' ).
        cl_abap_unit_assert=>fail( 'Error expected' ).
      CATCH zcx_abapgit_exception ##NO_HANDLER.
    ENDTRY.
  ENDMETHOD.

  METHOD full1.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-full
      iv_package  = c_top
      iv_path     = c_src ).
  ENDMETHOD.

  METHOD full2.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-full
      iv_package  = '$TOP_FOO'
      iv_path     = '/src/top_foo/' ).
  ENDMETHOD.

ENDCLASS.

CLASS ltcl_folder_logic_namespaces DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL.

  PUBLIC SECTION.
    INTERFACES: zif_abapgit_sap_package.

  PRIVATE SECTION.
    CONSTANTS: c_top TYPE devclass VALUE '/TEST/TOOLS',
               c_src TYPE string VALUE '/src/'.

    METHODS:
      setup,
      teardown,
      prefix1 FOR TESTING RAISING zcx_abapgit_exception,
      prefix2 FOR TESTING RAISING zcx_abapgit_exception,
      full1 FOR TESTING RAISING zcx_abapgit_exception,
      full2 FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.                    "ltcl_convert DEFINITION

CLASS ltcl_folder_logic_namespaces IMPLEMENTATION.

  METHOD zif_abapgit_sap_package~list_subpackages.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~list_superpackages.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~are_changes_recorded_in_tr_req.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~read_parent.
    rv_parentcl = c_top.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~create_child.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~exists.
    rv_bool = abap_true.
  ENDMETHOD.

  METHOD setup.
    FIELD-SYMBOLS: <ls_inject> LIKE LINE OF zcl_abapgit_sap_package=>gt_injected.

    CLEAR zcl_abapgit_sap_package=>gt_injected.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '/TEST/TOOLS'.
    <ls_inject>-object  = me.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '/TEST/T1'.
    <ls_inject>-object  = me.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '/TEST/TOOLS_T1'.
    <ls_inject>-object  = me.
  ENDMETHOD.

  METHOD teardown.
    CLEAR zcl_abapgit_sap_package=>gt_injected.
  ENDMETHOD.

  METHOD prefix1.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_package  = c_top
      iv_path     = c_src ).
  ENDMETHOD.

  METHOD prefix2.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_package  = '/TEST/TOOLS_T1'
      iv_path     = '/src/t1/' ).
  ENDMETHOD.

  METHOD full1.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-full
      iv_package  = c_top
      iv_path     = c_src ).
  ENDMETHOD.

  METHOD full2.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-full
      iv_package  = '/TEST/T1'
      iv_path     = '/src/#test#t1/' ).
  ENDMETHOD.

ENDCLASS.

CLASS ltcl_folder_logic_helper DEFINITION FOR TESTING FINAL.

  PUBLIC SECTION.
    CLASS-METHODS: test
      IMPORTING
                iv_starting TYPE string
                iv_top      TYPE devclass
                iv_logic    TYPE string
                iv_package  TYPE devclass
                iv_path     TYPE string
      RAISING   zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_folder_logic_helper IMPLEMENTATION.

  METHOD test.

    DATA: lv_path    TYPE string,
          lv_package TYPE devclass,
          lo_dot     TYPE REF TO zcl_abapgit_dot_abapgit.

    lo_dot = zcl_abapgit_dot_abapgit=>build_default( ).
    lo_dot->set_starting_folder( iv_starting ).
    lo_dot->set_folder_logic( iv_logic ).

    lv_package = zcl_abapgit_folder_logic=>path_to_package(
      iv_top  = iv_top
      io_dot  = lo_dot
      iv_path = iv_path ).

    lv_path = zcl_abapgit_folder_logic=>package_to_path(
      iv_top     = iv_top
      io_dot     = lo_dot
      iv_package = iv_package ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_package
      exp = iv_package ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_path
      exp = iv_path ).

  ENDMETHOD.

ENDCLASS.

CLASS ltcl_folder_logic DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL.

  PUBLIC SECTION.
    INTERFACES: zif_abapgit_sap_package.

  PRIVATE SECTION.
    CONSTANTS: c_top TYPE devclass VALUE '$TOP',
               c_src TYPE string VALUE '/src/'.

    METHODS:
      setup,
      teardown,
      prefix1 FOR TESTING RAISING zcx_abapgit_exception,
      prefix2 FOR TESTING RAISING zcx_abapgit_exception,
      prefix_error1 FOR TESTING RAISING zcx_abapgit_exception,
      full1 FOR TESTING RAISING zcx_abapgit_exception,
      full2 FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.                    "ltcl_convert DEFINITION

CLASS ltcl_folder_logic IMPLEMENTATION.

  METHOD zif_abapgit_sap_package~list_subpackages.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~list_superpackages.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~read_parent.
    rv_parentcl = '$TOP'.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~create_child.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~exists.
    rv_bool = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~are_changes_recorded_in_tr_req.
    RETURN.
  ENDMETHOD.

  METHOD setup.
    FIELD-SYMBOLS: <ls_inject> LIKE LINE OF zcl_abapgit_sap_package=>gt_injected.

    CLEAR zcl_abapgit_sap_package=>gt_injected.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '$TOP'.
    <ls_inject>-object  = me.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '$TOP_FOO'.
    <ls_inject>-object  = me.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '$FOOBAR'.
    <ls_inject>-object  = me.
  ENDMETHOD.

  METHOD teardown.
    CLEAR zcl_abapgit_sap_package=>gt_injected.
  ENDMETHOD.

  METHOD prefix1.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_package  = c_top
      iv_path     = c_src ).
  ENDMETHOD.

  METHOD prefix2.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_package  = '$TOP_FOO'
      iv_path     = '/src/foo/' ).
  ENDMETHOD.

  METHOD prefix_error1.
* PREFIX mode, top package is $TOP, so all subpackages should be named $TOP_something
    TRY.
        ltcl_folder_logic_helper=>test(
          iv_starting = c_src
          iv_top      = c_top
          iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
          iv_package  = '$FOOBAR'
          iv_path     = '/src/' ).
        cl_abap_unit_assert=>fail( 'Error expected' ).
      CATCH zcx_abapgit_exception ##NO_HANDLER.
    ENDTRY.
  ENDMETHOD.

  METHOD full1.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-full
      iv_package  = c_top
      iv_path     = c_src ).
  ENDMETHOD.

  METHOD full2.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-full
      iv_package  = '$TOP_FOO'
      iv_path     = '/src/top_foo/' ).
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~get_transport_type.
    RETURN.
  ENDMETHOD.

ENDCLASS.

CLASS ltcl_folder_logic_namespaces DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL.

  PUBLIC SECTION.
    INTERFACES: zif_abapgit_sap_package.

  PRIVATE SECTION.
    CONSTANTS: c_top TYPE devclass VALUE '/TEST/TOOLS',
               c_src TYPE string VALUE '/src/'.

    METHODS:
      setup,
      teardown,
      prefix1 FOR TESTING RAISING zcx_abapgit_exception,
      prefix2 FOR TESTING RAISING zcx_abapgit_exception,
      full1 FOR TESTING RAISING zcx_abapgit_exception,
      full2 FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.                    "ltcl_convert DEFINITION

CLASS ltcl_folder_logic_namespaces IMPLEMENTATION.

  METHOD zif_abapgit_sap_package~list_subpackages.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~list_superpackages.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~are_changes_recorded_in_tr_req.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~read_parent.
    rv_parentcl = c_top.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~create_child.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~exists.
    rv_bool = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_sap_package~get_transport_type.
    RETURN.
  ENDMETHOD.

  METHOD setup.
    FIELD-SYMBOLS: <ls_inject> LIKE LINE OF zcl_abapgit_sap_package=>gt_injected.

    CLEAR zcl_abapgit_sap_package=>gt_injected.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '/TEST/TOOLS'.
    <ls_inject>-object  = me.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '/TEST/T1'.
    <ls_inject>-object  = me.

    APPEND INITIAL LINE TO zcl_abapgit_sap_package=>gt_injected ASSIGNING <ls_inject>.
    <ls_inject>-package = '/TEST/TOOLS_T1'.
    <ls_inject>-object  = me.
  ENDMETHOD.

  METHOD teardown.
    CLEAR zcl_abapgit_sap_package=>gt_injected.
  ENDMETHOD.

  METHOD prefix1.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_package  = c_top
      iv_path     = c_src ).
  ENDMETHOD.

  METHOD prefix2.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_package  = '/TEST/TOOLS_T1'
      iv_path     = '/src/t1/' ).
  ENDMETHOD.

  METHOD full1.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-full
      iv_package  = c_top
      iv_path     = c_src ).
  ENDMETHOD.

  METHOD full2.
    ltcl_folder_logic_helper=>test(
      iv_starting = c_src
      iv_top      = c_top
      iv_logic    = zif_abapgit_dot_abapgit=>c_folder_logic-full
      iv_package  = '/TEST/T1'
      iv_path     = '/src/#test#t1/' ).
  ENDMETHOD.

ENDCLASS.

implement missing interface methods

implement missing interface methods


"! Progress reporter logger
"!

"! This logger shows all log entries in the SAP GUI progress indicator (status bar), using
"! CL_PROGRESS_INDICATOR internally (which itself is a wrapper class for function module
"! SAPGUI_PROGRESS_INDICATOR.
"!

"!

"! Keep in mind that sending status messages using the progress indicator to the front end may cause
"! severe performance problems. If that is a concern supply IV_OUTPUT_IMMEDIATELY in the
"! constructor with ABAP_FALSE.
"!

class ZCL_ALOG_PROGRESS_REP_LOGGER definition
  public
  inheriting from ZCL_ALOG_MSG_LOGGER_BASE
  create public .

public section.

      "! @parameter iv_output_immediately | Output log entries immediately / always
  methods CONSTRUCTOR
    importing
      !IV_OUTPUT_IMMEDIATELY type ABAP_BOOL default ABAP_TRUE .
  methods SET_TOTAL_ENTRIES
    importing
      !IV_TOTAL_ENTRIES type INT4 .
  methods SET_ACTUAL_ENTRIES
    importing
      !IV_ACTUAL_ENTRIES type INT4 .
protected section.

  methods ENTRY_INTERNAL
    redefinition .
  methods ENTRY_MSG_INTERNAL
    redefinition .
private section.

  data MV_OUTPUT_IMMEDIATELY type ABAP_BOOL .
  data MV_TOTAL_ENTRIES type INT4 .
  data MV_ACTUAL_ENTRIES type INT4 .
ENDCLASS.

CLASS ZCL_ALOG_PROGRESS_REP_LOGGER IMPLEMENTATION.

  METHOD constructor.
    super->constructor( ).
    mv_output_immediately = iv_output_immediately.
* EP Set actual and default maxinum counter
    SET_actual_ENTRIES( 1 ).
    SET_TOTAL_ENTRIES( 100 ).

  ENDMETHOD.

  METHOD entry_internal.
    cl_progress_indicator=>progress_indicate( i_text               = iv_text
                                              i_output_immediately = mv_output_immediately
* EP use maximun message
*                                              i_processed          = 1
*                                              i_total              = 100 ).
                                              i_processed          = MV_ACTUAL_ENTRIES
                                              i_total              = MV_TOTAL_ENTRIES ).
  ENDMETHOD.

  METHOD entry_msg_internal.
    cl_progress_indicator=>progress_indicate( i_msgid              = iv_msgid
                                              i_msgno              = iv_msgno
                                              i_msgv1              = iv_msgv1
                                              i_msgv2              = iv_msgv2
                                              i_msgv3              = iv_msgv3
                                              i_msgv4              = iv_msgv4
                                              i_output_immediately = mv_output_immediately
                                              i_processed          = 1
                                              i_total              = 100 ).
  ENDMETHOD.

  method SET_ACTUAL_ENTRIES.
    mv_actual_ENTRIES = iv_actual_ENTRIES.
  endmethod.

  method SET_TOTAL_ENTRIES.
    mv_TOTAL_ENTRIES = iv_TOTAL_ENTRIES.
  endmethod.
ENDCLASS.

"! Progress reporter logger
"!

"! This logger shows all log entries in the SAP GUI progress indicator (status bar), using
"! CL_PROGRESS_INDICATOR internally (which itself is a wrapper class for function module
"! SAPGUI_PROGRESS_INDICATOR.
"!

"!

"! Keep in mind that sending status messages using the progress indicator to the front end may cause
"! severe performance problems. If that is a concern supply IV_OUTPUT_IMMEDIATELY in the
"! constructor with ABAP_FALSE.
"!

CLASS zcl_alog_progress_rep_logger DEFINITION
  PUBLIC
  INHERITING FROM zcl_alog_msg_logger_base
  CREATE PUBLIC .

  PUBLIC SECTION.

    "! @parameter iv_output_immediately | Output log entries immediately / always
    METHODS constructor
      IMPORTING
        !iv_output_immediately TYPE abap_bool DEFAULT abap_true .
    METHODS set_total_entries
      IMPORTING
        !iv_total_entries TYPE int4 .
    METHODS set_actual_entries
      IMPORTING
        !iv_actual_entries TYPE int4 .
  PROTECTED SECTION.

    METHODS entry_internal
         REDEFINITION .
    METHODS entry_msg_internal
         REDEFINITION .
  PRIVATE SECTION.

    DATA mv_output_immediately TYPE abap_bool .
    DATA mv_total_entries TYPE int4 .
    DATA mv_actual_entries TYPE int4 .
ENDCLASS.

CLASS ZCL_ALOG_PROGRESS_REP_LOGGER IMPLEMENTATION.

  METHOD constructor.
    super->constructor( ).
    mv_output_immediately = iv_output_immediately.
* EP Set actual and default maxinum counter
    set_actual_entries( 1 ).
    set_total_entries( 100 ).

  ENDMETHOD.

  METHOD entry_internal.
    cl_progress_indicator=>progress_indicate( i_text               = iv_text
                                              i_output_immediately = mv_output_immediately
* EP use maximun message
*                                              i_processed          = 1
*                                              i_total              = 100 ).
                                              i_processed          = mv_actual_entries
                                              i_total              = mv_total_entries ).
  ENDMETHOD.

  METHOD entry_msg_internal.
    cl_progress_indicator=>progress_indicate( i_msgid              = iv_msgid
                                              i_msgno              = iv_msgno
                                              i_msgv1              = iv_msgv1
                                              i_msgv2              = iv_msgv2
                                              i_msgv3              = iv_msgv3
                                              i_msgv4              = iv_msgv4
                                              i_output_immediately = mv_output_immediately
                                              i_processed          = 1
                                              i_total              = 100 ).
  ENDMETHOD.

  METHOD set_actual_entries.
    mv_actual_entries = iv_actual_entries.
  ENDMETHOD.

  METHOD set_total_entries.
    mv_total_entries = iv_total_entries.
  ENDMETHOD.
ENDCLASS.

Fix indentation in progress bar

Fix indentation in progress bar


CLASS ltcl_test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.

  PRIVATE SECTION.

    METHODS:
      repo_host FOR TESTING RAISING zcx_abapgit_exception,
      repo_name1 FOR TESTING RAISING zcx_abapgit_exception,
      repo_name2 FOR TESTING RAISING zcx_abapgit_exception,
      repo_name3 FOR TESTING RAISING zcx_abapgit_exception,
      repo_name4 FOR TESTING RAISING zcx_abapgit_exception,
      repo_name5 FOR TESTING RAISING zcx_abapgit_exception,
      repo_error FOR TESTING,
      url_validate1 FOR TESTING,
      url_validate2 FOR TESTING,
      url_validate3 FOR TESTING.

ENDCLASS.

CLASS ltcl_test IMPLEMENTATION.

  METHOD repo_error.

    TRY.
        zcl_abapgit_url=>host( 'not a real url' ).
        cl_abap_unit_assert=>fail( ).
      CATCH zcx_abapgit_exception.                      "#EC NO_HANDLER
    ENDTRY.

  ENDMETHOD.

  METHOD repo_host.

    DATA: lv_host TYPE string.

    lv_host = zcl_abapgit_url=>host( 'https://github.com/larshp/Foobar.git' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'https://github.com'
        act = lv_host ).

  ENDMETHOD.

  METHOD repo_name1.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://github.com/larshp/Foobar.git' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'Foobar'
        act = lv_name ).

  ENDMETHOD.

  METHOD repo_name2.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://git.hanatrial.ondemand.com/p12345trial/yay' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'yay'
        act = lv_name ).

  ENDMETHOD.

  METHOD repo_name3.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://github.com/larshp/Foobar/' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'Foobar'
        act = lv_name ).

  ENDMETHOD.

  METHOD repo_name4.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://github.com/larshp/foo-bar/' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'foo-bar'
        act = lv_name ).

  ENDMETHOD.

  METHOD repo_name5.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://github.com/larshp/foo_bar/' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'foo_bar'
        act = lv_name ).

  ENDMETHOD.

  METHOD url_validate1.

    TRY.
        zcl_abapgit_url=>validate( 'http://github.com/larshp/Foobar.git' ).
      CATCH zcx_abapgit_exception.                      "#EC NO_HANDLER
        cl_abap_unit_assert=>fail( ).
    ENDTRY.

  ENDMETHOD.

  METHOD url_validate2.

    TRY.
        zcl_abapgit_url=>validate( 'https://github.com/larshp/Foobar.git' ).
      CATCH zcx_abapgit_exception.                      "#EC NO_HANDLER
        cl_abap_unit_assert=>fail( ).
    ENDTRY.

  ENDMETHOD.

  METHOD url_validate3.

    TRY.
        zcl_abapgit_url=>validate( 'XYZ://github.com/larshp/Foobar.git' ).
        cl_abap_unit_assert=>fail( ).
      CATCH zcx_abapgit_exception.                      "#EC NO_HANDLER
    ENDTRY.

  ENDMETHOD.

ENDCLASS.

CLASS ltcl_test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.

  PRIVATE SECTION.

    METHODS:
      repo_host FOR TESTING RAISING zcx_abapgit_exception,
      repo_name1 FOR TESTING RAISING zcx_abapgit_exception,
      repo_name2 FOR TESTING RAISING zcx_abapgit_exception,
      repo_name3 FOR TESTING RAISING zcx_abapgit_exception,
      repo_name4 FOR TESTING RAISING zcx_abapgit_exception,
      repo_name5 FOR TESTING RAISING zcx_abapgit_exception,
      repo_error FOR TESTING,
      url_validate1 FOR TESTING,
      url_validate2 FOR TESTING,
      url_validate3 FOR TESTING.

ENDCLASS.

CLASS ltcl_test IMPLEMENTATION.

  METHOD repo_error.

    TRY.
        zcl_abapgit_url=>host( 'not a real url' ).
        cl_abap_unit_assert=>fail( ).
      CATCH zcx_abapgit_exception.                      "#EC NO_HANDLER
    ENDTRY.

  ENDMETHOD.

  METHOD repo_host.

    DATA: lv_host TYPE string.

    lv_host = zcl_abapgit_url=>host( 'https://github.com/larshp/Foobar.git' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'https://github.com'
        act = lv_host ).

  ENDMETHOD.

  METHOD repo_name1.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://github.com/larshp/Foobar.git' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'Foobar'
        act = lv_name ).

  ENDMETHOD.

  METHOD repo_name2.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://git.hanatrial.ondemand.com/p12345trial/yay' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'yay'
        act = lv_name ).

  ENDMETHOD.

  METHOD repo_name3.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://github.com/larshp/Foobar/' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'Foobar'
        act = lv_name ).

  ENDMETHOD.

  METHOD repo_name4.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://github.com/larshp/foo-bar/' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'foo-bar'
        act = lv_name ).

  ENDMETHOD.

  METHOD repo_name5.

    DATA: lv_name TYPE string.

    lv_name = zcl_abapgit_url=>name( 'https://github.com/larshp/foo_bar/' ).

    cl_abap_unit_assert=>assert_equals(
        exp = 'foo_bar'
        act = lv_name ).

  ENDMETHOD.

  METHOD url_validate1.

    TRY.
        zcl_abapgit_url=>validate( 'http://github.com/larshp/Foobar.git' ).
      CATCH zcx_abapgit_exception.
        cl_abap_unit_assert=>fail( ).
    ENDTRY.

  ENDMETHOD.

  METHOD url_validate2.

    TRY.
        zcl_abapgit_url=>validate( 'https://github.com/larshp/Foobar.git' ).
      CATCH zcx_abapgit_exception.
        cl_abap_unit_assert=>fail( ).
    ENDTRY.

  ENDMETHOD.

  METHOD url_validate3.

    TRY.
        zcl_abapgit_url=>validate( 'XYZ://github.com/larshp/Foobar.git' ).
        cl_abap_unit_assert=>fail( ).
      CATCH zcx_abapgit_exception.                      "#EC NO_HANDLER
    ENDTRY.

  ENDMETHOD.

ENDCLASS.

remove NO_HANDLER pseudo comments when handlers exist (#3846)

* remove NO_HANDLER pseudo comments when handlers exist

* Update zcl_abapgit_url.clas.testclasses.abap


CLASS zcl_abapgit_object_scvi DEFINITION
  PUBLIC
  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_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.

    DATA: lv_text TYPE natxt.

    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    = 01.
    IF sy-subrc <> 0.
      MESSAGE e413(ms) WITH ls_screen_variant-shdsvci-scvariant INTO lv_text.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

    corr_insert( iv_package = 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_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~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.

*   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.

    SELECT *
    FROM shdgxtcode
    INTO TABLE ls_screen_variant-shdgxtcode[]
    WHERE scvariant = ls_screen_variant-shdsvci-scvariant.

    io_xml->add( iv_name = 'SCVI'
                 ig_data = ls_screen_variant ).

  ENDMETHOD.
ENDCLASS.

CLASS zcl_abapgit_object_scvi DEFINITION
  PUBLIC
  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_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.

    DATA: lv_text TYPE natxt.

    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    = 01.
    IF sy-subrc <> 0.
      MESSAGE e413(ms) WITH ls_screen_variant-shdsvci-scvariant INTO lv_text.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

    corr_insert( iv_package = 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_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~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.

*   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.

Sort tables to avoid diffs (#5745)

SCVI: Sort tables to avoid diffs (#5745)