mirror of
https://github.com/abapGit/abapGit.git
synced 2025-04-30 11:46:38 +08:00
Possible solution to zabapgit merge functionality to resolve conflicts (#1407)
* Merging per Textfile * Add files via upload * Delete WolfTreak_ABAPGIT_Merging * Refactoring vom Coding, Darstellung verbessert * Merging page changed and also merging class extended to instance and conflict methods added * Refactoring for Travis * Refactoring for Travis * Escaping of merged content functions now correct
This commit is contained in:
parent
174f9eafa7
commit
0aecdf7255
|
@ -1,31 +1,39 @@
|
|||
CLASS zcl_abapgit_gui_page_merge DEFINITION
|
||||
PUBLIC
|
||||
INHERITING FROM zcl_abapgit_gui_page
|
||||
FINAL
|
||||
CREATE PUBLIC INHERITING FROM zcl_abapgit_gui_page.
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
METHODS:
|
||||
constructor
|
||||
IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online
|
||||
iv_source TYPE string
|
||||
iv_target TYPE string
|
||||
RAISING zcx_abapgit_exception,
|
||||
zif_abapgit_gui_page~on_event REDEFINITION.
|
||||
|
||||
METHODS constructor
|
||||
IMPORTING
|
||||
!io_repo TYPE REF TO zcl_abapgit_repo_online
|
||||
!iv_source TYPE string
|
||||
!iv_target TYPE string
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
|
||||
METHODS zif_abapgit_gui_page~on_event
|
||||
REDEFINITION.
|
||||
PROTECTED SECTION.
|
||||
METHODS render_content REDEFINITION.
|
||||
|
||||
PRIVATE SECTION.
|
||||
DATA: mo_repo TYPE REF TO zcl_abapgit_repo_online,
|
||||
ms_merge TYPE zif_abapgit_definitions=>ty_merge.
|
||||
|
||||
CONSTANTS: BEGIN OF c_actions,
|
||||
DATA mo_repo TYPE REF TO zcl_abapgit_repo_online .
|
||||
DATA mo_merge TYPE REF TO zcl_abapgit_merge .
|
||||
CONSTANTS:
|
||||
BEGIN OF c_actions,
|
||||
merge TYPE string VALUE 'merge' ##NO_TEXT,
|
||||
END OF c_actions.
|
||||
res_conflicts TYPE string VALUE 'res_conflicts' ##NO_TEXT,
|
||||
END OF c_actions .
|
||||
|
||||
METHODS:
|
||||
build_menu
|
||||
RETURNING VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar.
|
||||
METHODS build_menu
|
||||
IMPORTING
|
||||
VALUE(iv_with_conflict) TYPE boolean OPTIONAL
|
||||
RETURNING
|
||||
VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar .
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
|
@ -37,7 +45,11 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_MERGE IMPLEMENTATION.
|
|||
|
||||
CREATE OBJECT ro_menu.
|
||||
|
||||
ro_menu->add( iv_txt = 'Merge' iv_act = c_actions-merge ) ##NO_TEXT.
|
||||
ro_menu->add( iv_txt = 'Merge' iv_act = c_actions-merge iv_cur = abap_false ) ##NO_TEXT.
|
||||
|
||||
IF iv_with_conflict EQ abap_true.
|
||||
ro_menu->add( iv_txt = 'Resolve Conflicts' iv_act = c_actions-res_conflicts ) ##NO_TEXT.
|
||||
ENDIF.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
@ -45,15 +57,18 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_MERGE IMPLEMENTATION.
|
|||
METHOD constructor.
|
||||
|
||||
super->constructor( ).
|
||||
ms_control-page_title = 'MERGE'.
|
||||
ms_control-page_menu = build_menu( ).
|
||||
|
||||
mo_repo = io_repo.
|
||||
|
||||
ms_merge = zcl_abapgit_merge=>run(
|
||||
CREATE OBJECT mo_merge
|
||||
EXPORTING
|
||||
io_repo = io_repo
|
||||
iv_source = iv_source
|
||||
iv_target = iv_target ).
|
||||
iv_source_branch = iv_source
|
||||
iv_target_branch = iv_target.
|
||||
mo_merge->run( ).
|
||||
|
||||
ms_control-page_title = 'MERGE'.
|
||||
ms_control-page_menu = build_menu( iv_with_conflict = mo_merge->has_conflicts( ) ).
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
@ -78,12 +93,17 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_MERGE IMPLEMENTATION.
|
|||
ENDIF.
|
||||
END-OF-DEFINITION.
|
||||
|
||||
DATA: lt_files LIKE ms_merge-stree,
|
||||
ls_result LIKE LINE OF ms_merge-result.
|
||||
DATA: ls_merge TYPE zif_abapgit_definitions=>ty_merge,
|
||||
lt_files LIKE ls_merge-stree,
|
||||
ls_result LIKE LINE OF ls_merge-result.
|
||||
|
||||
FIELD-SYMBOLS: <ls_show> LIKE LINE OF lt_files,
|
||||
<ls_file> LIKE LINE OF lt_files.
|
||||
|
||||
ls_merge = mo_merge->get_result( ).
|
||||
|
||||
"If now exists no conflicts anymore, conflicts button should disappear
|
||||
ms_control-page_menu = build_menu( iv_with_conflict = mo_merge->has_conflicts( ) ).
|
||||
|
||||
CREATE OBJECT ro_html.
|
||||
|
||||
|
@ -95,27 +115,27 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_MERGE IMPLEMENTATION.
|
|||
|
||||
ro_html->add( '<table>' ).
|
||||
ro_html->add( '<tr>' ).
|
||||
ro_html->add( '<td>Source:</td>' ).
|
||||
ro_html->add( '<td>Source</td>' ).
|
||||
ro_html->add( '<td>' ).
|
||||
ro_html->add( ms_merge-source-name ).
|
||||
ro_html->add( ls_merge-source-name ).
|
||||
ro_html->add( '</td></tr>' ).
|
||||
ro_html->add( '<tr>' ).
|
||||
ro_html->add( '<td>Target:</td>' ).
|
||||
ro_html->add( '<td>Target</td>' ).
|
||||
ro_html->add( '<td>' ).
|
||||
ro_html->add( ms_merge-target-name ).
|
||||
ro_html->add( ls_merge-target-name ).
|
||||
ro_html->add( '</td></tr>' ).
|
||||
ro_html->add( '<tr>' ).
|
||||
ro_html->add( '<td>Ancestor:</td>' ).
|
||||
ro_html->add( '<td>Ancestor</td>' ).
|
||||
ro_html->add( '<td>' ).
|
||||
ro_html->add( ms_merge-common-commit ).
|
||||
ro_html->add( ls_merge-common-commit ).
|
||||
ro_html->add( '</td></tr>' ).
|
||||
ro_html->add( '</table>' ).
|
||||
|
||||
ro_html->add( '<br>' ).
|
||||
|
||||
APPEND LINES OF ms_merge-stree TO lt_files.
|
||||
APPEND LINES OF ms_merge-ttree TO lt_files.
|
||||
APPEND LINES OF ms_merge-ctree TO lt_files.
|
||||
APPEND LINES OF ls_merge-stree TO lt_files.
|
||||
APPEND LINES OF ls_merge-ttree TO lt_files.
|
||||
APPEND LINES OF ls_merge-ctree TO lt_files.
|
||||
SORT lt_files BY path DESCENDING name ASCENDING.
|
||||
DELETE ADJACENT DUPLICATES FROM lt_files COMPARING path name.
|
||||
|
||||
|
@ -132,20 +152,20 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_MERGE IMPLEMENTATION.
|
|||
ro_html->add( '</tr>' ).
|
||||
LOOP AT lt_files ASSIGNING <ls_file>.
|
||||
CLEAR ls_result.
|
||||
READ TABLE ms_merge-result INTO ls_result
|
||||
READ TABLE ls_merge-result INTO ls_result
|
||||
WITH KEY path = <ls_file>-path name = <ls_file>-name.
|
||||
|
||||
ro_html->add( '<tr>' ).
|
||||
_show_file ms_merge-stree.
|
||||
_show_file ms_merge-ttree.
|
||||
_show_file ms_merge-ctree.
|
||||
_show_file ms_merge-result.
|
||||
_show_file ls_merge-stree.
|
||||
_show_file ls_merge-ttree.
|
||||
_show_file ls_merge-ctree.
|
||||
_show_file ls_merge-result.
|
||||
ro_html->add( '</tr>' ).
|
||||
ENDLOOP.
|
||||
ro_html->add( '</table>' ).
|
||||
ro_html->add( '<br>' ).
|
||||
ro_html->add( '<b>' ).
|
||||
ro_html->add( ms_merge-conflict ).
|
||||
ro_html->add( ls_merge-conflict ).
|
||||
ro_html->add( '</b>' ).
|
||||
ro_html->add( '</div>' ).
|
||||
|
||||
|
@ -156,15 +176,28 @@ CLASS ZCL_ABAPGIT_GUI_PAGE_MERGE IMPLEMENTATION.
|
|||
|
||||
CASE iv_action.
|
||||
WHEN c_actions-merge.
|
||||
IF ms_merge-stage->count( ) = 0.
|
||||
IF mo_merge->has_conflicts( ) EQ abap_true.
|
||||
zcx_abapgit_exception=>raise( 'conflicts exists' ).
|
||||
ENDIF.
|
||||
|
||||
IF mo_merge->get_result( )-stage->count( ) EQ 0.
|
||||
zcx_abapgit_exception=>raise( 'nothing to merge' ).
|
||||
ENDIF.
|
||||
|
||||
CREATE OBJECT ei_page TYPE zcl_abapgit_gui_page_commit
|
||||
EXPORTING
|
||||
io_repo = mo_repo
|
||||
io_stage = ms_merge-stage.
|
||||
io_stage = mo_merge->get_result( )-stage.
|
||||
ev_state = zif_abapgit_definitions=>gc_event_state-new_page.
|
||||
|
||||
WHEN c_actions-res_conflicts.
|
||||
CREATE OBJECT ei_page TYPE zcl_abapgit_gui_page_merge_res
|
||||
EXPORTING
|
||||
io_repo = mo_repo
|
||||
io_merge_page = me
|
||||
io_merge = mo_merge.
|
||||
ev_state = zif_abapgit_definitions=>gc_event_state-new_page.
|
||||
|
||||
ENDCASE.
|
||||
|
||||
ENDMETHOD.
|
||||
|
|
|
@ -14,6 +14,14 @@
|
|||
<FIXPT>X</FIXPT>
|
||||
<UNICODE>X</UNICODE>
|
||||
</VSEOCLASS>
|
||||
<DESCRIPTIONS>
|
||||
<SEOCOMPOTX>
|
||||
<CLSNAME>ZCL_ABAPGIT_GUI_PAGE_MERGE</CLSNAME>
|
||||
<CMPNAME>MO_MERGE</CMPNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>Merge logic</DESCRIPT>
|
||||
</SEOCOMPOTX>
|
||||
</DESCRIPTIONS>
|
||||
</asx:values>
|
||||
</asx:abap>
|
||||
</abapGit>
|
||||
|
|
583
src/ui/zcl_abapgit_gui_page_merge_res.clas.abap
Normal file
583
src/ui/zcl_abapgit_gui_page_merge_res.clas.abap
Normal file
|
@ -0,0 +1,583 @@
|
|||
CLASS zcl_abapgit_gui_page_merge_res DEFINITION
|
||||
PUBLIC
|
||||
INHERITING FROM zcl_abapgit_gui_page
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
|
||||
METHODS constructor
|
||||
IMPORTING
|
||||
!io_repo TYPE REF TO zcl_abapgit_repo_online
|
||||
!io_merge_page TYPE REF TO zcl_abapgit_gui_page_merge
|
||||
!io_merge TYPE REF TO zcl_abapgit_merge
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
|
||||
METHODS zif_abapgit_gui_page~on_event
|
||||
REDEFINITION .
|
||||
PROTECTED SECTION.
|
||||
METHODS render_content REDEFINITION.
|
||||
|
||||
PRIVATE SECTION.
|
||||
|
||||
TYPES:
|
||||
BEGIN OF ty_file_diff,
|
||||
path TYPE string,
|
||||
filename TYPE string,
|
||||
lstate TYPE char1,
|
||||
rstate TYPE char1,
|
||||
fstate TYPE char1, " FILE state - Abstraction for shorter ifs
|
||||
o_diff TYPE REF TO zcl_abapgit_diff,
|
||||
changed_by TYPE xubname,
|
||||
type TYPE string,
|
||||
END OF ty_file_diff .
|
||||
TYPES:
|
||||
tt_file_diff TYPE STANDARD TABLE OF ty_file_diff .
|
||||
|
||||
CONSTANTS:
|
||||
BEGIN OF c_actions,
|
||||
toggle_mode TYPE string VALUE 'toggle_mode' ##NO_TEXT,
|
||||
apply_merge TYPE string VALUE 'apply_merge' ##NO_TEXT,
|
||||
apply_source TYPE string VALUE 'apply_source' ##NO_TEXT,
|
||||
apply_target TYPE string VALUE 'apply_target' ##NO_TEXT,
|
||||
cancel TYPE string VALUE 'cancel' ##NO_TEXT,
|
||||
END OF c_actions .
|
||||
CONSTANTS:
|
||||
BEGIN OF c_merge_mode,
|
||||
selection TYPE string VALUE 'selection' ##NO_TEXT,
|
||||
merge TYPE string VALUE 'merge' ##NO_TEXT,
|
||||
END OF c_merge_mode .
|
||||
DATA mo_merge TYPE REF TO zcl_abapgit_merge .
|
||||
DATA mo_merge_page TYPE REF TO zcl_abapgit_gui_page_merge .
|
||||
DATA mo_repo TYPE REF TO zcl_abapgit_repo_online .
|
||||
DATA ms_diff_file TYPE ty_file_diff .
|
||||
DATA mv_current_conflict_index TYPE sytabix .
|
||||
DATA mv_merge_mode TYPE string .
|
||||
DATA mt_conflicts TYPE zif_abapgit_definitions=>tt_merge_conflict .
|
||||
|
||||
METHODS apply_merged_content
|
||||
IMPORTING
|
||||
!it_postdata TYPE cnht_post_data_tab
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
METHODS build_menu
|
||||
IMPORTING
|
||||
VALUE(iv_with_conflict) TYPE boolean OPTIONAL
|
||||
RETURNING
|
||||
VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar .
|
||||
METHODS is_binary
|
||||
IMPORTING
|
||||
!iv_d1 TYPE xstring
|
||||
!iv_d2 TYPE xstring
|
||||
RETURNING
|
||||
VALUE(rv_yes) TYPE abap_bool .
|
||||
METHODS render_beacon
|
||||
IMPORTING
|
||||
!is_diff_line TYPE zif_abapgit_definitions=>ty_diff
|
||||
!is_diff TYPE ty_file_diff
|
||||
RETURNING
|
||||
VALUE(ro_html) TYPE REF TO zcl_abapgit_html .
|
||||
METHODS render_diff
|
||||
IMPORTING
|
||||
!is_diff TYPE ty_file_diff
|
||||
RETURNING
|
||||
VALUE(ro_html) TYPE REF TO zcl_abapgit_html
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
METHODS render_diff_head
|
||||
IMPORTING
|
||||
!is_diff TYPE ty_file_diff
|
||||
RETURNING
|
||||
VALUE(ro_html) TYPE REF TO zcl_abapgit_html .
|
||||
METHODS render_lines
|
||||
IMPORTING
|
||||
!is_diff TYPE ty_file_diff
|
||||
RETURNING
|
||||
VALUE(ro_html) TYPE REF TO zcl_abapgit_html .
|
||||
METHODS render_line_split
|
||||
IMPORTING
|
||||
!is_diff_line TYPE zif_abapgit_definitions=>ty_diff
|
||||
!iv_fstate TYPE char1
|
||||
RETURNING
|
||||
VALUE(ro_html) TYPE REF TO zcl_abapgit_html .
|
||||
METHODS render_table_head
|
||||
RETURNING
|
||||
VALUE(ro_html) TYPE REF TO zcl_abapgit_html .
|
||||
METHODS resolve_diff
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
METHODS toggle_merge_mode .
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
|
||||
CLASS ZCL_ABAPGIT_GUI_PAGE_MERGE_RES IMPLEMENTATION.
|
||||
|
||||
|
||||
METHOD apply_merged_content.
|
||||
|
||||
CONSTANTS: lc_replace TYPE string VALUE '<<new>>'.
|
||||
|
||||
DATA: BEGIN OF filedata,
|
||||
merge_content TYPE string,
|
||||
END OF filedata.
|
||||
|
||||
DATA: lv_string TYPE string,
|
||||
lt_fields TYPE tihttpnvp,
|
||||
lv_new_file_content TYPE xstring.
|
||||
|
||||
FIELD-SYMBOLS: <postdata_line> LIKE LINE OF it_postdata,
|
||||
<ls_conflict> TYPE zif_abapgit_definitions=>ty_merge_conflict.
|
||||
|
||||
LOOP AT it_postdata ASSIGNING <postdata_line>.
|
||||
lv_string = |{ lv_string }{ <postdata_line> }|.
|
||||
ENDLOOP.
|
||||
REPLACE ALL OCCURRENCES OF zif_abapgit_definitions=>gc_crlf IN lv_string WITH lc_replace.
|
||||
REPLACE ALL OCCURRENCES OF zif_abapgit_definitions=>gc_newline IN lv_string WITH lc_replace.
|
||||
|
||||
lt_fields = zcl_abapgit_html_action_utils=>parse_fields_upper_case_name( lv_string ).
|
||||
zcl_abapgit_html_action_utils=>get_field( EXPORTING name = 'MERGE_CONTENT'
|
||||
it = lt_fields
|
||||
CHANGING cv = filedata ).
|
||||
filedata-merge_content = cl_http_utility=>unescape_url( escaped = filedata-merge_content ).
|
||||
REPLACE ALL OCCURRENCES OF lc_replace IN filedata-merge_content WITH zif_abapgit_definitions=>gc_newline.
|
||||
|
||||
lv_new_file_content = zcl_abapgit_convert=>string_to_xstring_utf8( iv_string = filedata-merge_content ).
|
||||
|
||||
READ TABLE mt_conflicts ASSIGNING <ls_conflict> INDEX mv_current_conflict_index.
|
||||
<ls_conflict>-result_sha1 = zcl_abapgit_hash=>sha1( iv_type = zif_abapgit_definitions=>gc_type-blob
|
||||
iv_data = lv_new_file_content ).
|
||||
<ls_conflict>-result_data = lv_new_file_content.
|
||||
mo_merge->resolve_conflict( is_conflict = <ls_conflict> ).
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD build_menu.
|
||||
|
||||
CREATE OBJECT ro_menu.
|
||||
ro_menu->add( iv_txt = 'Toggle merge mode' iv_act = c_actions-toggle_mode ) ##NO_TEXT.
|
||||
ro_menu->add( iv_txt = 'Cancel' iv_act = c_actions-cancel ) ##NO_TEXT.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD constructor.
|
||||
|
||||
super->constructor( ).
|
||||
|
||||
mo_repo = io_repo.
|
||||
ms_control-page_title = 'Resolve Conflicts'.
|
||||
ms_control-page_menu = build_menu( ).
|
||||
|
||||
mo_merge_page = io_merge_page.
|
||||
mo_merge = io_merge.
|
||||
mv_merge_mode = c_merge_mode-selection.
|
||||
mv_current_conflict_index = 1.
|
||||
mt_conflicts = io_merge->get_conflicts( ).
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD is_binary.
|
||||
|
||||
DATA: lv_len TYPE i,
|
||||
lv_idx TYPE i,
|
||||
lv_x TYPE x.
|
||||
|
||||
FIELD-SYMBOLS <lv_data> LIKE iv_d1.
|
||||
|
||||
|
||||
IF iv_d1 IS NOT INITIAL. " One of them might be new and so empty
|
||||
ASSIGN iv_d1 TO <lv_data>.
|
||||
ELSE.
|
||||
ASSIGN iv_d2 TO <lv_data>.
|
||||
ENDIF.
|
||||
|
||||
lv_len = xstrlen( <lv_data> ).
|
||||
IF lv_len = 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
|
||||
IF lv_len > 100.
|
||||
lv_len = 100.
|
||||
ENDIF.
|
||||
|
||||
" Simple char range test
|
||||
" stackoverflow.com/questions/277521/how-to-identify-the-file-content-as-ascii-or-binary
|
||||
DO lv_len TIMES. " I'm sure there is more efficient way ...
|
||||
lv_idx = sy-index - 1.
|
||||
lv_x = <lv_data>+lv_idx(1).
|
||||
|
||||
IF NOT ( lv_x BETWEEN 9 AND 13 OR lv_x BETWEEN 32 AND 126 ).
|
||||
rv_yes = abap_true.
|
||||
EXIT.
|
||||
ENDIF.
|
||||
ENDDO.
|
||||
|
||||
ENDMETHOD. " is_binary.
|
||||
|
||||
|
||||
METHOD render_beacon.
|
||||
|
||||
DATA: lv_beacon TYPE string.
|
||||
|
||||
CREATE OBJECT ro_html.
|
||||
|
||||
IF is_diff_line-beacon > 0.
|
||||
READ TABLE is_diff-o_diff->mt_beacons INTO lv_beacon INDEX is_diff_line-beacon.
|
||||
ELSE.
|
||||
lv_beacon = '---'.
|
||||
ENDIF.
|
||||
|
||||
|
||||
ro_html->add( '<thead class="nav_line">' ).
|
||||
ro_html->add( '<tr>' ).
|
||||
|
||||
ro_html->add( '<th class="num"></th>' ).
|
||||
ro_html->add( |<th colspan="3">@@ { is_diff_line-new_num } @@ { lv_beacon }</th>| ).
|
||||
|
||||
ro_html->add( '</tr>' ).
|
||||
ro_html->add( '</thead>' ).
|
||||
|
||||
ENDMETHOD. " render_beacon.
|
||||
|
||||
|
||||
METHOD render_content.
|
||||
|
||||
resolve_diff( ).
|
||||
IF ms_diff_file IS INITIAL.
|
||||
zcx_abapgit_exception=>raise( 'no conflict found' ).
|
||||
ENDIF.
|
||||
|
||||
CREATE OBJECT ro_html.
|
||||
ro_html->add( |<div id="diff-list" data-repo-key="{ mo_repo->get_key( ) }">| ).
|
||||
ro_html->add( render_diff( ms_diff_file ) ).
|
||||
ro_html->add( '</div>' ).
|
||||
|
||||
ENDMETHOD. "render_content
|
||||
|
||||
|
||||
METHOD render_diff.
|
||||
|
||||
DATA: lv_target_content TYPE string.
|
||||
FIELD-SYMBOLS: <ls_conflict> TYPE zif_abapgit_definitions=>ty_merge_conflict.
|
||||
|
||||
CREATE OBJECT ro_html.
|
||||
|
||||
ro_html->add( |<div class="diff" data-type="{ is_diff-type
|
||||
}" data-changed-by="{ is_diff-changed_by
|
||||
}" data-file="{ is_diff-path && is_diff-filename }">| ). "#EC NOTEXT
|
||||
ro_html->add( render_diff_head( is_diff ) ).
|
||||
|
||||
" Content
|
||||
IF is_diff-type <> 'binary'.
|
||||
|
||||
IF mv_merge_mode EQ c_merge_mode-selection.
|
||||
ro_html->add( '<div class="diff_content">' ). "#EC NOTEXT
|
||||
ro_html->add( '<table class="diff_tab syntax-hl">' ). "#EC NOTEXT
|
||||
ro_html->add( render_table_head( ) ).
|
||||
ro_html->add( render_lines( is_diff ) ).
|
||||
ro_html->add( '</table>' ). "#EC NOTEXT
|
||||
ro_html->add( '</div>' ). "#EC NOTEXT
|
||||
ELSE.
|
||||
|
||||
"Table for Div-Table and textarea
|
||||
ro_html->add( '<div class="diff_content">' ). "#EC NOTEXT
|
||||
ro_html->add( '<table>' ). "#EC NOTEXT
|
||||
ro_html->add( '<thead class="header">' ). "#EC NOTEXT
|
||||
ro_html->add( '<tr>' ). "#EC NOTEXT
|
||||
ro_html->add( '<th>Code</th>' ). "#EC NOTEXT
|
||||
ro_html->add( '<th>Merge - ' ). "#EC NOTEXT
|
||||
ro_html->add_a( iv_act = 'submitFormById(''merge_form'');' "#EC NOTEXT
|
||||
iv_txt = 'Apply'
|
||||
iv_typ = zif_abapgit_definitions=>gc_action_type-onclick
|
||||
iv_opt = zif_abapgit_definitions=>gc_html_opt-strong ).
|
||||
ro_html->add( '</th> ' ). "#EC NOTEXT
|
||||
ro_html->add( '</tr>' ). "#EC NOTEXT
|
||||
ro_html->add( '</thead>' ). "#EC NOTEXT
|
||||
ro_html->add( '<td>' ).
|
||||
|
||||
"Diff-Table of source and target file
|
||||
ro_html->add( '<table class="diff_tab syntax-hl">' ). "#EC NOTEXT
|
||||
ro_html->add( render_table_head( ) ).
|
||||
ro_html->add( render_lines( is_diff ) ).
|
||||
ro_html->add( '</table>' ). "#EC NOTEXT
|
||||
|
||||
READ TABLE mt_conflicts ASSIGNING <ls_conflict> INDEX mv_current_conflict_index.
|
||||
IF sy-subrc EQ 0.
|
||||
lv_target_content = zcl_abapgit_convert=>xstring_to_string_utf8( <ls_conflict>-target_data ).
|
||||
lv_target_content = escape( val = lv_target_content format = cl_abap_format=>e_html_text ).
|
||||
ENDIF.
|
||||
|
||||
ro_html->add( '</td>' ). "#EC NOTEXT
|
||||
ro_html->add( '<td>' ). "#EC NOTEXT
|
||||
ro_html->add( '<div class="form-container">' ).
|
||||
ro_html->add( |<form id="merge_form" class="aligned-form" accept-charset="UTF-8"| ).
|
||||
ro_html->add( |method="post" action="sapevent:apply_merge">| ).
|
||||
ro_html->add( |<textarea id="merge_content" name="merge_content" | ).
|
||||
ro_html->add( |rows="{ lines( is_diff-o_diff->get( ) ) }">{ lv_target_content }</textarea>| ).
|
||||
ro_html->add( '<input type="submit" class="hidden-submit">' ).
|
||||
ro_html->add( '</form>' ). "#EC NOTEXT
|
||||
ro_html->add( '</div>' ). "#EC NOTEXT
|
||||
ro_html->add( '</td>' ). "#EC NOTEXT
|
||||
ro_html->add( '</table>' ). "#EC NOTEXT
|
||||
ro_html->add( '</div>' ). "#EC NOTEXT
|
||||
ENDIF.
|
||||
ELSE.
|
||||
ro_html->add( '<div class="diff_content paddings center grey">' ). "#EC NOTEXT
|
||||
ro_html->add( 'The content seems to be binary.' ). "#EC NOTEXT
|
||||
ro_html->add( 'Cannot display as diff.' ). "#EC NOTEXT
|
||||
ro_html->add( '</div>' ). "#EC NOTEXT
|
||||
ENDIF.
|
||||
|
||||
ro_html->add( '</div>' ). "#EC NOTEXT
|
||||
|
||||
ENDMETHOD. " render_diff
|
||||
|
||||
|
||||
METHOD render_diff_head.
|
||||
|
||||
DATA: ls_stats TYPE zif_abapgit_definitions=>ty_count.
|
||||
|
||||
CREATE OBJECT ro_html.
|
||||
|
||||
ro_html->add( '<div class="diff_head">' ). "#EC NOTEXT
|
||||
|
||||
IF is_diff-type <> 'binary' AND is_diff-o_diff IS NOT INITIAL.
|
||||
ls_stats = is_diff-o_diff->stats( ).
|
||||
ro_html->add( |<span class="diff_banner diff_ins">+ { ls_stats-insert }</span>| ).
|
||||
ro_html->add( |<span class="diff_banner diff_del">- { ls_stats-delete }</span>| ).
|
||||
ro_html->add( |<span class="diff_banner diff_upd">~ { ls_stats-update }</span>| ).
|
||||
ENDIF.
|
||||
|
||||
ro_html->add( |<span class="diff_name">{ is_diff-filename }</span>| ). "#EC NOTEXT
|
||||
ro_html->add( '</div>' ). "#EC NOTEXT
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD render_lines.
|
||||
|
||||
DATA: lo_highlighter TYPE REF TO zcl_abapgit_syntax_highlighter,
|
||||
lt_diffs TYPE zif_abapgit_definitions=>ty_diffs_tt,
|
||||
lv_insert_nav TYPE abap_bool.
|
||||
|
||||
FIELD-SYMBOLS <ls_diff> LIKE LINE OF lt_diffs.
|
||||
|
||||
lo_highlighter = zcl_abapgit_syntax_highlighter=>create( is_diff-filename ).
|
||||
CREATE OBJECT ro_html.
|
||||
|
||||
lt_diffs = is_diff-o_diff->get( ).
|
||||
|
||||
LOOP AT lt_diffs ASSIGNING <ls_diff>.
|
||||
IF <ls_diff>-short = abap_false.
|
||||
lv_insert_nav = abap_true.
|
||||
CONTINUE.
|
||||
ENDIF.
|
||||
|
||||
IF lv_insert_nav = abap_true. " Insert separator line with navigation
|
||||
ro_html->add( render_beacon( is_diff_line = <ls_diff> is_diff = is_diff ) ).
|
||||
lv_insert_nav = abap_false.
|
||||
ENDIF.
|
||||
|
||||
IF lo_highlighter IS BOUND.
|
||||
<ls_diff>-new = lo_highlighter->process_line( <ls_diff>-new ).
|
||||
<ls_diff>-old = lo_highlighter->process_line( <ls_diff>-old ).
|
||||
ELSE.
|
||||
<ls_diff>-new = escape( val = <ls_diff>-new format = cl_abap_format=>e_html_attr ).
|
||||
<ls_diff>-old = escape( val = <ls_diff>-old format = cl_abap_format=>e_html_attr ).
|
||||
ENDIF.
|
||||
|
||||
CONDENSE <ls_diff>-new_num. "get rid of leading spaces
|
||||
CONDENSE <ls_diff>-old_num.
|
||||
|
||||
ro_html->add( render_line_split( is_diff_line = <ls_diff>
|
||||
iv_fstate = is_diff-fstate ) ).
|
||||
|
||||
ENDLOOP.
|
||||
|
||||
ENDMETHOD. "render_lines
|
||||
|
||||
|
||||
METHOD render_line_split.
|
||||
|
||||
DATA: lv_new TYPE string,
|
||||
lv_old TYPE string,
|
||||
lv_merge TYPE string,
|
||||
lv_mark TYPE string,
|
||||
lv_bg TYPE string.
|
||||
|
||||
CREATE OBJECT ro_html.
|
||||
|
||||
" New line
|
||||
lv_mark = ` `.
|
||||
IF is_diff_line-result = zif_abapgit_definitions=>c_diff-update.
|
||||
lv_bg = ' diff_upd'.
|
||||
lv_mark = `~`.
|
||||
ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-insert.
|
||||
lv_bg = ' diff_ins'.
|
||||
lv_mark = `+`.
|
||||
ENDIF.
|
||||
lv_new = |<td class="num" line-num="{ is_diff_line-new_num }"></td>|
|
||||
&& |<td class="code{ lv_bg }">{ lv_mark }{ is_diff_line-new }</td>|.
|
||||
|
||||
" Old line
|
||||
CLEAR lv_bg.
|
||||
lv_mark = ` `.
|
||||
IF is_diff_line-result = zif_abapgit_definitions=>c_diff-update.
|
||||
lv_bg = ' diff_upd'.
|
||||
lv_mark = `~`.
|
||||
ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-delete.
|
||||
lv_bg = ' diff_del'.
|
||||
lv_mark = `-`.
|
||||
ENDIF.
|
||||
lv_old = |<td class="num" line-num="{ is_diff_line-old_num }"></td>|
|
||||
&& |<td class="code{ lv_bg }">{ lv_mark }{ is_diff_line-old }</td>|.
|
||||
|
||||
" render line, inverse sides if remote is newer
|
||||
ro_html->add( '<tr>' ). "#EC NOTEXT
|
||||
ro_html->add( lv_old ). " Target
|
||||
ro_html->add( lv_new ). " Source
|
||||
ro_html->add( '</tr>' ). "#EC NOTEXT
|
||||
|
||||
ENDMETHOD. "render_line_split
|
||||
|
||||
|
||||
METHOD render_table_head.
|
||||
|
||||
CREATE OBJECT ro_html.
|
||||
IF mv_merge_mode EQ c_merge_mode-selection.
|
||||
ro_html->add( '<thead class="header">' ). "#EC NOTEXT
|
||||
ro_html->add( '<tr>' ). "#EC NOTEXT
|
||||
ro_html->add( '<th class="num"></th>' ). "#EC NOTEXT
|
||||
ro_html->add( '<form id="target_form" method="post" action="sapevent:apply_target">' ). "#EC NOTEXT
|
||||
ro_html->add( '<th>Target - ' && mo_merge->get_target_branch( ) && ' - ' ). "#EC NOTEXT
|
||||
ro_html->add_a( iv_act = 'submitFormById(''target_form'');' "#EC NOTEXT
|
||||
iv_txt = 'Apply'
|
||||
iv_typ = zif_abapgit_definitions=>gc_action_type-onclick
|
||||
iv_opt = zif_abapgit_definitions=>gc_html_opt-strong ).
|
||||
ro_html->add( '</th> ' ). "#EC NOTEXT
|
||||
ro_html->add( '</form>' ). "#EC NOTEXT
|
||||
ro_html->add( '<th class="num"></th>' ). "#EC NOTEXT
|
||||
ro_html->add( '<form id="source_form" method="post" action="sapevent:apply_source">' ). "#EC NOTEXT
|
||||
ro_html->add( '<th>Source - ' && mo_merge->get_source_branch( ) &&' - ' ). "#EC NOTEXT
|
||||
ro_html->add_a( iv_act = 'submitFormById(''source_form'');' "#EC NOTEXT
|
||||
iv_txt = 'Apply'
|
||||
iv_typ = zif_abapgit_definitions=>gc_action_type-onclick
|
||||
iv_opt = zif_abapgit_definitions=>gc_html_opt-strong ).
|
||||
ro_html->add( '</th> ' ). "#EC NOTEXT
|
||||
ro_html->add( '</form>' ). "#EC NOTEXT
|
||||
ro_html->add( '</tr>' ). "#EC NOTEXT
|
||||
ro_html->add( '</thead>' ). "#EC NOTEXT
|
||||
ELSE.
|
||||
ro_html->add( '<thead class="header">' ). "#EC NOTEXT
|
||||
ro_html->add( '<tr>' ). "#EC NOTEXT
|
||||
ro_html->add( '<th class="num"></th>' ). "#EC NOTEXT
|
||||
ro_html->add( '<th>Target - ' && mo_merge->get_target_branch( ) &&'</th> ' ). "#EC NOTEXT
|
||||
ro_html->add( '<th class="num"></th>' ). "#EC NOTEXT
|
||||
ro_html->add( '<th>Source - ' && mo_merge->get_source_branch( ) &&'</th> ' ). "#EC NOTEXT
|
||||
ro_html->add( '</tr>' ). "#EC NOTEXT
|
||||
ro_html->add( '</thead>' ). "#EC NOTEXT
|
||||
ENDIF.
|
||||
|
||||
ENDMETHOD. " render_table_head.
|
||||
|
||||
|
||||
METHOD resolve_diff.
|
||||
|
||||
DATA: lv_offs TYPE i.
|
||||
FIELD-SYMBOLS: <ls_conflict> TYPE zif_abapgit_definitions=>ty_merge_conflict.
|
||||
|
||||
CLEAR ms_diff_file.
|
||||
|
||||
READ TABLE mt_conflicts ASSIGNING <ls_conflict> INDEX mv_current_conflict_index.
|
||||
IF sy-subrc NE 0.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
|
||||
ms_diff_file-path = <ls_conflict>-path.
|
||||
ms_diff_file-filename = <ls_conflict>-filename.
|
||||
ms_diff_file-type = reverse( <ls_conflict>-filename ).
|
||||
|
||||
FIND FIRST OCCURRENCE OF '.' IN ms_diff_file-type MATCH OFFSET lv_offs.
|
||||
ms_diff_file-type = reverse( substring( val = ms_diff_file-type len = lv_offs ) ).
|
||||
IF ms_diff_file-type <> 'xml' AND ms_diff_file-type <> 'abap'.
|
||||
ms_diff_file-type = 'other'.
|
||||
ENDIF.
|
||||
|
||||
IF ms_diff_file-type = 'other'
|
||||
AND is_binary( iv_d1 = <ls_conflict>-source_data iv_d2 = <ls_conflict>-target_data ) = abap_true.
|
||||
ms_diff_file-type = 'binary'.
|
||||
ENDIF.
|
||||
|
||||
IF ms_diff_file-type <> 'binary'.
|
||||
CREATE OBJECT ms_diff_file-o_diff
|
||||
EXPORTING
|
||||
iv_new = <ls_conflict>-source_data
|
||||
iv_old = <ls_conflict>-target_data.
|
||||
ENDIF.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD toggle_merge_mode.
|
||||
|
||||
IF mv_merge_mode EQ c_merge_mode-selection.
|
||||
mv_merge_mode = c_merge_mode-merge.
|
||||
ELSE.
|
||||
mv_merge_mode = c_merge_mode-selection.
|
||||
ENDIF.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD zif_abapgit_gui_page~on_event.
|
||||
|
||||
FIELD-SYMBOLS: <ls_conflict> TYPE zif_abapgit_definitions=>ty_merge_conflict.
|
||||
|
||||
CASE iv_action.
|
||||
WHEN c_actions-apply_merge
|
||||
OR c_actions-apply_source
|
||||
OR c_actions-apply_target
|
||||
OR c_actions-cancel.
|
||||
|
||||
CASE iv_action.
|
||||
WHEN c_actions-apply_merge.
|
||||
apply_merged_content( it_postdata = it_postdata ).
|
||||
|
||||
WHEN c_actions-apply_source.
|
||||
READ TABLE mt_conflicts ASSIGNING <ls_conflict> INDEX mv_current_conflict_index.
|
||||
<ls_conflict>-result_sha1 = <ls_conflict>-source_sha1.
|
||||
<ls_conflict>-result_data = <ls_conflict>-source_data.
|
||||
mo_merge->resolve_conflict( is_conflict = <ls_conflict> ).
|
||||
|
||||
WHEN c_actions-apply_target.
|
||||
READ TABLE mt_conflicts ASSIGNING <ls_conflict> INDEX mv_current_conflict_index.
|
||||
<ls_conflict>-result_sha1 = <ls_conflict>-target_sha1.
|
||||
<ls_conflict>-result_data = <ls_conflict>-target_data.
|
||||
mo_merge->resolve_conflict( is_conflict = <ls_conflict> ).
|
||||
|
||||
ENDCASE.
|
||||
|
||||
mv_current_conflict_index = mv_current_conflict_index + 1.
|
||||
IF mv_current_conflict_index > lines( mt_conflicts ).
|
||||
CLEAR mv_current_conflict_index.
|
||||
ENDIF.
|
||||
|
||||
IF mv_current_conflict_index IS NOT INITIAL.
|
||||
ev_state = zif_abapgit_definitions=>gc_event_state-re_render.
|
||||
ELSE.
|
||||
ei_page = mo_merge_page.
|
||||
ev_state = zif_abapgit_definitions=>gc_event_state-go_back.
|
||||
ENDIF.
|
||||
|
||||
WHEN c_actions-toggle_mode.
|
||||
toggle_merge_mode( ).
|
||||
ev_state = zif_abapgit_definitions=>gc_event_state-re_render.
|
||||
|
||||
ENDCASE.
|
||||
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
45
src/ui/zcl_abapgit_gui_page_merge_res.clas.xml
Normal file
45
src/ui/zcl_abapgit_gui_page_merge_res.clas.xml
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?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_GUI_PAGE_MERGE_RES</CLSNAME>
|
||||
<VERSION>1</VERSION>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>GUI - Resolving Conflicts page</DESCRIPT>
|
||||
<EXPOSURE>2</EXPOSURE>
|
||||
<STATE>1</STATE>
|
||||
<CLSFINAL>X</CLSFINAL>
|
||||
<CLSCCINCL>X</CLSCCINCL>
|
||||
<FIXPT>X</FIXPT>
|
||||
<UNICODE>X</UNICODE>
|
||||
</VSEOCLASS>
|
||||
<DESCRIPTIONS>
|
||||
<SEOCOMPOTX>
|
||||
<CLSNAME>ZCL_ABAPGIT_GUI_PAGE_MERGE_RES</CLSNAME>
|
||||
<CMPNAME>MO_MERGE</CMPNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>Merge logic</DESCRIPT>
|
||||
</SEOCOMPOTX>
|
||||
<SEOCOMPOTX>
|
||||
<CLSNAME>ZCL_ABAPGIT_GUI_PAGE_MERGE_RES</CLSNAME>
|
||||
<CMPNAME>MO_MERGE_PAGE</CMPNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>GUI - Merging page</DESCRIPT>
|
||||
</SEOCOMPOTX>
|
||||
<SEOCOMPOTX>
|
||||
<CLSNAME>ZCL_ABAPGIT_GUI_PAGE_MERGE_RES</CLSNAME>
|
||||
<CMPNAME>MO_REPO</CMPNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>Online Repository</DESCRIPT>
|
||||
</SEOCOMPOTX>
|
||||
<SEOCOMPOTX>
|
||||
<CLSNAME>ZCL_ABAPGIT_GUI_PAGE_MERGE_RES</CLSNAME>
|
||||
<CMPNAME>MV_CURRENT_CONFLICT_INDEX</CMPNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>Row Index of Internal Tables</DESCRIPT>
|
||||
</SEOCOMPOTX>
|
||||
</DESCRIPTIONS>
|
||||
</asx:values>
|
||||
</asx:abap>
|
||||
</abapGit>
|
|
@ -1,37 +1,78 @@
|
|||
CLASS zcl_abapgit_merge DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
||||
CLASS zcl_abapgit_merge DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
CLASS-METHODS:
|
||||
run
|
||||
IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online
|
||||
iv_source TYPE string
|
||||
iv_target TYPE string
|
||||
RETURNING VALUE(rs_merge) TYPE zif_abapgit_definitions=>ty_merge
|
||||
RAISING zcx_abapgit_exception.
|
||||
|
||||
METHODS constructor
|
||||
IMPORTING
|
||||
!io_repo TYPE REF TO zcl_abapgit_repo_online
|
||||
!iv_source_branch TYPE string
|
||||
!iv_target_branch TYPE string
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
METHODS get_conflicts
|
||||
RETURNING
|
||||
VALUE(rt_conflicts) TYPE zif_abapgit_definitions=>tt_merge_conflict .
|
||||
METHODS get_result
|
||||
RETURNING
|
||||
VALUE(rs_merge) TYPE zif_abapgit_definitions=>ty_merge .
|
||||
METHODS get_source_branch
|
||||
RETURNING
|
||||
VALUE(rv_source_branch) TYPE string .
|
||||
METHODS get_target_branch
|
||||
RETURNING
|
||||
VALUE(rv_target_branch) TYPE string .
|
||||
METHODS has_conflicts
|
||||
RETURNING
|
||||
VALUE(rv_conflicts_exists) TYPE boolean .
|
||||
METHODS resolve_conflict
|
||||
IMPORTING
|
||||
!is_conflict TYPE zif_abapgit_definitions=>ty_merge_conflict
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
METHODS run
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
PRIVATE SECTION.
|
||||
CLASS-DATA: gs_merge TYPE zif_abapgit_definitions=>ty_merge,
|
||||
gt_objects TYPE zif_abapgit_definitions=>ty_objects_tt.
|
||||
|
||||
TYPES: ty_ancestor_tt TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_ancestor WITH DEFAULT KEY.
|
||||
TYPES:
|
||||
ty_ancestor_tt TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_ancestor WITH DEFAULT KEY .
|
||||
|
||||
CLASS-METHODS:
|
||||
all_files
|
||||
RETURNING VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_expanded_tt,
|
||||
calculate_result
|
||||
RAISING zcx_abapgit_exception,
|
||||
find_ancestors
|
||||
IMPORTING iv_commit TYPE zif_abapgit_definitions=>ty_sha1
|
||||
RETURNING VALUE(rt_ancestors) TYPE ty_ancestor_tt
|
||||
RAISING zcx_abapgit_exception,
|
||||
find_first_common
|
||||
IMPORTING it_list1 TYPE ty_ancestor_tt
|
||||
it_list2 TYPE ty_ancestor_tt
|
||||
RETURNING VALUE(rs_common) TYPE zif_abapgit_definitions=>ty_ancestor
|
||||
RAISING zcx_abapgit_exception,
|
||||
fetch_git
|
||||
IMPORTING iv_source TYPE string
|
||||
iv_target TYPE string
|
||||
RAISING zcx_abapgit_exception.
|
||||
DATA mo_repo TYPE REF TO zcl_abapgit_repo_online .
|
||||
DATA ms_merge TYPE zif_abapgit_definitions=>ty_merge .
|
||||
DATA mt_conflicts TYPE zif_abapgit_definitions=>tt_merge_conflict .
|
||||
DATA mt_objects TYPE zif_abapgit_definitions=>ty_objects_tt .
|
||||
DATA mv_source_branch TYPE string .
|
||||
DATA mv_target_branch TYPE string .
|
||||
|
||||
METHODS all_files
|
||||
RETURNING
|
||||
VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_expanded_tt .
|
||||
METHODS calculate_result
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
METHODS fetch_git
|
||||
RETURNING
|
||||
VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
METHODS find_ancestors
|
||||
IMPORTING
|
||||
!iv_commit TYPE zif_abapgit_definitions=>ty_sha1
|
||||
RETURNING
|
||||
VALUE(rt_ancestors) TYPE ty_ancestor_tt
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
METHODS find_first_common
|
||||
IMPORTING
|
||||
!it_list1 TYPE ty_ancestor_tt
|
||||
!it_list2 TYPE ty_ancestor_tt
|
||||
RETURNING
|
||||
VALUE(rs_common) TYPE zif_abapgit_definitions=>ty_ancestor
|
||||
RAISING
|
||||
zcx_abapgit_exception .
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
|
@ -41,9 +82,9 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
|
||||
METHOD all_files.
|
||||
|
||||
APPEND LINES OF gs_merge-stree TO rt_files.
|
||||
APPEND LINES OF gs_merge-ttree TO rt_files.
|
||||
APPEND LINES OF gs_merge-ctree TO rt_files.
|
||||
APPEND LINES OF ms_merge-stree TO rt_files.
|
||||
APPEND LINES OF ms_merge-ttree TO rt_files.
|
||||
APPEND LINES OF ms_merge-ctree TO rt_files.
|
||||
SORT rt_files BY path DESCENDING name ASCENDING.
|
||||
DELETE ADJACENT DUPLICATES FROM rt_files COMPARING path name.
|
||||
|
||||
|
@ -53,12 +94,12 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
METHOD calculate_result.
|
||||
|
||||
DEFINE _from_source.
|
||||
READ TABLE gt_objects ASSIGNING <ls_object>
|
||||
READ TABLE mt_objects ASSIGNING <ls_object>
|
||||
WITH KEY type = zif_abapgit_definitions=>gc_type-blob
|
||||
sha1 = <ls_source>-sha1.
|
||||
ASSERT sy-subrc = 0.
|
||||
|
||||
gs_merge-stage->add( iv_path = <ls_file>-path
|
||||
ms_merge-stage->add( iv_path = <ls_file>-path
|
||||
iv_filename = <ls_file>-name
|
||||
iv_data = <ls_object>-data ).
|
||||
END-OF-DEFINITION.
|
||||
|
@ -72,17 +113,17 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
<ls_target> LIKE LINE OF lt_files,
|
||||
<ls_common> LIKE LINE OF lt_files,
|
||||
<ls_file> LIKE LINE OF lt_files,
|
||||
<ls_result> LIKE LINE OF gs_merge-result,
|
||||
<ls_object> LIKE LINE OF gt_objects.
|
||||
|
||||
<ls_result> LIKE LINE OF ms_merge-result,
|
||||
<ls_object> LIKE LINE OF mt_objects,
|
||||
<ls_conflict> LIKE LINE OF mt_conflicts.
|
||||
|
||||
lt_files = all_files( ).
|
||||
|
||||
CREATE OBJECT gs_merge-stage
|
||||
CREATE OBJECT ms_merge-stage
|
||||
EXPORTING
|
||||
iv_branch_name = gs_merge-target-name
|
||||
iv_branch_sha1 = gs_merge-target-sha1
|
||||
iv_merge_source = gs_merge-source-sha1.
|
||||
iv_branch_name = ms_merge-target-name
|
||||
iv_branch_sha1 = ms_merge-target-sha1
|
||||
iv_merge_source = ms_merge-source-sha1.
|
||||
|
||||
LOOP AT lt_files ASSIGNING <ls_file>.
|
||||
|
||||
|
@ -90,11 +131,11 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
UNASSIGN <ls_target>.
|
||||
UNASSIGN <ls_common>.
|
||||
|
||||
READ TABLE gs_merge-stree ASSIGNING <ls_source>
|
||||
READ TABLE ms_merge-stree ASSIGNING <ls_source>
|
||||
WITH KEY path = <ls_file>-path name = <ls_file>-name. "#EC CI_SUBRC
|
||||
READ TABLE gs_merge-ttree ASSIGNING <ls_target>
|
||||
READ TABLE ms_merge-ttree ASSIGNING <ls_target>
|
||||
WITH KEY path = <ls_file>-path name = <ls_file>-name. "#EC CI_SUBRC
|
||||
READ TABLE gs_merge-ctree ASSIGNING <ls_common>
|
||||
READ TABLE ms_merge-ctree ASSIGNING <ls_common>
|
||||
WITH KEY path = <ls_file>-path name = <ls_file>-name. "#EC CI_SUBRC
|
||||
|
||||
lv_found_source = boolc( <ls_source> IS ASSIGNED ).
|
||||
|
@ -109,7 +150,7 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
AND lv_found_common = abap_true
|
||||
AND <ls_target>-sha1 = <ls_common>-sha1.
|
||||
* deleted in source, skip
|
||||
gs_merge-stage->rm( iv_path = <ls_file>-path
|
||||
ms_merge-stage->rm( iv_path = <ls_file>-path
|
||||
iv_filename = <ls_file>-name ).
|
||||
CONTINUE.
|
||||
ELSEIF lv_found_target = abap_false
|
||||
|
@ -119,7 +160,7 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
CONTINUE.
|
||||
ENDIF.
|
||||
|
||||
APPEND INITIAL LINE TO gs_merge-result ASSIGNING <ls_result>.
|
||||
APPEND INITIAL LINE TO ms_merge-result ASSIGNING <ls_result>.
|
||||
<ls_result>-path = <ls_file>-path.
|
||||
<ls_result>-name = <ls_file>-name.
|
||||
|
||||
|
@ -135,15 +176,32 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
AND <ls_target>-sha1 = <ls_source>-sha1.
|
||||
* added in source and target
|
||||
<ls_result>-sha1 = <ls_source>-sha1.
|
||||
ELSEIF lv_found_common = abap_false
|
||||
AND <ls_target>-sha1 <> <ls_source>-sha1.
|
||||
|
||||
INSERT INITIAL LINE INTO TABLE mt_conflicts ASSIGNING <ls_conflict>.
|
||||
<ls_conflict>-path = <ls_file>-path.
|
||||
<ls_conflict>-filename = <ls_file>-name.
|
||||
<ls_conflict>-source_sha1 = <ls_source>-sha1.
|
||||
READ TABLE mt_objects ASSIGNING <ls_object> WITH KEY type = zif_abapgit_definitions=>gc_type-blob
|
||||
sha1 = <ls_source>-sha1.
|
||||
<ls_conflict>-source_data = <ls_object>-data.
|
||||
|
||||
<ls_conflict>-target_sha1 = <ls_target>-sha1.
|
||||
READ TABLE mt_objects ASSIGNING <ls_object> WITH KEY type = zif_abapgit_definitions=>gc_type-blob
|
||||
sha1 = <ls_target>-sha1.
|
||||
<ls_conflict>-target_data = <ls_object>-data.
|
||||
|
||||
* added in source and target, but different, merge conflict must be resolved
|
||||
ms_merge-conflict = |{ <ls_file>-name } merge conflict|.
|
||||
CONTINUE.
|
||||
ENDIF.
|
||||
|
||||
IF lv_found_source = abap_false
|
||||
OR lv_found_target = abap_false
|
||||
OR lv_found_common = abap_false.
|
||||
CLEAR gs_merge-result.
|
||||
gs_merge-conflict = |{ <ls_file>-name
|
||||
} merge conflict, not found anywhere|.
|
||||
RETURN.
|
||||
ms_merge-conflict = |{ <ls_file>-name } merge conflict, not found anywhere|.
|
||||
CONTINUE.
|
||||
ENDIF.
|
||||
|
||||
IF <ls_target>-sha1 = <ls_source>-sha1.
|
||||
|
@ -158,13 +216,36 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
<ls_result>-sha1 = <ls_target>-sha1.
|
||||
ELSE.
|
||||
* changed in source and target, conflict
|
||||
CLEAR gs_merge-result.
|
||||
gs_merge-conflict = |{ <ls_file>-name
|
||||
} merge conflict, changed in source and target branch|.
|
||||
RETURN.
|
||||
* conflict must be resolved before merge
|
||||
INSERT INITIAL LINE INTO TABLE mt_conflicts ASSIGNING <ls_conflict>.
|
||||
<ls_conflict>-path = <ls_file>-path.
|
||||
<ls_conflict>-filename = <ls_file>-name.
|
||||
<ls_conflict>-source_sha1 = <ls_source>-sha1.
|
||||
READ TABLE mt_objects ASSIGNING <ls_object> WITH KEY type = zif_abapgit_definitions=>gc_type-blob
|
||||
sha1 = <ls_source>-sha1.
|
||||
<ls_conflict>-source_data = <ls_object>-data.
|
||||
|
||||
<ls_conflict>-target_sha1 = <ls_target>-sha1.
|
||||
READ TABLE mt_objects ASSIGNING <ls_object> WITH KEY type = zif_abapgit_definitions=>gc_type-blob
|
||||
sha1 = <ls_target>-sha1.
|
||||
<ls_conflict>-target_data = <ls_object>-data.
|
||||
|
||||
ms_merge-conflict = |{ <ls_file>-name } merge conflict, changed in source and target branch|.
|
||||
ENDIF.
|
||||
ENDLOOP.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD constructor.
|
||||
|
||||
IF iv_source_branch EQ iv_target_branch.
|
||||
zcx_abapgit_exception=>raise( 'source = target' ).
|
||||
ENDIF.
|
||||
|
||||
ENDLOOP.
|
||||
mo_repo = io_repo.
|
||||
mv_source_branch = iv_source_branch.
|
||||
mv_target_branch = iv_target_branch.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
@ -174,24 +255,23 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
DATA: lo_branch_list TYPE REF TO zcl_abapgit_git_branch_list,
|
||||
lt_upload TYPE zif_abapgit_definitions=>ty_git_branch_list_tt.
|
||||
|
||||
lo_branch_list = zcl_abapgit_git_transport=>branches( ms_merge-repo->get_url( ) ).
|
||||
ms_merge-source = lo_branch_list->find_by_name(
|
||||
zcl_abapgit_git_branch_list=>complete_heads_branch_name( mv_source_branch ) ).
|
||||
ms_merge-target = lo_branch_list->find_by_name(
|
||||
zcl_abapgit_git_branch_list=>complete_heads_branch_name( mv_target_branch ) ).
|
||||
|
||||
lo_branch_list = zcl_abapgit_git_transport=>branches( gs_merge-repo->get_url( ) ).
|
||||
gs_merge-source = lo_branch_list->find_by_name(
|
||||
zcl_abapgit_git_branch_list=>complete_heads_branch_name( iv_source ) ).
|
||||
gs_merge-target = lo_branch_list->find_by_name(
|
||||
zcl_abapgit_git_branch_list=>complete_heads_branch_name( iv_target ) ).
|
||||
|
||||
APPEND gs_merge-source TO lt_upload.
|
||||
APPEND gs_merge-target TO lt_upload.
|
||||
APPEND ms_merge-source TO lt_upload.
|
||||
APPEND ms_merge-target TO lt_upload.
|
||||
|
||||
zcl_abapgit_git_transport=>upload_pack(
|
||||
EXPORTING
|
||||
iv_url = gs_merge-repo->get_url( )
|
||||
iv_branch_name = gs_merge-repo->get_branch_name( )
|
||||
iv_url = ms_merge-repo->get_url( )
|
||||
iv_branch_name = ms_merge-repo->get_branch_name( )
|
||||
iv_deepen = abap_false
|
||||
it_branches = lt_upload
|
||||
IMPORTING
|
||||
et_objects = gt_objects ).
|
||||
et_objects = rt_objects ).
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
@ -212,13 +292,13 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
lv_commit LIKE LINE OF lt_visit.
|
||||
|
||||
FIELD-SYMBOLS: <ls_ancestor> LIKE LINE OF rt_ancestors,
|
||||
<ls_object> LIKE LINE OF gt_objects.
|
||||
<ls_object> LIKE LINE OF mt_objects.
|
||||
|
||||
|
||||
APPEND iv_commit TO lt_visit.
|
||||
|
||||
LOOP AT lt_visit INTO lv_commit.
|
||||
READ TABLE gt_objects ASSIGNING <ls_object>
|
||||
READ TABLE mt_objects ASSIGNING <ls_object>
|
||||
WITH KEY type = zif_abapgit_definitions=>gc_type-commit sha1 = lv_commit.
|
||||
ASSERT sy-subrc = 0.
|
||||
|
||||
|
@ -231,9 +311,11 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
<ls_ancestor>-commit = lv_commit.
|
||||
<ls_ancestor>-tree = ls_commit-tree.
|
||||
<ls_ancestor>-body = ls_commit-body.
|
||||
FIND REGEX zif_abapgit_definitions=>gc_author_regex IN ls_commit-author
|
||||
SUBMATCHES <ls_ancestor>-time ##NO_TEXT.
|
||||
ASSERT sy-subrc = 0.
|
||||
<ls_ancestor>-time = ls_commit-author.
|
||||
|
||||
"Strip Author entry of all but the time component
|
||||
REPLACE ALL OCCURRENCES OF REGEX '[a-zA-Z<>@.-]*' IN <ls_ancestor>-time WITH ''.
|
||||
CONDENSE <ls_ancestor>-time.
|
||||
ENDLOOP.
|
||||
|
||||
SORT rt_ancestors BY time DESCENDING.
|
||||
|
@ -246,7 +328,6 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
FIELD-SYMBOLS: <ls_list1> LIKE LINE OF it_list1,
|
||||
<ls_list2> LIKE LINE OF it_list2.
|
||||
|
||||
|
||||
LOOP AT it_list1 ASSIGNING <ls_list1>.
|
||||
LOOP AT it_list2 ASSIGNING <ls_list2>.
|
||||
IF <ls_list1>-tree = <ls_list2>-tree.
|
||||
|
@ -261,42 +342,107 @@ CLASS ZCL_ABAPGIT_MERGE IMPLEMENTATION.
|
|||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD get_conflicts.
|
||||
|
||||
rt_conflicts = mt_conflicts.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD get_result.
|
||||
|
||||
rs_merge = ms_merge.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD get_source_branch.
|
||||
|
||||
rv_source_branch = mv_source_branch.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD get_target_branch.
|
||||
|
||||
rv_target_branch = mv_target_branch.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD has_conflicts.
|
||||
|
||||
IF lines( mt_conflicts ) > 0.
|
||||
rv_conflicts_exists = abap_true.
|
||||
ELSE.
|
||||
rv_conflicts_exists = abap_false.
|
||||
ENDIF.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD resolve_conflict.
|
||||
|
||||
FIELD-SYMBOLS: <ls_conflict> TYPE zif_abapgit_definitions=>ty_merge_conflict,
|
||||
<ls_result> LIKE LINE OF ms_merge-result.
|
||||
|
||||
IF is_conflict-result_sha1 IS NOT INITIAL
|
||||
AND is_conflict-result_data IS NOT INITIAL.
|
||||
READ TABLE mt_conflicts ASSIGNING <ls_conflict> WITH KEY path = is_conflict-path
|
||||
filename = is_conflict-filename.
|
||||
IF sy-subrc EQ 0.
|
||||
READ TABLE ms_merge-result ASSIGNING <ls_result> WITH KEY path = is_conflict-path
|
||||
name = is_conflict-filename.
|
||||
IF sy-subrc EQ 0.
|
||||
<ls_result>-sha1 = is_conflict-result_sha1.
|
||||
|
||||
ms_merge-stage->add( iv_path = <ls_conflict>-path
|
||||
iv_filename = <ls_conflict>-filename
|
||||
iv_data = is_conflict-result_data ).
|
||||
|
||||
DELETE mt_conflicts WHERE path EQ is_conflict-path
|
||||
AND filename EQ is_conflict-filename.
|
||||
ENDIF.
|
||||
|
||||
READ TABLE ms_merge-result ASSIGNING <ls_result> WITH KEY sha1 = space.
|
||||
IF sy-subrc EQ 0.
|
||||
ms_merge-conflict = |{ <ls_result>-name } merge conflict, changed in source and target branch|.
|
||||
ELSE.
|
||||
CLEAR ms_merge-conflict.
|
||||
ENDIF.
|
||||
ENDIF.
|
||||
ENDIF.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD run.
|
||||
|
||||
DATA: lt_asource TYPE ty_ancestor_tt,
|
||||
lt_atarget TYPE ty_ancestor_tt.
|
||||
|
||||
CLEAR: ms_merge, mt_objects, mt_conflicts.
|
||||
|
||||
IF iv_source = iv_target.
|
||||
zcx_abapgit_exception=>raise( 'source = target' ).
|
||||
ENDIF.
|
||||
ms_merge-repo = mo_repo.
|
||||
mt_objects = fetch_git( ).
|
||||
|
||||
CLEAR gs_merge.
|
||||
lt_asource = find_ancestors( ms_merge-source-sha1 ).
|
||||
lt_atarget = find_ancestors( ms_merge-target-sha1 ).
|
||||
|
||||
gs_merge-repo = io_repo.
|
||||
|
||||
fetch_git( iv_source = iv_source
|
||||
iv_target = iv_target ).
|
||||
|
||||
lt_asource = find_ancestors( gs_merge-source-sha1 ).
|
||||
lt_atarget = find_ancestors( gs_merge-target-sha1 ).
|
||||
|
||||
gs_merge-common = find_first_common( it_list1 = lt_asource
|
||||
ms_merge-common = find_first_common( it_list1 = lt_asource
|
||||
it_list2 = lt_atarget ).
|
||||
|
||||
gs_merge-stree = zcl_abapgit_git_porcelain=>full_tree(
|
||||
it_objects = gt_objects
|
||||
iv_branch = gs_merge-source-sha1 ).
|
||||
gs_merge-ttree = zcl_abapgit_git_porcelain=>full_tree(
|
||||
it_objects = gt_objects
|
||||
iv_branch = gs_merge-target-sha1 ).
|
||||
gs_merge-ctree = zcl_abapgit_git_porcelain=>full_tree(
|
||||
it_objects = gt_objects
|
||||
iv_branch = gs_merge-common-commit ).
|
||||
ms_merge-stree = zcl_abapgit_git_porcelain=>full_tree(
|
||||
it_objects = mt_objects
|
||||
iv_branch = ms_merge-source-sha1 ).
|
||||
ms_merge-ttree = zcl_abapgit_git_porcelain=>full_tree(
|
||||
it_objects = mt_objects
|
||||
iv_branch = ms_merge-target-sha1 ).
|
||||
ms_merge-ctree = zcl_abapgit_git_porcelain=>full_tree(
|
||||
it_objects = mt_objects
|
||||
iv_branch = ms_merge-common-commit ).
|
||||
|
||||
calculate_result( ).
|
||||
|
||||
rs_merge = gs_merge.
|
||||
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
|
|
|
@ -14,6 +14,20 @@
|
|||
<FIXPT>X</FIXPT>
|
||||
<UNICODE>X</UNICODE>
|
||||
</VSEOCLASS>
|
||||
<DESCRIPTIONS>
|
||||
<SEOCOMPOTX>
|
||||
<CLSNAME>ZCL_ABAPGIT_MERGE</CLSNAME>
|
||||
<CMPNAME>CONSTRUCTOR</CMPNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>CONSTRUCTOR</DESCRIPT>
|
||||
</SEOCOMPOTX>
|
||||
<SEOCOMPOTX>
|
||||
<CLSNAME>ZCL_ABAPGIT_MERGE</CLSNAME>
|
||||
<CMPNAME>MO_REPO</CMPNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>Online Repository</DESCRIPT>
|
||||
</SEOCOMPOTX>
|
||||
</DESCRIPTIONS>
|
||||
</asx:values>
|
||||
</asx:abap>
|
||||
</abapGit>
|
||||
|
|
|
@ -272,6 +272,18 @@ INTERFACE zif_abapgit_definitions PUBLIC.
|
|||
conflict TYPE string,
|
||||
END OF ty_merge.
|
||||
|
||||
TYPES: BEGIN OF ty_merge_conflict,
|
||||
path TYPE string,
|
||||
filename TYPE string,
|
||||
source_sha1 TYPE zif_abapgit_definitions=>ty_sha1,
|
||||
source_data TYPE xstring,
|
||||
target_sha1 TYPE zif_abapgit_definitions=>ty_sha1,
|
||||
target_data TYPE xstring,
|
||||
result_sha1 TYPE zif_abapgit_definitions=>ty_sha1,
|
||||
result_data TYPE xstring,
|
||||
END OF ty_merge_conflict,
|
||||
tt_merge_conflict TYPE STANDARD TABLE OF ty_merge_conflict WITH DEFAULT KEY.
|
||||
|
||||
TYPES: BEGIN OF ty_repo_item,
|
||||
obj_type TYPE tadir-object,
|
||||
obj_name TYPE tadir-obj_name,
|
||||
|
|
Loading…
Reference in New Issue
Block a user