calculate merged tree #275 (#277)

* merge #275, scaffolding

* refactoring few gui pages
top class element moved to page_super

* syle FORM dropdown

* find common ancestor

* calculate merged tree #275
This commit is contained in:
Lars Hvam 2016-07-06 16:08:00 +02:00 committed by GitHub
parent b286a6c62e
commit af74a24b6d
10 changed files with 1016 additions and 445 deletions

View File

@ -3,7 +3,7 @@ REPORT zabapgit LINE-SIZE 100.
* See http://www.abapgit.org
CONSTANTS: gc_xml_version TYPE string VALUE 'v1.0.0', "#EC NOTEXT
gc_abap_version TYPE string VALUE 'v1.12.11'. "#EC NOTEXT
gc_abap_version TYPE string VALUE 'v1.12.12'. "#EC NOTEXT
********************************************************************************
* The MIT License (MIT)
@ -72,7 +72,9 @@ INCLUDE zabapgit_background.
INCLUDE zabapgit_zip.
INCLUDE zabapgit_transport.
INCLUDE zabapgit_page.
INCLUDE zabapgit_page_merge.
INCLUDE zabapgit_page_branch_overview.
INCLUDE zabapgit_page_commit.
INCLUDE zabapgit_gui.
INCLUDE zabapgit_app_impl.
INCLUDE zabapgit_unit_test.

View File

@ -572,6 +572,8 @@ CLASS lcl_git_transport IMPLEMENTATION.
FIELD-SYMBOLS: <ls_branch> LIKE LINE OF lt_branches.
CLEAR et_objects.
find_branch(
EXPORTING
io_repo = io_repo
@ -1321,6 +1323,15 @@ CLASS lcl_git_porcelain DEFINITION FINAL FRIENDS ltcl_git_porcelain.
PUBLIC SECTION.
TYPES: BEGIN OF ty_expanded,
path TYPE string,
name TYPE string,
sha1 TYPE ty_sha1,
chmod TYPE ty_chmod,
END OF ty_expanded.
TYPES: ty_expanded_tt TYPE STANDARD TABLE OF ty_expanded WITH DEFAULT KEY.
CLASS-METHODS pull
IMPORTING io_repo TYPE REF TO lcl_repo_online
EXPORTING et_files TYPE ty_files_tt
@ -1341,15 +1352,13 @@ CLASS lcl_git_porcelain DEFINITION FINAL FRIENDS ltcl_git_porcelain.
iv_from TYPE ty_sha1
RAISING lcx_exception.
PRIVATE SECTION.
TYPES: BEGIN OF ty_expanded,
path TYPE string,
name TYPE string,
sha1 TYPE ty_sha1,
chmod TYPE ty_chmod,
END OF ty_expanded.
CLASS-METHODS full_tree
IMPORTING it_objects TYPE ty_objects_tt
iv_branch TYPE ty_sha1
RETURNING VALUE(rt_expanded) TYPE ty_expanded_tt
RAISING lcx_exception.
TYPES: ty_expanded_tt TYPE STANDARD TABLE OF ty_expanded WITH DEFAULT KEY.
PRIVATE SECTION.
TYPES: BEGIN OF ty_tree,
path TYPE string,
@ -1390,12 +1399,6 @@ CLASS lcl_git_porcelain DEFINITION FINAL FRIENDS ltcl_git_porcelain.
RETURNING VALUE(rt_expanded) TYPE ty_expanded_tt
RAISING lcx_exception.
CLASS-METHODS full_tree
IMPORTING it_objects TYPE ty_objects_tt
iv_branch TYPE ty_sha1
RETURNING VALUE(rt_expanded) TYPE ty_expanded_tt
RAISING lcx_exception.
CLASS-METHODS receive_pack
IMPORTING is_comment TYPE ty_comment
io_repo TYPE REF TO lcl_repo_online

View File

@ -200,12 +200,14 @@ CLASS lcl_gui IMPLEMENTATION.
TRY.
IF mi_cur_page IS BOUND.
lv_state = mi_cur_page->on_event(
iv_action = action
iv_frame = frame
iv_getdata = getdata
it_postdata = postdata
it_query_table = query_table ).
mi_cur_page->on_event(
EXPORTING
iv_action = action
iv_getdata = getdata
it_postdata = postdata
IMPORTING
ei_page = li_page
ev_state = lv_state ).
ENDIF.
IF lv_state IS INITIAL.
@ -418,11 +420,6 @@ CLASS lcl_gui_page_main DEFINITION FINAL INHERITING FROM lcl_gui_page_super.
METHODS lif_gui_page~render REDEFINITION.
METHODS lif_gui_page~get_assets REDEFINITION.
CLASS-METHODS render_repo_top
IMPORTING io_repo TYPE REF TO lcl_repo
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
RAISING lcx_exception.
PRIVATE SECTION.
TYPES: BEGIN OF ty_repo_item,
@ -850,7 +847,7 @@ CLASS lcl_gui_page_background IMPLEMENTATION.
CASE iv_action.
WHEN 'save'.
save( iv_getdata ).
rv_state = gc_event_state-re_render.
ev_state = gc_event_state-re_render.
ENDCASE.
ENDMETHOD.
@ -975,268 +972,6 @@ CLASS lcl_gui_page_background IMPLEMENTATION.
ENDCLASS.
CLASS lcl_gui_page_commit DEFINITION FINAL INHERITING FROM lcl_gui_page_super.
PUBLIC SECTION.
METHODS constructor
IMPORTING iv_repo_key TYPE lcl_persistence_repo=>ty_repo-key
RAISING lcx_exception.
METHODS lif_gui_page~render REDEFINITION.
PRIVATE SECTION.
DATA: mo_repo TYPE REF TO lcl_repo_online,
mo_stage TYPE REF TO lcl_stage.
METHODS render_menu
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper.
METHODS render_stage
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
RAISING lcx_exception.
METHODS render_form
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
RAISING lcx_exception.
METHODS styles
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper.
METHODS scripts
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper.
ENDCLASS.
CLASS lcl_gui_page_commit IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mo_repo ?= lcl_app=>repo_srv( )->get( iv_repo_key ).
mo_stage = lcl_app=>repo_srv( )->get_stage( iv_repo_key ).
ENDMETHOD.
METHOD render_stage.
DATA: lt_stage TYPE lcl_stage=>ty_stage_tt.
FIELD-SYMBOLS: <ls_stage> LIKE LINE OF lt_stage.
CREATE OBJECT ro_html.
lt_stage = mo_stage->get_all( ).
ro_html->add( '<table class="stage_tab">' ).
ro_html->add( '<tr class="title firstrow">').
ro_html->add( '<td colspan="2">Staged files</td>').
ro_html->add( '</tr>' ).
LOOP AT lt_stage ASSIGNING <ls_stage>.
ro_html->add( '<tr>' ).
ro_html->add( '<td class="method">' ).
ro_html->add( lcl_stage=>method_description( <ls_stage>-method ) ).
ro_html->add( '</td>' ).
ro_html->add( '<td>' ).
ro_html->add( <ls_stage>-file-path && <ls_stage>-file-filename ).
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ENDLOOP.
ro_html->add( '</table>' ).
ENDMETHOD. "render_stage
METHOD render_form.
DATA: lo_user TYPE REF TO lcl_persistence_user,
lv_user TYPE string,
lv_key TYPE string,
lv_email TYPE string.
* see https://git-scm.com/book/ch5-2.html
* commit messages should be max 50 characters
* body should wrap at 72 characters
lo_user = lcl_app=>user( ).
lv_user = lo_user->get_username( ).
lv_email = lo_user->get_email( ).
lv_key = mo_repo->get_key( ).
CREATE OBJECT ro_html.
ro_html->add( '<div class="form_div">' ).
ro_html->add( '<form id="commit_form" method="post" action="sapevent:commit_post">' ).
ro_html->add( |<input name="key" type="hidden" value="{ lv_key }">| ).
ro_html->add( '<table>' ).
ro_html->add( '<tr>' ).
ro_html->add( '<td class="field_name">username</td>' ).
ro_html->add( '<td>' ).
ro_html->add( |<input name="username" type="text" size="50" value="{ lv_user }">| ).
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ro_html->add( '<tr>' ).
ro_html->add( '<td class="field_name">email</td>' ).
ro_html->add( '<td>' ).
ro_html->add( |<input name="email" type="text" size="50" value="{ lv_email }">| ).
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ro_html->add( '<tr>' ).
ro_html->add( '<td class="field_name">comment</td>' ).
ro_html->add( '<td>' ).
ro_html->add(
'<input name="comment" type="text" id="commit_msg" maxlength="50" size="50">' ).
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ro_html->add( '<tr>' ).
ro_html->add( '<td class="field_name">body</td>' ).
ro_html->add( '<td>' ).
ro_html->add( '<textarea name="body" rows="10" cols="50"></textarea>' ).
ro_html->add( '<input type="submit" class="hidden-submit">' ). "Hmmm ... reconsider
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ro_html->add( '</table>' ).
ro_html->add( '</form>' ).
ro_html->add( '</div>' ).
ENDMETHOD. "render_form
METHOD render_menu.
DATA lo_toolbar TYPE REF TO lcl_html_toolbar.
CREATE OBJECT ro_html.
CREATE OBJECT lo_toolbar.
lo_toolbar->add( iv_act = 'submitCommit();'
iv_txt = 'Commit'
iv_typ = gc_action_type-onclick
iv_opt = gc_html_opt-emphas ) ##NO_TEXT.
lo_toolbar->add( iv_act = 'commit_cancel'
iv_txt = 'Cancel'
iv_opt = gc_html_opt-cancel ) ##NO_TEXT.
ro_html->add( '<div class="paddings">' ).
ro_html->add( lo_toolbar->render( ) ).
ro_html->add( '</div>' ).
ENDMETHOD. "render_menu
METHOD lif_gui_page~render.
CREATE OBJECT ro_html.
ro_html->add( header( io_include_style = styles( ) ) ).
ro_html->add( title( 'COMMIT' ) ).
ro_html->add( '<div class="repo">' ).
ro_html->add( lcl_gui_page_main=>render_repo_top( mo_repo ) ).
ro_html->add( render_menu( ) ).
ro_html->add( render_form( ) ).
ro_html->add( render_stage( ) ).
ro_html->add( '</div>' ).
ro_html->add( footer( io_include_script = scripts( ) ) ).
ENDMETHOD. "lif_gui_page~render
METHOD styles.
CREATE OBJECT ro_html.
_add '/* REPOSITORY */'.
_add 'div.repo {'.
_add ' margin-top: 3px;'.
_add ' background-color: #f2f2f2;'.
_add ' padding: 0.5em 1em 0.5em 1em;'.
_add '}'.
_add '.repo_name span {'.
_add ' color: #333;'.
_add ' font-weight: bold;'.
_add ' font-size: 14pt;'.
_add '}'.
_add '.repo_name img {'.
_add ' vertical-align: baseline;'.
_add ' margin: 0 5px 0 5px;'.
_add '}'.
_add '.repo_attr {'.
_add ' color: grey;'.
_add ' font-size: 12pt;'.
_add '}'.
_add '.repo_attr span {'.
_add ' margin-left: 0.2em;'.
_add ' margin-right: 0.5em;'.
_add '}'.
_add '.repo_attr input {'.
_add ' color: grey;'. " Input wants it personaly
_add ' font-size: 12pt;'. " Input wants it personaly
_add ' margin-left: 0.5em;'.
_add ' margin-right: 0.5em;'.
_add ' background-color: transparent;'.
_add ' border-style: none;'.
_add ' text-overflow: ellipsis;'.
_add '}'.
_add '/* STAGE */'.
_add '.stage_tab {'.
_add ' border: 1px solid #DDD;'.
_add ' background: #fff;'.
_add ' margin-top: 0.2em;'.
_add '}'.
_add '.stage_tab td {'.
_add ' border-top: 1px solid #eee;'.
_add ' color: #333;'.
_add ' vertical-align: middle;'.
_add ' padding: 2px 0.5em;'.
_add '}'.
_add '.stage_tab td.method {'.
_add ' color: #ccc;'.
_add '}'.
_add '.stage_tab tr.firstrow td { border-top: 0px; } ' .
_add '.stage_tab tr.title td {'.
_add ' color: #BBB;'.
_add ' font-size: 10pt;'.
_add ' background-color: #edf2f9;'.
_add ' padding: 4px 0.5em;'.
_add ' text-align: center;'.
_add '}'.
_add '/* COMMIT */'.
_add 'div.form_div {'.
_add ' margin: 0.5em 0em;'.
_add ' background-color: #F8F8F8;'.
_add ' padding: 1em 1em;'.
_add '}'.
_add 'div.form_div td.field_name {'.
_add ' color: #BBB;'.
_add ' padding-right: 1em;'.
_add '}'.
ENDMETHOD. "styles
METHOD scripts.
CREATE OBJECT ro_html.
_add 'function setInitialFocus() {'.
_add ' document.getElementById("commit_msg").focus();'.
_add '}'.
_add 'function submitCommit() {'.
_add ' document.getElementById("commit_form").submit();'.
_add '}'.
_add 'setInitialFocus();'.
ENDMETHOD. "scripts
ENDCLASS. "lcl_gui_page_commit
CLASS lcl_gui_page_stage DEFINITION FINAL INHERITING FROM lcl_gui_page_super.
PUBLIC SECTION.
@ -1244,7 +979,7 @@ CLASS lcl_gui_page_stage DEFINITION FINAL INHERITING FROM lcl_gui_page_super.
IMPORTING io_repo TYPE REF TO lcl_repo_online
RAISING lcx_exception.
METHODS lif_gui_page~render REDEFINITION.
METHODS lif_gui_page~render REDEFINITION.
PRIVATE SECTION.
DATA: mo_repo TYPE REF TO lcl_repo_online,
@ -1348,7 +1083,7 @@ CLASS lcl_gui_page_stage IMPLEMENTATION.
ro_html->add( title( 'STAGE' ) ).
ro_html->add( '<div class="repo">' ).
ro_html->add( lcl_gui_page_main=>render_repo_top( mo_repo ) ).
ro_html->add( render_repo_top( mo_repo ) ).
ro_html->add( render_menu( ) ).
ro_html->add( '<table class="stage_tab">' ).
@ -1389,39 +1124,6 @@ CLASS lcl_gui_page_stage IMPLEMENTATION.
CREATE OBJECT ro_html.
_add '/* REPOSITORY */'.
_add 'div.repo {'.
_add ' margin-top: 3px;'.
_add ' background-color: #f2f2f2;'.
_add ' padding: 0.5em 1em 0.5em 1em;'.
_add '}'.
_add '.repo_name span {'.
_add ' color: #333;'.
_add ' font-weight: bold;'.
_add ' font-size: 14pt;'.
_add '}'.
_add '.repo_name img {'.
_add ' vertical-align: baseline;'.
_add ' margin: 0 5px 0 5px;'.
_add '}'.
_add '.repo_attr {'.
_add ' color: grey;'.
_add ' font-size: 12pt;'.
_add '}'.
_add '.repo_attr span {'.
_add ' margin-left: 0.2em;'.
_add ' margin-right: 0.5em;'.
_add '}'.
_add '.repo_attr input {'.
_add ' color: grey;'. " Input wants it personaly
_add ' font-size: 12pt;'. " Input wants it personaly
_add ' margin-left: 0.5em;'.
_add ' margin-right: 0.5em;'.
_add ' background-color: transparent;'.
_add ' border-style: none;'.
_add ' text-overflow: ellipsis;'.
_add '}'.
_add '/* STAGE */'.
_add '.stage_tab {'.
_add ' border: 1px solid #DDD;'.
@ -1502,40 +1204,8 @@ CLASS lcl_gui_page_main IMPLEMENTATION.
ENDMETHOD. "build main_menu
METHOD styles.
CREATE OBJECT ro_html.
_add '/* REPOSITORY */'.
_add 'div.repo {'.
_add ' margin-top: 3px;'.
_add ' background-color: #f2f2f2;'.
_add ' padding: 0.5em 1em 0.5em 1em;'.
_add '}'.
_add '.repo_name span {'.
_add ' font-weight: bold;'.
_add ' color: #333;'.
_add ' font-size: 14pt;'.
_add '}'.
_add '.repo_name img {'.
_add ' vertical-align: baseline;'.
_add ' margin: 0 5px 0 5px;'.
_add '}'.
_add '.repo_attr {'.
_add ' color: grey;'.
_add ' font-size: 12pt;'.
_add '}'.
_add '.repo_attr span {'.
_add ' margin-left: 0.2em;'.
_add ' margin-right: 0.5em;'.
_add '}'.
_add '.repo_attr input {'.
_add ' color: grey;'. " Input wants it personaly
_add ' font-size: 12pt;'. " Input wants it personaly
_add ' margin-left: 0.5em;'.
_add ' margin-right: 0.5em;'.
_add ' background-color: transparent;'.
_add ' border-style: none;'.
_add ' text-overflow: ellipsis;'.
_add '}'.
CREATE OBJECT ro_html.
_add '/* REPOSITORY TABLE*/'.
_add '.repo_tab {'.
@ -1665,45 +1335,6 @@ CLASS lcl_gui_page_main IMPLEMENTATION.
ENDMETHOD.
METHOD render_repo_top.
DATA: lo_repo_online TYPE REF TO lcl_repo_online,
lv_icon TYPE string.
CREATE OBJECT ro_html.
IF io_repo->is_offline( ) = abap_true.
lv_icon = 'img/repo_offline' ##NO_TEXT.
ELSE.
lv_icon = 'img/repo_online' ##NO_TEXT.
ENDIF.
ro_html->add( |<a id="repo{ io_repo->get_key( ) }"></a>| ).
ro_html->add( '<table width="100%"><tr>' ).
ro_html->add( '<td class="repo_name">' ).
ro_html->add( |<img src="{ lv_icon }">| ).
ro_html->add( |<span>{ io_repo->get_name( ) }</span>| ).
ro_html->add( '</td>' ).
ro_html->add( '<td class="repo_attr right">' ).
ro_html->add( '<img src="img/pkg">' ).
ro_html->add( |<span>{ io_repo->get_package( ) }</span>| ).
IF io_repo->is_offline( ) = abap_false.
lo_repo_online ?= io_repo.
ro_html->add( '<img src="img/branch">' ).
ro_html->add( |<span>{ lo_repo_online->get_branch_name( ) }</span>| ).
ro_html->add( '<img src="img/link">' ).
ro_html->add( |<input type="text" value="{ lo_repo_online->get_url( ) }" readonly>| ).
ENDIF.
ro_html->add( '</td>' ).
ro_html->add( '</tr></table>' ).
ENDMETHOD.
METHOD render_repo.
DATA: lt_repo_items TYPE tt_repo_items,
lx_error TYPE REF TO lcx_exception,

View File

@ -278,15 +278,14 @@ CLASS lcl_object_webi IMPLEMENTATION.
li_field->set_type( mi_vi->get_type( typename = <ls_struc>-typeref
version = sews_c_vif_version-inactive ) ).
IF lv_index = 1.
IF li_struc->if_ws_md_vif_type~has_soap_extension_type(
sews_c_vif_version-all ) = abap_false.
READ TABLE is_webi-pveptypesoapext ASSIGNING <ls_soap>
WITH KEY typename = <ls_struc>-typename.
IF sy-subrc = 0.
li_soap = li_struc->if_ws_md_vif_type~create_soap_extension_type( ).
li_soap->set_namespace( <ls_soap>-namespace ).
ENDIF.
IF lv_index = 1
AND li_struc->if_ws_md_vif_type~has_soap_extension_type(
sews_c_vif_version-all ) = abap_false.
READ TABLE is_webi-pveptypesoapext ASSIGNING <ls_soap>
WITH KEY typename = <ls_struc>-typename.
IF sy-subrc = 0.
li_soap = li_struc->if_ws_md_vif_type~create_soap_extension_type( ).
li_soap->set_namespace( <ls_soap>-namespace ).
ENDIF.
ENDIF.
ENDLOOP.

View File

@ -8,12 +8,11 @@
INTERFACE lif_gui_page.
METHODS on_event
IMPORTING iv_action TYPE clike
iv_frame TYPE clike
iv_getdata TYPE clike
it_postdata TYPE cnht_post_data_tab
it_query_table TYPE cnht_query_table
RETURNING VALUE(rv_state) TYPE i
IMPORTING iv_action TYPE clike
iv_getdata TYPE clike OPTIONAL
it_postdata TYPE cnht_post_data_tab OPTIONAL
EXPORTING ei_page TYPE REF TO lif_gui_page
ev_state TYPE i
RAISING lcx_exception.
METHODS render
@ -30,6 +29,11 @@ CLASS lcl_gui_page_super DEFINITION ABSTRACT.
INTERFACES lif_gui_page ABSTRACT METHODS render.
PROTECTED SECTION.
METHODS render_repo_top
IMPORTING io_repo TYPE REF TO lcl_repo
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
RAISING lcx_exception.
METHODS header
IMPORTING io_include_style TYPE REF TO lcl_html_helper OPTIONAL
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper.
@ -54,6 +58,45 @@ ENDCLASS.
CLASS lcl_gui_page_super IMPLEMENTATION.
METHOD render_repo_top.
DATA: lo_repo_online TYPE REF TO lcl_repo_online,
lv_icon TYPE string.
CREATE OBJECT ro_html.
IF io_repo->is_offline( ) = abap_true.
lv_icon = 'img/repo_offline' ##NO_TEXT.
ELSE.
lv_icon = 'img/repo_online' ##NO_TEXT.
ENDIF.
ro_html->add( |<a id="repo{ io_repo->get_key( ) }"></a>| ).
ro_html->add( '<table width="100%"><tr>' ).
ro_html->add( '<td class="repo_name">' ).
ro_html->add( |<img src="{ lv_icon }">| ).
ro_html->add( |<span>{ io_repo->get_name( ) }</span>| ).
ro_html->add( '</td>' ).
ro_html->add( '<td class="repo_attr right">' ).
ro_html->add( '<img src="img/pkg">' ).
ro_html->add( |<span>{ io_repo->get_package( ) }</span>| ).
IF io_repo->is_offline( ) = abap_false.
lo_repo_online ?= io_repo.
ro_html->add( '<img src="img/branch">' ).
ro_html->add( |<span>{ lo_repo_online->get_branch_name( ) }</span>| ).
ro_html->add( '<img src="img/link">' ).
ro_html->add( |<input type="text" value="{ lo_repo_online->get_url( ) }" readonly>| ).
ENDIF.
ro_html->add( '</td>' ).
ro_html->add( '</tr></table>' ).
ENDMETHOD.
METHOD header.
CREATE OBJECT ro_html.
@ -160,7 +203,7 @@ CLASS lcl_gui_page_super IMPLEMENTATION.
_add 'table { border-collapse: collapse; }'.
_add 'pre { display: inline; }'.
_add 'form input, textarea {'.
_add 'form input, textarea, select {'.
_add ' border: 1px solid #DDD;'.
_add ' padding: 3px 6px;'.
_add '}'.
@ -252,6 +295,39 @@ CLASS lcl_gui_page_super IMPLEMENTATION.
_add '.dropdown:hover .dropdown_content { display: block; }'.
_add '.dropdown:hover .dropbtn { color: #79a0d2; }'.
_add '/* REPOSITORY */'.
_add 'div.repo {'.
_add ' margin-top: 3px;'.
_add ' background-color: #f2f2f2;'.
_add ' padding: 0.5em 1em 0.5em 1em;'.
_add '}'.
_add '.repo_name span {'.
_add ' font-weight: bold;'.
_add ' color: #333;'.
_add ' font-size: 14pt;'.
_add '}'.
_add '.repo_name img {'.
_add ' vertical-align: baseline;'.
_add ' margin: 0 5px 0 5px;'.
_add '}'.
_add '.repo_attr {'.
_add ' color: grey;'.
_add ' font-size: 12pt;'.
_add '}'.
_add '.repo_attr span {'.
_add ' margin-left: 0.2em;'.
_add ' margin-right: 0.5em;'.
_add '}'.
_add '.repo_attr input {'.
_add ' color: grey;'. " Input wants it personaly
_add ' font-size: 12pt;'. " Input wants it personaly
_add ' margin-left: 0.5em;'.
_add ' margin-right: 0.5em;'.
_add ' background-color: transparent;'.
_add ' border-style: none;'.
_add ' text-overflow: ellipsis;'.
_add '}'.
" Other and outdated (?) styles
_add '/* MISC AND REFACTOR */'.
_add 'a.grey:link {color: grey; font-size: smaller;}'.
@ -372,7 +448,7 @@ CLASS lcl_gui_page_super IMPLEMENTATION.
ENDMETHOD. "lif_gui_page~get_assets
METHOD lif_gui_page~on_event.
rv_state = gc_event_state-not_handled.
ev_state = gc_event_state-not_handled.
ENDMETHOD. "lif_gui_page~on_event
ENDCLASS.

View File

@ -36,6 +36,9 @@ CLASS lcl_branch_overview DEFINITION FINAL.
RETURNING VALUE(rt_commits) TYPE ty_commit_tt
RAISING lcx_exception.
CLASS-METHODS: get_branches
RETURNING VALUE(rt_branches) TYPE lcl_git_transport=>ty_branch_list_tt.
PRIVATE SECTION.
CLASS-METHODS:
@ -61,18 +64,12 @@ ENDCLASS.
CLASS lcl_branch_overview IMPLEMENTATION.
METHOD get_branches.
rt_branches = gt_branches.
ENDMETHOD.
METHOD compress.
DATA: lv_previous TYPE i,
lv_index TYPE i,
lv_name TYPE string,
lt_temp LIKE it_commits.
FIELD-SYMBOLS: <ls_branch> LIKE LINE OF gt_branches,
<ls_new> LIKE LINE OF rt_commits,
<ls_temp> LIKE LINE OF lt_temp,
<ls_commit> LIKE LINE OF it_commits.
DEFINE _compress.
IF lines( lt_temp ) >= 10.
READ TABLE lt_temp ASSIGNING <ls_temp> INDEX 1.
@ -87,6 +84,16 @@ CLASS lcl_branch_overview IMPLEMENTATION.
ENDIF.
END-OF-DEFINITION.
DATA: lv_previous TYPE i,
lv_index TYPE i,
lv_name TYPE string,
lt_temp LIKE it_commits.
FIELD-SYMBOLS: <ls_branch> LIKE LINE OF gt_branches,
<ls_new> LIKE LINE OF rt_commits,
<ls_temp> LIKE LINE OF lt_temp,
<ls_commit> LIKE LINE OF it_commits.
LOOP AT gt_branches ASSIGNING <ls_branch>.
@ -303,24 +310,44 @@ CLASS lcl_gui_page_branch_overview DEFINITION FINAL INHERITING FROM lcl_gui_page
PUBLIC SECTION.
METHODS:
constructor
IMPORTING io_repo TYPE REF TO lcl_repo_online,
IMPORTING io_repo TYPE REF TO lcl_repo_online
RAISING lcx_exception,
lif_gui_page~on_event REDEFINITION,
lif_gui_page~render REDEFINITION.
PRIVATE SECTION.
DATA: mo_repo TYPE REF TO lcl_repo_online,
mv_compress TYPE abap_bool VALUE abap_false.
mv_compress TYPE abap_bool VALUE abap_false,
mt_commits TYPE lcl_branch_overview=>ty_commit_tt.
CONSTANTS: BEGIN OF c_actions,
uncompress TYPE string VALUE 'uncompress' ##NO_TEXT,
compress TYPE string VALUE 'compress' ##NO_TEXT,
refresh TYPE string VALUE 'refresh' ##NO_TEXT,
merge TYPE string VALUE 'merge' ##NO_TEXT,
END OF c_actions.
TYPES: BEGIN OF ty_merge,
source TYPE string,
target TYPE string,
END OF ty_merge.
METHODS:
refresh
RAISING lcx_exception,
body
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
RAISING lcx_exception,
form_select
IMPORTING iv_name TYPE string
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper,
render_merge
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
RAISING lcx_exception,
decode_merge
IMPORTING it_postdata TYPE cnht_post_data_tab
RETURNING VALUE(rs_merge) TYPE ty_merge
RAISING lcx_exception,
build_menu
RETURNING VALUE(ro_menu) TYPE REF TO lcl_html_toolbar,
escape_branch
@ -340,6 +367,16 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mo_repo = io_repo.
refresh( ).
ENDMETHOD.
METHOD refresh.
mt_commits = lcl_branch_overview=>run( mo_repo ).
IF mv_compress = abap_true.
mt_commits = lcl_branch_overview=>compress( mt_commits ).
ENDIF.
ENDMETHOD.
METHOD get_script.
@ -373,17 +410,54 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
ENDMETHOD.
METHOD form_select.
DATA: lv_name TYPE string,
lt_branches TYPE lcl_git_transport=>ty_branch_list_tt.
FIELD-SYMBOLS: <ls_branch> LIKE LINE OF lt_branches.
CREATE OBJECT ro_html.
lt_branches = lcl_branch_overview=>get_branches( ).
ro_html->add( |<select name="{ iv_name }">| ).
LOOP AT lt_branches ASSIGNING <ls_branch>.
lv_name = <ls_branch>-name+11.
ro_html->add( |<option value="{ lv_name }">{ lv_name }</option>| ).
ENDLOOP.
ro_html->add( '</select>' ).
ENDMETHOD.
METHOD render_merge.
CREATE OBJECT ro_html.
ro_html->add( '<form id="commit_form" method="post" action="sapevent:merge">' ).
ro_html->add( 'Merge' ).
ro_html->add( form_select( 'source' ) ).
ro_html->add( 'into' ).
ro_html->add( form_select( 'target' ) ).
ro_html->add( '<input type="submit" value="Submit">' ).
ro_html->add( '</form>' ).
ENDMETHOD.
METHOD body.
DATA: lt_commits TYPE lcl_branch_overview=>ty_commit_tt.
FIELD-SYMBOLS: <ls_commit> LIKE LINE OF lt_commits,
FIELD-SYMBOLS: <ls_commit> LIKE LINE OF mt_commits,
<ls_create> LIKE LINE OF <ls_commit>-create.
CREATE OBJECT ro_html.
ro_html->add( |Repository: { mo_repo->get_url( ) }<br>| ).
ro_html->add( render_repo_top( mo_repo ) ).
ro_html->add( '<br>' ).
ro_html->add( '<br>' ).
ro_html->add( render_merge( ) ).
* see http://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-element
_add '<canvas id="gitGraph"></canvas>'.
@ -396,10 +470,7 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
* when above issue is fixed
ro_html->add( get_script( ) ).
_add '</script>'.
_add '<script type="text/javascript">'.
_add 'var myTemplateConfig = {'.
ro_html->add( 'colors: [ "#979797", "#008fb5", "#f1c109", "'
&& '#095256", "#087F8C", "#5AAA95", "#86A873", "#BB9F06" ],' ) ##NO_TEXT.
@ -418,15 +489,9 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
_add ' orientation: "vertical-reverse"'.
_add '});'.
lt_commits = lcl_branch_overview=>run( mo_repo ).
IF mv_compress = abap_true.
lt_commits = lcl_branch_overview=>compress( lt_commits ).
ENDIF.
* todo: limit number of commits shown, or squash commits?
LOOP AT lt_commits ASSIGNING <ls_commit>.
LOOP AT mt_commits ASSIGNING <ls_commit>.
IF sy-tabix = 1.
* assumption: all branches are created from master
* assumption: all branches are created from master, todo
ro_html->add( |var {
escape_branch( <ls_commit>-branch ) } = gitgraph.branch("{
<ls_commit>-branch }");| ).
@ -497,17 +562,56 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
ENDMETHOD.
METHOD decode_merge.
DATA: lv_string TYPE string,
ls_content TYPE lcl_persistence_db=>ty_content,
lt_fields TYPE tihttpnvp.
FIELD-SYMBOLS: <ls_field> LIKE LINE OF lt_fields.
CONCATENATE LINES OF it_postdata INTO lv_string.
lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ).
READ TABLE lt_fields ASSIGNING <ls_field> WITH KEY name = 'source' ##NO_TEXT.
ASSERT sy-subrc = 0.
rs_merge-source = <ls_field>-value.
READ TABLE lt_fields ASSIGNING <ls_field> WITH KEY name = 'target' ##NO_TEXT.
ASSERT sy-subrc = 0.
rs_merge-target = <ls_field>-value.
ENDMETHOD.
METHOD lif_gui_page~on_event.
DATA: ls_merge TYPE ty_merge,
lo_merge TYPE REF TO lcl_gui_page_merge.
CASE iv_action.
WHEN c_actions-refresh.
rv_state = gc_event_state-re_render.
refresh( ).
ev_state = gc_event_state-re_render.
WHEN c_actions-uncompress.
mv_compress = abap_false.
rv_state = gc_event_state-re_render.
refresh( ).
ev_state = gc_event_state-re_render.
WHEN c_actions-compress.
mv_compress = abap_true.
rv_state = gc_event_state-re_render.
refresh( ).
ev_state = gc_event_state-re_render.
WHEN c_actions-merge.
ls_merge = decode_merge( it_postdata ).
CREATE OBJECT lo_merge
EXPORTING
io_repo = mo_repo
iv_source = ls_merge-source
iv_target = ls_merge-target.
ei_page = lo_merge.
ev_state = gc_event_state-new_page.
ENDCASE.
ENDMETHOD.
@ -518,9 +622,9 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
ro_html->add( header( ) ).
ro_html->add( title( iv_title = 'BRANCH_OVERVIEW' io_menu = build_menu( ) ) ).
_add '<div id="toc">'.
ro_html->add( '<div id="toc">' ).
ro_html->add( body( ) ).
_add '</div>'.
ro_html->add( '</div>' ).
ro_html->add( footer( ) ).
ENDMETHOD.

View File

@ -0,0 +1,234 @@
*&---------------------------------------------------------------------*
*& Include ZABAPGIT_PAGE_COMMIT
*&---------------------------------------------------------------------*
CLASS lcl_gui_page_commit DEFINITION FINAL INHERITING FROM lcl_gui_page_super.
PUBLIC SECTION.
METHODS constructor
IMPORTING iv_repo_key TYPE lcl_persistence_repo=>ty_repo-key
RAISING lcx_exception.
METHODS lif_gui_page~render REDEFINITION.
PRIVATE SECTION.
DATA: mo_repo TYPE REF TO lcl_repo_online,
mo_stage TYPE REF TO lcl_stage.
METHODS render_menu
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper.
METHODS render_stage
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
RAISING lcx_exception.
METHODS render_form
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
RAISING lcx_exception.
METHODS styles
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper.
METHODS scripts
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper.
ENDCLASS.
CLASS lcl_gui_page_commit IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mo_repo ?= lcl_app=>repo_srv( )->get( iv_repo_key ).
mo_stage = lcl_app=>repo_srv( )->get_stage( iv_repo_key ).
ENDMETHOD.
METHOD render_stage.
DATA: lt_stage TYPE lcl_stage=>ty_stage_tt.
FIELD-SYMBOLS: <ls_stage> LIKE LINE OF lt_stage.
CREATE OBJECT ro_html.
lt_stage = mo_stage->get_all( ).
ro_html->add( '<table class="stage_tab">' ).
ro_html->add( '<tr class="title firstrow">').
ro_html->add( '<td colspan="2">Staged files</td>').
ro_html->add( '</tr>' ).
LOOP AT lt_stage ASSIGNING <ls_stage>.
ro_html->add( '<tr>' ).
ro_html->add( '<td class="method">' ).
ro_html->add( lcl_stage=>method_description( <ls_stage>-method ) ).
ro_html->add( '</td>' ).
ro_html->add( '<td>' ).
ro_html->add( <ls_stage>-file-path && <ls_stage>-file-filename ).
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ENDLOOP.
ro_html->add( '</table>' ).
ENDMETHOD. "render_stage
METHOD render_form.
DATA: lo_user TYPE REF TO lcl_persistence_user,
lv_user TYPE string,
lv_key TYPE string,
lv_email TYPE string.
* see https://git-scm.com/book/ch5-2.html
* commit messages should be max 50 characters
* body should wrap at 72 characters
lo_user = lcl_app=>user( ).
lv_user = lo_user->get_username( ).
lv_email = lo_user->get_email( ).
lv_key = mo_repo->get_key( ).
CREATE OBJECT ro_html.
ro_html->add( '<div class="form_div">' ).
ro_html->add( '<form id="commit_form" method="post" action="sapevent:commit_post">' ).
ro_html->add( |<input name="key" type="hidden" value="{ lv_key }">| ).
ro_html->add( '<table>' ).
ro_html->add( '<tr>' ).
ro_html->add( '<td class="field_name">username</td>' ).
ro_html->add( '<td>' ).
ro_html->add( |<input name="username" type="text" size="50" value="{ lv_user }">| ).
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ro_html->add( '<tr>' ).
ro_html->add( '<td class="field_name">email</td>' ).
ro_html->add( '<td>' ).
ro_html->add( |<input name="email" type="text" size="50" value="{ lv_email }">| ).
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ro_html->add( '<tr>' ).
ro_html->add( '<td class="field_name">comment</td>' ).
ro_html->add( '<td>' ).
ro_html->add(
'<input name="comment" type="text" id="commit_msg" maxlength="50" size="50">' ).
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ro_html->add( '<tr>' ).
ro_html->add( '<td class="field_name">body</td>' ).
ro_html->add( '<td>' ).
ro_html->add( '<textarea name="body" rows="10" cols="50"></textarea>' ).
ro_html->add( '<input type="submit" class="hidden-submit">' ). "Hmmm ... reconsider
ro_html->add( '</td>' ).
ro_html->add( '</tr>' ).
ro_html->add( '</table>' ).
ro_html->add( '</form>' ).
ro_html->add( '</div>' ).
ENDMETHOD. "render_form
METHOD render_menu.
DATA lo_toolbar TYPE REF TO lcl_html_toolbar.
CREATE OBJECT ro_html.
CREATE OBJECT lo_toolbar.
lo_toolbar->add( iv_act = 'submitCommit();'
iv_txt = 'Commit'
iv_typ = gc_action_type-onclick
iv_opt = gc_html_opt-emphas ) ##NO_TEXT.
lo_toolbar->add( iv_act = 'commit_cancel'
iv_txt = 'Cancel'
iv_opt = gc_html_opt-cancel ) ##NO_TEXT.
ro_html->add( '<div class="paddings">' ).
ro_html->add( lo_toolbar->render( ) ).
ro_html->add( '</div>' ).
ENDMETHOD. "render_menu
METHOD lif_gui_page~render.
CREATE OBJECT ro_html.
ro_html->add( header( io_include_style = styles( ) ) ).
ro_html->add( title( 'COMMIT' ) ).
ro_html->add( '<div class="repo">' ).
ro_html->add( render_repo_top( mo_repo ) ).
ro_html->add( render_menu( ) ).
ro_html->add( render_form( ) ).
ro_html->add( render_stage( ) ).
ro_html->add( '</div>' ).
ro_html->add( footer( io_include_script = scripts( ) ) ).
ENDMETHOD. "lif_gui_page~render
METHOD styles.
CREATE OBJECT ro_html.
_add '/* STAGE */'.
_add '.stage_tab {'.
_add ' border: 1px solid #DDD;'.
_add ' background: #fff;'.
_add ' margin-top: 0.2em;'.
_add '}'.
_add '.stage_tab td {'.
_add ' border-top: 1px solid #eee;'.
_add ' color: #333;'.
_add ' vertical-align: middle;'.
_add ' padding: 2px 0.5em;'.
_add '}'.
_add '.stage_tab td.method {'.
_add ' color: #ccc;'.
_add '}'.
_add '.stage_tab tr.firstrow td { border-top: 0px; } '.
_add '.stage_tab tr.title td {'.
_add ' color: #BBB;'.
_add ' font-size: 10pt;'.
_add ' background-color: #edf2f9;'.
_add ' padding: 4px 0.5em;'.
_add ' text-align: center;'.
_add '}'.
_add '/* COMMIT */'.
_add 'div.form_div {'.
_add ' margin: 0.5em 0em;'.
_add ' background-color: #F8F8F8;'.
_add ' padding: 1em 1em;'.
_add '}'.
_add 'div.form_div td.field_name {'.
_add ' color: #BBB;'.
_add ' padding-right: 1em;'.
_add '}'.
ENDMETHOD. "styles
METHOD scripts.
CREATE OBJECT ro_html.
_add 'function setInitialFocus() {'.
_add ' document.getElementById("commit_msg").focus();'.
_add '}'.
_add 'function submitCommit() {'.
_add ' document.getElementById("commit_form").submit();'.
_add '}'.
_add 'setInitialFocus();'.
ENDMETHOD. "scripts
ENDCLASS. "lcl_gui_page_commit

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_PROG" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<PROGDIR>
<NAME>ZABAPGIT_PAGE_COMMIT</NAME>
<STATE>A</STATE>
<SQLX/>
<EDTX/>
<VARCL>X</VARCL>
<DBAPL/>
<DBNA/>
<CLAS/>
<TYPE/>
<OCCURS/>
<SUBC>I</SUBC>
<APPL/>
<SECU/>
<CNAM/>
<CDAT>0000-00-00</CDAT>
<UNAM/>
<UDAT>0000-00-00</UDAT>
<VERN/>
<LEVL/>
<RSTAT/>
<RMAND/>
<RLOAD>E</RLOAD>
<FIXPT/>
<SSET/>
<SDATE>0000-00-00</SDATE>
<STIME/>
<IDATE>0000-00-00</IDATE>
<ITIME/>
<LDBNAME/>
<UCCHECK>X</UCCHECK>
</PROGDIR>
<TPOOL>
<item>
<ID>R</ID>
<KEY/>
<ENTRY>Include ZABAPGIT_PAGE_COMMIT</ENTRY>
<LENGTH>28</LENGTH>
<SPLIT/>
</item>
</TPOOL>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,426 @@
*&---------------------------------------------------------------------*
*& Include ZABAPGIT_PAGE_MERGE
*&---------------------------------------------------------------------*
CLASS lcl_merge DEFINITION FINAL.
PUBLIC SECTION.
TYPES: BEGIN OF ty_ancestor,
commit TYPE ty_sha1,
tree TYPE ty_sha1,
time TYPE string,
body TYPE string,
END OF ty_ancestor.
TYPES: BEGIN OF ty_merge,
repo TYPE REF TO lcl_repo_online,
source TYPE lcl_git_transport=>ty_branch_list,
target TYPE lcl_git_transport=>ty_branch_list,
common TYPE ty_ancestor,
stree TYPE lcl_git_porcelain=>ty_expanded_tt,
ttree TYPE lcl_git_porcelain=>ty_expanded_tt,
ctree TYPE lcl_git_porcelain=>ty_expanded_tt,
result TYPE lcl_git_porcelain=>ty_expanded_tt,
END OF ty_merge.
CLASS-METHODS:
run
IMPORTING io_repo TYPE REF TO lcl_repo_online
iv_source TYPE string
iv_target TYPE string
RETURNING VALUE(rs_merge) TYPE ty_merge
RAISING lcx_exception.
PRIVATE SECTION.
CLASS-DATA: gs_merge TYPE ty_merge,
gt_objects TYPE ty_objects_tt.
TYPES: ty_ancestor_tt TYPE STANDARD TABLE OF ty_ancestor WITH DEFAULT KEY.
CLASS-METHODS:
all_files
RETURNING VALUE(rt_files) TYPE lcl_git_porcelain=>ty_expanded_tt,
calculate_result
RAISING lcx_exception,
find_ancestors
IMPORTING iv_commit TYPE ty_sha1
RETURNING VALUE(rt_ancestors) TYPE ty_ancestor_tt
RAISING lcx_exception,
find_first_common
IMPORTING it_list1 TYPE ty_ancestor_tt
it_list2 TYPE ty_ancestor_tt
RETURNING VALUE(rs_common) TYPE ty_ancestor
RAISING lcx_exception,
fetch_git
IMPORTING iv_source TYPE string
iv_target TYPE string
RAISING lcx_exception.
ENDCLASS.
CLASS lcl_merge IMPLEMENTATION.
METHOD run.
DATA: lt_asource TYPE ty_ancestor_tt,
lt_atarget TYPE ty_ancestor_tt.
ASSERT NOT iv_source = iv_target.
CLEAR gs_merge.
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
it_list2 = lt_atarget ).
gs_merge-stree = lcl_git_porcelain=>full_tree(
it_objects = gt_objects
iv_branch = gs_merge-source-sha1 ).
gs_merge-ttree = lcl_git_porcelain=>full_tree(
it_objects = gt_objects
iv_branch = gs_merge-target-sha1 ).
gs_merge-ctree = lcl_git_porcelain=>full_tree(
it_objects = gt_objects
iv_branch = gs_merge-common-commit ).
BREAK-POINT.
calculate_result( ).
rs_merge = gs_merge.
ENDMETHOD.
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.
SORT rt_files BY path DESCENDING name ASCENDING.
DELETE ADJACENT DUPLICATES FROM rt_files COMPARING path name.
ENDMETHOD.
METHOD calculate_result.
DATA: lt_files TYPE lcl_git_porcelain=>ty_expanded_tt,
lv_found_source TYPE abap_bool,
lv_found_target TYPE abap_bool,
lv_found_common TYPE abap_bool.
FIELD-SYMBOLS: <ls_source> LIKE LINE OF lt_files,
<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.
lt_files = all_files( ).
LOOP AT lt_files ASSIGNING <ls_file>.
UNASSIGN <ls_source>.
UNASSIGN <ls_target>.
UNASSIGN <ls_common>.
READ TABLE gs_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>
WITH KEY path = <ls_file>-path name = <ls_file>-name. "#EC CI_SUBRC
READ TABLE gs_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 ).
lv_found_target = boolc( <ls_target> IS ASSIGNED ).
lv_found_common = boolc( <ls_common> IS ASSIGNED ).
IF lv_found_source = abap_false
AND lv_found_target = abap_false.
* deleted in source and target, skip
CONTINUE.
ELSEIF lv_found_source = abap_false
AND lv_found_common = abap_true
AND <ls_target>-sha1 = <ls_common>-sha1.
* deleted in source, skip
CONTINUE.
ELSEIF lv_found_target = abap_false
AND lv_found_common = abap_true
AND <ls_source>-sha1 = <ls_common>-sha1.
* deleted in target, skip
CONTINUE.
ENDIF.
APPEND INITIAL LINE TO gs_merge-result ASSIGNING <ls_result>.
<ls_result>-path = <ls_file>-path.
<ls_result>-name = <ls_file>-name.
IF lv_found_target = abap_false.
* added in source
<ls_result>-sha1 = <ls_source>-sha1.
ELSEIF lv_found_source = abap_false.
* added in target
<ls_result>-sha1 = <ls_target>-sha1.
ELSEIF lv_found_common = abap_false
AND <ls_target>-sha1 = <ls_source>-sha1.
* added in source and target
<ls_result>-sha1 = <ls_source>-sha1.
ENDIF.
IF lv_found_source = abap_false
OR lv_found_target = abap_false
OR lv_found_common = abap_false.
_raise 'merge conflict'.
ENDIF.
IF <ls_target>-sha1 = <ls_source>-sha1.
* target and source match
<ls_result>-sha1 = <ls_source>-sha1.
ELSEIF <ls_target>-sha1 = <ls_common>-sha1.
* changed in source
<ls_result>-sha1 = <ls_source>-sha1.
ELSEIF <ls_source>-sha1 = <ls_common>-sha1.
* changed in target
<ls_result>-sha1 = <ls_target>-sha1.
ELSE.
* changed in source and target, conflict
_raise 'merge conflict'.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD find_first_common.
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.
rs_common = <ls_list1>.
RETURN.
ENDIF.
ENDLOOP.
ENDLOOP.
_raise 'error finding common ancestor'.
ENDMETHOD.
METHOD find_ancestors.
DEFINE _visit.
IF NOT &1 IS INITIAL.
READ TABLE lt_visit FROM &1 TRANSPORTING NO FIELDS.
IF sy-subrc <> 0.
APPEND &1 TO lt_visit.
ENDIF.
ENDIF.
END-OF-DEFINITION.
DATA: ls_commit TYPE lcl_git_pack=>ty_commit,
lt_visit TYPE STANDARD TABLE OF ty_sha1,
lv_commit LIKE LINE OF lt_visit.
FIELD-SYMBOLS: <ls_ancestor> LIKE LINE OF rt_ancestors,
<ls_object> LIKE LINE OF gt_objects.
APPEND iv_commit TO lt_visit.
LOOP AT lt_visit INTO lv_commit.
READ TABLE gt_objects ASSIGNING <ls_object>
WITH KEY type = gc_type-commit sha1 = lv_commit.
ASSERT sy-subrc = 0.
ls_commit = lcl_git_pack=>decode_commit( <ls_object>-data ).
_visit ls_commit-parent.
_visit ls_commit-parent2.
APPEND INITIAL LINE TO rt_ancestors ASSIGNING <ls_ancestor>.
<ls_ancestor>-commit = lv_commit.
<ls_ancestor>-tree = ls_commit-tree.
<ls_ancestor>-body = ls_commit-body.
FIND REGEX '^[\w\s]+ <(.*)> (\d{10}) .\d{4}$' IN ls_commit-author
SUBMATCHES <ls_ancestor>-time ##NO_TEXT.
ASSERT sy-subrc = 0.
ENDLOOP.
SORT rt_ancestors BY time ASCENDING.
ENDMETHOD.
METHOD fetch_git.
DEFINE _find.
lv_name = 'refs/heads/' && &1.
READ TABLE lt_branches INTO &2 WITH KEY name = lv_name.
ASSERT sy-subrc = 0.
APPEND &2 TO lt_upload.
END-OF-DEFINITION.
DATA: lv_name TYPE string,
lt_branches TYPE lcl_git_transport=>ty_branch_list_tt,
lt_upload TYPE lcl_git_transport=>ty_branch_list_tt.
FIELD-SYMBOLS: <ls_branch> LIKE LINE OF lt_upload.
lt_branches = lcl_git_transport=>branches( gs_merge-repo->get_url( ) ).
_find iv_source gs_merge-source.
_find iv_target gs_merge-target.
lcl_git_transport=>upload_pack( EXPORTING io_repo = gs_merge-repo
iv_deepen = abap_false
it_branches = lt_upload
IMPORTING et_objects = gt_objects ).
DELETE gt_objects WHERE type = gc_type-blob.
ENDMETHOD.
ENDCLASS.
*********************************
CLASS lcl_gui_page_merge DEFINITION FINAL INHERITING FROM lcl_gui_page_super.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING io_repo TYPE REF TO lcl_repo_online
iv_source TYPE string
iv_target TYPE string
RAISING lcx_exception,
lif_gui_page~on_event REDEFINITION,
lif_gui_page~render REDEFINITION.
PRIVATE SECTION.
DATA: mo_repo TYPE REF TO lcl_repo_online,
ms_merge TYPE lcl_merge=>ty_merge.
ENDCLASS. "lcl_gui_page_merge DEFINITION
CLASS lcl_gui_page_merge IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mo_repo = io_repo.
ms_merge = lcl_merge=>run(
io_repo = io_repo
iv_source = iv_source
iv_target = iv_target ).
ENDMETHOD.
METHOD lif_gui_page~on_event.
BREAK-POINT.
ENDMETHOD.
METHOD lif_gui_page~render.
DEFINE _show_file.
READ TABLE &1 ASSIGNING <ls_show>
WITH KEY path = <ls_file>-path name = <ls_file>-name.
IF sy-subrc = 0.
IF <ls_show>-sha1 = ls_result-sha1.
ro_html->add( |<td>{
<ls_show>-path }{ <ls_show>-name }</td><td><b>{
<ls_show>-sha1(7) }</b></td>| ).
ELSE.
ro_html->add( |<td>{
<ls_show>-path }{ <ls_show>-name }</td><td>{
<ls_show>-sha1(7) }</td>| ).
ENDIF.
ELSE.
ro_html->add( '<td></td><td></td>' ).
ENDIF.
END-OF-DEFINITION.
DATA: lt_files LIKE ms_merge-stree,
ls_result LIKE LINE OF ms_merge-result.
FIELD-SYMBOLS: <ls_show> LIKE LINE OF lt_files,
<ls_file> LIKE LINE OF lt_files.
CREATE OBJECT ro_html.
ro_html->add( header( ) ).
ro_html->add( title( 'MERGE' ) ).
ro_html->add( '<div id="toc">' ).
ro_html->add( render_repo_top( mo_repo ) ).
_add '<table>'.
_add '<tr>'.
_add '<td>Source:</td>'.
_add '<td>'.
_add ms_merge-source-name.
_add '</td></tr>'.
_add '<tr>'.
_add '<td>Target:</td>'.
_add '<td>'.
_add ms_merge-target-name.
_add '</td></tr>'.
_add '<tr>'.
_add '<td>Ancestor:</td>'.
_add '<td>'.
_add ms_merge-common-commit.
_add '</td></tr>'.
_add '</table>'.
_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.
SORT lt_files BY path DESCENDING name ASCENDING.
DELETE ADJACENT DUPLICATES FROM lt_files COMPARING path name.
ro_html->add( '<table>' ).
ro_html->add( '<tr>' ).
ro_html->add( '<td><u>Source</u></td>' ).
ro_html->add( '<td></td>' ).
ro_html->add( '<td><u>Target</u></td>' ).
ro_html->add( '<td></td>' ).
ro_html->add( '<td><u>Ancestor</u></td>' ).
ro_html->add( '<td></td>' ).
ro_html->add( '<td><u>Result</u></td>' ).
ro_html->add( '<td></td>' ).
ro_html->add( '</tr>' ).
LOOP AT lt_files ASSIGNING <ls_file>.
CLEAR ls_result.
READ TABLE ms_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.
ro_html->add( '</tr>' ).
ENDLOOP.
ro_html->add( '</table>' ).
ro_html->add( '<br>Todo' ).
ro_html->add( '</div>' ).
ro_html->add( footer( ) ).
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_PROG" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<PROGDIR>
<NAME>ZABAPGIT_PAGE_MERGE</NAME>
<STATE>A</STATE>
<SQLX/>
<EDTX/>
<VARCL>X</VARCL>
<DBAPL/>
<DBNA/>
<CLAS/>
<TYPE/>
<OCCURS/>
<SUBC>I</SUBC>
<APPL/>
<SECU/>
<CNAM/>
<CDAT>0000-00-00</CDAT>
<UNAM/>
<UDAT>0000-00-00</UDAT>
<VERN/>
<LEVL/>
<RSTAT/>
<RMAND/>
<RLOAD>E</RLOAD>
<FIXPT/>
<SSET/>
<SDATE>0000-00-00</SDATE>
<STIME/>
<IDATE>0000-00-00</IDATE>
<ITIME/>
<LDBNAME/>
<UCCHECK>X</UCCHECK>
</PROGDIR>
<TPOOL>
<item>
<ID>R</ID>
<KEY/>
<ENTRY>Include ZABAPGIT_PAGE_MERGE</ENTRY>
<LENGTH>27</LENGTH>
<SPLIT/>
</item>
</TPOOL>
</asx:values>
</asx:abap>
</abapGit>