mirror of
https://github.com/abapGit/abapGit.git
synced 2025-05-01 12:20:51 +08:00
1194 lines
31 KiB
ABAP
1194 lines
31 KiB
ABAP
*&---------------------------------------------------------------------*
|
|
*& Include ZABAPGIT_UTIL
|
|
*&---------------------------------------------------------------------*
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_language DEFINITION
|
|
*----------------------------------------------------------------------*
|
|
* This helper class is used to set and restore the current language.
|
|
* As some of the SAP functions used rely on SY-LANGU containing the
|
|
* master language, this class is used to temporarily change and then
|
|
* restore the value of SY-LANGU.
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_language DEFINITION.
|
|
|
|
PUBLIC SECTION.
|
|
|
|
CLASS-DATA:
|
|
current_language TYPE langu READ-ONLY,
|
|
login_language TYPE langu READ-ONLY.
|
|
|
|
CLASS-METHODS:
|
|
class_constructor,
|
|
restore_login_language,
|
|
set_current_language
|
|
IMPORTING
|
|
iv_language TYPE langu.
|
|
|
|
ENDCLASS.
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_language IMPLEMENTATION
|
|
*----------------------------------------------------------------------*
|
|
*
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_language IMPLEMENTATION.
|
|
|
|
METHOD class_constructor.
|
|
DATA lv_dummy TYPE string.
|
|
|
|
GET LOCALE LANGUAGE login_language COUNTRY lv_dummy MODIFIER lv_dummy.
|
|
ENDMETHOD.
|
|
|
|
METHOD restore_login_language.
|
|
SET LOCALE LANGUAGE login_language.
|
|
ENDMETHOD.
|
|
|
|
METHOD set_current_language.
|
|
SET LOCALE LANGUAGE iv_language.
|
|
ENDMETHOD.
|
|
|
|
ENDCLASS.
|
|
|
|
CLASS lcl_state DEFINITION.
|
|
|
|
PUBLIC SECTION.
|
|
|
|
CLASS-METHODS:
|
|
reduce
|
|
IMPORTING
|
|
iv_cur TYPE char1
|
|
CHANGING
|
|
cv_prev TYPE char1.
|
|
|
|
ENDCLASS.
|
|
|
|
CLASS lcl_state IMPLEMENTATION.
|
|
|
|
METHOD reduce.
|
|
|
|
IF cv_prev = iv_cur OR iv_cur IS INITIAL.
|
|
RETURN. " No change
|
|
ELSEIF cv_prev IS INITIAL.
|
|
cv_prev = iv_cur.
|
|
ELSE.
|
|
cv_prev = zif_abapgit_definitions=>gc_state-mixed.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
ENDCLASS.
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_convert DEFINITION
|
|
*----------------------------------------------------------------------*
|
|
*
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_convert DEFINITION FINAL.
|
|
|
|
PUBLIC SECTION.
|
|
CLASS-METHODS bitbyte_to_int
|
|
IMPORTING iv_bits TYPE clike
|
|
RETURNING VALUE(rv_int) TYPE i.
|
|
|
|
CLASS-METHODS x_to_bitbyte
|
|
IMPORTING iv_x TYPE x
|
|
RETURNING VALUE(rv_bitbyte) TYPE zif_abapgit_definitions=>ty_bitbyte.
|
|
|
|
CLASS-METHODS string_to_xstring_utf8
|
|
IMPORTING iv_string TYPE string
|
|
RETURNING VALUE(rv_xstring) TYPE xstring.
|
|
|
|
CLASS-METHODS xstring_to_string_utf8
|
|
IMPORTING iv_data TYPE xstring
|
|
RETURNING VALUE(rv_string) TYPE string.
|
|
|
|
CLASS-METHODS xstring_to_int
|
|
IMPORTING iv_xstring TYPE xstring
|
|
RETURNING VALUE(rv_i) TYPE i
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
CLASS-METHODS int_to_xstring4
|
|
IMPORTING iv_i TYPE i
|
|
RETURNING VALUE(rv_xstring) TYPE xstring.
|
|
|
|
CLASS-METHODS split_string
|
|
IMPORTING iv_string TYPE string
|
|
RETURNING VALUE(rt_lines) TYPE string_table.
|
|
|
|
ENDCLASS. "lcl_convert DEFINITION
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_convert IMPLEMENTATION
|
|
*----------------------------------------------------------------------*
|
|
*
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_convert IMPLEMENTATION.
|
|
|
|
METHOD int_to_xstring4.
|
|
* returns xstring of length 4 containing the integer value iv_i
|
|
|
|
DATA: lv_x TYPE x LENGTH 4.
|
|
|
|
|
|
lv_x = iv_i.
|
|
rv_xstring = lv_x.
|
|
|
|
ENDMETHOD. "int_to_xstring
|
|
|
|
METHOD xstring_to_int.
|
|
|
|
DATA: lv_xstring TYPE xstring,
|
|
lv_x TYPE x.
|
|
|
|
|
|
lv_xstring = iv_xstring.
|
|
WHILE xstrlen( lv_xstring ) > 0.
|
|
lv_x = lv_xstring(1).
|
|
rv_i = rv_i * 256 + lv_x.
|
|
lv_xstring = lv_xstring+1.
|
|
ENDWHILE.
|
|
|
|
ENDMETHOD. "xstring_to_int
|
|
|
|
METHOD xstring_to_string_utf8.
|
|
|
|
DATA: lv_len TYPE i,
|
|
lo_obj TYPE REF TO cl_abap_conv_in_ce.
|
|
|
|
|
|
TRY.
|
|
lo_obj = cl_abap_conv_in_ce=>create(
|
|
input = iv_data
|
|
encoding = 'UTF-8' ).
|
|
lv_len = xstrlen( iv_data ).
|
|
|
|
lo_obj->read( EXPORTING n = lv_len
|
|
IMPORTING data = rv_string ).
|
|
|
|
CATCH cx_parameter_invalid_range
|
|
cx_sy_codepage_converter_init
|
|
cx_sy_conversion_codepage
|
|
cx_parameter_invalid_type. "#EC NO_HANDLER
|
|
ENDTRY.
|
|
|
|
ENDMETHOD. "xstring_to_string_utf8
|
|
|
|
METHOD string_to_xstring_utf8.
|
|
|
|
DATA: lo_obj TYPE REF TO cl_abap_conv_out_ce.
|
|
|
|
|
|
TRY.
|
|
lo_obj = cl_abap_conv_out_ce=>create( encoding = 'UTF-8' ).
|
|
|
|
lo_obj->convert( EXPORTING data = iv_string
|
|
IMPORTING buffer = rv_xstring ).
|
|
|
|
CATCH cx_parameter_invalid_range
|
|
cx_sy_codepage_converter_init
|
|
cx_sy_conversion_codepage
|
|
cx_parameter_invalid_type. "#EC NO_HANDLER
|
|
ENDTRY.
|
|
|
|
ENDMETHOD. "string_to_xstring_utf8
|
|
|
|
METHOD bitbyte_to_int.
|
|
|
|
DATA: lv_bits TYPE string.
|
|
|
|
|
|
lv_bits = iv_bits.
|
|
|
|
rv_int = 0.
|
|
WHILE strlen( lv_bits ) > 0.
|
|
rv_int = rv_int * 2.
|
|
IF lv_bits(1) = '1'.
|
|
rv_int = rv_int + 1.
|
|
ENDIF.
|
|
lv_bits = lv_bits+1.
|
|
ENDWHILE.
|
|
|
|
ENDMETHOD. "bitbyte_to_int
|
|
|
|
METHOD x_to_bitbyte.
|
|
|
|
DATA: lv_b TYPE n.
|
|
|
|
CLEAR rv_bitbyte.
|
|
|
|
DO 8 TIMES.
|
|
GET BIT sy-index OF iv_x INTO lv_b.
|
|
CONCATENATE rv_bitbyte lv_b INTO rv_bitbyte.
|
|
ENDDO.
|
|
|
|
ENDMETHOD. "x_to_bitbyte
|
|
|
|
METHOD split_string.
|
|
|
|
FIND FIRST OCCURRENCE OF cl_abap_char_utilities=>cr_lf IN iv_string.
|
|
|
|
" Convert string into table depending on separator type CR_LF vs. LF
|
|
IF sy-subrc = 0.
|
|
SPLIT iv_string AT cl_abap_char_utilities=>cr_lf INTO TABLE rt_lines.
|
|
ELSE.
|
|
SPLIT iv_string AT cl_abap_char_utilities=>newline INTO TABLE rt_lines.
|
|
ENDIF.
|
|
|
|
ENDMETHOD. "split_string
|
|
|
|
ENDCLASS. "lcl_convert IMPLEMENTATION
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_hash DEFINITION
|
|
*----------------------------------------------------------------------*
|
|
*
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_hash DEFINITION FINAL.
|
|
|
|
PUBLIC SECTION.
|
|
TYPES: ty_adler32 TYPE x LENGTH 4.
|
|
|
|
CLASS-METHODS adler32
|
|
IMPORTING iv_xstring TYPE xstring
|
|
RETURNING VALUE(rv_checksum) TYPE ty_adler32.
|
|
|
|
CLASS-METHODS sha1
|
|
IMPORTING iv_type TYPE zif_abapgit_definitions=>ty_type
|
|
iv_data TYPE xstring
|
|
RETURNING VALUE(rv_sha1) TYPE zif_abapgit_definitions=>ty_sha1
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
CLASS-METHODS sha1_raw
|
|
IMPORTING iv_data TYPE xstring
|
|
RETURNING VALUE(rv_sha1) TYPE zif_abapgit_definitions=>ty_sha1
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
ENDCLASS. "lcl_hash DEFINITION
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_hash IMPLEMENTATION
|
|
*----------------------------------------------------------------------*
|
|
*
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_hash IMPLEMENTATION.
|
|
|
|
METHOD adler32.
|
|
|
|
CONSTANTS: lc_adler TYPE i VALUE 65521,
|
|
lc_max_b TYPE i VALUE 1800000000.
|
|
|
|
DATA: lv_index TYPE i,
|
|
lv_a TYPE i VALUE 1,
|
|
lv_b TYPE i VALUE 0,
|
|
lv_x TYPE x LENGTH 2,
|
|
lv_ca TYPE c LENGTH 4,
|
|
lv_cb TYPE c LENGTH 4,
|
|
lv_char8 TYPE c LENGTH 8.
|
|
|
|
|
|
DO xstrlen( iv_xstring ) TIMES.
|
|
lv_index = sy-index - 1.
|
|
|
|
lv_a = lv_a + iv_xstring+lv_index(1).
|
|
lv_b = lv_b + lv_a.
|
|
|
|
* delay the MOD operation until the integer might overflow
|
|
* articles describe 5552 additions are allowed, but this assumes unsigned integers
|
|
* instead of allowing a fixed number of additions before running MOD, then
|
|
* just compare value of lv_b, this is 1 operation less than comparing and adding
|
|
IF lv_b > lc_max_b.
|
|
lv_a = lv_a MOD lc_adler.
|
|
lv_b = lv_b MOD lc_adler.
|
|
ENDIF.
|
|
ENDDO.
|
|
|
|
lv_a = lv_a MOD lc_adler.
|
|
lv_b = lv_b MOD lc_adler.
|
|
|
|
lv_x = lv_a.
|
|
lv_ca = lv_x.
|
|
|
|
lv_x = lv_b.
|
|
lv_cb = lv_x.
|
|
|
|
CONCATENATE lv_cb lv_ca INTO lv_char8.
|
|
|
|
rv_checksum = lv_char8.
|
|
|
|
ENDMETHOD. "adler32
|
|
|
|
METHOD sha1_raw.
|
|
|
|
DATA: lv_hash TYPE hash160.
|
|
|
|
|
|
CALL FUNCTION 'CALCULATE_HASH_FOR_RAW'
|
|
EXPORTING
|
|
data = iv_data
|
|
IMPORTING
|
|
hash = lv_hash
|
|
EXCEPTIONS
|
|
unknown_alg = 1
|
|
param_error = 2
|
|
internal_error = 3
|
|
OTHERS = 4.
|
|
IF sy-subrc <> 0.
|
|
zcx_abapgit_exception=>raise( 'Error while calculating SHA1' ).
|
|
ENDIF.
|
|
|
|
rv_sha1 = lv_hash.
|
|
|
|
TRANSLATE rv_sha1 TO LOWER CASE.
|
|
|
|
ENDMETHOD. "sha1_raw
|
|
|
|
METHOD sha1.
|
|
|
|
DATA: lv_len TYPE i,
|
|
lv_char10 TYPE c LENGTH 10,
|
|
lv_string TYPE string,
|
|
lv_xstring TYPE xstring.
|
|
|
|
|
|
lv_len = xstrlen( iv_data ).
|
|
lv_char10 = lv_len.
|
|
CONDENSE lv_char10.
|
|
CONCATENATE iv_type lv_char10 INTO lv_string SEPARATED BY space.
|
|
lv_xstring = lcl_convert=>string_to_xstring_utf8( lv_string ).
|
|
|
|
lv_string = lv_xstring.
|
|
CONCATENATE lv_string '00' INTO lv_string.
|
|
lv_xstring = lv_string.
|
|
|
|
CONCATENATE lv_xstring iv_data INTO lv_xstring IN BYTE MODE.
|
|
|
|
rv_sha1 = sha1_raw( lv_xstring ).
|
|
|
|
ENDMETHOD. "sha1
|
|
|
|
ENDCLASS. "lcl_hash IMPLEMENTATION
|
|
|
|
CLASS lcl_path DEFINITION FINAL.
|
|
|
|
PUBLIC SECTION.
|
|
|
|
CLASS-METHODS split_file_location
|
|
IMPORTING iv_fullpath TYPE string
|
|
EXPORTING ev_path TYPE string
|
|
ev_filename TYPE string.
|
|
|
|
CLASS-METHODS is_root
|
|
IMPORTING iv_path TYPE string
|
|
RETURNING VALUE(rv_yes) TYPE abap_bool.
|
|
|
|
CLASS-METHODS is_subdir
|
|
IMPORTING iv_path TYPE string
|
|
iv_parent TYPE string
|
|
RETURNING VALUE(rv_yes) TYPE abap_bool.
|
|
|
|
CLASS-METHODS change_dir
|
|
IMPORTING iv_cur_dir TYPE string
|
|
iv_cd TYPE string
|
|
RETURNING VALUE(rv_path) TYPE string.
|
|
|
|
CLASS-METHODS get_filename_from_syspath
|
|
IMPORTING iv_path TYPE string
|
|
RETURNING VALUE(rv_filename) TYPE string.
|
|
|
|
ENDCLASS. "lcl_path
|
|
|
|
CLASS lcl_path IMPLEMENTATION.
|
|
|
|
METHOD split_file_location.
|
|
|
|
DATA: lv_cnt TYPE i,
|
|
lv_len TYPE i.
|
|
|
|
FIND FIRST OCCURRENCE OF REGEX '^/(.*/)?' IN iv_fullpath
|
|
MATCH COUNT lv_cnt
|
|
MATCH LENGTH lv_len.
|
|
|
|
IF lv_cnt > 0.
|
|
ev_path = iv_fullpath+0(lv_len).
|
|
ev_filename = iv_fullpath+lv_len.
|
|
ELSE.
|
|
CLEAR ev_path.
|
|
ev_filename = iv_fullpath.
|
|
ENDIF.
|
|
|
|
ENDMETHOD. "split_file_location
|
|
|
|
METHOD is_root.
|
|
rv_yes = boolc( iv_path = '/' ).
|
|
ENDMETHOD. "is_root
|
|
|
|
METHOD is_subdir.
|
|
|
|
DATA lv_len TYPE i.
|
|
DATA lv_last TYPE i.
|
|
|
|
lv_len = strlen( iv_parent ).
|
|
lv_last = lv_len - 1.
|
|
rv_yes = boolc( strlen( iv_path ) > lv_len
|
|
AND iv_path+0(lv_len) = iv_parent
|
|
AND ( iv_parent+lv_last(1) = '/' OR iv_path+lv_len(1) = '/' ) ).
|
|
|
|
ENDMETHOD. "is_subdir
|
|
|
|
METHOD change_dir.
|
|
|
|
DATA: lv_last TYPE i,
|
|
lv_temp TYPE string.
|
|
|
|
lv_last = strlen( iv_cur_dir ) - 1.
|
|
|
|
IF iv_cd = '' OR iv_cd = '.'. " No change
|
|
rv_path = iv_cur_dir.
|
|
ELSEIF iv_cd+0(1) = '/'. " Absolute path
|
|
rv_path = iv_cd.
|
|
ELSEIF iv_cd = '..'. " CD back
|
|
IF iv_cur_dir = '/' OR iv_cur_dir = ''. " Back from root = root
|
|
rv_path = iv_cur_dir.
|
|
ELSE.
|
|
lv_temp = reverse( iv_cur_dir ).
|
|
IF lv_temp+0(1) = '/'.
|
|
SHIFT lv_temp BY 1 PLACES LEFT.
|
|
ENDIF.
|
|
SHIFT lv_temp UP TO '/' LEFT.
|
|
rv_path = reverse( lv_temp ).
|
|
ENDIF.
|
|
ELSEIF iv_cur_dir+lv_last(1) = '/'. " Append cd to cur_dir separated by /
|
|
rv_path = iv_cur_dir && iv_cd.
|
|
ELSE.
|
|
rv_path = iv_cur_dir && '/' && iv_cd.
|
|
ENDIF.
|
|
|
|
" TODO: improve logic and cases
|
|
|
|
ENDMETHOD. "change_dir
|
|
|
|
METHOD get_filename_from_syspath.
|
|
|
|
DATA: lv_split TYPE c LENGTH 1,
|
|
lv_index TYPE i,
|
|
lt_split TYPE TABLE OF string.
|
|
|
|
" filename | c:\filename | /dir/filename | \\server\filename
|
|
IF iv_path CA '/'.
|
|
lv_split = '/'.
|
|
ELSE.
|
|
lv_split = '\'.
|
|
ENDIF.
|
|
|
|
SPLIT iv_path AT lv_split INTO TABLE lt_split.
|
|
|
|
lv_index = lines( lt_split ).
|
|
|
|
READ TABLE lt_split INDEX lv_index INTO rv_filename.
|
|
|
|
ENDMETHOD. " get_filename_from_syspath.
|
|
|
|
ENDCLASS. "lcl_path
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_url DEFINITION
|
|
*----------------------------------------------------------------------*
|
|
*
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_url DEFINITION FINAL.
|
|
|
|
PUBLIC SECTION.
|
|
CLASS-METHODS host
|
|
IMPORTING iv_repo TYPE string
|
|
RETURNING VALUE(rv_host) TYPE string
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
CLASS-METHODS name
|
|
IMPORTING iv_repo TYPE string
|
|
RETURNING VALUE(rv_name) TYPE string
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
CLASS-METHODS path_name
|
|
IMPORTING iv_repo TYPE string
|
|
RETURNING VALUE(rv_path_name) TYPE string
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
PRIVATE SECTION.
|
|
CLASS-METHODS regex
|
|
IMPORTING iv_repo TYPE string
|
|
EXPORTING ev_host TYPE string
|
|
ev_path TYPE string
|
|
ev_name TYPE string
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
ENDCLASS. "lcl_repo DEFINITION
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_url IMPLEMENTATION
|
|
*----------------------------------------------------------------------*
|
|
*
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_url IMPLEMENTATION.
|
|
|
|
METHOD host.
|
|
regex( EXPORTING iv_repo = iv_repo
|
|
IMPORTING ev_host = rv_host ).
|
|
ENDMETHOD. "host
|
|
|
|
METHOD name.
|
|
regex( EXPORTING iv_repo = iv_repo
|
|
IMPORTING ev_name = rv_name ).
|
|
ENDMETHOD. "short_name
|
|
|
|
METHOD path_name.
|
|
|
|
DATA: lv_host TYPE string ##NEEDED.
|
|
|
|
FIND REGEX '(.*://[^/]*)(.*)' IN iv_repo
|
|
SUBMATCHES lv_host rv_path_name.
|
|
|
|
ENDMETHOD. "path_name
|
|
|
|
METHOD regex.
|
|
|
|
FIND REGEX '(.*://[^/]*)(.*/)([^\.]*)[\.git]?' IN iv_repo
|
|
SUBMATCHES ev_host ev_path ev_name.
|
|
IF sy-subrc <> 0.
|
|
zcx_abapgit_exception=>raise( 'Malformed URL' ).
|
|
ENDIF.
|
|
|
|
ENDMETHOD. "url
|
|
|
|
ENDCLASS. "lcl_repo IMPLEMENTATION
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_diff DEFINITION
|
|
*----------------------------------------------------------------------*
|
|
*
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_diff DEFINITION FINAL.
|
|
|
|
PUBLIC SECTION.
|
|
CONSTANTS: BEGIN OF c_diff,
|
|
insert TYPE c LENGTH 1 VALUE 'I',
|
|
delete TYPE c LENGTH 1 VALUE 'D',
|
|
update TYPE c LENGTH 1 VALUE 'U',
|
|
END OF c_diff.
|
|
|
|
TYPES: BEGIN OF ty_diff,
|
|
new_num TYPE c LENGTH 6,
|
|
new TYPE string,
|
|
result TYPE c LENGTH 1,
|
|
old_num TYPE c LENGTH 6,
|
|
old TYPE string,
|
|
short TYPE abap_bool,
|
|
beacon TYPE i,
|
|
END OF ty_diff.
|
|
TYPES: ty_diffs_tt TYPE STANDARD TABLE OF ty_diff WITH DEFAULT KEY.
|
|
|
|
TYPES: BEGIN OF ty_count,
|
|
insert TYPE i,
|
|
delete TYPE i,
|
|
update TYPE i,
|
|
END OF ty_count.
|
|
|
|
DATA mt_beacons TYPE zif_abapgit_definitions=>ty_string_tt READ-ONLY.
|
|
|
|
* assumes data is UTF8 based with newlines
|
|
* only works with lines up to 255 characters
|
|
METHODS constructor
|
|
IMPORTING iv_new TYPE xstring
|
|
iv_old TYPE xstring.
|
|
|
|
METHODS get
|
|
RETURNING VALUE(rt_diff) TYPE ty_diffs_tt.
|
|
|
|
METHODS stats
|
|
RETURNING VALUE(rs_count) TYPE ty_count.
|
|
|
|
PRIVATE SECTION.
|
|
DATA mt_diff TYPE ty_diffs_tt.
|
|
DATA ms_stats TYPE ty_count.
|
|
|
|
CLASS-METHODS:
|
|
unpack
|
|
IMPORTING iv_new TYPE xstring
|
|
iv_old TYPE xstring
|
|
EXPORTING et_new TYPE abaptxt255_tab
|
|
et_old TYPE abaptxt255_tab,
|
|
render
|
|
IMPORTING it_new TYPE abaptxt255_tab
|
|
it_old TYPE abaptxt255_tab
|
|
it_delta TYPE vxabapt255_tab
|
|
RETURNING VALUE(rt_diff) TYPE ty_diffs_tt,
|
|
compute
|
|
IMPORTING it_new TYPE abaptxt255_tab
|
|
it_old TYPE abaptxt255_tab
|
|
RETURNING VALUE(rt_delta) TYPE vxabapt255_tab.
|
|
|
|
METHODS:
|
|
calculate_line_num_and_stats,
|
|
map_beacons,
|
|
shortlist.
|
|
|
|
ENDCLASS. "lcl_diff DEFINITION
|
|
|
|
*----------------------------------------------------------------------*
|
|
* CLASS lcl_diff IMPLEMENTATION
|
|
*----------------------------------------------------------------------*
|
|
*
|
|
*----------------------------------------------------------------------*
|
|
CLASS lcl_diff IMPLEMENTATION.
|
|
|
|
METHOD get.
|
|
rt_diff = mt_diff.
|
|
ENDMETHOD. "get
|
|
|
|
METHOD stats.
|
|
rs_count = ms_stats.
|
|
ENDMETHOD. "count
|
|
|
|
METHOD unpack.
|
|
|
|
DATA: lv_new TYPE string,
|
|
lv_old TYPE string.
|
|
|
|
|
|
lv_new = lcl_convert=>xstring_to_string_utf8( iv_new ).
|
|
lv_old = lcl_convert=>xstring_to_string_utf8( iv_old ).
|
|
|
|
SPLIT lv_new AT zif_abapgit_definitions=>gc_newline INTO TABLE et_new.
|
|
SPLIT lv_old AT zif_abapgit_definitions=>gc_newline INTO TABLE et_old.
|
|
|
|
ENDMETHOD. "unpack
|
|
|
|
METHOD compute.
|
|
|
|
DATA: lt_trdirtab_old TYPE TABLE OF trdir,
|
|
lt_trdirtab_new TYPE TABLE OF trdir,
|
|
lt_trdir_delta TYPE TABLE OF xtrdir.
|
|
|
|
|
|
CALL FUNCTION 'SVRS_COMPUTE_DELTA_REPS'
|
|
TABLES
|
|
texttab_old = it_old
|
|
texttab_new = it_new
|
|
trdirtab_old = lt_trdirtab_old
|
|
trdirtab_new = lt_trdirtab_new
|
|
trdir_delta = lt_trdir_delta
|
|
text_delta = rt_delta.
|
|
|
|
ENDMETHOD. "compute
|
|
|
|
METHOD shortlist.
|
|
|
|
DATA: lv_index TYPE i.
|
|
|
|
FIELD-SYMBOLS: <ls_diff> LIKE LINE OF mt_diff.
|
|
|
|
IF lines( mt_diff ) < 20.
|
|
LOOP AT mt_diff ASSIGNING <ls_diff>.
|
|
<ls_diff>-short = abap_true.
|
|
ENDLOOP.
|
|
ELSE.
|
|
LOOP AT mt_diff TRANSPORTING NO FIELDS
|
|
WHERE NOT result IS INITIAL AND short = abap_false.
|
|
lv_index = sy-tabix.
|
|
|
|
DO 8 TIMES. " Backward
|
|
READ TABLE mt_diff INDEX ( lv_index - sy-index ) ASSIGNING <ls_diff>.
|
|
IF sy-subrc <> 0 OR <ls_diff>-short = abap_true. " tab bound or prev marker
|
|
EXIT.
|
|
ENDIF.
|
|
<ls_diff>-short = abap_true.
|
|
ENDDO.
|
|
|
|
DO 8 TIMES. " Forward
|
|
READ TABLE mt_diff INDEX ( lv_index + sy-index - 1 ) ASSIGNING <ls_diff>.
|
|
IF sy-subrc <> 0. " tab bound reached
|
|
EXIT.
|
|
ENDIF.
|
|
CHECK <ls_diff>-short = abap_false. " skip marked
|
|
<ls_diff>-short = abap_true.
|
|
ENDDO.
|
|
|
|
ENDLOOP.
|
|
ENDIF.
|
|
|
|
ENDMETHOD. " shortlist
|
|
|
|
METHOD calculate_line_num_and_stats.
|
|
|
|
DATA: lv_new TYPE i VALUE 1,
|
|
lv_old TYPE i VALUE 1.
|
|
|
|
FIELD-SYMBOLS: <ls_diff> LIKE LINE OF mt_diff.
|
|
|
|
|
|
LOOP AT mt_diff ASSIGNING <ls_diff>.
|
|
<ls_diff>-new_num = lv_new.
|
|
<ls_diff>-old_num = lv_old.
|
|
|
|
CASE <ls_diff>-result. " Line nums
|
|
WHEN c_diff-delete.
|
|
lv_old = lv_old + 1.
|
|
CLEAR <ls_diff>-new_num.
|
|
WHEN c_diff-insert.
|
|
lv_new = lv_new + 1.
|
|
CLEAR <ls_diff>-old_num.
|
|
WHEN OTHERS.
|
|
lv_new = lv_new + 1.
|
|
lv_old = lv_old + 1.
|
|
ENDCASE.
|
|
|
|
CASE <ls_diff>-result. " Stats
|
|
WHEN c_diff-insert.
|
|
ms_stats-insert = ms_stats-insert + 1.
|
|
WHEN c_diff-delete.
|
|
ms_stats-delete = ms_stats-delete + 1.
|
|
WHEN c_diff-update.
|
|
ms_stats-update = ms_stats-update + 1.
|
|
ENDCASE.
|
|
|
|
ENDLOOP.
|
|
|
|
ENDMETHOD. " calculate_line_num_and_stats
|
|
|
|
METHOD map_beacons.
|
|
|
|
DEFINE _add_regex.
|
|
CREATE OBJECT lo_regex
|
|
EXPORTING pattern = &1
|
|
ignore_case = abap_true ##NO_TEXT.
|
|
APPEND lo_regex TO lt_regex_set.
|
|
END-OF-DEFINITION.
|
|
|
|
DATA: lv_beacon_idx TYPE i,
|
|
lv_offs TYPE i,
|
|
lv_beacon_str TYPE string,
|
|
lv_beacon_2lev TYPE string,
|
|
lv_submatch TYPE string,
|
|
lo_regex TYPE REF TO cl_abap_regex,
|
|
lt_regex_set TYPE TABLE OF REF TO cl_abap_regex.
|
|
|
|
FIELD-SYMBOLS: <ls_diff> LIKE LINE OF mt_diff.
|
|
|
|
|
|
_add_regex '^\s*(CLASS|FORM|MODULE|REPORT|METHOD)\s'.
|
|
_add_regex '^\s*START-OF-'.
|
|
_add_regex '^\s*INITIALIZATION(\s|\.)'.
|
|
|
|
LOOP AT mt_diff ASSIGNING <ls_diff>.
|
|
|
|
CLEAR lv_offs.
|
|
<ls_diff>-beacon = lv_beacon_idx.
|
|
|
|
LOOP AT lt_regex_set INTO lo_regex. "
|
|
FIND FIRST OCCURRENCE OF REGEX lo_regex IN <ls_diff>-new SUBMATCHES lv_submatch.
|
|
IF sy-subrc = 0. " Match
|
|
lv_beacon_str = <ls_diff>-new.
|
|
lv_submatch = to_upper( lv_submatch ).
|
|
|
|
" Get rid of comments and end of line
|
|
FIND FIRST OCCURRENCE OF '.' IN lv_beacon_str MATCH OFFSET lv_offs.
|
|
IF sy-subrc <> 0.
|
|
FIND FIRST OCCURRENCE OF '"' IN lv_beacon_str MATCH OFFSET lv_offs.
|
|
ENDIF.
|
|
|
|
IF lv_offs > 0.
|
|
lv_beacon_str = lv_beacon_str(lv_offs).
|
|
ENDIF.
|
|
|
|
IF lv_submatch = 'CLASS'.
|
|
lv_beacon_2lev = lv_beacon_str.
|
|
ELSEIF lv_submatch = 'METHOD'.
|
|
lv_beacon_str = lv_beacon_2lev && ` => ` && lv_beacon_str.
|
|
ENDIF.
|
|
|
|
APPEND lv_beacon_str TO mt_beacons.
|
|
lv_beacon_idx = sy-tabix.
|
|
<ls_diff>-beacon = lv_beacon_idx.
|
|
EXIT. "Loop
|
|
ENDIF.
|
|
ENDLOOP.
|
|
ENDLOOP.
|
|
|
|
ENDMETHOD. " map_beacons
|
|
|
|
METHOD constructor.
|
|
|
|
DATA: lt_delta TYPE vxabapt255_tab,
|
|
lt_new TYPE abaptxt255_tab,
|
|
lt_old TYPE abaptxt255_tab.
|
|
|
|
|
|
unpack( EXPORTING iv_new = iv_new
|
|
iv_old = iv_old
|
|
IMPORTING et_new = lt_new
|
|
et_old = lt_old ).
|
|
|
|
lt_delta = compute( it_new = lt_new
|
|
it_old = lt_old ).
|
|
|
|
mt_diff = render( it_new = lt_new
|
|
it_old = lt_old
|
|
it_delta = lt_delta ).
|
|
|
|
calculate_line_num_and_stats( ).
|
|
map_beacons( ).
|
|
shortlist( ).
|
|
|
|
ENDMETHOD. "diff
|
|
|
|
METHOD render.
|
|
|
|
DEFINE _append.
|
|
CLEAR ls_diff.
|
|
ls_diff-new = &1.
|
|
ls_diff-result = &2.
|
|
ls_diff-old = &3.
|
|
APPEND ls_diff TO rt_diff.
|
|
END-OF-DEFINITION.
|
|
|
|
DATA: lv_oindex TYPE i VALUE 1,
|
|
lv_nindex TYPE i VALUE 1,
|
|
ls_new LIKE LINE OF it_new,
|
|
ls_old LIKE LINE OF it_old,
|
|
ls_diff LIKE LINE OF rt_diff,
|
|
lt_delta LIKE it_delta,
|
|
ls_delta LIKE LINE OF it_delta.
|
|
|
|
|
|
lt_delta = it_delta.
|
|
|
|
DO.
|
|
READ TABLE lt_delta INTO ls_delta WITH KEY number = lv_oindex.
|
|
IF sy-subrc = 0.
|
|
DELETE lt_delta INDEX sy-tabix.
|
|
|
|
CASE ls_delta-vrsflag.
|
|
WHEN c_diff-delete.
|
|
_append '' c_diff-delete ls_delta-line.
|
|
lv_oindex = lv_oindex + 1.
|
|
WHEN c_diff-insert.
|
|
_append ls_delta-line c_diff-insert ''.
|
|
lv_nindex = lv_nindex + 1.
|
|
WHEN c_diff-update.
|
|
CLEAR ls_new.
|
|
READ TABLE it_new INTO ls_new INDEX lv_nindex.
|
|
ASSERT sy-subrc = 0.
|
|
_append ls_new c_diff-update ls_delta-line.
|
|
lv_nindex = lv_nindex + 1.
|
|
lv_oindex = lv_oindex + 1.
|
|
WHEN OTHERS.
|
|
ASSERT 0 = 1.
|
|
ENDCASE.
|
|
ELSE.
|
|
CLEAR ls_new.
|
|
READ TABLE it_new INTO ls_new INDEX lv_nindex. "#EC CI_SUBRC
|
|
lv_nindex = lv_nindex + 1.
|
|
CLEAR ls_old.
|
|
READ TABLE it_old INTO ls_old INDEX lv_oindex. "#EC CI_SUBRC
|
|
lv_oindex = lv_oindex + 1.
|
|
_append ls_new '' ls_old.
|
|
ENDIF.
|
|
|
|
IF lv_nindex > lines( it_new ) AND lv_oindex > lines( it_old ).
|
|
EXIT. " current loop
|
|
ENDIF.
|
|
ENDDO.
|
|
|
|
|
|
ENDMETHOD. " render
|
|
|
|
ENDCLASS. "lcl_diff IMPLEMENTATION
|
|
|
|
CLASS lcl_login_manager DEFINITION FINAL.
|
|
|
|
PUBLIC SECTION.
|
|
CLASS-METHODS:
|
|
load
|
|
IMPORTING iv_uri TYPE string
|
|
ii_client TYPE REF TO if_http_client OPTIONAL
|
|
RETURNING VALUE(rv_authorization) TYPE string
|
|
RAISING zcx_abapgit_exception,
|
|
save
|
|
IMPORTING iv_uri TYPE string
|
|
ii_client TYPE REF TO if_http_client
|
|
RAISING zcx_abapgit_exception,
|
|
clear,
|
|
set
|
|
IMPORTING iv_uri TYPE string
|
|
iv_username TYPE string
|
|
iv_password TYPE string
|
|
RETURNING VALUE(rv_auth) TYPE string
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
PRIVATE SECTION.
|
|
TYPES: BEGIN OF ty_auth,
|
|
uri TYPE string,
|
|
authorization TYPE string,
|
|
END OF ty_auth.
|
|
|
|
CLASS-DATA: gt_auth TYPE TABLE OF ty_auth WITH DEFAULT KEY.
|
|
|
|
CLASS-METHODS:
|
|
append
|
|
IMPORTING iv_uri TYPE string
|
|
iv_auth TYPE string
|
|
RAISING zcx_abapgit_exception.
|
|
|
|
ENDCLASS.
|
|
|
|
CLASS lcl_login_manager IMPLEMENTATION.
|
|
|
|
METHOD clear.
|
|
CLEAR gt_auth.
|
|
ENDMETHOD.
|
|
|
|
METHOD set.
|
|
|
|
DATA: lv_concat TYPE string.
|
|
|
|
|
|
ASSERT NOT iv_uri IS INITIAL.
|
|
|
|
IF iv_username IS INITIAL OR iv_password IS INITIAL.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
CONCATENATE iv_username ':' iv_password INTO lv_concat.
|
|
|
|
rv_auth = cl_http_utility=>if_http_utility~encode_base64( lv_concat ).
|
|
|
|
CONCATENATE 'Basic' rv_auth INTO rv_auth
|
|
SEPARATED BY space ##NO_TEXT.
|
|
|
|
append( iv_uri = iv_uri
|
|
iv_auth = rv_auth ).
|
|
|
|
ENDMETHOD.
|
|
|
|
METHOD load.
|
|
|
|
DATA: ls_auth LIKE LINE OF gt_auth.
|
|
|
|
|
|
READ TABLE gt_auth INTO ls_auth WITH KEY uri = lcl_url=>host( iv_uri ).
|
|
IF sy-subrc = 0.
|
|
rv_authorization = ls_auth-authorization.
|
|
|
|
IF NOT ii_client IS INITIAL.
|
|
ii_client->request->set_header_field(
|
|
name = 'authorization'
|
|
value = ls_auth-authorization ). "#EC NOTEXT
|
|
ii_client->propertytype_logon_popup = ii_client->co_disabled.
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
METHOD save.
|
|
|
|
DATA: lv_auth TYPE string.
|
|
|
|
|
|
lv_auth = ii_client->request->get_header_field( 'authorization' ). "#EC NOTEXT
|
|
|
|
IF NOT lv_auth IS INITIAL.
|
|
append( iv_uri = iv_uri
|
|
iv_auth = lv_auth ).
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
METHOD append.
|
|
|
|
FIELD-SYMBOLS: <ls_auth> LIKE LINE OF gt_auth.
|
|
|
|
|
|
READ TABLE gt_auth WITH KEY uri = lcl_url=>host( iv_uri )
|
|
TRANSPORTING NO FIELDS.
|
|
IF sy-subrc <> 0.
|
|
APPEND INITIAL LINE TO gt_auth ASSIGNING <ls_auth>.
|
|
<ls_auth>-uri = lcl_url=>host( iv_uri ).
|
|
<ls_auth>-authorization = iv_auth.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
ENDCLASS.
|
|
|
|
CLASS lcl_progress DEFINITION FINAL.
|
|
|
|
PUBLIC SECTION.
|
|
CLASS-METHODS:
|
|
show
|
|
IMPORTING
|
|
iv_key TYPE string
|
|
VALUE(iv_current) TYPE i
|
|
iv_total TYPE i
|
|
iv_text TYPE csequence.
|
|
|
|
PRIVATE SECTION.
|
|
CLASS-METHODS:
|
|
calc_pct
|
|
IMPORTING iv_current TYPE i
|
|
iv_total TYPE i
|
|
RETURNING VALUE(rv_pct) TYPE i.
|
|
|
|
ENDCLASS.
|
|
|
|
CLASS lcl_progress IMPLEMENTATION.
|
|
|
|
METHOD show.
|
|
|
|
DATA: lv_pct TYPE i,
|
|
lv_text TYPE string.
|
|
|
|
|
|
lv_pct = calc_pct( iv_current = iv_current
|
|
iv_total = iv_total ).
|
|
CONCATENATE iv_key '-' iv_text INTO lv_text SEPARATED BY space.
|
|
|
|
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
|
|
EXPORTING
|
|
percentage = lv_pct
|
|
text = lv_text.
|
|
|
|
ENDMETHOD.
|
|
|
|
METHOD calc_pct.
|
|
|
|
DATA: lv_f TYPE f.
|
|
|
|
|
|
lv_f = ( iv_current / iv_total ) * 100.
|
|
rv_pct = lv_f.
|
|
|
|
IF rv_pct = 100.
|
|
rv_pct = 99.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
ENDCLASS.
|
|
|
|
CLASS lcl_log DEFINITION FINAL.
|
|
|
|
PUBLIC SECTION.
|
|
METHODS:
|
|
add
|
|
IMPORTING
|
|
iv_msg TYPE csequence
|
|
iv_type TYPE symsgty DEFAULT 'E'
|
|
iv_rc TYPE balsort OPTIONAL,
|
|
count
|
|
RETURNING VALUE(rv_count) TYPE i,
|
|
to_html
|
|
RETURNING VALUE(ro_html) TYPE REF TO lcl_html,
|
|
clear,
|
|
has_rc "For unit tests mainly
|
|
IMPORTING iv_rc TYPE balsort
|
|
RETURNING VALUE(rv_yes) TYPE abap_bool,
|
|
show.
|
|
|
|
PRIVATE SECTION.
|
|
TYPES: BEGIN OF ty_log,
|
|
msg TYPE string,
|
|
type TYPE symsgty,
|
|
rc TYPE balsort,
|
|
END OF ty_log.
|
|
|
|
DATA: mt_log TYPE STANDARD TABLE OF ty_log WITH DEFAULT KEY.
|
|
|
|
ENDCLASS.
|
|
|
|
CLASS lcl_log IMPLEMENTATION.
|
|
|
|
METHOD to_html.
|
|
|
|
DATA: lv_class TYPE string,
|
|
lv_icon TYPE string.
|
|
|
|
FIELD-SYMBOLS: <ls_log> LIKE LINE OF mt_log.
|
|
|
|
CREATE OBJECT ro_html.
|
|
|
|
IF count( ) = 0.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
LOOP AT mt_log ASSIGNING <ls_log>.
|
|
CASE <ls_log>-type.
|
|
WHEN 'W'.
|
|
lv_icon = 'alert'.
|
|
lv_class = 'warning'.
|
|
WHEN 'E'.
|
|
lv_icon = 'flame'.
|
|
lv_class = 'error'.
|
|
WHEN OTHERS. " ??? unexpected
|
|
lv_icon = 'flame'.
|
|
lv_class = 'error'.
|
|
ENDCASE.
|
|
|
|
ro_html->add( |<span class="{ lv_class }">| ).
|
|
ro_html->add_icon( iv_name = lv_icon ).
|
|
ro_html->add( <ls_log>-msg ).
|
|
ro_html->add( '</span>' ).
|
|
ENDLOOP.
|
|
|
|
ENDMETHOD.
|
|
|
|
METHOD add.
|
|
|
|
FIELD-SYMBOLS: <ls_log> LIKE LINE OF mt_log.
|
|
|
|
APPEND INITIAL LINE TO mt_log ASSIGNING <ls_log>.
|
|
<ls_log>-msg = iv_msg.
|
|
<ls_log>-type = iv_type.
|
|
<ls_log>-rc = iv_rc.
|
|
|
|
ENDMETHOD.
|
|
|
|
METHOD show.
|
|
* only supports showing 4 errors, but I guess this is okay
|
|
* alternatively refactor to use method TO_HTML instead
|
|
|
|
DATA: ls_log1 LIKE LINE OF mt_log,
|
|
ls_log2 LIKE LINE OF mt_log,
|
|
ls_log3 LIKE LINE OF mt_log,
|
|
ls_log4 LIKE LINE OF mt_log.
|
|
|
|
|
|
READ TABLE mt_log INDEX 1 INTO ls_log1.
|
|
READ TABLE mt_log INDEX 2 INTO ls_log2.
|
|
READ TABLE mt_log INDEX 3 INTO ls_log3.
|
|
READ TABLE mt_log INDEX 4 INTO ls_log4.
|
|
|
|
CALL FUNCTION 'POPUP_TO_INFORM'
|
|
EXPORTING
|
|
titel = 'Log'
|
|
txt1 = ls_log1-msg
|
|
txt2 = ls_log2-msg
|
|
txt3 = ls_log3-msg
|
|
txt4 = ls_log4-msg.
|
|
|
|
ENDMETHOD.
|
|
|
|
METHOD count.
|
|
rv_count = lines( mt_log ).
|
|
ENDMETHOD.
|
|
|
|
METHOD clear.
|
|
CLEAR mt_log.
|
|
ENDMETHOD. " clear.
|
|
|
|
METHOD has_rc.
|
|
READ TABLE mt_log WITH KEY rc = iv_rc TRANSPORTING NO FIELDS.
|
|
rv_yes = boolc( sy-subrc = 0 ).
|
|
ENDMETHOD. "has_rc
|
|
|
|
ENDCLASS.
|