CLASS zcl_abapgit_object_auth DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

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

ENDCLASS.

CLASS zcl_abapgit_object_auth IMPLEMENTATION.

  METHOD zif_abapgit_object~changed_by.
* looks like "changed by user" is not stored in the database
    rv_user = c_user_unknown.
  ENDMETHOD.

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

  METHOD zif_abapgit_object~delete.

    DATA: lv_fieldname TYPE authx-fieldname.

    lv_fieldname = ms_item-obj_name.

* there is a bug in SAP standard, the TADIR entries are not deleted
* when the AUTH object is deleted in transaction SU20
    CALL FUNCTION 'SUSR_AUTF_DELETE_FIELD'
      EXPORTING
        fieldname           = lv_fieldname
      EXCEPTIONS
        delete_not_possible = 1
        field_in_use        = 2
        not_existing        = 3
        no_authority        = 4
        OTHERS              = 5.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error from SUSR_AUTF_DELETE_FIELD' ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_object~deserialize.
* see include LSAUT_FIELDF02

    DATA: ls_authx TYPE authx,
          lo_auth  TYPE REF TO cl_auth_tools.

    io_xml->read( EXPORTING iv_name = 'AUTHX'
                  CHANGING cg_data = ls_authx ).

    tadir_insert( iv_package ).

    CREATE OBJECT lo_auth.

    IF lo_auth->add_afield_to_trkorr( ls_authx-fieldname ) <> 0.
      zcx_abapgit_exception=>raise( 'Error deserializing AUTH' ).
    ENDIF.

    MODIFY authx FROM ls_authx.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'Error deserializing AUTH' ).
    ENDIF.

    CALL FUNCTION 'DB_COMMIT'.
    lo_auth->set_authfld_info_from_db( ls_authx-fieldname ).

  ENDMETHOD.

  METHOD zif_abapgit_object~exists.

    DATA: lv_fieldname TYPE authx-fieldname.

    SELECT SINGLE fieldname FROM authx
      INTO lv_fieldname
      WHERE fieldname = ms_item-obj_name.               "#EC CI_GENBUFF
    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.

  METHOD zif_abapgit_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.

  METHOD zif_abapgit_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    DATA: lv_field TYPE fieldname.

    lv_field = ms_item-obj_name.

* TODO, this function module does not exist in 702
    CALL FUNCTION 'SU20_MAINTAIN_SNGL'
      EXPORTING
        id_field    = lv_field
        id_wbo_mode = abap_false.

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA: ls_authx TYPE authx.

    SELECT SINGLE * FROM authx INTO ls_authx
      WHERE fieldname = ms_item-obj_name.               "#EC CI_GENBUFF
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    io_xml->add( iv_name = 'AUTHX'
                 ig_data = ls_authx ).

  ENDMETHOD.

  METHOD zif_abapgit_object~is_locked.

    rv_is_locked = abap_false.

  ENDMETHOD.

ENDCLASS.

CLASS zcl_abapgit_object_auth DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.
    METHODS constructor
      IMPORTING
        is_item     TYPE zif_abapgit_definitions=>ty_item
        iv_language TYPE spras.
  PRIVATE SECTION.
    DATA: mv_fieldname TYPE authx-fieldname.

ENDCLASS.

CLASS zcl_abapgit_object_auth IMPLEMENTATION.

  METHOD constructor.

    super->constructor( is_item     = is_item
                        iv_language = iv_language ).

    mv_fieldname = ms_item-obj_name.

  ENDMETHOD.

  METHOD zif_abapgit_object~changed_by.
* looks like "changed by user" is not stored in the database
    rv_user = c_user_unknown.
  ENDMETHOD.

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

  METHOD zif_abapgit_object~delete.

    " there is a bug in SAP standard, the TADIR entries are not deleted
    " when the AUTH object is deleted in transaction SU20

    " FM SUSR_AUTF_DELETE_FIELD calls the UI, therefore we reimplement its logic

    DATA:
      lt_objlst TYPE susr_t_xuobject,
      lo_auth   TYPE REF TO cl_auth_tools,
      lv_dummy  TYPE string.

    " authority check
    CREATE OBJECT lo_auth.
    IF lo_auth->authority_check_suso( actvt     = '06'
                                      fieldname = mv_fieldname ) <> 0.
      MESSAGE e463(01) WITH mv_fieldname INTO lv_dummy.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

    " if field is used check
    lt_objlst = lo_auth->suso_where_used_afield( mv_fieldname ).
    IF lt_objlst IS NOT INITIAL.
      MESSAGE i453(01) WITH mv_fieldname INTO lv_dummy.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

    " collect fieldname into a transport task
    IF lo_auth->add_afield_to_trkorr( mv_fieldname ) <> 0.
      "no transport -> no deletion
      MESSAGE e507(0m) INTO lv_dummy.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

    DELETE FROM authx WHERE fieldname = mv_fieldname.
    IF sy-subrc <> 0.
      MESSAGE e507(0m) INTO DATA(dummy).
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_object~deserialize.
* see include LSAUT_FIELDF02

    DATA: ls_authx TYPE authx,
          lo_auth  TYPE REF TO cl_auth_tools.

    io_xml->read( EXPORTING iv_name = 'AUTHX'
                  CHANGING cg_data = ls_authx ).

    tadir_insert( iv_package ).

    CREATE OBJECT lo_auth.

    IF lo_auth->add_afield_to_trkorr( ls_authx-fieldname ) <> 0.
      zcx_abapgit_exception=>raise( 'Error deserializing AUTH' ).
    ENDIF.

    MODIFY authx FROM ls_authx.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'Error deserializing AUTH' ).
    ENDIF.

    CALL FUNCTION 'DB_COMMIT'.
    lo_auth->set_authfld_info_from_db( ls_authx-fieldname ).

  ENDMETHOD.

  METHOD zif_abapgit_object~exists.

    SELECT SINGLE fieldname FROM authx
      INTO mv_fieldname
      WHERE fieldname = ms_item-obj_name.               "#EC CI_GENBUFF
    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.

  METHOD zif_abapgit_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.

  METHOD zif_abapgit_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

* TODO, this function module does not exist in 702
    CALL FUNCTION 'SU20_MAINTAIN_SNGL'
      EXPORTING
        id_field    = mv_fieldname
        id_wbo_mode = abap_false.

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA: ls_authx TYPE authx.

    SELECT SINGLE * FROM authx INTO ls_authx
      WHERE fieldname = ms_item-obj_name.               "#EC CI_GENBUFF
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    io_xml->add( iv_name = 'AUTHX'
                 ig_data = ls_authx ).

  ENDMETHOD.

  METHOD zif_abapgit_object~is_locked.

    rv_is_locked = abap_false.

  ENDMETHOD.

ENDCLASS.

remove delete popups

AUTH: remove delete popups


CLASS ltcl_determine_max_threads DEFINITION DEFERRED.
CLASS zcl_abapgit_serialize DEFINITION LOCAL FRIENDS ltcl_determine_max_threads.

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

  PRIVATE SECTION.
    DATA:
      mo_cut TYPE REF TO zcl_abapgit_serialize.

    METHODS:
      setup,
      determine_max_threads FOR TESTING RAISING zcx_abapgit_exception,
      force FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_determine_max_threads IMPLEMENTATION.

  METHOD setup.
    TRY.
        CREATE OBJECT mo_cut.
      CATCH zcx_abapgit_exception.
        cl_abap_unit_assert=>fail( 'Error creating serializer' ).
    ENDTRY.
  ENDMETHOD.

  METHOD determine_max_threads.

    DATA: lv_threads TYPE i.

    lv_threads = mo_cut->determine_max_threads( ).

    cl_abap_unit_assert=>assert_differs(
      act = lv_threads
      exp = 0 ).

  ENDMETHOD.

  METHOD force.

    DATA: lv_threads TYPE i.

    lv_threads = mo_cut->determine_max_threads( abap_true ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_threads
      exp = 1 ).

  ENDMETHOD.

ENDCLASS.

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

  PRIVATE SECTION.
    DATA:
      mo_dot TYPE REF TO zcl_abapgit_dot_abapgit,
      mo_cut TYPE REF TO zcl_abapgit_serialize.

    METHODS:
      setup,
      test FOR TESTING RAISING zcx_abapgit_exception,
      unsupported FOR TESTING RAISING zcx_abapgit_exception,
      ignored FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_serialize IMPLEMENTATION.

  METHOD setup.

    mo_dot = zcl_abapgit_dot_abapgit=>build_default( ).

    TRY.
        CREATE OBJECT mo_cut
          EXPORTING
            io_dot_abapgit = mo_dot.
      CATCH zcx_abapgit_exception.
        cl_abap_unit_assert=>fail( 'Error creating serializer' ).
    ENDTRY.
  ENDMETHOD.

  METHOD test.

    DATA: lt_tadir      TYPE zif_abapgit_definitions=>ty_tadir_tt,
          lt_sequential TYPE zif_abapgit_definitions=>ty_files_item_tt,
          lt_parallel   TYPE zif_abapgit_definitions=>ty_files_item_tt.

    FIELD-SYMBOLS: <ls_tadir> LIKE LINE OF lt_tadir.

    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'PROG'.
    <ls_tadir>-obj_name = 'RSABAPPROGRAM'.
    <ls_tadir>-devclass = 'PACKAGE'.
    <ls_tadir>-path     = 'foobar'.

    lt_sequential = mo_cut->serialize(
      it_tadir            = lt_tadir
      iv_force_sequential = abap_true ).

    lt_parallel = mo_cut->serialize(
      it_tadir            = lt_tadir
      iv_force_sequential = abap_false ).

    cl_abap_unit_assert=>assert_equals(
      act = lt_sequential
      exp = lt_parallel ).

  ENDMETHOD.

  METHOD unsupported.

    DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt,
          ls_msg   TYPE zif_abapgit_log=>ty_log_out,
          lt_msg   TYPE zif_abapgit_log=>ty_log_outs,
          li_log1  TYPE REF TO zif_abapgit_log,
          li_log2  TYPE REF TO zif_abapgit_log.

    FIELD-SYMBOLS: <ls_tadir> LIKE LINE OF lt_tadir.

    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'ABCD'.
    <ls_tadir>-obj_name = 'OBJECT'.

    CREATE OBJECT li_log1 TYPE zcl_abapgit_log.
    mo_cut->serialize(
      it_tadir            = lt_tadir
      ii_log              = li_log1
      iv_force_sequential = abap_true ).

    CREATE OBJECT li_log2 TYPE zcl_abapgit_log.
    mo_cut->serialize(
      it_tadir            = lt_tadir
      ii_log              = li_log2
      iv_force_sequential = abap_false ).

    lt_msg = li_log1->get_messages( ).
    READ TABLE lt_msg INTO ls_msg INDEX 1.
    cl_abap_unit_assert=>assert_subrc( ).

    cl_abap_unit_assert=>assert_char_cp(
      act = ls_msg-text
      exp = '*Object type ABCD not supported*' ).

    lt_msg = li_log2->get_messages( ).
    READ TABLE lt_msg INTO ls_msg INDEX 1.
    cl_abap_unit_assert=>assert_subrc( ).

    cl_abap_unit_assert=>assert_char_cp(
      act = ls_msg-text
      exp = '*Object type ABCD not supported*' ).

  ENDMETHOD.

  METHOD ignored.

    DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt,
          ls_msg   TYPE zif_abapgit_log=>ty_log_out,
          lt_msg   TYPE zif_abapgit_log=>ty_log_outs,
          li_log1  TYPE REF TO zif_abapgit_log,
          li_log2  TYPE REF TO zif_abapgit_log.

    FIELD-SYMBOLS: <ls_tadir> LIKE LINE OF lt_tadir.

    mo_dot->add_ignore(
      iv_path     = '/src/'
      iv_filename = 'zcl_test_ignore.clas.*' ).

    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'CLAS'.
    <ls_tadir>-obj_name = 'ZCL_TEST'.
    <ls_tadir>-devclass = '$ZTEST'.

    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'CLAS'.
    <ls_tadir>-obj_name = 'ZCL_TEST_IGNORE'.
    <ls_tadir>-devclass = '$ZTEST'.

    CREATE OBJECT li_log1 TYPE zcl_abapgit_log.
    mo_cut->serialize(
      iv_package          = '$ZTEST'
      it_tadir            = lt_tadir
      ii_log              = li_log1
      iv_force_sequential = abap_true ).

    CREATE OBJECT li_log2 TYPE zcl_abapgit_log.
    mo_cut->serialize(
      iv_package          = '$ZTEST'
      it_tadir            = lt_tadir
      ii_log              = li_log2
      iv_force_sequential = abap_false ).

    lt_msg = li_log1->get_messages( ).
    READ TABLE lt_msg INTO ls_msg INDEX 1.
    cl_abap_unit_assert=>assert_subrc( ).

    cl_abap_unit_assert=>assert_char_cp(
      act = ls_msg-text
      exp = '*Object CLAS ZCL_TEST_IGNORE ignored*' ).

    lt_msg = li_log2->get_messages( ).
    READ TABLE lt_msg INTO ls_msg INDEX 1.
    cl_abap_unit_assert=>assert_subrc( ).

    cl_abap_unit_assert=>assert_char_cp(
      act = ls_msg-text
      exp = '*Object CLAS ZCL_TEST_IGNORE ignored*' ).

  ENDMETHOD.

ENDCLASS.

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

  PRIVATE SECTION.
    DATA:
      mo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit,
      mo_cut         TYPE REF TO zcl_abapgit_serialize.

    METHODS:
      setup,
      test FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_i18n IMPLEMENTATION.

  METHOD setup.
    DATA ls_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit.

    " Main language: English, Translations: German
    ls_data-master_language = 'E'.
    INSERT 'DE' INTO TABLE ls_data-i18n_languages.

    TRY.
        CREATE OBJECT mo_dot_abapgit
          EXPORTING
            is_data = ls_data.

        CREATE OBJECT mo_cut
          EXPORTING
            io_dot_abapgit = mo_dot_abapgit.
      CATCH zcx_abapgit_exception.
        cl_abap_unit_assert=>fail( 'Error creating serializer' ).
    ENDTRY.
  ENDMETHOD.

  METHOD test.

    DATA: lt_tadir      TYPE zif_abapgit_definitions=>ty_tadir_tt,
          lt_result     TYPE zif_abapgit_definitions=>ty_files_item_tt,
          lv_xml        TYPE string,
          lo_input      TYPE REF TO zcl_abapgit_xml_input,
          ls_dd02v      TYPE dd02v,
          lt_i18n_langs TYPE TABLE OF langu.

    FIELD-SYMBOLS: <ls_tadir>      LIKE LINE OF lt_tadir,
                   <ls_result>     LIKE LINE OF lt_result,
                   <ls_i18n_langs> LIKE LINE OF lt_i18n_langs.

    " Assumption: Table T100 has English and German description
    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'TABL'.
    <ls_tadir>-obj_name = 'T100'.
    <ls_tadir>-devclass = 'PACKAGE'.
    <ls_tadir>-path     = 'foobar'.

    lt_result = mo_cut->serialize( lt_tadir ).

    cl_abap_unit_assert=>assert_equals(
      act = lines( lt_result )
      exp = 1 ).

    READ TABLE lt_result ASSIGNING <ls_result> INDEX 1.
    ASSERT sy-subrc = 0.

    lv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( <ls_result>-file-data ).

    CREATE OBJECT lo_input
      EXPORTING
        iv_xml = lv_xml.

    lo_input->zif_abapgit_xml_input~read( EXPORTING iv_name = 'DD02V'
                                          CHANGING  cg_data = ls_dd02v ).

    cl_abap_unit_assert=>assert_equals(
      act = ls_dd02v-ddlanguage
      exp = 'E' ).

    lo_input->zif_abapgit_xml_input~read( EXPORTING iv_name = 'I18N_LANGS'
                                          CHANGING  cg_data = lt_i18n_langs ).

    cl_abap_unit_assert=>assert_equals(
      act = lines( lt_i18n_langs )
      exp = 1 ).

    READ TABLE lt_i18n_langs ASSIGNING <ls_i18n_langs> INDEX 1.
    ASSERT sy-subrc = 0.

    cl_abap_unit_assert=>assert_equals(
      act = <ls_i18n_langs>
      exp = 'D' ).

  ENDMETHOD.
ENDCLASS.

CLASS ltcl_determine_max_threads DEFINITION DEFERRED.
CLASS zcl_abapgit_serialize DEFINITION LOCAL FRIENDS ltcl_determine_max_threads.

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

  PRIVATE SECTION.
    DATA:
      mo_cut TYPE REF TO zcl_abapgit_serialize.

    METHODS:
      setup,
      determine_max_threads FOR TESTING RAISING zcx_abapgit_exception,
      force FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_determine_max_threads IMPLEMENTATION.

  METHOD setup.
    TRY.
        CREATE OBJECT mo_cut.
      CATCH zcx_abapgit_exception.
        cl_abap_unit_assert=>fail( 'Error creating serializer' ).
    ENDTRY.
  ENDMETHOD.

  METHOD determine_max_threads.

    DATA: lv_threads TYPE i.

    lv_threads = mo_cut->determine_max_threads( ).

    cl_abap_unit_assert=>assert_differs(
      act = lv_threads
      exp = 0 ).

  ENDMETHOD.

  METHOD force.

    DATA: lv_threads TYPE i.

    lv_threads = mo_cut->determine_max_threads( abap_true ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_threads
      exp = 1 ).

  ENDMETHOD.

ENDCLASS.

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

  PRIVATE SECTION.
    DATA:
      mo_dot TYPE REF TO zcl_abapgit_dot_abapgit,
      mo_cut TYPE REF TO zcl_abapgit_serialize.

    METHODS:
      setup,
      test FOR TESTING RAISING zcx_abapgit_exception,
      unsupported FOR TESTING RAISING zcx_abapgit_exception,
      ignored FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_serialize IMPLEMENTATION.

  METHOD setup.

    mo_dot = zcl_abapgit_dot_abapgit=>build_default( ).

    TRY.
        CREATE OBJECT mo_cut
          EXPORTING
            io_dot_abapgit = mo_dot.
      CATCH zcx_abapgit_exception.
        cl_abap_unit_assert=>fail( 'Error creating serializer' ).
    ENDTRY.
  ENDMETHOD.

  METHOD test.

    DATA: lt_tadir      TYPE zif_abapgit_definitions=>ty_tadir_tt,
          lt_sequential TYPE zif_abapgit_definitions=>ty_files_item_tt,
          lt_parallel   TYPE zif_abapgit_definitions=>ty_files_item_tt.

    FIELD-SYMBOLS: <ls_tadir> LIKE LINE OF lt_tadir.

    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'PROG'.
    <ls_tadir>-obj_name = 'RSABAPPROGRAM'.
    <ls_tadir>-devclass = 'PACKAGE'.
    <ls_tadir>-path     = 'foobar'.

    lt_sequential = mo_cut->serialize(
      it_tadir            = lt_tadir
      iv_force_sequential = abap_true ).

    lt_parallel = mo_cut->serialize(
      it_tadir            = lt_tadir
      iv_force_sequential = abap_false ).

    cl_abap_unit_assert=>assert_equals(
      act = lt_sequential
      exp = lt_parallel ).

  ENDMETHOD.

  METHOD unsupported.

    DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt,
          ls_msg   TYPE zif_abapgit_log=>ty_log_out,
          lt_msg   TYPE zif_abapgit_log=>ty_log_outs,
          li_log1  TYPE REF TO zif_abapgit_log,
          li_log2  TYPE REF TO zif_abapgit_log.

    FIELD-SYMBOLS: <ls_tadir> LIKE LINE OF lt_tadir.

    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'ABCD'.
    <ls_tadir>-obj_name = 'OBJECT'.

    CREATE OBJECT li_log1 TYPE zcl_abapgit_log.
    mo_cut->serialize(
      it_tadir            = lt_tadir
      ii_log              = li_log1
      iv_force_sequential = abap_true ).

    CREATE OBJECT li_log2 TYPE zcl_abapgit_log.
    mo_cut->serialize(
      it_tadir            = lt_tadir
      ii_log              = li_log2
      iv_force_sequential = abap_false ).

    lt_msg = li_log1->get_messages( ).
    READ TABLE lt_msg INTO ls_msg INDEX 1.
    cl_abap_unit_assert=>assert_subrc( ).

    cl_abap_unit_assert=>assert_char_cp(
      act = ls_msg-text
      exp = '*Object type ABCD not supported*' ).

    lt_msg = li_log2->get_messages( ).
    READ TABLE lt_msg INTO ls_msg INDEX 1.
    cl_abap_unit_assert=>assert_subrc( ).

    cl_abap_unit_assert=>assert_char_cp(
      act = ls_msg-text
      exp = '*Object type ABCD not supported*' ).

  ENDMETHOD.

  METHOD ignored.

    DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt,
          ls_msg   TYPE zif_abapgit_log=>ty_log_out,
          lt_msg   TYPE zif_abapgit_log=>ty_log_outs,
          li_log1  TYPE REF TO zif_abapgit_log,
          li_log2  TYPE REF TO zif_abapgit_log.

    FIELD-SYMBOLS: <ls_tadir> LIKE LINE OF lt_tadir.

    mo_dot->add_ignore(
      iv_path     = '/src/'
      iv_filename = 'zcl_test_ignore.clas.*' ).

    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'CLAS'.
    <ls_tadir>-obj_name = 'ZCL_TEST'.
    <ls_tadir>-devclass = '$ZTEST'.

    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'CLAS'.
    <ls_tadir>-obj_name = 'ZCL_TEST_IGNORE'.
    <ls_tadir>-devclass = '$ZTEST'.

    CREATE OBJECT li_log1 TYPE zcl_abapgit_log.
    mo_cut->serialize(
      iv_package          = '$ZTEST'
      it_tadir            = lt_tadir
      ii_log              = li_log1
      iv_force_sequential = abap_true ).

    CREATE OBJECT li_log2 TYPE zcl_abapgit_log.
    mo_cut->serialize(
      iv_package          = '$ZTEST'
      it_tadir            = lt_tadir
      ii_log              = li_log2
      iv_force_sequential = abap_false ).

    lt_msg = li_log1->get_messages( ).
    READ TABLE lt_msg INTO ls_msg INDEX 1.
    cl_abap_unit_assert=>assert_subrc( ).

    cl_abap_unit_assert=>assert_char_cp(
      act = ls_msg-text
      exp = '*Object CLAS ZCL_TEST_IGNORE ignored*' ).

    lt_msg = li_log2->get_messages( ).
    READ TABLE lt_msg INTO ls_msg INDEX 1.
    cl_abap_unit_assert=>assert_subrc( ).

    cl_abap_unit_assert=>assert_char_cp(
      act = ls_msg-text
      exp = '*Object CLAS ZCL_TEST_IGNORE ignored*' ).

  ENDMETHOD.

ENDCLASS.

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

  PRIVATE SECTION.
    DATA:
      mo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit,
      mo_cut         TYPE REF TO zcl_abapgit_serialize.

    METHODS:
      setup,
      test FOR TESTING RAISING zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_i18n IMPLEMENTATION.

  METHOD setup.
    DATA ls_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit.

    " Main language: English, Translations: German
    ls_data-master_language = 'E'.
    INSERT 'DE' INTO TABLE ls_data-i18n_languages.

    TRY.
        CREATE OBJECT mo_dot_abapgit
          EXPORTING
            is_data = ls_data.

        CREATE OBJECT mo_cut
          EXPORTING
            io_dot_abapgit = mo_dot_abapgit.
      CATCH zcx_abapgit_exception.
        cl_abap_unit_assert=>fail( 'Error creating serializer' ).
    ENDTRY.
  ENDMETHOD.

  METHOD test.

    DATA: lt_tadir      TYPE zif_abapgit_definitions=>ty_tadir_tt,
          lt_result     TYPE zif_abapgit_definitions=>ty_files_item_tt,
          lv_xml        TYPE string,
          lo_input      TYPE REF TO zcl_abapgit_xml_input,
          ls_dd02v      TYPE dd02v,
          lt_i18n_langs TYPE TABLE OF langu.

    FIELD-SYMBOLS: <ls_tadir>      LIKE LINE OF lt_tadir,
                   <ls_result>     LIKE LINE OF lt_result,
                   <ls_i18n_langs> LIKE LINE OF lt_i18n_langs.

    " Assumption: Table T100 has at least English and German description
    APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
    <ls_tadir>-object   = 'TABL'.
    <ls_tadir>-obj_name = 'T100'.
    <ls_tadir>-devclass = 'PACKAGE'.
    <ls_tadir>-path     = 'foobar'.

    lt_result = mo_cut->serialize( lt_tadir ).

    cl_abap_unit_assert=>assert_equals(
      act = lines( lt_result )
      exp = 1 ).

    READ TABLE lt_result ASSIGNING <ls_result> INDEX 1.
    ASSERT sy-subrc = 0.

    lv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( <ls_result>-file-data ).

    CREATE OBJECT lo_input
      EXPORTING
        iv_xml = lv_xml.

    lo_input->zif_abapgit_xml_input~read( EXPORTING iv_name = 'DD02V'
                                          CHANGING  cg_data = ls_dd02v ).

    cl_abap_unit_assert=>assert_equals(
      act = ls_dd02v-ddlanguage
      exp = 'E' ).

    lo_input->zif_abapgit_xml_input~read( EXPORTING iv_name = 'I18N_LANGS'
                                          CHANGING  cg_data = lt_i18n_langs ).

    cl_abap_unit_assert=>assert_not_initial( lt_i18n_langs ).

    READ TABLE lt_i18n_langs ASSIGNING <ls_i18n_langs> WITH KEY table_line = 'D'.
    cl_abap_unit_assert=>assert_subrc( ).

  ENDMETHOD.
ENDCLASS.

fix language dependent unit test (#5799)

Co-authored-by: Marc Bernard <b87df29b98274de0b03db8f81c149b8b52bd050e@users.noreply.github.com>


*&---------------------------------------------------------------------*
*& Include          ZABAPGIT_OBJECT_CLAS_NEW
*&---------------------------------------------------------------------*

* todo: refactoring
* todo: testing, possible from master branch via experimental switch

CLASS lcl_oo_class_new DEFINITION INHERITING FROM lcl_oo_class.

  PUBLIC SECTION.
    METHODS:
      lif_oo_object_fnc~create REDEFINITION,
      lif_oo_object_fnc~generate_locals REDEFINITION,
      lif_oo_object_fnc~deserialize_source REDEFINITION.

  PRIVATE SECTION.
    CLASS-METHODS:
      update_report
        IMPORTING
          iv_program        TYPE programm
          it_source         TYPE string_table
        RETURNING
          VALUE(rv_updated) TYPE abap_bool,
      generate_classpool
        IMPORTING
          iv_name TYPE seoclsname
        RAISING
          zcx_abapgit_exception,
      update_meta
        IMPORTING
          iv_name     TYPE seoclsname
          iv_exposure TYPE seoexpose
          it_source   TYPE rswsourcet
        RAISING
          zcx_abapgit_exception,
      determine_method_include
        IMPORTING
          iv_name           TYPE seoclsname
          iv_method         TYPE seocpdname
        RETURNING
          VALUE(rv_program) TYPE programm
        RAISING
          zcx_abapgit_exception,
      init_scanner
        IMPORTING
          it_source         TYPE lif_defs=>ty_string_tt
          iv_name           TYPE seoclsname
        RETURNING
          VALUE(ro_scanner) TYPE REF TO cl_oo_source_scanner_class.

ENDCLASS.

CLASS lcl_oo_class_new IMPLEMENTATION.

  METHOD determine_method_include.

    DATA: ls_mtdkey TYPE seocpdkey.

    ls_mtdkey-clsname = iv_name.
    ls_mtdkey-cpdname = iv_method.

    cl_oo_classname_service=>get_method_include(
      EXPORTING
        mtdkey              = ls_mtdkey
      RECEIVING
        result              = rv_program
      EXCEPTIONS
        method_not_existing = 1 ).
    IF sy-subrc = 0.
      RETURN.
    ENDIF.

    CALL FUNCTION 'SEO_METHOD_GENERATE_INCLUDE'
      EXPORTING
        suppress_mtdkey_check          = seox_true
        mtdkey                         = ls_mtdkey
      EXCEPTIONS
        not_existing                   = 1
        model_only                     = 2
        include_existing               = 3
        method_imp_not_generated       = 4
        method_imp_not_initialised     = 5
        _internal_class_not_existing   = 6
        _internal_method_overflow      = 7
        cancelled                      = 8
        method_is_abstract_implemented = 9
        method_is_final_implemented    = 10
        internal_error_insert_report   = 11
        OTHERS                         = 12.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error from SEO_METHOD_GENERATE_INCLUDE' ).
    ENDIF.

    rv_program = cl_oo_classname_service=>get_method_include( ls_mtdkey ).

  ENDMETHOD.

  METHOD lif_oo_object_fnc~create.
* same as in super class, but with "version = seoc_version_active"

    CALL FUNCTION 'SEO_CLASS_CREATE_COMPLETE'
      EXPORTING
        devclass        = iv_package
        overwrite       = iv_overwrite
        version         = seoc_version_active
      CHANGING
        class           = is_properties
      EXCEPTIONS
        existing        = 1
        is_interface    = 2
        db_error        = 3
        component_error = 4
        no_access       = 5
        other           = 6
        OTHERS          = 7.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error from SEO_CLASS_CREATE_COMPLETE' ).
    ENDIF.

  ENDMETHOD.

  METHOD init_scanner.

    ro_scanner = cl_oo_source_scanner_class=>create_class_scanner(
      clif_name = iv_name
      source    = it_source ).
    ro_scanner->scan( ).

  ENDMETHOD.

  METHOD update_report.

    DATA: lt_old TYPE string_table.

    READ REPORT iv_program INTO lt_old.
    ASSERT sy-subrc = 0. " include should have been created previously
    IF lt_old <> it_source.
      INSERT REPORT iv_program FROM it_source.
      ASSERT sy-subrc = 0.
      rv_updated = abap_true.
    ELSE.
      rv_updated = abap_false.
    ENDIF.

  ENDMETHOD.

  METHOD lif_oo_object_fnc~generate_locals.

    DATA: lv_program TYPE programm.

    lv_program = cl_oo_classname_service=>get_ccdef_name( is_key-clsname ).
    update_report( iv_program = lv_program
                   it_source  = it_local_definitions ).

    lv_program = cl_oo_classname_service=>get_ccimp_name( is_key-clsname ).
    update_report( iv_program = lv_program
                   it_source  = it_local_implementations ).

    lv_program = cl_oo_classname_service=>get_ccmac_name( is_key-clsname ).
    update_report( iv_program = lv_program
                   it_source  = it_local_macros ).

    IF lines( it_local_test_classes ) > 0.
      lv_program = cl_oo_classname_service=>get_ccau_name( is_key-clsname ).
      update_report( iv_program = lv_program
                     it_source  = it_local_test_classes ).
    ENDIF.

  ENDMETHOD.

  METHOD update_meta.

    DATA: lo_update     TYPE REF TO cl_oo_class_section_source,
          ls_clskey     TYPE seoclskey,
          lv_scan_error TYPE seox_boolean.

    ls_clskey-clsname = iv_name.

* todo, downport to 702, see https://github.com/larshp/abapGit/issues/933
    CREATE OBJECT lo_update TYPE ('CL_OO_CLASS_SECTION_SOURCE')
      EXPORTING
        clskey                        = ls_clskey
        exposure                      = iv_exposure
        state                         = 'A'
        source                        = it_source
        suppress_constrctr_generation = seox_true
      EXCEPTIONS
        class_not_existing            = 1
        read_source_error             = 2
        OTHERS                        = 3.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error instantiating CL_OO_CLASS_SECTION_SOURCE' ).
    ENDIF.

    lo_update->set_dark_mode( seox_true ).
    TRY.
        CALL METHOD lo_update->('SET_AMDP_SUPPORT')
          EXPORTING
            enabled = abap_true.
      CATCH cx_sy_dyn_call_illegal_method.
* AMDP not supported in this system, ignore error
    ENDTRY.
    lo_update->scan_section_source(
      RECEIVING
        scan_error             = lv_scan_error
      EXCEPTIONS
        scan_abap_source_error = 1
        OTHERS                 = 2 ).
    IF sy-subrc <> 0 OR lv_scan_error = abap_true.
      zcx_abapgit_exception=>raise( 'CLAS, error while scanning source' ).
    ENDIF.

* this will update the SEO* database tables
    lo_update->revert_scan_result( ).

    IF iv_exposure = seoc_exposure_public.
      generate_classpool( iv_name ).
    ENDIF.

  ENDMETHOD.

  METHOD generate_classpool.

    DATA: ls_clskey TYPE seoclskey.

    ls_clskey-clsname = iv_name.

    CALL FUNCTION 'SEO_CLASS_GENERATE_CLASSPOOL'
      EXPORTING
        clskey                        = ls_clskey
        suppress_corr                 = seox_true
      EXCEPTIONS
        not_existing                  = 1
        model_only                    = 2
        class_pool_not_generated      = 3
        class_stment_not_generated    = 4
        locals_not_generated          = 5
        macros_not_generated          = 6
        public_sec_not_generated      = 7
        protected_sec_not_generated   = 8
        private_sec_not_generated     = 9
        typeref_not_generated         = 10
        class_pool_not_initialised    = 11
        class_stment_not_initialised  = 12
        locals_not_initialised        = 13
        macros_not_initialised        = 14
        public_sec_not_initialised    = 15
        protected_sec_not_initialised = 16
        private_sec_not_initialised   = 17
        typeref_not_initialised       = 18
        _internal_class_overflow      = 19
        OTHERS                        = 20.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error from SEO_CLASS_GENERATE_CLASSPOOL' ).
    ENDIF.

  ENDMETHOD.

  METHOD lif_oo_object_fnc~deserialize_source.

    DATA: lv_updated TYPE abap_bool,
          lv_program TYPE program,
          lo_scanner TYPE REF TO cl_oo_source_scanner_class,
          lt_methods TYPE cl_oo_source_scanner_class=>type_method_implementations,
          lv_method  LIKE LINE OF lt_methods,
          lt_source  TYPE seop_source_string.

    lo_scanner = init_scanner(
      it_source = it_source
      iv_name   = is_key-clsname ).

* public
    lt_source = lo_scanner->get_public_section_source( ).
    lv_program = cl_oo_classname_service=>get_pubsec_name( is_key-clsname ).
    lv_updated = update_report( iv_program = lv_program
                                it_source  = lt_source ).
    IF lv_updated = abap_true.
      update_meta( iv_name     = is_key-clsname
                   iv_exposure = seoc_exposure_public
                   it_source   = lt_source ).
    ENDIF.

* protected
    lt_source = lo_scanner->get_protected_section_source( ).
    lv_program = cl_oo_classname_service=>get_prosec_name( is_key-clsname ).
    lv_updated = update_report( iv_program = lv_program
                                it_source  = lt_source ).
    IF lv_updated = abap_true.
      update_meta( iv_name     = is_key-clsname
                   iv_exposure = seoc_exposure_protected
                   it_source   = lt_source ).
    ENDIF.

* private
    lt_source = lo_scanner->get_private_section_source( ).
    lv_program = cl_oo_classname_service=>get_prisec_name( is_key-clsname ).
    lv_updated = update_report( iv_program = lv_program
                                it_source  = lt_source ).
    IF lv_updated = abap_true.
      update_meta( iv_name     = is_key-clsname
                   iv_exposure = seoc_exposure_private
                   it_source   = lt_source ).
    ENDIF.

* methods
    lt_methods = lo_scanner->get_method_implementations( ).

    LOOP AT lt_methods INTO lv_method.
      TRY.
          lt_source = lo_scanner->get_method_impl_source( lv_method ).
        CATCH cx_oo_clif_component.
          zcx_abapgit_exception=>raise( 'error from GET_METHOD_IMPL_SOURCE' ).
      ENDTRY.
      lv_program = determine_method_include(
        iv_name   = is_key-clsname
        iv_method = lv_method ).

      update_report(
        iv_program = lv_program
        it_source  = lt_source ).
    ENDLOOP.

  ENDMETHOD.

ENDCLASS.

CLASS lcl_object_clas_new DEFINITION INHERITING FROM lcl_object_clas.

  PUBLIC SECTION.
    METHODS: constructor
      IMPORTING
        is_item     TYPE lif_defs=>ty_item
        iv_language TYPE spras.

  PROTECTED SECTION.
    METHODS:
      deserialize_abap REDEFINITION.

ENDCLASS.

CLASS lcl_object_clas_new IMPLEMENTATION.

  METHOD constructor.
    super->constructor( is_item     = is_item
                        iv_language = iv_language ).

    CREATE OBJECT mo_object_oriented_object_fct TYPE lcl_oo_class_new.
  ENDMETHOD.

  METHOD deserialize_abap.
* same as in lcl_object_clas, but without "mo_object_oriented_object_fct->add_to_activation_list"

    DATA: ls_vseoclass             TYPE vseoclass,
          lt_source                TYPE seop_source_string,
          lt_local_definitions     TYPE seop_source_string,
          lt_local_implementations TYPE seop_source_string,
          lt_local_macros          TYPE seop_source_string,
          lt_test_classes          TYPE seop_source_string,
          lt_descriptions          TYPE lif_defs=>ty_seocompotx_tt,
          ls_class_key             TYPE seoclskey.

    lt_source = mo_files->read_abap( ).

    lt_local_definitions = mo_files->read_abap( iv_extra = 'locals_def'
                                                iv_error = abap_false ). "#EC NOTEXT

    lt_local_implementations = mo_files->read_abap( iv_extra = 'locals_imp'
                                                    iv_error = abap_false ). "#EC NOTEXT

    lt_local_macros = mo_files->read_abap( iv_extra = 'macros'
                                           iv_error = abap_false ). "#EC NOTEXT

    lt_test_classes = mo_files->read_abap( iv_extra = 'testclasses'
                                           iv_error = abap_false ). "#EC NOTEXT

    ls_class_key-clsname = ms_item-obj_name.

    io_xml->read( EXPORTING iv_name = 'VSEOCLASS'
                  CHANGING cg_data = ls_vseoclass ).

    mo_object_oriented_object_fct->create(
      EXPORTING
        iv_package    = iv_package
      CHANGING
        is_properties = ls_vseoclass ).

    mo_object_oriented_object_fct->generate_locals(
      is_key                   = ls_class_key
      iv_force                 = seox_true
      it_local_definitions     = lt_local_definitions
      it_local_implementations = lt_local_implementations
      it_local_macros          = lt_local_macros
      it_local_test_classes    = lt_test_classes ).

    mo_object_oriented_object_fct->deserialize_source(
      is_key    = ls_class_key
      it_source = lt_source ).

    io_xml->read( EXPORTING iv_name = 'DESCRIPTIONS'
                  CHANGING cg_data = lt_descriptions ).

    mo_object_oriented_object_fct->update_descriptions(
      is_key          = ls_class_key
      it_descriptions = lt_descriptions ).

  ENDMETHOD.

ENDCLASS.

*&---------------------------------------------------------------------*
*& Include          ZABAPGIT_OBJECT_CLAS_NEW
*&---------------------------------------------------------------------*

* todo: refactoring
* todo: testing, possible from master branch via experimental switch

CLASS lcl_oo_class_new DEFINITION INHERITING FROM lcl_oo_class.

  PUBLIC SECTION.
    METHODS:
      lif_oo_object_fnc~create REDEFINITION,
      lif_oo_object_fnc~generate_locals REDEFINITION,
      lif_oo_object_fnc~deserialize_source REDEFINITION.

  PRIVATE SECTION.
    CLASS-METHODS:
      update_report
        IMPORTING
          iv_program        TYPE programm
          it_source         TYPE string_table
        RETURNING
          VALUE(rv_updated) TYPE abap_bool,
      generate_classpool
        IMPORTING
          iv_name TYPE seoclsname
        RAISING
          zcx_abapgit_exception,
      update_meta
        IMPORTING
          iv_name     TYPE seoclsname
          iv_exposure TYPE seoexpose
          it_source   TYPE rswsourcet
        RAISING
          zcx_abapgit_exception,
      determine_method_include
        IMPORTING
          iv_name           TYPE seoclsname
          iv_method         TYPE seocpdname
        RETURNING
          VALUE(rv_program) TYPE programm
        RAISING
          zcx_abapgit_exception,
      init_scanner
        IMPORTING
          it_source         TYPE lif_defs=>ty_string_tt
          iv_name           TYPE seoclsname
        RETURNING
          VALUE(ro_scanner) TYPE REF TO cl_oo_source_scanner_class,
      update_full_class_include
        IMPORTING
          iv_classname TYPE seoclsname
          it_source    TYPE string_table
          it_methods   TYPE cl_oo_source_scanner_class=>type_method_implementations,
      create_report
        IMPORTING
          iv_program      TYPE programm
          it_source       TYPE string_table
          iv_extension    TYPE sychar02
          iv_program_type TYPE sychar01
          iv_version      TYPE r3state,
      update_cs_number_of_methods
        IMPORTING
          iv_classname              TYPE seoclsname
          iv_number_of_impl_methods TYPE i.

ENDCLASS.

CLASS lcl_oo_class_new IMPLEMENTATION.

  METHOD determine_method_include.

    DATA: ls_mtdkey TYPE seocpdkey.

    ls_mtdkey-clsname = iv_name.
    ls_mtdkey-cpdname = iv_method.

    cl_oo_classname_service=>get_method_include(
      EXPORTING
        mtdkey              = ls_mtdkey
      RECEIVING
        result              = rv_program
      EXCEPTIONS
        method_not_existing = 1 ).
    IF sy-subrc = 0.
      RETURN.
    ENDIF.

    CALL FUNCTION 'SEO_METHOD_GENERATE_INCLUDE'
      EXPORTING
        suppress_mtdkey_check          = seox_true
        mtdkey                         = ls_mtdkey
      EXCEPTIONS
        not_existing                   = 1
        model_only                     = 2
        include_existing               = 3
        method_imp_not_generated       = 4
        method_imp_not_initialised     = 5
        _internal_class_not_existing   = 6
        _internal_method_overflow      = 7
        cancelled                      = 8
        method_is_abstract_implemented = 9
        method_is_final_implemented    = 10
        internal_error_insert_report   = 11
        OTHERS                         = 12.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error from SEO_METHOD_GENERATE_INCLUDE' ).
    ENDIF.

    rv_program = cl_oo_classname_service=>get_method_include( ls_mtdkey ).

  ENDMETHOD.

  METHOD lif_oo_object_fnc~create.
* same as in super class, but with "version = seoc_version_active"

    CALL FUNCTION 'SEO_CLASS_CREATE_COMPLETE'
      EXPORTING
        devclass        = iv_package
        overwrite       = iv_overwrite
        version         = seoc_version_active
      CHANGING
        class           = is_properties
      EXCEPTIONS
        existing        = 1
        is_interface    = 2
        db_error        = 3
        component_error = 4
        no_access       = 5
        other           = 6
        OTHERS          = 7.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error from SEO_CLASS_CREATE_COMPLETE' ).
    ENDIF.

  ENDMETHOD.

  METHOD init_scanner.

    ro_scanner = cl_oo_source_scanner_class=>create_class_scanner(
      clif_name = iv_name
      source    = it_source ).
    ro_scanner->scan( ).

  ENDMETHOD.

  METHOD update_report.

    DATA: lt_old TYPE string_table.

    READ REPORT iv_program INTO lt_old.
    ASSERT sy-subrc = 0. " include should have been created previously
    IF lt_old <> it_source.
      INSERT REPORT iv_program FROM it_source.
      ASSERT sy-subrc = 0.
      rv_updated = abap_true.
    ELSE.
      rv_updated = abap_false.
    ENDIF.

  ENDMETHOD.

  METHOD lif_oo_object_fnc~generate_locals.

    DATA: lv_program TYPE programm.

    lv_program = cl_oo_classname_service=>get_ccdef_name( is_key-clsname ).
    update_report( iv_program = lv_program
                   it_source  = it_local_definitions ).

    lv_program = cl_oo_classname_service=>get_ccimp_name( is_key-clsname ).
    update_report( iv_program = lv_program
                   it_source  = it_local_implementations ).

    lv_program = cl_oo_classname_service=>get_ccmac_name( is_key-clsname ).
    update_report( iv_program = lv_program
                   it_source  = it_local_macros ).

    IF lines( it_local_test_classes ) > 0.
      lv_program = cl_oo_classname_service=>get_ccau_name( is_key-clsname ).
      update_report( iv_program = lv_program
                     it_source  = it_local_test_classes ).
    ENDIF.

  ENDMETHOD.

  METHOD update_meta.

    DATA: lo_update     TYPE REF TO cl_oo_class_section_source,
          ls_clskey     TYPE seoclskey,
          lv_scan_error TYPE seox_boolean.

    ls_clskey-clsname = iv_name.

* todo, downport to 702, see https://github.com/larshp/abapGit/issues/933
    CREATE OBJECT lo_update TYPE ('CL_OO_CLASS_SECTION_SOURCE')
      EXPORTING
        clskey                        = ls_clskey
        exposure                      = iv_exposure
        state                         = 'A'
        source                        = it_source
        suppress_constrctr_generation = seox_true
      EXCEPTIONS
        class_not_existing            = 1
        read_source_error             = 2
        OTHERS                        = 3.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error instantiating CL_OO_CLASS_SECTION_SOURCE' ).
    ENDIF.

    lo_update->set_dark_mode( seox_true ).
    TRY.
        CALL METHOD lo_update->('SET_AMDP_SUPPORT')
          EXPORTING
            enabled = abap_true.
      CATCH cx_sy_dyn_call_illegal_method.
* AMDP not supported in this system, ignore error
    ENDTRY.
    lo_update->scan_section_source(
      RECEIVING
        scan_error             = lv_scan_error
      EXCEPTIONS
        scan_abap_source_error = 1
        OTHERS                 = 2 ).
    IF sy-subrc <> 0 OR lv_scan_error = abap_true.
      zcx_abapgit_exception=>raise( 'CLAS, error while scanning source' ).
    ENDIF.

* this will update the SEO* database tables
    lo_update->revert_scan_result( ).

    IF iv_exposure = seoc_exposure_public.
      generate_classpool( iv_name ).
    ENDIF.

  ENDMETHOD.

  METHOD generate_classpool.

    DATA: ls_clskey TYPE seoclskey.

    ls_clskey-clsname = iv_name.

    CALL FUNCTION 'SEO_CLASS_GENERATE_CLASSPOOL'
      EXPORTING
        clskey                        = ls_clskey
        suppress_corr                 = seox_true
      EXCEPTIONS
        not_existing                  = 1
        model_only                    = 2
        class_pool_not_generated      = 3
        class_stment_not_generated    = 4
        locals_not_generated          = 5
        macros_not_generated          = 6
        public_sec_not_generated      = 7
        protected_sec_not_generated   = 8
        private_sec_not_generated     = 9
        typeref_not_generated         = 10
        class_pool_not_initialised    = 11
        class_stment_not_initialised  = 12
        locals_not_initialised        = 13
        macros_not_initialised        = 14
        public_sec_not_initialised    = 15
        protected_sec_not_initialised = 16
        private_sec_not_initialised   = 17
        typeref_not_initialised       = 18
        _internal_class_overflow      = 19
        OTHERS                        = 20.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error from SEO_CLASS_GENERATE_CLASSPOOL' ).
    ENDIF.

  ENDMETHOD.

  METHOD lif_oo_object_fnc~deserialize_source.

    DATA: lv_updated TYPE abap_bool,
          lv_program TYPE program,
          lo_scanner TYPE REF TO cl_oo_source_scanner_class,
          lt_methods TYPE cl_oo_source_scanner_class=>type_method_implementations,
          lv_method  LIKE LINE OF lt_methods,
          lt_source  TYPE seop_source_string.

    lo_scanner = init_scanner(
      it_source = it_source
      iv_name   = is_key-clsname ).

* public
    lt_source = lo_scanner->get_public_section_source( ).
    lv_program = cl_oo_classname_service=>get_pubsec_name( is_key-clsname ).
    lv_updated = update_report( iv_program = lv_program
                                it_source  = lt_source ).
    IF lv_updated = abap_true.
      update_meta( iv_name     = is_key-clsname
                   iv_exposure = seoc_exposure_public
                   it_source   = lt_source ).
    ENDIF.

* protected
    lt_source = lo_scanner->get_protected_section_source( ).
    lv_program = cl_oo_classname_service=>get_prosec_name( is_key-clsname ).
    lv_updated = update_report( iv_program = lv_program
                                it_source  = lt_source ).
    IF lv_updated = abap_true.
      update_meta( iv_name     = is_key-clsname
                   iv_exposure = seoc_exposure_protected
                   it_source   = lt_source ).
    ENDIF.

* private
    lt_source = lo_scanner->get_private_section_source( ).
    lv_program = cl_oo_classname_service=>get_prisec_name( is_key-clsname ).
    lv_updated = update_report( iv_program = lv_program
                                it_source  = lt_source ).
    IF lv_updated = abap_true.
      update_meta( iv_name     = is_key-clsname
                   iv_exposure = seoc_exposure_private
                   it_source   = lt_source ).
    ENDIF.

* methods
    lt_methods = lo_scanner->get_method_implementations( ).

    LOOP AT lt_methods INTO lv_method.
      TRY.
          lt_source = lo_scanner->get_method_impl_source( lv_method ).
        CATCH cx_oo_clif_component.
          zcx_abapgit_exception=>raise( 'error from GET_METHOD_IMPL_SOURCE' ).
      ENDTRY.
      lv_program = determine_method_include(
        iv_name   = is_key-clsname
        iv_method = lv_method ).

      update_report(
        iv_program = lv_program
        it_source  = lt_source ).
    ENDLOOP.

* full class include
    update_full_class_include( iv_classname = is_key-clsname
                               it_source    = it_source
                               it_methods   = lt_methods ).

  ENDMETHOD.

  METHOD update_full_class_include.
    CONSTANTS c_class_source_extension TYPE sychar02 VALUE 'CS'.
    CONSTANTS c_include_program_type TYPE sychar01 VALUE 'I'.
    CONSTANTS c_active_version TYPE r3state VALUE 'A'.

    create_report( iv_program      = cl_oo_classname_service=>get_cs_name( iv_classname )
                   it_source       = it_source
                   iv_extension    = c_class_source_extension
                   iv_program_type = c_include_program_type
                   iv_version      = c_active_version ).

    update_cs_number_of_methods( iv_classname              = iv_classname
                                 iv_number_of_impl_methods = lines( it_methods ) ). " Assuming that all methods that were scanned are implemented

  ENDMETHOD.

  METHOD create_report.
    INSERT REPORT iv_program FROM it_source EXTENSION TYPE iv_extension STATE iv_version PROGRAM TYPE iv_program_type.
    ASSERT sy-subrc = 0.
  ENDMETHOD.

  METHOD update_cs_number_of_methods.
    DATA cs_cache_entry TYPE seo_cs_cache.
    cs_cache_entry-clsname            = iv_classname.
    cs_cache_entry-no_of_method_impls = iv_number_of_impl_methods.
    MODIFY seo_cs_cache FROM cs_cache_entry.
  ENDMETHOD.

ENDCLASS.

CLASS lcl_object_clas_new DEFINITION INHERITING FROM lcl_object_clas.

  PUBLIC SECTION.
    METHODS: constructor
      IMPORTING
        is_item     TYPE lif_defs=>ty_item
        iv_language TYPE spras.

  PROTECTED SECTION.
    METHODS:
      deserialize_abap REDEFINITION.

ENDCLASS.

CLASS lcl_object_clas_new IMPLEMENTATION.

  METHOD constructor.
    super->constructor( is_item     = is_item
                        iv_language = iv_language ).

    CREATE OBJECT mo_object_oriented_object_fct TYPE lcl_oo_class_new.
  ENDMETHOD.

  METHOD deserialize_abap.
* same as in lcl_object_clas, but without "mo_object_oriented_object_fct->add_to_activation_list"

    DATA: ls_vseoclass             TYPE vseoclass,
          lt_source                TYPE seop_source_string,
          lt_local_definitions     TYPE seop_source_string,
          lt_local_implementations TYPE seop_source_string,
          lt_local_macros          TYPE seop_source_string,
          lt_test_classes          TYPE seop_source_string,
          lt_descriptions          TYPE lif_defs=>ty_seocompotx_tt,
          ls_class_key             TYPE seoclskey.

    lt_source = mo_files->read_abap( ).

    lt_local_definitions = mo_files->read_abap( iv_extra = 'locals_def'
                                                iv_error = abap_false ). "#EC NOTEXT

    lt_local_implementations = mo_files->read_abap( iv_extra = 'locals_imp'
                                                    iv_error = abap_false ). "#EC NOTEXT

    lt_local_macros = mo_files->read_abap( iv_extra = 'macros'
                                           iv_error = abap_false ). "#EC NOTEXT

    lt_test_classes = mo_files->read_abap( iv_extra = 'testclasses'
                                           iv_error = abap_false ). "#EC NOTEXT

    ls_class_key-clsname = ms_item-obj_name.

    io_xml->read( EXPORTING iv_name = 'VSEOCLASS'
                  CHANGING cg_data = ls_vseoclass ).

    mo_object_oriented_object_fct->create(
      EXPORTING
        iv_package    = iv_package
      CHANGING
        is_properties = ls_vseoclass ).

    mo_object_oriented_object_fct->generate_locals(
      is_key                   = ls_class_key
      iv_force                 = seox_true
      it_local_definitions     = lt_local_definitions
      it_local_implementations = lt_local_implementations
      it_local_macros          = lt_local_macros
      it_local_test_classes    = lt_test_classes ).

    mo_object_oriented_object_fct->deserialize_source(
      is_key    = ls_class_key
      it_source = lt_source ).

    io_xml->read( EXPORTING iv_name = 'DESCRIPTIONS'
                  CHANGING cg_data = lt_descriptions ).

    mo_object_oriented_object_fct->update_descriptions(
      is_key          = ls_class_key
      it_descriptions = lt_descriptions ).

  ENDMETHOD.

ENDCLASS.

Fix experimental clas deserializer method order


*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_DEFINITIONS
*&---------------------------------------------------------------------*

TYPE-POOLS seop.

INTERFACE lif_defs.

  TYPES: ty_type    TYPE c LENGTH 6,
         ty_bitbyte TYPE c LENGTH 8,
         ty_sha1    TYPE c LENGTH 40.

  TYPES: BEGIN OF ty_file_signature,
           path     TYPE string,
           filename TYPE string,
           sha1     TYPE lif_defs=>ty_sha1,
         END OF ty_file_signature.

  TYPES: ty_file_signatures_tt TYPE STANDARD TABLE OF
           ty_file_signature WITH DEFAULT KEY.

  TYPES: ty_file_signatures_ts TYPE SORTED TABLE OF
           ty_file_signature WITH UNIQUE KEY path filename.

  TYPES: BEGIN OF ty_file.
      INCLUDE TYPE ty_file_signature.
  TYPES: data TYPE xstring,
         END OF ty_file.
  TYPES: ty_files_tt TYPE STANDARD TABLE OF ty_file WITH DEFAULT KEY.

  TYPES: ty_string_tt TYPE STANDARD TABLE OF string WITH DEFAULT KEY.

  TYPES:
    BEGIN OF ty_git_user,
      name  TYPE string,
      email TYPE string,
    END OF ty_git_user.

  TYPES:
    BEGIN OF ty_comment,
      committer TYPE ty_git_user,
      author    TYPE ty_git_user,
      comment   TYPE string,
    END OF ty_comment.

  TYPES: BEGIN OF ty_item,
           obj_type TYPE tadir-object,
           obj_name TYPE tadir-obj_name,
           devclass TYPE devclass,
         END OF ty_item,
         ty_items_tt TYPE STANDARD TABLE OF ty_item WITH DEFAULT KEY,
         ty_items_ts TYPE SORTED TABLE OF ty_item WITH UNIQUE KEY obj_type obj_name.

  TYPES: BEGIN OF ty_file_item,
           file TYPE lif_defs=>ty_file,
           item TYPE ty_item,
         END OF ty_file_item.
  TYPES: ty_files_item_tt TYPE STANDARD TABLE OF ty_file_item WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_metadata,
           class        TYPE string,
           version      TYPE string,
           late_deser   TYPE abap_bool,
           delete_tadir TYPE abap_bool,
           ddic         TYPE abap_bool,
         END OF ty_metadata.

  TYPES: BEGIN OF ty_web_asset,
           url     TYPE w3url,
           base64  TYPE string,
           content TYPE xstring,
         END OF ty_web_asset.
  TYPES  tt_web_assets TYPE STANDARD TABLE OF ty_web_asset WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_repo_file,
           path       TYPE string,
           filename   TYPE string,
           is_changed TYPE abap_bool,
           rstate     TYPE char1,
           lstate     TYPE char1,
         END OF ty_repo_file.
  TYPES  tt_repo_files TYPE STANDARD TABLE OF ty_repo_file WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_stage_files,
           local  TYPE lif_defs=>ty_files_item_tt,
           remote TYPE lif_defs=>ty_files_tt,
         END OF ty_stage_files.

  CONSTANTS: BEGIN OF gc_type,
               commit TYPE lif_defs=>ty_type VALUE 'commit', "#EC NOTEXT
               tree   TYPE lif_defs=>ty_type VALUE 'tree',  "#EC NOTEXT
               ref_d  TYPE lif_defs=>ty_type VALUE 'ref_d', "#EC NOTEXT
               blob   TYPE lif_defs=>ty_type VALUE 'blob',  "#EC NOTEXT
             END OF gc_type.

  TYPES: ty_chmod TYPE c LENGTH 6.

  TYPES: BEGIN OF ty_object,
           sha1 TYPE lif_defs=>ty_sha1,
           type TYPE lif_defs=>ty_type,
           data TYPE xstring,
         END OF ty_object.
  TYPES: ty_objects_tt TYPE STANDARD TABLE OF ty_object WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_tadir,
           pgmid    TYPE tadir-pgmid,
           object   TYPE tadir-object,
           obj_name TYPE tadir-obj_name,
           devclass TYPE tadir-devclass,
           korrnum  TYPE tadir-korrnum,
           path     TYPE string,
         END OF ty_tadir.
  TYPES: ty_tadir_tt TYPE STANDARD TABLE OF ty_tadir WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_result,
           obj_type TYPE tadir-object,
           obj_name TYPE tadir-obj_name,
           path     TYPE string,
           filename TYPE string,
           package  TYPE devclass,
           match    TYPE sap_bool,
           lstate   TYPE char1,
           rstate   TYPE char1,
         END OF ty_result.
  TYPES: ty_results_tt TYPE STANDARD TABLE OF ty_result WITH DEFAULT KEY.

  TYPES: ty_sval_tt TYPE STANDARD TABLE OF sval WITH DEFAULT KEY.

  TYPES: ty_seocompotx_tt TYPE STANDARD TABLE OF seocompotx WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_tpool.
      INCLUDE TYPE textpool.
  TYPES:   split TYPE c LENGTH 8.
  TYPES: END OF ty_tpool.

  TYPES: ty_tpool_tt TYPE STANDARD TABLE OF ty_tpool WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_sotr,
           header  TYPE sotr_head,
           entries TYPE sotr_text_tt,
         END OF ty_sotr.

  TYPES: ty_sotr_tt TYPE STANDARD TABLE OF ty_sotr WITH DEFAULT KEY.

  TYPES:
    BEGIN OF ty_transport_to_branch,
      branch_name TYPE string,
      commit_text TYPE string,
    END OF ty_transport_to_branch.

  CONSTANTS: BEGIN OF gc_state, " https://git-scm.com/docs/git-status
               unchanged TYPE char1 VALUE '',
               added     TYPE char1 VALUE 'A',
               modified  TYPE char1 VALUE 'M',
               deleted   TYPE char1 VALUE 'D', "For future use
               mixed     TYPE char1 VALUE '*',
             END OF gc_state.

  CONSTANTS: BEGIN OF gc_chmod,
               file       TYPE ty_chmod VALUE '100644',
               executable TYPE ty_chmod VALUE '100755',
               dir        TYPE ty_chmod VALUE '40000 ',
             END OF gc_chmod.

  CONSTANTS: BEGIN OF gc_event_state,
               not_handled         VALUE 0,
               re_render           VALUE 1,
               new_page            VALUE 2,
               go_back             VALUE 3,
               no_more_act         VALUE 4,
               new_page_w_bookmark VALUE 5,
               go_back_to_bookmark VALUE 6,
               new_page_replacing  VALUE 7,
             END OF gc_event_state.

  CONSTANTS: BEGIN OF gc_html_opt,
               strong   TYPE c VALUE 'E',
               cancel   TYPE c VALUE 'C',
               crossout TYPE c VALUE 'X',
             END OF gc_html_opt.

  CONSTANTS: BEGIN OF gc_action_type,
               sapevent  TYPE c VALUE 'E',
               url       TYPE c VALUE 'U',
               onclick   TYPE c VALUE 'C',
               separator TYPE c VALUE 'S',
               dummy     TYPE c VALUE '_',
             END OF gc_action_type.

  CONSTANTS: gc_crlf    TYPE abap_cr_lf VALUE cl_abap_char_utilities=>cr_lf.
  CONSTANTS: gc_newline TYPE abap_char1 VALUE cl_abap_char_utilities=>newline.

  CONSTANTS: gc_english TYPE spras VALUE 'E'.

  CONSTANTS: gc_root_dir     TYPE string VALUE '/',
             gc_dot_abapgit  TYPE string VALUE '.abapgit.xml' ##NO_TEXT,
             gc_author_regex TYPE string VALUE '^([\w\s\.@\-_1-9]+) <(.*)> (\d{10}).\d{4}$' ##NO_TEXT.

  CONSTANTS: BEGIN OF gc_action,
               repo_clone               TYPE string VALUE 'repo_clone',
               repo_refresh             TYPE string VALUE 'repo_refresh',
               repo_remove              TYPE string VALUE 'repo_remove',
               repo_settings            TYPE string VALUE 'repo_settings',
               repo_purge               TYPE string VALUE 'repo_purge',
               repo_newoffline          TYPE string VALUE 'repo_newoffline',
               repo_remote_attach       TYPE string VALUE 'repo_remote_attach',
               repo_remote_detach       TYPE string VALUE 'repo_remote_detach',
               repo_remote_change       TYPE string VALUE 'repo_remote_change',
               repo_refresh_checksums   TYPE string VALUE 'repo_refresh_checksums',
               repo_toggle_fav          TYPE string VALUE 'repo_toggle_fav',
               repo_transport_to_branch TYPE string VALUE 'repo_transport_to_branch',

               abapgit_home             TYPE string VALUE 'abapgit_home',
               abapgit_wiki             TYPE string VALUE 'abapgit_wiki',
               abapgit_install          TYPE string VALUE 'abapgit_install',
               abapgit_install_pi       TYPE string VALUE 'abapgit_install_pi',

               zip_import               TYPE string VALUE 'zip_import',
               zip_export               TYPE string VALUE 'zip_export',
               zip_package              TYPE string VALUE 'zip_package',
               zip_transport            TYPE string VALUE 'zip_transport',
               zip_object               TYPE string VALUE 'zip_object',

               git_pull                 TYPE string VALUE 'git_pull',
               git_reset                TYPE string VALUE 'git_reset',
               git_branch_create        TYPE string VALUE 'git_branch_create',
               git_branch_switch        TYPE string VALUE 'git_branch_switch',
               git_branch_delete        TYPE string VALUE 'git_branch_delete',
               git_commit               TYPE string VALUE 'git_commit',

               db_delete                TYPE string VALUE 'db_delete',
               db_update                TYPE string VALUE 'db_update',
               db_display               TYPE string VALUE 'db_display',
               db_edit                  TYPE string VALUE 'db_edit',
               bg_update                TYPE string VALUE 'bg_update',

               go_main                  TYPE string VALUE 'go_main',
               go_explore               TYPE string VALUE 'go_explore',
               go_db                    TYPE string VALUE 'go_db',
               go_background            TYPE string VALUE 'go_background',
               go_background_run        TYPE string VALUE 'go_background_run',
               go_diff                  TYPE string VALUE 'go_diff',
               go_stage                 TYPE string VALUE 'go_stage',
               go_commit                TYPE string VALUE 'go_commit',
               go_branch_overview       TYPE string VALUE 'go_branch_overview',
               go_playground            TYPE string VALUE 'go_playground',
               go_debuginfo             TYPE string VALUE 'go_debuginfo',
               go_settings              TYPE string VALUE 'go_settings',
               go_tutorial              TYPE string VALUE 'go_tutorial',

               jump                     TYPE string VALUE 'jump',
               jump_pkg                 TYPE string VALUE 'jump_pkg',
             END OF gc_action.

ENDINTERFACE.

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_DEFINITIONS
*&---------------------------------------------------------------------*

TYPE-POOLS seop.

INTERFACE lif_defs.

  TYPES: ty_type    TYPE c LENGTH 6,
         ty_bitbyte TYPE c LENGTH 8,
         ty_sha1    TYPE c LENGTH 40.

  TYPES: BEGIN OF ty_file_signature,
           path     TYPE string,
           filename TYPE string,
           sha1     TYPE lif_defs=>ty_sha1,
         END OF ty_file_signature.

  TYPES: ty_file_signatures_tt TYPE STANDARD TABLE OF
           ty_file_signature WITH DEFAULT KEY.

  TYPES: ty_file_signatures_ts TYPE SORTED TABLE OF
           ty_file_signature WITH UNIQUE KEY path filename.

  TYPES: BEGIN OF ty_file.
      INCLUDE TYPE ty_file_signature.
  TYPES: data TYPE xstring,
         END OF ty_file.
  TYPES: ty_files_tt TYPE STANDARD TABLE OF ty_file WITH DEFAULT KEY.

  TYPES: ty_string_tt TYPE STANDARD TABLE OF string WITH DEFAULT KEY.

  TYPES:
    BEGIN OF ty_git_user,
      name  TYPE string,
      email TYPE string,
    END OF ty_git_user.

  TYPES:
    BEGIN OF ty_comment,
      committer TYPE ty_git_user,
      author    TYPE ty_git_user,
      comment   TYPE string,
    END OF ty_comment.

  TYPES: BEGIN OF ty_item,
           obj_type TYPE tadir-object,
           obj_name TYPE tadir-obj_name,
           devclass TYPE devclass,
         END OF ty_item,
         ty_items_tt TYPE STANDARD TABLE OF ty_item WITH DEFAULT KEY,
         ty_items_ts TYPE SORTED TABLE OF ty_item WITH UNIQUE KEY obj_type obj_name.

  TYPES: BEGIN OF ty_file_item,
           file TYPE lif_defs=>ty_file,
           item TYPE ty_item,
         END OF ty_file_item.
  TYPES: ty_files_item_tt TYPE STANDARD TABLE OF ty_file_item WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_metadata,
           class        TYPE string,
           version      TYPE string,
           late_deser   TYPE abap_bool,
           delete_tadir TYPE abap_bool,
           ddic         TYPE abap_bool,
         END OF ty_metadata.

  TYPES: BEGIN OF ty_web_asset,
           url     TYPE w3url,
           base64  TYPE string,
           content TYPE xstring,
         END OF ty_web_asset.
  TYPES  tt_web_assets TYPE STANDARD TABLE OF ty_web_asset WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_repo_file,
           path       TYPE string,
           filename   TYPE string,
           is_changed TYPE abap_bool,
           rstate     TYPE char1,
           lstate     TYPE char1,
         END OF ty_repo_file.
  TYPES  tt_repo_files TYPE STANDARD TABLE OF ty_repo_file WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_stage_files,
           local  TYPE lif_defs=>ty_files_item_tt,
           remote TYPE lif_defs=>ty_files_tt,
         END OF ty_stage_files.

  CONSTANTS: BEGIN OF gc_type,
               commit TYPE lif_defs=>ty_type VALUE 'commit', "#EC NOTEXT
               tree   TYPE lif_defs=>ty_type VALUE 'tree',  "#EC NOTEXT
               ref_d  TYPE lif_defs=>ty_type VALUE 'ref_d', "#EC NOTEXT
               blob   TYPE lif_defs=>ty_type VALUE 'blob',  "#EC NOTEXT
             END OF gc_type.

  TYPES: ty_chmod TYPE c LENGTH 6.

  TYPES: BEGIN OF ty_object,
           sha1 TYPE lif_defs=>ty_sha1,
           type TYPE lif_defs=>ty_type,
           data TYPE xstring,
         END OF ty_object.
  TYPES: ty_objects_tt TYPE STANDARD TABLE OF ty_object WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_tadir,
           pgmid    TYPE tadir-pgmid,
           object   TYPE tadir-object,
           obj_name TYPE tadir-obj_name,
           devclass TYPE tadir-devclass,
           korrnum  TYPE tadir-korrnum,
           path     TYPE string,
         END OF ty_tadir.
  TYPES: ty_tadir_tt TYPE STANDARD TABLE OF ty_tadir WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_result,
           obj_type TYPE tadir-object,
           obj_name TYPE tadir-obj_name,
           path     TYPE string,
           filename TYPE string,
           package  TYPE devclass,
           match    TYPE sap_bool,
           lstate   TYPE char1,
           rstate   TYPE char1,
         END OF ty_result.
  TYPES: ty_results_tt TYPE STANDARD TABLE OF ty_result WITH DEFAULT KEY.

  TYPES: ty_sval_tt TYPE STANDARD TABLE OF sval WITH DEFAULT KEY.

  TYPES: ty_seocompotx_tt TYPE STANDARD TABLE OF seocompotx WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_tpool.
      INCLUDE TYPE textpool.
  TYPES:   split TYPE c LENGTH 8.
  TYPES: END OF ty_tpool.

  TYPES: ty_tpool_tt TYPE STANDARD TABLE OF ty_tpool WITH DEFAULT KEY.

  TYPES: BEGIN OF ty_sotr,
           header  TYPE sotr_head,
           entries TYPE sotr_text_tt,
         END OF ty_sotr.

  TYPES: ty_sotr_tt TYPE STANDARD TABLE OF ty_sotr WITH DEFAULT KEY.

  TYPES:
    BEGIN OF ty_transport_to_branch,
      branch_name TYPE string,
      commit_text TYPE string,
    END OF ty_transport_to_branch.

  CONSTANTS: BEGIN OF gc_state, " https://git-scm.com/docs/git-status
               unchanged TYPE char1 VALUE '',
               added     TYPE char1 VALUE 'A',
               modified  TYPE char1 VALUE 'M',
               deleted   TYPE char1 VALUE 'D', "For future use
               mixed     TYPE char1 VALUE '*',
             END OF gc_state.

  CONSTANTS: BEGIN OF gc_chmod,
               file       TYPE ty_chmod VALUE '100644',
               executable TYPE ty_chmod VALUE '100755',
               dir        TYPE ty_chmod VALUE '40000 ',
             END OF gc_chmod.

  CONSTANTS: BEGIN OF gc_event_state,
               not_handled         VALUE 0,
               re_render           VALUE 1,
               new_page            VALUE 2,
               go_back             VALUE 3,
               no_more_act         VALUE 4,
               new_page_w_bookmark VALUE 5,
               go_back_to_bookmark VALUE 6,
               new_page_replacing  VALUE 7,
             END OF gc_event_state.

  CONSTANTS: BEGIN OF gc_html_opt,
               strong   TYPE c VALUE 'E',
               cancel   TYPE c VALUE 'C',
               crossout TYPE c VALUE 'X',
             END OF gc_html_opt.

  CONSTANTS: BEGIN OF gc_action_type,
               sapevent  TYPE c VALUE 'E',
               url       TYPE c VALUE 'U',
               onclick   TYPE c VALUE 'C',
               separator TYPE c VALUE 'S',
               dummy     TYPE c VALUE '_',
             END OF gc_action_type.

  CONSTANTS: gc_crlf    TYPE abap_cr_lf VALUE cl_abap_char_utilities=>cr_lf.
  CONSTANTS: gc_newline TYPE abap_char1 VALUE cl_abap_char_utilities=>newline.

  CONSTANTS: gc_english TYPE spras VALUE 'E'.

  CONSTANTS: gc_root_dir     TYPE string VALUE '/',
             gc_dot_abapgit  TYPE string VALUE '.abapgit.xml' ##NO_TEXT,
             gc_author_regex TYPE string VALUE '^([\w\s\.@\-_1-9]+) <(.*)> (\d{10})\s?.\d{4}$' ##NO_TEXT.

  CONSTANTS: BEGIN OF gc_action,
               repo_clone               TYPE string VALUE 'repo_clone',
               repo_refresh             TYPE string VALUE 'repo_refresh',
               repo_remove              TYPE string VALUE 'repo_remove',
               repo_settings            TYPE string VALUE 'repo_settings',
               repo_purge               TYPE string VALUE 'repo_purge',
               repo_newoffline          TYPE string VALUE 'repo_newoffline',
               repo_remote_attach       TYPE string VALUE 'repo_remote_attach',
               repo_remote_detach       TYPE string VALUE 'repo_remote_detach',
               repo_remote_change       TYPE string VALUE 'repo_remote_change',
               repo_refresh_checksums   TYPE string VALUE 'repo_refresh_checksums',
               repo_toggle_fav          TYPE string VALUE 'repo_toggle_fav',
               repo_transport_to_branch TYPE string VALUE 'repo_transport_to_branch',

               abapgit_home             TYPE string VALUE 'abapgit_home',
               abapgit_wiki             TYPE string VALUE 'abapgit_wiki',
               abapgit_install          TYPE string VALUE 'abapgit_install',
               abapgit_install_pi       TYPE string VALUE 'abapgit_install_pi',

               zip_import               TYPE string VALUE 'zip_import',
               zip_export               TYPE string VALUE 'zip_export',
               zip_package              TYPE string VALUE 'zip_package',
               zip_transport            TYPE string VALUE 'zip_transport',
               zip_object               TYPE string VALUE 'zip_object',

               git_pull                 TYPE string VALUE 'git_pull',
               git_reset                TYPE string VALUE 'git_reset',
               git_branch_create        TYPE string VALUE 'git_branch_create',
               git_branch_switch        TYPE string VALUE 'git_branch_switch',
               git_branch_delete        TYPE string VALUE 'git_branch_delete',
               git_commit               TYPE string VALUE 'git_commit',

               db_delete                TYPE string VALUE 'db_delete',
               db_update                TYPE string VALUE 'db_update',
               db_display               TYPE string VALUE 'db_display',
               db_edit                  TYPE string VALUE 'db_edit',
               bg_update                TYPE string VALUE 'bg_update',

               go_main                  TYPE string VALUE 'go_main',
               go_explore               TYPE string VALUE 'go_explore',
               go_db                    TYPE string VALUE 'go_db',
               go_background            TYPE string VALUE 'go_background',
               go_background_run        TYPE string VALUE 'go_background_run',
               go_diff                  TYPE string VALUE 'go_diff',
               go_stage                 TYPE string VALUE 'go_stage',
               go_commit                TYPE string VALUE 'go_commit',
               go_branch_overview       TYPE string VALUE 'go_branch_overview',
               go_playground            TYPE string VALUE 'go_playground',
               go_debuginfo             TYPE string VALUE 'go_debuginfo',
               go_settings              TYPE string VALUE 'go_settings',
               go_tutorial              TYPE string VALUE 'go_tutorial',

               jump                     TYPE string VALUE 'jump',
               jump_pkg                 TYPE string VALUE 'jump_pkg',
             END OF gc_action.

ENDINTERFACE.

fix #778

fix #778

too lazy to add unit test, the splitting of commit author should be moved to some other class


CLASS zcl_abapgit_background DEFINITION PUBLIC CREATE PUBLIC.

  PUBLIC SECTION.
    CLASS-METHODS:
      run
        RAISING zcx_abapgit_exception.

  PRIVATE SECTION.
    CLASS-METHODS:
      build_comment
        IMPORTING is_files          TYPE zif_abapgit_definitions=>ty_stage_files
        RETURNING VALUE(rv_comment) TYPE string,
      push
        IMPORTING io_repo     TYPE REF TO zcl_abapgit_repo_online
                  is_settings TYPE zcl_abapgit_persist_background=>ty_background
        RAISING   zcx_abapgit_exception,
      push_fixed
        IMPORTING io_repo     TYPE REF TO zcl_abapgit_repo_online
                  is_settings TYPE zcl_abapgit_persist_background=>ty_background
        RAISING   zcx_abapgit_exception,
      push_auto
        IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online
        RAISING   zcx_abapgit_exception.

ENDCLASS.

CLASS zcl_abapgit_background IMPLEMENTATION.

  METHOD build_comment.

    DATA: lt_objects TYPE STANDARD TABLE OF string WITH DEFAULT KEY,
          lv_str     TYPE string.

    FIELD-SYMBOLS: <ls_local> LIKE LINE OF is_files-local.

    LOOP AT is_files-local ASSIGNING <ls_local>.
      lv_str = |{ <ls_local>-item-obj_type } { <ls_local>-item-obj_name }|.
      APPEND lv_str TO lt_objects.
    ENDLOOP.

    SORT lt_objects AS TEXT.
    DELETE ADJACENT DUPLICATES FROM lt_objects.

    IF lines( lt_objects ) = 1.
      rv_comment = |BG: { lv_str }|.
    ELSE.
      rv_comment = 'BG: Multiple objects'.
      LOOP AT lt_objects INTO lv_str.
        CONCATENATE rv_comment zif_abapgit_definitions=>gc_newline lv_str INTO rv_comment.
      ENDLOOP.
    ENDIF.

  ENDMETHOD.

  METHOD push.

    IF lines( zcl_abapgit_stage_logic=>get( io_repo )-local ) = 0.
      WRITE: / 'nothing to stage' ##NO_TEXT.
      RETURN.
    ENDIF.

    CASE is_settings-amethod.
      WHEN zcl_abapgit_persist_background=>c_amethod-fixed.
        push_fixed( io_repo     = io_repo
                    is_settings = is_settings ).
      WHEN zcl_abapgit_persist_background=>c_amethod-auto.
        push_auto( io_repo ).
      WHEN OTHERS.
        zcx_abapgit_exception=>raise( 'unknown push method' ).
    ENDCASE.

  ENDMETHOD.

  METHOD push_auto.

    TYPES: BEGIN OF ty_changed,
             filename   TYPE string,
             path       TYPE string,
             changed_by TYPE xubname,
           END OF ty_changed.

    DATA: ls_comment    TYPE zif_abapgit_definitions=>ty_comment,
          ls_files      TYPE zif_abapgit_definitions=>ty_stage_files,
          lt_changed    TYPE STANDARD TABLE OF ty_changed WITH DEFAULT KEY,
          lt_users      TYPE STANDARD TABLE OF xubname WITH DEFAULT KEY,
          ls_user_files LIKE ls_files,
          lv_changed_by TYPE xubname,
          lo_stage      TYPE REF TO zcl_abapgit_stage,
          lt_return     TYPE TABLE OF bapiret2,
          ls_address    TYPE bapiaddr3,
          lt_smtp       TYPE TABLE OF bapiadsmtp,
          ls_smtp       TYPE bapiadsmtp.

    FIELD-SYMBOLS: <ls_changed> LIKE LINE OF lt_changed,
                   <ls_remote>  LIKE LINE OF ls_files-remote,
                   <ls_local>   LIKE LINE OF ls_files-local.

    ls_files = zcl_abapgit_stage_logic=>get( io_repo ).

    LOOP AT ls_files-local ASSIGNING <ls_local>.
      lv_changed_by = zcl_abapgit_objects=>changed_by( <ls_local>-item ).
      APPEND lv_changed_by TO lt_users.
      APPEND INITIAL LINE TO lt_changed ASSIGNING <ls_changed>.
      <ls_changed>-changed_by = lv_changed_by.
      <ls_changed>-filename   = <ls_local>-file-filename.
      <ls_changed>-path       = <ls_local>-file-path.
    ENDLOOP.

    SORT lt_users ASCENDING.
    DELETE ADJACENT DUPLICATES FROM lt_users.

    LOOP AT lt_users INTO lv_changed_by.
      CLEAR ls_comment.

      CALL FUNCTION 'BAPI_USER_GET_DETAIL'
        EXPORTING
          username = lv_changed_by
        IMPORTING
          address  = ls_address
        TABLES
          return   = lt_return
          addsmtp  = lt_smtp.

      LOOP AT lt_smtp INTO ls_smtp.
        ls_comment-committer-email = ls_smtp-e_mail.
      ENDLOOP.

      IF ls_comment-committer-email IS INITIAL.
        ls_comment-committer-email = |{ lv_changed_by }@localhost|.
      ENDIF.

      ls_comment-committer-name = ls_address-fullname.

      IF ls_comment-committer-name IS INITIAL.
        ls_comment-committer-name  = lv_changed_by.
      ENDIF.

      CREATE OBJECT lo_stage
        EXPORTING
          iv_branch_name = io_repo->get_branch_name( )
          iv_branch_sha1 = io_repo->get_sha1_remote( ).

      CLEAR ls_user_files.

      LOOP AT ls_files-local ASSIGNING <ls_local>.
        READ TABLE lt_changed WITH KEY
          path = <ls_local>-file-path
          filename = <ls_local>-file-filename
          changed_by = lv_changed_by
          TRANSPORTING NO FIELDS.
        IF sy-subrc = 0.
          WRITE: / 'stage' ##NO_TEXT,
            ls_comment-committer-name,
            <ls_local>-file-path,
            <ls_local>-file-filename.

          lo_stage->add( iv_path     = <ls_local>-file-path
                         iv_filename = <ls_local>-file-filename
                         iv_data     = <ls_local>-file-data ).

          APPEND <ls_local> TO ls_user_files-local.

          LOOP AT ls_files-remote ASSIGNING <ls_remote>
              WHERE filename = <ls_local>-file-filename
              AND path <> <ls_local>-file-path
              AND filename <> 'package.devc.xml'.
            WRITE: / 'rm' ##NO_TEXT,
              <ls_remote>-path,
              <ls_remote>-filename.

* rm old file when object has moved
            lo_stage->rm(
              iv_path     = <ls_remote>-path
              iv_filename = <ls_remote>-filename ).
            EXIT. " assumption: only one file
          ENDLOOP.
        ENDIF.
      ENDLOOP.

      ls_comment-comment = build_comment( ls_user_files ).

      io_repo->push( is_comment = ls_comment
                     io_stage   = lo_stage ).
    ENDLOOP.

  ENDMETHOD.

  METHOD push_fixed.

    DATA: ls_comment TYPE zif_abapgit_definitions=>ty_comment,
          ls_files   TYPE zif_abapgit_definitions=>ty_stage_files,
          lo_stage   TYPE REF TO zcl_abapgit_stage.

    FIELD-SYMBOLS: <ls_local> LIKE LINE OF ls_files-local.

    ls_files = zcl_abapgit_stage_logic=>get( io_repo ).
    ASSERT lines( ls_files-local ) > 0.

    CREATE OBJECT lo_stage
      EXPORTING
        iv_branch_name = io_repo->get_branch_name( )
        iv_branch_sha1 = io_repo->get_sha1_remote( ).

    LOOP AT ls_files-local ASSIGNING <ls_local>.
      WRITE: / 'stage' ##NO_TEXT,
        <ls_local>-file-path,
        <ls_local>-file-filename.
      lo_stage->add( iv_path     = <ls_local>-file-path
                     iv_filename = <ls_local>-file-filename
                     iv_data     = <ls_local>-file-data ).
    ENDLOOP.

    ls_comment-committer-name  = is_settings-aname.
    ls_comment-committer-email = is_settings-amail.
    ls_comment-comment         = build_comment( ls_files ).

    io_repo->push( is_comment = ls_comment
                   io_stage   = lo_stage ).

  ENDMETHOD.

  METHOD run.

    CONSTANTS: lc_enq_type TYPE c LENGTH 12 VALUE 'BACKGROUND'.

    DATA: lo_per       TYPE REF TO zcl_abapgit_persist_background,
          lo_repo      TYPE REF TO zcl_abapgit_repo_online,
          lt_list      TYPE zcl_abapgit_persist_background=>tt_background,
          lv_repo_name TYPE string.

    FIELD-SYMBOLS: <ls_list> LIKE LINE OF lt_list.

    CALL FUNCTION 'ENQUEUE_EZABAPGIT'
      EXPORTING
        mode_zabapgit  = 'E'
        type           = lc_enq_type
        _scope         = '3'
      EXCEPTIONS
        foreign_lock   = 1
        system_failure = 2
        OTHERS         = 3.
    IF sy-subrc <> 0.
      WRITE: / 'Another intance of the program is already running'.
      RETURN.
    ENDIF.

    CREATE OBJECT lo_per.
    lt_list = lo_per->list( ).

    WRITE: / 'Background mode' ##NO_TEXT.

    LOOP AT lt_list ASSIGNING <ls_list>.
      lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( <ls_list>-key ).
      lv_repo_name = lo_repo->get_name( ).
      WRITE: / <ls_list>-method, lv_repo_name.

      zcl_abapgit_login_manager=>set(
        iv_uri      = lo_repo->get_url( )
        iv_username = <ls_list>-username
        iv_password = <ls_list>-password ).

      CASE <ls_list>-method.
        WHEN zcl_abapgit_persist_background=>c_method-pull.
          lo_repo->deserialize( ).
        WHEN zcl_abapgit_persist_background=>c_method-push.
          push( io_repo     = lo_repo
                is_settings = <ls_list> ).
        WHEN OTHERS.
          zcx_abapgit_exception=>raise( 'background, unknown mode' ).
      ENDCASE.
    ENDLOOP.

    IF lines( lt_list ) = 0.
      WRITE: / 'Nothing configured' ##NO_TEXT.
    ENDIF.

    CALL FUNCTION 'DEQUEUE_EZABAPGIT'
      EXPORTING
        type = lc_enq_type.

  ENDMETHOD.
ENDCLASS.

CLASS zcl_abapgit_background DEFINITION PUBLIC CREATE PUBLIC.

  PUBLIC SECTION.
    CLASS-METHODS:
      run
        RAISING zcx_abapgit_exception.

  PRIVATE SECTION.
    CLASS-METHODS:
      build_comment
        IMPORTING is_files          TYPE zif_abapgit_definitions=>ty_stage_files
        RETURNING VALUE(rv_comment) TYPE string,
      push
        IMPORTING io_repo     TYPE REF TO zcl_abapgit_repo_online
                  is_settings TYPE zcl_abapgit_persist_background=>ty_background
        RAISING   zcx_abapgit_exception,
      push_fixed
        IMPORTING io_repo     TYPE REF TO zcl_abapgit_repo_online
                  is_settings TYPE zcl_abapgit_persist_background=>ty_background
        RAISING   zcx_abapgit_exception,
      push_auto
        IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online
        RAISING   zcx_abapgit_exception.

ENDCLASS.

CLASS zcl_abapgit_background IMPLEMENTATION.

  METHOD build_comment.

    DATA: lt_objects TYPE STANDARD TABLE OF string WITH DEFAULT KEY,
          lv_str     TYPE string.

    FIELD-SYMBOLS: <ls_local> LIKE LINE OF is_files-local.

    LOOP AT is_files-local ASSIGNING <ls_local>.
      lv_str = |{ <ls_local>-item-obj_type } { <ls_local>-item-obj_name }|.
      APPEND lv_str TO lt_objects.
    ENDLOOP.

    SORT lt_objects AS TEXT.
    DELETE ADJACENT DUPLICATES FROM lt_objects.

    IF lines( lt_objects ) = 1.
      rv_comment = |BG: { lv_str }|.
    ELSE.
      rv_comment = 'BG: Multiple objects'.
      LOOP AT lt_objects INTO lv_str.
        CONCATENATE rv_comment zif_abapgit_definitions=>gc_newline lv_str INTO rv_comment.
      ENDLOOP.
    ENDIF.

  ENDMETHOD.

  METHOD push.

    IF lines( zcl_abapgit_stage_logic=>get( io_repo )-local ) = 0.
      WRITE: / 'nothing to stage' ##NO_TEXT.
      RETURN.
    ENDIF.

    CASE is_settings-amethod.
      WHEN zcl_abapgit_persist_background=>c_amethod-fixed.
        push_fixed( io_repo     = io_repo
                    is_settings = is_settings ).
      WHEN zcl_abapgit_persist_background=>c_amethod-auto.
        push_auto( io_repo ).
      WHEN OTHERS.
        zcx_abapgit_exception=>raise( 'unknown push method' ).
    ENDCASE.

  ENDMETHOD.

  METHOD push_auto.

    TYPES: BEGIN OF ty_changed,
             filename   TYPE string,
             path       TYPE string,
             changed_by TYPE xubname,
           END OF ty_changed.

    DATA: ls_comment    TYPE zif_abapgit_definitions=>ty_comment,
          ls_files      TYPE zif_abapgit_definitions=>ty_stage_files,
          lt_changed    TYPE STANDARD TABLE OF ty_changed WITH DEFAULT KEY,
          lt_users      TYPE STANDARD TABLE OF xubname WITH DEFAULT KEY,
          ls_user_files LIKE ls_files,
          lv_changed_by TYPE xubname,
          lo_stage      TYPE REF TO zcl_abapgit_stage,
          lt_return     TYPE TABLE OF bapiret2,
          ls_address    TYPE bapiaddr3,
          lt_smtp       TYPE TABLE OF bapiadsmtp,
          ls_smtp       TYPE bapiadsmtp.

    FIELD-SYMBOLS: <ls_changed> LIKE LINE OF lt_changed,
                   <ls_remote>  LIKE LINE OF ls_files-remote,
                   <ls_local>   LIKE LINE OF ls_files-local.

    ls_files = zcl_abapgit_stage_logic=>get( io_repo ).

    LOOP AT ls_files-local ASSIGNING <ls_local>.
      lv_changed_by = zcl_abapgit_objects=>changed_by( <ls_local>-item ).
      APPEND lv_changed_by TO lt_users.
      APPEND INITIAL LINE TO lt_changed ASSIGNING <ls_changed>.
      <ls_changed>-changed_by = lv_changed_by.
      <ls_changed>-filename   = <ls_local>-file-filename.
      <ls_changed>-path       = <ls_local>-file-path.
    ENDLOOP.

    SORT lt_users ASCENDING.
    DELETE ADJACENT DUPLICATES FROM lt_users.

    LOOP AT lt_users INTO lv_changed_by.
      CLEAR: ls_comment, ls_address, lt_return, lt_smtp.

      CALL FUNCTION 'BAPI_USER_GET_DETAIL'
        EXPORTING
          username = lv_changed_by
        IMPORTING
          address  = ls_address
        TABLES
          return   = lt_return
          addsmtp  = lt_smtp.

      LOOP AT lt_smtp INTO ls_smtp.
        ls_comment-committer-email = ls_smtp-e_mail.
      ENDLOOP.

      IF ls_comment-committer-email IS INITIAL.
        ls_comment-committer-email = |{ lv_changed_by }@localhost|.
      ENDIF.

      ls_comment-committer-name = ls_address-fullname.

      IF ls_comment-committer-name IS INITIAL.
        ls_comment-committer-name  = lv_changed_by.
      ENDIF.

      CREATE OBJECT lo_stage
        EXPORTING
          iv_branch_name = io_repo->get_branch_name( )
          iv_branch_sha1 = io_repo->get_sha1_remote( ).

      CLEAR ls_user_files.

      LOOP AT ls_files-local ASSIGNING <ls_local>.
        READ TABLE lt_changed WITH KEY
          path = <ls_local>-file-path
          filename = <ls_local>-file-filename
          changed_by = lv_changed_by
          TRANSPORTING NO FIELDS.
        IF sy-subrc = 0.
          WRITE: / 'stage' ##NO_TEXT,
            ls_comment-committer-name,
            <ls_local>-file-path,
            <ls_local>-file-filename.

          lo_stage->add( iv_path     = <ls_local>-file-path
                         iv_filename = <ls_local>-file-filename
                         iv_data     = <ls_local>-file-data ).

          APPEND <ls_local> TO ls_user_files-local.

          LOOP AT ls_files-remote ASSIGNING <ls_remote>
              WHERE filename = <ls_local>-file-filename
              AND path <> <ls_local>-file-path
              AND filename <> 'package.devc.xml'.
            WRITE: / 'rm' ##NO_TEXT,
              <ls_remote>-path,
              <ls_remote>-filename.

* rm old file when object has moved
            lo_stage->rm(
              iv_path     = <ls_remote>-path
              iv_filename = <ls_remote>-filename ).
            EXIT. " assumption: only one file
          ENDLOOP.
        ENDIF.
      ENDLOOP.

      ls_comment-comment = build_comment( ls_user_files ).

      io_repo->push( is_comment = ls_comment
                     io_stage   = lo_stage ).
    ENDLOOP.

  ENDMETHOD.

  METHOD push_fixed.

    DATA: ls_comment TYPE zif_abapgit_definitions=>ty_comment,
          ls_files   TYPE zif_abapgit_definitions=>ty_stage_files,
          lo_stage   TYPE REF TO zcl_abapgit_stage.

    FIELD-SYMBOLS: <ls_local> LIKE LINE OF ls_files-local.

    ls_files = zcl_abapgit_stage_logic=>get( io_repo ).
    ASSERT lines( ls_files-local ) > 0.

    CREATE OBJECT lo_stage
      EXPORTING
        iv_branch_name = io_repo->get_branch_name( )
        iv_branch_sha1 = io_repo->get_sha1_remote( ).

    LOOP AT ls_files-local ASSIGNING <ls_local>.
      WRITE: / 'stage' ##NO_TEXT,
        <ls_local>-file-path,
        <ls_local>-file-filename.
      lo_stage->add( iv_path     = <ls_local>-file-path
                     iv_filename = <ls_local>-file-filename
                     iv_data     = <ls_local>-file-data ).
    ENDLOOP.

    ls_comment-committer-name  = is_settings-aname.
    ls_comment-committer-email = is_settings-amail.
    ls_comment-comment         = build_comment( ls_files ).

    io_repo->push( is_comment = ls_comment
                   io_stage   = lo_stage ).

  ENDMETHOD.

  METHOD run.

    CONSTANTS: lc_enq_type TYPE c LENGTH 12 VALUE 'BACKGROUND'.

    DATA: lo_per       TYPE REF TO zcl_abapgit_persist_background,
          lo_repo      TYPE REF TO zcl_abapgit_repo_online,
          lt_list      TYPE zcl_abapgit_persist_background=>tt_background,
          lv_repo_name TYPE string.

    FIELD-SYMBOLS: <ls_list> LIKE LINE OF lt_list.

    CALL FUNCTION 'ENQUEUE_EZABAPGIT'
      EXPORTING
        mode_zabapgit  = 'E'
        type           = lc_enq_type
        _scope         = '3'
      EXCEPTIONS
        foreign_lock   = 1
        system_failure = 2
        OTHERS         = 3.
    IF sy-subrc <> 0.
      WRITE: / 'Another intance of the program is already running'.
      RETURN.
    ENDIF.

    CREATE OBJECT lo_per.
    lt_list = lo_per->list( ).

    WRITE: / 'Background mode' ##NO_TEXT.

    LOOP AT lt_list ASSIGNING <ls_list>.
      lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( <ls_list>-key ).
      lv_repo_name = lo_repo->get_name( ).
      WRITE: / <ls_list>-method, lv_repo_name.

      zcl_abapgit_login_manager=>set(
        iv_uri      = lo_repo->get_url( )
        iv_username = <ls_list>-username
        iv_password = <ls_list>-password ).

      CASE <ls_list>-method.
        WHEN zcl_abapgit_persist_background=>c_method-pull.
          lo_repo->deserialize( ).
        WHEN zcl_abapgit_persist_background=>c_method-push.
          push( io_repo     = lo_repo
                is_settings = <ls_list> ).
        WHEN OTHERS.
          zcx_abapgit_exception=>raise( 'background, unknown mode' ).
      ENDCASE.
    ENDLOOP.

    IF lines( lt_list ) = 0.
      WRITE: / 'Nothing configured' ##NO_TEXT.
    ENDIF.

    CALL FUNCTION 'DEQUEUE_EZABAPGIT'
      EXPORTING
        type = lc_enq_type.

  ENDMETHOD.
ENDCLASS.

Clear the variables

Clear the variables


*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_PASSWORD_DIALOG
*&---------------------------------------------------------------------*

SELECTION-SCREEN BEGIN OF SCREEN 1002 TITLE s_title.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(18) s_url FOR FIELD p_url.
PARAMETERS: p_url TYPE string LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(18) s_user FOR FIELD p_user.
PARAMETERS: p_user TYPE string LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(18) s_pass FOR FIELD p_pass.
PARAMETERS: p_pass TYPE c LENGTH 255 LOWER CASE VISIBLE LENGTH 40 ##SEL_WRONG.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF SCREEN 1002.

*-----------------------------------------------------------------------
* LCL_PASSWORD_DIALOG
*-----------------------------------------------------------------------
CLASS lcl_password_dialog DEFINITION FINAL.

**************
* This class will remain local in the report
**************

  PUBLIC SECTION.
    CONSTANTS c_dynnr TYPE c LENGTH 4 VALUE '1002'.

    CLASS-METHODS popup
      IMPORTING
        iv_repo_url TYPE string
      CHANGING
        cv_user     TYPE string
        cv_pass     TYPE string.

    CLASS-METHODS on_screen_init.
    CLASS-METHODS on_screen_output.
    CLASS-METHODS on_screen_event
      IMPORTING
        iv_ucomm TYPE sy-ucomm.

  PRIVATE SECTION.
    CLASS-DATA gv_confirm TYPE abap_bool.
    CLASS-METHODS enrich_title_by_hostname
      IMPORTING
        iv_repo_url TYPE string.

ENDCLASS.

CLASS lcl_password_dialog IMPLEMENTATION.

  METHOD popup.

    CLEAR p_pass.
    p_url      = iv_repo_url.
    p_user     = cv_user.
    gv_confirm = abap_false.

    enrich_title_by_hostname( iv_repo_url ).

    CALL SELECTION-SCREEN c_dynnr STARTING AT 5 5 ENDING AT 80 8.

    IF gv_confirm = abap_true.
      cv_user = p_user.
      cv_pass = p_pass.
    ELSE.
      CLEAR: cv_user, cv_pass.
    ENDIF.

    CLEAR: p_url, p_user, p_pass.

  ENDMETHOD.

  METHOD on_screen_init.
    s_title = 'Login'.
    s_url   = 'Repo URL'.
    s_user  = 'User'.
    s_pass  = 'Password or Token'.
  ENDMETHOD.

  METHOD on_screen_output.
    DATA lt_ucomm TYPE TABLE OF sy-ucomm.

    ASSERT sy-dynnr = c_dynnr.

    LOOP AT SCREEN.
      IF screen-name = 'P_URL'.
        screen-input       = '0'.
        screen-intensified = '1'.
        screen-display_3d  = '0'.
        MODIFY SCREEN.
      ENDIF.
      IF screen-name = 'P_PASS'.
        screen-invisible   = '1'.
        MODIFY SCREEN.
      ENDIF.
    ENDLOOP.

    " Program RSSYSTDB, GUI Status %_CSP
    PERFORM set_pf_status IN PROGRAM rsdbrunt IF FOUND.
    APPEND 'NONE' TO lt_ucomm.  "Button Check
    APPEND 'SPOS' TO lt_ucomm.  "Save as Variant

    CALL FUNCTION 'RS_SET_SELSCREEN_STATUS'
      EXPORTING
        p_status  = sy-pfkey
      TABLES
        p_exclude = lt_ucomm.

    IF p_user IS NOT INITIAL.
      SET CURSOR FIELD 'P_PASS'.
    ENDIF.

  ENDMETHOD.

  METHOD on_screen_event.
    ASSERT sy-dynnr = c_dynnr.

    " CRET   - F8
    " OTHERS - simulate Enter press
    CASE iv_ucomm.
      WHEN 'CRET'.
        gv_confirm = abap_true.
      WHEN OTHERS. "TODO REFACTOR !!! A CLUTCH !
        " This will work unless any new specific logic appear
        " for other commands. The problem is that the password dialog
        " does not have Enter event (or I don't know how to activate it ;)
        " so Enter issues previous command from previous screen
        " But for now this works :) Fortunately Esc produces another flow
        gv_confirm = abap_true.
        LEAVE TO SCREEN 0.
    ENDCASE.

  ENDMETHOD.

  METHOD enrich_title_by_hostname.

    DATA lv_host TYPE string.

    FIND REGEX 'https?://([^/^:]*)' IN iv_repo_url SUBMATCHES lv_host.
    IF lv_host IS NOT INITIAL AND lv_host <> space.
      CLEAR s_title.
      CONCATENATE 'Login:' lv_host INTO s_title IN CHARACTER MODE SEPARATED BY space.
    ENDIF.

  ENDMETHOD.

ENDCLASS.

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_PASSWORD_DIALOG
*&---------------------------------------------------------------------*

SELECTION-SCREEN BEGIN OF SCREEN 1002 TITLE s_title.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(18) s_url FOR FIELD p_url.
PARAMETERS: p_url TYPE string LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(18) s_user FOR FIELD p_user.
PARAMETERS: p_user TYPE string LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(18) s_pass FOR FIELD p_pass.
PARAMETERS: p_pass TYPE c LENGTH 255 LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF SCREEN 1002.

*-----------------------------------------------------------------------
* LCL_PASSWORD_DIALOG
*-----------------------------------------------------------------------
CLASS lcl_password_dialog DEFINITION FINAL.

**************
* This class will remain local in the report
**************

  PUBLIC SECTION.
    CONSTANTS c_dynnr TYPE c LENGTH 4 VALUE '1002'.

    CLASS-METHODS popup
      IMPORTING
        iv_repo_url TYPE string
      CHANGING
        cv_user     TYPE string
        cv_pass     TYPE string.

    CLASS-METHODS on_screen_init.
    CLASS-METHODS on_screen_output.
    CLASS-METHODS on_screen_event
      IMPORTING
        iv_ucomm TYPE sy-ucomm.

  PRIVATE SECTION.
    CLASS-DATA gv_confirm TYPE abap_bool.
    CLASS-METHODS enrich_title_by_hostname
      IMPORTING
        iv_repo_url TYPE string.

ENDCLASS.

CLASS lcl_password_dialog IMPLEMENTATION.

  METHOD popup.

    CLEAR p_pass.
    p_url      = iv_repo_url.
    p_user     = cv_user.
    gv_confirm = abap_false.

    enrich_title_by_hostname( iv_repo_url ).

    CALL SELECTION-SCREEN c_dynnr STARTING AT 5 5 ENDING AT 80 8.

    IF gv_confirm = abap_true.
      cv_user = p_user.
      cv_pass = p_pass.
    ELSE.
      CLEAR: cv_user, cv_pass.
    ENDIF.

    CLEAR: p_url, p_user, p_pass.

  ENDMETHOD.

  METHOD on_screen_init.
    s_title = 'Login'.
    s_url   = 'Repo URL'.
    s_user  = 'User'.
    s_pass  = 'Password or Token'.
  ENDMETHOD.

  METHOD on_screen_output.
    DATA lt_ucomm TYPE TABLE OF sy-ucomm.

    ASSERT sy-dynnr = c_dynnr.

    LOOP AT SCREEN.
      IF screen-name = 'P_URL'.
        screen-input       = '0'.
        screen-intensified = '1'.
        screen-display_3d  = '0'.
        MODIFY SCREEN.
      ENDIF.
      IF screen-name = 'P_PASS'.
        screen-invisible   = '1'.
        MODIFY SCREEN.
      ENDIF.
    ENDLOOP.

    " Program RSSYSTDB, GUI Status %_CSP
    PERFORM set_pf_status IN PROGRAM rsdbrunt IF FOUND.
    APPEND 'NONE' TO lt_ucomm.  "Button Check
    APPEND 'SPOS' TO lt_ucomm.  "Save as Variant

    CALL FUNCTION 'RS_SET_SELSCREEN_STATUS'
      EXPORTING
        p_status  = sy-pfkey
      TABLES
        p_exclude = lt_ucomm.

    IF p_user IS NOT INITIAL.
      SET CURSOR FIELD 'P_PASS'.
    ENDIF.

  ENDMETHOD.

  METHOD on_screen_event.
    ASSERT sy-dynnr = c_dynnr.

    " CRET   - F8
    " OTHERS - simulate Enter press
    CASE iv_ucomm.
      WHEN 'CRET'.
        gv_confirm = abap_true.
      WHEN OTHERS. "TODO REFACTOR !!! A CLUTCH !
        " This will work unless any new specific logic appear
        " for other commands. The problem is that the password dialog
        " does not have Enter event (or I don't know how to activate it ;)
        " so Enter issues previous command from previous screen
        " But for now this works :) Fortunately Esc produces another flow
        gv_confirm = abap_true.
        LEAVE TO SCREEN 0.
    ENDCASE.

  ENDMETHOD.

  METHOD enrich_title_by_hostname.

    DATA lv_host TYPE string.

    FIND REGEX 'https?://([^/^:]*)' IN iv_repo_url SUBMATCHES lv_host.
    IF lv_host IS NOT INITIAL AND lv_host <> space.
      CLEAR s_title.
      CONCATENATE 'Login:' lv_host INTO s_title IN CHARACTER MODE SEPARATED BY space.
    ENDIF.

  ENDMETHOD.

ENDCLASS.

Adjust password field visible length (#4138)