mirror of
https://github.com/abapGit/abapGit.git
synced 2025-05-02 13:03:01 +08:00

* mark inactive objects in repo list Inactive object are marked in the repo list The sort order for changed files is not changed unchanged inactive files come right after the changed files * move acitve check to object interface * add is_active for objects up to F * add is_active for objects up to P * add is_active for objects up to T * add is_active for objects up to X all core object implement (except SSFO) the standard active check via FM RS_INACTIVE_OBJECTS_WARNING now * add is_active to plugins bridge - always active * finish object interface implementation + objects * add is_active for offline with object interface * rename returning to RV_ * use returning for serialize * cleanup, PP, UT
439 lines
16 KiB
ABAP
439 lines
16 KiB
ABAP
CLASS zcl_abapgit_file_status DEFINITION
|
|
PUBLIC
|
|
FINAL
|
|
CREATE PUBLIC .
|
|
|
|
PUBLIC SECTION.
|
|
|
|
CLASS-METHODS status
|
|
IMPORTING io_repo TYPE REF TO zcl_abapgit_repo
|
|
io_log TYPE REF TO zcl_abapgit_log OPTIONAL
|
|
RETURNING VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
PRIVATE SECTION.
|
|
|
|
CLASS-METHODS:
|
|
calculate_status
|
|
IMPORTING iv_devclass TYPE devclass
|
|
io_dot TYPE REF TO zcl_abapgit_dot_abapgit
|
|
it_local TYPE zif_abapgit_definitions=>ty_files_item_tt
|
|
it_remote TYPE zif_abapgit_definitions=>ty_files_tt
|
|
it_cur_state TYPE zif_abapgit_definitions=>ty_file_signatures_tt
|
|
RETURNING VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt
|
|
RAISING zcx_abapgit_exception,
|
|
run_checks
|
|
IMPORTING io_log TYPE REF TO zcl_abapgit_log
|
|
it_results TYPE zif_abapgit_definitions=>ty_results_tt
|
|
io_dot TYPE REF TO zcl_abapgit_dot_abapgit
|
|
iv_top TYPE devclass
|
|
RAISING zcx_abapgit_exception,
|
|
build_existing
|
|
IMPORTING is_local TYPE zif_abapgit_definitions=>ty_file_item
|
|
is_remote TYPE zif_abapgit_definitions=>ty_file
|
|
it_state TYPE zif_abapgit_definitions=>ty_file_signatures_ts
|
|
RETURNING VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_result,
|
|
build_new_local
|
|
IMPORTING is_local TYPE zif_abapgit_definitions=>ty_file_item
|
|
RETURNING VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_result,
|
|
build_new_remote
|
|
IMPORTING iv_devclass TYPE devclass
|
|
io_dot TYPE REF TO zcl_abapgit_dot_abapgit
|
|
is_remote TYPE zif_abapgit_definitions=>ty_file
|
|
it_items TYPE zif_abapgit_definitions=>ty_items_ts
|
|
it_state TYPE zif_abapgit_definitions=>ty_file_signatures_ts
|
|
RETURNING VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_result
|
|
RAISING zcx_abapgit_exception,
|
|
identify_object
|
|
IMPORTING iv_filename TYPE string
|
|
iv_path TYPE string
|
|
iv_devclass TYPE devclass
|
|
io_dot TYPE REF TO zcl_abapgit_dot_abapgit
|
|
EXPORTING es_item TYPE zif_abapgit_definitions=>ty_item
|
|
ev_is_xml TYPE abap_bool
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
ENDCLASS.
|
|
|
|
|
|
|
|
CLASS ZCL_ABAPGIT_FILE_STATUS IMPLEMENTATION.
|
|
|
|
|
|
METHOD build_existing.
|
|
|
|
DATA: ls_file_sig LIKE LINE OF it_state.
|
|
|
|
" Item
|
|
rs_result-obj_type = is_local-item-obj_type.
|
|
rs_result-obj_name = is_local-item-obj_name.
|
|
rs_result-package = is_local-item-devclass.
|
|
|
|
" File
|
|
rs_result-path = is_local-file-path.
|
|
rs_result-filename = is_local-file-filename.
|
|
|
|
IF is_local-file-sha1 = is_remote-sha1.
|
|
rs_result-match = abap_true.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" Match against current state
|
|
READ TABLE it_state INTO ls_file_sig
|
|
WITH KEY path = is_local-file-path
|
|
filename = is_local-file-filename
|
|
BINARY SEARCH.
|
|
|
|
IF sy-subrc = 0.
|
|
IF ls_file_sig-sha1 <> is_local-file-sha1.
|
|
rs_result-lstate = zif_abapgit_definitions=>c_state-modified.
|
|
ENDIF.
|
|
IF ls_file_sig-sha1 <> is_remote-sha1.
|
|
rs_result-rstate = zif_abapgit_definitions=>c_state-modified.
|
|
ENDIF.
|
|
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 = zif_abapgit_definitions=>c_state-modified.
|
|
rs_result-rstate = zif_abapgit_definitions=>c_state-modified.
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD build_new_local.
|
|
|
|
" Item
|
|
rs_result-obj_type = is_local-item-obj_type.
|
|
rs_result-obj_name = is_local-item-obj_name.
|
|
rs_result-package = is_local-item-devclass.
|
|
|
|
" File
|
|
rs_result-path = is_local-file-path.
|
|
rs_result-filename = is_local-file-filename.
|
|
|
|
" Match
|
|
rs_result-match = abap_false.
|
|
rs_result-lstate = zif_abapgit_definitions=>c_state-added.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD build_new_remote.
|
|
|
|
DATA: ls_item LIKE LINE OF it_items,
|
|
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 = zif_abapgit_definitions=>c_state-added.
|
|
|
|
identify_object( EXPORTING iv_filename = is_remote-filename
|
|
iv_path = is_remote-path
|
|
iv_devclass = iv_devclass
|
|
io_dot = io_dot
|
|
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 = zif_abapgit_definitions=>c_state-modified.
|
|
ENDIF.
|
|
|
|
" Item is in state and in cache but with no package - it was deleted
|
|
" OR devclass is the same as repo package (see #532)
|
|
IF ls_item-devclass IS INITIAL OR ls_item-devclass = iv_devclass.
|
|
rs_result-match = abap_false.
|
|
rs_result-lstate = zif_abapgit_definitions=>c_state-deleted.
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
ELSE. " Completely unknown file, probably non-abapgit
|
|
ASSERT 1 = 1. " No action, just follow defaults
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD calculate_status.
|
|
|
|
DATA: lt_remote LIKE it_remote,
|
|
lt_items TYPE zif_abapgit_definitions=>ty_items_tt,
|
|
ls_item LIKE LINE OF lt_items,
|
|
lv_is_xml TYPE abap_bool,
|
|
lv_sub_fetched TYPE abap_bool,
|
|
lt_sub_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt,
|
|
lt_items_idx TYPE zif_abapgit_definitions=>ty_items_ts,
|
|
lt_state_idx TYPE zif_abapgit_definitions=>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( <ls_local> ).
|
|
ENDIF.
|
|
<ls_result>-inactive = <ls_local>-item-inactive.
|
|
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
|
|
iv_path = <ls_remote>-path
|
|
io_dot = io_dot
|
|
iv_devclass = iv_devclass
|
|
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 = zcl_abapgit_factory=>get_tadir( )->get_object_package(
|
|
iv_object = ls_item-obj_type
|
|
iv_obj_name = ls_item-obj_name ).
|
|
|
|
IF NOT ls_item-devclass IS INITIAL AND iv_devclass <> ls_item-devclass.
|
|
IF lv_sub_fetched = abap_false.
|
|
lt_sub_packages = zcl_abapgit_factory=>get_sap_package( iv_devclass )->list_subpackages( ).
|
|
lv_sub_fetched = abap_true.
|
|
SORT lt_sub_packages BY table_line. "Optimize Read Access
|
|
ENDIF.
|
|
* make sure the package is under the repo main package
|
|
READ TABLE lt_sub_packages TRANSPORTING NO FIELDS
|
|
WITH KEY table_line = ls_item-devclass
|
|
BINARY SEARCH.
|
|
IF sy-subrc <> 0.
|
|
CLEAR ls_item-devclass.
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
APPEND ls_item TO lt_items.
|
|
ENDLOOP.
|
|
|
|
SORT lt_items DESCENDING. " Default key - type, name, pkg, inactive
|
|
DELETE ADJACENT DUPLICATES FROM lt_items COMPARING obj_type obj_name devclass.
|
|
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( iv_devclass = iv_devclass
|
|
io_dot = io_dot
|
|
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.
|
|
|
|
|
|
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 '/'.
|
|
REPLACE ALL OCCURRENCES OF '#' IN lv_type WITH '/'.
|
|
REPLACE ALL OCCURRENCES OF '#' IN lv_ext WITH '/'.
|
|
|
|
" Try to get a unique package name for DEVC by using the path
|
|
IF lv_type = 'DEVC'.
|
|
ASSERT lv_name = 'PACKAGE'.
|
|
lv_name = zcl_abapgit_folder_logic=>get_instance( )->path_to_package(
|
|
iv_top = iv_devclass
|
|
io_dot = io_dot
|
|
iv_create_if_not_exists = abap_false
|
|
iv_path = iv_path ).
|
|
ENDIF.
|
|
|
|
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.
|
|
|
|
|
|
METHOD run_checks.
|
|
|
|
DATA: lv_path TYPE string,
|
|
ls_item TYPE zif_abapgit_definitions=>ty_item,
|
|
ls_file TYPE zif_abapgit_definitions=>ty_file_signature,
|
|
lt_res_sort LIKE it_results,
|
|
lt_item_idx LIKE it_results.
|
|
DATA: lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic.
|
|
|
|
FIELD-SYMBOLS: <ls_res1> LIKE LINE OF it_results,
|
|
<ls_res2> LIKE LINE OF it_results.
|
|
|
|
|
|
IF io_log IS INITIAL.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" Collect object indexe
|
|
lt_res_sort = it_results.
|
|
SORT lt_res_sort BY obj_type ASCENDING obj_name ASCENDING.
|
|
|
|
LOOP AT it_results ASSIGNING <ls_res1> WHERE NOT obj_type IS INITIAL.
|
|
IF NOT ( <ls_res1>-obj_type = ls_item-obj_type
|
|
AND <ls_res1>-obj_name = ls_item-obj_name ).
|
|
APPEND INITIAL LINE TO lt_item_idx ASSIGNING <ls_res2>.
|
|
<ls_res2>-obj_type = <ls_res1>-obj_type.
|
|
<ls_res2>-obj_name = <ls_res1>-obj_name.
|
|
<ls_res2>-path = <ls_res1>-path.
|
|
MOVE-CORRESPONDING <ls_res1> TO ls_item.
|
|
ENDIF.
|
|
ENDLOOP.
|
|
|
|
" Check files for one object is in the same folder
|
|
|
|
LOOP AT it_results ASSIGNING <ls_res1> WHERE NOT obj_type IS INITIAL AND obj_type <> 'DEVC'.
|
|
READ TABLE lt_item_idx ASSIGNING <ls_res2>
|
|
WITH KEY obj_type = <ls_res1>-obj_type obj_name = <ls_res1>-obj_name
|
|
BINARY SEARCH. " Sorted above
|
|
|
|
IF sy-subrc <> 0 OR <ls_res1>-path <> <ls_res2>-path. " All paths are same
|
|
io_log->add( iv_msg = |Files for object { <ls_res1>-obj_type } {
|
|
<ls_res1>-obj_name } are not placed in the same folder|
|
|
iv_type = 'W'
|
|
iv_rc = '1' ) ##no_text.
|
|
ENDIF.
|
|
ENDLOOP.
|
|
|
|
" Check that objects are created in package corresponding to folder
|
|
lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ).
|
|
LOOP AT it_results ASSIGNING <ls_res1>
|
|
WHERE NOT package IS INITIAL AND NOT path IS INITIAL.
|
|
lv_path = lo_folder_logic->package_to_path(
|
|
iv_top = iv_top
|
|
io_dot = io_dot
|
|
iv_package = <ls_res1>-package ).
|
|
IF lv_path <> <ls_res1>-path.
|
|
io_log->add( iv_msg = |Package and path does not match for object, {
|
|
<ls_res1>-obj_type } { <ls_res1>-obj_name }|
|
|
iv_type = 'W'
|
|
iv_rc = '2' ) ##no_text.
|
|
ENDIF.
|
|
ENDLOOP.
|
|
|
|
" Check for multiple files with same filename
|
|
SORT lt_res_sort BY filename ASCENDING.
|
|
|
|
LOOP AT lt_res_sort ASSIGNING <ls_res1> WHERE obj_type <> 'DEVC'.
|
|
IF <ls_res1>-filename IS NOT INITIAL AND <ls_res1>-filename = ls_file-filename.
|
|
io_log->add( iv_msg = |Multiple files with same filename, { <ls_res1>-filename }|
|
|
iv_type = 'W'
|
|
iv_rc = '3' ) ##no_text.
|
|
ENDIF.
|
|
|
|
IF <ls_res1>-filename IS INITIAL.
|
|
io_log->add( iv_msg = |Filename is empty for object { <ls_res1>-obj_type } { <ls_res1>-obj_name }|
|
|
iv_type = 'W'
|
|
iv_rc = '4' ) ##no_text.
|
|
ENDIF.
|
|
|
|
MOVE-CORRESPONDING <ls_res1> TO ls_file.
|
|
ENDLOOP.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD status.
|
|
|
|
DATA: lv_index LIKE sy-tabix,
|
|
lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit.
|
|
|
|
FIELD-SYMBOLS <ls_result> LIKE LINE OF rt_results.
|
|
|
|
|
|
rt_results = calculate_status(
|
|
iv_devclass = io_repo->get_package( )
|
|
io_dot = io_repo->get_dot_abapgit( )
|
|
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.
|
|
CONTINUE.
|
|
ENDIF.
|
|
ENDLOOP.
|
|
|
|
run_checks(
|
|
io_log = io_log
|
|
it_results = rt_results
|
|
io_dot = lo_dot_abapgit
|
|
iv_top = io_repo->get_package( ) ).
|
|
|
|
ENDMETHOD.
|
|
ENDCLASS.
|