File status refactoring, part 2 (#6124)

Co-authored-by: Marc Bernard <59966492+mbtools@users.noreply.github.com>
Co-authored-by: Lars Hvam <larshp@hotmail.com>
This commit is contained in:
Alexander Tsybulsky 2023-03-06 20:45:20 +02:00 committed by GitHub
parent af2b111c7b
commit c8636912f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 522 additions and 358 deletions

View File

@ -20,6 +20,18 @@ CLASS zcl_abapgit_filename_logic DEFINITION
END OF c_json_file.
CLASS-METHODS detect_obj_definition
IMPORTING
!iv_type TYPE string
!iv_ext TYPE string
EXPORTING
!ev_is_xml TYPE abap_bool
!ev_is_json TYPE abap_bool.
CLASS-METHODS is_obj_definition_file
IMPORTING
!iv_filename TYPE string
RETURNING
VALUE(rv_yes) TYPE abap_bool.
CLASS-METHODS file_to_object
IMPORTING
!iv_filename TYPE string
@ -48,7 +60,15 @@ ENDCLASS.
CLASS zcl_abapgit_filename_logic IMPLEMENTATION.
CLASS ZCL_ABAPGIT_FILENAME_LOGIC IMPLEMENTATION.
METHOD detect_obj_definition.
ev_is_xml = boolc( iv_ext = to_upper( c_package_file-extension ) AND strlen( iv_type ) = 4 ).
ev_is_json = boolc( iv_ext = to_upper( c_json_file-extension ) AND strlen( iv_type ) = 4 ).
ENDMETHOD.
METHOD file_to_object.
@ -89,8 +109,37 @@ CLASS zcl_abapgit_filename_logic IMPLEMENTATION.
CLEAR es_item.
es_item-obj_type = lv_type.
es_item-obj_name = lv_name.
ev_is_xml = boolc( lv_ext = to_upper( c_package_file-extension ) AND strlen( lv_type ) = 4 ).
ev_is_json = boolc( lv_ext = to_upper( c_json_file-extension ) AND strlen( lv_type ) = 4 ).
detect_obj_definition(
EXPORTING
iv_ext = lv_ext
iv_type = lv_type
IMPORTING
ev_is_xml = ev_is_xml
ev_is_json = ev_is_json ).
ENDMETHOD.
METHOD is_obj_definition_file.
DATA:
lv_xml TYPE abap_bool,
lv_json TYPE abap_bool,
lv_name TYPE string,
lv_type TYPE string,
lv_ext TYPE string.
SPLIT to_upper( iv_filename ) AT '.' INTO lv_name lv_type lv_ext.
detect_obj_definition(
EXPORTING
iv_ext = lv_ext
iv_type = lv_type
IMPORTING
ev_is_xml = lv_xml
ev_is_json = lv_json ).
rv_yes = boolc( lv_json = abap_true OR lv_xml = abap_true ).
ENDMETHOD.

View File

@ -9,6 +9,7 @@ CLASS ltcl_run_checks DEFINITION FOR TESTING RISK LEVEL HARMLESS
METHODS:
setup,
is_obj_def_file FOR TESTING,
dot_abapgit FOR TESTING RAISING zcx_abapgit_exception,
file_to_object FOR TESTING RAISING zcx_abapgit_exception,
object_to_file FOR TESTING RAISING zcx_abapgit_exception,
@ -45,6 +46,26 @@ CLASS ltcl_run_checks IMPLEMENTATION.
ENDMETHOD.
METHOD is_obj_def_file.
cl_abap_unit_assert=>assert_equals(
act = zcl_abapgit_filename_logic=>is_obj_definition_file( zif_abapgit_definitions=>c_dot_abapgit )
exp = abap_false ).
cl_abap_unit_assert=>assert_equals(
act = zcl_abapgit_filename_logic=>is_obj_definition_file( 'ztest.prog.xml' )
exp = abap_true ).
cl_abap_unit_assert=>assert_equals(
act = zcl_abapgit_filename_logic=>is_obj_definition_file( 'ztest.prog.json' )
exp = abap_true ).
cl_abap_unit_assert=>assert_equals(
act = zcl_abapgit_filename_logic=>is_obj_definition_file( 'ztest.prog.abap' )
exp = abap_false ).
ENDMETHOD.
METHOD file_to_object.
DATA ls_item TYPE zif_abapgit_definitions=>ty_item.

View File

@ -60,12 +60,6 @@ CLASS zcl_abapgit_file_status DEFINITION
!ct_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
METHODS run_checks
IMPORTING
!ii_log TYPE REF TO zif_abapgit_log
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
CLASS-METHODS build_existing
IMPORTING
!is_local TYPE zif_abapgit_definitions=>ty_file_item
@ -95,45 +89,6 @@ CLASS zcl_abapgit_file_status DEFINITION
VALUE(rv_devclass) TYPE devclass
RAISING
zcx_abapgit_exception .
CLASS-METHODS check_package_move
IMPORTING
!ii_log TYPE REF TO zif_abapgit_log
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
CLASS-METHODS check_files_folder
IMPORTING
!ii_log TYPE REF TO zif_abapgit_log
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
CLASS-METHODS check_package_sub_package
IMPORTING
!ii_log TYPE REF TO zif_abapgit_log
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
!iv_top TYPE devclass
RAISING
zcx_abapgit_exception .
CLASS-METHODS check_package_folder
IMPORTING
!ii_log TYPE REF TO zif_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 .
CLASS-METHODS check_multiple_files
IMPORTING
!ii_log TYPE REF TO zif_abapgit_log
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
CLASS-METHODS check_namespace
IMPORTING
!ii_log TYPE REF TO zif_abapgit_log
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
CLASS-METHODS check_local_remote_consistency
IMPORTING
!is_local TYPE zif_abapgit_definitions=>ty_file_item
@ -151,7 +106,7 @@ ENDCLASS.
CLASS zcl_abapgit_file_status IMPLEMENTATION.
CLASS ZCL_ABAPGIT_FILE_STATUS IMPLEMENTATION.
METHOD build_existing.
@ -339,52 +294,6 @@ CLASS zcl_abapgit_file_status IMPLEMENTATION.
ENDMETHOD.
METHOD check_files_folder.
DATA:
ls_item TYPE zif_abapgit_definitions=>ty_item,
lt_res_sort LIKE it_results,
lt_item_idx LIKE it_results.
FIELD-SYMBOLS:
<ls_result> LIKE LINE OF it_results,
<ls_result_idx> LIKE LINE OF it_results.
" Collect object index
lt_res_sort = it_results.
SORT lt_res_sort BY obj_type ASCENDING obj_name ASCENDING.
LOOP AT it_results ASSIGNING <ls_result> WHERE NOT obj_type IS INITIAL AND packmove = abap_false.
IF NOT ( <ls_result>-obj_type = ls_item-obj_type
AND <ls_result>-obj_name = ls_item-obj_name ).
APPEND INITIAL LINE TO lt_item_idx ASSIGNING <ls_result_idx>.
<ls_result_idx>-obj_type = <ls_result>-obj_type.
<ls_result_idx>-obj_name = <ls_result>-obj_name.
<ls_result_idx>-path = <ls_result>-path.
MOVE-CORRESPONDING <ls_result> TO ls_item.
ENDIF.
ENDLOOP.
LOOP AT it_results ASSIGNING <ls_result>
WHERE NOT obj_type IS INITIAL AND obj_type <> 'DEVC' AND packmove = abap_false.
READ TABLE lt_item_idx ASSIGNING <ls_result_idx>
WITH KEY obj_type = <ls_result>-obj_type obj_name = <ls_result>-obj_name
BINARY SEARCH. " Sorted above
IF sy-subrc <> 0 OR <ls_result>-path <> <ls_result_idx>-path. " All paths are same
ii_log->add( iv_msg = |Files for object { <ls_result>-obj_type } {
<ls_result>-obj_name } are not placed in the same folder|
iv_type = 'W' ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD check_local_remote_consistency.
IF is_remote-sha1 IS INITIAL.
IF is_local-file-filename = zcl_abapgit_filename_logic=>c_package_file.
@ -400,156 +309,6 @@ CLASS zcl_abapgit_file_status IMPLEMENTATION.
ENDMETHOD.
METHOD check_multiple_files.
DATA:
lt_res_sort LIKE it_results,
ls_file TYPE zif_abapgit_git_definitions=>ty_file_signature.
FIELD-SYMBOLS <ls_result> LIKE LINE OF it_results.
lt_res_sort = it_results.
SORT lt_res_sort BY filename ASCENDING.
LOOP AT lt_res_sort ASSIGNING <ls_result> WHERE obj_type <> 'DEVC' AND packmove = abap_false.
IF <ls_result>-filename IS NOT INITIAL AND <ls_result>-filename = ls_file-filename.
ii_log->add( iv_msg = |Multiple files with same filename, { <ls_result>-filename }|
iv_type = 'W' ).
ENDIF.
IF <ls_result>-filename IS INITIAL.
ii_log->add( iv_msg = |Filename is empty for object { <ls_result>-obj_type } { <ls_result>-obj_name }|
iv_type = 'W' ).
ENDIF.
MOVE-CORRESPONDING <ls_result> TO ls_file.
ENDLOOP.
ENDMETHOD.
METHOD check_namespace.
DATA:
lv_namespace TYPE namespace,
lt_namespace TYPE TABLE OF namespace,
ls_trnspace TYPE trnspace.
FIELD-SYMBOLS <ls_result> LIKE LINE OF it_results.
" Collect all namespaces based on name of xml-files
LOOP AT it_results ASSIGNING <ls_result>.
FIND REGEX '^#([a-zA-Z0-9]+)#.*\..*\.xml$' IN <ls_result>-filename SUBMATCHES lv_namespace.
IF sy-subrc = 0.
lv_namespace = '/' && to_upper( lv_namespace ) && '/'.
COLLECT lv_namespace INTO lt_namespace.
ENDIF.
ENDLOOP.
LOOP AT lt_namespace INTO lv_namespace.
SELECT SINGLE editflag FROM trnspace INTO ls_trnspace-editflag WHERE namespace = lv_namespace.
IF sy-subrc <> 0.
ii_log->add( iv_msg = |Namespace { lv_namespace } does not exist. Create it in transaction SE03|
iv_type = 'W' ).
ELSEIF ls_trnspace-editflag <> 'X'.
ii_log->add( iv_msg = |Namespace { lv_namespace } is not modifiable. Check it in transaction SE03|
iv_type = 'W' ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD check_package_folder.
DATA:
lv_path TYPE string,
lv_object TYPE string,
lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic.
FIELD-SYMBOLS <ls_result> LIKE LINE OF it_results.
lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ).
LOOP AT it_results ASSIGNING <ls_result>
WHERE NOT package IS INITIAL AND NOT path IS INITIAL AND packmove = abap_false.
lv_path = lo_folder_logic->package_to_path(
iv_top = iv_top
io_dot = io_dot
iv_package = <ls_result>-package ).
lv_object = |{ <ls_result>-obj_type } { <ls_result>-obj_name }|.
IF lv_path IS INITIAL.
ii_log->add_error( |{ lv_object } already exists outside of { iv_top } package hierarchy| ).
ELSEIF lv_path <> <ls_result>-path.
ii_log->add_warning( |Package and path do not match for object { lv_object }| ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD check_package_move.
DATA:
lt_move_idx LIKE it_results.
FIELD-SYMBOLS:
<ls_result> LIKE LINE OF it_results,
<ls_result_move> LIKE LINE OF it_results.
LOOP AT it_results ASSIGNING <ls_result>
WHERE lstate = zif_abapgit_definitions=>c_state-added AND packmove = abap_true.
READ TABLE lt_move_idx TRANSPORTING NO FIELDS
WITH KEY obj_type = <ls_result>-obj_type obj_name = <ls_result>-obj_name
BINARY SEARCH. " Sorted since it_result is sorted
IF sy-subrc <> 0.
ii_log->add( iv_msg = |Changed package assignment for object {
<ls_result>-obj_type } { <ls_result>-obj_name }|
iv_type = 'W' ).
APPEND INITIAL LINE TO lt_move_idx ASSIGNING <ls_result_move>.
<ls_result_move>-obj_type = <ls_result>-obj_type.
<ls_result_move>-obj_name = <ls_result>-obj_name.
<ls_result_move>-path = <ls_result>-path.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD check_package_sub_package.
DATA lv_msg TYPE string.
FIELD-SYMBOLS <ls_result> LIKE LINE OF it_results.
LOOP AT it_results ASSIGNING <ls_result> WHERE package IS INITIAL AND obj_type = 'DEVC'.
IF zcl_abapgit_factory=>get_sap_package( |{ <ls_result>-obj_name }| )->exists( ) = abap_true.
" If package already exist but is not included in the package hierarchy of
" the package assigned to the repository, then a manual change of the package
" is required i.e. setting a parent package to the repo package (or one of its
" subpackages). We don't do this automatically since it's not clear where in the
" hierarchy the new package should be located or whether the sub package shall be
" removed from the repo.
lv_msg = |Package { <ls_result>-obj_name } already exists but is not a sub-package of { iv_top }. |
&& |Check your package and folder logic, and either assign { <ls_result>-obj_name } |
&& |to the package hierarchy of { iv_top } or remove package { <ls_result>-obj_name } |
&& |from the repository.|.
ii_log->add( iv_msg = lv_msg
iv_type = 'W' ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD constructor.
mv_root_package = iv_root_package.
mo_dot = io_dot.
@ -657,7 +416,8 @@ CLASS zcl_abapgit_file_status IMPLEMENTATION.
iv_path = <ls_local>-file-path
iv_filename = <ls_local>-file-filename ) = abap_false.
IF <ls_local>-item IS NOT INITIAL.
IF <ls_local>-item IS NOT INITIAL
AND zcl_abapgit_filename_logic=>is_obj_definition_file( <ls_local>-file-filename ) = abap_true.
" Collect for item index
APPEND <ls_local>-item TO ct_items.
ENDIF.
@ -687,6 +447,7 @@ CLASS zcl_abapgit_file_status IMPLEMENTATION.
WITH KEY file
COMPONENTS filename = <ls_local>-file-filename.
IF sy-subrc = 0 AND <ls_local>-file-sha1 = <ls_remote>-sha1.
" If yes, then it was probably moved
<ls_result>-packmove = abap_true.
ELSEIF sy-subrc = 4.
" Check if file existed before and was deleted remotely
@ -700,7 +461,7 @@ CLASS zcl_abapgit_file_status IMPLEMENTATION.
ELSE.
<ls_result>-lstate = zif_abapgit_definitions=>c_state-modified.
ENDIF.
<ls_result>-rstate = zif_abapgit_definitions=>c_state-deleted.
<ls_result>-rstate = zif_abapgit_definitions=>c_state-deleted. " ??
ENDIF.
ENDIF.
ENDIF.
@ -751,55 +512,13 @@ CLASS zcl_abapgit_file_status IMPLEMENTATION.
ENDMETHOD.
METHOD run_checks.
" This method just adds messages to the log. No log, nothing to do here
IF ii_log IS INITIAL.
RETURN.
ENDIF.
" Find all objects which were assigned to a different package
check_package_move(
ii_log = ii_log
it_results = it_results ).
" Check files for one object is in the same folder
check_files_folder(
ii_log = ii_log
it_results = it_results ).
" Check that sub packages are included in the package hierarchy
check_package_sub_package(
ii_log = ii_log
it_results = it_results
iv_top = mv_root_package ).
" Check that objects are created in package corresponding to folder
check_package_folder(
ii_log = ii_log
it_results = it_results
io_dot = mo_dot
iv_top = mv_root_package ).
" Check for multiple files with same filename
check_multiple_files(
ii_log = ii_log
it_results = it_results ).
" Check if namespaces exist already
check_namespace(
ii_log = ii_log
it_results = it_results ).
ENDMETHOD.
METHOD status.
DATA lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt.
DATA lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt.
DATA li_exit TYPE REF TO zif_abapgit_exit.
DATA lo_instance TYPE REF TO zcl_abapgit_file_status.
DATA lo_consistency_checks TYPE REF TO lcl_status_consistency_checks.
lt_local = io_repo->get_files_local( ii_log = ii_log ).
@ -831,9 +550,14 @@ CLASS zcl_abapgit_file_status IMPLEMENTATION.
it_remote = lt_remote
it_cur_state = io_repo->zif_abapgit_repo~checksums( )->get_checksums_per_file( ) ).
lo_instance->run_checks(
ii_log = ii_log
it_results = rt_results ).
IF ii_log IS BOUND.
" This method just adds messages to the log. No log, nothing to do here
CREATE OBJECT lo_consistency_checks
EXPORTING
iv_root_package = io_repo->get_package( )
io_dot = io_repo->get_dot_abapgit( ).
ii_log->merge_with( lo_consistency_checks->run_checks( rt_results ) ).
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,301 @@
CLASS lcl_status_consistency_checks DEFINITION FINAL.
PUBLIC SECTION.
METHODS constructor
IMPORTING
iv_root_package TYPE devclass
io_dot TYPE REF TO zcl_abapgit_dot_abapgit.
METHODS run_checks
IMPORTING
it_results TYPE zif_abapgit_definitions=>ty_results_tt
RETURNING
VALUE(ri_log) TYPE REF TO zif_abapgit_log
RAISING
zcx_abapgit_exception .
PRIVATE SECTION.
DATA mv_root_package TYPE devclass.
DATA mo_dot TYPE REF TO zcl_abapgit_dot_abapgit.
DATA mi_log TYPE REF TO zif_abapgit_log.
METHODS check_package_move
IMPORTING
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
METHODS check_files_folder
IMPORTING
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
METHODS check_package_sub_package
IMPORTING
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
!iv_top TYPE devclass
RAISING
zcx_abapgit_exception .
METHODS check_package_folder
IMPORTING
!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 .
METHODS check_multiple_files
IMPORTING
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
METHODS check_namespace
IMPORTING
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RAISING
zcx_abapgit_exception .
ENDCLASS.
CLASS lcl_status_consistency_checks IMPLEMENTATION.
METHOD constructor.
mv_root_package = iv_root_package.
mo_dot = io_dot.
ENDMETHOD.
METHOD run_checks.
CREATE OBJECT mi_log TYPE zcl_abapgit_log.
" Find all objects which were assigned to a different package
check_package_move( it_results ).
" Check files for one object is in the same folder
check_files_folder( it_results ).
" Check that sub packages are included in the package hierarchy
check_package_sub_package(
it_results = it_results
iv_top = mv_root_package ).
" Check that objects are created in package corresponding to folder
check_package_folder(
it_results = it_results
io_dot = mo_dot
iv_top = mv_root_package ).
" Check for multiple files with same filename
check_multiple_files( it_results ).
" Check if namespaces exist already
check_namespace( it_results ).
ri_log = mi_log.
ENDMETHOD.
METHOD check_files_folder.
DATA:
ls_item TYPE zif_abapgit_definitions=>ty_item,
lt_res_sort LIKE it_results,
lt_item_idx LIKE it_results.
FIELD-SYMBOLS:
<ls_result> LIKE LINE OF it_results,
<ls_result_idx> LIKE LINE OF it_results.
" TODO optimize ?
" sort by obj, path
" loop, and compare to first object record
" Collect object index
lt_res_sort = it_results.
SORT lt_res_sort BY obj_type ASCENDING obj_name ASCENDING.
LOOP AT it_results ASSIGNING <ls_result> WHERE NOT obj_type IS INITIAL AND packmove = abap_false.
IF NOT ( <ls_result>-obj_type = ls_item-obj_type
AND <ls_result>-obj_name = ls_item-obj_name ).
APPEND INITIAL LINE TO lt_item_idx ASSIGNING <ls_result_idx>.
<ls_result_idx>-obj_type = <ls_result>-obj_type.
<ls_result_idx>-obj_name = <ls_result>-obj_name.
<ls_result_idx>-path = <ls_result>-path.
MOVE-CORRESPONDING <ls_result> TO ls_item.
ENDIF.
ENDLOOP.
LOOP AT it_results ASSIGNING <ls_result>
WHERE NOT obj_type IS INITIAL AND obj_type <> 'DEVC' AND packmove = abap_false.
READ TABLE lt_item_idx ASSIGNING <ls_result_idx>
WITH KEY obj_type = <ls_result>-obj_type obj_name = <ls_result>-obj_name
BINARY SEARCH. " Sorted above
IF sy-subrc <> 0 OR <ls_result>-path <> <ls_result_idx>-path. " All paths are same
mi_log->add( iv_msg = |Files for object { <ls_result>-obj_type } {
<ls_result>-obj_name } are not placed in the same folder|
iv_type = 'W' ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD check_multiple_files.
DATA:
lt_res_sort LIKE it_results,
ls_file TYPE zif_abapgit_git_definitions=>ty_file_signature.
FIELD-SYMBOLS <ls_result> LIKE LINE OF it_results.
lt_res_sort = it_results.
SORT lt_res_sort BY filename ASCENDING.
LOOP AT lt_res_sort ASSIGNING <ls_result> WHERE obj_type <> 'DEVC' AND packmove = abap_false.
IF <ls_result>-filename IS NOT INITIAL AND <ls_result>-filename = ls_file-filename.
mi_log->add( iv_msg = |Multiple files with same filename, { <ls_result>-filename }|
iv_type = 'W' ).
ENDIF.
IF <ls_result>-filename IS INITIAL.
mi_log->add( iv_msg = |Filename is empty for object { <ls_result>-obj_type } { <ls_result>-obj_name }|
iv_type = 'W' ).
ENDIF.
MOVE-CORRESPONDING <ls_result> TO ls_file.
ENDLOOP.
ENDMETHOD.
METHOD check_namespace.
DATA:
li_namespace TYPE REF TO zif_abapgit_sap_namespace,
lv_namespace TYPE namespace,
lt_namespace TYPE TABLE OF namespace.
FIELD-SYMBOLS <ls_result> LIKE LINE OF it_results.
" Collect all namespaces based on name of xml-files
LOOP AT it_results ASSIGNING <ls_result>.
FIND REGEX '^#([a-zA-Z0-9]+)#.*\..*\.xml$' IN <ls_result>-filename SUBMATCHES lv_namespace.
IF sy-subrc = 0.
lv_namespace = '/' && to_upper( lv_namespace ) && '/'.
COLLECT lv_namespace INTO lt_namespace.
ENDIF.
ENDLOOP.
li_namespace = zcl_abapgit_factory=>get_sap_namespace( ).
LOOP AT lt_namespace INTO lv_namespace.
IF li_namespace->exists( lv_namespace ) = abap_false.
mi_log->add(
iv_msg = |Namespace { lv_namespace } does not exist. Create it in transaction SE03|
iv_type = 'W' ).
ELSEIF li_namespace->is_editable( lv_namespace ) = abap_false.
mi_log->add(
iv_msg = |Namespace { lv_namespace } is not modifiable. Check it in transaction SE03|
iv_type = 'W' ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD check_package_folder.
DATA:
lv_path TYPE string,
lv_object TYPE string,
lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic.
FIELD-SYMBOLS <ls_result> LIKE LINE OF it_results.
lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ).
LOOP AT it_results ASSIGNING <ls_result>
WHERE NOT package IS INITIAL AND NOT path IS INITIAL AND packmove = abap_false.
lv_path = lo_folder_logic->package_to_path(
iv_top = iv_top
io_dot = io_dot
iv_package = <ls_result>-package ).
lv_object = |{ <ls_result>-obj_type } { <ls_result>-obj_name }|.
IF lv_path IS INITIAL.
mi_log->add_error( |{ lv_object } already exists outside of { iv_top } package hierarchy| ).
ELSEIF lv_path <> <ls_result>-path.
mi_log->add_warning( |Package and path do not match for object { lv_object }| ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD check_package_move.
DATA lt_move_idx LIKE it_results.
FIELD-SYMBOLS:
<ls_result> LIKE LINE OF it_results,
<ls_result_move> LIKE LINE OF it_results.
" TODO: optimize ?
" delete where packmove = false, delete adj duplicates and fire messages ?
LOOP AT it_results ASSIGNING <ls_result>
WHERE lstate = zif_abapgit_definitions=>c_state-added AND packmove = abap_true.
READ TABLE lt_move_idx TRANSPORTING NO FIELDS
WITH KEY
obj_type = <ls_result>-obj_type
obj_name = <ls_result>-obj_name
BINARY SEARCH. " Sorted since it_result is sorted
IF sy-subrc <> 0.
mi_log->add(
iv_msg = |Changed package assignment for object { <ls_result>-obj_type } { <ls_result>-obj_name }|
iv_type = 'W' ).
APPEND INITIAL LINE TO lt_move_idx ASSIGNING <ls_result_move>.
<ls_result_move>-obj_type = <ls_result>-obj_type.
<ls_result_move>-obj_name = <ls_result>-obj_name.
<ls_result_move>-path = <ls_result>-path.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD check_package_sub_package.
DATA lv_msg TYPE string.
FIELD-SYMBOLS <ls_result> LIKE LINE OF it_results.
LOOP AT it_results ASSIGNING <ls_result> WHERE package IS INITIAL AND obj_type = 'DEVC'.
IF zcl_abapgit_factory=>get_sap_package( |{ <ls_result>-obj_name }| )->exists( ) = abap_true.
" If package already exist but is not included in the package hierarchy of
" the package assigned to the repository, then a manual change of the package
" is required i.e. setting a parent package to the repo package (or one of its
" subpackages). We don't do this automatically since it's not clear where in the
" hierarchy the new package should be located or whether the sub package shall be
" removed from the repo.
lv_msg = |Package { <ls_result>-obj_name } already exists but is not a sub-package of { iv_top }. |
&& |Check your package and folder logic, and either assign { <ls_result>-obj_name } |
&& |to the package hierarchy of { iv_top } or remove package { <ls_result>-obj_name } |
&& |from the repository.|.
mi_log->add( iv_msg = lv_msg
iv_type = 'W' ).
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@ -34,13 +34,14 @@ CLASS ltcl_run_checks DEFINITION FOR TESTING RISK LEVEL HARMLESS
DURATION SHORT FINAL.
PUBLIC SECTION.
INTERFACES: zif_abapgit_sap_package.
INTERFACES zif_abapgit_sap_package.
INTERFACES zif_abapgit_sap_namespace.
PRIVATE SECTION.
DATA: mt_results TYPE zif_abapgit_definitions=>ty_results_tt,
mo_instance TYPE REF TO zcl_abapgit_file_status,
mo_dot TYPE REF TO zcl_abapgit_dot_abapgit,
mi_log TYPE REF TO zif_abapgit_log.
DATA: mt_results TYPE zif_abapgit_definitions=>ty_results_tt,
mo_instance TYPE REF TO lcl_status_consistency_checks,
mo_dot TYPE REF TO zcl_abapgit_dot_abapgit,
mi_log TYPE REF TO zif_abapgit_log.
METHODS:
append_result IMPORTING iv_obj_type TYPE trobjtype
@ -118,6 +119,13 @@ CLASS ltcl_run_checks IMPLEMENTATION.
RETURN.
ENDMETHOD.
METHOD zif_abapgit_sap_namespace~exists.
rv_yes = boolc( iv_namespace <> 'NOTEXIST' ).
ENDMETHOD.
METHOD zif_abapgit_sap_namespace~is_editable.
ENDMETHOD.
METHOD append_result.
DATA ls_result LIKE LINE OF mt_results.
@ -151,6 +159,8 @@ CLASS ltcl_run_checks IMPLEMENTATION.
zcl_abapgit_injector=>set_sap_package( iv_package = '$MAIN_SUB'
ii_sap_package = me ).
zcl_abapgit_injector=>set_sap_namespace( me ).
CREATE OBJECT mo_instance
EXPORTING
iv_root_package = '$Z$'
@ -197,9 +207,7 @@ CLASS ltcl_run_checks IMPLEMENTATION.
iv_path = '/'
iv_filename = 'zdoma2.doma.xml' ).
mo_instance->run_checks(
ii_log = mi_log
it_results = mt_results ).
mi_log = mo_instance->run_checks( mt_results ).
cl_abap_unit_assert=>assert_equals(
act = mi_log->count( )
@ -246,9 +254,7 @@ CLASS ltcl_run_checks IMPLEMENTATION.
iv_path = '/'
iv_filename = 'zdoma2.doma.xml' ).
mo_instance->run_checks(
ii_log = mi_log
it_results = mt_results ).
mi_log = mo_instance->run_checks( mt_results ).
" This one is not pure - incorrect path also triggers path vs package check
cl_abap_unit_assert=>assert_equals(
@ -300,9 +306,7 @@ CLASS ltcl_run_checks IMPLEMENTATION.
iv_path = '/'
iv_filename = '$$zdoma2.doma.xml' ).
mo_instance->run_checks(
ii_log = mi_log
it_results = mt_results ).
mi_log = mo_instance->run_checks( mt_results ).
cl_abap_unit_assert=>assert_equals(
act = mi_log->count( )
@ -353,9 +357,7 @@ CLASS ltcl_run_checks IMPLEMENTATION.
iv_path = '/'
iv_filename = '$$zdoma1.doma.xml' ).
mo_instance->run_checks(
ii_log = mi_log
it_results = mt_results ).
mi_log = mo_instance->run_checks( mt_results ).
cl_abap_unit_assert=>assert_equals(
act = mi_log->count( )
@ -397,9 +399,7 @@ CLASS ltcl_run_checks IMPLEMENTATION.
iv_path = '/'
iv_filename = '' ).
mo_instance->run_checks(
ii_log = mi_log
it_results = mt_results ).
mi_log = mo_instance->run_checks( mt_results ).
cl_abap_unit_assert=>assert_equals(
act = mi_log->count( )
@ -474,9 +474,7 @@ CLASS ltcl_run_checks IMPLEMENTATION.
iv_filename = 'zdoma1.doma.xml'
iv_packmove = 'X' ).
mo_instance->run_checks(
ii_log = mi_log
it_results = mt_results ).
mi_log = mo_instance->run_checks( mt_results ).
" Three files, but only two msg (for two changed objects)
cl_abap_unit_assert=>assert_equals(
@ -506,9 +504,7 @@ CLASS ltcl_run_checks IMPLEMENTATION.
iv_root_package = '/NOTEXIST/Z'
io_dot = mo_dot.
mo_instance->run_checks(
ii_log = mi_log
it_results = mt_results ).
mi_log = mo_instance->run_checks( mt_results ).
cl_abap_unit_assert=>assert_equals(
act = mi_log->count( )
@ -545,9 +541,7 @@ CLASS ltcl_run_checks IMPLEMENTATION.
iv_root_package = '$MAIN'
io_dot = mo_dot.
mo_instance->run_checks(
ii_log = mi_log
it_results = mt_results ).
mi_log = mo_instance->run_checks( mt_results ).
cl_abap_unit_assert=>assert_equals(
act = mi_log->count( )

View File

@ -34,9 +34,7 @@ CLASS zcl_abapgit_repo_checksums DEFINITION
METHODS build_checksums_from_files
IMPORTING
it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt
it_local TYPE ty_local_files_by_item_tt
iv_branches_equal TYPE abap_bool DEFAULT abap_false
RETURNING
VALUE(rt_checksums) TYPE zif_abapgit_persistence=>ty_local_checksum_tt.
@ -79,13 +77,16 @@ CLASS ZCL_ABAPGIT_REPO_CHECKSUMS IMPLEMENTATION.
DATA ls_last_item TYPE zif_abapgit_definitions=>ty_item.
FIELD-SYMBOLS:
<ls_checksum> LIKE LINE OF rt_checksums,
<ls_local> LIKE LINE OF it_local.
FIELD-SYMBOLS:
<ls_remote_file> LIKE LINE OF it_remote,
<ls_checksum> LIKE LINE OF rt_checksums,
<ls_local> LIKE LINE OF it_local,
<ls_cs_file_sig> LIKE LINE OF <ls_checksum>-files.
" This methods is run at repo creation moment or manually by user
" In the first case it assumes that the local state is the CURRENT state
" Thus the idea is to copy local state to checksums
" The second case is an exception, when we acknoledge that the state is unknown
" Thus copying the local to checksums is the "best guess"
LOOP AT it_local ASSIGNING <ls_local>.
IF ls_last_item <> <ls_local>-item OR sy-tabix = 1. " First or New item reached ?
APPEND INITIAL LINE TO rt_checksums ASSIGNING <ls_checksum>.
@ -93,26 +94,9 @@ CLASS ZCL_ABAPGIT_REPO_CHECKSUMS IMPLEMENTATION.
ls_last_item = <ls_local>-item.
ENDIF.
READ TABLE it_remote ASSIGNING <ls_remote_file>
WITH TABLE KEY file_path
COMPONENTS
path = <ls_local>-file-path
filename = <ls_local>-file-filename.
IF sy-subrc <> 0. " Ignore new local ones
CONTINUE.
ENDIF.
APPEND INITIAL LINE TO <ls_checksum>-files ASSIGNING <ls_cs_file_sig>.
MOVE-CORRESPONDING <ls_local>-file TO <ls_cs_file_sig>.
" If hashes are equal -> local sha1 is OK already (no change)
" Else
" if branches equal -> assume changes were local, state - remote sha1
" if remote branch is ahead (not equal) -> assume changes were remote, state - local sha1 (no change)
IF <ls_local>-file-sha1 <> <ls_remote_file>-sha1 AND iv_branches_equal = abap_true.
<ls_cs_file_sig>-sha1 = <ls_remote_file>-sha1.
ENDIF.
ENDLOOP.
ENDMETHOD.
@ -208,20 +192,13 @@ CLASS ZCL_ABAPGIT_REPO_CHECKSUMS IMPLEMENTATION.
METHOD zif_abapgit_repo_checksums~rebuild.
DATA lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt.
DATA lt_local TYPE ty_local_files_by_item_tt.
DATA lt_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt.
lt_local = mi_repo->get_files_local( ).
lt_remote = mi_repo->get_files_remote( ).
remove_non_code_related_files( CHANGING ct_local_files = lt_local ).
lt_checksums = build_checksums_from_files(
it_remote = lt_remote
it_local = lt_local
iv_branches_equal = iv_branches_equal ).
lt_checksums = build_checksums_from_files( lt_local ).
save_checksums( lt_checksums ).
ENDMETHOD.

View File

@ -10,8 +10,6 @@ INTERFACE zif_abapgit_repo_checksums
VALUE(rt_checksums) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt .
METHODS rebuild
IMPORTING
iv_branches_equal TYPE abap_bool DEFAULT abap_false
RAISING
zcx_abapgit_exception.

View File

@ -38,6 +38,9 @@ CLASS zcl_abapgit_factory DEFINITION
CLASS-METHODS get_lxe_texts
RETURNING
VALUE(ri_lxe_texts) TYPE REF TO zif_abapgit_lxe_texts .
CLASS-METHODS get_sap_namespace
RETURNING
VALUE(ri_namespace) TYPE REF TO zif_abapgit_sap_namespace .
PROTECTED SECTION.
PRIVATE SECTION.
@ -67,11 +70,12 @@ CLASS zcl_abapgit_factory DEFINITION
CLASS-DATA gi_longtext TYPE REF TO zif_abapgit_longtexts .
CLASS-DATA gi_http_agent TYPE REF TO zif_abapgit_http_agent .
CLASS-DATA gi_lxe_texts TYPE REF TO zif_abapgit_lxe_texts .
CLASS-DATA gi_sap_namespace TYPE REF TO zif_abapgit_sap_namespace .
ENDCLASS.
CLASS zcl_abapgit_factory IMPLEMENTATION.
CLASS ZCL_ABAPGIT_FACTORY IMPLEMENTATION.
METHOD get_code_inspector.
@ -147,6 +151,17 @@ CLASS zcl_abapgit_factory IMPLEMENTATION.
ENDMETHOD.
METHOD get_sap_namespace.
IF gi_sap_namespace IS NOT BOUND.
CREATE OBJECT gi_sap_namespace TYPE zcl_abapgit_sap_namespace.
ENDIF.
ri_namespace = gi_sap_namespace.
ENDMETHOD.
METHOD get_sap_package.
DATA: ls_sap_package TYPE ty_sap_package.

View File

@ -33,13 +33,17 @@ CLASS zcl_abapgit_injector DEFINITION
CLASS-METHODS set_lxe_texts
IMPORTING
!ii_lxe_texts TYPE REF TO zif_abapgit_lxe_texts .
CLASS-METHODS set_sap_namespace
IMPORTING
!ii_namespace TYPE REF TO zif_abapgit_sap_namespace .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_abapgit_injector IMPLEMENTATION.
CLASS ZCL_ABAPGIT_INJECTOR IMPLEMENTATION.
METHOD set_code_inspector.
@ -90,6 +94,11 @@ CLASS zcl_abapgit_injector IMPLEMENTATION.
ENDMETHOD.
METHOD set_sap_namespace.
zcl_abapgit_factory=>gi_sap_namespace = ii_namespace.
ENDMETHOD.
METHOD set_sap_package.
DATA: ls_sap_package TYPE zcl_abapgit_factory=>ty_sap_package.

View File

@ -0,0 +1,29 @@
CLASS zcl_abapgit_sap_namespace DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES zif_abapgit_sap_namespace.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ZCL_ABAPGIT_SAP_NAMESPACE IMPLEMENTATION.
METHOD zif_abapgit_sap_namespace~exists.
DATA lv_editflag TYPE trnspace-editflag.
SELECT SINGLE editflag FROM trnspace INTO lv_editflag WHERE namespace = iv_namespace.
rv_yes = boolc( sy-subrc = 0 ).
ENDMETHOD.
METHOD zif_abapgit_sap_namespace~is_editable.
DATA lv_editflag TYPE trnspace-editflag.
SELECT SINGLE editflag FROM trnspace INTO lv_editflag WHERE namespace = iv_namespace.
rv_yes = boolc( sy-subrc = 0 AND lv_editflag = 'X' ).
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_ABAPGIT_SAP_NAMESPACE</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abapGit sap namespace abstraction</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,16 @@
INTERFACE zif_abapgit_sap_namespace
PUBLIC .
METHODS exists
IMPORTING
iv_namespace TYPE trnspace-namespace
RETURNING
VALUE(rv_yes) TYPE abap_bool.
METHODS is_editable
IMPORTING
iv_namespace TYPE trnspace-namespace
RETURNING
VALUE(rv_yes) TYPE abap_bool.
ENDINTERFACE.

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_INTF" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOINTERF>
<CLSNAME>ZIF_ABAPGIT_SAP_NAMESPACE</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abapGit namespace abstraction</DESCRIPT>
<EXPOSURE>2</EXPOSURE>
<STATE>1</STATE>
<UNICODE>X</UNICODE>
</VSEOINTERF>
</asx:values>
</asx:abap>
</abapGit>