*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_FILE_STATUS
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_file_status DEFINITION
*----------------------------------------------------------------------*
CLASS ltcl_file_status DEFINITION DEFERRED.

CLASS lcl_file_status DEFINITION FINAL
  FRIENDS ltcl_file_status.

  PUBLIC SECTION.

    CLASS-METHODS status
      IMPORTING io_repo           TYPE REF TO lcl_repo
                io_log            TYPE REF TO lcl_log OPTIONAL
      RETURNING VALUE(rt_results) TYPE ty_results_tt
      RAISING   lcx_exception.

  PRIVATE SECTION.

    CLASS-METHODS calculate_status
      IMPORTING it_local           TYPE ty_files_item_tt
                it_remote          TYPE ty_files_tt
                it_cur_state       TYPE ty_file_signatures_tt
      RETURNING VALUE(rt_results)  TYPE ty_results_tt.

    CLASS-METHODS:
      build_existing
        IMPORTING is_local         TYPE ty_file_item
                  is_remote        TYPE ty_file
                  it_state         TYPE ty_file_signatures_ts
        RETURNING VALUE(rs_result) TYPE ty_result,
      build_new_local
        IMPORTING is_local         TYPE ty_file_item
        RETURNING VALUE(rs_result) TYPE ty_result,
      build_new_remote
        IMPORTING is_remote        TYPE ty_file
                  it_items         TYPE ty_items_ts
                  it_state         TYPE ty_file_signatures_ts
        RETURNING VALUE(rs_result) TYPE ty_result,
      identify_object
        IMPORTING iv_filename      TYPE string
        EXPORTING es_item          TYPE ty_item
                  ev_is_xml        TYPE abap_bool.

ENDCLASS.                    "lcl_file_status DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_file_status IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_file_status IMPLEMENTATION.

  METHOD status.

    DATA: lv_index       LIKE sy-tabix,
          lo_dot_abapgit TYPE REF TO lcl_dot_abapgit.

    FIELD-SYMBOLS <ls_result> LIKE LINE OF rt_results.

    rt_results = calculate_status(
      it_local     = io_repo->get_files_local( io_log )
      it_remote    = io_repo->get_files_remote( )
      it_cur_state = io_repo->get_local_checksums_per_file( ) ).

    lo_dot_abapgit = io_repo->get_dot_abapgit( ).

    " Remove ignored files, fix .abapgit
    LOOP AT rt_results ASSIGNING <ls_result>.
      lv_index = sy-tabix.

      IF lo_dot_abapgit->is_ignored(
          iv_path     = <ls_result>-path
          iv_filename = <ls_result>-filename ) = abap_true.
        DELETE rt_results INDEX lv_index.
      ENDIF.
    ENDLOOP.

    lcl_sap_package=>check(
      io_log     = io_log
      it_results = rt_results
      iv_start   = lo_dot_abapgit->get_starting_folder( )
      iv_top     = io_repo->get_package( ) ).

  ENDMETHOD.  "status

  METHOD calculate_status.

    DATA: lt_remote    LIKE it_remote,
          lt_items     TYPE ty_items_tt,
          ls_item      LIKE LINE OF lt_items,
          lv_is_xml    TYPE abap_bool,
          lt_items_idx TYPE ty_items_ts,
          lt_state_idx TYPE ty_file_signatures_ts. " Sorted by path+filename

    FIELD-SYMBOLS: <ls_remote> LIKE LINE OF it_remote,
                   <ls_result> LIKE LINE OF rt_results,
                   <ls_local>  LIKE LINE OF it_local.

    lt_state_idx = it_cur_state. " Force sort it
    lt_remote    = it_remote.
    SORT lt_remote BY path filename.

    " Process local files and new local files
    LOOP AT it_local ASSIGNING <ls_local>.
      APPEND INITIAL LINE TO rt_results ASSIGNING <ls_result>.
      IF <ls_local>-item IS NOT INITIAL.
        APPEND <ls_local>-item TO lt_items. " Collect for item index
      ENDIF.

      READ TABLE lt_remote ASSIGNING <ls_remote>
        WITH KEY path = <ls_local>-file-path filename = <ls_local>-file-filename
        BINARY SEARCH.
      IF sy-subrc = 0.  " Exist local and remote
        <ls_result> = build_existing(
          is_local  = <ls_local>
          is_remote = <ls_remote>
          it_state  = lt_state_idx ).
        ASSERT <ls_remote>-sha1 IS NOT INITIAL.
        CLEAR <ls_remote>-sha1. " Mark as processed
      ELSE.             " Only L exists
        <ls_result> = build_new_local( is_local = <ls_local> ).
      ENDIF.
    ENDLOOP.

    " Complete item index for unmarked remote files
    LOOP AT lt_remote ASSIGNING <ls_remote> WHERE sha1 IS NOT INITIAL.
      identify_object( EXPORTING iv_filename = <ls_remote>-filename
                       IMPORTING es_item     = ls_item
                                 ev_is_xml   = lv_is_xml ).

      CHECK lv_is_xml = abap_true. " Skip all but obj definitions

      ls_item-devclass = lcl_tadir=>get_object_package(
                           iv_object   = ls_item-obj_type
                           iv_obj_name = ls_item-obj_name ).
      APPEND ls_item TO lt_items.
    ENDLOOP.

    SORT lt_items. " Default key - type, name, pkg
    DELETE ADJACENT DUPLICATES FROM lt_items.
    lt_items_idx = lt_items. " Self protection + UNIQUE records assertion

    " Process new remote files (marked above with empty SHA1)
    LOOP AT lt_remote ASSIGNING <ls_remote> WHERE sha1 IS NOT INITIAL.
      APPEND INITIAL LINE TO rt_results ASSIGNING <ls_result>.
      <ls_result> = build_new_remote( is_remote = <ls_remote>
                                      it_items  = lt_items_idx
                                      it_state  = lt_state_idx ).
    ENDLOOP.

    SORT rt_results BY
      obj_type ASCENDING
      obj_name ASCENDING
      filename ASCENDING.

  ENDMETHOD.  "calculate_status.

  METHOD identify_object.

    DATA: lv_name   TYPE tadir-obj_name,
          lv_type   TYPE string,
          lv_ext    TYPE string.

    " Guess object type and name
    SPLIT to_upper( iv_filename ) AT '.' INTO lv_name lv_type lv_ext.

    " Handle namespaces
    REPLACE ALL OCCURRENCES OF '#' IN lv_name WITH '/'.

    CLEAR es_item.
    es_item-obj_type = lv_type.
    es_item-obj_name = lv_name.
    ev_is_xml        = boolc( lv_ext = 'XML' AND strlen( lv_type ) = 4 ).

  ENDMETHOD.  "identify_object.

  METHOD build_existing.

    DATA: ls_file_sig LIKE LINE OF it_state.

    " Item
    rs_result-obj_type = is_local-item-obj_type.
    rs_result-obj_name = is_local-item-obj_name.
    rs_result-package  = is_local-item-devclass.

    " File
    rs_result-path     = is_local-file-path.
    rs_result-filename = is_local-file-filename.

    " Match against current state
    READ TABLE it_state INTO ls_file_sig
      WITH KEY path = is_local-file-path
      filename = is_local-file-filename
      BINARY SEARCH.

    IF sy-subrc = 0.
      IF ls_file_sig-sha1 <> is_local-file-sha1.
        rs_result-lstate = gc_state-modified.
      ENDIF.
      IF ls_file_sig-sha1 <> is_remote-sha1.
        rs_result-rstate = gc_state-modified.
      ENDIF.
      rs_result-match = boolc( rs_result-lstate IS INITIAL
        AND rs_result-rstate IS INITIAL ).
    ELSE.
      " This is a strange situation. As both local and remote exist
      " the state should also be present. Maybe this is a first run of the code.
      " In this case just compare hashes directly and mark both changed
      " the user will presumably decide what to do after checking the actual diff
      rs_result-match = boolc( is_local-file-sha1 = is_remote-sha1 ).
      IF rs_result-match = abap_false.
        rs_result-lstate = gc_state-modified.
        rs_result-rstate = gc_state-modified.
      ENDIF.
    ENDIF.

  ENDMETHOD.  "build_existing

  METHOD build_new_local.

    " Item
    rs_result-obj_type = is_local-item-obj_type.
    rs_result-obj_name = is_local-item-obj_name.
    rs_result-package  = is_local-item-devclass.

    " File
    rs_result-path     = is_local-file-path.
    rs_result-filename = is_local-file-filename.

    " Match
    rs_result-match    = abap_false.
    rs_result-lstate   = gc_state-added.

  ENDMETHOD.  "build_new_local

  METHOD build_new_remote.

    DATA: ls_item     LIKE LINE OF it_items,
          ls_file_sig LIKE LINE OF it_state.

    " Common and default part
    rs_result-path     = is_remote-path.
    rs_result-filename = is_remote-filename.
    rs_result-match    = abap_false.
    rs_result-rstate   = gc_state-added.

    identify_object( EXPORTING iv_filename = is_remote-filename
                     IMPORTING es_item     = ls_item ).

    " Check if in item index + get package
    READ TABLE it_items INTO ls_item
      WITH KEY obj_type = ls_item-obj_type obj_name = ls_item-obj_name
      BINARY SEARCH.

    IF sy-subrc = 0.

      " Completely new (xml, abap) and new file in an existing object
      rs_result-obj_type = ls_item-obj_type.
      rs_result-obj_name = ls_item-obj_name.
      rs_result-package  = ls_item-devclass.

      READ TABLE it_state INTO ls_file_sig
        WITH KEY path = is_remote-path filename = is_remote-filename
        BINARY SEARCH.

      " Existing file but from another package
      " was not added during local file proc as was not in tadir for repo package
      IF sy-subrc = 0.
        IF ls_file_sig-sha1 = is_remote-sha1.
          rs_result-match = abap_true.
          CLEAR rs_result-rstate.
        ELSE.
          rs_result-rstate = gc_state-modified.
        ENDIF.

        " Item is in state and in cache but with no package - it was deleted
        IF ls_item-devclass IS INITIAL.
          rs_result-match  = abap_false.
          rs_result-lstate = gc_state-deleted.
        ENDIF.
      ENDIF.

    ELSE. " Completely unknown file, probably non-abapgit
      ASSERT 1 = 1. " No action, just follow defaults
    ENDIF.

  ENDMETHOD.  "build_new_remote

ENDCLASS.                    "lcl_file_status IMPLEMENTATION

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_FILE_STATUS
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_file_status DEFINITION
*----------------------------------------------------------------------*
CLASS ltcl_file_status DEFINITION DEFERRED.

CLASS lcl_file_status DEFINITION FINAL
  FRIENDS ltcl_file_status.

  PUBLIC SECTION.

    CLASS-METHODS status
      IMPORTING io_repo           TYPE REF TO lcl_repo
                io_log            TYPE REF TO lcl_log OPTIONAL
      RETURNING VALUE(rt_results) TYPE ty_results_tt
      RAISING   lcx_exception.

  PRIVATE SECTION.

    CLASS-METHODS calculate_status
      IMPORTING it_local           TYPE ty_files_item_tt
                it_remote          TYPE ty_files_tt
                it_cur_state       TYPE ty_file_signatures_tt
      RETURNING VALUE(rt_results)  TYPE ty_results_tt.

    CLASS-METHODS:
      build_existing
        IMPORTING is_local         TYPE ty_file_item
                  is_remote        TYPE ty_file
                  it_state         TYPE ty_file_signatures_ts
        RETURNING VALUE(rs_result) TYPE ty_result,
      build_new_local
        IMPORTING is_local         TYPE ty_file_item
        RETURNING VALUE(rs_result) TYPE ty_result,
      build_new_remote
        IMPORTING is_remote        TYPE ty_file
                  it_items         TYPE ty_items_ts
                  it_state         TYPE ty_file_signatures_ts
        RETURNING VALUE(rs_result) TYPE ty_result,
      identify_object
        IMPORTING iv_filename      TYPE string
        EXPORTING es_item          TYPE ty_item
                  ev_is_xml        TYPE abap_bool.

ENDCLASS.                    "lcl_file_status DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_file_status IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_file_status IMPLEMENTATION.

  METHOD status.

    DATA: lv_index       LIKE sy-tabix,
          lo_dot_abapgit TYPE REF TO lcl_dot_abapgit.

    FIELD-SYMBOLS <ls_result> LIKE LINE OF rt_results.

    rt_results = calculate_status(
      it_local     = io_repo->get_files_local( io_log = io_log )
      it_remote    = io_repo->get_files_remote( )
      it_cur_state = io_repo->get_local_checksums_per_file( ) ).

    lo_dot_abapgit = io_repo->get_dot_abapgit( ).

    " Remove ignored files, fix .abapgit
    LOOP AT rt_results ASSIGNING <ls_result>.
      lv_index = sy-tabix.

      IF lo_dot_abapgit->is_ignored(
          iv_path     = <ls_result>-path
          iv_filename = <ls_result>-filename ) = abap_true.
        DELETE rt_results INDEX lv_index.
      ENDIF.
    ENDLOOP.

    lcl_sap_package=>check(
      io_log     = io_log
      it_results = rt_results
      iv_start   = lo_dot_abapgit->get_starting_folder( )
      iv_top     = io_repo->get_package( ) ).

  ENDMETHOD.  "status

  METHOD calculate_status.

    DATA: lt_remote    LIKE it_remote,
          lt_items     TYPE ty_items_tt,
          ls_item      LIKE LINE OF lt_items,
          lv_is_xml    TYPE abap_bool,
          lt_items_idx TYPE ty_items_ts,
          lt_state_idx TYPE ty_file_signatures_ts. " Sorted by path+filename

    FIELD-SYMBOLS: <ls_remote> LIKE LINE OF it_remote,
                   <ls_result> LIKE LINE OF rt_results,
                   <ls_local>  LIKE LINE OF it_local.

    lt_state_idx = it_cur_state. " Force sort it
    lt_remote    = it_remote.
    SORT lt_remote BY path filename.

    " Process local files and new local files
    LOOP AT it_local ASSIGNING <ls_local>.
      APPEND INITIAL LINE TO rt_results ASSIGNING <ls_result>.
      IF <ls_local>-item IS NOT INITIAL.
        APPEND <ls_local>-item TO lt_items. " Collect for item index
      ENDIF.

      READ TABLE lt_remote ASSIGNING <ls_remote>
        WITH KEY path = <ls_local>-file-path filename = <ls_local>-file-filename
        BINARY SEARCH.
      IF sy-subrc = 0.  " Exist local and remote
        <ls_result> = build_existing(
          is_local  = <ls_local>
          is_remote = <ls_remote>
          it_state  = lt_state_idx ).
        ASSERT <ls_remote>-sha1 IS NOT INITIAL.
        CLEAR <ls_remote>-sha1. " Mark as processed
      ELSE.             " Only L exists
        <ls_result> = build_new_local( is_local = <ls_local> ).
      ENDIF.
    ENDLOOP.

    " Complete item index for unmarked remote files
    LOOP AT lt_remote ASSIGNING <ls_remote> WHERE sha1 IS NOT INITIAL.
      identify_object( EXPORTING iv_filename = <ls_remote>-filename
                       IMPORTING es_item     = ls_item
                                 ev_is_xml   = lv_is_xml ).

      CHECK lv_is_xml = abap_true. " Skip all but obj definitions

      ls_item-devclass = lcl_tadir=>get_object_package(
                           iv_object   = ls_item-obj_type
                           iv_obj_name = ls_item-obj_name ).
      APPEND ls_item TO lt_items.
    ENDLOOP.

    SORT lt_items. " Default key - type, name, pkg
    DELETE ADJACENT DUPLICATES FROM lt_items.
    lt_items_idx = lt_items. " Self protection + UNIQUE records assertion

    " Process new remote files (marked above with empty SHA1)
    LOOP AT lt_remote ASSIGNING <ls_remote> WHERE sha1 IS NOT INITIAL.
      APPEND INITIAL LINE TO rt_results ASSIGNING <ls_result>.
      <ls_result> = build_new_remote( is_remote = <ls_remote>
                                      it_items  = lt_items_idx
                                      it_state  = lt_state_idx ).
    ENDLOOP.

    SORT rt_results BY
      obj_type ASCENDING
      obj_name ASCENDING
      filename ASCENDING.

  ENDMETHOD.  "calculate_status.

  METHOD identify_object.

    DATA: lv_name   TYPE tadir-obj_name,
          lv_type   TYPE string,
          lv_ext    TYPE string.

    " Guess object type and name
    SPLIT to_upper( iv_filename ) AT '.' INTO lv_name lv_type lv_ext.

    " Handle namespaces
    REPLACE ALL OCCURRENCES OF '#' IN lv_name WITH '/'.

    CLEAR es_item.
    es_item-obj_type = lv_type.
    es_item-obj_name = lv_name.
    ev_is_xml        = boolc( lv_ext = 'XML' AND strlen( lv_type ) = 4 ).

  ENDMETHOD.  "identify_object.

  METHOD build_existing.

    DATA: ls_file_sig LIKE LINE OF it_state.

    " Item
    rs_result-obj_type = is_local-item-obj_type.
    rs_result-obj_name = is_local-item-obj_name.
    rs_result-package  = is_local-item-devclass.

    " File
    rs_result-path     = is_local-file-path.
    rs_result-filename = is_local-file-filename.

    " Match against current state
    READ TABLE it_state INTO ls_file_sig
      WITH KEY path = is_local-file-path
      filename = is_local-file-filename
      BINARY SEARCH.

    IF sy-subrc = 0.
      IF ls_file_sig-sha1 <> is_local-file-sha1.
        rs_result-lstate = gc_state-modified.
      ENDIF.
      IF ls_file_sig-sha1 <> is_remote-sha1.
        rs_result-rstate = gc_state-modified.
      ENDIF.
      rs_result-match = boolc( rs_result-lstate IS INITIAL
        AND rs_result-rstate IS INITIAL ).
    ELSE.
      " This is a strange situation. As both local and remote exist
      " the state should also be present. Maybe this is a first run of the code.
      " In this case just compare hashes directly and mark both changed
      " the user will presumably decide what to do after checking the actual diff
      rs_result-match = boolc( is_local-file-sha1 = is_remote-sha1 ).
      IF rs_result-match = abap_false.
        rs_result-lstate = gc_state-modified.
        rs_result-rstate = gc_state-modified.
      ENDIF.
    ENDIF.

  ENDMETHOD.  "build_existing

  METHOD build_new_local.

    " Item
    rs_result-obj_type = is_local-item-obj_type.
    rs_result-obj_name = is_local-item-obj_name.
    rs_result-package  = is_local-item-devclass.

    " File
    rs_result-path     = is_local-file-path.
    rs_result-filename = is_local-file-filename.

    " Match
    rs_result-match    = abap_false.
    rs_result-lstate   = gc_state-added.

  ENDMETHOD.  "build_new_local

  METHOD build_new_remote.

    DATA: ls_item     LIKE LINE OF it_items,
          ls_file_sig LIKE LINE OF it_state.

    " Common and default part
    rs_result-path     = is_remote-path.
    rs_result-filename = is_remote-filename.
    rs_result-match    = abap_false.
    rs_result-rstate   = gc_state-added.

    identify_object( EXPORTING iv_filename = is_remote-filename
                     IMPORTING es_item     = ls_item ).

    " Check if in item index + get package
    READ TABLE it_items INTO ls_item
      WITH KEY obj_type = ls_item-obj_type obj_name = ls_item-obj_name
      BINARY SEARCH.

    IF sy-subrc = 0.

      " Completely new (xml, abap) and new file in an existing object
      rs_result-obj_type = ls_item-obj_type.
      rs_result-obj_name = ls_item-obj_name.
      rs_result-package  = ls_item-devclass.

      READ TABLE it_state INTO ls_file_sig
        WITH KEY path = is_remote-path filename = is_remote-filename
        BINARY SEARCH.

      " Existing file but from another package
      " was not added during local file proc as was not in tadir for repo package
      IF sy-subrc = 0.
        IF ls_file_sig-sha1 = is_remote-sha1.
          rs_result-match = abap_true.
          CLEAR rs_result-rstate.
        ELSE.
          rs_result-rstate = gc_state-modified.
        ENDIF.

        " Item is in state and in cache but with no package - it was deleted
        IF ls_item-devclass IS INITIAL.
          rs_result-match  = abap_false.
          rs_result-lstate = gc_state-deleted.
        ENDIF.
      ENDIF.

    ELSE. " Completely unknown file, probably non-abapgit
      ASSERT 1 = 1. " No action, just follow defaults
    ENDIF.

  ENDMETHOD.  "build_new_remote

ENDCLASS.                    "lcl_file_status IMPLEMENTATION

Update zabapgit_file_status.prog.abap

Update zabapgit_file_status.prog.abap


"! Logging failed exception
CLASS zcx_alog_logging_failed DEFINITION
  PUBLIC
  INHERITING FROM cx_dynamic_check
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    CONSTANTS:
      BEGIN OF gc_no_arguments,
        msgid TYPE symsgid VALUE 'ZALOG',
        msgno TYPE symsgno VALUE '004',
        attr1 TYPE scx_attrname VALUE '',
        attr2 TYPE scx_attrname VALUE '',
        attr3 TYPE scx_attrname VALUE '',
        attr4 TYPE scx_attrname VALUE '',
      END OF gc_no_arguments,
      BEGIN OF gc_with_reason,
        msgid TYPE symsgid VALUE 'ZALOG',
        msgno TYPE symsgno VALUE '005',
        attr1 TYPE scx_attrname VALUE '',
        attr2 TYPE scx_attrname VALUE '',
        attr3 TYPE scx_attrname VALUE '',
        attr4 TYPE scx_attrname VALUE '',
      END OF gc_with_reason.
    INTERFACES:
      if_t100_message.
    METHODS:
      "! @parameter is_textid | Textid
      "! @parameter ix_previous | Previous exception
      "! @parameter iv_reason | Reason
      constructor IMPORTING is_textid   LIKE if_t100_message=>t100key OPTIONAL
                            ix_previous LIKE previous OPTIONAL
                            iv_reason   TYPE csequence OPTIONAL.
    DATA:
      mv_reason TYPE string.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcx_alog_logging_failed IMPLEMENTATION.
  METHOD constructor ##ADT_SUPPRESS_GENERATION.
    super->constructor( previous = ix_previous ).

    mv_reason = iv_reason.

    CLEAR me->textid.
    IF is_textid IS INITIAL.
      if_t100_message~t100key = gc_no_arguments.
    ELSE.
      if_t100_message~t100key = is_textid.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

"! Logging failed exception
CLASS zcx_alog_logging_failed DEFINITION
  PUBLIC
  INHERITING FROM cx_dynamic_check
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    CONSTANTS:
      BEGIN OF gc_no_arguments,
        msgid TYPE symsgid VALUE 'ZALOG',
        msgno TYPE symsgno VALUE '004',
        attr1 TYPE scx_attrname VALUE '',
        attr2 TYPE scx_attrname VALUE '',
        attr3 TYPE scx_attrname VALUE '',
        attr4 TYPE scx_attrname VALUE '',
      END OF gc_no_arguments,
      BEGIN OF gc_with_reason,
        msgid TYPE symsgid VALUE 'ZALOG',
        msgno TYPE symsgno VALUE '005',
        attr1 TYPE scx_attrname VALUE 'MV_REASON',
        attr2 TYPE scx_attrname VALUE '',
        attr3 TYPE scx_attrname VALUE '',
        attr4 TYPE scx_attrname VALUE '',
      END OF gc_with_reason.
    INTERFACES:
      if_t100_message.
    METHODS:
      "! @parameter is_textid | Textid
      "! @parameter ix_previous | Previous exception
      "! @parameter iv_reason | Reason
      constructor IMPORTING is_textid   LIKE if_t100_message=>t100key OPTIONAL
                            ix_previous LIKE previous OPTIONAL
                            iv_reason   TYPE csequence OPTIONAL.
    DATA:
      mv_reason TYPE string.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcx_alog_logging_failed IMPLEMENTATION.
  METHOD constructor ##ADT_SUPPRESS_GENERATION.
    super->constructor( previous = ix_previous ).

    mv_reason = iv_reason.

    CLEAR me->textid.
    IF is_textid IS INITIAL.
      if_t100_message~t100key = gc_no_arguments.
    ELSE.
      if_t100_message~t100key = is_textid.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

Fix missing message variable constant

Fix missing message variable constant


*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_OBJECT_WAPA
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_object_wapa DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_object_wapa DEFINITION INHERITING FROM lcl_objects_super FINAL.

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

  PRIVATE SECTION.
    TYPES: BEGIN OF ty_page,
             attributes     TYPE o2pagattr,
             event_handlers TYPE o2pagevh_tabletype,
             parameters     TYPE o2pagpar_tabletype,
             types          TYPE rswsourcet,
           END OF ty_page.

    TYPES: ty_pages_tt TYPE STANDARD TABLE OF ty_page WITH DEFAULT KEY.

    CONSTANTS: c_active TYPE so2_version VALUE 'A'.

    METHODS:
      get_page_content
        IMPORTING io_page           TYPE REF TO cl_o2_api_pages
        RETURNING VALUE(rv_content) TYPE xstring,
      to_page_content
        IMPORTING iv_content        TYPE xstring
        RETURNING VALUE(rt_content) TYPE o2pageline_table,
      read_page
        IMPORTING is_page        TYPE o2pagattr
        RETURNING VALUE(rs_page) TYPE ty_page
        RAISING   zcx_abapgit_exception.

ENDCLASS.                    "lcl_object_TRAN DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_object_wapa IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_object_wapa IMPLEMENTATION.

  METHOD lif_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.  "lif_object~has_changed_since

  METHOD lif_object~changed_by.

    DATA: lv_name   TYPE o2applname,
          lt_pages  TYPE STANDARD TABLE OF o2pagdir WITH DEFAULT KEY,
          ls_latest LIKE LINE OF lt_pages.

    lv_name = ms_item-obj_name.

    SELECT * FROM o2pagdir INTO TABLE lt_pages WHERE applname = lv_name.
    IF sy-subrc <> 0.
      rv_user = c_user_unknown.
      RETURN.
    ENDIF.

    SORT lt_pages BY changedon DESCENDING changetime DESCENDING.

    READ TABLE lt_pages INDEX 1 INTO ls_latest.
    ASSERT sy-subrc = 0.

    rv_user = ls_latest-changedby.

  ENDMETHOD.

  METHOD lif_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.                    "lif_object~get_metadata

  METHOD lif_object~exists.

    DATA: lv_name TYPE o2applname.

    lv_name = ms_item-obj_name.

    cl_o2_api_application=>load(
      EXPORTING
        p_application_name  = lv_name
      EXCEPTIONS
        object_not_existing = 1
        permission_failure  = 2
        error_occured       = 3 ).
    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.                    "lif_object~exists

  METHOD lif_object~jump.

    CALL FUNCTION 'RS_TOOL_ACCESS'
      EXPORTING
        operation     = 'SHOW'
        object_name   = ms_item-obj_name
        object_type   = ms_item-obj_type
        in_new_window = abap_true.

  ENDMETHOD.                    "jump

  METHOD lif_object~delete.

    DATA: lv_name    TYPE o2applname,
          lo_bsp     TYPE REF TO cl_o2_api_application,
          ls_pagekey TYPE o2pagkey,
          lv_object  TYPE seu_objkey,
          lt_pages   TYPE o2pagelist.

    FIELD-SYMBOLS: <ls_page> LIKE LINE OF lt_pages.

    lv_name = ms_item-obj_name.

    cl_o2_api_application=>load(
      EXPORTING
        p_application_name  = lv_name
      IMPORTING
        p_application       = lo_bsp
      EXCEPTIONS
        object_not_existing = 1
        permission_failure  = 2
        error_occured       = 3 ).
    ASSERT sy-subrc = 0.

    lo_bsp->set_changeable(
      p_changeable           = abap_true
      p_complete_application = abap_true ).

    cl_o2_api_pages=>get_all_pages(
      EXPORTING
        p_applname = lv_name
        p_version  = c_active
      IMPORTING
        p_pages    = lt_pages ).

    LOOP AT lt_pages ASSIGNING <ls_page>.
      CLEAR ls_pagekey.
      ls_pagekey-applname = lv_name.
      ls_pagekey-pagekey  = <ls_page>-pagekey.

      cl_o2_page=>delete_page_for_application(
        EXPORTING
          p_pagekey           = ls_pagekey
        EXCEPTIONS
          object_not_existing = 1
          error_occured       = 2 ).
      ASSERT sy-subrc = 0.
    ENDLOOP.

    lo_bsp->delete( ).

* release lock
    lv_object = lv_name.
    cl_o2_api_application=>call_access_permission(
      p_mode                 = 'FREE'
      p_object               = lv_object
      p_complete_application = abap_true ).

  ENDMETHOD.                    "delete

  METHOD lif_object~deserialize.

    DATA: lo_bsp        TYPE REF TO cl_o2_api_application,
          ls_attributes TYPE o2applattr,
          lt_nodes      TYPE o2applnode_table,
          lt_navgraph   TYPE o2applgrap_table,
          lv_objkey     TYPE seu_objkey,
          ls_item       LIKE ms_item,
          lv_extra      TYPE string,
          lv_content    TYPE xstring,
          lv_ext        TYPE string,
          lo_page       TYPE REF TO cl_o2_api_pages,
          lt_pages_info TYPE ty_pages_tt.

    FIELD-SYMBOLS: <ls_page> LIKE LINE OF lt_pages_info.

    io_xml->read( EXPORTING iv_name = 'ATTRIBUTES'
                  CHANGING cg_data = ls_attributes ).
    io_xml->read( EXPORTING iv_name = 'NAVGRAPH'
                  CHANGING cg_data = lt_navgraph ).
    io_xml->read( EXPORTING iv_name = 'PAGES'
                  CHANGING cg_data = lt_pages_info ).

    ls_attributes-devclass = iv_package.

* todo: overwrite existing
    cl_o2_api_application=>create_new(
      EXPORTING
        p_application_data      = ls_attributes
        p_nodes                 = lt_nodes
        p_navgraph              = lt_navgraph
      IMPORTING
        p_application           = lo_bsp
      EXCEPTIONS
        object_already_existing = 1
        object_just_created     = 2
        not_authorized          = 3
        undefined_name          = 4
        author_not_existing     = 5
        action_cancelled        = 6
        error_occured           = 7
        invalid_parameter       = 8 ).
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |WAPA - error from create_new: { sy-subrc }| ).
    ENDIF.

    lo_bsp->save( ).

    lo_bsp->set_changeable(
      p_changeable           = abap_false
      p_complete_application = abap_true ).

    ls_item-obj_type = 'WAPD'.
    ls_item-obj_name = ms_item-obj_name.
    lcl_objects_activation=>add_item( ls_item ).

    lv_objkey = ls_item-obj_name.
* todo, hmm, the WAPD is not added to the worklist during activation
    cl_o2_api_application=>activate( lv_objkey ).

    LOOP AT lt_pages_info ASSIGNING <ls_page>.
      cl_o2_api_pages=>create_new_page(
        EXPORTING
          p_pageattrs = <ls_page>-attributes
        IMPORTING
          p_page      = lo_page ).

      SPLIT <ls_page>-attributes-pagename AT '.' INTO lv_extra lv_ext.
      REPLACE ALL OCCURRENCES OF '_-' IN lv_extra WITH '/'.
      lv_content = mo_files->read_raw( iv_extra = lv_extra
                                       iv_ext   = lv_ext ).
      lo_page->set_page( to_page_content( lv_content ) ).

      lo_page->set_event_handlers( <ls_page>-event_handlers ).
      lo_page->set_parameters( <ls_page>-parameters ).
      lo_page->set_type_source( <ls_page>-types ).

      lo_page->save( p_with_all_texts = abap_true ).

      ls_item-obj_type = 'WAPP'.
      ls_item-obj_name = cl_wb_object_type=>get_concatenated_key_from_id(
        p_key_component1 = <ls_page>-attributes-applname
        p_key_component2 = <ls_page>-attributes-pagekey
        p_external_id    = 'WG ' ).
      lcl_objects_activation=>add_item( ls_item ).
    ENDLOOP.

  ENDMETHOD.                    "deserialize

  METHOD lif_object~serialize.

    DATA: lv_name       TYPE o2applname,
          ls_attributes TYPE o2applattr,
          lt_navgraph   TYPE o2applgrap_table,
          lt_pages      TYPE o2pagelist,
          lt_pages_info TYPE ty_pages_tt,
          lo_bsp        TYPE REF TO cl_o2_api_application.

    FIELD-SYMBOLS: <ls_page> LIKE LINE OF lt_pages.

    lv_name = ms_item-obj_name.

    cl_o2_api_application=>load(
      EXPORTING
        p_application_name  = lv_name
      IMPORTING
        p_application       = lo_bsp
      EXCEPTIONS
        object_not_existing = 1
        permission_failure  = 2
        error_occured       = 3 ).
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    lo_bsp->get_attributes(
      EXPORTING
        p_version    = c_active
      IMPORTING
        p_attributes = ls_attributes ).

    CLEAR: ls_attributes-author,
           ls_attributes-createdon,
           ls_attributes-changedby,
           ls_attributes-changedon,
           ls_attributes-devclass.

    io_xml->add( iv_name = 'ATTRIBUTES'
                 ig_data = ls_attributes ).

    lo_bsp->get_navgraph(
      EXPORTING
        p_version  = c_active
      IMPORTING
        p_navgraph = lt_navgraph ).

    io_xml->add( iv_name = 'NAVGRAPH'
                 ig_data = lt_navgraph ).

    cl_o2_api_pages=>get_all_pages(
      EXPORTING
        p_applname = lv_name
        p_version  = c_active
      IMPORTING
        p_pages    = lt_pages ).

    LOOP AT lt_pages ASSIGNING <ls_page>.
      APPEND read_page( <ls_page> ) TO lt_pages_info.
    ENDLOOP.

    io_xml->add( iv_name = 'PAGES'
                 ig_data = lt_pages_info ).

  ENDMETHOD.                    "serialize

  METHOD read_page.

    DATA: lv_name    TYPE o2applname,
          ls_pagekey TYPE o2pagkey,
          lv_content TYPE xstring,
          lv_extra   TYPE string,
          lv_ext     TYPE string,
          lo_page    TYPE REF TO cl_o2_api_pages.

    lv_name = ms_item-obj_name.

    ls_pagekey-applname = lv_name.
    ls_pagekey-pagekey = is_page-pagekey.

    cl_o2_api_pages=>load(
      EXPORTING
        p_pagekey = ls_pagekey
      IMPORTING
        p_page    = lo_page ).

    lo_page->get_event_handlers(
      IMPORTING
        p_ev_handler = rs_page-event_handlers
      EXCEPTIONS
        page_deleted = 1
        invalid_call = 2 ).
    ASSERT sy-subrc = 0.

    lo_page->get_parameters(
      IMPORTING
        p_parameters = rs_page-parameters
      EXCEPTIONS
        page_deleted = 1
        invalid_call = 2
        OTHERS       = 3 ).
    ASSERT sy-subrc = 0.

    lo_page->get_type_source(
      IMPORTING
        p_source     = rs_page-types
      EXCEPTIONS
        page_deleted = 1
        invalid_call = 2
        OTHERS       = 3 ).
    ASSERT sy-subrc = 0.

    lv_content = get_page_content( lo_page ).
    SPLIT is_page-pagename AT '.' INTO lv_extra lv_ext.
    REPLACE ALL OCCURRENCES OF '/' IN lv_extra WITH '_-'.
    mo_files->add_raw(
      iv_extra = lv_extra
      iv_ext   = lv_ext
      iv_data  = lv_content ).

    lo_page->get_attrs(
      IMPORTING
        p_attrs = rs_page-attributes ).

    CLEAR: rs_page-attributes-author,
           rs_page-attributes-createdon,
           rs_page-attributes-changedby,
           rs_page-attributes-changedon,
           rs_page-attributes-changetime,
           rs_page-attributes-implclass,
           rs_page-attributes-gendate,
           rs_page-attributes-gentime,
           rs_page-attributes-devclass.

  ENDMETHOD.

  METHOD to_page_content.

    DATA: lv_string TYPE string.

    lv_string = lcl_convert=>xstring_to_string_utf8( iv_content ).

    SPLIT lv_string AT zif_abapgit_definitions=>gc_newline INTO TABLE rt_content.

  ENDMETHOD.

  METHOD get_page_content.

    DATA: lt_content TYPE o2pageline_table,
          lv_string  TYPE string.

    io_page->get_page(
      IMPORTING
        p_content = lt_content ).

    CONCATENATE LINES OF lt_content INTO lv_string SEPARATED BY zif_abapgit_definitions=>gc_newline RESPECTING BLANKS.

    rv_content = lcl_convert=>string_to_xstring_utf8( lv_string ).

  ENDMETHOD.

  METHOD lif_object~compare_to_remote_version.
    CREATE OBJECT ro_comparison_result TYPE lcl_comparison_null.
  ENDMETHOD.

ENDCLASS.                    "lcl_object_tran IMPLEMENTATION

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_OBJECT_WAPA
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_object_wapa DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_object_wapa DEFINITION INHERITING FROM lcl_objects_super FINAL.

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

  PRIVATE SECTION.
    TYPES: BEGIN OF ty_page,
             attributes     TYPE o2pagattr,
             event_handlers TYPE o2pagevh_tabletype,
             parameters     TYPE o2pagpar_tabletype,
             types          TYPE rswsourcet,
           END OF ty_page.

    TYPES: ty_pages_tt TYPE STANDARD TABLE OF ty_page WITH DEFAULT KEY.

    CONSTANTS: c_active TYPE so2_version VALUE 'A'.

    METHODS:
      get_page_content
        IMPORTING io_page           TYPE REF TO cl_o2_api_pages
        RETURNING VALUE(rv_content) TYPE xstring
        RAISING   zcx_abapgit_exception,
      to_page_content
        IMPORTING iv_content        TYPE xstring
        RETURNING VALUE(rt_content) TYPE o2pageline_table,
      read_page
        IMPORTING is_page        TYPE o2pagattr
        RETURNING VALUE(rs_page) TYPE ty_page
        RAISING   zcx_abapgit_exception.

ENDCLASS.                    "lcl_object_TRAN DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_object_wapa IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_object_wapa IMPLEMENTATION.

  METHOD lif_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.  "lif_object~has_changed_since

  METHOD lif_object~changed_by.

    DATA: lv_name   TYPE o2applname,
          lt_pages  TYPE STANDARD TABLE OF o2pagdir WITH DEFAULT KEY,
          ls_latest LIKE LINE OF lt_pages.

    lv_name = ms_item-obj_name.

    SELECT * FROM o2pagdir INTO TABLE lt_pages WHERE applname = lv_name.
    IF sy-subrc <> 0.
      rv_user = c_user_unknown.
      RETURN.
    ENDIF.

    SORT lt_pages BY changedon DESCENDING changetime DESCENDING.

    READ TABLE lt_pages INDEX 1 INTO ls_latest.
    ASSERT sy-subrc = 0.

    rv_user = ls_latest-changedby.

  ENDMETHOD.

  METHOD lif_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.                    "lif_object~get_metadata

  METHOD lif_object~exists.

    DATA: lv_name TYPE o2applname.

    lv_name = ms_item-obj_name.

    cl_o2_api_application=>load(
      EXPORTING
        p_application_name  = lv_name
      EXCEPTIONS
        object_not_existing = 1
        permission_failure  = 2
        error_occured       = 3 ).
    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.                    "lif_object~exists

  METHOD lif_object~jump.

    CALL FUNCTION 'RS_TOOL_ACCESS'
      EXPORTING
        operation     = 'SHOW'
        object_name   = ms_item-obj_name
        object_type   = ms_item-obj_type
        in_new_window = abap_true.

  ENDMETHOD.                    "jump

  METHOD lif_object~delete.

    DATA: lv_name    TYPE o2applname,
          lo_bsp     TYPE REF TO cl_o2_api_application,
          ls_pagekey TYPE o2pagkey,
          lv_object  TYPE seu_objkey,
          lt_pages   TYPE o2pagelist.

    FIELD-SYMBOLS: <ls_page> LIKE LINE OF lt_pages.

    lv_name = ms_item-obj_name.

    cl_o2_api_application=>load(
      EXPORTING
        p_application_name  = lv_name
      IMPORTING
        p_application       = lo_bsp
      EXCEPTIONS
        object_not_existing = 1
        permission_failure  = 2
        error_occured       = 3 ).
    ASSERT sy-subrc = 0.

    lo_bsp->set_changeable(
      p_changeable           = abap_true
      p_complete_application = abap_true ).

    cl_o2_api_pages=>get_all_pages(
      EXPORTING
        p_applname = lv_name
        p_version  = c_active
      IMPORTING
        p_pages    = lt_pages ).

    LOOP AT lt_pages ASSIGNING <ls_page>.
      CLEAR ls_pagekey.
      ls_pagekey-applname = lv_name.
      ls_pagekey-pagekey  = <ls_page>-pagekey.

      cl_o2_page=>delete_page_for_application(
        EXPORTING
          p_pagekey           = ls_pagekey
        EXCEPTIONS
          object_not_existing = 1
          error_occured       = 2 ).
      ASSERT sy-subrc = 0.
    ENDLOOP.

    lo_bsp->delete( ).

* release lock
    lv_object = lv_name.
    cl_o2_api_application=>call_access_permission(
      p_mode                 = 'FREE'
      p_object               = lv_object
      p_complete_application = abap_true ).

  ENDMETHOD.                    "delete

  METHOD lif_object~deserialize.

    DATA: lo_bsp        TYPE REF TO cl_o2_api_application,
          ls_attributes TYPE o2applattr,
          lt_nodes      TYPE o2applnode_table,
          lt_navgraph   TYPE o2applgrap_table,
          lv_objkey     TYPE seu_objkey,
          lv_obj_name   TYPE string,
          ls_item       LIKE ms_item,
          lv_extra      TYPE string,
          lv_content    TYPE xstring,
          lv_ext        TYPE string,
          lo_page       TYPE REF TO cl_o2_api_pages,
          lt_pages_info TYPE ty_pages_tt.

    FIELD-SYMBOLS: <ls_page> LIKE LINE OF lt_pages_info.

    io_xml->read( EXPORTING iv_name = 'ATTRIBUTES'
                  CHANGING cg_data = ls_attributes ).
    io_xml->read( EXPORTING iv_name = 'NAVGRAPH'
                  CHANGING cg_data = lt_navgraph ).
    io_xml->read( EXPORTING iv_name = 'PAGES'
                  CHANGING cg_data = lt_pages_info ).

    ls_attributes-devclass = iv_package.

* todo: overwrite existing
    cl_o2_api_application=>create_new(
      EXPORTING
        p_application_data      = ls_attributes
        p_nodes                 = lt_nodes
        p_navgraph              = lt_navgraph
      IMPORTING
        p_application           = lo_bsp
      EXCEPTIONS
        object_already_existing = 1
        object_just_created     = 2
        not_authorized          = 3
        undefined_name          = 4
        author_not_existing     = 5
        action_cancelled        = 6
        error_occured           = 7
        invalid_parameter       = 8 ).
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |WAPA - error from create_new: { sy-subrc }| ).
    ENDIF.

    lo_bsp->save( ).

    lo_bsp->set_changeable(
      p_changeable           = abap_false
      p_complete_application = abap_true ).

    ls_item-obj_type = 'WAPD'.
    ls_item-obj_name = ms_item-obj_name.
    lcl_objects_activation=>add_item( ls_item ).

    lv_objkey = ls_item-obj_name.
* todo, hmm, the WAPD is not added to the worklist during activation
    cl_o2_api_application=>activate( lv_objkey ).

    LOOP AT lt_pages_info ASSIGNING <ls_page>.
      cl_o2_api_pages=>create_new_page(
        EXPORTING
          p_pageattrs = <ls_page>-attributes
        IMPORTING
          p_page      = lo_page ).

      IF <ls_page>-attributes-pagetype <> so2_controller.

        SPLIT <ls_page>-attributes-pagename AT '.' INTO lv_extra lv_ext.
        REPLACE ALL OCCURRENCES OF '_-' IN lv_extra WITH '/'.
        lv_content = mo_files->read_raw( iv_extra = lv_extra
                                         iv_ext   = lv_ext ).
        lo_page->set_page( to_page_content( lv_content ) ).

        lo_page->set_event_handlers( <ls_page>-event_handlers ).
        lo_page->set_parameters( <ls_page>-parameters ).
        lo_page->set_type_source( <ls_page>-types ).

      ENDIF.

      lo_page->save( p_with_all_texts = abap_true ).

      lv_obj_name = cl_wb_object_type=>get_concatenated_key_from_id(
        p_key_component1 = <ls_page>-attributes-applname
        p_key_component2 = <ls_page>-attributes-pagekey
        p_external_id    = 'WG ' ).

      lcl_objects_activation=>add( iv_type = 'WAPP'
                                   iv_name = lv_obj_name ).

    ENDLOOP.

  ENDMETHOD.                    "deserialize

  METHOD lif_object~serialize.

    DATA: lv_name       TYPE o2applname,
          ls_attributes TYPE o2applattr,
          lt_navgraph   TYPE o2applgrap_table,
          lt_pages      TYPE o2pagelist,
          lt_pages_info TYPE ty_pages_tt,
          lo_bsp        TYPE REF TO cl_o2_api_application.

    FIELD-SYMBOLS: <ls_page> LIKE LINE OF lt_pages.

    lv_name = ms_item-obj_name.

    cl_o2_api_application=>load(
      EXPORTING
        p_application_name  = lv_name
      IMPORTING
        p_application       = lo_bsp
      EXCEPTIONS
        object_not_existing = 1
        permission_failure  = 2
        error_occured       = 3 ).
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    lo_bsp->get_attributes(
      EXPORTING
        p_version    = c_active
      IMPORTING
        p_attributes = ls_attributes ).

    CLEAR: ls_attributes-author,
           ls_attributes-createdon,
           ls_attributes-changedby,
           ls_attributes-changedon,
           ls_attributes-devclass.

    io_xml->add( iv_name = 'ATTRIBUTES'
                 ig_data = ls_attributes ).

    lo_bsp->get_navgraph(
      EXPORTING
        p_version  = c_active
      IMPORTING
        p_navgraph = lt_navgraph ).

    io_xml->add( iv_name = 'NAVGRAPH'
                 ig_data = lt_navgraph ).

    cl_o2_api_pages=>get_all_pages(
      EXPORTING
        p_applname = lv_name
        p_version  = c_active
      IMPORTING
        p_pages    = lt_pages ).

    LOOP AT lt_pages ASSIGNING <ls_page>.
      APPEND read_page( <ls_page> ) TO lt_pages_info.
    ENDLOOP.

    io_xml->add( iv_name = 'PAGES'
                 ig_data = lt_pages_info ).

  ENDMETHOD.                    "serialize

  METHOD read_page.

    DATA: lv_name    TYPE o2applname,
          ls_pagekey TYPE o2pagkey,
          lv_content TYPE xstring,
          lv_extra   TYPE string,
          lv_ext     TYPE string,
          lo_page    TYPE REF TO cl_o2_api_pages.

    lv_name = ms_item-obj_name.

    ls_pagekey-applname = lv_name.
    ls_pagekey-pagekey = is_page-pagekey.

    cl_o2_api_pages=>load(
      EXPORTING
        p_pagekey = ls_pagekey
      IMPORTING
        p_page    = lo_page ).

    lo_page->get_attrs(
      IMPORTING
        p_attrs = rs_page-attributes ).

    IF rs_page-attributes-pagetype <> so2_controller.

      lo_page->get_event_handlers(
        IMPORTING
          p_ev_handler = rs_page-event_handlers
        EXCEPTIONS
          page_deleted = 1
          invalid_call = 2 ).
      ASSERT sy-subrc = 0.

      lo_page->get_parameters(
        IMPORTING
          p_parameters = rs_page-parameters
        EXCEPTIONS
          page_deleted = 1
          invalid_call = 2
          OTHERS       = 3 ).
      ASSERT sy-subrc = 0.

      lo_page->get_type_source(
        IMPORTING
          p_source     = rs_page-types
        EXCEPTIONS
          page_deleted = 1
          invalid_call = 2
          OTHERS       = 3 ).
      ASSERT sy-subrc = 0.

      lv_content = get_page_content( lo_page ).
      SPLIT is_page-pagename AT '.' INTO lv_extra lv_ext.
      REPLACE ALL OCCURRENCES OF '/' IN lv_extra WITH '_-'.
      mo_files->add_raw(
        iv_extra = lv_extra
        iv_ext   = lv_ext
        iv_data  = lv_content ).

      CLEAR: rs_page-attributes-implclass.

    ENDIF.

    CLEAR: rs_page-attributes-author,
           rs_page-attributes-createdon,
           rs_page-attributes-changedby,
           rs_page-attributes-changedon,
           rs_page-attributes-changetime,
           rs_page-attributes-gendate,
           rs_page-attributes-gentime,
           rs_page-attributes-devclass.

  ENDMETHOD.

  METHOD to_page_content.

    DATA: lv_string TYPE string.

    lv_string = lcl_convert=>xstring_to_string_utf8( iv_content ).

    SPLIT lv_string AT zif_abapgit_definitions=>gc_newline INTO TABLE rt_content.

  ENDMETHOD.

  METHOD get_page_content.

    DATA: lt_content TYPE o2pageline_table,
          lv_string  TYPE string.

    io_page->get_page(
      IMPORTING
        p_content = lt_content
      EXCEPTIONS
        invalid_call = 1
        page_deleted = 2
        OTHERS       = 3 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |WAPA - error from get_page_content| ).
    ENDIF.

    CONCATENATE LINES OF lt_content INTO lv_string SEPARATED BY zif_abapgit_definitions=>gc_newline RESPECTING BLANKS.

    rv_content = lcl_convert=>string_to_xstring_utf8( lv_string ).

  ENDMETHOD.

  METHOD lif_object~compare_to_remote_version.
    CREATE OBJECT ro_comparison_result TYPE lcl_comparison_null.
  ENDMETHOD.

ENDCLASS.                    "lcl_object_tran IMPLEMENTATION

Fix Issue 985

Fix Issue 985


*&---------------------------------------------------------------------*
*&  Include  zabapgit_requirements
*&---------------------------------------------------------------------*

"! Helper class for checking requirements / dependencies
CLASS lcl_requirement_helper DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES:
      BEGIN OF gty_status,
        met               TYPE abap_bool,
        component         TYPE dlvunit,
        description       TYPE text80,
        installed_release TYPE saprelease,
        installed_patch   TYPE sappatchlv,
        required_release  TYPE saprelease,
        required_patch    TYPE sappatchlv,
      END OF gty_status,
      gty_status_tab TYPE STANDARD TABLE OF gty_status WITH DEFAULT KEY.
    CLASS-METHODS:
      "! Check if the given requirements are met with user interaction
      "! <p>
      "! Shows a popup if requested and asks the user if he wants to continue if there are unmet
      "! requirements. If not an exception is raised.
      "! </p>
      "! @parameter it_requirements | The requirements to check
      "! @parameter iv_show_popup | Show popup with requirements
      "! @raising lcx_exception | Cancelled by user or internal error
      check_requirements IMPORTING it_requirements TYPE lcl_dot_abapgit=>ty_requirement_tab
                                   iv_show_popup   TYPE abap_bool DEFAULT abap_true
                         RAISING   lcx_exception,
      "! Get a table with information about each requirement
      "! @parameter it_requirements | Requirements
      "! @parameter rt_status | Result
      "! @raising lcx_exception | Internal error
      get_requirement_met_status IMPORTING it_requirements  TYPE lcl_dot_abapgit=>ty_requirement_tab
                                 RETURNING VALUE(rt_status) TYPE gty_status_tab
                                 RAISING   lcx_exception.
  PROTECTED SECTION.
  PRIVATE SECTION.
    CLASS-METHODS:
      show_requirement_popup IMPORTING it_requirements TYPE gty_status_tab
                             RAISING   lcx_exception,
      version_greater_or_equal IMPORTING is_status      TYPE gty_status
                               RETURNING VALUE(rv_true) TYPE abap_bool.
ENDCLASS.

CLASS lcl_requirement_helper IMPLEMENTATION.
  METHOD check_requirements.
    DATA: lt_met_status TYPE gty_status_tab,
          lv_answer     TYPE c LENGTH 1.

    lt_met_status = get_requirement_met_status( it_requirements ).

    IF iv_show_popup = abap_true.
      show_requirement_popup( lt_met_status ).
    ENDIF.

    LOOP AT lt_met_status TRANSPORTING NO FIELDS WHERE met = abap_false.
      EXIT.
    ENDLOOP.

    IF sy-subrc = 0.
      CALL FUNCTION 'POPUP_TO_CONFIRM'
        EXPORTING
          text_question = 'The project has unmet requirements. Install anyways?'
        IMPORTING
          answer        = lv_answer.
      IF lv_answer <> '1'.
        lcx_exception=>raise( 'Cancelling because of unmet requirements.' ).
      ENDIF.
    ENDIF.
  ENDMETHOD.

  METHOD get_requirement_met_status.
    DATA: lt_installed TYPE STANDARD TABLE OF cvers_sdu.
    FIELD-SYMBOLS: <ls_requirement>    TYPE lcl_dot_abapgit=>ty_requirement,
                   <ls_status>         TYPE gty_status,
                   <ls_installed_comp> TYPE cvers_sdu.

    CALL FUNCTION 'DELIVERY_GET_INSTALLED_COMPS'
      TABLES
        tt_comptab       = lt_installed
      EXCEPTIONS
        no_release_found = 1
        OTHERS           = 2.
    IF sy-subrc <> 0.
      lcx_exception=>raise( |Error from DELIVERY_GET_INSTALLED_COMPS { sy-subrc }| ) ##NO_TEXT.
    ENDIF.

    LOOP AT it_requirements ASSIGNING <ls_requirement>.
      APPEND INITIAL LINE TO rt_status ASSIGNING <ls_status>.
      <ls_status>-component = <ls_requirement>-component.
      <ls_status>-required_release = <ls_requirement>-min_release.
      <ls_status>-required_patch = <ls_requirement>-min_patch.

      READ TABLE lt_installed WITH KEY component = <ls_requirement>-component
                              ASSIGNING <ls_installed_comp>.
      IF sy-subrc = 0.
        <ls_status>-installed_release = <ls_installed_comp>-release.
        <ls_status>-installed_patch = <ls_installed_comp>-extrelease.
        <ls_status>-description = <ls_installed_comp>-desc_text.

        <ls_status>-met = version_greater_or_equal( <ls_status> ).
      ENDIF.

      UNASSIGN <ls_installed_comp>.
    ENDLOOP.
  ENDMETHOD.

  METHOD version_greater_or_equal.
    DATA: lv_number TYPE numc4.

    TRY.
        MOVE EXACT: is_status-installed_release TO lv_number,
                    is_status-installed_patch   TO lv_number,
                    is_status-required_release  TO lv_number,
                    is_status-required_patch    TO lv_number.
      CATCH cx_sy_conversion_error.
        " Cannot compare by number, assume requirement not fullfilled (user can force install
        " anyways if this was an error)
        rv_true = abap_false.
        RETURN.
    ENDTRY.

    " Check if versions are comparable by number
    IF is_status-installed_release > is_status-required_release
       OR ( is_status-installed_release = is_status-required_release
            AND ( is_status-required_patch IS INITIAL OR
                  is_status-installed_patch >= is_status-required_patch ) ).

      rv_true = abap_true.
    ENDIF.
  ENDMETHOD.

  METHOD show_requirement_popup.
    TYPES: BEGIN OF lty_color_line,
             color TYPE lvc_t_scol.
        INCLUDE TYPE gty_status.
    TYPES: END OF lty_color_line,
    lty_color_tab TYPE STANDARD TABLE OF lty_color_line WITH DEFAULT KEY.
    DATA: lo_alv         TYPE REF TO cl_salv_table,
          lo_column      TYPE REF TO cl_salv_column,
          lt_color_table TYPE lty_color_tab,
          lt_color_neg   TYPE lvc_t_scol,
          lt_color_pos   TYPE lvc_t_scol,
          ls_color       TYPE lvc_s_scol,
          lx_ex          TYPE REF TO cx_root.
    FIELD-SYMBOLS: <ls_line> TYPE lty_color_line.

    ls_color-color-col = col_negative.
    APPEND ls_color TO lt_color_neg.

    ls_color-color-col = col_positive.
    APPEND ls_color TO lt_color_pos.

    CLEAR ls_color.

    MOVE-CORRESPONDING it_requirements TO lt_color_table.

    LOOP AT lt_color_table ASSIGNING <ls_line>.
      IF <ls_line>-met = abap_false.
        <ls_line>-color = lt_color_neg.
      ELSE.
        <ls_line>-color = lt_color_pos.
      ENDIF.
    ENDLOOP.
    UNASSIGN <ls_line>.

    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table   = lo_alv
          CHANGING
            t_table        = lt_color_table
        ).

        lo_alv->get_columns(:
          )->get_column( 'MET' )->set_short_text( 'Met' ),
          )->set_color_column( 'COLOR' ),
          )->set_optimize( ),
        ).

        lo_column = lo_alv->get_columns( )->get_column( 'REQUIRED_RELEASE' ).
        lo_column->set_fixed_header_text( 'S').
        lo_column->set_short_text( 'Req. Rel.' ).

        lo_column = lo_alv->get_columns( )->get_column( 'REQUIRED_PATCH' ).
        lo_column->set_fixed_header_text( 'S').
        lo_column->set_short_text( 'Req. SP L.' ).

        lo_alv->set_screen_popup( start_column = 30
                                  end_column   = 100
                                  start_line   = 10
                                  end_line     = 20 ).
        lo_alv->get_display_settings( )->set_list_header( 'Requirements' ).
        lo_alv->display( ).

      CATCH cx_salv_msg cx_salv_not_found cx_salv_data_error INTO lx_ex.
        RAISE EXCEPTION TYPE lcx_exception
          EXPORTING
            iv_text     = lx_ex->get_text( )
            ix_previous = lx_ex.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

*&---------------------------------------------------------------------*
*&  Include  zabapgit_requirements
*&---------------------------------------------------------------------*

"! Helper class for checking requirements / dependencies
CLASS lcl_requirement_helper DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES:
      BEGIN OF gty_status,
        met               TYPE abap_bool,
        component         TYPE dlvunit,
        description       TYPE text80,
        installed_release TYPE saprelease,
        installed_patch   TYPE sappatchlv,
        required_release  TYPE saprelease,
        required_patch    TYPE sappatchlv,
      END OF gty_status,
      gty_status_tab TYPE STANDARD TABLE OF gty_status WITH DEFAULT KEY.
    CLASS-METHODS:
      "! Check if the given requirements are met with user interaction
      "! <p>
      "! Shows a popup if requested and asks the user if he wants to continue if there are unmet
      "! requirements. If not an exception is raised.
      "! </p>
      "! @parameter it_requirements | The requirements to check
      "! @parameter iv_show_popup | Show popup with requirements
      "! @raising lcx_exception | Cancelled by user or internal error
      check_requirements IMPORTING it_requirements TYPE lcl_dot_abapgit=>ty_requirement_tab
                                   iv_show_popup   TYPE abap_bool DEFAULT abap_true
                         RAISING   lcx_exception,
      "! Get a table with information about each requirement
      "! @parameter it_requirements | Requirements
      "! @parameter rt_status | Result
      "! @raising lcx_exception | Internal error
      get_requirement_met_status IMPORTING it_requirements  TYPE lcl_dot_abapgit=>ty_requirement_tab
                                 RETURNING VALUE(rt_status) TYPE gty_status_tab
                                 RAISING   lcx_exception.
  PROTECTED SECTION.
  PRIVATE SECTION.
    CLASS-METHODS:
      show_requirement_popup IMPORTING it_requirements TYPE gty_status_tab
                             RAISING   lcx_exception,
      version_greater_or_equal IMPORTING is_status      TYPE gty_status
                               RETURNING VALUE(rv_true) TYPE abap_bool.
ENDCLASS.

CLASS lcl_requirement_helper IMPLEMENTATION.
  METHOD check_requirements.
    DATA: lt_met_status TYPE gty_status_tab,
          lv_answer     TYPE c LENGTH 1.

    lt_met_status = get_requirement_met_status( it_requirements ).

    IF iv_show_popup = abap_true.
      show_requirement_popup( lt_met_status ).
    ENDIF.

    LOOP AT lt_met_status TRANSPORTING NO FIELDS WHERE met = abap_false.
      EXIT.
    ENDLOOP.

    IF sy-subrc = 0.
      CALL FUNCTION 'POPUP_TO_CONFIRM'
        EXPORTING
          text_question = 'The project has unmet requirements. Install anyways?'
        IMPORTING
          answer        = lv_answer.
      IF lv_answer <> '1'.
        lcx_exception=>raise( 'Cancelling because of unmet requirements.' ).
      ENDIF.
    ENDIF.
  ENDMETHOD.

  METHOD get_requirement_met_status.
    DATA: lt_installed TYPE STANDARD TABLE OF cvers_sdu.
    FIELD-SYMBOLS: <ls_requirement>    TYPE lcl_dot_abapgit=>ty_requirement,
                   <ls_status>         TYPE gty_status,
                   <ls_installed_comp> TYPE cvers_sdu.

    CALL FUNCTION 'DELIVERY_GET_INSTALLED_COMPS'
      TABLES
        tt_comptab       = lt_installed
      EXCEPTIONS
        no_release_found = 1
        OTHERS           = 2.
    IF sy-subrc <> 0.
      lcx_exception=>raise( |Error from DELIVERY_GET_INSTALLED_COMPS { sy-subrc }| ) ##NO_TEXT.
    ENDIF.

    LOOP AT it_requirements ASSIGNING <ls_requirement>.
      APPEND INITIAL LINE TO rt_status ASSIGNING <ls_status>.
      <ls_status>-component = <ls_requirement>-component.
      <ls_status>-required_release = <ls_requirement>-min_release.
      <ls_status>-required_patch = <ls_requirement>-min_patch.

      READ TABLE lt_installed WITH KEY component = <ls_requirement>-component
                              ASSIGNING <ls_installed_comp>.
      IF sy-subrc = 0.
        <ls_status>-installed_release = <ls_installed_comp>-release.
        <ls_status>-installed_patch = <ls_installed_comp>-extrelease.
        <ls_status>-description = <ls_installed_comp>-desc_text.

        <ls_status>-met = version_greater_or_equal( <ls_status> ).
      ENDIF.

      UNASSIGN <ls_installed_comp>.
    ENDLOOP.
  ENDMETHOD.

  METHOD version_greater_or_equal.
    DATA: lv_number TYPE numc4.

    TRY.
        MOVE EXACT: is_status-installed_release TO lv_number,
                    is_status-installed_patch   TO lv_number,
                    is_status-required_release  TO lv_number,
                    is_status-required_patch    TO lv_number.
      CATCH cx_sy_conversion_error.
        " Cannot compare by number, assume requirement not fullfilled (user can force install
        " anyways if this was an error)
        rv_true = abap_false.
        RETURN.
    ENDTRY.

    " Check if versions are comparable by number
    IF is_status-installed_release > is_status-required_release
       OR ( is_status-installed_release = is_status-required_release
            AND ( is_status-required_patch IS INITIAL OR
                  is_status-installed_patch >= is_status-required_patch ) ).

      rv_true = abap_true.
    ENDIF.
  ENDMETHOD.

  METHOD show_requirement_popup.
    TYPES: BEGIN OF lty_color_line,
             color TYPE lvc_t_scol.
        INCLUDE TYPE gty_status.
    TYPES: END OF lty_color_line,
    lty_color_tab TYPE STANDARD TABLE OF lty_color_line WITH DEFAULT KEY.
    DATA: lo_alv         TYPE REF TO cl_salv_table,
          lo_column      TYPE REF TO cl_salv_column,
          lo_columns     TYPE REF TO cl_salv_columns_table,
          lt_color_table TYPE lty_color_tab,
          lt_color_neg   TYPE lvc_t_scol,
          lt_color_pos   TYPE lvc_t_scol,
          ls_color       TYPE lvc_s_scol,
          lx_ex          TYPE REF TO cx_root.
    FIELD-SYMBOLS: <ls_line> TYPE lty_color_line.

    ls_color-color-col = col_negative.
    APPEND ls_color TO lt_color_neg.

    ls_color-color-col = col_positive.
    APPEND ls_color TO lt_color_pos.

    CLEAR ls_color.

    MOVE-CORRESPONDING it_requirements TO lt_color_table.

    LOOP AT lt_color_table ASSIGNING <ls_line>.
      IF <ls_line>-met = abap_false.
        <ls_line>-color = lt_color_neg.
      ELSE.
        <ls_line>-color = lt_color_pos.
      ENDIF.
    ENDLOOP.
    UNASSIGN <ls_line>.

    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table   = lo_alv
          CHANGING
            t_table        = lt_color_table
        ).

        lo_columns = lo_alv->get_columns( ).
        lo_columns->get_column( 'MET' )->set_short_text( 'Met' ).
        lo_columns->set_color_column( 'COLOR' ).
        lo_columns->set_optimize( ).

        lo_column = lo_columns->get_column( 'REQUIRED_RELEASE' ).
        lo_column->set_fixed_header_text( 'S').
        lo_column->set_short_text( 'Req. Rel.' ).

        lo_column = lo_columns->get_column( 'REQUIRED_PATCH' ).
        lo_column->set_fixed_header_text( 'S').
        lo_column->set_short_text( 'Req. SP L.' ).

        lo_alv->set_screen_popup( start_column = 30
                                  end_column   = 100
                                  start_line   = 10
                                  end_line     = 20 ).
        lo_alv->get_display_settings( )->set_list_header( 'Requirements' ).
        lo_alv->display( ).

      CATCH cx_salv_msg cx_salv_not_found cx_salv_data_error INTO lx_ex.
        RAISE EXCEPTION TYPE lcx_exception
          EXPORTING
            iv_text     = lx_ex->get_text( )
            ix_previous = lx_ex.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

Apply requested changes from code review


*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_FORMS
*&---------------------------------------------------------------------*

*&---------------------------------------------------------------------*
*&      Form  run
*&---------------------------------------------------------------------*
FORM run.

  DATA: lx_exception TYPE REF TO zcx_abapgit_exception,
        lv_ind       TYPE t000-ccnocliind.

  TRY.
      zcl_abapgit_migrations=>run( ).
      PERFORM open_gui.
    CATCH zcx_abapgit_exception INTO lx_exception.
      MESSAGE lx_exception TYPE 'E'.
  ENDTRY.

ENDFORM.                    "run

FORM open_gui RAISING zcx_abapgit_exception.

  IF sy-batch = abap_true.
    zcl_abapgit_background=>run( ).
  ELSE.

    zcl_abapgit_services_abapgit=>prepare_gui_startup( ).
    zcl_abapgit_ui_factory=>get_gui( )->go_home( ).
    CALL SELECTION-SCREEN 1001. " trigger screen

  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  branch_popup
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->TT_FIELDS      text
*      -->PV_CODE        text
*      -->CS_ERROR       text
*      -->CV_SHOW_POPUP  text
*      -->RAISING        text
*      -->zcx_abapgit_exception  text
*      -->##CALLED       text
*      -->##NEEDED       text
*----------------------------------------------------------------------*
FORM branch_popup TABLES   tt_fields TYPE zif_abapgit_definitions=>ty_sval_tt
                  USING    pv_code TYPE clike
                  CHANGING cs_error TYPE svale
                           cv_show_popup TYPE c
                  RAISING zcx_abapgit_exception ##called ##needed.
* called dynamically from function module POPUP_GET_VALUES_USER_BUTTONS

  DATA: lx_error  TYPE REF TO zcx_abapgit_exception,
        li_popups TYPE REF TO zif_abapgit_popups.

  TRY.
      li_popups = zcl_abapgit_ui_factory=>get_popups( ).
      li_popups->branch_popup_callback(
        EXPORTING
          iv_code       = pv_code
        CHANGING
          ct_fields     = tt_fields[]
          cs_error      = cs_error
          cv_show_popup = cv_show_popup ).

    CATCH zcx_abapgit_exception INTO lx_error.
      MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

ENDFORM.                    "branch_popup

FORM package_popup TABLES   tt_fields TYPE zif_abapgit_definitions=>ty_sval_tt
                   USING    pv_code TYPE clike
                   CHANGING cs_error TYPE svale
                            cv_show_popup TYPE c
                   RAISING  zcx_abapgit_exception ##called ##needed.
* called dynamically from function module POPUP_GET_VALUES_USER_BUTTONS

  DATA: lx_error  TYPE REF TO zcx_abapgit_exception,
        li_popups TYPE REF TO zif_abapgit_popups.

  TRY.
      li_popups = zcl_abapgit_ui_factory=>get_popups( ).
      li_popups->package_popup_callback(
        EXPORTING
          iv_code       = pv_code
        CHANGING
          ct_fields     = tt_fields[]
          cs_error      = cs_error
          cv_show_popup = cv_show_popup ).

    CATCH zcx_abapgit_exception INTO lx_error.
      MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

ENDFORM.                    "package_popup

FORM output.
  DATA: lt_ucomm TYPE TABLE OF sy-ucomm.

  PERFORM set_pf_status IN PROGRAM rsdbrunt IF FOUND.

  APPEND 'CRET' TO lt_ucomm.  "Button Execute
  APPEND 'SPOS' TO lt_ucomm.  "Button Save

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

ENDFORM.

FORM exit RAISING zcx_abapgit_exception.
  DATA li_page TYPE REF TO zif_abapgit_gui_renderable.
  CASE sy-ucomm.
    WHEN 'CBAC'.  "Back
      IF zcl_abapgit_ui_factory=>get_gui( )->back( ) = abap_true. " end of stack
        zcl_abapgit_ui_factory=>get_gui( )->free( ). " Graceful shutdown
      ELSE.
        LEAVE TO SCREEN 1001.
      ENDIF.
    WHEN 'CEND'.
      CREATE OBJECT li_page TYPE zcl_abapgit_gui_page_main.
      zcl_abapgit_ui_factory=>get_gui( )->go_page( li_page ).
      LEAVE TO SCREEN 1001.
  ENDCASE.
ENDFORM.

FORM password_popup
      USING
        iv_repo_url TYPE string
      CHANGING
        cv_user     TYPE string
        cv_pass     TYPE string.

  lcl_password_dialog=>popup(
    EXPORTING
      iv_repo_url     = iv_repo_url
    CHANGING
      cv_user         = cv_user
      cv_pass         = cv_pass ).

ENDFORM.

FORM remove_toolbar USING pv_dynnr TYPE char4.

  DATA: ls_header               TYPE rpy_dyhead,
        lt_containers           TYPE dycatt_tab,
        lt_fields_to_containers TYPE dyfatc_tab,
        lt_flow_logic           TYPE swydyflow.

  CALL FUNCTION 'RPY_DYNPRO_READ'
    EXPORTING
      progname             = sy-cprog
      dynnr                = pv_dynnr
    IMPORTING
      header               = ls_header
    TABLES
      containers           = lt_containers
      fields_to_containers = lt_fields_to_containers
      flow_logic           = lt_flow_logic
    EXCEPTIONS
      cancelled            = 1
      not_found            = 2
      permission_error     = 3
      OTHERS               = 4.
  IF sy-subrc IS NOT INITIAL.
    RETURN. " Ignore errors, just exit
  ENDIF.

  IF ls_header-no_toolbar = abap_true.
    RETURN. " No change required
  ENDIF.

  ls_header-no_toolbar = abap_true.

  CALL FUNCTION 'RPY_DYNPRO_INSERT'
    EXPORTING
      header                 = ls_header
      suppress_exist_checks  = abap_true
    TABLES
      containers             = lt_containers
      fields_to_containers   = lt_fields_to_containers
      flow_logic             = lt_flow_logic
    EXCEPTIONS
      cancelled              = 1
      already_exists         = 2
      program_not_exists     = 3
      not_executed           = 4
      missing_required_field = 5
      illegal_field_value    = 6
      field_not_allowed      = 7
      not_generated          = 8
      illegal_field_position = 9
      OTHERS                 = 10.
  IF sy-subrc <> 2 AND sy-subrc <> 0.
    RETURN. " Ignore errors, just exit
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_FORMS
*&---------------------------------------------------------------------*

*&---------------------------------------------------------------------*
*&      Form  run
*&---------------------------------------------------------------------*
FORM run.

  DATA: lx_exception TYPE REF TO zcx_abapgit_exception,
        lv_ind       TYPE t000-ccnocliind.

  TRY.
      zcl_abapgit_migrations=>run( ).
      PERFORM open_gui.
    CATCH zcx_abapgit_exception INTO lx_exception.
      MESSAGE lx_exception TYPE 'E'.
  ENDTRY.

ENDFORM.                    "run

FORM open_gui RAISING zcx_abapgit_exception.

  IF sy-batch = abap_true.
    zcl_abapgit_background=>run( ).
  ELSE.

    zcl_abapgit_services_abapgit=>prepare_gui_startup( ).
    zcl_abapgit_ui_factory=>get_gui( )->go_home( ).
    CALL SELECTION-SCREEN 1001. " trigger screen

  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  branch_popup
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->TT_FIELDS      text
*      -->PV_CODE        text
*      -->CS_ERROR       text
*      -->CV_SHOW_POPUP  text
*      -->RAISING        text
*      -->zcx_abapgit_exception  text
*      -->##CALLED       text
*      -->##NEEDED       text
*----------------------------------------------------------------------*
FORM branch_popup TABLES   tt_fields TYPE zif_abapgit_definitions=>ty_sval_tt
                  USING    pv_code TYPE clike
                  CHANGING cs_error TYPE svale
                           cv_show_popup TYPE c
                  RAISING zcx_abapgit_exception ##called ##needed.
* called dynamically from function module POPUP_GET_VALUES_USER_BUTTONS

  DATA: lx_error  TYPE REF TO zcx_abapgit_exception,
        li_popups TYPE REF TO zif_abapgit_popups.

  TRY.
      li_popups = zcl_abapgit_ui_factory=>get_popups( ).
      li_popups->branch_popup_callback(
        EXPORTING
          iv_code       = pv_code
        CHANGING
          ct_fields     = tt_fields[]
          cs_error      = cs_error
          cv_show_popup = cv_show_popup ).

    CATCH zcx_abapgit_exception INTO lx_error.
      MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

ENDFORM.                    "branch_popup

FORM package_popup TABLES   tt_fields TYPE zif_abapgit_definitions=>ty_sval_tt
                   USING    pv_code TYPE clike
                   CHANGING cs_error TYPE svale
                            cv_show_popup TYPE c
                   RAISING  zcx_abapgit_exception ##called ##needed.
* called dynamically from function module POPUP_GET_VALUES_USER_BUTTONS

  DATA: lx_error  TYPE REF TO zcx_abapgit_exception,
        li_popups TYPE REF TO zif_abapgit_popups.

  TRY.
      li_popups = zcl_abapgit_ui_factory=>get_popups( ).
      li_popups->package_popup_callback(
        EXPORTING
          iv_code       = pv_code
        CHANGING
          ct_fields     = tt_fields[]
          cs_error      = cs_error
          cv_show_popup = cv_show_popup ).

    CATCH zcx_abapgit_exception INTO lx_error.
      MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

ENDFORM.                    "package_popup

FORM output.
  DATA: lt_ucomm TYPE TABLE OF sy-ucomm.

  PERFORM set_pf_status IN PROGRAM rsdbrunt IF FOUND.

  APPEND 'CRET' TO lt_ucomm.  "Button Execute
  APPEND 'SPOS' TO lt_ucomm.  "Button Save

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

ENDFORM.

FORM exit RAISING zcx_abapgit_exception.
  CASE sy-ucomm.
    WHEN 'CBAC'.  "Back
      IF zcl_abapgit_ui_factory=>get_gui( )->back( ) = abap_true. " end of stack
        zcl_abapgit_ui_factory=>get_gui( )->free( ). " Graceful shutdown
      ELSE.
        LEAVE TO SCREEN 1001.
      ENDIF.
  ENDCASE.
ENDFORM.

FORM password_popup
      USING
        iv_repo_url TYPE string
      CHANGING
        cv_user     TYPE string
        cv_pass     TYPE string.

  lcl_password_dialog=>popup(
    EXPORTING
      iv_repo_url     = iv_repo_url
    CHANGING
      cv_user         = cv_user
      cv_pass         = cv_pass ).

ENDFORM.

FORM remove_toolbar USING pv_dynnr TYPE char4.

  DATA: ls_header               TYPE rpy_dyhead,
        lt_containers           TYPE dycatt_tab,
        lt_fields_to_containers TYPE dyfatc_tab,
        lt_flow_logic           TYPE swydyflow.

  CALL FUNCTION 'RPY_DYNPRO_READ'
    EXPORTING
      progname             = sy-cprog
      dynnr                = pv_dynnr
    IMPORTING
      header               = ls_header
    TABLES
      containers           = lt_containers
      fields_to_containers = lt_fields_to_containers
      flow_logic           = lt_flow_logic
    EXCEPTIONS
      cancelled            = 1
      not_found            = 2
      permission_error     = 3
      OTHERS               = 4.
  IF sy-subrc IS NOT INITIAL.
    RETURN. " Ignore errors, just exit
  ENDIF.

  IF ls_header-no_toolbar = abap_true.
    RETURN. " No change required
  ENDIF.

  ls_header-no_toolbar = abap_true.

  CALL FUNCTION 'RPY_DYNPRO_INSERT'
    EXPORTING
      header                 = ls_header
      suppress_exist_checks  = abap_true
    TABLES
      containers             = lt_containers
      fields_to_containers   = lt_fields_to_containers
      flow_logic             = lt_flow_logic
    EXCEPTIONS
      cancelled              = 1
      already_exists         = 2
      program_not_exists     = 3
      not_executed           = 4
      missing_required_field = 5
      illegal_field_value    = 6
      field_not_allowed      = 7
      not_generated          = 8
      illegal_field_position = 9
      OTHERS                 = 10.
  IF sy-subrc <> 2 AND sy-subrc <> 0.
    RETURN. " Ignore errors, just exit
  ENDIF.

ENDFORM.

Revert behavior of second back button (#2779)

* Revert behavior of second back button

* Leave clearing of stack on go home