diff --git a/.abapgit.xml b/.abapgit.xml index b436bd601..1ad2643c1 100644 --- a/.abapgit.xml +++ b/.abapgit.xml @@ -10,6 +10,7 @@ /LICENSE /README.md /package.json + /changelog.txt diff --git a/README.md b/README.md index a618b239b..6b6f55250 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Git client for ABAP -Works with: [GitHub](https://github.com/), [GitLab](https://gitlab.com/), [Assembla](https://www.assembla.com/git/), [Bitbucket](https://bitbucket.org/), [abapGitServer](https://github.com/larshp/abapGitServer), and more +Works with: [GitHub](https://github.com/), [GitLab](https://gitlab.com/), [Assembla](https://www.assembla.com/git/), [Bitbucket](https://bitbucket.org/), [abapGitServer](https://github.com/larshp/abapGitServer), [HCP](http://go.sap.com/denmark/developer/tutorials/hcp-webide-commit-git.html), [TFS](https://www.visualstudio.com/team-services/git/) and more ABAP Version: 702 or higher @@ -23,4 +23,4 @@ See [Wiki](https://github.com/larshp/abapGit/wiki/) ## FAQ ## For questions/comments/bugs/feature requests/wishes please create an [issue](https://github.com/larshp/abapGit/issues) -![abapgit](https://github.com/larshp/abapGit/wiki/img/abapgit_1_16_1.png) +![abapgit](https://github.com/larshp/abapGit/wiki/img/abapgit_1_17_17.png) diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 000000000..6cabba47f --- /dev/null +++ b/changelog.txt @@ -0,0 +1,31 @@ +abapGit changelog +================= + +Legend +------ +* : fixed +! : changed ++ : added +- : removed + +2016-12-01 v1.24.0 +------------------ ++ abap syntax highlighting + +2016-11-22 +------------------ ++ supported object list @debugpage ++ New favorites bar. All repos are displayed in dropdown burger-button. A repo can be "starred" to appear in favbar. +! W3xx serialization change (v2.0.0). Now data file is stored as a separate file instead of base64 field in XML. +* Fixed bug in diff page: change counters values + +2016-11-12 +------------------ ++ brand new style for file diff display - local and remote statuses are independent and based on local/remote hash and saved state ++ diffs can now be displayed for new local files +* stage header diff (all changes) now display all diff including new local files +! local state in DB is now calculated per file. This will require rebuilding of local checksums - the dislog will popup at the begining. The logic is: if local and remote file differs then: if remote branch is ahead then assume changes are remote, else (branches are equal) assume changes are local. This will lead to incorrect state for files changed on both sides (which should be a rare case though). If this is critical - it is better to sync repo with a previous version of abapGit first. + +before 2016-11-12 +------------------ +long history of abapGit development ;) diff --git a/package.json b/package.json index e571cc70f..f0cdb6687 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "url": "git+https://github.com/larshp/abapGit.git" }, "devDependencies": { - "abapmerge": "^0.5.4", + "abapmerge": "^0.6.2", "abaplint": ">=0.26.7" } } diff --git a/src/zabapgit.prog.abap b/src/zabapgit.prog.abap index d75ad836b..ef48a5c98 100644 --- a/src/zabapgit.prog.abap +++ b/src/zabapgit.prog.abap @@ -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.17.9'. "#EC NOTEXT + gc_abap_version TYPE string VALUE 'v1.24.5'. "#EC NOTEXT ******************************************************************************** * The MIT License (MIT) @@ -30,100 +30,57 @@ CONSTANTS: gc_xml_version TYPE string VALUE 'v1.0.0', "#EC NOTEXT ******************************************************************************** SELECTION-SCREEN BEGIN OF SCREEN 1001. -* dummy for triggering screen +* dummy for triggering screen on Java SAP GUI SELECTION-SCREEN END OF SCREEN 1001. INCLUDE zabapgit_password_dialog. " !!! Contains SELECTION SCREEN INCLUDE zabapgit_definitions. +INCLUDE zabapgit_macros. INCLUDE zabapgit_exceptions. INCLUDE zabapgit_zlib. +INCLUDE zabapgit_html. INCLUDE zabapgit_util. INCLUDE zabapgit_xml. -CLASS lcl_gui DEFINITION DEFERRED. -CLASS lcl_persistence_user DEFINITION DEFERRED. -CLASS lcl_repo_srv DEFINITION DEFERRED. -CLASS lcl_persistence_db DEFINITION DEFERRED. - -INCLUDE zabapgit_app. +INCLUDE zabapgit_app. " Some deferred definitions here +INCLUDE zabapgit_persistence_old. INCLUDE zabapgit_persistence. -INCLUDE zabapgit_html. INCLUDE zabapgit_dot_abapgit. INCLUDE zabapgit_sap_package. -CLASS lcl_repo_online DEFINITION DEFERRED. - INCLUDE zabapgit_stage. INCLUDE zabapgit_git_helpers. INCLUDE zabapgit_repo. -INCLUDE zabapgit_git. INCLUDE zabapgit_stage_logic. +INCLUDE zabapgit_http. +INCLUDE zabapgit_git. INCLUDE zabapgit_objects. INCLUDE zabapgit_tadir. INCLUDE zabapgit_file_status. -INCLUDE zabapgit_object. -INCLUDE zabapgit_object_acid. -INCLUDE zabapgit_object_auth. -INCLUDE zabapgit_object_doct. -INCLUDE zabapgit_object_docv. -INCLUDE zabapgit_object_doma. -INCLUDE zabapgit_object_dtel. -INCLUDE zabapgit_object_enho. -INCLUDE zabapgit_object_enhs. -INCLUDE zabapgit_object_enqu. -INCLUDE zabapgit_object_ensc. -INCLUDE zabapgit_object_iarp. -INCLUDE zabapgit_object_iasp. -INCLUDE zabapgit_object_iatu. -INCLUDE zabapgit_object_msag. -INCLUDE zabapgit_object_nrob. -INCLUDE zabapgit_object_para. -INCLUDE zabapgit_object_pinf. -INCLUDE zabapgit_object_sfbf. -INCLUDE zabapgit_object_sfbs. -INCLUDE zabapgit_object_sfsw. -INCLUDE zabapgit_object_shi3. -INCLUDE zabapgit_object_shlp. -INCLUDE zabapgit_object_sicf. -INCLUDE zabapgit_object_smim. -INCLUDE zabapgit_object_splo. -INCLUDE zabapgit_object_ssfo. -INCLUDE zabapgit_object_ssst. -INCLUDE zabapgit_object_susc. -INCLUDE zabapgit_object_suso. -INCLUDE zabapgit_object_tabl. -INCLUDE zabapgit_object_tobj. -INCLUDE zabapgit_object_tran. -INCLUDE zabapgit_object_ttyp. -INCLUDE zabapgit_object_type. -INCLUDE zabapgit_object_vcls. -INCLUDE zabapgit_object_view. -INCLUDE zabapgit_object_w3xx. -INCLUDE zabapgit_object_wdya. -INCLUDE zabapgit_object_wdyn. -INCLUDE zabapgit_object_webi. -INCLUDE zabapgit_object_xslt. +INCLUDE zabapgit_popups. +INCLUDE zabapgit_zip. +INCLUDE zabapgit_objects_impl. + +INCLUDE zabapgit_object_serializing. " All serializing classes here INCLUDE zabapgit_repo_impl. INCLUDE zabapgit_background. -INCLUDE zabapgit_zip. INCLUDE zabapgit_transport. -INCLUDE zabapgit_popups. -INCLUDE zabapgit_page. -INCLUDE zabapgit_page_commit. -INCLUDE zabapgit_page_merge. -INCLUDE zabapgit_page_branch_overview. -INCLUDE zabapgit_page_stage. -INCLUDE zabapgit_page_db. -INCLUDE zabapgit_page_main. -INCLUDE zabapgit_page_background. +INCLUDE zabapgit_services. " All services here +INCLUDE zabapgit_gui_asset_manager. +INCLUDE zabapgit_gui_pages. " All GUI pages here +INCLUDE zabapgit_gui_pages_userexit IF FOUND. +INCLUDE zabapgit_gui_router. INCLUDE zabapgit_gui. + INCLUDE zabapgit_app_impl. INCLUDE zabapgit_unit_test. +INCLUDE zabapgit_migrations. " Data migration routines INCLUDE zabapgit_forms. +********************************************************************** INITIALIZATION. lcl_password_dialog=>on_screen_init( ). @@ -132,7 +89,7 @@ START-OF-SELECTION. * Hide Execute button from screen AT SELECTION-SCREEN OUTPUT. - IF sy-dynnr = lcl_password_dialog=>DYNNR. + IF sy-dynnr = lcl_password_dialog=>dynnr. lcl_password_dialog=>on_screen_output( ). ELSE. PERFORM output. @@ -143,6 +100,6 @@ AT SELECTION-SCREEN ON EXIT-COMMAND. PERFORM exit. AT SELECTION-SCREEN. - IF sy-dynnr = lcl_password_dialog=>DYNNR. + IF sy-dynnr = lcl_password_dialog=>dynnr. lcl_password_dialog=>on_screen_event( sscrfields-ucomm ). ENDIF. \ No newline at end of file diff --git a/src/zabapgit.prog.xml b/src/zabapgit.prog.xml index c45af12c8..aed90ce00 100644 --- a/src/zabapgit.prog.xml +++ b/src/zabapgit.prog.xml @@ -35,27 +35,6 @@ X - - - - - - - - - - - - - - - - - - - - - R diff --git a/src/zabapgit_app.prog.abap b/src/zabapgit_app.prog.abap index 0588a81f1..26f17a1b2 100644 --- a/src/zabapgit_app.prog.abap +++ b/src/zabapgit_app.prog.abap @@ -2,6 +2,12 @@ *& Include ZABAPGIT_APP *&---------------------------------------------------------------------* +CLASS lcl_gui DEFINITION DEFERRED. +CLASS lcl_persistence_user DEFINITION DEFERRED. +CLASS lcl_repo_srv DEFINITION DEFERRED. +CLASS lcl_persistence_db DEFINITION DEFERRED. +CLASS lcl_persistence_settings DEFINITION DEFERRED. + *----------------------------------------------------------------------* * CLASS lcl_app DEFINITION *----------------------------------------------------------------------* @@ -26,10 +32,14 @@ CLASS lcl_app DEFINITION FINAL. CLASS-METHODS db RETURNING VALUE(ro_db) TYPE REF TO lcl_persistence_db. + CLASS-METHODS settings + RETURNING VALUE(ro_settings) TYPE REF TO lcl_persistence_settings. + PRIVATE SECTION. CLASS-DATA: go_gui TYPE REF TO lcl_gui, go_current_user TYPE REF TO lcl_persistence_user, go_db TYPE REF TO lcl_persistence_db, - go_repo_srv TYPE REF TO lcl_repo_srv. + go_repo_srv TYPE REF TO lcl_repo_srv, + go_settings TYPE REF TO lcl_persistence_settings. ENDCLASS. "lcl_app \ No newline at end of file diff --git a/src/zabapgit_app_impl.prog.abap b/src/zabapgit_app_impl.prog.abap index c9d95128e..9af5079b0 100644 --- a/src/zabapgit_app_impl.prog.abap +++ b/src/zabapgit_app_impl.prog.abap @@ -60,4 +60,11 @@ CLASS lcl_app IMPLEMENTATION. ENDMETHOD. "repo_srv + METHOD settings. + IF go_settings IS NOT BOUND. + CREATE OBJECT go_settings. + ENDIF. + ro_settings = go_settings. + ENDMETHOD. + ENDCLASS. "lcl_app \ No newline at end of file diff --git a/src/zabapgit_background.prog.abap b/src/zabapgit_background.prog.abap index cd729c657..b183c992d 100644 --- a/src/zabapgit_background.prog.abap +++ b/src/zabapgit_background.prog.abap @@ -5,11 +5,15 @@ CLASS lcl_background DEFINITION FINAL. PUBLIC SECTION. - CLASS-METHODS: run - RAISING lcx_exception. + CLASS-METHODS: + run + RAISING lcx_exception. PRIVATE SECTION. CLASS-METHODS: + build_comment + IMPORTING is_files TYPE ty_stage_files + RETURNING VALUE(rv_comment) TYPE string, push IMPORTING io_repo TYPE REF TO lcl_repo_online is_settings TYPE lcl_persistence_background=>ty_background @@ -54,14 +58,9 @@ CLASS lcl_background IMPLEMENTATION. FIELD-SYMBOLS: LIKE LINE OF ls_files-local. - ls_files = lcl_stage_logic=>get( io_repo ). ASSERT lines( ls_files-local ) > 0. - ls_comment-username = is_settings-aname. - ls_comment-email = is_settings-amail. - ls_comment-comment = 'abapGit background mode' ##NO_TEXT. - CREATE OBJECT lo_stage EXPORTING iv_branch_name = io_repo->get_branch_name( ) @@ -76,16 +75,45 @@ CLASS lcl_background IMPLEMENTATION. iv_data = -file-data ). ENDLOOP. + ls_comment-username = is_settings-aname. + ls_comment-email = is_settings-amail. + ls_comment-comment = build_comment( ls_files ). + io_repo->push( is_comment = ls_comment io_stage = lo_stage ). ENDMETHOD. + METHOD build_comment. + + DATA: lt_objects TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + lv_str TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF is_files-local. + + + LOOP AT is_files-local ASSIGNING . + lv_str = |{ -item-obj_type } { -item-obj_name }|. + APPEND lv_str TO lt_objects. + ENDLOOP. + + IF lines( lt_objects ) = 1. + rv_comment = |BG: { lv_str }|. + ELSE. + rv_comment = 'BG: Multiple objects'. + LOOP AT lt_objects INTO lv_str. + CONCATENATE rv_comment gc_newline lv_str INTO rv_comment. + ENDLOOP. + ENDIF. + + ENDMETHOD. + METHOD push_auto. - DATA: ls_comment TYPE ty_comment, - ls_files TYPE ty_stage_files, - lo_stage TYPE REF TO lcl_stage. + DATA: ls_comment TYPE ty_comment, + ls_files TYPE ty_stage_files, + ls_user_files LIKE ls_files, + lo_stage TYPE REF TO lcl_stage. FIELD-SYMBOLS: LIKE LINE OF ls_files-local. @@ -94,7 +122,6 @@ CLASS lcl_background IMPLEMENTATION. ls_files = lcl_stage_logic=>get( io_repo ). DO. - READ TABLE ls_files-local INDEX 1 ASSIGNING . IF sy-subrc <> 0. EXIT. @@ -103,13 +130,14 @@ CLASS lcl_background IMPLEMENTATION. CLEAR ls_comment. ls_comment-username = lcl_objects=>changed_by( -item ). ls_comment-email = |{ ls_comment-username }@localhost|. - ls_comment-comment = 'abapGit background mode' ##NO_TEXT. CREATE OBJECT lo_stage EXPORTING iv_branch_name = io_repo->get_branch_name( ) iv_branch_sha1 = io_repo->get_sha1_remote( ). + CLEAR ls_user_files. + LOOP AT ls_files-local ASSIGNING . IF lcl_objects=>changed_by( -item ) = ls_comment-username. WRITE: / 'stage' ##NO_TEXT, @@ -120,9 +148,13 @@ CLASS lcl_background IMPLEMENTATION. lo_stage->add( iv_path = -file-path iv_filename = -file-filename iv_data = -file-data ). + + APPEND TO ls_user_files-local. ENDIF. ENDLOOP. + ls_comment-comment = build_comment( ls_user_files ). + io_repo->push( is_comment = ls_comment io_stage = lo_stage ). diff --git a/src/zabapgit_css_common.w3mi.data.css b/src/zabapgit_css_common.w3mi.data.css new file mode 100644 index 000000000..f81327870 --- /dev/null +++ b/src/zabapgit_css_common.w3mi.data.css @@ -0,0 +1,608 @@ +/* + * ABAPGIT COMMON CSS + */ + +/* GLOBALS */ + +body { + font-family: Arial,Helvetica,sans-serif; + font-size: 12pt; + background: #E8E8E8; +} + +a, a:visited { + color: #4078c0; + text-decoration: none; +} + +a:hover, a:active { + cursor: pointer; + text-decoration: underline; +} + +img { border: 0px; vertical-align: middle; } +table { border-collapse: collapse; } +pre { display: inline; } + +form input, textarea, select { + border: 1px solid #DDD; + padding: 3px 6px; +} + +form input:focus, textarea:focus { + border: 1px solid #8cadd9; +} + +/* MODIFIERS */ +.grey { color: lightgrey !important; } +.emphasis { font-weight: bold !important; } +.attention { color: red !important; } +.crossout { text-decoration: line-through !important; } +.right { text-align:right; } +.paddings { padding: 0.5em 0.5em; } +.pad-sides { padding: 0 0.3em; } +.pad4px { padding: 4px; } + +/* STRUCTURE DIVS, HEADER & FOOTER */ +td.headpad { padding-top: 11px; } +td.logo { width: 164px; } + +div#header { + padding: 0.5em 0.5em; + border-bottom: 3px double lightgrey; +} + +div#toc { + padding: 0.5em 1em; + background-color: #f2f2f2; +} + +div#toc div.toc_grid { + margin: -0.3em 0em; +} + +div#toc div.toc_grid a { + color: #ccc; +} + +div#toc:hover div.toc_grid a { + color: #4078c0; +} + +div#toc div.toc_row { + margin: 0.3em 0em; +} + +div#footer { + padding: 0.5em 1em; + border-top: 3px double lightgrey; + text-align: center; +} + +div.dummydiv { + background-color: #f2f2f2; + padding: 0.5em 1em; + text-align: center; +} + +span.version { + display: block; + color: grey; + margin-top: 0.3em; +} + +span.page_title { + font-weight: normal; + font-size: 18pt; + color: #bbb; + padding-left: 0.4em; +} + +/* MENU */ +div.menu { display: inline; } +div.menu .menu_end { border-right: 0px !important; } +div.menu a { + padding-left: 0.5em; + padding-right: 0.5em; + border-right: 1px solid lightgrey; + font-size: 12pt; +} +div.menu_vertical { display: inline; } +div.menu_vertical a { + display: block; + font-size: 12pt; +} + +/*DROP DOWN*/ +.dropdown { + position: relative; + display: inline; +} +.dropdown_angle { + position: absolute !important; + right: -4px; + top: -1px; +} +.dropbtn_angle { + width: 0; + height: 0; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #4078c0; + transform: rotate(45deg); + -ms-transform: rotate(45deg); +} +.dropdown_content { + display: none; + z-index: 1; + position: absolute; + right: -12px; + top: 1em; + padding: 6px 10px 10px 10px; + white-space: nowrap; +} +.dropdown div.minizone { + display: none; + z-index: 1; + position: absolute; + padding: 0px; + width: 16px; + height: 16px; + bottom: 0px; + left: -16px; +} +.dropdown_angle .dropdown_content { + top: -1px; +} +.dropdown:hover .dropdown_content { display: block; } +.dropdown:hover .minizone { display: block; } +.dropdown_content a { + padding: 0.2em; + background-color: #f9f9f9; + text-decoration: none; + display: block; + border: none !important; +} +.dropdown_content div.box { + border-bottom: 1px solid #C0C0C0; + border-right: 1px solid #C0C0C0; + background-color: #f9f9f9; + padding: 2px; +} +.dropdown_content td { text-align: left; padding: 2px; } +.dropdown_content td a { padding: 0em 0.2em; } +.dropdown_content td.icon { padding: 0 3px 0 6px; } +.dropdown_content a:hover { background-color: #f1f1f1 } +.dropdown:hover .dropbtn { color: #79a0d2; } + +/* REPOSITORY */ +div.repo { + margin-top: 3px; + background-color: #f2f2f2; + padding: 0.5em 1em 0.5em 1em; +} +.repo_name span.name { + font-weight: bold; + color: #333; + font-size: 14pt; +} +.repo_name span.url { + color: #ccc; + font-size: 12pt; + margin-left: 0.5em; +} +.repo_name img { + vertical-align: baseline; + margin: 0 5px 0 5px; +} +.repo_attr { + color: grey; + font-size: 12pt; +} +.repo_attr span { + margin-left: 0.2em; + margin-right: 0.5em; +} +.repo_attr span.bg_marker { + border: 1px solid #d2d2d2; + border-radius: 3px; + background: #d8d8d8; + color: #fff; + font-size: 8pt; + padding: 4px 2px 3px 2px; +} +.repo_attr span.branch { + padding: 2px 4px; + border: 1px solid #d9d9d9; + border-radius: 4px; + background-color: #e2e2e2; +} +.repo_attr span.branch_head { + border-color: #d8dff3; + background-color: #eceff9; +} +.repo_attr span.branch_branch { + border-color: #e7d9b1; + background-color: #f8f0d8; +} + +/* MISC AND REFACTOR */ +.hidden-submit { + border: 0 none; + height: 0; + width: 0; + padding: 0; + margin: 0; + overflow: hidden; +} + +#debug-output { + text-align: right; + padding-right: 0.5em; + color: #ccc; + font-style: italic; + font-size: small; +} + +/* REPOSITORY TABLE*/ +div.repo_container { + position: relative; +} +.repo_tab { + border: 1px solid #DDD; + border-radius: 3px; + background: #fff; + margin-top: 0.5em; +} +.repo_tab td { + border-top: 1px solid #eee; + vertical-align: middle; + color: #333; + padding-top: 2px; + padding-bottom: 2px; +} +.repo_tab td.icon { + width: 32px; + text-align: center; +} +.repo_tab td.type { + width: 3em; +} +.repo_tab td.object { + padding-left: 0.5em; +} +.repo_tab td.files { + padding-left: 0.5em; +} +.repo_tab td.cmd { + text-align: right; + padding-left: 0.5em; + padding-right: 0.7em; +} +.repo_tab tr.unsupported { color: lightgrey; } +.repo_tab tr.modified { background: #fbf7e9; } +.repo_tab tr:first-child td { border-top: 0px; } +.repo_tab td.current_dir { color: #ccc; } +.repo_tab td.cmd span.state-block { + margin-left: 1em; + font-family: Consolas, Lucida Console, Courier, monospace; + font-size: x-small; + vertical-align: 13%; + display: inline-block; + text-align: center; +} +.repo_tab td.cmd span.state-block span { + display: inline-block; + padding: 0px 2px; + border: 1px solid #000; +} +.repo_tab td.cmd span.state-block span.added { + background-color: #69ad74; + border-color: #579e64; + color: white; +} +.repo_tab td.cmd span.state-block span.changed { + background-color: #e0c150; + border-color: #d4af25; + color: white; +} +.repo_tab td.cmd span.state-block span.mixed { + background-color: #e0c150; + border-color: #579e64; + color: #69ad74; +} +.repo_tab td.cmd span.state-block span.deleted { + background-color: #c76861; + border-color: #b8605a; + color: white; +} +.repo_tab td.cmd span.state-block span.none { + background-color: #e8e8e8; + border-color: #dbdbdb; + color: #c8c8c8; +} + +/* STAGE */ +.stage_tab { + border: 1px solid #DDD; + background: #fff; + margin-top: 0.2em; +} +.stage_tab td { + border-top: 1px solid #eee; + color: #333; + vertical-align: middle; + padding: 2px 0.5em; +} +.stage_tab th { + color: #BBB; + font-size: 10pt; + text-align: left; + font-weight: normal; + background-color: #edf2f9; + padding: 4px 0.5em; +} +.stage_tab td.status { + width: 2em; + text-align: center; +} +.stage_tab tbody tr:first-child td { padding-top: 0.5em; } +.stage_tab tbody tr:last-child td { padding-bottom: 0.5em; } +.stage_tab td.cmd a { padding: 0px 4px; } + +/* STAGE */ +.stage_tab td.method { + color: #ccc; +} +.stage_tab tr.firstrow td { border-top: 0px; } +.stage_tab tr.title td { + color: #BBB; + font-size: 10pt; + background-color: #edf2f9; + padding: 4px 0.5em; + text-align: center; +} + +/* COMMIT */ +div.form_div { + margin: 0.5em 0em; + background-color: #F8F8F8; + padding: 1em 1em; +} + +div.form_div td.field_name { + color: #BBB; + padding-right: 1em; +} + +/* SETTINGS STYLES */ +div.settings_container { + padding: 0.5em; + font-size: 10pt; + color: #444; + background-color: #f2f2f2; +} + +/* DIFF */ +div.diff { + background-color: #f2f2f2; + padding: 0.7em +} +div.diff_head { + padding-bottom: 0.7em; +} +span.diff_name { + padding-left: 0.5em; + color: grey; +} +span.diff_name strong { + color: #333; +} +span.diff_banner { + border-style: solid; + border-width: 1px; + border-radius: 3px; + padding-left: 0.3em; + padding-right: 0.3em; +} +.diff_ins { + border-color: #7bea7b; + background-color: #d3f8d3; +} +.diff_del { + border-color: #ff667d; + background-color: #ffccd4; +} +.diff_upd { + border-color: #dada00; + background-color: #ffffcc; +} +div.diff_content { + background: #fff; + border-top: 1px solid #DDD; + border-bottom: 1px solid #DDD; +} +div.diff_head span.state-block { + margin-left: 0.5em; + font-family: Consolas, Lucida Console, Courier, monospace; + display: inline-block; + text-align: center; +} +div.diff_head span.state-block span { + display: inline-block; + padding: 0px 4px; + border: 1px solid #000; +} +div.diff_head span.state-block span.added { + background-color: #69ad74; + border-color: #579e64; + color: white; +} +div.diff_head span.state-block span.changed { + background-color: #e0c150; + border-color: #d4af25; + color: white; +} +div.diff_head span.state-block span.mixed { + background-color: #e0c150; + border-color: #579e64; + color: #69ad74; +} +div.diff_head span.state-block span.deleted { + background-color: #c76861; + border-color: #b8605a; + color: white; +} +div.diff_head span.state-block span.none { + background-color: #e8e8e8; + border-color: #dbdbdb; + color: #c8c8c8; +} + +/* DIFF TABLE */ +table.diff_tab { + font-family: Consolas, Courier, monospace; + font-size: 10pt; +} +table.diff_tab td,th { + color: #444; + padding-left: 0.5em; + padding-right: 0.5em; +} +table.diff_tab th { + text-align: left; + font-weight: normal; + padding-top: 3px; + padding-bottom: 3px; +} +table.diff_tab thead.header th { + color: #EEE; + background-color: #BBB; + text-align: left; + font-weight: bold; + padding-left: 0.5em; + font-size: 9pt; +} +table.diff_tab thead.nav_line { + background-color: #edf2f9; +} +table.diff_tab thead.nav_line th { + color: #bbb; +} +table.diff_tab td.num, th.num { + text-align: right; + color: #ccc; + border-left: 1px solid #eee; + border-right: 1px solid #eee; +} +table.diff_tab code { + font-family: inherit; + white-space: pre; +} + +table.diff_tab code span.keyword { color: #0a69ce; } +table.diff_tab code span.text { color: #48ce4f; } +table.diff_tab code span.comment { color: #808080; font-style: italic; } + +table.diff_tab tbody tr:first-child td { padding-top: 0.5em; } +table.diff_tab tbody tr:last-child td { padding-bottom: 0.5em; } + +/* DEBUG INFO STYLES */ +div.debug_container { + padding: 0.5em; + font-size: 10pt; + color: #444; + font-family: Consolas, Courier, monospace; +} +div.debug_container p { + margin: 0px; +} + +/* DB ENTRIES */ +div.db_list { + background-color: #f2f2f2; + padding: 0.5em; +} +table.db_tab pre { + display: inline-block; + overflow: hidden; + word-wrap:break-word; + white-space: pre-wrap; + margin: 0px; + width: 30em; +} +table.db_tab tr.firstrow td { padding-top: 0.5em; } +table.db_tab th { + text-align: left; + color: #888; + padding: 0.5em; + border-bottom: 1px #ddd solid; +} +table.db_tab td { + color: #333; + padding: 0.5em; + vertical-align: top; +} +table.db_tab td.data { + color: #888; + font-style: italic; +} + +/* DB ENTRY DISPLAY */ +div.db_entry { + background-color: #f2f2f2; + padding: 0.5em; +} +div.db_entry pre { + display: block; + overflow: hidden; + word-wrap:break-word; + white-space: pre-wrap; + background-color: #eaeaea; + padding: 0.5em; + margin: 0.5em 0em; + width: 50em; +} +div.db_entry table.toolbar { + width: 50em; +} +table.tag { + display: inline-block; + border: 1px #b3c1cc solid; + background-color: #eee; + border-radius: 3px; + margin-right: 0.5em; +} +table.tag td { padding: 0.2em 0.5em; } +table.tag td.label { background-color: #b3c1cc; } + +/* DB ENTRY DISPLAY */ +div.db_entry textarea { margin: 0.5em 0em; } +table.tag { + display: inline-block; + border: 1px #b3c1cc solid; + background-color: #eee; + border-radius: 3px; + margin-right: 0.5em; +} +table.tag td { padding: 0.2em 0.5em; } +table.tag td.label { background-color: #b3c1cc; } + +/* TUTORIAL */ + +div.tutorial { + margin-top: 3px; + background-color: #f2f2f2; + padding: 0.5em 1em 0.5em 1em; +} + +div.tutorial hr { border-color: #CCC; } +div.tutorial li { margin: 2px 0px } +div.tutorial h1 { + font-size: 18pt; + color: #404040; +} +div.tutorial h2 { + font-size: 14pt; + color: #404040; +} diff --git a/src/zabapgit_css_common.w3mi.xml b/src/zabapgit_css_common.w3mi.xml new file mode 100644 index 000000000..10d1ffd0d --- /dev/null +++ b/src/zabapgit_css_common.w3mi.xml @@ -0,0 +1,29 @@ + + + + + ZABAPGIT_CSS_COMMON + AbapGit common styles + + + MI + ZABAPGIT_CSS_COMMON + fileextension + .css + + + MI + ZABAPGIT_CSS_COMMON + filename + ~wwwtmp.css + + + MI + ZABAPGIT_CSS_COMMON + mimetype + text/css + + + + + diff --git a/src/zabapgit_definitions.prog.abap b/src/zabapgit_definitions.prog.abap index ab14d3f0b..6cccf90c5 100644 --- a/src/zabapgit_definitions.prog.abap +++ b/src/zabapgit_definitions.prog.abap @@ -8,10 +8,18 @@ TYPES: ty_type TYPE c LENGTH 6, ty_bitbyte TYPE c LENGTH 8, ty_sha1 TYPE c LENGTH 40. -TYPES: BEGIN OF ty_file, +TYPES: BEGIN OF ty_file_signature, path TYPE string, filename TYPE string, - data TYPE xstring, + sha1 TYPE ty_sha1, + END OF ty_file_signature. + +TYPES: ty_file_signatures_tt TYPE STANDARD TABLE OF ty_file_signature WITH DEFAULT KEY. +TYPES: ty_file_signatures_ts TYPE SORTED TABLE OF ty_file_signature WITH UNIQUE KEY path filename. + +TYPES: BEGIN OF ty_file. + INCLUDE TYPE ty_file_signature. +TYPES: data TYPE xstring, END OF ty_file. TYPES: ty_files_tt TYPE STANDARD TABLE OF ty_file WITH DEFAULT KEY. @@ -27,7 +35,10 @@ TYPES: BEGIN OF ty_comment, TYPES: BEGIN OF ty_item, obj_type TYPE tadir-object, obj_name TYPE tadir-obj_name, - END OF ty_item. + devclass TYPE devclass, + END OF ty_item, + ty_items_tt TYPE STANDARD TABLE OF ty_item WITH DEFAULT KEY, + ty_items_ts TYPE SORTED TABLE OF ty_item WITH UNIQUE KEY obj_type obj_name. TYPES: BEGIN OF ty_file_item, file TYPE ty_file, @@ -36,21 +47,25 @@ TYPES: BEGIN OF ty_file_item, TYPES: ty_files_item_tt TYPE STANDARD TABLE OF ty_file_item WITH DEFAULT KEY. TYPES: BEGIN OF ty_metadata, - class TYPE string, - version TYPE string, - late_deser TYPE string, + class TYPE string, + version TYPE string, + late_deser TYPE string, + delete_tadir TYPE abap_bool, END OF ty_metadata. TYPES: BEGIN OF ty_web_asset, url TYPE w3url, - content TYPE string, + base64 TYPE string, + content TYPE xstring, END OF ty_web_asset. TYPES tt_web_assets TYPE STANDARD TABLE OF ty_web_asset WITH DEFAULT KEY. TYPES: BEGIN OF ty_repo_file, - path TYPE string, - filename TYPE string, - is_changed TYPE abap_bool, + path TYPE string, + filename TYPE string, + is_changed TYPE abap_bool, + rstate TYPE char1, + lstate TYPE char1, END OF ty_repo_file. TYPES tt_repo_files TYPE STANDARD TABLE OF ty_repo_file WITH DEFAULT KEY. @@ -86,17 +101,27 @@ TYPES: BEGIN OF ty_tadir, TYPES: ty_tadir_tt TYPE STANDARD TABLE OF ty_tadir WITH DEFAULT KEY. TYPES: BEGIN OF ty_result, - obj_type TYPE tadir-object, - obj_name TYPE tadir-obj_name, - match TYPE sap_bool, - filename TYPE string, - package TYPE devclass, - path TYPE string, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + path TYPE string, + filename TYPE string, + package TYPE devclass, + match TYPE sap_bool, + lstate TYPE char1, + rstate TYPE char1, END OF ty_result. TYPES: ty_results_tt TYPE STANDARD TABLE OF ty_result WITH DEFAULT KEY. TYPES: ty_sval_tt TYPE STANDARD TABLE OF sval WITH DEFAULT KEY. +CONSTANTS: BEGIN OF gc_state, " https://git-scm.com/docs/git-status + unchanged TYPE char1 VALUE '', + added TYPE char1 VALUE 'A', + modified TYPE char1 VALUE 'M', + deleted TYPE char1 VALUE 'D', "For future use + mixed TYPE char1 VALUE '*', + END OF gc_state. + CONSTANTS: BEGIN OF gc_chmod, file TYPE ty_chmod VALUE '100644', executable TYPE ty_chmod VALUE '100755', @@ -111,11 +136,13 @@ CONSTANTS: BEGIN OF gc_event_state, no_more_act VALUE 4, new_page_w_bookmark VALUE 5, go_back_to_bookmark VALUE 6, + new_page_replacing VALUE 7, END OF gc_event_state. CONSTANTS: BEGIN OF gc_html_opt, - emphas TYPE c VALUE 'E', - cancel TYPE c VALUE 'C', + emphas TYPE c VALUE 'E', + cancel TYPE c VALUE 'C', + crossout TYPE c VALUE 'X', END OF gc_html_opt. CONSTANTS: BEGIN OF gc_action_type, @@ -128,7 +155,59 @@ CONSTANTS: gc_newline TYPE abap_char1 VALUE cl_abap_char_utilities=>newline. CONSTANTS: gc_english TYPE spras VALUE 'E'. -CONSTANTS: gc_abapgit_homepage TYPE string VALUE 'http://www.abapgit.org' ##NO_TEXT. - CONSTANTS: gc_root_dir TYPE string VALUE '/', - gc_dot_abapgit TYPE string VALUE '.abapgit.xml' ##NO_TEXT. \ No newline at end of file + gc_dot_abapgit TYPE string VALUE '.abapgit.xml' ##NO_TEXT, + gc_author_regex TYPE string VALUE '^([\w\s\.@\-_1-9]+) <(.*)> (\d{10}) .\d{4}$' ##NO_TEXT. + +CONSTANTS: BEGIN OF gc_action, + repo_clone TYPE string VALUE 'repo_clone', + repo_refresh TYPE string VALUE 'repo_refresh', + repo_remove TYPE string VALUE 'repo_remove', + repo_purge TYPE string VALUE 'repo_purge', + repo_newoffline TYPE string VALUE 'repo_newoffline', + repo_remote_attach TYPE string VALUE 'repo_remote_attach', + repo_remote_detach TYPE string VALUE 'repo_remote_detach', + repo_remote_change TYPE string VALUE 'repo_remote_change', + repo_refresh_checksums TYPE string VALUE 'repo_refresh_checksums', + repo_toggle_fav TYPE string VALUE 'repo_toggle_fav', + + abapgit_home TYPE string VALUE 'abapgit_home', + abapgit_wiki TYPE string VALUE 'abapgit_wiki', + abapgit_install TYPE string VALUE 'abapgit_install', + abapgit_install_pi TYPE string VALUE 'abapgit_install_pi', + + zip_import TYPE string VALUE 'zip_import', + zip_export TYPE string VALUE 'zip_export', + zip_package TYPE string VALUE 'zip_package', + zip_transport TYPE string VALUE 'zip_transport', + zip_object TYPE string VALUE 'zip_object', + + git_pull TYPE string VALUE 'git_pull', + git_reset TYPE string VALUE 'git_reset', + git_branch_create TYPE string VALUE 'git_branch_create', + git_branch_switch TYPE string VALUE 'git_branch_switch', + git_branch_delete TYPE string VALUE 'git_branch_delete', + git_commit TYPE string VALUE 'git_commit', + + db_delete TYPE string VALUE 'db_delete', + db_update TYPE string VALUE 'db_update', + db_display TYPE string VALUE 'db_display', + db_edit TYPE string VALUE 'db_edit', + bg_update TYPE string VALUE 'bg_update', + + go_main TYPE string VALUE 'go_main', + go_explore TYPE string VALUE 'go_explore', + go_db TYPE string VALUE 'go_db', + go_background TYPE string VALUE 'go_background', + go_background_run TYPE string VALUE 'go_background_run', + go_diff TYPE string VALUE 'go_diff', + go_stage TYPE string VALUE 'go_stage', + go_commit TYPE string VALUE 'go_commit', + go_branch_overview TYPE string VALUE 'go_branch_overview', + go_playground TYPE string VALUE 'go_playground', + go_debuginfo TYPE string VALUE 'go_debuginfo', + go_settings TYPE STRING VALUE 'go_settings', + go_tutorial TYPE STRING VALUE 'go_tutorial', + jump TYPE string VALUE 'jump', + jump_pkg TYPE string VALUE 'jump_pkg', + END OF gc_action. \ No newline at end of file diff --git a/src/zabapgit_dot_abapgit.prog.abap b/src/zabapgit_dot_abapgit.prog.abap index 24c761ca4..36d823007 100644 --- a/src/zabapgit_dot_abapgit.prog.abap +++ b/src/zabapgit_dot_abapgit.prog.abap @@ -35,9 +35,12 @@ CLASS lcl_dot_abapgit DEFINITION CREATE PRIVATE FINAL FRIENDS ltcl_dot_abapgit. * set_starting_folder * IMPORTING iv_path TYPE string, get_master_language - RETURNING VALUE(rv_language) TYPE spras. + RETURNING VALUE(rv_language) TYPE spras, * set_master_language * IMPORTING iv_language TYPE spras. + get_signature + RETURNING VALUE(rs_signature) TYPE ty_file_signature + RAISING lcx_exception. PRIVATE SECTION. TYPES: BEGIN OF ty_dot_abapgit, @@ -207,4 +210,13 @@ CLASS lcl_dot_abapgit IMPLEMENTATION. * ms_data-master_language = iv_language. * ENDMETHOD. + METHOD get_signature. + + rs_signature-path = gc_root_dir. + rs_signature-filename = gc_dot_abapgit. + rs_signature-sha1 = lcl_hash=>sha1( iv_type = gc_type-blob + iv_data = serialize( ) ). + + ENDMETHOD. "get_signature + ENDCLASS. \ No newline at end of file diff --git a/src/zabapgit_exceptions.prog.abap b/src/zabapgit_exceptions.prog.abap index 19f7542f0..076cbd371 100644 --- a/src/zabapgit_exceptions.prog.abap +++ b/src/zabapgit_exceptions.prog.abap @@ -5,8 +5,6 @@ *----------------------------------------------------------------------* * CLASS LCX_EXCEPTION DEFINITION *----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* CLASS lcx_exception DEFINITION INHERITING FROM cx_static_check FINAL. PUBLIC SECTION. @@ -27,8 +25,6 @@ ENDCLASS. "CX_LOCAL_EXCEPTION DEFINITION *----------------------------------------------------------------------* * CLASS LCX_EXCEPTION IMPLEMENTATION *----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* CLASS lcx_exception IMPLEMENTATION. METHOD constructor. @@ -48,8 +44,6 @@ ENDCLASS. "lcx_exception IMPLEMENTATION *----------------------------------------------------------------------* * CLASS LCX_NOT_FOUND DEFINITION *----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* CLASS lcx_not_found DEFINITION INHERITING FROM cx_static_check FINAL. ENDCLASS. "CX_LOCAL_EXCEPTION DEFINITION @@ -57,8 +51,20 @@ ENDCLASS. "CX_LOCAL_EXCEPTION DEFINITION *----------------------------------------------------------------------* * CLASS LCX_NOT_FOUND IMPLEMENTATION *----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* CLASS lcx_not_found IMPLEMENTATION. -ENDCLASS. "lcx_not_found IMPLEMENTATION \ No newline at end of file +ENDCLASS. "lcx_not_found IMPLEMENTATION + +*----------------------------------------------------------------------* +* CLASS LCX_CANCEL DEFINITION +*----------------------------------------------------------------------* +CLASS lcx_cancel DEFINITION INHERITING FROM cx_static_check FINAL. + +ENDCLASS. "lcx_cancel DEFINITION + +*----------------------------------------------------------------------* +* CLASS LCX_CANCEL IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcx_cancel IMPLEMENTATION. + +ENDCLASS. "lcx_cancel IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_file_status.prog.abap b/src/zabapgit_file_status.prog.abap index a8d3a122c..7aee25688 100644 --- a/src/zabapgit_file_status.prog.abap +++ b/src/zabapgit_file_status.prog.abap @@ -5,9 +5,10 @@ *----------------------------------------------------------------------* * CLASS lcl_file_status DEFINITION *----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_file_status DEFINITION FINAL. +CLASS ltcl_file_status DEFINITION DEFERRED. + +CLASS lcl_file_status DEFINITION FINAL + FRIENDS ltcl_file_status. PUBLIC SECTION. @@ -19,180 +20,272 @@ CLASS lcl_file_status DEFINITION FINAL. PRIVATE SECTION. - CLASS-METHODS compare_files - IMPORTING it_repo TYPE ty_files_tt - is_gen TYPE ty_file - RETURNING VALUE(rv_match) TYPE sap_bool - RAISING lcx_exception. + CLASS-METHODS calculate_status + IMPORTING it_local TYPE ty_files_item_tt + it_remote TYPE ty_files_tt + it_cur_state TYPE ty_file_signatures_tt + RETURNING VALUE(rt_results) TYPE ty_results_tt. + + CLASS-METHODS: + build_existing + IMPORTING is_local TYPE ty_file_item + is_remote TYPE ty_file + it_state TYPE ty_file_signatures_ts + RETURNING VALUE(rs_result) TYPE ty_result, + build_new_local + IMPORTING is_local TYPE ty_file_item + RETURNING VALUE(rs_result) TYPE ty_result, + build_new_remote + IMPORTING is_remote TYPE ty_file + it_items TYPE ty_items_ts + it_state TYPE ty_file_signatures_ts + RETURNING VALUE(rs_result) TYPE ty_result, + identify_object + IMPORTING iv_filename TYPE string + EXPORTING es_item TYPE ty_item + ev_is_xml TYPE abap_bool. ENDCLASS. "lcl_file_status DEFINITION *----------------------------------------------------------------------* * CLASS lcl_file_status IMPLEMENTATION *----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* CLASS lcl_file_status IMPLEMENTATION. - METHOD compare_files. - - READ TABLE it_repo WITH KEY - path = is_gen-path - filename = is_gen-filename - data = is_gen-data - TRANSPORTING NO FIELDS. - IF sy-subrc <> 0. - rv_match = abap_false. - ELSE. - rv_match = abap_true. - ENDIF. - - ENDMETHOD. "compare_files - METHOD status. - DATA: lv_pre TYPE tadir-obj_name, - lt_files TYPE ty_files_tt, - ls_result LIKE LINE OF rt_results, - lv_type TYPE string, - ls_item TYPE ty_item, - lt_tadir TYPE ty_tadir_tt, - lt_local TYPE ty_files_item_tt, - ls_tadir TYPE tadir, - lt_remote TYPE ty_files_tt, - lv_ext TYPE string. + DATA: lv_index LIKE sy-tabix, + lo_dot_abapgit TYPE REF TO lcl_dot_abapgit. - FIELD-SYMBOLS: LIKE LINE OF lt_remote, - LIKE LINE OF lt_tadir, + FIELD-SYMBOLS LIKE LINE OF rt_results. + + + rt_results = calculate_status( + it_local = io_repo->get_files_local( io_log ) + it_remote = io_repo->get_files_remote( ) + it_cur_state = io_repo->get_local_checksums_per_file( ) ). + + lo_dot_abapgit = io_repo->get_dot_abapgit( ). + + " Remove ignored files, fix .abapgit + LOOP AT rt_results ASSIGNING . + lv_index = sy-tabix. + + IF lo_dot_abapgit->is_ignored( + iv_path = -path + iv_filename = -filename ) = abap_true. + DELETE rt_results INDEX lv_index. + ENDIF. + ENDLOOP. + + lcl_sap_package=>check( + io_log = io_log + it_results = rt_results + iv_start = lo_dot_abapgit->get_starting_folder( ) + iv_top = io_repo->get_package( ) ). + + ENDMETHOD. "status + + METHOD calculate_status. + + DATA: lt_remote LIKE it_remote, + lt_items TYPE ty_items_tt, + ls_item LIKE LINE OF lt_items, + lv_is_xml TYPE abap_bool, + lt_items_idx TYPE ty_items_ts, + lt_state_idx TYPE ty_file_signatures_ts. " Sorted by path+filename + + FIELD-SYMBOLS: LIKE LINE OF it_remote, LIKE LINE OF rt_results, - LIKE LINE OF lt_local, - LIKE LINE OF lt_files. + LIKE LINE OF it_local. - lt_remote = io_repo->get_files_remote( ). - lt_local = io_repo->get_files_local( io_log ). + lt_state_idx = it_cur_state. " Force sort it + lt_remote = it_remote. + SORT lt_remote BY path filename. - LOOP AT lt_remote ASSIGNING . - lcl_progress=>show( iv_key = 'Status' - iv_current = sy-tabix - iv_total = lines( lt_remote ) - iv_text = -filename ) ##NO_TEXT. - - SPLIT -filename AT '.' INTO lv_pre lv_type lv_ext. - TRANSLATE lv_pre TO UPPER CASE. - TRANSLATE lv_type TO UPPER CASE. - - IF lv_ext <> 'xml' OR strlen( lv_type ) <> 4. - CONTINUE. " current loop + " Process local files and new local files + LOOP AT it_local ASSIGNING . + APPEND INITIAL LINE TO rt_results ASSIGNING . + IF -item IS NOT INITIAL. + APPEND -item TO lt_items. " Collect for item index ENDIF. -* handle namespaces - REPLACE ALL OCCURRENCES OF '#' IN lv_pre WITH '/'. - - CLEAR ls_result. - ls_result-obj_type = lv_type. - ls_result-obj_name = lv_pre. - - CLEAR ls_item. - ls_item-obj_type = lv_type. - ls_item-obj_name = lv_pre. - - CLEAR lt_files. - LOOP AT lt_local ASSIGNING WHERE item = ls_item. - APPEND -file TO lt_files. - ENDLOOP. - - IF lt_files[] IS INITIAL. -* item does not exist locally - ls_result-filename = -filename. - APPEND ls_result TO rt_results. - CONTINUE. " current loop - ENDIF. - - LOOP AT lt_files ASSIGNING . - ls_result-filename = -filename. - ls_result-match = compare_files( it_repo = lt_remote - is_gen = ). - APPEND ls_result TO rt_results. - ENDLOOP. - ENDLOOP. - -* find files only existing remotely, including non abapGit related - LOOP AT lt_remote ASSIGNING . - READ TABLE rt_results WITH KEY filename = -filename - TRANSPORTING NO FIELDS. - IF sy-subrc <> 0. - IF io_repo->get_dot_abapgit( )->is_ignored( - iv_path = -path - iv_filename = -filename ) = abap_true. - CONTINUE. - ENDIF. - - CLEAR ls_result. - ls_result-match = abap_true. - ls_result-filename = -filename. - APPEND ls_result TO rt_results. + READ TABLE lt_remote ASSIGNING + WITH KEY path = -file-path filename = -file-filename + BINARY SEARCH. + IF sy-subrc = 0. " Exist local and remote + = build_existing( + is_local = + is_remote = + it_state = lt_state_idx ). + ASSERT -sha1 IS NOT INITIAL. + CLEAR -sha1. " Mark as processed + ELSE. " Only L exists + = build_new_local( is_local = ). ENDIF. ENDLOOP. -* add path information for files - LOOP AT lt_remote ASSIGNING . - READ TABLE rt_results ASSIGNING WITH KEY filename = -filename. - IF sy-subrc = 0. - -path = -path. - ENDIF. + " Complete item index for unmarked remote files + LOOP AT lt_remote ASSIGNING WHERE sha1 IS NOT INITIAL. + identify_object( EXPORTING iv_filename = -filename + IMPORTING es_item = ls_item + ev_is_xml = lv_is_xml ). + + CHECK lv_is_xml = abap_true. " Skip all but obj definitions + + ls_item-devclass = lcl_tadir=>get_object_package( + iv_object = ls_item-obj_type + iv_obj_name = ls_item-obj_name ). + APPEND ls_item TO lt_items. ENDLOOP. -* find objects only existing locally - lt_tadir = lcl_tadir=>read( io_repo->get_package( ) ). - LOOP AT lt_tadir ASSIGNING . - READ TABLE rt_results - WITH KEY obj_type = -object - obj_name = -obj_name - TRANSPORTING NO FIELDS. - IF sy-subrc <> 0. - ls_item-obj_type = -object. - ls_item-obj_name = -obj_name. - IF lcl_objects=>is_supported( ls_item ) = abap_false. - CONTINUE. - ENDIF. + SORT lt_items. " Default key - type, name, pkg + DELETE ADJACENT DUPLICATES FROM lt_items. + lt_items_idx = lt_items. " Self protection + UNIQUE records assertion - CLEAR ls_result. - ls_result-match = abap_true. - ls_result-obj_type = -object. - ls_result-obj_name = -obj_name. - APPEND ls_result TO rt_results. - ENDIF. - - LOOP AT rt_results ASSIGNING - WHERE obj_type = -object - AND obj_name = -obj_name - AND path IS INITIAL. -* new file added locally to existing object - -path = io_repo->get_dot_abapgit( )->get_starting_folder( ) && -path. - ENDLOOP. - ENDLOOP. - -* add package information - LOOP AT rt_results ASSIGNING WHERE NOT obj_type IS INITIAL. - ls_tadir = lcl_tadir=>read_single( iv_object = -obj_type - iv_obj_name = -obj_name ). - -package = ls_tadir-devclass. + " Process new remote files (marked above with empty SHA1) + LOOP AT lt_remote ASSIGNING WHERE sha1 IS NOT INITIAL. + APPEND INITIAL LINE TO rt_results ASSIGNING . + = build_new_remote( is_remote = + it_items = lt_items_idx + it_state = lt_state_idx ). ENDLOOP. SORT rt_results BY obj_type ASCENDING obj_name ASCENDING filename ASCENDING. - DELETE ADJACENT DUPLICATES FROM rt_results - COMPARING obj_type obj_name filename. - lcl_sap_package=>check( - io_log = io_log - it_results = rt_results - iv_start = io_repo->get_dot_abapgit( )->get_starting_folder( ) - iv_top = io_repo->get_package( ) ). + ENDMETHOD. "calculate_status. - ENDMETHOD. "status + METHOD identify_object. + + DATA: lv_name TYPE tadir-obj_name, + lv_type TYPE string, + lv_ext TYPE string. + + " Guess object type and name + SPLIT to_upper( iv_filename ) AT '.' INTO lv_name lv_type lv_ext. + + " Handle namespaces + REPLACE ALL OCCURRENCES OF '#' IN lv_name WITH '/'. + + CLEAR es_item. + es_item-obj_type = lv_type. + es_item-obj_name = lv_name. + ev_is_xml = boolc( lv_ext = 'XML' AND strlen( lv_type ) = 4 ). + + ENDMETHOD. "identify_object. + + METHOD build_existing. + + DATA: ls_file_sig LIKE LINE OF it_state. + + " Item + rs_result-obj_type = is_local-item-obj_type. + rs_result-obj_name = is_local-item-obj_name. + rs_result-package = is_local-item-devclass. + + " File + rs_result-path = is_local-file-path. + rs_result-filename = is_local-file-filename. + + " Match against current state + READ TABLE it_state INTO ls_file_sig + WITH KEY path = is_local-file-path filename = is_local-file-filename + BINARY SEARCH. + + IF sy-subrc = 0. + IF ls_file_sig-sha1 <> is_local-file-sha1. + rs_result-lstate = gc_state-modified. + ENDIF. + IF ls_file_sig-sha1 <> is_remote-sha1. + rs_result-rstate = gc_state-modified. + ENDIF. + rs_result-match = boolc( rs_result-lstate IS INITIAL AND rs_result-rstate IS INITIAL ). + ELSE. + " This is a strange situation. As both local and remote exist + " the state should also be present. Maybe this is a first run of the code. + " In this case just compare hashes directly and mark both changed + " the user will presumably decide what to do after checking the actual diff + rs_result-match = boolc( is_local-file-sha1 = is_remote-sha1 ). + IF rs_result-match = abap_false. + rs_result-lstate = gc_state-modified. + rs_result-rstate = gc_state-modified. + ENDIF. + ENDIF. + + ENDMETHOD. "build_existing + + METHOD build_new_local. + + " Item + rs_result-obj_type = is_local-item-obj_type. + rs_result-obj_name = is_local-item-obj_name. + rs_result-package = is_local-item-devclass. + + " File + rs_result-path = is_local-file-path. + rs_result-filename = is_local-file-filename. + + " Match + rs_result-match = abap_false. + rs_result-lstate = gc_state-added. + + ENDMETHOD. "build_new_local + + METHOD build_new_remote. + + DATA: ls_item LIKE LINE OF it_items, + ls_file_sig LIKE LINE OF it_state. + + " Common and default part + rs_result-path = is_remote-path. + rs_result-filename = is_remote-filename. + rs_result-match = abap_false. + rs_result-rstate = gc_state-added. + + identify_object( EXPORTING iv_filename = is_remote-filename + IMPORTING es_item = ls_item ). + + " Check if in item index + get package + READ TABLE it_items INTO ls_item + WITH KEY obj_type = ls_item-obj_type obj_name = ls_item-obj_name + BINARY SEARCH. + + IF sy-subrc = 0. + + " Completely new (xml, abap) and new file in an existing object + rs_result-obj_type = ls_item-obj_type. + rs_result-obj_name = ls_item-obj_name. + rs_result-package = ls_item-devclass. + + READ TABLE it_state INTO ls_file_sig + WITH KEY path = is_remote-path filename = is_remote-filename + BINARY SEARCH. + + " Existing file but from another package + " was not added during local file proc as was not in tadir for repo package + IF sy-subrc = 0. + IF ls_file_sig-sha1 = is_remote-sha1. + rs_result-match = abap_true. + CLEAR rs_result-rstate. + ELSE. + rs_result-rstate = gc_state-modified. + ENDIF. + + " Item is in state and in cache but with no package - it was deleted + IF ls_item-devclass IS INITIAL. + rs_result-match = abap_false. + rs_result-lstate = gc_state-deleted. + ENDIF. + ENDIF. + + ELSE. " Completely unknown file, probably non-abapgit + ASSERT 1 = 1. " No action, just follow defaults + ENDIF. + + ENDMETHOD. "build_new_remote ENDCLASS. "lcl_file_status IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_forms.prog.abap b/src/zabapgit_forms.prog.abap index cd8359a13..d40ba19e7 100644 --- a/src/zabapgit_forms.prog.abap +++ b/src/zabapgit_forms.prog.abap @@ -2,7 +2,6 @@ *& Include ZABAPGIT_FORMS *&---------------------------------------------------------------------* - *&---------------------------------------------------------------------* *& Form run *&---------------------------------------------------------------------* @@ -22,7 +21,7 @@ FORM run. ENDIF. TRY. - lcl_persistence_migrate=>run( ). + lcl_migrations=>run( ). lcl_app=>run( ). CATCH lcx_exception INTO lx_exception. MESSAGE lx_exception->mv_text TYPE 'E'. diff --git a/src/zabapgit_git.prog.abap b/src/zabapgit_git.prog.abap index 5a2c23569..08ebd1c45 100644 --- a/src/zabapgit_git.prog.abap +++ b/src/zabapgit_git.prog.abap @@ -34,12 +34,7 @@ CLASS lcl_git_transport DEFINITION FINAL. RETURNING VALUE(ro_branch_list) TYPE REF TO lcl_git_branch_list RAISING lcx_exception. - CLASS-METHODS class_constructor. - - PRIVATE SECTION. - CLASS-DATA: gv_agent TYPE string. - CONSTANTS: BEGIN OF c_service, receive TYPE string VALUE 'receive', "#EC NOTEXT upload TYPE string VALUE 'upload', "#EC NOTEXT @@ -48,7 +43,7 @@ CLASS lcl_git_transport DEFINITION FINAL. CLASS-METHODS branch_list IMPORTING iv_url TYPE string iv_service TYPE string - EXPORTING ei_client TYPE REF TO if_http_client + EXPORTING eo_client TYPE REF TO lcl_http_client eo_branch_list TYPE REF TO lcl_git_branch_list RAISING lcx_exception. @@ -56,7 +51,7 @@ CLASS lcl_git_transport DEFINITION FINAL. IMPORTING iv_url TYPE string iv_service TYPE string iv_branch_name TYPE string - EXPORTING ei_client TYPE REF TO if_http_client + EXPORTING eo_client TYPE REF TO lcl_http_client ev_branch TYPE ty_sha1 RAISING lcx_exception. @@ -65,30 +60,6 @@ CLASS lcl_git_transport DEFINITION FINAL. CHANGING cv_data TYPE xstring RAISING lcx_exception. - CLASS-METHODS set_headers - IMPORTING iv_url TYPE string - iv_service TYPE string - ii_client TYPE REF TO if_http_client - RAISING lcx_exception. - - CLASS-METHODS check_http_200 - IMPORTING ii_client TYPE REF TO if_http_client - RAISING lcx_exception. - - CLASS-METHODS send_receive - IMPORTING ii_client TYPE REF TO if_http_client - RAISING lcx_exception. - - CLASS-METHODS check_auth_requested - IMPORTING ii_client TYPE REF TO if_http_client - RETURNING VALUE(rv_auth_requested) TYPE abap_bool - RAISING lcx_exception. - - CLASS-METHODS acquire_login_details - IMPORTING ii_client TYPE REF TO if_http_client - iv_url TYPE string - RAISING lcx_exception. - ENDCLASS. "lcl_transport DEFINITION *----------------------------------------------------------------------* @@ -189,114 +160,6 @@ ENDCLASS. "lcl_pack DEFINITION *----------------------------------------------------------------------* CLASS lcl_git_transport IMPLEMENTATION. - METHOD class_constructor. - -* bitbucket require agent prefix = "git/" - gv_agent = 'git/abapGit-' && gc_abap_version. - - ENDMETHOD. "class_constructor - - METHOD set_headers. - - DATA: lv_value TYPE string. - - - ii_client->request->set_header_field( - name = '~request_method' - value = 'POST' ). - - lv_value = lcl_url=>path_name( iv_url ) && - '.git/git-' && - iv_service && - '-pack'. - ii_client->request->set_header_field( - name = '~request_uri' - value = lv_value ). - - lv_value = 'application/x-git-' - && iv_service && '-pack-request'. "#EC NOTEXT - ii_client->request->set_header_field( - name = 'Content-Type' - value = lv_value ). "#EC NOTEXT - - lv_value = 'application/x-git-' - && iv_service && '-pack-result'. "#EC NOTEXT - ii_client->request->set_header_field( - name = 'Accept' - value = lv_value ). "#EC NOTEXT - - ENDMETHOD. "set_headers - - METHOD check_http_200. - - DATA: lv_code TYPE i. - - - ii_client->response->get_status( - IMPORTING - code = lv_code ). - CASE lv_code. - WHEN 200. - RETURN. - WHEN 302. - lcx_exception=>raise( 'HTTP redirect, check URL' ). - WHEN 401. - lcx_exception=>raise( 'HTTP 401, unauthorized' ). - WHEN 403. - lcx_exception=>raise( 'HTTP 403, forbidden' ). - WHEN 404. - lcx_exception=>raise( 'HTTP 404, not found' ). - WHEN 415. - lcx_exception=>raise( 'HTTP 415, unsupported media type' ). - WHEN OTHERS. - lcx_exception=>raise( 'HTTP error code' ). - ENDCASE. - - ENDMETHOD. "http_200 - - METHOD check_auth_requested. - - DATA: lv_code TYPE i. - - ii_client->response->get_status( - IMPORTING - code = lv_code ). - IF lv_code = 401. - rv_auth_requested = abap_true. - ENDIF. - - ENDMETHOD. "check_auth_requested - - METHOD acquire_login_details. - DATA: - lv_default_user TYPE string, - lv_user TYPE string, - lv_pass TYPE string. - - lv_default_user = lcl_app=>user( )->get_repo_username( iv_url = iv_url ). - lv_user = lv_default_user. - - lcl_password_dialog=>popup( - EXPORTING - iv_repo_url = iv_url - CHANGING - cv_user = lv_user - cv_pass = lv_pass ). - - IF lv_user IS INITIAL. - lcx_exception=>raise( 'HTTP 401, unauthorized' ). - ENDIF. - - IF lv_user <> lv_default_user. - lcl_app=>user( )->set_repo_username( iv_url = iv_url iv_username = lv_user ). - ENDIF. - - ii_client->authenticate( - username = lv_user - password = lv_pass ). - - ENDMETHOD. "acquire_login_details - METHOD find_branch. DATA: lo_branch_list TYPE REF TO lcl_git_branch_list. @@ -306,7 +169,7 @@ CLASS lcl_git_transport IMPLEMENTATION. iv_url = iv_url iv_service = iv_service IMPORTING - ei_client = ei_client + eo_client = eo_client eo_branch_list = lo_branch_list ). IF ev_branch IS SUPPLIED. @@ -317,7 +180,7 @@ CLASS lcl_git_transport IMPLEMENTATION. METHOD branches. - DATA: li_client TYPE REF TO if_http_client. + DATA: lo_client TYPE REF TO lcl_http_client. lcl_git_transport=>branch_list( @@ -325,98 +188,33 @@ CLASS lcl_git_transport IMPLEMENTATION. iv_url = iv_url iv_service = c_service-upload IMPORTING - ei_client = li_client + eo_client = lo_client eo_branch_list = ro_branch_list ). - li_client->close( ). + + lo_client->close( ). ENDMETHOD. "branches METHOD branch_list. - DATA: lv_data TYPE string, - lv_uri TYPE string, - lv_expect_potentual_auth TYPE abap_bool. + DATA: lv_data TYPE string. - cl_http_client=>create_by_url( + eo_client = lcl_http=>create_by_url( + iv_url = iv_url + iv_service = iv_service ). + + lv_data = eo_client->get_cdata( ). + + CREATE OBJECT eo_branch_list EXPORTING - url = lcl_url=>host( iv_url ) - ssl_id = 'ANONYM' - IMPORTING - client = ei_client ). - - ei_client->request->set_cdata( '' ). - ei_client->request->set_header_field( - name = '~request_method' - value = 'GET' ). - ei_client->request->set_header_field( - name = 'user-agent' - value = gv_agent ). "#EC NOTEXT - lv_uri = lcl_url=>path_name( iv_url ) && - '.git/info/refs?service=git-' && - iv_service && - '-pack'. - ei_client->request->set_header_field( - name = '~request_uri' - value = lv_uri ). - - " Disable internal auth dialog (due to its unclarity) - ei_client->propertytype_logon_popup = if_http_client=>co_disabled. - - lv_expect_potentual_auth = boolc( - lcl_login_manager=>load( iv_uri = iv_url - ii_client = ei_client ) IS INITIAL ). - - send_receive( ei_client ). - IF lv_expect_potentual_auth = abap_true - AND check_auth_requested( ei_client ) = abap_true. - acquire_login_details( ii_client = ei_client iv_url = iv_url ). - send_receive( ei_client ). - ENDIF. - check_http_200( ei_client ). - - lcl_login_manager=>save( iv_uri = iv_url - ii_client = ei_client ). - - lv_data = ei_client->response->get_cdata( ). - create object eo_branch_list exporting iv_data = lv_data. + iv_data = lv_data. ENDMETHOD. "branch_list - METHOD send_receive. - - DATA lv_text TYPE string. - - ii_client->send( ). - ii_client->receive( - EXCEPTIONS - http_communication_failure = 1 - http_invalid_state = 2 - http_processing_failed = 3 - OTHERS = 4 ). - IF sy-subrc <> 0. - CASE sy-subrc. - WHEN 1. - " make sure: - " a) SSL is setup properly in STRUST - " b) no firewalls - " check trace file in transaction SMICM - lv_text = 'HTTP Communication Failure'. "#EC NOTEXT - WHEN 2. - lv_text = 'HTTP Invalid State'. "#EC NOTEXT - WHEN 3. - lv_text = 'HTTP Processing failed'. "#EC NOTEXT - WHEN OTHERS. - lv_text = 'Another error occured'. "#EC NOTEXT - ENDCASE. - lcx_exception=>raise( lv_text ). - ENDIF. - - ENDMETHOD. "send_receive - METHOD receive_pack. - DATA: li_client TYPE REF TO if_http_client, + DATA: lo_client TYPE REF TO lcl_http_client, lv_cmd_pkt TYPE string, lv_line TYPE string, lv_tmp TYPE xstring, @@ -432,14 +230,13 @@ CLASS lcl_git_transport IMPLEMENTATION. iv_service = c_service-receive iv_branch_name = iv_branch_name IMPORTING - ei_client = li_client ). + eo_client = lo_client ). - set_headers( + lo_client->set_headers( iv_url = iv_url - iv_service = c_service-receive - ii_client = li_client ). + iv_service = c_service-receive ). - lv_cap_list = 'report-status agent=' && gv_agent ##NO_TEXT. + lv_cap_list = 'report-status agent=' && lcl_http=>get_agent( ) ##NO_TEXT. lv_line = iv_old && ` ` && @@ -457,13 +254,7 @@ CLASS lcl_git_transport IMPLEMENTATION. CONCATENATE lv_tmp iv_pack INTO lv_xstring IN BYTE MODE. - li_client->request->set_data( lv_xstring ). - - send_receive( li_client ). - check_http_200( li_client ). - - lv_xstring = li_client->response->get_data( ). - li_client->close( ). + lv_xstring = lo_client->send_receive_close( lv_xstring ). lv_string = lcl_convert=>xstring_to_string_utf8( lv_xstring ). IF NOT lv_string CP '*unpack ok*'. @@ -512,7 +303,7 @@ CLASS lcl_git_transport IMPLEMENTATION. METHOD upload_pack. - DATA: li_client TYPE REF TO if_http_client, + DATA: lo_client TYPE REF TO lcl_http_client, lv_buffer TYPE string, lv_xstring TYPE xstring, lv_line TYPE string, @@ -531,7 +322,7 @@ CLASS lcl_git_transport IMPLEMENTATION. iv_service = c_service-upload iv_branch_name = io_repo->get_branch_name( ) IMPORTING - ei_client = li_client + eo_client = lo_client ev_branch = ev_branch ). IF it_branches IS INITIAL. @@ -541,13 +332,12 @@ CLASS lcl_git_transport IMPLEMENTATION. lt_branches = it_branches. ENDIF. - set_headers( iv_url = io_repo->get_url( ) - iv_service = c_service-upload - ii_client = li_client ). + lo_client->set_headers( iv_url = io_repo->get_url( ) + iv_service = c_service-upload ). LOOP AT lt_branches FROM 1 ASSIGNING . IF sy-tabix = 1. - lv_capa = 'side-band-64k no-progress agent=' && gv_agent ##NO_TEXT. + lv_capa = 'side-band-64k no-progress multi_ack agent=' && lcl_http=>get_agent( ) ##NO_TEXT. lv_line = 'want' && ` ` && -sha1 && ` ` && lv_capa && gc_newline. "#EC NOTEXT ELSE. @@ -565,12 +355,7 @@ CLASS lcl_git_transport IMPLEMENTATION. && '0000' && '0009done' && gc_newline. -* do not use set_cdata as it modifies the Content-Type header field - li_client->request->set_data( lcl_convert=>string_to_xstring_utf8( lv_buffer ) ). - send_receive( li_client ). - check_http_200( li_client ). - lv_xstring = li_client->response->get_data( ). - li_client->close( ). + lv_xstring = lo_client->send_receive_close( lcl_convert=>string_to_xstring_utf8( lv_buffer ) ). parse( IMPORTING ev_pack = lv_pack CHANGING cv_data = lv_xstring ). @@ -1285,7 +1070,8 @@ CLASS lcl_git_porcelain DEFINITION FINAL FRIENDS ltcl_git_porcelain. IMPORTING io_repo TYPE REF TO lcl_repo_online is_comment TYPE ty_comment io_stage TYPE REF TO lcl_stage - RETURNING VALUE(rv_branch) TYPE ty_sha1 + EXPORTING ev_branch TYPE ty_sha1 + et_updated_files TYPE ty_file_signatures_tt RAISING lcx_exception. CLASS-METHODS create_branch @@ -1432,7 +1218,7 @@ CLASS lcl_git_porcelain IMPLEMENTATION. iv_data = lv_commit ). lcl_git_transport=>receive_pack( - iv_url = io_repo->get_url( ) + iv_url = io_repo->get_url( ) iv_old = io_stage->get_branch_sha1( ) iv_new = rv_branch iv_branch_name = io_stage->get_branch_name( ) @@ -1488,11 +1274,14 @@ CLASS lcl_git_porcelain IMPLEMENTATION. lt_branches TYPE lcl_git_branch_list=>ty_git_branch_list_tt, lt_stage TYPE lcl_stage=>ty_stage_tt. - FIELD-SYMBOLS: LIKE LINE OF lt_stage, - LIKE LINE OF lt_branches, - LIKE LINE OF lt_expanded. + FIELD-SYMBOLS: LIKE LINE OF lt_stage, + LIKE LINE OF et_updated_files, + LIKE LINE OF lt_branches, + LIKE LINE OF lt_expanded. + CLEAR et_updated_files. + IF io_stage->get_branch_sha1( ) = io_repo->get_sha1_remote( ). * objects cached in io_repo can be used, if pushing to the branch configured in repo lt_objects = io_repo->get_objects( ). @@ -1511,6 +1300,11 @@ CLASS lcl_git_porcelain IMPLEMENTATION. lt_stage = io_stage->get_all( ). LOOP AT lt_stage ASSIGNING . + + " Save file ref to updated files table + APPEND INITIAL LINE TO et_updated_files ASSIGNING . + MOVE-CORRESPONDING -file TO . + CASE -method. WHEN lcl_stage=>c_method-add. @@ -1531,11 +1325,17 @@ CLASS lcl_git_porcelain IMPLEMENTATION. IF -sha1 <> lv_sha1. -sha1 = lv_sha1. ENDIF. + + -sha1 = lv_sha1. "New sha1 + WHEN lcl_stage=>c_method-rm. DELETE lt_expanded WHERE name = -file-filename - AND path = -file-path. + AND path = -file-path. ASSERT sy-subrc = 0. + + CLEAR -sha1. " Mark as deleted + WHEN OTHERS. lcx_exception=>raise( 'stage method not supported, todo' ). ENDCASE. @@ -1543,7 +1343,7 @@ CLASS lcl_git_porcelain IMPLEMENTATION. lt_trees = build_trees( lt_expanded ). - rv_branch = receive_pack( is_comment = is_comment + ev_branch = receive_pack( is_comment = is_comment io_repo = io_repo it_trees = lt_trees it_blobs = lt_blobs @@ -1763,6 +1563,7 @@ CLASS lcl_git_porcelain IMPLEMENTATION. ls_file-path = iv_path. ls_file-filename = -name. ls_file-data = -data. + ls_file-sha1 = -sha1. APPEND ls_file TO ct_files. ENDIF. ENDLOOP. diff --git a/src/zabapgit_git_helpers.prog.abap b/src/zabapgit_git_helpers.prog.abap index 123d2ff8f..bbcb29962 100644 --- a/src/zabapgit_git_helpers.prog.abap +++ b/src/zabapgit_git_helpers.prog.abap @@ -268,11 +268,11 @@ CLASS lcl_git_branch_list IMPLEMENTATION. METHOD is_ignored. - IF iv_branch_name EQ 'refs/heads/gh-pages'. " Github pages + IF iv_branch_name = 'refs/heads/gh-pages'. " Github pages rv_ignore = abap_true. ENDIF. - IF iv_branch_name CP 'refs/pull/*' + IF iv_branch_name CP 'refs/pull/*' OR iv_branch_name CP 'refs/merge-requests/*' OR iv_branch_name CP 'refs/keep-around/*' OR iv_branch_name CP 'refs/tmp/*'. @@ -302,7 +302,6 @@ CLASS lcl_git_branch_list IMPLEMENTATION. IF iv_branch_name CP 'refs/tags/*'. rv_type = c_type-tag. - RETURN. ENDIF. ENDMETHOD. "get_type diff --git a/src/zabapgit_gui.prog.abap b/src/zabapgit_gui.prog.abap index cf23604e8..b5397ea7d 100644 --- a/src/zabapgit_gui.prog.abap +++ b/src/zabapgit_gui.prog.abap @@ -2,81 +2,6 @@ *& Include ZABAPGIT_GUI *&---------------------------------------------------------------------* -*----------------------------------------------------------------------* -* CLASS lcl_gui_router DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_gui_router DEFINITION FINAL. - PUBLIC SECTION. - - METHODS on_event - 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. - - PRIVATE SECTION. - - METHODS get_page_by_name - IMPORTING iv_name TYPE clike - RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page - RAISING lcx_exception. - - METHODS get_page_diff - IMPORTING iv_getdata TYPE clike - RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page - RAISING lcx_exception. - - METHODS get_page_branch_overview - IMPORTING iv_getdata TYPE clike - RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page - RAISING lcx_exception. - - METHODS get_page_stage - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page - RAISING lcx_exception. - - METHODS get_page_db_by_name - IMPORTING iv_name TYPE clike - iv_getdata TYPE clike - RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page - RAISING lcx_exception. - - METHODS abapgit_installation - RAISING lcx_exception. - - METHODS repo_purge - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RAISING lcx_exception. - - METHODS repo_remove - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RAISING lcx_exception. - - METHODS repo_pull - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RAISING lcx_exception. - - METHODS reset - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RAISING lcx_exception. - - METHODS create_branch - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RAISING lcx_exception. - - METHODS db_delete - IMPORTING iv_getdata TYPE clike - RAISING lcx_exception. - - METHODS db_save - IMPORTING it_postdata TYPE cnht_post_data_tab - RAISING lcx_exception. - -ENDCLASS. - *----------------------------------------------------------------------* * CLASS lcl_gui DEFINITION *----------------------------------------------------------------------* @@ -103,9 +28,9 @@ CLASS lcl_gui DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. END OF ty_page_stack. DATA: mi_cur_page TYPE REF TO lif_gui_page, - mt_stack TYPE TABLE OF ty_page_stack, - mt_assets TYPE tt_w3urls, + mt_stack TYPE STANDARD TABLE OF ty_page_stack, mo_router TYPE REF TO lcl_gui_router, + mo_asset_man TYPE REF TO lcl_gui_asset_manager, mo_html_viewer TYPE REF TO cl_gui_html_viewer. METHODS constructor @@ -114,28 +39,41 @@ CLASS lcl_gui DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. METHODS startup RAISING lcx_exception. - METHODS cache_image - IMPORTING iv_url TYPE w3url - iv_base64 TYPE string. - METHODS cache_html - IMPORTING iv_html TYPE string + IMPORTING iv_text TYPE string + RETURNING VALUE(rv_url) TYPE w3url. + + METHODS cache_asset + IMPORTING iv_text TYPE string OPTIONAL + iv_xdata TYPE xstring OPTIONAL + iv_url TYPE w3url OPTIONAL + iv_type TYPE c + iv_subtype TYPE c RETURNING VALUE(rv_url) TYPE w3url. METHODS render RAISING lcx_exception. + METHODS get_current_page_name + RETURNING VALUE(rv_page_name) TYPE string. + METHODS call_page IMPORTING ii_page TYPE REF TO lif_gui_page iv_with_bookmark TYPE abap_bool DEFAULT abap_false + iv_replacing TYPE abap_bool DEFAULT abap_false RAISING lcx_exception. + METHODS handle_action + IMPORTING action TYPE c + frame TYPE c OPTIONAL + getdata TYPE c OPTIONAL + postdata TYPE cnht_post_data_tab OPTIONAL + query_table TYPE cnht_query_table OPTIONAL. + ENDCLASS. "lcl_gui DEFINITION *----------------------------------------------------------------------* -* CLASS lcl_view IMPLEMENTATION -*----------------------------------------------------------------------* -* +* CLASS lcl_gui IMPLEMENTATION *----------------------------------------------------------------------* CLASS lcl_gui IMPLEMENTATION. @@ -145,7 +83,7 @@ CLASS lcl_gui IMPLEMENTATION. ENDMETHOD. "constructor - METHOD on_event. + METHOD handle_action. DATA: lx_exception TYPE REF TO lcx_exception, li_page TYPE REF TO lif_gui_page, @@ -155,23 +93,25 @@ CLASS lcl_gui IMPLEMENTATION. IF mi_cur_page IS BOUND. mi_cur_page->on_event( EXPORTING - iv_action = action - iv_getdata = getdata - it_postdata = postdata + iv_action = action + iv_prev_page = get_current_page_name( ) + iv_getdata = getdata + it_postdata = postdata IMPORTING - ei_page = li_page - ev_state = lv_state ). + ei_page = li_page + ev_state = lv_state ). ENDIF. IF lv_state IS INITIAL. mo_router->on_event( EXPORTING - iv_action = action - iv_getdata = getdata - it_postdata = postdata + iv_action = action + iv_prev_page = get_current_page_name( ) + iv_getdata = getdata + it_postdata = postdata IMPORTING - ei_page = li_page - ev_state = lv_state ). + ei_page = li_page + ev_state = lv_state ). ENDIF. CASE lv_state. @@ -181,6 +121,8 @@ CLASS lcl_gui IMPLEMENTATION. call_page( li_page ). WHEN gc_event_state-new_page_w_bookmark. call_page( ii_page = li_page iv_with_bookmark = abap_true ). + WHEN gc_event_state-new_page_replacing. + call_page( ii_page = li_page iv_replacing = abap_true ). WHEN gc_event_state-go_back. back( ). WHEN gc_event_state-go_back_to_bookmark. @@ -188,14 +130,27 @@ CLASS lcl_gui IMPLEMENTATION. WHEN gc_event_state-no_more_act. " Do nothing, handling completed WHEN OTHERS. - lcx_exception=>raise( 'Unknown action' ). + lcx_exception=>raise( |Unknown action: { action }| ). ENDCASE. CATCH lcx_exception INTO lx_exception. ROLLBACK WORK. MESSAGE lx_exception->mv_text TYPE 'S' DISPLAY LIKE 'E'. + CATCH lcx_cancel ##NO_HANDLER. + " Do nothing = gc_event_state-no_more_act ENDTRY. + ENDMETHOD. "handle_action + + METHOD on_event. + + handle_action( + action = action + frame = frame + getdata = getdata + postdata = postdata + query_table = query_table ). + ENDMETHOD. "on_event METHOD back. @@ -231,26 +186,14 @@ CLASS lcl_gui IMPLEMENTATION. METHOD call_page. - DATA: lt_assets TYPE tt_web_assets, - ls_stack TYPE ty_page_stack. - FIELD-SYMBOLS LIKE LINE OF lt_assets. + DATA: ls_stack TYPE ty_page_stack. - IF NOT mi_cur_page IS INITIAL. + IF iv_replacing = abap_false AND NOT mi_cur_page IS INITIAL. ls_stack-page = mi_cur_page. ls_stack-bookmark = iv_with_bookmark. APPEND ls_stack TO mt_stack. ENDIF. - lt_assets = ii_page->get_assets( ). - IF lines( lt_assets ) > 0. - LOOP AT lt_assets ASSIGNING . - READ TABLE mt_assets TRANSPORTING NO FIELDS WITH KEY table_line = -url. - CHECK sy-subrc IS NOT INITIAL. - APPEND -url TO mt_assets. - cache_image( iv_url = -url iv_base64 = -content ). - ENDLOOP. - ENDIF. - mi_cur_page = ii_page. render( ). @@ -258,27 +201,50 @@ CLASS lcl_gui IMPLEMENTATION. METHOD go_home. - on_event( action = 'main' ) ##NO_TEXT. + on_event( action = |{ gc_action-go_main }| ). " doesn't accept strings directly ENDMETHOD. "go_home METHOD startup. DATA: lt_events TYPE cntl_simple_events, - ls_event LIKE LINE OF lt_events. + ls_event LIKE LINE OF lt_events, + lt_assets TYPE tt_web_assets. + + FIELD-SYMBOLS LIKE LINE OF lt_assets. CREATE OBJECT mo_router. + CREATE OBJECT mo_asset_man. CREATE OBJECT mo_html_viewer EXPORTING query_table_disabled = abap_true parent = cl_gui_container=>screen0. - CLEAR ls_event. - ls_event-eventid = mo_html_viewer->m_id_sapevent. + cache_asset( iv_xdata = mo_asset_man->get_asset( 'css_common' ) + iv_url = 'css/common.css' + iv_type = 'text' + iv_subtype = 'css' ). + + cache_asset( iv_xdata = mo_asset_man->get_asset( 'js_common' ) + iv_url = 'js/common.js' + iv_type = 'text' + iv_subtype = 'javascript' ). + + lt_assets = mo_asset_man->get_images( ). + IF lines( lt_assets ) > 0. + LOOP AT lt_assets ASSIGNING . + cache_asset( iv_xdata = -content + iv_url = -url + iv_type = 'image' + iv_subtype = 'png' ). + ENDLOOP. + ENDIF. + + ls_event-eventid = mo_html_viewer->m_id_sapevent. ls_event-appl_event = abap_true. APPEND ls_event TO lt_events. - mo_html_viewer->set_registered_events( lt_events ). + mo_html_viewer->set_registered_events( lt_events ). SET HANDLER me->on_event FOR mo_html_viewer. ENDMETHOD. "startup @@ -295,866 +261,68 @@ CLASS lcl_gui IMPLEMENTATION. METHOD cache_html. - DATA: lt_data TYPE TABLE OF text200. - - CALL FUNCTION 'SCMS_STRING_TO_FTEXT' - EXPORTING - text = iv_html - TABLES - ftext_tab = lt_data. - - mo_html_viewer->load_data( - IMPORTING - assigned_url = rv_url - CHANGING - data_table = lt_data ). + rv_url = cache_asset( iv_text = iv_text + iv_type = 'text' + iv_subtype = 'html' ). ENDMETHOD. "cache_html - METHOD cache_image. + METHOD cache_asset. - DATA lv_xtmp TYPE xstring. - DATA lv_size TYPE int4. - DATA lt_xdata TYPE TABLE OF w3_mime. " RAW255 + DATA: lv_xstr TYPE xstring, + lt_xdata TYPE TABLE OF w3_mime, " RAW255 + lv_size TYPE int4. - CALL FUNCTION 'SSFC_BASE64_DECODE' - EXPORTING - b64data = iv_base64 - IMPORTING - bindata = lv_xtmp - EXCEPTIONS - OTHERS = 1. + ASSERT iv_text IS SUPPLIED OR iv_xdata IS SUPPLIED. - ASSERT sy-subrc = 0. " Image data error + IF iv_text IS SUPPLIED. " String input + + CALL FUNCTION 'SCMS_STRING_TO_XSTRING' + EXPORTING + text = iv_text + IMPORTING + buffer = lv_xstr + EXCEPTIONS + OTHERS = 1. + ASSERT sy-subrc = 0. + + ELSE. " Raw input + lv_xstr = iv_xdata. + ENDIF. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING - buffer = lv_xtmp + buffer = lv_xstr IMPORTING output_length = lv_size TABLES binary_tab = lt_xdata. mo_html_viewer->load_data( - EXPORTING type = 'image' - subtype = 'png' - size = lv_size - url = iv_url - CHANGING data_table = lt_xdata - EXCEPTIONS OTHERS = 1 ) ##NO_TEXT. + EXPORTING + type = iv_type + subtype = iv_subtype + size = lv_size + url = iv_url + IMPORTING + assigned_url = rv_url + CHANGING + data_table = lt_xdata + EXCEPTIONS + OTHERS = 1 ) ##NO_TEXT. ASSERT sy-subrc = 0. " Image data error - ENDMETHOD. "cache_image + ENDMETHOD. " cache_asset. -ENDCLASS. "lcl_gui IMPLEMENTATION + METHOD get_current_page_name. + IF mi_cur_page IS BOUND. + rv_page_name = + cl_abap_classdescr=>describe_by_object_ref( mi_cur_page + )->get_relative_name( ). + SHIFT rv_page_name LEFT DELETING LEADING 'LCL_GUI_'. + ENDIF." ELSE - return is empty => initial page -CLASS lcl_gui_page_explore DEFINITION FINAL INHERITING FROM lcl_gui_page_super. - PUBLIC SECTION. - METHODS lif_gui_page~render REDEFINITION. + ENDMETHOD. "get_current_page_name -ENDCLASS. "lcl_gui_page_explore DEFINITION - -CLASS lcl_gui_page_explore IMPLEMENTATION. - - METHOD lif_gui_page~render. - - CREATE OBJECT ro_html. - ro_html->add( redirect( 'http://larshp.github.io/abapGit/explore.html' ) ). - - ENDMETHOD. - -ENDCLASS. "lcl_gui_page_explore IMPLEMENTATION - -CLASS lcl_gui_page_diff DEFINITION FINAL INHERITING FROM lcl_gui_page_super. - - PUBLIC SECTION. - METHODS: constructor - IMPORTING - is_local TYPE ty_file - is_remote TYPE ty_file. - - METHODS lif_gui_page~render REDEFINITION. - - PRIVATE SECTION. - DATA: mv_filename TYPE string, - mo_diff TYPE REF TO lcl_diff. - - METHODS styles RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. - METHODS render_head RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. - METHODS render_diff RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. - METHODS render_lines RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. - -ENDCLASS. - -CLASS lcl_gui_page_diff IMPLEMENTATION. - - METHOD constructor. - super->constructor( ). - - mv_filename = is_local-filename. - - CREATE OBJECT mo_diff - EXPORTING - iv_local = is_local-data - iv_remote = is_remote-data. - - ENDMETHOD. - - METHOD styles. - DATA lo_html TYPE REF TO lcl_html_helper. - CREATE OBJECT lo_html. - - lo_html->add( '/* DIFF */' ). "#EC NOTEXT - lo_html->add( 'div.diff {' ). "#EC NOTEXT - lo_html->add( ' background-color: #f2f2f2;' ). "#EC NOTEXT - lo_html->add( ' padding: 0.7em ' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'div.diff_head {' ). "#EC NOTEXT - lo_html->add( ' border-bottom: 1px solid #DDD;' ). "#EC NOTEXT - lo_html->add( ' padding-bottom: 0.7em;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'span.diff_name {' ). "#EC NOTEXT - lo_html->add( ' padding-left: 0.5em;' ). "#EC NOTEXT - lo_html->add( ' color: grey;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'span.diff_name strong {' ). "#EC NOTEXT - lo_html->add( ' color: #333;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'span.diff_banner {' ). "#EC NOTEXT - lo_html->add( ' border-style: solid;' ). "#EC NOTEXT - lo_html->add( ' border-width: 1px;' ). "#EC NOTEXT - lo_html->add( ' border-radius: 3px;' ). "#EC NOTEXT - lo_html->add( ' padding-left: 0.3em;' ). "#EC NOTEXT - lo_html->add( ' padding-right: 0.3em;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( '.diff_ins {' ). "#EC NOTEXT - lo_html->add( ' border-color: #38e038;' ). "#EC NOTEXT - lo_html->add( ' background-color: #91ee91 !important;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( '.diff_del {' ). "#EC NOTEXT - lo_html->add( ' border-color: #ff8093;' ). "#EC NOTEXT - lo_html->add( ' background-color: #ffb3be !important;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( '.diff_upd {' ). "#EC NOTEXT - lo_html->add( ' border-color: #dada00;' ). "#EC NOTEXT - lo_html->add( ' background-color: #ffffb3 !important;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'div.diff_content {' ). "#EC NOTEXT - lo_html->add( ' background: #fff;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - - " Table part - lo_html->add( '/* DIFF TABLE */' ). "#EC NOTEXT - lo_html->add( 'table.diff_tab {' ). "#EC NOTEXT - lo_html->add( ' font-family: Consolas, Courier, monospace;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'table.diff_tab th {' ). "#EC NOTEXT - lo_html->add( ' color: grey;' ). "#EC NOTEXT - lo_html->add( ' text-align: left;' ). "#EC NOTEXT - lo_html->add( ' font-weight: normal;' ). "#EC NOTEXT - lo_html->add( ' padding: 0.5em;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'table.diff_tab td {' ). "#EC NOTEXT - lo_html->add( ' color: #444;' ). "#EC NOTEXT - lo_html->add( ' padding-left: 0.5em;' ). "#EC NOTEXT - lo_html->add( ' padding-right: 0.5em;' ). "#EC NOTEXT - lo_html->add( ' font-size: 12pt;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'table.diff_tab td.num, th.num {' ). "#EC NOTEXT - lo_html->add( ' text-align: right;' ). "#EC NOTEXT - lo_html->add( ' color: #ccc;' ). "#EC NOTEXT - lo_html->add( ' border-left: 1px solid #eee;' ). "#EC NOTEXT - lo_html->add( ' border-right: 1px solid #eee;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'table.diff_tab td.cmd, th.cmd {' ). "#EC NOTEXT - lo_html->add( ' text-align: center !important;' ). "#EC NOTEXT - lo_html->add( ' white-space: nowrap;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - lo_html->add( 'table.diff_tab tr.diff_nav_line {'). "#EC NOTEXT - lo_html->add( ' background-color: #edf2f9;'). "#EC NOTEXT - lo_html->add( '}'). "#EC NOTEXT - lo_html->add( 'table.diff_tab tr.diff_nav_line td {'). "#EC NOTEXT - lo_html->add( ' color: #ccc;'). "#EC NOTEXT - lo_html->add( '}'). "#EC NOTEXT - lo_html->add( 'table.diff_tab code {' ). "#EC NOTEXT - lo_html->add( ' font-family: inherit;' ). "#EC NOTEXT - lo_html->add( ' white-space: pre;' ). "#EC NOTEXT - lo_html->add( '}' ). "#EC NOTEXT - - ro_html = lo_html. - ENDMETHOD. - - METHOD render_head. - DATA: lo_html TYPE REF TO lcl_html_helper, - ls_stats TYPE lcl_diff=>ty_count. - - CREATE OBJECT lo_html. - - ls_stats = mo_diff->stats( ). - - lo_html->add( '
' ). "#EC NOTEXT - lo_html->add( |+ { ls_stats-insert }| ). - lo_html->add( |- { ls_stats-delete }| ). - lo_html->add( |~ { ls_stats-update }| ). - lo_html->add( '' ). "#EC NOTEXT - lo_html->add( |{ mv_filename }| ). - lo_html->add( '' ). "#EC NOTEXT - lo_html->add( '
' ). "#EC NOTEXT - - ro_html = lo_html. - ENDMETHOD. - - METHOD render_diff. - - CREATE OBJECT ro_html. - - ro_html->add( '
' ). "#EC NOTEXT - ro_html->add( render_head( ) ). - - " Content - ro_html->add( '
' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( render_lines( ) ). - ro_html->add( '
@LOCAL@REMOTE
' ). "#EC NOTEXT - ro_html->add( '
' ). "#EC NOTEXT - - ro_html->add( '
' ). "#EC NOTEXT - - ENDMETHOD. - - METHOD render_lines. - - DATA: lt_diffs TYPE lcl_diff=>ty_diffs_tt, - lv_local TYPE string, - lv_remote TYPE string, - lv_attr_local TYPE string, - lv_attr_remote TYPE string, - lv_beacon TYPE string, - lv_insert_nav TYPE abap_bool. - - FIELD-SYMBOLS LIKE LINE OF lt_diffs. - - - CREATE OBJECT ro_html. - lt_diffs = mo_diff->get( ). - - LOOP AT lt_diffs ASSIGNING . - IF -short = abap_false. - lv_insert_nav = abap_true. - CONTINUE. - ENDIF. - - IF lv_insert_nav = abap_true. " Insert separator line with navigation - IF -beacon > 0. - READ TABLE mo_diff->mt_beacons INTO lv_beacon INDEX -beacon. - ELSE. - lv_beacon = '---'. - ENDIF. - - ro_html->add( ''). - ro_html->add( '' ). - ro_html->add( |@@ { -local_line } @@ { lv_beacon }| ). - ro_html->add( '' ). - lv_insert_nav = abap_false. - ENDIF. - - lv_local = escape( val = -local format = cl_abap_format=>e_html_attr ). - lv_remote = escape( val = -remote format = cl_abap_format=>e_html_attr ). - - CLEAR: lv_attr_local, lv_attr_remote. " Class for changed lines - CASE -result. - WHEN lcl_diff=>c_diff-insert. - lv_attr_local = ' class="diff_ins"'. "#EC NOTEXT - WHEN lcl_diff=>c_diff-delete. - lv_attr_remote = ' class="diff_del"'. "#EC NOTEXT - WHEN lcl_diff=>c_diff-update. - lv_attr_local = ' class="diff_upd"'. "#EC NOTEXT - lv_attr_remote = ' class="diff_upd"'. "#EC NOTEXT - ENDCASE. - - ro_html->add( '' ). "#EC NOTEXT - ro_html->add( |{ -local_line }| ). "#EC NOTEXT - ro_html->add( |{ lv_local }| ). "#EC NOTEXT - ro_html->add( |{ -remote_line }| ). "#EC NOTEXT - ro_html->add( |{ lv_remote }| ). "#EC NOTEXT - ro_html->add( '' ). "#EC NOTEXT - - ENDLOOP. - - ENDMETHOD. - - METHOD lif_gui_page~render. - - CREATE OBJECT ro_html. - - ro_html->add( header( io_include_style = styles( ) ) ). - ro_html->add( title( 'DIFF' ) ). - ro_html->add( render_diff( ) ). - ro_html->add( footer( ) ). - - ENDMETHOD. - -ENDCLASS. - -*----------------------------------------------------------------------* -* CLASS lcl_gui_router IMPLEMENTATION -*----------------------------------------------------------------------* -CLASS lcl_gui_router IMPLEMENTATION. - - METHOD on_event. - - DATA: lv_url TYPE string, - lv_key TYPE lcl_persistence_repo=>ty_repo-key, - ls_item TYPE ty_item. - - - CASE iv_action. - " General routing - WHEN 'main' - OR 'explore' - OR 'db' - OR 'background_run'. - ei_page = get_page_by_name( iv_action ). - ev_state = gc_event_state-new_page. - WHEN 'background'. - lv_key = iv_getdata. - CREATE OBJECT ei_page TYPE lcl_gui_page_background - EXPORTING - iv_key = lv_key. - ev_state = gc_event_state-new_page. - WHEN 'abapgithome'. - cl_gui_frontend_services=>execute( EXPORTING document = gc_abapgit_homepage - EXCEPTIONS OTHERS = 1 ). - IF sy-subrc <> 0. - lcx_exception=>raise( 'Opening page in external browser failed.' ). - ENDIF. - ev_state = gc_event_state-no_more_act. - WHEN 'abapgit_installation'. - abapgit_installation( ). - ev_state = gc_event_state-re_render. - WHEN 'jump'. - lcl_html_action_utils=>jump_decode( EXPORTING iv_string = iv_getdata - IMPORTING ev_obj_type = ls_item-obj_type - ev_obj_name = ls_item-obj_name ). - lcl_objects=>jump( ls_item ). - ev_state = gc_event_state-no_more_act. - WHEN 'diff'. - ei_page = get_page_diff( iv_getdata ). - ev_state = gc_event_state-new_page. - - " DB actions - WHEN 'db_display' OR 'db_edit'. - ei_page = get_page_db_by_name( iv_name = iv_action iv_getdata = iv_getdata ). - ev_state = gc_event_state-new_page. - WHEN 'db_delete'. - db_delete( iv_getdata = iv_getdata ). - ev_state = gc_event_state-re_render. - WHEN 'db_save'. - db_save( it_postdata ). - ev_state = gc_event_state-go_back. - - " Repository state actions - WHEN 'uninstall'. - lv_key = iv_getdata. - repo_purge( lv_key ). - ev_state = gc_event_state-re_render. - WHEN 'remove'. - lv_key = iv_getdata. - repo_remove( lv_key ). - ev_state = gc_event_state-re_render. - WHEN 'zipimport'. - lv_key = iv_getdata. - lcl_zip=>import( lv_key ). - ev_state = gc_event_state-re_render. - WHEN 'zipexport'. - lv_key = iv_getdata. - lcl_zip=>export( lcl_app=>repo_srv( )->get( lv_key ) ). - ev_state = gc_event_state-no_more_act. - WHEN 'files_commit'. "TODO refactor name ? - lv_key = iv_getdata. - lcl_zip=>export( io_repo = lcl_app=>repo_srv( )->get( lv_key ) - iv_zip = abap_false ). - ev_state = gc_event_state-no_more_act. - WHEN 'packagezip'. - lcl_popups=>repo_package_zip( ). - ev_state = gc_event_state-no_more_act. - WHEN 'transportzip'. - lcl_transport=>zip( ). - ev_state = gc_event_state-no_more_act. - WHEN 'refresh'. - lv_key = iv_getdata. - lcl_app=>repo_srv( )->get( lv_key )->refresh( ). - ev_state = gc_event_state-re_render. - - " explore page - WHEN 'install'. - lv_url = iv_getdata. - lcl_popups=>repo_clone( lv_url ). - ev_state = gc_event_state-re_render. - - " Repository online actions - WHEN 'pull'. - lv_key = iv_getdata. - repo_pull( lv_key ). - ev_state = gc_event_state-re_render. - WHEN 'stage'. - lv_key = iv_getdata. - ei_page = get_page_stage( lv_key ). - ev_state = gc_event_state-new_page_w_bookmark. - WHEN 'reset'. - lv_key = iv_getdata. - reset( lv_key ). - ev_state = gc_event_state-re_render. - WHEN 'create_branch'. - lv_key = iv_getdata. - create_branch( lv_key ). - ev_state = gc_event_state-re_render. - WHEN 'branch_overview'. - ei_page = get_page_branch_overview( iv_getdata ). - ev_state = gc_event_state-new_page. - WHEN OTHERS. - ev_state = gc_event_state-not_handled. - ENDCASE. - ENDMETHOD. " on_event - - METHOD get_page_by_name. - - DATA: lv_page_class TYPE string, - lv_message TYPE string. - - lv_page_class = |LCL_GUI_PAGE_{ to_upper( iv_name ) }|. - - TRY. - CREATE OBJECT ri_page TYPE (lv_page_class). - CATCH cx_sy_create_object_error. - lv_message = |Cannot create page class { lv_page_class }|. - lcx_exception=>raise( lv_message ). - ENDTRY. - - ENDMETHOD. " get_page_by_name - - METHOD get_page_db_by_name. - - DATA: lv_page_class TYPE string, - lv_message TYPE string, - ls_key TYPE lcl_persistence_db=>ty_content. - - lv_page_class = |LCL_GUI_PAGE_{ to_upper( iv_name ) }|. - ls_key = lcl_html_action_utils=>dbkey_decode( iv_getdata ). - - TRY. - CREATE OBJECT ri_page TYPE (lv_page_class) - EXPORTING - is_key = ls_key. - - CATCH cx_sy_create_object_error. - lv_message = |Cannot create page class { lv_page_class }|. - lcx_exception=>raise( lv_message ). - ENDTRY. - - ENDMETHOD. " get_page_db_by_name - - METHOD get_page_branch_overview. - - DATA: lo_repo TYPE REF TO lcl_repo_online, - lo_page TYPE REF TO lcl_gui_page_branch_overview, - lv_key TYPE lcl_persistence_repo=>ty_repo-key. - - - lv_key = iv_getdata. - - lo_repo ?= lcl_app=>repo_srv( )->get( lv_key ). - - CREATE OBJECT lo_page - EXPORTING - io_repo = lo_repo. - - ri_page = lo_page. - - ENDMETHOD. - - METHOD get_page_diff. - - DATA: lt_remote TYPE ty_files_tt, - lt_local TYPE ty_files_item_tt, - lo_page TYPE REF TO lcl_gui_page_diff, - lo_repo TYPE REF TO lcl_repo_online, - ls_file TYPE ty_repo_file, - lv_key TYPE lcl_persistence_repo=>ty_repo-key. - - FIELD-SYMBOLS: LIKE LINE OF lt_remote, - LIKE LINE OF lt_local. - - lcl_html_action_utils=>file_decode( EXPORTING iv_string = iv_getdata - IMPORTING ev_key = lv_key - eg_file = ls_file ). - - lo_repo ?= lcl_app=>repo_srv( )->get( lv_key ). - lt_remote = lo_repo->get_files_remote( ). - lt_local = lo_repo->get_files_local( ). - - READ TABLE lt_remote ASSIGNING - WITH KEY filename = ls_file-filename - path = ls_file-path. - IF sy-subrc <> 0. - lcx_exception=>raise( 'file not found remotely' ). - ENDIF. - - READ TABLE lt_local ASSIGNING - WITH KEY file-filename = ls_file-filename - file-path = ls_file-path. - IF sy-subrc <> 0. - lcx_exception=>raise( 'file not found locally' ). - ENDIF. - - CREATE OBJECT lo_page - EXPORTING - is_local = -file - is_remote = . - - ri_page = lo_page. - - ENDMETHOD. - - METHOD abapgit_installation. - - CONSTANTS lc_package_abapgit TYPE devclass VALUE '$ABAPGIT'. - CONSTANTS lc_package_plugins TYPE devclass VALUE '$ABAPGIT_PLUGINS'. - - DATA lv_text TYPE c LENGTH 100. - DATA lv_answer TYPE c LENGTH 1. - DATA lo_repo TYPE REF TO lcl_repo_online. - DATA lv_url TYPE string. - DATA lv_target_package TYPE devclass. - - lv_text = |Installing current version ABAPGit to package { lc_package_abapgit } | - && |and plugins to { lc_package_plugins }|. - - CALL FUNCTION 'POPUP_TO_CONFIRM' - EXPORTING - titlebar = 'Install abapGit' - text_question = lv_text - text_button_1 = 'Continue' - text_button_2 = 'Cancel' - default_button = '2' - display_cancel_button = abap_false - IMPORTING - answer = lv_answer ##no_text. - IF lv_answer <> '1'. - RETURN. ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - ENDIF. - - DO 2 TIMES. - CASE sy-index. - WHEN 1. - lv_url = 'https://github.com/larshp/abapGit.git'. - lv_target_package = lc_package_abapgit. - WHEN 2. - lv_url = 'https://github.com/larshp/abapGit-plugins.git' ##no_text. - lv_target_package = lc_package_plugins. - ENDCASE. - - IF abap_false = lcl_app=>repo_srv( )->is_repo_installed( - iv_url = lv_url - iv_target_package = lv_target_package ). - - lcl_sap_package=>create_local( lv_target_package ). - - lo_repo = lcl_app=>repo_srv( )->new_online( - iv_url = lv_url - iv_branch_name = 'refs/heads/master' "TODO replace with HEAD ? - iv_package = lv_target_package ) ##NO_TEXT. - - lo_repo->status( ). " check for errors - lo_repo->deserialize( ). - ENDIF. - ENDDO. - - COMMIT WORK. - - ENDMETHOD. "abapgit_installation - - METHOD repo_purge. - - DATA: lt_tadir TYPE ty_tadir_tt, - lv_count TYPE c LENGTH 3, - lv_answer TYPE c LENGTH 1, - lo_repo TYPE REF TO lcl_repo, - lv_package TYPE devclass, - lv_question TYPE c LENGTH 100. - - - lo_repo = lcl_app=>repo_srv( )->get( iv_key ). - lv_package = lo_repo->get_package( ). - - lt_tadir = lcl_tadir=>read( lv_package ). - - IF lines( lt_tadir ) > 0. - lv_count = lines( lt_tadir ). - - CONCATENATE 'This will delete all objects in package' lv_package - INTO lv_question - SEPARATED BY space. "#EC NOTEXT - - CONCATENATE lv_question '(' lv_count 'objects)' - INTO lv_question - SEPARATED BY space. "#EC NOTEXT - - CALL FUNCTION 'POPUP_TO_CONFIRM' - EXPORTING - titlebar = 'Uninstall' - text_question = lv_question - text_button_1 = 'Delete' - icon_button_1 = 'ICON_DELETE' - text_button_2 = 'Cancel' - icon_button_2 = 'ICON_CANCEL' - default_button = '2' - display_cancel_button = abap_false - IMPORTING - answer = lv_answer - EXCEPTIONS - text_not_found = 1 - OTHERS = 2. "#EC NOTEXT - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from POPUP_TO_CONFIRM' ). - ENDIF. - - IF lv_answer = '2'. - RETURN. - ENDIF. - - lcl_objects=>delete( lt_tadir ). - - ENDIF. - - lcl_app=>repo_srv( )->delete( lo_repo ). - - COMMIT WORK. - - ENDMETHOD. "repo_purge - - METHOD repo_remove. - - DATA: lv_answer TYPE c LENGTH 1, - lo_repo TYPE REF TO lcl_repo, - lv_package TYPE devclass, - lv_question TYPE c LENGTH 100. - - - lo_repo = lcl_app=>repo_srv( )->get( iv_key ). - lv_package = lo_repo->get_package( ). - - CONCATENATE 'This will remove the repository reference to the package' - lv_package - INTO lv_question - SEPARATED BY space. "#EC NOTEXT - - CALL FUNCTION 'POPUP_TO_CONFIRM' - EXPORTING - titlebar = 'Remove' - text_question = lv_question - text_button_1 = 'Remove' - icon_button_1 = 'ICON_WF_UNLINK' - text_button_2 = 'Cancel' - icon_button_2 = 'ICON_CANCEL' - default_button = '2' - display_cancel_button = abap_false - IMPORTING - answer = lv_answer - EXCEPTIONS - text_not_found = 1 - OTHERS = 2. "#EC NOTEXT - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from POPUP_TO_CONFIRM' ). - ENDIF. - - IF lv_answer = '2'. - RETURN. - ENDIF. - - lcl_app=>repo_srv( )->delete( lo_repo ). - - COMMIT WORK. - - ENDMETHOD. "repo_remove - - METHOD reset. - - DATA: lo_repo TYPE REF TO lcl_repo_online, - lv_answer TYPE c LENGTH 1. - - - lo_repo ?= lcl_app=>repo_srv( )->get( iv_key ). - - CALL FUNCTION 'POPUP_TO_CONFIRM' - EXPORTING - titlebar = 'Warning' - text_question = 'Reset local objects?' - text_button_1 = 'Ok' - icon_button_1 = 'ICON_OKAY' - text_button_2 = 'Cancel' - icon_button_2 = 'ICON_CANCEL' - default_button = '2' - display_cancel_button = abap_false - IMPORTING - answer = lv_answer - EXCEPTIONS - text_not_found = 1 - OTHERS = 2. "#EC NOTEXT - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from POPUP_TO_CONFIRM' ). - ENDIF. - - IF lv_answer = '2'. - RETURN. - ENDIF. - - lo_repo->deserialize( ). - - ENDMETHOD. - - METHOD create_branch. - - DATA: lv_name TYPE string, - lv_cancel TYPE abap_bool, - lo_repo TYPE REF TO lcl_repo_online. - - - lo_repo ?= lcl_app=>repo_srv( )->get( iv_key ). - - lcl_popups=>create_branch_popup( - IMPORTING - ev_name = lv_name - ev_cancel = lv_cancel ). - IF lv_cancel = abap_true. - RETURN. - ENDIF. - - ASSERT lv_name CP 'refs/heads/+*'. - - lcl_git_porcelain=>create_branch( - io_repo = lo_repo - iv_name = lv_name - iv_from = lo_repo->get_sha1_local( ) ). - -* automatically switch to new branch - lo_repo->set_branch_name( lv_name ). - - MESSAGE 'Switched to new branch' TYPE 'S' ##NO_TEXT. - - ENDMETHOD. - - METHOD repo_pull. - - DATA: lo_repo TYPE REF TO lcl_repo_online. - - lo_repo ?= lcl_app=>repo_srv( )->get( iv_key ). - lo_repo->refresh( ). - lo_repo->deserialize( ). - - COMMIT WORK. - - ENDMETHOD. "pull - - METHOD get_page_stage. - - DATA: lo_repo TYPE REF TO lcl_repo_online, - lo_stage_page TYPE REF TO lcl_gui_page_stage. - - - lo_repo ?= lcl_app=>repo_srv( )->get( iv_key ). - - " force refresh on stage, to make sure the latest local and remote files are used - lo_repo->refresh( ). - - CREATE OBJECT lo_stage_page - EXPORTING - io_repo = lo_repo. - - ri_page = lo_stage_page. - - ENDMETHOD. - - METHOD db_delete. - - DATA: lv_answer TYPE c LENGTH 1, - ls_key TYPE lcl_persistence_db=>ty_content. - - - ls_key = lcl_html_action_utils=>dbkey_decode( iv_getdata ). - - CALL FUNCTION 'POPUP_TO_CONFIRM' - EXPORTING - titlebar = 'Warning' - text_question = 'Delete?' - text_button_1 = 'Ok' - icon_button_1 = 'ICON_DELETE' - text_button_2 = 'Cancel' - icon_button_2 = 'ICON_CANCEL' - default_button = '2' - display_cancel_button = abap_false - IMPORTING - answer = lv_answer - EXCEPTIONS - text_not_found = 1 - OTHERS = 2. "#EC NOTEXT - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from POPUP_TO_CONFIRM' ). - ENDIF. - - IF lv_answer = '2'. - RETURN. - ENDIF. - - lcl_app=>db( )->delete( - iv_type = ls_key-type - iv_value = ls_key-value ). - - COMMIT WORK. - - ENDMETHOD. - - METHOD db_save. - - DATA: lv_string TYPE string, - ls_content TYPE lcl_persistence_db=>ty_content, - lt_fields TYPE tihttpnvp. - - FIELD-SYMBOLS: 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 WITH KEY name = 'type' ##NO_TEXT. - ASSERT sy-subrc = 0. - ls_content-type = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'value' ##NO_TEXT. - ASSERT sy-subrc = 0. - ls_content-value = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'xmldata' ##NO_TEXT. - ASSERT sy-subrc = 0. - IF -value(1) <> '<'. - ls_content-data_str = -value+1. " hmm - ENDIF. - - lcl_app=>db( )->update( - iv_type = ls_content-type - iv_value = ls_content-value - iv_data = ls_content-data_str ). - - COMMIT WORK. - - ENDMETHOD. - -ENDCLASS. " lcl_gui_router \ No newline at end of file +ENDCLASS. "lcl_gui IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_gui_asset_manager.prog.abap b/src/zabapgit_gui_asset_manager.prog.abap new file mode 100644 index 000000000..2ff246994 --- /dev/null +++ b/src/zabapgit_gui_asset_manager.prog.abap @@ -0,0 +1,414 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_GUI_ASSET_MANAGER +*&---------------------------------------------------------------------* + +CLASS lcl_gui_asset_manager DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_gui. + PUBLIC SECTION. + + METHODS get_asset + IMPORTING iv_asset_name TYPE string + RETURNING VALUE(rv_data) TYPE xstring + RAISING lcx_exception. + + METHODS get_images + RETURNING VALUE(rt_images) TYPE tt_web_assets. + + PRIVATE SECTION. + + METHODS get_inline_asset + IMPORTING iv_asset_name TYPE string + RETURNING VALUE(rv_data) TYPE xstring + RAISING lcx_exception. + + METHODS get_mime_asset + IMPORTING iv_asset_name TYPE c + RETURNING VALUE(rv_data) TYPE xstring + RAISING lcx_exception. + + METHODS get_inline_images + RETURNING VALUE(rt_images) TYPE tt_web_assets. + +ENDCLASS. "lcl_gui_asset_manager + +CLASS lcl_gui_asset_manager IMPLEMENTATION. + + METHOD get_asset. + + DATA: lv_asset_name TYPE string, + lv_mime_name TYPE wwwdatatab-objid. + + lv_asset_name = to_upper( iv_asset_name ). + + CASE lv_asset_name. + WHEN 'CSS_COMMON'. + lv_mime_name = 'ZABAPGIT_CSS_COMMON'. + WHEN 'JS_COMMON'. + lv_mime_name = 'ZABAPGIT_JS_COMMON'. + WHEN OTHERS. + lcx_exception=>raise( |Improper resource name: { iv_asset_name }| ). + ENDCASE. + + rv_data = get_mime_asset( lv_mime_name ). + IF rv_data IS INITIAL. " Fallback to inline asset + rv_data = get_inline_asset( lv_asset_name ). + ENDIF. + + IF rv_data IS INITIAL. + lcx_exception=>raise( |Failed to get GUI resource: { iv_asset_name }| ). + ENDIF. + + ENDMETHOD. " get_asset. + + METHOD get_mime_asset. + + DATA: ls_key TYPE wwwdatatab, + lv_size_c TYPE wwwparams-value, + lv_size TYPE i, + lt_w3mime TYPE STANDARD TABLE OF w3mime. + + ls_key-relid = 'MI'. + ls_key-objid = iv_asset_name. + + " Get exact file size + CALL FUNCTION 'WWWPARAMS_READ' + EXPORTING + relid = ls_key-relid + objid = ls_key-objid + name = 'filesize' + IMPORTING + value = lv_size_c + EXCEPTIONS + entry_not_exists = 1. + + IF sy-subrc IS NOT INITIAL. + RETURN. + ENDIF. + + lv_size = lv_size_c. + + " Get binary data + CALL FUNCTION 'WWWDATA_IMPORT' + EXPORTING + key = ls_key + TABLES + mime = lt_w3mime + EXCEPTIONS + wrong_object_type = 1 + import_error = 2. + + IF sy-subrc IS NOT INITIAL. + RETURN. + ENDIF. + + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_size + IMPORTING + buffer = rv_data + TABLES + binary_tab = lt_w3mime + EXCEPTIONS + failed = 1. + + IF sy-subrc IS NOT INITIAL. + RETURN. + ENDIF. + + ENDMETHOD. " get_mime_asset. + + METHOD get_images. + + FIELD-SYMBOLS LIKE LINE OF rt_images. + + rt_images = get_inline_images( ). + + " Convert to xstring + LOOP AT rt_images ASSIGNING . + CALL FUNCTION 'SSFC_BASE64_DECODE' + EXPORTING + b64data = -base64 + IMPORTING + bindata = -content + EXCEPTIONS + OTHERS = 1. + ASSERT sy-subrc = 0. " Image data error + ENDLOOP. + + ENDMETHOD. " get_images. + + DEFINE _inline. + APPEND &1 TO lt_data. + END-OF-DEFINITION. + + METHOD get_inline_asset. + + DATA: lt_data TYPE ty_string_tt, + lv_str TYPE string. + + CASE iv_asset_name. + WHEN 'CSS_COMMON'. + " @@abapmerge include zabapgit_css_common.w3mi.data.css > _inline '$$'. + WHEN 'JS_COMMON'. + " @@abapmerge include zabapgit_js_common.w3mi.data.js > _inline '$$'. + WHEN OTHERS. + lcx_exception=>raise( |No inline resource: { iv_asset_name }| ). + ENDCASE. + + CONCATENATE LINES OF lt_data INTO lv_str SEPARATED BY gc_newline. + + CALL FUNCTION 'SCMS_STRING_TO_XSTRING' + EXPORTING + text = lv_str + IMPORTING + buffer = rv_data + EXCEPTIONS + OTHERS = 1. + ASSERT sy-subrc = 0. + + ENDMETHOD. " get_inline_asset. + + METHOD get_inline_images. + + DATA ls_image TYPE ty_web_asset. + +* see https://github.com/larshp/abapGit/issues/201 for source SVG + ls_image-url = 'img/logo' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAAKMAAAAoCAYAAACSG0qbAAAABHNCSVQICAgIfAhkiAAA' + && 'AAlwSFlzAAAEJQAABCUBprHeCQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9y' + && 'Z5vuPBoAAA8VSURBVHic7Zx7cJzVeYef31nJAtvYko1JjM3FYHlXimwZkLWyLEMcwIGQ' + && 'cEkDJWmTltLStGkoDCkzwBAuCemUlksDNCkhJTTTljJpZhIuBQxxAWPvyuYiW7UkG8Il' + && 'UByIsS1sLEu75+0fu5JXu9/etAJz0TOzM/rOec85765+37m+3yczY8w0NU3qrwv9npfa' + && 'Hfx02pPPd469sgk+7misYnyjpWXy5IOG7kd8ZjjNjEtr13TdOm7eTfCxwo2lUJAQASRu' + && '2dnRfMn4uDbBx42yxZhPiMNMCHKCsVK2GGuqqqoQUwrZTAhygrFQshjfaGmZ/M7yxQtm' + && 'xGL9/qDqzwLxQvYTgpygXEoS4/DQ7LE1O05atLBu1YZdE4KcYLwpupoOmCO+5Z2dXPfE' + && 'xk07Tm2ZroGhBwX1wAygKqiOiVX2Rw9Jam/gyH0wuGGzvTEudRYSY4HFyogghxN2n7Sw' + && 'IendvcCioLoOtCCXNeqohOf0oDwPq9f3Wt/77dOHlWhYzUj/BRybTnrGEnZO5wv2m0rq' + && 'DezJoOiqeZbzegzpk6TVPPWJTT39y5svMogF1ZcesjlQgkwYp4F+EJQXwv4E+MiLUZJa' + && 'F7AIcRq4hWZ2mMRhQD/oZcErXv7FScaja3rt/wpU9E/sFyLACQq57wB/XIl/gWIstn2T' + && 'xpHVre7ZW71p8sFDeQscSEHKu3pTBadNH2Lq61VT57iwNazLgaNSqYaUaWXLDZCJIbBo' + && 'g3tK2A2xHns0oMrm3CRrqdTPnAVMiUIEmLlz2XGLMxNmH7YrifFcoUIHalHj8f8p6UfA' + && 'O+932weStno1zghps6Q7GBFiUYRxopkeaZ2vIwLyfxtQ4vV8lbWHNScacf+T/vwqn90o' + && 'MZYhRADJ+bv725vmj6Q8tHWffPKUD6IgO/tsfawneRHYd97Pdg8kSyJaZiGtBY4pYPYO' + && 'kH84C0Cyv8tKSiK7OZ99EpYAJ2V8AhkRY5lCHGaxhaq+BLCzY/EXd5y0aOG0td1vf1AF' + && 'CWCw7/1u80DQEtahQvcB03MyjQfM7Hwnmxfv9dPivX5SssqOwuzPSqk71mN3ymw5ZtdK' + && 'dmVIdly8xx7JZ29yy0qptwrGLMRRCA6T1w93nLTo5Lq13Zv625tOMRd6DLF4v0lWmQO8' + && 'qPko45y7TWaHZyUnwa6M99mN2fYbuu1V4K5oxF1B4Z4UgFifrQHWFLNbvkh1QheV5DNN' + && 'TZMqFWIGs5zX48M95PTqGa3TZ4erzbvj8/WUErf0L2++uNyGJLn2Js1oDeuYlkbNbmlR' + && 'deXup2hq0qS2es2VlHMDFaOlRdXL5uuwlnodG23QTEljCkbJV3d7WHOK+dXWqHqZnZeb' + && 'Y1fGe3OFOArRU5GTGbSHNWdwUL8Epo1qIQ9V/bXu3HES4jCznNfjb7e1zZ8Ri/UD1MLz' + && 'u05s/huMx4IKGNy4+8Tj/2Pqk8++Vaji86TQqxEuNNM5rWGtSCaokSDkgd0QjbidoPvN' + && '+5s7t9jz5TgdbdBMvLsG2cop6FgLUdUaZk804jYKuyrWa6vzlT2+XrOqQnxd6KwQOj5R' + && 'hULpL9Yaxkcj7g3QT6zK397ZbdtGtbtAZ+B0U3adkt0c67E7OyI6fFDuSpktC6HGpJjU' + && 'GmZ3NOI2mdnVnX32eHZZ7903hGXfBG8mp3J7sd/B0DPCTgUmBf9O7lmMybk56or3Jn8f' + && 'oLVB7Q5dZ9Iy4OBsw2jYbUUk96fwQrzHf955iBZzsDA+aL9k1owZ20fNzaY/tfFXwK48' + && 'ldQkSZ5YqJXmZk15JaJfmOmfgdOAmgCzWrCvyum5aIO+Uor3AIbOx7QV2TeBMPu3vKYA' + && 'Sw091hbWt4PKRhu0oDqkmND1wAnk3vkOmAN2lRLa2hrWMVm5Tek2R3286YzWiK4eQltk' + && '9g1gMfsFMhVYKunR1obQddk+SXZqwLe8acMGe7fYb9HZk7wm3utrBmpsqiXsyClHMHK6' + && '0hLWoRjHBfmLbP9K3bPYjFPIFWLaQeZnlZ8H4JyFflrMwcK4wG63v3/ycZnXOzqalxE0' + && 'mU7x9rvvVv93oVZqBtzNGGeU7Jbp9pZGzS7ReiVQVyDfmXRda4PaA9p5mBLmWGmmSron' + && 'M0FytUGGgjPTAi8UIeVk9u1og5YOJ0QbNBOjIac+Y22JPgLQ1WV7Ol+w36xebYnhtGpj' + && 'FjBYTj3l4KY9/dx6My4d74pN/Ki/Y9HpSG5HR/Nyh/1DHtO9OM6dvWFDwbtWslOykt6U' + && 's5VWZbOFnQtsyMqvc56Ty3T7NeBhLGAfDZDpe5nX6V5uXpbZ43K2NGQ2V9glwLas/I62' + && 'hfrE8EWsJ3mFsGYs+OQqze+A1cBLgbmma4f/9AmOJGBe5vKVLYN1W6wnOWSHmdkVhexM' + && 'PG6yC0x2AbmjoQ3njdh4uwrSw1Htmq5bd3Y0I3FLpQ5n0GTSQ7s6Fva70RPYTPbi+Pz0' + && 'J7ryboRC+m5PnRfsJjVEAfp5bLNflTb52dKIBj36RWY5ZyX2WCLukvbX67ZYHFLHZtGw' + && '+1fD/jDL8qQljWpav9m6Uw3wKYzXgUNJTxsk+0Fssw0L6x+j4dCx6eF/BEtwDBkbx7Fe' + && '29gWCa0yrC2rvXXO26WZfrWG3V2kji8zWbm0QUev67GX5ZgZ8A0H121hXIIZNrxou9oW' + && '6m4b4m/z2aTP+fsAohF3PaNHROvssZ8ElRs5DnyPBAkovxDFF4oJESDeY9tJD4Ur5umg' + && 'PSFm1Uy23Zk2SaM7e43p5Y4uxUMzu2f4H56+tuZmff2gfTqHrGEy5DkW6Abo7LH7gfsB' + && '2uo1LQGzBmoYFSwg57vNcjqqo4F1JXh2S7Zfx83TZZNqdD6MXkQkU369jONgcmfxe83M' + && 'B7XQEdEhg1B0HzDk2ZHpy3vBqLPpMQhyi/f2AIA3WyPZG6KkeVpKiE925awEi7H6JRsA' + && 'cqJDfIi9oayfW8ZB5dY/TFeX7YlGQg+RmgJkcnSQfWyr9QP92enmGcgeNCvx67mXbGdb' + && 'xD1hjI5AklJ+ydgTUGz6iiZNXd09+gYGGIRlQgXn6wDesZYSRFsJOYES5QjSw7fqnu7q' + && 'Bqh7uqu7f3nzdw3uKFJszEIcpqVRs12SRuAYiTrJ1YXMzSGgS6iQnHmWyQWe70pySz/F' + && 'MZagMWnMlaiTuTqTTih7s7IIHm1T1ncVI37l3BAAA4McAYF7iAvG17uxExi1U6Igd9XN' + && 'Dj+UmZA8qPrf3MDQbeSPIN8Ldub0JzeWLcT2I3Swn8JFhr4VQnMze5uKnv0ugOHfUXa3' + && 'ZhySedkR0eGDuMtbw/rTZCI1pA9PF0yWf4e3MnJ7YKXm0pOr6H03QRIIZeYnUj1njhid' + && '8aaRscKX/VGWSRLsCjnK2rcdC3njGUsQ5PSdv92yqJaMk5WBoRMpJsSnNgZufBdCkmsN' + && '60FgRbllK8PNzOlttT/qpz2sOUnpeWGHvq9ewcyc28/7XQCru213NOL+l6wgZ0kXAjnD' + && 'cazP7gXuTdu41rCyxbgr3mt/P16+F6LgUVXtmq5bC237yNsNu5YtPBZgx4kLFznZ1XlM' + && 'BzB/1liECBAN801yhfiq0HflbKXz1ojZ4qCylSBsbm6q/93wX0n0Q1Ir6UzWYXaZyZaF' + && 'qqxeZn813n4ZlhPWJWXMo00P5OTDF5c0qmm8fRlPip6bFhHk6Ti3ddfy5i3OXBemJQE2' + && 'A5g/c/qaTasC8krC0KdzE+3qWG/y6thmW7Vui/UkQ7w51vqDaGnRZFInPdlshNQ2C8oJ' + && 'h0oqaefF++zmzh5bu7bbXrBxjp88bp5qgZzNdyfWD/9t+B+TO4GW8/p+R0SHcGBxLWEF' + && 'jiQlHeIXEaRIPZAVRMVCTDcQCUh8LfOyaqjgCcr+YpY7NRFa2VY/egsqtNtdw8ie5gjJ' + && 'oUTqicjofOYA2f/YgcR03s5MMBF4wlIa7rMr5mnUyru6xl0LZAeFvDG3l83DF5199muk' + && 'oJO1FUMoviSi8Nh9Kg+Ru7qvUvCqPO+cMZsxbPsM4HXW9KcrEyKApTa7s9BVSyLaF3Ik' + && 'SbLSQros18RyInkkV2u5q+6zLaS+aCT0oJl/QVI78IWcsvDos1vtLYCE551QKNuCKW63' + && '+157g36cMOYI9yWhC3K+j4KDEHKxC9+t0altDaFHwL/kvVZIBJw761/uM5/MTJlU7S/Z' + && 'N6hTBNlhZA0OPReNuGdM6nL4jR4G5ZnRusAtKmVHwg1Slcxe11nODZJKh1fJ6kwM3dQa' + && 'VgOw3omjkGuL9/o/L/vFTzs7mi8pQZBpIT4f9PxE2bRFQncY9pdjKDoExDH7ebzPbgFo' + && 'bQjdng48KBfvzZau77ORN61FI66PsW2N7ARiZnZTZ589BtAWCV1v5J1zF+JNVdui2CbL' + && 'OcJsq1ejD2lVgCDL4e14r58J0N6k+cmEu0HYIssdrbxgnaGeeG9yJEg32hC6GbOix81y' + && 'trTsWLtiixpgQNLZ4yVEgCT++xSP0H7C0N1ZadVAh6SR3kRm2WfJO0H/XqTuQcn+IlOI' + && 'AFjRVaZhus3g2az0WuA0wcIi5QP3DDNIIPtakBABYltts7AO4OEi9eTFYGCksSRzwM4L' + && 'ECKAM1gG9tVR5UP+RkqZN5s7a0yBnwUEOSDp7GlPPp83BH0srO+1PmQrDIIen9wOdnln' + && 'n31G5n9ZtDLL6ck2x3uTf6DUee8rASX6vNnyWI/dmZ0R77O7LNXLBkWy9CE7Pd6XvNih' + && 'QkEQeZHZl9PBFtsDstebtyWFwv0B4r32UrzXn+6xDtBdwIslNL0N+JnMvravxiraFO/s' + && 'tm0y+xzQlcfkddCNCe/vGfP7GQH6lzdfbHAjqSCBHZK+PN5CzESSlixgnhMLzXAeXp+3' + && 'hWfuM0sWL10abQv1CdtHixzvmtiYPhcvSFOTJk1NEPEQkWdPUry4oc96y2o3YJiWs5Wx' + && 'zbYq83THHHu9Y1N2kG45tDRqdsgzxxuznKPOGbsTsN2M7d6zfXhePJ5Ici1h6mUcAcw0' + && '8Zo5fp35NoqKxAjwTrRhZmLSpPY9ySmPzV27dm+lTn9cKSTGA+XT+03Jq+l8HBLv2Q7c' + && 'X9K+ygQTFGDcHhaaoGJyouDNV7JH+eGj4mF6gspoC+tzJt1ObsT4MDsF2zxs886+Ml5v' + && '/PogUvEwPUGFiE+SX4gAtQa1gkhV7onQR4oJMR5oxC6stDeghd7Dh6E+CPw/HL4vVO2f' + && 'cpUAAAAASUVORK5CYII='. + APPEND ls_image TO rt_images. + +* http://fa2png.io/r/octicons/ +* colour: #808080 +* size: 16 +* https://www.base64-image.de/ can be used to convert images to base64 + + ls_image-url = 'img/sync' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAA6ElEQVQYGY3BIWuUAQAG' + && '4Pc7N72xsbGBYNE8tYpVZKDZX2CcYLEZ9yQxOQSz3D/YmkUsVovRQ2SYNJnlkFfH7VZu' + && 'wefJgrGHXnjrpQeu5B93smCwr6qqqp54433mDI5Ucds1u577o+p35hyoqe2cMThWVatJ' + && '7KiZrZxz18SJqqtJPFXPssRgw0oSH9WNXMCQU76qzSxx2cxxTlk3yhKb6mcSQy7kvjpM' + && 'Ylt98tpjN3POyFTdSuKSqppayxkjE/Uhc36p+m7PhhXr7vmmfhhnzpHPJqqqquqdcRY8' + && 'spq47sAXMyde2c3/+wvX7Y18BexhBwAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/toc' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEUAAACAgICAgICA' + && 'gICAgICAgICAgIAO39T0AAAABnRSTlMABBCRlMXJzV0oAAAAN0lEQVQIW2NgwABuaWlB' + && 'YWlpDgwJDAxiAgxACshgYwAz0tLY2NISSBWBMYAmg4ADyBZhARCJAQBBchGypGCbQgAA' + && 'AABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/repo_online' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAApVBMVEUAAABQbJxQbJxQ' + && 'bJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQ' + && 'bJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQ' + && 'bJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQbJxQ' + && 'bJz+TJ01AAAANnRSTlMAAQIDBAcJCgwSFBocHygqMTM1NkRHSU1QUWFiZGlweHuDiImL' + && 'lZiio6a5vsfT3uTo6e3x9fsxY2JuAAAAgUlEQVQYGXXB6RaBUBSA0e+IEuIiMs9zhlDn' + && '/R/NZWmt/LA3f1RcoaB50SydCbn20wjedkPu3sKSpMGH21PhLdZ0BATZ+cCXtxtDHGLV' + && 'pgFW9QqJj2U0wvJvMF+5jiNGI3HK9dMQSouH6sRoFGoWd8l1dEDRWlWPQsFS98KPvvDH' + && 'C3HLClrWc70ZAAAAAElFTkSuQmCC'. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/repo_offline' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAVFBMVEUAAACAgICAgICA' + && 'gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA' + && 'gICAgICAgICAgICAgICAgICAgICAgICuaWnmAAAAG3RSTlMAAgQFBgsQFxweIiMtN3yI' + && 'nqOvt9Hp6/Hz9fktMNR/AAAAXElEQVQYV5WO2xJAMAxES1q3ugfF/v9/0qLyyL4k58xk' + && 'J0p9D7N5oeqZgSwy7fDZnHNdEE1gWK116tksl7hPimGFFPWYl7MU0zksRCl8TStKg1AJ' + && '0XNC8Zm4/c0BUVQHi0llOUYAAAAASUVORK5CYII='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/pkg' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAA30lEQVQoU43OIUuDcRSF' + && '8fvqhuB0mFwaKLbVBVdkX0GTFss+wYL2H4rJIIgyQQSzZcUPoGHZ9CKCmAwTMS8Y/ga3' + && 'BWVjT7hwOQ+HEzEbMhU7jrTd69q2KhtFRU2nrvS927dm3pyqPXcuNRVD7sxiRIQlDSc+' + && 'PGjZUFDWkYekLfdoV2XYua4rSZ61pZBkEUq2XPty41XuXJIiZGNhPDVZiFCYIMSor+Db' + && '7RQhYnQnCsNvNmGgPFFYMQh1PU9aqrLxyGUNx/p66r9mUc2hFx3JhU9vDtQU4y9KGjaV' + && '/gXT+AGZVIinhU2EAwAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/branch' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAqFBMVEUAAACAgICAgICA' + && 'gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA' + && 'gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA' + && 'gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA' + && 'gICAgID/OyosAAAAN3RSTlMAAQIDBAYICQ8TFRweJScoKSo3Oj1FRk1dYWJjZmhzdIaJ' + && 'j5GVm6CwsrS5vsHDyszV19ne7/X583teZAAAAIFJREFUGFdVytkagVAYheFvFzJlnqc0' + && 'EEoR+u//zhxI7dbZ9z4LMJ1op9DmjpntdXiBigHbLiAYqukBVr63+YGRSazgCY/iEooP' + && 'xKZxr0EnSbo14B1Rg4msKzj150fJrQpERPLBv7mIfNxlq+zRbZsu0JYpGlcdwjY9Twfr' + && 'nAbNsr6IKQxJI/U5CgAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/link' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAXVBMVEUAAACAgICAgICA' + && 'gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA' + && 'gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICVwFMKAAAAHnRSTlMAAwQFBgcK' + && 'FR4gIiMmP0JHSm+RmKDByM/R09rg+/0jN/q+AAAAX0lEQVQYV43Nxw6AIBAE0FGw916Z' + && '//9MRQ0S4sG5bPZlCxqSCyBGXgFUJKUA4A8PUOKONzuQOxOZIjcLkrMvxGQg3skSCFYL' + && 'Kl1Ds5LWz+33yyf4rQOSf6CjnV6rHeAA87gJtKzI8ocAAAAASUVORK5CYII='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/code' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOBAMAAADtZjDiAAAAElBMVEUAAACAgICAgICA' + && 'gICAgICAgIC07w1vAAAABXRSTlMABECUxcOwZQcAAAA1SURBVAhbY2AODQ0NEWBgYGVg' + && 'YGByhNAMKgIMrKyhAQxMDhA+QwCCZgVqIIUP1Q+yJzTUAAAfUAq+Os55uAAAAABJRU5E' + && 'rkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/bin' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOBAMAAADtZjDiAAAAElBMVEUAAACAgICAgICA' + && 'gICAgICAgIC07w1vAAAABXRSTlMABECUxcOwZQcAAABBSURBVAhbXcqxDYAwAMRAK8h9' + && 'hmAARoANvuD3X4UCiojqZMlsbe8JAuN6ZZ9ozThRCVmsJe9H0HwdXf19W9v2eAA6Fws2' + && 'RotPsQAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/obj' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOBAMAAADtZjDiAAAAIVBMVEUAAACAgICAgICA' + && 'gICAgICAgICAgICAgICAgICAgICAgIDcWqnoAAAACnRSTlMABD1AZI+RlcPFIaFe1gAA' + && 'AEVJREFUCFtjYF+1atVKAQYGLgYGBuaJEJrBUgBCM0+A0AwLgLQIgyOIZmwCSgNptgAG' + && '1gQQfzKDhgCSPFw9Kg2yZ9WqAgBWJBENLk6V3AAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/lock' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAOVBMVEUAAACIiIiIiIiI' + && 'iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjNaTNB' + && 'AAAAEnRSTlMABgdBVXt8iYuRsNXZ3uDi6Pmu6tfUAAAASUlEQVQYV63KSxJAQBAE0TQ0' + && 'Znym1f0PayE0QdjJ5asCgGTu1hClqjppvaRXB60swBeA2QNUAIq+ICvKx367nqAn/P8Y' + && 't2jg3Q5rgASaF3KNRwAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/dir' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAASFBMVEUAAABmksxmksxm' + && 'ksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxm' + && 'ksxmksxmksxmksxMwQo8AAAAF3RSTlMABhIYIy1fZmhpe3+IiYuMkZvD7e/x93sipD4A' + && 'AAA+SURBVBhXY2BABzwiokAgzAYXEGdiBAIWIYQAPzcQCApzgwEXM4M4KuBDFxAYKAEx' + && 'VAFeBlYOTiTAzoThewD5hBAcnWM4gwAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/burger' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAHlBMVEUAAABtktltktlt' + && 'ktltktltktltktltktltktltktk7ccVDAAAACXRSTlMAFDBLY2SFoPGv/DFMAAAAJ0lE' + && 'QVQIW2NggIHKmWAwmaETwpjGoBoKBo4MmIAkxXApuGK4dgwAAJa5IzLs+gRBAAAAAElF' + && 'TkSuQmCC'. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/star' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAilBMVEUAAABejclejcle' + && 'jclejclejclejclejclejclejclejclejclejclejclejclejclejclejclejclejcle' + && 'jclejclejclejclejclejclejclejclejclejclejclejclejclejclejclejclejcle' + && 'jclejclejclejclejclejclejclejclejcn2yvsVAAAALXRSTlMAAQIFBwkKCw0QERUY' + && 'HB4jLzEzNjg7PVdYYmRvd3mDm52eub7R0+Tr8fX3+/16wo8zAAAAcElEQVQYGW3BBxKC' + && 'MABFwYcQETv2hg1UVP79ryeTZBxw3MWL+JGltBgVtGRSSoORVOAE8Xi5zVU7rWfDCOaV' + && 'Gu59mLz0dTPUBg95eYjVK2VdOzjBW9YZL5FT4i2k5+YoKcY5VPsQkoumOLsu1mjFHx8o' + && 'ahA3YV7OfwAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + ls_image-url = 'img/star-grey' ##NO_TEXT. + ls_image-base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAilBMVEUAAADQ0NDQ0NDQ' + && '0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ' + && '0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ' + && '0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NC2QdifAAAALXRSTlMAAQIFBwkKCw0QERUY' + && 'HB4jLzEzNjg7PVdYYmRvd3mDm52eub7R0+Tr8fX3+/16wo8zAAAAcElEQVQYGW3BBxKC' + && 'MABFwYcQETv2hg1UVP79ryeTZBxw3MWL+JGltBgVtGRSSoORVOAE8Xi5zVU7rWfDCOaV' + && 'Gu59mLz0dTPUBg95eYjVK2VdOzjBW9YZL5FT4i2k5+YoKcY5VPsQkoumOLsu1mjFHx8o' + && 'ahA3YV7OfwAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_images. + + + ENDMETHOD. " get_inline_images. + +ENDCLASS. "lcl_gui_asset_manager \ No newline at end of file diff --git a/src/zabapgit_gui_asset_manager.prog.xml b/src/zabapgit_gui_asset_manager.prog.xml new file mode 100644 index 000000000..bcab6cac1 --- /dev/null +++ b/src/zabapgit_gui_asset_manager.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_GUI_ASSET_MANAGER + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_GUI_ASSET_MANAGER + 34 + + + + + + diff --git a/src/zabapgit_gui_pages.prog.abap b/src/zabapgit_gui_pages.prog.abap new file mode 100644 index 000000000..910211fd0 --- /dev/null +++ b/src/zabapgit_gui_pages.prog.abap @@ -0,0 +1,30 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_GUI_PAGES +*&---------------------------------------------------------------------* + +* All UI pages + +* Super class +INCLUDE zabapgit_page. + +* Utils and helpers +INCLUDE zabapgit_html_action_utils. +INCLUDE zabapgit_repo_browser_util. + +* Components and templates +INCLUDE zabapgit_view_repo. +INCLUDE zabapgit_view_tutorial. +INCLUDE zabapgit_syntax_highlighter. + +* Pages +INCLUDE zabapgit_page_commit. +INCLUDE zabapgit_page_merge. +INCLUDE zabapgit_page_background. +INCLUDE zabapgit_page_branch_overview. +INCLUDE zabapgit_page_db. +INCLUDE zabapgit_page_diff. +INCLUDE zabapgit_page_explore. +INCLUDE zabapgit_page_main. +INCLUDE zabapgit_page_stage. +INCLUDE zabapgit_page_debug. +INCLUDE zabapgit_page_settings. \ No newline at end of file diff --git a/src/zabapgit_gui_pages.prog.xml b/src/zabapgit_gui_pages.prog.xml new file mode 100644 index 000000000..068beb75a --- /dev/null +++ b/src/zabapgit_gui_pages.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_GUI_PAGES + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_GUI_PAGES + 26 + + + + + + diff --git a/src/zabapgit_gui_router.prog.abap b/src/zabapgit_gui_router.prog.abap new file mode 100644 index 000000000..3c259c095 --- /dev/null +++ b/src/zabapgit_gui_router.prog.abap @@ -0,0 +1,345 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_GUI_ROUTER +*&---------------------------------------------------------------------* + +*----------------------------------------------------------------------* +* CLASS lcl_gui_router DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_gui_router DEFINITION FINAL. + PUBLIC SECTION. + + METHODS on_event + IMPORTING iv_action TYPE clike + iv_prev_page 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 lcx_cancel. + + PRIVATE SECTION. + + METHODS get_page_by_name + IMPORTING iv_name TYPE clike + RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page + RAISING lcx_exception. + + METHODS get_page_diff + IMPORTING iv_getdata TYPE clike + RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page + RAISING lcx_exception. + + METHODS get_page_branch_overview + IMPORTING iv_getdata TYPE clike + RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page + RAISING lcx_exception. + + METHODS get_page_stage + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page + RAISING lcx_exception. + + METHODS get_page_db_by_name + IMPORTING iv_name TYPE clike + iv_getdata TYPE clike + RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page + RAISING lcx_exception. + + METHODS get_page_background + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page + RAISING lcx_exception. + + METHODS get_page_playground + RETURNING VALUE(ri_page) TYPE REF TO lif_gui_page + RAISING lcx_exception lcx_cancel. + +ENDCLASS. + +*----------------------------------------------------------------------* +* CLASS lcl_gui_router IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_gui_router IMPLEMENTATION. + + METHOD on_event. + + DATA: lv_url TYPE string, + lv_key TYPE lcl_persistence_repo=>ty_repo-key, + ls_db TYPE lcl_persistence_db=>ty_content, + ls_item TYPE ty_item. + + lv_key = iv_getdata. " TODO refactor + lv_url = iv_getdata. " TODO refactor + + CASE iv_action. + " General routing + WHEN gc_action-go_main " Go Main page + OR gc_action-go_explore " Go Explore page + OR gc_action-go_db " Go DB util page + OR gc_action-go_background_run " Go background run page + OR gc_action-go_debuginfo " Go debug info page + OR gc_action-go_settings. " Go settings page + ei_page = get_page_by_name( iv_action ). + ev_state = gc_event_state-new_page. + WHEN gc_action-go_background. " Go Background page + ei_page = get_page_background( lv_key ). + ev_state = gc_event_state-new_page. + WHEN gc_action-go_diff. " Go Diff page + ei_page = get_page_diff( iv_getdata ). + ev_state = gc_event_state-new_page. + WHEN gc_action-go_stage. " Go Staging page + ei_page = get_page_stage( lv_key ). + ev_state = gc_event_state-new_page_w_bookmark. + WHEN gc_action-go_branch_overview. " Go repo branch overview + ei_page = get_page_branch_overview( iv_getdata ). + ev_state = gc_event_state-new_page. + WHEN gc_action-go_playground. " Create playground page + ei_page = get_page_playground( ). + ev_state = gc_event_state-new_page. + WHEN gc_action-go_tutorial. " Go to tutorial + lcl_app=>user( )->set_repo_show( '' ). " Clear show_id + ev_state = gc_event_state-re_render. " Assume we are on main page + + " SAP GUI actions + WHEN gc_action-jump. " Open object editor + lcl_html_action_utils=>jump_decode( EXPORTING iv_string = iv_getdata + IMPORTING ev_obj_type = ls_item-obj_type + ev_obj_name = ls_item-obj_name ). + lcl_objects=>jump( ls_item ). + ev_state = gc_event_state-no_more_act. + + WHEN gc_action-jump_pkg. " Open SE80 + lcl_services_repo=>open_se80( |{ iv_getdata }| ). + ev_state = gc_event_state-no_more_act. + + " DB actions + WHEN gc_action-db_display OR gc_action-db_edit. " DB Display/Edit + ei_page = get_page_db_by_name( iv_name = iv_action iv_getdata = iv_getdata ). + ev_state = gc_event_state-new_page. + IF iv_prev_page = 'PAGE_DB_DISPLAY'. + ev_state = gc_event_state-new_page_replacing. + ENDIF. + WHEN gc_action-db_delete. " DB Delete + ls_db = lcl_html_action_utils=>dbkey_decode( iv_getdata ). + lcl_services_db=>delete( ls_db ). + ev_state = gc_event_state-re_render. + WHEN gc_action-db_update. " DB Update + ls_db = lcl_html_action_utils=>dbcontent_decode( it_postdata ). + lcl_services_db=>update( ls_db ). + ev_state = gc_event_state-go_back. + + " Abapgit services actions + WHEN gc_action-abapgit_home. " Go abapGit homepage + lcl_services_abapgit=>open_abapgit_homepage( ). + ev_state = gc_event_state-no_more_act. + WHEN gc_action-abapgit_wiki. " Go abapGit wikipage + lcl_services_abapgit=>open_abapgit_wikipage( ). + ev_state = gc_event_state-no_more_act. + WHEN gc_action-abapgit_install. " Install abapGit + lcl_services_abapgit=>install_abapgit( ). + ev_state = gc_event_state-re_render. + WHEN gc_action-abapgit_install_pi. " Install abapGit plugins + lcl_services_abapgit=>install_abapgit_pi( ). + ev_state = gc_event_state-re_render. + + " Repository services actions + WHEN gc_action-repo_newoffline. " New offline repo + lcl_services_repo=>new_offline( ). + ev_state = gc_event_state-re_render. + WHEN gc_action-repo_refresh. " Repo refresh + lcl_services_repo=>refresh( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-repo_purge. " Repo remove & purge all objects + lcl_services_repo=>purge( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-repo_remove. " Repo remove + lcl_services_repo=>remove( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-repo_clone OR 'install'. " Repo clone, 'install' is for explore page + lcl_services_repo=>clone( lv_url ). + ev_state = gc_event_state-re_render. + WHEN gc_action-repo_refresh_checksums. " Rebuil local checksums + lcl_services_repo=>refresh_local_checksums( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-repo_toggle_fav. " Toggle repo as favorite + lcl_services_repo=>toggle_favorite( lv_key ). + ev_state = gc_event_state-re_render. + + " ZIP services actions + WHEN gc_action-zip_import. " Import repo from ZIP + lcl_zip=>import( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-zip_export. " Export repo as ZIP + lcl_zip=>export( lcl_app=>repo_srv( )->get( lv_key ) ). + ev_state = gc_event_state-no_more_act. + WHEN gc_action-zip_package. " Export package as ZIP + lcl_zip=>export_package( ). + ev_state = gc_event_state-no_more_act. + WHEN gc_action-zip_transport. " Export transport as ZIP + lcl_transport=>zip( ). + ev_state = gc_event_state-no_more_act. + WHEN gc_action-zip_object. " Export object as ZIP + lcl_zip=>export_object( ). + ev_state = gc_event_state-no_more_act. + + " Remote origin manipulations + WHEN gc_action-repo_remote_attach. " Remote attach + lcl_services_repo=>remote_attach( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-repo_remote_detach. " Remote detach + lcl_services_repo=>remote_detach( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-repo_remote_change. " Remote change + lcl_services_repo=>remote_change( lv_key ). + ev_state = gc_event_state-re_render. + + " Git actions + WHEN gc_action-git_pull. " GIT Pull + lcl_services_git=>pull( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-git_reset. " GIT Reset + lcl_services_git=>reset( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-git_branch_create. " GIT Create new branch + lcl_services_git=>create_branch( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-git_branch_delete. " Delete remote branch + lcl_services_git=>delete_branch( lv_key ). + ev_state = gc_event_state-re_render. + WHEN gc_action-git_branch_switch. " Switch branch + lcl_services_git=>switch_branch( lv_key ). + ev_state = gc_event_state-re_render. + + "Others + WHEN OTHERS. + ev_state = gc_event_state-not_handled. + ENDCASE. + + ENDMETHOD. " on_event + + METHOD get_page_by_name. + + DATA: lv_page_class TYPE string, + lv_page_name TYPE string. + + lv_page_name = iv_name. + SHIFT lv_page_name LEFT DELETING LEADING 'go_'. + lv_page_class = |LCL_GUI_PAGE_{ to_upper( lv_page_name ) }|. + + TRY. + CREATE OBJECT ri_page TYPE (lv_page_class). + CATCH cx_sy_create_object_error. + lcx_exception=>raise( |Cannot create page class { lv_page_class }| ). + ENDTRY. + + ENDMETHOD. " get_page_by_name + + METHOD get_page_db_by_name. + + DATA: lv_page_class TYPE string, + lv_message TYPE string, + ls_key TYPE lcl_persistence_db=>ty_content. + + lv_page_class = |LCL_GUI_PAGE_{ to_upper( iv_name ) }|. + ls_key = lcl_html_action_utils=>dbkey_decode( iv_getdata ). + + TRY. + CREATE OBJECT ri_page TYPE (lv_page_class) + EXPORTING + is_key = ls_key. + + CATCH cx_sy_create_object_error. + lv_message = |Cannot create page class { lv_page_class }|. + lcx_exception=>raise( lv_message ). + ENDTRY. + + ENDMETHOD. " get_page_db_by_name + + METHOD get_page_branch_overview. + + DATA: lo_repo TYPE REF TO lcl_repo_online, + lo_page TYPE REF TO lcl_gui_page_branch_overview, + lv_key TYPE lcl_persistence_repo=>ty_repo-key. + + + lv_key = iv_getdata. + + lo_repo ?= lcl_app=>repo_srv( )->get( lv_key ). + + CREATE OBJECT lo_page + EXPORTING + io_repo = lo_repo. + + ri_page = lo_page. + + ENDMETHOD. "get_page_branch_overview + + METHOD get_page_diff. + + DATA: ls_file TYPE ty_file, + ls_object TYPE ty_item, + lo_page TYPE REF TO lcl_gui_page_diff, + lv_key TYPE lcl_persistence_repo=>ty_repo-key. + + + lcl_html_action_utils=>file_obj_decode( EXPORTING iv_string = iv_getdata + IMPORTING ev_key = lv_key + eg_file = ls_file + eg_object = ls_object ). + + CREATE OBJECT lo_page + EXPORTING + iv_key = lv_key + is_file = ls_file + is_object = ls_object. + + ri_page = lo_page. + + ENDMETHOD. "get_page_diff + + METHOD get_page_stage. + + DATA: lo_repo TYPE REF TO lcl_repo_online, + lo_stage_page TYPE REF TO lcl_gui_page_stage. + + + lo_repo ?= lcl_app=>repo_srv( )->get( iv_key ). + + " force refresh on stage, to make sure the latest local and remote files are used + lo_repo->refresh( ). + + CREATE OBJECT lo_stage_page + EXPORTING + io_repo = lo_repo. + + ri_page = lo_stage_page. + + ENDMETHOD. "get_page_stage + + METHOD get_page_background. + + CREATE OBJECT ri_page TYPE lcl_gui_page_background + EXPORTING + iv_key = iv_key. + + ENDMETHOD. "get_page_background + + METHOD get_page_playground. + DATA: lv_class_name TYPE string, + lv_cancel TYPE abap_bool. + + lcl_popups=>run_page_class_popup( IMPORTING ev_name = lv_class_name + ev_cancel = lv_cancel ). + IF lv_cancel = abap_true. + RAISE EXCEPTION TYPE lcx_cancel. + ENDIF. + + TRY. + CREATE OBJECT ri_page TYPE (lv_class_name). + CATCH cx_sy_create_object_error. + lcx_exception=>raise( |Cannot create page class { lv_class_name }| ). + ENDTRY. + + ENDMETHOD. "get_page_playground + +ENDCLASS. " lcl_gui_router \ No newline at end of file diff --git a/src/zabapgit_gui_router.prog.xml b/src/zabapgit_gui_router.prog.xml new file mode 100644 index 000000000..554bbc558 --- /dev/null +++ b/src/zabapgit_gui_router.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_GUI_ROUTER + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_GUI_ROUTER + 27 + + + + + + diff --git a/src/zabapgit_html.prog.abap b/src/zabapgit_html.prog.abap index 31b2bef31..784e91e9f 100644 --- a/src/zabapgit_html.prog.abap +++ b/src/zabapgit_html.prog.abap @@ -6,263 +6,6 @@ DEFINE _add. ro_html->add( &1 ) ##NO_TEXT. END-OF-DEFINITION. -*----------------------------------------------------------------------* -* CLASS lcl_html_action_utils DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_html_action_utils DEFINITION FINAL. - PUBLIC SECTION. - - TYPES: BEGIN OF ty_commit_fields, "TODO refactor ! Move to normal place - repo_key TYPE lcl_persistence_repo=>ty_repo-key, - username TYPE string, - email TYPE string, - comment TYPE string, - body TYPE string, - END OF ty_commit_fields. - - CLASS-METHODS jump_encode - IMPORTING iv_obj_type TYPE tadir-object - iv_obj_name TYPE tadir-obj_name - RETURNING VALUE(rv_string) TYPE string. - - CLASS-METHODS jump_decode - IMPORTING iv_string TYPE clike - EXPORTING ev_obj_type TYPE tadir-object - ev_obj_name TYPE tadir-obj_name - RAISING lcx_exception. - - CLASS-METHODS file_encode - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - ig_file TYPE any "ty_repo_file - RETURNING VALUE(rv_string) TYPE string. - - CLASS-METHODS file_decode - IMPORTING iv_string TYPE clike - EXPORTING ev_key TYPE lcl_persistence_repo=>ty_repo-key - eg_file TYPE any "ty_repo_file - RAISING lcx_exception. - - CLASS-METHODS dbkey_encode - IMPORTING is_key TYPE lcl_persistence_db=>ty_content - RETURNING VALUE(rv_string) TYPE string. - - CLASS-METHODS dbkey_decode - IMPORTING iv_string TYPE clike - RETURNING VALUE(rs_key) TYPE lcl_persistence_db=>ty_content. - - CLASS-METHODS parse_commit_request - IMPORTING it_postdata TYPE cnht_post_data_tab - RETURNING VALUE(rs_fields) TYPE ty_commit_fields. - - CLASS-METHODS repo_key_encode - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RETURNING VALUE(rv_string) TYPE string. - -ENDCLASS. "lcl_html_action_utils DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_html_action_utils IMPLEMENTATION -*----------------------------------------------------------------------* -CLASS lcl_html_action_utils IMPLEMENTATION. - - METHOD jump_encode. - - DATA: lt_fields TYPE tihttpnvp, - ls_field LIKE LINE OF lt_fields. - - - ls_field-name = 'TYPE'. - ls_field-value = iv_obj_type. - APPEND ls_field TO lt_fields. - - ls_field-name = 'NAME'. - ls_field-value = iv_obj_name. - APPEND ls_field TO lt_fields. - - rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). - - ENDMETHOD. "jump_encode - - METHOD jump_decode. - - DATA: lt_fields TYPE tihttpnvp, - lv_string TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields. - - - lv_string = iv_string. " type conversion - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'TYPE'. - IF sy-subrc = 0. - ev_obj_type = -value. - ELSE. - CLEAR ev_obj_type. - ENDIF. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'NAME'. - IF sy-subrc = 0. - ev_obj_name = -value. - ELSE. - CLEAR ev_obj_name. - ENDIF. - - ENDMETHOD. "jump_decode - - METHOD file_encode. - - DATA: lt_fields TYPE tihttpnvp, - ls_field LIKE LINE OF lt_fields. - - FIELD-SYMBOLS TYPE string. - - ls_field-name = 'KEY'. - ls_field-value = iv_key. - APPEND ls_field TO lt_fields. - - ls_field-name = 'PATH'. - ASSIGN COMPONENT ls_field-name OF STRUCTURE ig_file TO . - ASSERT IS ASSIGNED. - ls_field-value = . - APPEND ls_field TO lt_fields. - - ls_field-name = 'FILENAME'. - ASSIGN COMPONENT ls_field-name OF STRUCTURE ig_file TO . - ASSERT IS ASSIGNED. - ls_field-value = . - APPEND ls_field TO lt_fields. - - rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). - - ENDMETHOD. "file_encode - - METHOD file_decode. - - DATA: lt_fields TYPE tihttpnvp, - lv_string TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields, - TYPE string. - - CLEAR: ev_key, eg_file. - lv_string = iv_string. " type conversion - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'KEY'. - IF sy-subrc = 0. - ev_key = -value. - ENDIF. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'PATH'. - IF sy-subrc = 0. - ASSIGN COMPONENT 'PATH' OF STRUCTURE eg_file TO . - ASSERT IS ASSIGNED. - = -value. - ENDIF. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'FILENAME'. - IF sy-subrc = 0. - ASSIGN COMPONENT 'FILENAME' OF STRUCTURE eg_file TO . - ASSERT IS ASSIGNED. - = -value. - ENDIF. - - ENDMETHOD. "file_decode - - METHOD dbkey_encode. - - DATA: lt_fields TYPE tihttpnvp, - ls_field LIKE LINE OF lt_fields. - - ls_field-name = 'TYPE'. - ls_field-value = is_key-type. - APPEND ls_field TO lt_fields. - - ls_field-name = 'VALUE'. - ls_field-value = is_key-value. - APPEND ls_field TO lt_fields. - - rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). - - ENDMETHOD. "dbkey_encode - - METHOD dbkey_decode. - - DATA: lt_fields TYPE tihttpnvp, - lv_string TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields. - - lv_string = iv_string. " type conversion - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'TYPE'. - IF sy-subrc = 0. - rs_key-type = -value. - ENDIF. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'VALUE'. - IF sy-subrc = 0. - rs_key-value = -value. - ENDIF. - - ENDMETHOD. "dbkey_decode - - METHOD parse_commit_request. - - CONSTANTS: lc_replace TYPE string VALUE '<>'. - - DATA: lv_string TYPE string, - lt_fields TYPE tihttpnvp. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields. - - - CONCATENATE LINES OF it_postdata INTO lv_string. - - REPLACE ALL OCCURRENCES OF gc_newline IN lv_string WITH lc_replace. - - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'key' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-repo_key = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'username' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-username = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'email' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-email = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'comment' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-comment = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'body' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-body = -value. - REPLACE ALL OCCURRENCES OF lc_replace IN rs_fields-body WITH gc_newline. - - ENDMETHOD. "parse_commit_request - - METHOD repo_key_encode. - - DATA: lt_fields TYPE tihttpnvp, - ls_field LIKE LINE OF lt_fields. - - ls_field-name = 'KEY'. - ls_field-value = iv_key. - APPEND ls_field TO lt_fields. - - rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). - - ENDMETHOD. "repo_key_encode - -ENDCLASS. "lcl_html_action_utils IMPLEMENTATION - *----------------------------------------------------------------------* * CLASS lcl_html_helper DEFINITION *----------------------------------------------------------------------* @@ -273,15 +16,18 @@ CLASS lcl_html_helper DEFINITION FINAL. DATA mv_html TYPE string READ-ONLY. DATA mv_indent TYPE i READ-ONLY. DATA mv_within_style TYPE i READ-ONLY. + DATA mv_within_js TYPE i READ-ONLY. METHODS add IMPORTING iv_chunk TYPE any. METHODS reset. METHODS add_anchor IMPORTING iv_txt TYPE string iv_act TYPE string - iv_opt TYPE char1 OPTIONAL + iv_opt TYPE clike OPTIONAL iv_typ TYPE char1 DEFAULT gc_action_type-sapevent - iv_class TYPE string OPTIONAL. + iv_class TYPE string OPTIONAL + iv_id TYPE string OPTIONAL + iv_style TYPE string OPTIONAL. PRIVATE SECTION. METHODS _add_str IMPORTING iv_str TYPE csequence. @@ -336,6 +82,8 @@ CLASS lcl_html_helper IMPLEMENTATION. DATA lv_shift_back TYPE i. DATA lv_style_tag_open TYPE i. DATA lv_style_tag_close TYPE i. + DATA lv_js_tag_open TYPE i. + DATA lv_js_tag_close TYPE i. DATA lv_curly TYPE i. FIND FIRST OCCURRENCE OF ' 0 AND sy-subrc = 0 AND lv_close_offs = 0 AND mv_indent > 0. + IF ( mv_within_style > 0 OR mv_within_js > 0 ) + AND sy-subrc = 0 AND lv_close_offs = 0 AND mv_indent > 0. lv_shift_back = 1. ENDIF. @@ -359,11 +108,15 @@ CLASS lcl_html_helper IMPLEMENTATION. lv_tags_open = lv_tags - lv_tags_close - lv_tags_single. - FIND ALL OCCURRENCES OF '' IN iv_str MATCH COUNT lv_style_tag_close IGNORING CASE. mv_within_style = mv_within_style + lv_style_tag_open - lv_style_tag_close. - IF mv_within_style > 0. + FIND ALL OCCURRENCES OF '' IN iv_str MATCH COUNT lv_js_tag_close IGNORING CASE. + mv_within_js = mv_within_js + lv_js_tag_open - lv_js_tag_close. + + IF mv_within_style > 0 OR mv_within_js > 0. FIND ALL OCCURRENCES OF '{' IN iv_str MATCH COUNT lv_curly. lv_tags_open = lv_tags_open + lv_curly. FIND ALL OCCURRENCES OF '}' IN iv_str MATCH COUNT lv_curly. @@ -394,16 +147,21 @@ CLASS lcl_html_helper IMPLEMENTATION. METHOD add_anchor. DATA: lv_class TYPE string, - lv_href TYPE string. + lv_href TYPE string, + lv_id TYPE string, + lv_style TYPE string. lv_class = iv_class. - IF iv_opt = gc_html_opt-emphas. + IF iv_opt CA gc_html_opt-emphas. lv_class = lv_class && ' emphasis' ##NO_TEXT. ENDIF. - IF iv_opt = gc_html_opt-cancel. + IF iv_opt CA gc_html_opt-cancel. lv_class = lv_class && ' attention' ##NO_TEXT. ENDIF. + IF iv_opt CA gc_html_opt-crossout. + lv_class = lv_class && ' crossout grey' ##NO_TEXT. + ENDIF. IF lv_class IS NOT INITIAL. SHIFT lv_class LEFT DELETING LEADING space. lv_class = | class="{ lv_class }"|. @@ -420,7 +178,15 @@ CLASS lcl_html_helper IMPLEMENTATION. ENDCASE. ENDIF. - _add_str( |{ iv_txt }| ). + IF iv_id IS NOT INITIAL. + lv_id = | id="{ iv_id }"|. + ENDIF. + + IF iv_style IS NOT INITIAL. + lv_style = | style="{ iv_style }"|. + ENDIF. + + _add_str( |{ iv_txt }| ). ENDMETHOD. "add_action @@ -438,6 +204,7 @@ CLASS lcl_html_toolbar DEFINITION FINAL. iv_txt TYPE string io_sub TYPE REF TO lcl_html_toolbar OPTIONAL iv_act TYPE string OPTIONAL + iv_ico TYPE string OPTIONAL iv_opt TYPE c OPTIONAL iv_typ TYPE c DEFAULT gc_action_type-sapevent, count @@ -448,6 +215,9 @@ CLASS lcl_html_toolbar DEFINITION FINAL. iv_no_separator TYPE abap_bool OPTIONAL iv_vertical TYPE abap_bool OPTIONAL iv_sort TYPE abap_bool OPTIONAL + iv_as_angle TYPE abap_bool OPTIONAL + iv_with_icons TYPE abap_bool OPTIONAL + iv_add_minizone TYPE abap_bool OPTIONAL RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. @@ -455,6 +225,7 @@ CLASS lcl_html_toolbar DEFINITION FINAL. TYPES: BEGIN OF ty_item, txt TYPE string, act TYPE string, + ico TYPE string, sub TYPE REF TO lcl_html_toolbar, opt TYPE char1, typ TYPE char1, @@ -483,47 +254,66 @@ CLASS lcl_html_toolbar IMPLEMENTATION. ls_item-txt = iv_txt. ls_item-act = iv_act. + ls_item-ico = iv_ico. ls_item-sub = io_sub. ls_item-opt = iv_opt. ls_item-typ = iv_typ. APPEND ls_item TO mt_items. ENDMETHOD. "add - METHOD render. + METHOD render. "TODO refactor - DATA: lv_class TYPE string, - lv_last TYPE abap_bool. + DATA: lv_class TYPE string, + lv_is_drop TYPE abap_bool, + lv_last TYPE abap_bool. FIELD-SYMBOLS LIKE LINE OF mt_items. CREATE OBJECT ro_html. + lv_is_drop = boolc( iv_as_droplist_with_label IS NOT INITIAL OR iv_as_angle IS NOT INITIAL ). - IF iv_as_droplist_with_label IS INITIAL. + IF lv_is_drop = abap_false. " Normal menu IF iv_vertical = abap_true. lv_class = 'menu_vertical' ##NO_TEXT. ELSE. lv_class = 'menu' ##NO_TEXT. ENDIF. + ELSEIF iv_as_angle IS NOT INITIAL. + lv_class = 'dropdown dropdown_angle' ##NO_TEXT. ELSE. lv_class = 'dropdown' ##NO_TEXT. ENDIF. ro_html->add( |
| ). - IF iv_as_droplist_with_label IS NOT INITIAL. - lv_class = 'dropbtn'. - IF iv_no_separator = abap_true. - lv_class = lv_class && ' menu_end' ##NO_TEXT. + IF lv_is_drop = abap_true. " Dropdown + IF iv_as_angle = abap_true. + ro_html->add( '
' ). + ELSE. + lv_class = 'dropbtn'. + IF iv_no_separator = abap_true. + lv_class = lv_class && ' menu_end' ##NO_TEXT. + ENDIF. + ro_html->add( |{ iv_as_droplist_with_label }| ). ENDIF. - ro_html->add( |{ iv_as_droplist_with_label }| ). + + IF iv_add_minizone = abap_true. + ro_html->add( '
' ). + ENDIF. + ro_html->add( '' ). ENDIF. ro_html->add( '
' ). ENDMETHOD. "render -ENDCLASS. "lcl_html_toolbar IMPLEMENTATION - -CLASS lcl_log DEFINITION FINAL. - - PUBLIC SECTION. - METHODS: - add - IMPORTING - iv_msgv1 TYPE csequence - iv_msgv2 TYPE csequence OPTIONAL - iv_msgv3 TYPE csequence OPTIONAL - iv_msgv4 TYPE csequence OPTIONAL, - count - RETURNING VALUE(rv_count) TYPE i, - to_html - RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper, - show. - - PRIVATE SECTION. - DATA: mt_log TYPE rs_t_msg. - -ENDCLASS. - -CLASS lcl_log IMPLEMENTATION. - - METHOD to_html. - - DATA: lv_string TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF mt_log. - - CREATE OBJECT ro_html. - - IF count( ) = 0. - RETURN. - ENDIF. - - ro_html->add( '
' ). - LOOP AT mt_log ASSIGNING . - CONCATENATE -msgv1 - -msgv2 - -msgv3 - -msgv4 INTO lv_string SEPARATED BY space. - ro_html->add( lv_string ). - ro_html->add( '
' ). - ENDLOOP. - ro_html->add( '
' ). - - ENDMETHOD. - - METHOD add. - - FIELD-SYMBOLS: LIKE LINE OF mt_log. - - APPEND INITIAL LINE TO mt_log ASSIGNING . - -msgty = 'W'. - -msgid = '00'. - -msgno = '001'. - -msgv1 = iv_msgv1. - -msgv2 = iv_msgv2. - -msgv3 = iv_msgv3. - -msgv4 = iv_msgv4. - - ENDMETHOD. - - METHOD show. - CALL FUNCTION 'RSDC_SHOW_MESSAGES_POPUP' - EXPORTING - i_t_msg = mt_log - i_txt = 'Warning' - i_with_s_on_empty = abap_false - i_one_msg_direct = abap_false - i_one_msg_type_s = abap_false - ##no_text. - ENDMETHOD. - - METHOD count. - rv_count = lines( mt_log ). - ENDMETHOD. - -ENDCLASS. \ No newline at end of file +ENDCLASS. "lcl_html_toolbar IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_html_action_utils.prog.abap b/src/zabapgit_html_action_utils.prog.abap new file mode 100644 index 000000000..8fd1ed7bb --- /dev/null +++ b/src/zabapgit_html_action_utils.prog.abap @@ -0,0 +1,329 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_HTML_ACTION_UTILS +*&---------------------------------------------------------------------* + +*----------------------------------------------------------------------* +* CLASS lcl_html_action_utils DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_html_action_utils DEFINITION FINAL. + PUBLIC SECTION. + + CLASS-METHODS field_keys_to_upper + CHANGING ct_fields TYPE tihttpnvp. + + CLASS-METHODS add_field + IMPORTING name TYPE string + iv TYPE any + CHANGING ct TYPE tihttpnvp. + + CLASS-METHODS get_field + IMPORTING name TYPE string + it TYPE tihttpnvp + CHANGING cv TYPE any. + + CLASS-METHODS jump_encode + IMPORTING iv_obj_type TYPE tadir-object + iv_obj_name TYPE tadir-obj_name + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS jump_decode + IMPORTING iv_string TYPE clike + EXPORTING ev_obj_type TYPE tadir-object + ev_obj_name TYPE tadir-obj_name + RAISING lcx_exception. + + CLASS-METHODS dir_encode + IMPORTING iv_path TYPE string + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS dir_decode + IMPORTING iv_string TYPE clike + RETURNING VALUE(rv_path) TYPE string + RAISING lcx_exception. + + CLASS-METHODS file_encode + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + ig_file TYPE any "assuming ty_file + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS obj_encode + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + ig_object TYPE any "assuming ty_item + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS file_obj_decode + IMPORTING iv_string TYPE clike + EXPORTING ev_key TYPE lcl_persistence_repo=>ty_repo-key + eg_file TYPE any "assuming ty_file + eg_object TYPE any "assuming ty_item + RAISING lcx_exception. + + CLASS-METHODS dbkey_encode + IMPORTING is_key TYPE lcl_persistence_db=>ty_content + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS dbkey_decode + IMPORTING iv_string TYPE clike + RETURNING VALUE(rs_key) TYPE lcl_persistence_db=>ty_content. + + CLASS-METHODS dbcontent_decode + IMPORTING it_postdata TYPE cnht_post_data_tab + RETURNING VALUE(rs_content) TYPE lcl_persistence_db=>ty_content. + + CLASS-METHODS parse_commit_request + IMPORTING it_postdata TYPE cnht_post_data_tab + EXPORTING es_fields TYPE any. + + CLASS-METHODS decode_bg_update + IMPORTING iv_getdata TYPE clike + RETURNING VALUE(rs_fields) TYPE lcl_persistence_background=>ty_background. + + +ENDCLASS. "lcl_html_action_utils DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_html_action_utils IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_html_action_utils IMPLEMENTATION. + + METHOD field_keys_to_upper. + + FIELD-SYMBOLS LIKE LINE OF ct_fields. + + LOOP AT ct_fields ASSIGNING . + -name = to_upper( -name ). + ENDLOOP. + + ENDMETHOD. "field_keys_to_upper + + METHOD add_field. + + DATA ls_field LIKE LINE OF ct. + + FIELD-SYMBOLS TYPE any. + + ls_field-name = name. + + CASE cl_abap_typedescr=>describe_by_data( iv )->kind. + WHEN cl_abap_typedescr=>kind_elem. + ls_field-value = iv. + WHEN cl_abap_typedescr=>kind_struct. + ASSIGN COMPONENT name OF STRUCTURE iv TO . + ASSERT IS ASSIGNED. + ls_field-value = . + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + + APPEND ls_field TO ct. + + ENDMETHOD. "add_field + + METHOD get_field. + + FIELD-SYMBOLS: LIKE LINE OF it, + TYPE any. + + + READ TABLE it ASSIGNING WITH KEY name = name. + IF sy-subrc IS NOT INITIAL. + RETURN. + ENDIF. + + CASE cl_abap_typedescr=>describe_by_data( cv )->kind. + WHEN cl_abap_typedescr=>kind_elem. + cv = -value. + WHEN cl_abap_typedescr=>kind_struct. + ASSIGN COMPONENT name OF STRUCTURE cv TO . + ASSERT IS ASSIGNED. + = -value. + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + + ENDMETHOD. "get_field + + METHOD jump_encode. + + DATA: lt_fields TYPE tihttpnvp. + + + add_field( EXPORTING name = 'TYPE' iv = iv_obj_type CHANGING ct = lt_fields ). + add_field( EXPORTING name = 'NAME' iv = iv_obj_name CHANGING ct = lt_fields ). + + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "jump_encode + + METHOD jump_decode. + + DATA: lt_fields TYPE tihttpnvp. + + + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( |{ iv_string }| ). + + get_field( EXPORTING name = 'TYPE' it = lt_fields CHANGING cv = ev_obj_type ). + get_field( EXPORTING name = 'NAME' it = lt_fields CHANGING cv = ev_obj_name ). + + ENDMETHOD. "jump_decode + + METHOD dir_encode. + + DATA: lt_fields TYPE tihttpnvp. + add_field( EXPORTING name = 'PATH' iv = iv_path CHANGING ct = lt_fields ). + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "dir_encode + + METHOD dir_decode. + + DATA: lt_fields TYPE tihttpnvp. + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( |{ iv_string }| ). + get_field( EXPORTING name = 'PATH' it = lt_fields CHANGING cv = rv_path ). + + ENDMETHOD. "dir_decode + + METHOD file_encode. + + DATA: lt_fields TYPE tihttpnvp. + + + add_field( EXPORTING name = 'KEY' iv = iv_key CHANGING ct = lt_fields ). + add_field( EXPORTING name = 'PATH' iv = ig_file CHANGING ct = lt_fields ). + add_field( EXPORTING name = 'FILENAME' iv = ig_file CHANGING ct = lt_fields ). + + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "file_encode + + METHOD obj_encode. + + DATA: lt_fields TYPE tihttpnvp. + + + add_field( EXPORTING name = 'KEY' iv = iv_key CHANGING ct = lt_fields ). + add_field( EXPORTING name = 'OBJ_TYPE' iv = ig_object CHANGING ct = lt_fields ). + add_field( EXPORTING name = 'OBJ_NAME' iv = ig_object CHANGING ct = lt_fields ). + + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "obj_encode + + METHOD file_obj_decode. + + DATA: lt_fields TYPE tihttpnvp. + + ASSERT eg_file IS SUPPLIED OR eg_object IS SUPPLIED. + + CLEAR: ev_key, eg_file, eg_object. + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( |{ iv_string }| ). + field_keys_to_upper( CHANGING ct_fields = lt_fields ). + + get_field( EXPORTING name = 'KEY' it = lt_fields CHANGING cv = ev_key ). + + IF eg_file IS SUPPLIED. + get_field( EXPORTING name = 'PATH' it = lt_fields CHANGING cv = eg_file ). + get_field( EXPORTING name = 'FILENAME' it = lt_fields CHANGING cv = eg_file ). + ENDIF. + + IF eg_object IS SUPPLIED. + get_field( EXPORTING name = 'OBJ_TYPE' it = lt_fields CHANGING cv = eg_object ). + get_field( EXPORTING name = 'OBJ_NAME' it = lt_fields CHANGING cv = eg_object ). + ENDIF. + + ENDMETHOD. "file_decode + + METHOD dbkey_encode. + + DATA: lt_fields TYPE tihttpnvp. + + add_field( EXPORTING name = 'TYPE' iv = is_key-type CHANGING ct = lt_fields ). + add_field( EXPORTING name = 'VALUE' iv = is_key-value CHANGING ct = lt_fields ). + + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "dbkey_encode + + METHOD dbkey_decode. + + DATA: lt_fields TYPE tihttpnvp. + + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( |{ iv_string }| ). + field_keys_to_upper( CHANGING ct_fields = lt_fields ). + + get_field( EXPORTING name = 'TYPE' it = lt_fields CHANGING cv = rs_key-type ). + get_field( EXPORTING name = 'VALUE' it = lt_fields CHANGING cv = rs_key-value ). + + ENDMETHOD. "dbkey_decode + + METHOD dbcontent_decode. + + DATA: lt_fields TYPE tihttpnvp, + lv_string TYPE string. + + + CONCATENATE LINES OF it_postdata INTO lv_string. + rs_content = dbkey_decode( lv_string ). + + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). + field_keys_to_upper( CHANGING ct_fields = lt_fields ). + + get_field( EXPORTING name = 'XMLDATA' it = lt_fields CHANGING cv = rs_content-data_str ). + IF rs_content-data_str(1) <> '<' AND rs_content-data_str+1(1) = '<'. " Hmmm ??? + rs_content-data_str = rs_content-data_str+1. + ELSE. + CLEAR rs_content-data_str. + ENDIF. + + ENDMETHOD. "dbcontent_decode + + METHOD parse_commit_request. + + CONSTANTS: lc_replace TYPE string VALUE '<>'. + + DATA: lv_string TYPE string, + lt_fields TYPE tihttpnvp. + + FIELD-SYMBOLS TYPE string. + + CLEAR es_fields. + + CONCATENATE LINES OF it_postdata INTO lv_string. + REPLACE ALL OCCURRENCES OF gc_newline IN lv_string WITH lc_replace. + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). + field_keys_to_upper( CHANGING ct_fields = lt_fields ). + + get_field( EXPORTING name = 'REPO_KEY' it = lt_fields CHANGING cv = es_fields ). + get_field( EXPORTING name = 'USERNAME' it = lt_fields CHANGING cv = es_fields ). + get_field( EXPORTING name = 'EMAIL' it = lt_fields CHANGING cv = es_fields ). + get_field( EXPORTING name = 'COMMENT' it = lt_fields CHANGING cv = es_fields ). + get_field( EXPORTING name = 'BODY' it = lt_fields CHANGING cv = es_fields ). + + ASSIGN COMPONENT 'BODY' OF STRUCTURE es_fields TO . + ASSERT IS ASSIGNED. + REPLACE ALL OCCURRENCES OF lc_replace IN WITH gc_newline. + + ASSERT es_fields IS NOT INITIAL. + + ENDMETHOD. "parse_commit_request + + METHOD decode_bg_update. + + DATA: lt_fields TYPE tihttpnvp. + + + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( |{ iv_getdata }| ). + field_keys_to_upper( CHANGING ct_fields = lt_fields ). + + get_field( EXPORTING name = 'METHOD' it = lt_fields CHANGING cv = rs_fields ). + get_field( EXPORTING name = 'USERNAME' it = lt_fields CHANGING cv = rs_fields ). + get_field( EXPORTING name = 'PASSWORD' it = lt_fields CHANGING cv = rs_fields ). + get_field( EXPORTING name = 'AMETHOD' it = lt_fields CHANGING cv = rs_fields ). + get_field( EXPORTING name = 'ANAME' it = lt_fields CHANGING cv = rs_fields ). + get_field( EXPORTING name = 'AMAIL' it = lt_fields CHANGING cv = rs_fields ). + + ASSERT NOT rs_fields IS INITIAL. + + ENDMETHOD. "decode_bg_update + +ENDCLASS. "lcl_html_action_utils IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_html_action_utils.prog.xml b/src/zabapgit_html_action_utils.prog.xml new file mode 100644 index 000000000..a83a04c8a --- /dev/null +++ b/src/zabapgit_html_action_utils.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_HTML_ACTION_UTILS + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_HTML_ACTION_UTILS + 34 + + + + + + diff --git a/src/zabapgit_http.prog.abap b/src/zabapgit_http.prog.abap new file mode 100644 index 000000000..1f08d18f5 --- /dev/null +++ b/src/zabapgit_http.prog.abap @@ -0,0 +1,520 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_HTTP +*&---------------------------------------------------------------------* + +CLASS lcl_http_digest DEFINITION FINAL. + + PUBLIC SECTION. + METHODS: + constructor + IMPORTING + ii_client TYPE REF TO if_http_client + iv_username TYPE string + iv_password TYPE string + RAISING lcx_exception, + run + IMPORTING + ii_client TYPE REF TO if_http_client + RAISING lcx_exception. + + PRIVATE SECTION. + DATA: mv_ha1 TYPE string, + mv_username TYPE string, + mv_realm TYPE string, + mv_qop TYPE string, + mv_nonce TYPE string. + + CLASS-DATA: gv_nc TYPE n LENGTH 8. + + CLASS-METHODS: + md5 + IMPORTING + iv_data TYPE string + RETURNING + VALUE(rv_hash) TYPE string + RAISING lcx_exception. + + METHODS: + hash + IMPORTING + iv_qop TYPE string + iv_nonce TYPE string + iv_uri TYPE string + iv_method TYPE string + iv_cnonse TYPE string + RETURNING + VALUE(rv_response) TYPE string + RAISING lcx_exception, + parse + IMPORTING + ii_client TYPE REF TO if_http_client. + +ENDCLASS. + +CLASS lcl_http_client DEFINITION FINAL. + + PUBLIC SECTION. + + METHODS: + constructor + IMPORTING ii_client TYPE REF TO if_http_client, + close, + set_digest + IMPORTING io_digest TYPE REF TO lcl_http_digest, + send_receive_close + IMPORTING + iv_data TYPE xstring + RETURNING + VALUE(rv_data) TYPE xstring + RAISING lcx_exception, + get_cdata + RETURNING VALUE(rv_value) TYPE string, + check_http_200 + RAISING lcx_exception, + send_receive + RAISING lcx_exception, + set_headers + IMPORTING iv_url TYPE string + iv_service TYPE string + RAISING lcx_exception. + + PRIVATE SECTION. + DATA: mi_client TYPE REF TO if_http_client, + mo_digest TYPE REF TO lcl_http_digest. + +ENDCLASS. + +CLASS lcl_http_client IMPLEMENTATION. + + METHOD constructor. + mi_client = ii_client. + ENDMETHOD. + + METHOD set_digest. + mo_digest = io_digest. + ENDMETHOD. + + METHOD send_receive_close. + +* do not use set_cdata as it modifies the Content-Type header field + mi_client->request->set_data( iv_data ). + send_receive( ). + check_http_200( ). + rv_data = mi_client->response->get_data( ). + mi_client->close( ). + + ENDMETHOD. + + METHOD get_cdata. + rv_value = mi_client->response->get_cdata( ). + ENDMETHOD. + + METHOD close. + mi_client->close( ). + ENDMETHOD. + + METHOD set_headers. + + DATA: lv_value TYPE string. + + + mi_client->request->set_header_field( + name = '~request_method' + value = 'POST' ). + + lv_value = lcl_url=>path_name( iv_url ) && + '/git-' && + iv_service && + '-pack'. + mi_client->request->set_header_field( + name = '~request_uri' + value = lv_value ). + + lv_value = 'application/x-git-' + && iv_service && '-pack-request'. "#EC NOTEXT + mi_client->request->set_header_field( + name = 'Content-Type' + value = lv_value ). "#EC NOTEXT + + lv_value = 'application/x-git-' + && iv_service && '-pack-result'. "#EC NOTEXT + mi_client->request->set_header_field( + name = 'Accept' + value = lv_value ). "#EC NOTEXT + + IF mo_digest IS BOUND. + mo_digest->run( mi_client ). + ENDIF. + + ENDMETHOD. "set_headers + + METHOD send_receive. + + DATA lv_text TYPE string. + + mi_client->send( ). + mi_client->receive( + EXCEPTIONS + http_communication_failure = 1 + http_invalid_state = 2 + http_processing_failed = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + CASE sy-subrc. + WHEN 1. + " make sure: + " a) SSL is setup properly in STRUST + " b) no firewalls + " check trace file in transaction SMICM + lv_text = 'HTTP Communication Failure'. "#EC NOTEXT + WHEN 2. + lv_text = 'HTTP Invalid State'. "#EC NOTEXT + WHEN 3. + lv_text = 'HTTP Processing failed'. "#EC NOTEXT + WHEN OTHERS. + lv_text = 'Another error occured'. "#EC NOTEXT + ENDCASE. + lcx_exception=>raise( lv_text ). + ENDIF. + + ENDMETHOD. "send_receive + + METHOD check_http_200. + + DATA: lv_code TYPE i, + lv_text TYPE string. + + + mi_client->response->get_status( + IMPORTING + code = lv_code ). + CASE lv_code. + WHEN 200. + RETURN. + WHEN 302. + lcx_exception=>raise( 'HTTP redirect, check URL' ). + WHEN 401. + lcx_exception=>raise( 'HTTP 401, unauthorized' ). + WHEN 403. + lcx_exception=>raise( 'HTTP 403, forbidden' ). + WHEN 404. + lcx_exception=>raise( 'HTTP 404, not found' ). + WHEN 415. + lcx_exception=>raise( 'HTTP 415, unsupported media type' ). + WHEN OTHERS. + lv_text = mi_client->response->get_cdata( ). + lcx_exception=>raise( |HTTP error code: { lv_code }, { lv_text }| ). + ENDCASE. + + ENDMETHOD. "http_200 + +ENDCLASS. + +CLASS lcl_http_digest IMPLEMENTATION. + + METHOD constructor. + + parse( ii_client ). + + mv_ha1 = md5( |{ iv_username }:{ mv_realm }:{ iv_password }| ). + + mv_username = iv_username. + + ENDMETHOD. + + METHOD hash. + + DATA: lv_ha2 TYPE string. + + + lv_ha2 = md5( |{ iv_method }:{ iv_uri }| ). + + ASSERT NOT iv_cnonse IS INITIAL. + + rv_response = md5( |{ mv_ha1 }:{ iv_nonce }:{ gv_nc }:{ iv_cnonse }:{ iv_qop }:{ lv_ha2 }| ). + + ENDMETHOD. + + METHOD run. + + DATA: lv_response TYPE string, + lv_method TYPE string, + lv_cnonce TYPE string, + lv_uri TYPE string, + lv_auth TYPE string. + + + ASSERT NOT mv_nonce IS INITIAL. + + lv_method = ii_client->request->get_header_field( '~request_method' ). + lv_uri = ii_client->request->get_header_field( '~request_uri' ). + + CALL FUNCTION 'GENERAL_GET_RANDOM_STRING' + EXPORTING + number_chars = 24 + IMPORTING + random_string = lv_cnonce. + + lv_response = hash( + iv_qop = mv_qop + iv_nonce = mv_nonce + iv_uri = lv_uri + iv_method = lv_method + iv_cnonse = lv_cnonce ). + +* client response + lv_auth = |Digest username="{ mv_username + }", realm="{ mv_realm + }", nonce="{ mv_nonce + }", uri="{ lv_uri + }", qop={ mv_qop + }, nc={ gv_nc + }, cnonce="{ lv_cnonce + }", response="{ lv_response }"|. + + ii_client->request->set_header_field( + name = 'Authorization' + value = lv_auth ). + + ENDMETHOD. + + METHOD parse. + + DATA: lv_value TYPE string. + + + lv_value = ii_client->response->get_header_field( 'www-authenticate' ). + + FIND REGEX 'realm="([\w ]+)"' IN lv_value SUBMATCHES mv_realm. + FIND REGEX 'qop="(\w+)"' IN lv_value SUBMATCHES mv_qop. + FIND REGEX 'nonce="([\w=/+\$]+)"' IN lv_value SUBMATCHES mv_nonce. + + ENDMETHOD. + + METHOD md5. + + DATA: lv_xstr TYPE xstring, + lv_hash TYPE xstring. + + + lv_xstr = lcl_convert=>string_to_xstring_utf8( iv_data ). + + CALL FUNCTION 'CALCULATE_HASH_FOR_RAW' + EXPORTING + alg = 'MD5' + data = lv_xstr + IMPORTING + hashxstring = lv_hash + EXCEPTIONS + unknown_alg = 1 + param_error = 2 + internal_error = 3 + OTHERS = 4. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from CALCULATE_HASH_FOR_RAW' ). + ENDIF. + + rv_hash = lv_hash. + TRANSLATE rv_hash TO LOWER CASE. + + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_http DEFINITION FINAL. + + PUBLIC SECTION. + CONSTANTS: BEGIN OF gc_scheme, + digest TYPE string VALUE 'Digest', + END OF gc_scheme. + + CLASS-METHODS: + get_agent + RETURNING VALUE(rv_agent) TYPE string, + create_by_url + IMPORTING iv_url TYPE string + iv_service TYPE string + RETURNING VALUE(ro_client) TYPE REF TO lcl_http_client + RAISING lcx_exception. + + PRIVATE SECTION. + CLASS-METHODS: + check_auth_requested + IMPORTING ii_client TYPE REF TO if_http_client + RETURNING VALUE(rv_auth_requested) TYPE abap_bool + RAISING lcx_exception, + is_local_system + IMPORTING iv_url TYPE string + RETURNING VALUE(rv_bool) TYPE abap_bool, + acquire_login_details + IMPORTING ii_client TYPE REF TO if_http_client + io_client TYPE REF TO lcl_http_client + iv_url TYPE string + RETURNING VALUE(rv_scheme) TYPE string + RAISING lcx_exception. + +ENDCLASS. + +CLASS lcl_http IMPLEMENTATION. + + METHOD get_agent. + +* bitbucket require agent prefix = "git/" + rv_agent = 'git/abapGit-' && gc_abap_version. + + ENDMETHOD. + + METHOD create_by_url. + + DATA: lv_uri TYPE string, + lv_scheme TYPE string, + li_client TYPE REF TO if_http_client, + lo_settings TYPE REF TO lcl_settings. + + + lo_settings = lcl_app=>settings( )->read( ). + + cl_http_client=>create_by_url( + EXPORTING + url = lcl_url=>host( iv_url ) + ssl_id = 'ANONYM' + proxy_host = lo_settings->get_proxy_url( ) + proxy_service = lo_settings->get_proxy_port( ) + IMPORTING + client = li_client ). + + CREATE OBJECT ro_client + EXPORTING + ii_client = li_client. + + IF is_local_system( iv_url ) = abap_true. + li_client->send_sap_logon_ticket( ). + ENDIF. + + li_client->request->set_cdata( '' ). + li_client->request->set_header_field( + name = '~request_method' + value = 'GET' ). + li_client->request->set_header_field( + name = 'user-agent' + value = get_agent( ) ). "#EC NOTEXT + lv_uri = lcl_url=>path_name( iv_url ) && + '/info/refs?service=git-' && + iv_service && + '-pack'. + li_client->request->set_header_field( + name = '~request_uri' + value = lv_uri ). + + " Disable internal auth dialog (due to its unclarity) + li_client->propertytype_logon_popup = if_http_client=>co_disabled. + + lcl_login_manager=>load( iv_uri = iv_url + ii_client = li_client ). + + ro_client->send_receive( ). + IF check_auth_requested( li_client ) = abap_true. + lv_scheme = acquire_login_details( ii_client = li_client + io_client = ro_client + iv_url = iv_url ). + ro_client->send_receive( ). + ENDIF. + ro_client->check_http_200( ). + + IF lv_scheme <> gc_scheme-digest. + lcl_login_manager=>save( iv_uri = iv_url + ii_client = li_client ). + ENDIF. + + ENDMETHOD. + + METHOD is_local_system. + + DATA: lv_host TYPE string, + lt_list TYPE STANDARD TABLE OF icm_sinfo2 WITH DEFAULT KEY. + + + CALL FUNCTION 'ICM_GET_INFO2' + TABLES + servlist = lt_list + EXCEPTIONS + icm_error = 1 + icm_timeout = 2 + icm_not_authorized = 3 + OTHERS = 4. + IF sy-subrc <> 0. + RETURN. + ENDIF. + + FIND REGEX 'https?://([^/^:]*)' IN iv_url + SUBMATCHES lv_host. + + READ TABLE lt_list WITH KEY hostname = lv_host TRANSPORTING NO FIELDS. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. + + METHOD check_auth_requested. + + DATA: lv_code TYPE i. + + ii_client->response->get_status( + IMPORTING + code = lv_code ). + IF lv_code = 401. + rv_auth_requested = abap_true. + ENDIF. + + ENDMETHOD. "check_auth_requested + + METHOD acquire_login_details. + + DATA: lv_default_user TYPE string, + lv_user TYPE string, + lv_pass TYPE string, + lo_digest TYPE REF TO lcl_http_digest. + + + lv_default_user = lcl_app=>user( )->get_repo_username( iv_url ). + lv_user = lv_default_user. + + lcl_password_dialog=>popup( + EXPORTING + iv_repo_url = iv_url + CHANGING + cv_user = lv_user + cv_pass = lv_pass ). + + IF lv_user IS INITIAL. + lcx_exception=>raise( 'HTTP 401, unauthorized' ). + ENDIF. + + IF lv_user <> lv_default_user. + lcl_app=>user( )->set_repo_username( iv_url = iv_url + iv_username = lv_user ). + ENDIF. + + rv_scheme = ii_client->response->get_header_field( 'www-authenticate' ). + FIND REGEX '^(\w+)' IN rv_scheme SUBMATCHES rv_scheme. + + CASE rv_scheme. + WHEN gc_scheme-digest. +* https://en.wikipedia.org/wiki/Digest_access_authentication +* e.g. used by https://www.gerritcodereview.com/ + CREATE OBJECT lo_digest + EXPORTING + ii_client = ii_client + iv_username = lv_user + iv_password = lv_pass. + lo_digest->run( ii_client ). + io_client->set_digest( lo_digest ). + WHEN OTHERS. +* https://en.wikipedia.org/wiki/Basic_access_authentication + ii_client->authenticate( + username = lv_user + password = lv_pass ). + ENDCASE. + + ENDMETHOD. "acquire_login_details + +ENDCLASS. \ No newline at end of file diff --git a/src/zabapgit_http.prog.xml b/src/zabapgit_http.prog.xml new file mode 100644 index 000000000..e17d9183e --- /dev/null +++ b/src/zabapgit_http.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_HTTP + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_HTTP + 21 + + + + + + diff --git a/src/zabapgit_js_common.w3mi.data.js b/src/zabapgit_js_common.w3mi.data.js new file mode 100644 index 000000000..b8556c7e7 --- /dev/null +++ b/src/zabapgit_js_common.w3mi.data.js @@ -0,0 +1,208 @@ +/********************************************************** + * ABAPGIT JS function library + **********************************************************/ + +/********************************************************** + * Polyfills + **********************************************************/ + +// Bind polyfill (for IE7), taken from https://developer.mozilla.org/ +if (!Function.prototype.bind) { + Function.prototype.bind = function(oThis) { + if (typeof this !== "function") { + throw new TypeError("Function.prototype.bind - subject is not callable"); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function() {}, + fBound = function() { + return fToBind.apply(this instanceof fNOP + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + if (this.prototype) { + fNOP.prototype = this.prototype; + } + fBound.prototype = new fNOP(); + + return fBound; + }; +} + +/********************************************************** + * Common functions + **********************************************************/ + +// Output text to the debug div +function debugOutput(text, dstID) { + var stdout = document.getElementById(dstID || "debug-output"); + var wrapped = "

" + text + "

"; + stdout.innerHTML = stdout.innerHTML + wrapped; +} + +// Create hidden form and submit with sapevent +function submitSapeventForm(params, action) { + var form = document.createElement("form"); + form.setAttribute("method", "post"); + form.setAttribute("action", "sapevent:" + action); + + for(var key in params) { + var hiddenField = document.createElement("input"); + hiddenField.setAttribute("type", "hidden"); + hiddenField.setAttribute("name", key); + hiddenField.setAttribute("value", params[key]); + form.appendChild(hiddenField); + } + + document.body.appendChild(form); + form.submit(); +} + +// Set focus to a control +function setInitialFocus(id) { + document.getElementById(id).focus(); +} + +// Submit an existing form +function submitFormById(id) { + document.getElementById(id).submit(); +} + +/********************************************************** + * STAGE PAGE Logic + **********************************************************/ + +// Stage helper constructor +function StageHelper(params) { + this.pageSeed = params.seed; + this.tabId = params.stageTabId; + this.formAction = params.formAction; + this.commitNodeId = params.commitNodeId; + this.commitAllNodeId = params.commitAllNodeId; + this.choiseCount = 0; + this.setHook(); +} + +// Hook global click listener on table, load/unload actions +StageHelper.prototype.setHook = function() { + var stageTab = document.getElementById(this.tabId); + + if (stageTab.addEventListener) { + stageTab.addEventListener("click", this.onEvent.bind(this)); + } else { + stageTab.attachEvent("onclick", this.onEvent.bind(this)); + } + + window.onbeforeunload = this.onPageUnload.bind(this); + window.onload = this.onPageLoad.bind(this); +} + +// Store table state on leaving the page +StageHelper.prototype.onPageUnload = function() { + var data = this.collectData(); + window.sessionStorage.setItem(this.pageSeed, JSON.stringify(data)); +} + +// Re-store table state on entering the page +StageHelper.prototype.onPageLoad = function() { + var data = JSON.parse(window.sessionStorage.getItem(this.pageSeed)); + var stage = document.getElementById(this.tabId); + + for (var i = stage.rows.length - 1; i >= 0; i--) { + var tr = stage.rows[i]; + if (tr.parentNode.tagName == "THEAD") continue; + var context = tr.parentNode.className; + var cmd = data[tr.cells[1].innerText]; + if (!cmd) continue; + + this.formatTR(tr, cmd, context); + this.choiseCount += (this.countChoiceImpact(cmd) > 0) ? 1 : 0; + } + + this.updateMenu(); +} + +// Event handler, change status +StageHelper.prototype.onEvent = function (event) { + if (!event.target) { + if (event.srcElement) { event.target = event.srcElement; } + else { return; } + } + + if (event.target.tagName != "A") return; + + var td = event.target.parentNode; + if (!td || td.tagName != "TD" || td.className != "cmd") return; + + var cmd = event.target.innerText; + var tr = td.parentNode; + var context = tr.parentNode.className; + + switch (cmd) { + case "add": cmd = "A"; break; + case "remove": cmd = "R"; break; + case "ignore": cmd = "I"; break; + case "reset": cmd = "?"; break; + } + + this.formatTR(tr, cmd, context); + this.choiseCount += this.countChoiceImpact(cmd); + this.updateMenu(); +} + +// Update action counter -> affects menu update after +StageHelper.prototype.countChoiceImpact = function (cmd) { + if ("ARI".indexOf(cmd) > -1) { return 1; } + else if ("?".indexOf(cmd) > -1) { return -1; } + else { alert("Unknown command"); } +} + +// Re-format table line +StageHelper.prototype.formatTR = function (tr, cmd, context) { + var cmdReset = "reset"; + var cmdLocal = "add"; + var cmdRemote = "ignoreremove"; + + tr.cells[0].innerText = cmd; + if (cmd == "?") { + tr.cells[0].style.color = "#CCC"; //grey + tr.cells[2].innerHTML = (context == "local") ? cmdLocal : cmdRemote; + } else { + tr.cells[0].style.color = ""; + tr.cells[2].innerHTML = cmdReset; + } +} + +// Update menu items visibility +StageHelper.prototype.updateMenu = function () { + if (this.choiseCount > 0) { + document.getElementById(this.commitNodeId).style.display = "inline"; + document.getElementById(this.commitAllNodeId).style.display = "none"; + } else { + document.getElementById(this.commitNodeId).style.display = "none"; + document.getElementById(this.commitAllNodeId).style.display = "inline"; + } +} + +// Submin stage state to the server +StageHelper.prototype.submit = function () { + var data = this.collectData(); + submitSapeventForm(data, this.formAction); +} + +// Extract data from the table +StageHelper.prototype.collectData = function () { + var stage = document.getElementById(this.tabId); + var data = {}; + + for (var i = 0; i < stage.rows.length; i++) { + var row = stage.rows[i]; + if (row.parentNode.tagName == "THEAD") continue; + data[row.cells[1].innerText] = row.cells[0].innerText; + } + + return data; +} diff --git a/src/zabapgit_js_common.w3mi.xml b/src/zabapgit_js_common.w3mi.xml new file mode 100644 index 000000000..51f904696 --- /dev/null +++ b/src/zabapgit_js_common.w3mi.xml @@ -0,0 +1,29 @@ + + + + + ZABAPGIT_JS_COMMON + Abapgit common JS library + + + MI + ZABAPGIT_JS_COMMON + fileextension + .js + + + MI + ZABAPGIT_JS_COMMON + filename + common.js + + + MI + ZABAPGIT_JS_COMMON + mimetype + text/javascript + + + + + diff --git a/src/zabapgit_macros.prog.abap b/src/zabapgit_macros.prog.abap new file mode 100644 index 000000000..5bf603e19 --- /dev/null +++ b/src/zabapgit_macros.prog.abap @@ -0,0 +1,23 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_MACROS +*&---------------------------------------------------------------------* + +* Macros + +DEFINE _object_check_timestamp. + IF sy-subrc = 0 AND &1 IS NOT INITIAL AND &2 IS NOT INITIAL. + cl_abap_tstmp=>systemtstmp_syst2utc( + EXPORTING syst_date = &1 + syst_time = &2 + IMPORTING utc_tstmp = lv_ts ). + IF lv_ts < iv_timestamp. + rv_changed = abap_false. " Unchanged + ELSE. + rv_changed = abap_true. + RETURN. + ENDIF. + ELSE. " Not found? => changed + rv_changed = abap_true. + RETURN. + ENDIF. +END-OF-DEFINITION. \ No newline at end of file diff --git a/src/zabapgit_macros.prog.xml b/src/zabapgit_macros.prog.xml new file mode 100644 index 000000000..0e9ebfa35 --- /dev/null +++ b/src/zabapgit_macros.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_MACROS + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_MACROS + 23 + + + + + + diff --git a/src/zabapgit_migrations.prog.abap b/src/zabapgit_migrations.prog.abap new file mode 100644 index 000000000..a8f3f0aa0 --- /dev/null +++ b/src/zabapgit_migrations.prog.abap @@ -0,0 +1,93 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_MIGRATIONS +*&---------------------------------------------------------------------* + +CLASS lcl_migrations DEFINITION FINAL. + PUBLIC SECTION. + + CLASS-METHODS run + RAISING lcx_exception. + CLASS-METHODS rebuild_local_checksums_161112 + RAISING lcx_exception. + +ENDCLASS. "lcl_migrations + +CLASS lcl_migrations IMPLEMENTATION. + + METHOD run. + " Migrate STDTEXT to TABLE + lcl_persistence_migrate=>run( ). + + " Rebuild local file checksums + rebuild_local_checksums_161112( ). + + ENDMETHOD. " run. + + METHOD rebuild_local_checksums_161112. + + DATA: lt_repos TYPE lcl_repo_srv=>ty_repo_tt, + lv_repo_list TYPE string, + lv_question TYPE string, + lv_answer TYPE c, + lv_index TYPE i, + lo_repo TYPE REF TO lcl_repo_online. + + FIELD-SYMBOLS: LIKE LINE OF lt_repos. + + lt_repos = lcl_app=>repo_srv( )->list( ). + + LOOP AT lt_repos ASSIGNING . + lv_index = sy-tabix. + + IF ->is_offline( ) = abap_true. " Skip local repos + DELETE lt_repos INDEX lv_index. + CONTINUE. + ENDIF. + + " Ignore empty repos or repos with file checksums + IF lines( ->get_local_checksums( ) ) = 0 + OR lines( ->get_local_checksums_per_file( ) ) > 0 . + DELETE lt_repos INDEX lv_index. + CONTINUE. + ENDIF. + + lv_repo_list = lv_repo_list && `, ` && ->get_name( ). + + ENDLOOP. + + IF lines( lt_repos ) = 0. + RETURN. " All OK + ENDIF. + + SHIFT lv_repo_list BY 2 PLACES LEFT. " Remove leading ', ' + + lv_question = 'abapGit wants to rebuild missing local checksums' + && ' (changes from 2016-12-11).' + && ' Generally this is safe except if there are both local ' + && ' and remote changes at the same time. If unsure, please' + && ' skip and update repos individually' + && ' by "Advances/Update local checksums" command.' + && | Repos affected: { lv_repo_list }|. + + lv_answer = lcl_popups=>popup_to_confirm( + titlebar = 'Warning' + text_question = lv_question + text_button_1 = 'OK' + icon_button_1 = 'ICON_OK' + text_button_2 = 'Skip update' + icon_button_2 = 'ICON_CANCEL' + default_button = '2' + display_cancel_button = abap_false ). "#EC NOTEXT + + IF lv_answer = '2'. + RETURN. + ENDIF. + + LOOP AT lt_repos ASSIGNING . + lo_repo ?= . + lo_repo->rebuild_local_checksums( ). + ENDLOOP. + + ENDMETHOD. " rebuild_local_checksums_20161112. + +ENDCLASS. "lcl_migrations \ No newline at end of file diff --git a/src/zabapgit_migrations.prog.xml b/src/zabapgit_migrations.prog.xml new file mode 100644 index 000000000..69876d498 --- /dev/null +++ b/src/zabapgit_migrations.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_MIGRATIONS + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_MIGRATIONS + 27 + + + + + + diff --git a/src/zabapgit_object.prog.abap b/src/zabapgit_object.prog.abap deleted file mode 100644 index 97581478e..000000000 --- a/src/zabapgit_object.prog.abap +++ /dev/null @@ -1,2397 +0,0 @@ -*&---------------------------------------------------------------------* -*& Include ZABAPGIT_OBJECT -*&---------------------------------------------------------------------* - -*----------------------------------------------------------------------* -* CLASS lcl_objects IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_objects IMPLEMENTATION. - - METHOD warning_overwrite. - - DATA: lv_index TYPE i, - lv_answer TYPE c, - lv_question TYPE string, - lt_before TYPE lcl_persistence_repo=>ty_local_checksum_tt, - lt_current TYPE lcl_persistence_repo=>ty_local_checksum_tt. - - FIELD-SYMBOLS: LIKE LINE OF lt_before, - LIKE LINE OF lt_current, - LIKE LINE OF ct_results. - - - lt_before = io_repo->get_local_checksums( ). - lt_current = io_repo->build_local_checksums( ). - - LOOP AT ct_results ASSIGNING . - lv_index = sy-tabix. - - READ TABLE lt_before ASSIGNING - WITH KEY item-obj_type = -obj_type - item-obj_name = -obj_name. - IF sy-subrc <> 0. - CONTINUE. - ENDIF. - - READ TABLE lt_current ASSIGNING - WITH KEY item-obj_type = -obj_type - item-obj_name = -obj_name. - IF sy-subrc <> 0. - CONTINUE. - ENDIF. - - IF -sha1 <> -sha1. - lv_question = |It looks like object { -obj_type - } { -obj_name - } has been modified locally, overwrite object?|. - - CALL FUNCTION 'POPUP_TO_CONFIRM' - EXPORTING - titlebar = 'Warning' - text_question = lv_question - display_cancel_button = abap_false - IMPORTING - answer = lv_answer - EXCEPTIONS - text_not_found = 1 - OTHERS = 2 ##NO_TEXT. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from POPUP_TO_CONFIRM' ). - ENDIF. - - IF lv_answer = '2'. - DELETE ct_results INDEX lv_index. - ENDIF. - - ENDIF. - - ENDLOOP. - - ENDMETHOD. - - METHOD warning_package. - - DATA: lv_question TYPE c LENGTH 200, - lv_answer TYPE c, - ls_tadir TYPE tadir. - - - ls_tadir = lcl_tadir=>read_single( iv_object = is_item-obj_type - iv_obj_name = is_item-obj_name ). - IF NOT ls_tadir IS INITIAL AND ls_tadir-devclass <> iv_package. - CONCATENATE 'Overwrite object' is_item-obj_type is_item-obj_name - 'from package' ls_tadir-devclass - INTO lv_question SEPARATED BY space. "#EC NOTEXT - - CALL FUNCTION 'POPUP_TO_CONFIRM' - EXPORTING - titlebar = 'Warning' - text_question = lv_question - text_button_1 = 'Ok' - icon_button_1 = 'ICON_DELETE' - text_button_2 = 'Cancel' - icon_button_2 = 'ICON_CANCEL' - default_button = '2' - display_cancel_button = abap_false - IMPORTING - answer = lv_answer - EXCEPTIONS - text_not_found = 1 - OTHERS = 2. "#EC NOTEXT - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from POPUP_TO_CONFIRM' ). - ENDIF. - - IF lv_answer = '2'. - rv_cancel = abap_true. - ENDIF. - - ENDIF. - - ENDMETHOD. "check_warning - - METHOD update_package_tree. - - DATA: lt_packages TYPE lcl_sap_package=>ty_devclass_tt, - lv_package LIKE LINE OF lt_packages, - lv_tree TYPE dirtree-tname. - - - lt_packages = lcl_sap_package=>list_subpackages( iv_package ). - APPEND iv_package TO lt_packages. - - LOOP AT lt_packages INTO lv_package. -* update package tree for SE80 - lv_tree = 'EU_' && lv_package. - CALL FUNCTION 'WB_TREE_ACTUALIZE' - EXPORTING - tree_name = lv_tree - without_crossreference = abap_true - with_tcode_index = abap_true. - ENDLOOP. - - ENDMETHOD. "update_package_tree - - METHOD create_object. - - TYPES: BEGIN OF ty_obj_serializer_map, - item LIKE is_item, - metadata LIKE is_metadata, - END OF ty_obj_serializer_map. - - STATICS st_obj_serializer_map - TYPE SORTED TABLE OF ty_obj_serializer_map WITH UNIQUE KEY item. - - DATA: lv_message TYPE string, - lv_class_name TYPE string, - ls_obj_serializer_map LIKE LINE OF st_obj_serializer_map. - - - READ TABLE st_obj_serializer_map - INTO ls_obj_serializer_map WITH KEY item = is_item. - IF sy-subrc = 0. - lv_class_name = ls_obj_serializer_map-metadata-class. - ELSEIF is_metadata IS NOT INITIAL. -* Metadata is provided only on serialization -* Once this has been triggered, the same serializer shall be used -* for subsequent processes. -* Thus, buffer the metadata afterwards - ls_obj_serializer_map-item = is_item. - ls_obj_serializer_map-metadata = is_metadata. - INSERT ls_obj_serializer_map INTO TABLE st_obj_serializer_map. - - lv_class_name = is_metadata-class. - ELSE. - lv_class_name = class_name( is_item ). - ENDIF. - - TRY. - CREATE OBJECT ri_obj TYPE (lv_class_name) - EXPORTING - is_item = is_item - iv_language = iv_language. - CATCH cx_sy_create_object_error. - TRY. -* 2nd step, try looking for plugins - CREATE OBJECT ri_obj TYPE lcl_objects_bridge - EXPORTING - is_item = is_item. - CATCH cx_sy_create_object_error. - CONCATENATE 'Object type' is_item-obj_type 'not supported, serialize' - INTO lv_message - SEPARATED BY space. "#EC NOTEXT - lcx_exception=>raise( lv_message ). - ENDTRY. - ENDTRY. - - ENDMETHOD. "create_object - - METHOD is_supported. - - TRY. - create_object( is_item = is_item - iv_language = gc_english ). - rv_bool = abap_true. - CATCH lcx_exception. - rv_bool = abap_false. - ENDTRY. - - ENDMETHOD. "is_supported - - METHOD supported_list. - - DATA: lv_type LIKE LINE OF rt_types, - lt_snode TYPE TABLE OF snode. - - FIELD-SYMBOLS: LIKE LINE OF lt_snode. - - - CALL FUNCTION 'WB_TREE_ACTUALIZE' - EXPORTING - tree_name = 'PG_ZABAPGIT' - without_crossreference = abap_true - with_tcode_index = abap_true - TABLES - p_tree = lt_snode. - - DELETE lt_snode WHERE type <> 'OPL' - OR name NP 'LCL_OBJECT_++++'. - - LOOP AT lt_snode ASSIGNING . - lv_type = -name+11. - APPEND lv_type TO rt_types. - ENDLOOP. - - ENDMETHOD. "supported_list - - METHOD exists. - - DATA: li_obj TYPE REF TO lif_object. - - - TRY. - li_obj = create_object( is_item = is_item - iv_language = gc_english ). - rv_bool = li_obj->exists( ). - CATCH lcx_exception. -* ignore all errors and assume the object exists - rv_bool = abap_true. - ENDTRY. - - ENDMETHOD. "exists - - METHOD path_to_package. - - DATA: lv_length TYPE i, - lv_path TYPE string. - - - lv_length = strlen( iv_start ) - 1. - lv_path = iv_path+lv_length. - - CONCATENATE iv_top lv_path INTO rv_package. - - TRANSLATE rv_package USING '/_'. - - lv_length = strlen( rv_package ) - 1. - - rv_package = rv_package(lv_length). - - TRANSLATE rv_package TO UPPER CASE. - - IF lcl_sap_package=>exists( rv_package ) = abap_false. - lcl_sap_package=>create_child( iv_parent = iv_top - iv_child = rv_package ). - ENDIF. - - ENDMETHOD. - - METHOD class_name. - - CONCATENATE 'LCL_OBJECT_' is_item-obj_type INTO rv_class_name. "#EC NOTEXT - - ENDMETHOD. "class_name - - METHOD jump. - - DATA: li_obj TYPE REF TO lif_object. - - - li_obj = create_object( is_item = is_item - iv_language = gc_english ). - - li_obj->jump( ). - - ENDMETHOD. "jump - - METHOD changed_by. - - DATA: li_obj TYPE REF TO lif_object. - - - li_obj = create_object( is_item = is_item - iv_language = gc_english ). - - rv_user = li_obj->changed_by( ). - - ASSERT NOT rv_user IS INITIAL. - -* todo, fallback to looking at transports if rv_user = 'UNKNOWN'? - - ENDMETHOD. - - METHOD delete. - - DATA: ls_item TYPE ty_item, - lv_tabclass TYPE dd02l-tabclass, - lt_tadir LIKE it_tadir. - - FIELD-SYMBOLS: LIKE LINE OF it_tadir. - - -* misuse field KORRNUM to fix deletion sequence - - lt_tadir[] = it_tadir[]. - - LOOP AT lt_tadir ASSIGNING . - CASE -object. - WHEN 'IATU'. - -korrnum = '5500'. - WHEN 'IARP'. - -korrnum = '5510'. - WHEN 'IASP'. - -korrnum = '5520'. - WHEN 'SUSC'. - -korrnum = '5000'. - WHEN 'TTYP' OR 'TABL' OR 'VIEW'. - SELECT SINGLE tabclass FROM dd02l - INTO lv_tabclass - WHERE tabname = -obj_name - AND as4local = 'A' - AND as4vers = '0000'. - IF sy-subrc = 0 AND lv_tabclass = 'APPEND'. -* delete append structures before database tables - -korrnum = '6500'. - ELSE. - -korrnum = '7000'. - ENDIF. - WHEN 'DTEL'. - -korrnum = '8000'. - WHEN 'DOMA'. - -korrnum = '9000'. - WHEN 'PROG'. -* delete includes after main programs - SELECT COUNT(*) FROM reposrc - WHERE progname = -obj_name - AND r3state = 'A' - AND subc = 'I'. - IF sy-subrc = 0. - -korrnum = '2000'. - ELSE. - -korrnum = '1000'. - ENDIF. - WHEN OTHERS. - -korrnum = '1000'. - ENDCASE. - ENDLOOP. - - resolve_ddic( CHANGING ct_tadir = lt_tadir ). - - SORT lt_tadir BY korrnum ASCENDING. - - LOOP AT lt_tadir ASSIGNING . - lcl_progress=>show( iv_key = 'Delete' - iv_current = sy-tabix - iv_total = lines( lt_tadir ) - iv_text = -obj_name ) ##NO_TEXT. - - CLEAR ls_item. - ls_item-obj_type = -object. - ls_item-obj_name = -obj_name. - delete_obj( ls_item ). - ENDLOOP. - - ENDMETHOD. "delete - - METHOD resolve_ddic. -* this will make sure the deletion sequence of structures/tables work -* in case they have dependencies with .INCLUDE - - TYPES: BEGIN OF ty_edge, - from TYPE ty_item, - to TYPE ty_item, - END OF ty_edge. - - DATA: lt_nodes TYPE TABLE OF ty_item, - lt_edges TYPE TABLE OF ty_edge, - lt_findstrings TYPE TABLE OF rsfind, - lv_plus TYPE i VALUE 1, - lv_find_obj_cls TYPE euobj-id, - lv_index TYPE i, - lv_before TYPE i, - lt_founds TYPE TABLE OF rsfindlst, - lt_scope TYPE STANDARD TABLE OF seu_obj. - - FIELD-SYMBOLS: LIKE LINE OF ct_tadir, - LIKE LINE OF lt_edges, - LIKE LINE OF lt_founds, - LIKE LINE OF lt_nodes. - - -* build nodes - LOOP AT ct_tadir ASSIGNING - WHERE object = 'TABL' - OR object = 'TTYP'. - APPEND INITIAL LINE TO lt_nodes ASSIGNING . - -obj_name = -obj_name. - -obj_type = -object. - ENDLOOP. - - APPEND 'TABL' TO lt_scope. - APPEND 'STRU' TO lt_scope. - APPEND 'TTYP' TO lt_scope. - -* build edges - LOOP AT lt_nodes ASSIGNING . - - CLEAR lt_findstrings. - APPEND -obj_name TO lt_findstrings. - lv_find_obj_cls = -obj_type. - - CALL FUNCTION 'RS_EU_CROSSREF' - EXPORTING - i_find_obj_cls = lv_find_obj_cls - TABLES - i_findstrings = lt_findstrings - o_founds = lt_founds - i_scope_object_cls = lt_scope - EXCEPTIONS - not_executed = 1 - not_found = 2 - illegal_object = 3 - no_cross_for_this_object = 4 - batch = 5 - batchjob_error = 6 - wrong_type = 7 - object_not_exist = 8 - OTHERS = 9. - IF sy-subrc <> 0. - CONTINUE. - ENDIF. - - LOOP AT lt_founds ASSIGNING . - APPEND INITIAL LINE TO lt_edges ASSIGNING . - -from = . - - -to-obj_name = -object. - CASE -object_cls. - WHEN 'DS' - OR 'DT'. - -to-obj_type = 'TABL'. - WHEN 'DA'. - -to-obj_type = 'TTYP'. - WHEN OTHERS. - lcx_exception=>raise( 'resolve_ddic, unknown object_cls' ). - ENDCASE. - ENDLOOP. - - ENDLOOP. - - DO. - lv_before = lines( lt_nodes ). - LOOP AT lt_nodes ASSIGNING . - lv_index = sy-tabix. - READ TABLE lt_edges WITH KEY - from-obj_name = -obj_name - from-obj_type = -obj_type - TRANSPORTING NO FIELDS. - IF sy-subrc <> 0. - LOOP AT ct_tadir ASSIGNING - WHERE obj_name = -obj_name - AND object = -obj_type. - -korrnum = -korrnum + lv_plus. - CONDENSE -korrnum. - ENDLOOP. - DELETE lt_edges - WHERE to-obj_name = -obj_name - AND to-obj_type = -obj_type. - DELETE lt_nodes INDEX lv_index. - EXIT. " make sure the sequence is fixed - ENDIF. - ENDLOOP. - IF lv_before = lines( lt_nodes ). - EXIT. - ENDIF. - lv_plus = lv_plus + 1. - ENDDO. - - ENDMETHOD. "resolve_ddic - - METHOD delete_obj. - - DATA: li_obj TYPE REF TO lif_object. - - - IF is_supported( is_item ) = abap_true. - li_obj = create_object( is_item = is_item - iv_language = gc_english ). - li_obj->delete( ). - ENDIF. - - ENDMETHOD. "delete - - METHOD serialize. - - DATA: li_obj TYPE REF TO lif_object, - lo_xml TYPE REF TO lcl_xml_output, - lo_files TYPE REF TO lcl_objects_files. - - - IF is_supported( is_item ) = abap_false. - IF NOT io_log IS INITIAL. - io_log->add( iv_msgv1 = 'Object type ignored, not supported:' - iv_msgv2 = is_item-obj_type - iv_msgv3 = '-' - iv_msgv4 = is_item-obj_name ) ##no_text. - ENDIF. - RETURN. - ENDIF. - - CREATE OBJECT lo_files - EXPORTING - is_item = is_item. - - li_obj = create_object( is_item = is_item - iv_language = iv_language ). - li_obj->mo_files = lo_files. - CREATE OBJECT lo_xml. - li_obj->serialize( lo_xml ). - lo_files->add_xml( io_xml = lo_xml - is_metadata = li_obj->get_metadata( ) ). - - rt_files = lo_files->get_files( ). - - check_duplicates( rt_files ). - - ENDMETHOD. "serialize - - METHOD check_duplicates. - - DATA: lt_files TYPE ty_files_tt. - - - lt_files[] = it_files[]. - SORT lt_files BY path ASCENDING filename ASCENDING. - DELETE ADJACENT DUPLICATES FROM lt_files COMPARING path filename. - IF lines( lt_files ) <> lines( it_files ). - lcx_exception=>raise( 'Duplicates' ). - ENDIF. - - ENDMETHOD. - - METHOD prioritize_deser. - - FIELD-SYMBOLS: LIKE LINE OF it_results. - -* PROG before internet services, as the services might use the screens - LOOP AT it_results ASSIGNING WHERE obj_type = 'PROG'. - APPEND TO rt_results. - ENDLOOP. - -* ISAP has to be handled before ISRP - LOOP AT it_results ASSIGNING WHERE obj_type = 'IASP'. - APPEND TO rt_results. - ENDLOOP. - - LOOP AT it_results ASSIGNING - WHERE obj_type <> 'IASP' AND obj_type <> 'PROG'. - APPEND TO rt_results. - ENDLOOP. - - ENDMETHOD. "prioritize_deser - - METHOD deserialize. - - TYPES: BEGIN OF ty_late, - obj TYPE REF TO lif_object, - xml TYPE REF TO lcl_xml_input, - package TYPE devclass, - END OF ty_late. - - DATA: ls_item TYPE ty_item, - lv_cancel TYPE abap_bool, - li_obj TYPE REF TO lif_object, - lt_remote TYPE ty_files_tt, - lv_package TYPE devclass, - lo_files TYPE REF TO lcl_objects_files, - lo_xml TYPE REF TO lcl_xml_input, - lt_results TYPE ty_results_tt, - lt_late TYPE TABLE OF ty_late. - - FIELD-SYMBOLS: LIKE LINE OF lt_results, - LIKE LINE OF lt_late. - - - lcl_objects_activation=>clear( ). - - lt_remote = io_repo->get_files_remote( ). - - lt_results = lcl_file_status=>status( io_repo ). - DELETE lt_results WHERE match = abap_true. - SORT lt_results BY obj_type ASCENDING obj_name ASCENDING. - DELETE ADJACENT DUPLICATES FROM lt_results COMPARING obj_type obj_name. - - lt_results = prioritize_deser( lt_results ). - - warning_overwrite( EXPORTING io_repo = io_repo - CHANGING ct_results = lt_results ). - - LOOP AT lt_results ASSIGNING . - lcl_progress=>show( iv_key = 'Deserialize' - iv_current = sy-tabix - iv_total = lines( lt_results ) - iv_text = -obj_name ) ##NO_TEXT. - - CLEAR ls_item. - ls_item-obj_type = -obj_type. - ls_item-obj_name = -obj_name. -* handle namespaces - REPLACE ALL OCCURRENCES OF '#' IN ls_item-obj_name WITH '/'. - - lv_package = path_to_package( - iv_top = io_repo->get_package( ) - iv_start = io_repo->get_dot_abapgit( )->get_starting_folder( ) - iv_path = -path ). - - lv_cancel = warning_package( is_item = ls_item - iv_package = lv_package ). - IF lv_cancel = abap_true. - lcx_exception=>raise( 'cancelled' ). - ENDIF. - - CREATE OBJECT lo_files - EXPORTING - is_item = ls_item. - lo_files->set_files( lt_remote ). - -* Analyze XML in order to instantiate the proper serializer - lo_xml = lo_files->read_xml( ). - - li_obj = create_object( is_item = ls_item - iv_language = io_repo->get_master_language( ) - is_metadata = lo_xml->get_metadata( ) ). - - li_obj->mo_files = lo_files. - - IF li_obj->get_metadata( )-late_deser = abap_true. - APPEND INITIAL LINE TO lt_late ASSIGNING . - -obj = li_obj. - -xml = lo_xml. - -package = lv_package. - CONTINUE. - ENDIF. - - li_obj->deserialize( iv_package = lv_package - io_xml = lo_xml ). - - ENDLOOP. - - lcl_objects_activation=>activate( ). - - LOOP AT lt_late ASSIGNING . - -obj->deserialize( iv_package = -package - io_xml = -xml ). - ENDLOOP. - - update_package_tree( io_repo->get_package( ) ). - - ENDMETHOD. "deserialize - -ENDCLASS. "lcl_objects IMPLEMENTATION - -*----------------------------------------------------------------------* -* CLASS lcl_object_clas DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_object_clas DEFINITION INHERITING FROM lcl_objects_program. - - PUBLIC SECTION. - INTERFACES lif_object. - ALIASES mo_files FOR lif_object~mo_files. - - PRIVATE SECTION. - TYPES: BEGIN OF ty_sotr, - header TYPE sotr_head, - entries TYPE sotr_text_tt, - END OF ty_sotr. - - TYPES: ty_sotr_tt TYPE STANDARD TABLE OF ty_sotr WITH DEFAULT KEY. - - DATA mv_skip_testclass TYPE abap_bool. - - METHODS deserialize_abap - IMPORTING io_xml TYPE REF TO lcl_xml_input - iv_package TYPE devclass - RAISING lcx_exception. - - METHODS deserialize_textpool - IMPORTING io_xml TYPE REF TO lcl_xml_input - RAISING lcx_exception. - - METHODS deserialize_docu - IMPORTING io_xml TYPE REF TO lcl_xml_input - RAISING lcx_exception. - - METHODS deserialize_sotr - IMPORTING io_xml TYPE REF TO lcl_xml_input - iv_package TYPE devclass - RAISING lcx_exception. - - METHODS serialize_abap_old - IMPORTING is_clskey TYPE seoclskey - RETURNING VALUE(rt_source) TYPE ty_string_tt - RAISING lcx_exception. - - METHODS deserialize_abap_source_old - IMPORTING is_clskey TYPE seoclskey - it_source TYPE ty_string_tt - RAISING lcx_exception. - - METHODS deserialize_abap_source_new - IMPORTING is_clskey TYPE seoclskey - it_source TYPE ty_string_tt - RAISING lcx_exception - cx_sy_dyn_call_error. - - METHODS serialize_abap_new - IMPORTING is_clskey TYPE seoclskey - RETURNING VALUE(rt_source) TYPE ty_string_tt - RAISING lcx_exception - cx_sy_dyn_call_error. - - METHODS serialize_locals_imp - IMPORTING is_clskey TYPE seoclskey - RETURNING VALUE(rt_source) TYPE ty_string_tt - RAISING lcx_exception. - - METHODS serialize_locals_def - IMPORTING is_clskey TYPE seoclskey - RETURNING VALUE(rt_source) TYPE ty_string_tt - RAISING lcx_exception. - - METHODS read_include - IMPORTING is_clskey TYPE seoclskey - iv_type TYPE seop_include_ext_app - RETURNING VALUE(rt_source) TYPE seop_source_string. - - METHODS serialize_testclasses - IMPORTING is_clskey TYPE seoclskey - RETURNING VALUE(rt_source) TYPE ty_string_tt - RAISING lcx_exception. - - METHODS serialize_macros - IMPORTING is_clskey TYPE seoclskey - RETURNING VALUE(rt_source) TYPE ty_string_tt - RAISING lcx_exception. - - METHODS serialize_xml - IMPORTING io_xml TYPE REF TO lcl_xml_output - RAISING lcx_exception. - - METHODS read_sotr - RETURNING VALUE(rt_sotr) TYPE ty_sotr_tt - RAISING lcx_exception. - - METHODS remove_signatures - CHANGING ct_source TYPE ty_string_tt. - - METHODS reduce - CHANGING ct_source TYPE ty_string_tt. - -ENDCLASS. "lcl_object_dtel DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_object_intf DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_object_intf DEFINITION INHERITING FROM lcl_object_clas FINAL. -* todo, CLAS + INTF to be refactored, see: -* https://github.com/larshp/abapGit/issues/21 -ENDCLASS. "lcl_object_intf DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_object_clas IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_object_clas IMPLEMENTATION. - - METHOD lif_object~get_metadata. - rs_metadata = get_metadata( ). - ENDMETHOD. "lif_object~get_metadata - - METHOD lif_object~changed_by. -* todo, not sure this is correct, to be tested - SELECT SINGLE changedby FROM seoclassdf INTO rv_user - WHERE clsname = ms_item-obj_name - AND version = '1'. "#EC CI_GENBUFF - IF sy-subrc = 0 AND rv_user IS INITIAL. - SELECT SINGLE author FROM seoclassdf INTO rv_user - WHERE clsname = ms_item-obj_name - AND version = '1'. "#EC CI_GENBUFF - ENDIF. - IF sy-subrc <> 0. - rv_user = c_user_unknown. - ENDIF. - ENDMETHOD. - - METHOD lif_object~exists. - - DATA: ls_clskey TYPE seoclskey. - - - ls_clskey-clsname = ms_item-obj_name. - - CALL FUNCTION 'SEO_CLASS_EXISTENCE_CHECK' - EXPORTING - clskey = ls_clskey - EXCEPTIONS - not_specified = 1 - not_existing = 2 - is_interface = 3 - no_text = 4 - inconsistent = 5 - OTHERS = 6. - rv_bool = boolc( sy-subrc <> 2 ). - - ENDMETHOD. "lif_object~exists - - METHOD lif_object~jump. - - CALL FUNCTION 'RS_TOOL_ACCESS' - EXPORTING - operation = 'SHOW' - object_name = ms_item-obj_name - object_type = 'CLAS' - in_new_window = abap_true. - - ENDMETHOD. "jump - - METHOD lif_object~delete. - - DATA: ls_clskey TYPE seoclskey. - - - ls_clskey-clsname = ms_item-obj_name. - - CASE ms_item-obj_type. - WHEN 'CLAS'. - CALL FUNCTION 'SEO_CLASS_DELETE_COMPLETE' - EXPORTING - clskey = ls_clskey - EXCEPTIONS - not_existing = 1 - is_interface = 2 - db_error = 3 - no_access = 4 - other = 5 - OTHERS = 6. - IF sy-subrc <> 0. - lcx_exception=>raise( 'Error from SEO_CLASS_DELETE_COMPLETE' ). - ENDIF. - WHEN 'INTF'. - CALL FUNCTION 'SEO_INTERFACE_DELETE_COMPLETE' - EXPORTING - intkey = ls_clskey - EXCEPTIONS - not_existing = 1 - is_class = 2 - db_error = 3 - no_access = 4 - other = 5 - OTHERS = 6. - IF sy-subrc <> 0. - lcx_exception=>raise( 'Error from SEO_INTERFACE_DELETE_COMPLETE' ). - ENDIF. - WHEN OTHERS. - lcx_exception=>raise( 'class delete, unknown type' ). - ENDCASE. - - ENDMETHOD. "delete - - METHOD reduce. - - DATA: lv_source LIKE LINE OF ct_source, - lv_found TYPE sap_bool. - - -* skip files that only contain the standard comments - lv_found = abap_false. - LOOP AT ct_source INTO lv_source. - IF strlen( lv_source ) >= 3 AND lv_source(3) <> '*"*'. - lv_found = abap_true. - ENDIF. - ENDLOOP. - IF lv_found = abap_false. - CLEAR ct_source[]. - ENDIF. - - ENDMETHOD. "reduce - - METHOD serialize_locals_imp. - - rt_source = read_include( is_clskey = is_clskey - iv_type = seop_ext_class_locals_imp ). - - reduce( CHANGING ct_source = rt_source ). - - ENDMETHOD. "serialize_local - - METHOD serialize_locals_def. - - rt_source = read_include( is_clskey = is_clskey - iv_type = seop_ext_class_locals_def ). - - reduce( CHANGING ct_source = rt_source ). - - ENDMETHOD. "serialize_locals_def - - METHOD read_include. - - DATA: ls_include TYPE progstruc. - - - ASSERT iv_type = seop_ext_class_locals_def - OR iv_type = seop_ext_class_locals_imp - OR iv_type = seop_ext_class_macros - OR iv_type = seop_ext_class_testclasses. - - ls_include-rootname = is_clskey-clsname. - TRANSLATE ls_include-rootname USING ' ='. - ls_include-categorya = iv_type(1). - ls_include-codea = iv_type+1(4). - -* it looks like there is an issue in function module SEO_CLASS_GET_INCLUDE_SOURCE -* on 750 kernels, where the READ REPORT without STATE addition does not -* return the active version, this method is a workaround for this issue - READ REPORT ls_include INTO rt_source STATE 'A'. - - ENDMETHOD. - - METHOD serialize_testclasses. - - DATA: lv_line1 LIKE LINE OF rt_source, - lv_line2 LIKE LINE OF rt_source. - - - rt_source = read_include( is_clskey = is_clskey - iv_type = seop_ext_class_testclasses ). - -* when creating classes in Eclipse it automatically generates the -* testclass include, but it is not needed, so skip to avoid -* creating an extra file in the repository. -* Also remove it if the content is manually removed, but -* the class still thinks it contains tests - mv_skip_testclass = abap_false. - IF lines( rt_source ) = 2. - READ TABLE rt_source INDEX 1 INTO lv_line1. - ASSERT sy-subrc = 0. - READ TABLE rt_source INDEX 2 INTO lv_line2. - ASSERT sy-subrc = 0. - IF lv_line1(3) = '*"*' AND lv_line2 IS INITIAL. - mv_skip_testclass = abap_true. - ENDIF. - ELSEIF lines( rt_source ) = 1. - READ TABLE rt_source INDEX 1 INTO lv_line1. - ASSERT sy-subrc = 0. - IF lv_line1(3) = '*"*' OR lv_line1 IS INITIAL. - mv_skip_testclass = abap_true. - ENDIF. - ELSEIF lines( rt_source ) = 0. - mv_skip_testclass = abap_true. - ENDIF. - - ENDMETHOD. "serialize_test - - METHOD serialize_macros. - - rt_source = read_include( is_clskey = is_clskey - iv_type = seop_ext_class_macros ). - - reduce( CHANGING ct_source = rt_source ). - - ENDMETHOD. "serialize_macro - - METHOD serialize_abap_old. -* for old ABAP AS versions - DATA: lo_source TYPE REF TO cl_oo_source. - - - CREATE OBJECT lo_source - EXPORTING - clskey = is_clskey - EXCEPTIONS - class_not_existing = 1 - OTHERS = 2. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from CL_OO_SOURCE' ). - ENDIF. - - lo_source->read( 'A' ). - rt_source = lo_source->get_old_source( ). - remove_signatures( CHANGING ct_source = rt_source ). - - ENDMETHOD. "serialize_abap - - METHOD serialize_abap_new. - - DATA: lo_source TYPE REF TO object, - lo_instance TYPE REF TO object. - -* do not call the class/methods statically, as it will -* give syntax errors on old versions - CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') - RECEIVING - result = lo_instance. - - CALL METHOD lo_instance->('CREATE_CLIF_SOURCE') - EXPORTING - clif_name = is_clskey-clsname - version = 'A' - RECEIVING - result = lo_source. - - CALL METHOD lo_source->('GET_SOURCE') - IMPORTING - source = rt_source. - - ENDMETHOD. - - METHOD remove_signatures. - -* signatures messes up in CL_OO_SOURCE when deserializing and serializing -* within same session - - DATA: lv_begin TYPE string, - lv_end TYPE string, - lv_remove TYPE sap_bool, - lv_source LIKE LINE OF ct_source. - - - CONCATENATE '* ------------------------------------' - '---------------------------------------------------+' - INTO lv_begin. - - CONCATENATE '* +------------------------------------------------' - '--------------------------------------' - INTO lv_end. - - lv_remove = abap_false. - LOOP AT ct_source INTO lv_source. - IF lv_source = lv_begin. - lv_remove = abap_true. - ENDIF. - IF lv_remove = abap_true. - DELETE ct_source INDEX sy-tabix. - ENDIF. - IF lv_source = lv_end. - lv_remove = abap_false. - ENDIF. - ENDLOOP. - - ENDMETHOD. "remove_signatures - - METHOD lif_object~serialize. - - DATA: lt_source TYPE seop_source_string, - ls_clskey TYPE seoclskey. - - - ls_clskey-clsname = ms_item-obj_name. - - IF lif_object~exists( ) = abap_false. - RETURN. - ENDIF. - - CALL FUNCTION 'SEO_BUFFER_REFRESH' - EXPORTING - version = seoc_version_active - force = seox_true. - CALL FUNCTION 'SEO_BUFFER_REFRESH' - EXPORTING - version = seoc_version_inactive - force = seox_true. - - TRY. - lt_source = serialize_abap_new( ls_clskey ). - CATCH cx_sy_dyn_call_error. - lt_source = serialize_abap_old( ls_clskey ). - ENDTRY. - - mo_files->add_abap( lt_source ). - - IF ms_item-obj_type = 'CLAS'. - lt_source = serialize_locals_def( ls_clskey ). - IF NOT lt_source[] IS INITIAL. - mo_files->add_abap( iv_extra = 'locals_def' - it_abap = lt_source ). "#EC NOTEXT - ENDIF. - - lt_source = serialize_locals_imp( ls_clskey ). - IF NOT lt_source[] IS INITIAL. - mo_files->add_abap( iv_extra = 'locals_imp' - it_abap = lt_source ). "#EC NOTEXT - ENDIF. - - lt_source = serialize_testclasses( ls_clskey ). - IF NOT lt_source[] IS INITIAL AND mv_skip_testclass = abap_false. - mo_files->add_abap( iv_extra = 'testclasses' - it_abap = lt_source ). "#EC NOTEXT - ENDIF. - - lt_source = serialize_macros( ls_clskey ). - IF NOT lt_source[] IS INITIAL. - mo_files->add_abap( iv_extra = 'macros' - it_abap = lt_source ). "#EC NOTEXT - ENDIF. - ENDIF. - - serialize_xml( io_xml ). - - ENDMETHOD. "serialize - - METHOD read_sotr. - - DATA: lv_concept TYPE sotr_head-concept, - lt_seocompodf TYPE STANDARD TABLE OF seocompodf WITH DEFAULT KEY, - ls_header TYPE sotr_head, - lt_entries TYPE sotr_text_tt. - - FIELD-SYMBOLS: LIKE LINE OF rt_sotr, - LIKE LINE OF lt_seocompodf, - LIKE LINE OF lt_entries. - - - SELECT * FROM seocompodf - INTO TABLE lt_seocompodf - WHERE clsname = ms_item-obj_name - AND version = '1' - AND exposure = '2' - AND attdecltyp = '2' - AND type = 'SOTR_CONC' - ORDER BY PRIMARY KEY. - - LOOP AT lt_seocompodf ASSIGNING . - - lv_concept = translate( val = -attvalue from = '''' to = '' ). - - CALL FUNCTION 'SOTR_GET_CONCEPT' - EXPORTING - concept = lv_concept - IMPORTING - header = ls_header - TABLES - entries = lt_entries - EXCEPTIONS - no_entry_found = 1 - OTHERS = 2. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from SOTR_GET_CONCEPT' ). - ENDIF. - - CLEAR: ls_header-paket, - ls_header-crea_name, - ls_header-crea_tstut, - ls_header-chan_name, - ls_header-chan_tstut. - - LOOP AT lt_entries ASSIGNING . - CLEAR: -crea_name, - -crea_tstut, - -chan_name, - -chan_tstut. - ENDLOOP. - - APPEND INITIAL LINE TO rt_sotr ASSIGNING . - -header = ls_header. - -entries = lt_entries. - - ENDLOOP. - - ENDMETHOD. - - METHOD serialize_xml. - - DATA: ls_vseoclass TYPE vseoclass, - lv_cp TYPE program, - lt_tpool TYPE textpool_table, - lv_object TYPE dokhl-object, - lv_state TYPE dokhl-dokstate, - ls_vseointerf TYPE vseointerf, - ls_clskey TYPE seoclskey, - lt_sotr TYPE ty_sotr_tt, - lt_lines TYPE tlinetab. - - - ls_clskey-clsname = ms_item-obj_name. - - CALL FUNCTION 'SEO_CLIF_GET' - EXPORTING - cifkey = ls_clskey - version = seoc_version_active - IMPORTING - class = ls_vseoclass - interface = ls_vseointerf - EXCEPTIONS - not_existing = 1 - deleted = 2 - model_only = 3 - OTHERS = 4. - IF sy-subrc = 1. - RETURN. " in case only inactive version exists - ELSEIF sy-subrc <> 0. - lcx_exception=>raise( 'error from seo_clif_get' ). - ENDIF. - - CLEAR: ls_vseoclass-uuid, - ls_vseoclass-author, - ls_vseoclass-createdon, - ls_vseoclass-changedby, - ls_vseoclass-changedon, - ls_vseoclass-r3release, - ls_vseoclass-chgdanyby, - ls_vseoclass-chgdanyon. - - IF mv_skip_testclass = abap_true. - CLEAR ls_vseoclass-with_unit_tests. - ENDIF. - - CLEAR: ls_vseointerf-uuid, - ls_vseointerf-author, - ls_vseointerf-createdon, - ls_vseointerf-changedby, - ls_vseointerf-changedon, - ls_vseointerf-r3release. - - CASE ms_item-obj_type. - WHEN 'CLAS'. - io_xml->add( iv_name = 'VSEOCLASS' - ig_data = ls_vseoclass ). - - lv_cp = cl_oo_classname_service=>get_classpool_name( ls_clskey-clsname ). - READ TEXTPOOL lv_cp INTO lt_tpool LANGUAGE mv_language. "#EC CI_READ_REP - io_xml->add( iv_name = 'TPOOL' - ig_data = add_tpool( lt_tpool ) ). - - IF ls_vseoclass-category = seoc_category_exception. - lt_sotr = read_sotr( ). - IF lines( lt_sotr ) > 0. - io_xml->add( iv_name = 'SOTR' - ig_data = lt_sotr ). - ENDIF. - ENDIF. - WHEN 'INTF'. - io_xml->add( iv_name = 'VSEOINTERF' - ig_data = ls_vseointerf ). - WHEN OTHERS. - ASSERT 0 = 1. - ENDCASE. - - lv_object = ls_clskey-clsname. - CALL FUNCTION 'DOCU_GET' - EXPORTING - id = 'CL' - langu = mv_language - object = lv_object - IMPORTING - dokstate = lv_state - TABLES - line = lt_lines - EXCEPTIONS - no_docu_on_screen = 1 - no_docu_self_def = 2 - no_docu_temp = 3 - ret_code = 4 - OTHERS = 5. - IF sy-subrc = 0 AND lv_state = 'R'. - io_xml->add( iv_name = 'LINES' - ig_data = lt_lines ). - ENDIF. - - ENDMETHOD. "serialize_xml - - METHOD lif_object~deserialize. - -* function group SEOK -* function group SEOQ -* function group SEOP -* class CL_OO_CLASSNAME_SERVICE -* class CL_OO_SOURCE - - deserialize_abap( io_xml = io_xml - iv_package = iv_package ). - - IF ms_item-obj_type = 'CLAS'. - deserialize_textpool( io_xml ). - - deserialize_sotr( io_xml = io_xml - iv_package = iv_package ). - ENDIF. - - deserialize_docu( io_xml ). - - ENDMETHOD. "deserialize - - METHOD deserialize_sotr. - - DATA: lt_sotr TYPE ty_sotr_tt, - lt_objects TYPE sotr_objects, - ls_paket TYPE sotr_pack, - lv_object LIKE LINE OF lt_objects. - - FIELD-SYMBOLS: LIKE LINE OF lt_sotr. - - - io_xml->read( EXPORTING iv_name = 'SOTR' - CHANGING cg_data = lt_sotr ). - - IF lines( lt_sotr ) = 0. - RETURN. - ENDIF. - - LOOP AT lt_sotr ASSIGNING . - CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' - EXPORTING - object_vector = -header-objid_vec - IMPORTING - objects = lt_objects - EXCEPTIONS - object_not_found = 1 - OTHERS = 2. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from SOTR_OBJECT_GET_OBJECTS' ). - ENDIF. - - READ TABLE lt_objects INDEX 1 INTO lv_object. - ASSERT sy-subrc = 0. - - ls_paket-paket = iv_package. - - CALL FUNCTION 'SOTR_CREATE_CONCEPT' - EXPORTING - paket = ls_paket - crea_lan = -header-crea_lan - alias_name = -header-alias_name - object = lv_object - entries = -entries - concept_default = -header-concept - EXCEPTIONS - package_missing = 1 - crea_lan_missing = 2 - object_missing = 3 - paket_does_not_exist = 4 - alias_already_exist = 5 - object_type_not_found = 6 - langu_missing = 7 - identical_context_not_allowed = 8 - text_too_long = 9 - error_in_update = 10 - no_master_langu = 11 - error_in_concept_id = 12 - alias_not_allowed = 13 - tadir_entry_creation_failed = 14 - internal_error = 15 - error_in_correction = 16 - user_cancelled = 17 - no_entry_found = 18 - OTHERS = 19. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from SOTR_CREATE_CONCEPT' ). - ENDIF. - - ENDLOOP. - - ENDMETHOD. - - METHOD deserialize_docu. - - DATA: lt_lines TYPE tlinetab, - lv_object TYPE dokhl-object. - - - io_xml->read( EXPORTING iv_name = 'LINES' - CHANGING cg_data = lt_lines ). - - IF lt_lines[] IS INITIAL. - RETURN. - ENDIF. - - lv_object = ms_item-obj_name. - CALL FUNCTION 'DOCU_UPD' - EXPORTING - id = 'CL' - langu = mv_language - object = lv_object - TABLES - line = lt_lines - EXCEPTIONS - ret_code = 1 - OTHERS = 2. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from DOCU_UPD' ). - ENDIF. - - ENDMETHOD. "deserialize_doku - - METHOD deserialize_textpool. - - DATA: lv_cp TYPE program, - lv_clsname TYPE seoclsname, - lt_tpool_ext TYPE ty_tpool_tt, - lt_tpool TYPE textpool_table. - - - io_xml->read( EXPORTING iv_name = 'TPOOL' - CHANGING cg_data = lt_tpool_ext ). - lt_tpool = read_tpool( lt_tpool_ext ). - - IF lt_tpool[] IS INITIAL. - RETURN. - ENDIF. - - lv_clsname = ms_item-obj_name. - lv_cp = cl_oo_classname_service=>get_classpool_name( lv_clsname ). - - INSERT TEXTPOOL lv_cp - FROM lt_tpool - LANGUAGE mv_language - STATE 'I'. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from INSERT TEXTPOOL' ). - ENDIF. - - lcl_objects_activation=>add( iv_type = 'REPT' - iv_name = lv_cp ). - - ENDMETHOD. "deserialize_textpool - - METHOD deserialize_abap. - - DATA: ls_vseoclass TYPE vseoclass, - ls_vseointerf TYPE vseointerf, - lt_source TYPE seop_source_string, - lt_locals_def TYPE seop_source_string, - lt_locals_imp TYPE seop_source_string, - lt_locals_mac TYPE seop_source_string, - lt_testclasses TYPE seop_source_string, - ls_clskey TYPE seoclskey. - - - lt_source = mo_files->read_abap( ). - - lt_locals_def = mo_files->read_abap( iv_extra = 'locals_def' - iv_error = abap_false ). "#EC NOTEXT - - lt_locals_imp = mo_files->read_abap( iv_extra = 'locals_imp' - iv_error = abap_false ). "#EC NOTEXT - - lt_locals_mac = mo_files->read_abap( iv_extra = 'macros' - iv_error = abap_false ). "#EC NOTEXT - - lt_testclasses = mo_files->read_abap( iv_extra = 'testclasses' - iv_error = abap_false ). "#EC NOTEXT - - ls_clskey-clsname = ms_item-obj_name. - - - CASE ms_item-obj_type. - WHEN 'CLAS'. - io_xml->read( EXPORTING iv_name = 'VSEOCLASS' - CHANGING cg_data = ls_vseoclass ). - - CALL FUNCTION 'SEO_CLASS_CREATE_COMPLETE' - EXPORTING - devclass = iv_package - overwrite = seox_true - CHANGING - class = ls_vseoclass - EXCEPTIONS - existing = 1 - is_interface = 2 - db_error = 3 - component_error = 4 - no_access = 5 - other = 6 - OTHERS = 7. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from SEO_CLASS_CREATE_COMPLETE' ). - ENDIF. - - WHEN 'INTF'. - io_xml->read( EXPORTING iv_name = 'VSEOINTERF' - CHANGING cg_data = ls_vseointerf ). - - CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' - EXPORTING - devclass = iv_package - overwrite = seox_true - CHANGING - interface = ls_vseointerf - EXCEPTIONS - existing = 1 - is_class = 2 - db_error = 3 - component_error = 4 - no_access = 5 - other = 6 - OTHERS = 7. - IF sy-subrc <> 0. - lcx_exception=>raise( 'Error from SEO_INTERFACE_CREATE_COMPLETE' ). - ENDIF. - - WHEN OTHERS. - ASSERT 0 = 1. - ENDCASE. - - IF ms_item-obj_type = 'CLAS'. - CALL FUNCTION 'SEO_CLASS_GENERATE_LOCALS' - EXPORTING - clskey = ls_clskey - force = seox_true - locals_def = lt_locals_def - locals_imp = lt_locals_imp - locals_mac = lt_locals_mac - locals_testclasses = lt_testclasses - EXCEPTIONS - not_existing = 1 - model_only = 2 - locals_not_generated = 3 - locals_not_initialised = 4 - OTHERS = 5. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from generate_locals' ). - ENDIF. - ENDIF. - - TRY. - deserialize_abap_source_new( - is_clskey = ls_clskey - it_source = lt_source ). - CATCH cx_sy_dyn_call_error. - deserialize_abap_source_old( - is_clskey = ls_clskey - it_source = lt_source ). - ENDTRY. - - lcl_objects_activation=>add_item( ms_item ). - - ENDMETHOD. "deserialize - - METHOD deserialize_abap_source_old. -* for backwards compatability down to 702 - - DATA: lo_source TYPE REF TO cl_oo_source. - - - CREATE OBJECT lo_source - EXPORTING - clskey = is_clskey - EXCEPTIONS - class_not_existing = 1 - OTHERS = 2. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from CL_OO_SOURCE' ). - ENDIF. - - TRY. - lo_source->access_permission( seok_access_modify ). - lo_source->set_source( it_source ). - lo_source->save( ). - lo_source->access_permission( seok_access_free ). - CATCH cx_oo_access_permission. - lcx_exception=>raise( 'permission error' ). - CATCH cx_oo_source_save_failure. - lcx_exception=>raise( 'save failure' ). - ENDTRY. - - ENDMETHOD. - - METHOD deserialize_abap_source_new. - - DATA: lo_factory TYPE REF TO object, - lo_source TYPE REF TO object. - - - CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') - RECEIVING - result = lo_factory. - - CALL METHOD lo_factory->('CREATE_CLIF_SOURCE') - EXPORTING - clif_name = is_clskey-clsname - RECEIVING - result = lo_source. - - TRY. - CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~LOCK'). - CATCH cx_oo_access_permission. - lcx_exception=>raise( 'source_new, access permission exception' ). - ENDTRY. - - CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~SET_SOURCE') - EXPORTING - source = it_source. - - CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~SAVE'). - - CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~UNLOCK'). - - ENDMETHOD. - -ENDCLASS. "lcl_object_CLAS IMPLEMENTATION - -*----------------------------------------------------------------------* -* CLASS lcl_object_fugr DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_object_fugr DEFINITION INHERITING FROM lcl_objects_program FINAL. - - PUBLIC SECTION. - INTERFACES lif_object. - ALIASES mo_files FOR lif_object~mo_files. - - PRIVATE SECTION. - TYPES: ty_rs38l_incl_tt TYPE STANDARD TABLE OF rs38l_incl WITH DEFAULT KEY. - - TYPES: BEGIN OF ty_function, - funcname TYPE rs38l_fnam, - include TYPE progname, - global_flag TYPE rs38l-global, - remote_call TYPE rs38l-remote, - update_task TYPE rs38l-utask, - short_text TYPE tftit-stext, - remote_basxml TYPE rs38l-basxml_enabled, - import TYPE STANDARD TABLE OF rsimp WITH DEFAULT KEY, - changing TYPE STANDARD TABLE OF rscha WITH DEFAULT KEY, - export TYPE STANDARD TABLE OF rsexp WITH DEFAULT KEY, - tables TYPE STANDARD TABLE OF rstbl WITH DEFAULT KEY, - exception TYPE STANDARD TABLE OF rsexc WITH DEFAULT KEY, - documentation TYPE STANDARD TABLE OF rsfdo WITH DEFAULT KEY, - END OF ty_function. - - TYPES: ty_function_tt TYPE STANDARD TABLE OF ty_function WITH DEFAULT KEY. - - METHODS main_name - RETURNING VALUE(rv_program) TYPE program - RAISING lcx_exception. - - METHODS functions - RETURNING VALUE(rt_functab) TYPE ty_rs38l_incl_tt - RAISING lcx_exception. - - METHODS includes - RETURNING VALUE(rt_includes) TYPE rso_t_objnm - RAISING lcx_exception. - - METHODS serialize_functions - RETURNING VALUE(rt_functions) TYPE ty_function_tt - RAISING lcx_exception. - - METHODS deserialize_functions - IMPORTING it_functions TYPE ty_function_tt - RAISING lcx_exception. - - METHODS serialize_xml - IMPORTING io_xml TYPE REF TO lcl_xml_output - RAISING lcx_exception. - - METHODS deserialize_xml - IMPORTING io_xml TYPE REF TO lcl_xml_input - iv_package TYPE devclass - RAISING lcx_exception. - - METHODS serialize_includes - RAISING lcx_exception. - - METHODS deserialize_includes - IMPORTING io_xml TYPE REF TO lcl_xml_input - iv_package TYPE devclass - RAISING lcx_exception. - -* METHODS deserialize_dynpros -* IMPORTING it_dynpros TYPE ty_dynpro_tt -* RAISING lcx_exception. -* -* METHODS deserialize_cua -* IMPORTING is_cua TYPE ty_cua -* RAISING lcx_exception. - -ENDCLASS. "lcl_object_fugr DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_object_dtel IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_object_fugr IMPLEMENTATION. - -* function group SEUF -* function group SIFP -* function group SUNI - - METHOD lif_object~changed_by. - rv_user = c_user_unknown. " todo - ENDMETHOD. - - METHOD lif_object~get_metadata. - rs_metadata = get_metadata( ). - ENDMETHOD. "lif_object~get_metadata - - METHOD lif_object~exists. - - DATA: lv_pool TYPE tlibg-area. - - - lv_pool = ms_item-obj_name. - CALL FUNCTION 'RS_FUNCTION_POOL_EXISTS' - EXPORTING - function_pool = lv_pool - EXCEPTIONS - pool_not_exists = 1. - rv_bool = boolc( sy-subrc <> 1 ). - - ENDMETHOD. "lif_object~exists - - METHOD deserialize_functions. - - DATA: lv_include TYPE rs38l-include, - lv_area TYPE rs38l-area, - lt_source TYPE TABLE OF abaptxt255. - - FIELD-SYMBOLS: LIKE LINE OF it_functions. - - - LOOP AT it_functions ASSIGNING . - - lt_source = mo_files->read_abap( iv_extra = -funcname ). - - lv_area = ms_item-obj_name. - - CALL FUNCTION 'FUNCTION_EXISTS' - EXPORTING - funcname = -funcname - IMPORTING - include = lv_include - EXCEPTIONS - function_not_exist = 1. - IF sy-subrc = 0. -* delete the function module to make sure the parameters are updated -* havent found a nice way to update the paramters - CALL FUNCTION 'FUNCTION_DELETE' - EXPORTING - funcname = -funcname - suppress_success_message = abap_true - EXCEPTIONS - error_message = 1 - OTHERS = 2. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from FUNCTION_DELETE' ). - ENDIF. - ENDIF. - - CALL FUNCTION 'RS_FUNCTIONMODULE_INSERT' - EXPORTING - funcname = -funcname - function_pool = lv_area - interface_global = -global_flag - remote_call = -remote_call - short_text = -short_text -* NAMESPACE = ' ' todo - remote_basxml_supported = -remote_basxml - IMPORTING - function_include = lv_include - TABLES - import_parameter = -import - export_parameter = -export - tables_parameter = -tables - changing_parameter = -changing - exception_list = -exception - parameter_docu = -documentation - EXCEPTIONS - double_task = 1 - error_message = 2 - function_already_exists = 3 - invalid_function_pool = 4 - invalid_name = 5 - too_many_functions = 6 - no_modify_permission = 7 - no_show_permission = 8 - enqueue_system_failure = 9 - canceled_in_corr = 10 - OTHERS = 11. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from RS_FUNCTIONMODULE_INSERT' ). - ENDIF. - - INSERT REPORT lv_include FROM lt_source. - -* lcl_objects_activation=>add( iv_type = 'FUNC' -* iv_name = -funcname ). - - ENDLOOP. - - ENDMETHOD. "deserialize_functions - - METHOD deserialize_includes. - - DATA: lo_xml TYPE REF TO lcl_xml_input, - ls_progdir TYPE ty_progdir, - lt_includes TYPE rso_t_objnm, - lt_tpool TYPE textpool_table, - lt_tpool_ext TYPE ty_tpool_tt, - lt_source TYPE TABLE OF abaptxt255. - - FIELD-SYMBOLS: LIKE LINE OF lt_includes. - - - io_xml->read( EXPORTING iv_name = 'INCLUDES' - CHANGING cg_data = lt_includes ). - - LOOP AT lt_includes ASSIGNING . - - lt_source = mo_files->read_abap( iv_extra = ). - - lo_xml = mo_files->read_xml( ). - - lo_xml->read( EXPORTING iv_name = 'PROGDIR' - CHANGING cg_data = ls_progdir ). - - lo_xml->read( EXPORTING iv_name = 'TPOOL' - CHANGING cg_data = lt_tpool_ext ). - lt_tpool = read_tpool( lt_tpool_ext ). - - deserialize_program( is_progdir = ls_progdir - it_source = lt_source - it_tpool = lt_tpool - iv_package = iv_package ). - - ENDLOOP. - - ENDMETHOD. "deserialize_includes - - METHOD deserialize_xml. - - DATA: lv_complete TYPE rs38l-area, - lv_namespace TYPE rs38l-namespace, - lv_areat TYPE tlibt-areat, - lv_stext TYPE tftit-stext, - lv_group TYPE rs38l-area. - - - lv_complete = ms_item-obj_name. - - CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' - EXPORTING - complete_area = lv_complete - IMPORTING - namespace = lv_namespace - group = lv_group - EXCEPTIONS - include_not_exists = 1 - group_not_exists = 2 - no_selections = 3 - no_function_include = 4 - no_function_pool = 5 - delimiter_wrong_position = 6 - no_customer_function_group = 7 - no_customer_function_include = 8 - reserved_name_customer = 9 - namespace_too_long = 10 - area_length_error = 11 - OTHERS = 12. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from FUNCTION_INCLUDE_SPLIT' ). - ENDIF. - - io_xml->read( EXPORTING iv_name = 'AREAT' - CHANGING cg_data = lv_areat ). - lv_stext = lv_areat. - - CALL FUNCTION 'RS_FUNCTION_POOL_INSERT' - EXPORTING - function_pool = lv_group - short_text = lv_stext - namespace = lv_namespace - devclass = iv_package - EXCEPTIONS - name_already_exists = 1 - name_not_correct = 2 - function_already_exists = 3 - invalid_function_pool = 4 - invalid_name = 5 - too_many_functions = 6 - no_modify_permission = 7 - no_show_permission = 8 - enqueue_system_failure = 9 - canceled_in_corr = 10 - undefined_error = 11 - OTHERS = 12. - IF sy-subrc <> 0 AND sy-subrc <> 1 AND sy-subrc <> 3. -* todo, change description - lcx_exception=>raise( 'error from RS_FUNCTION_POOL_INSERT' ). - ENDIF. - - ENDMETHOD. "deserialize_xml - - METHOD serialize_xml. - - DATA: lt_functab TYPE ty_rs38l_incl_tt, - lt_includes TYPE rso_t_objnm, - lv_areat TYPE tlibt-areat. - - - SELECT SINGLE areat INTO lv_areat - FROM tlibt - WHERE spras = mv_language - AND area = ms_item-obj_name. "#EC CI_GENBUFF - IF sy-subrc <> 0. - lcx_exception=>raise( 'not found in TLIBT' ). - ENDIF. - - lt_functab = functions( ). - lt_includes = includes( ). - -* todo, dynpros - - io_xml->add( iv_name = 'AREAT' - ig_data = lv_areat ). - io_xml->add( iv_name = 'INCLUDES' - ig_data = lt_includes ). - - ENDMETHOD. "serialize_xml - - METHOD includes. - - DATA: lv_program TYPE program, - lv_cnam TYPE reposrc-cnam, - lv_tabix LIKE sy-tabix, - lt_functab TYPE ty_rs38l_incl_tt. - - FIELD-SYMBOLS: LIKE LINE OF rt_includes, - LIKE LINE OF lt_functab. - - - lv_program = main_name( ). - lt_functab = functions( ). - - CALL FUNCTION 'RS_GET_ALL_INCLUDES' - EXPORTING - program = lv_program -* WITH_RESERVED_INCLUDES = -* WITH_CLASS_INCLUDES = ' ' hmm, todo - TABLES - includetab = rt_includes - EXCEPTIONS - not_existent = 1 - no_program = 2 - OTHERS = 3. - IF sy-subrc <> 0. - lcx_exception=>raise( 'Error from RS_GET_ALL_INCLUDES' ). - ENDIF. - - LOOP AT lt_functab ASSIGNING . - DELETE TABLE rt_includes FROM -include. - ENDLOOP. - - - LOOP AT rt_includes ASSIGNING . - lv_tabix = sy-tabix. - -* skip SAP standard includes - SELECT SINGLE cnam FROM reposrc INTO lv_cnam - WHERE progname = - AND r3state = 'A' - AND cnam = 'SAP'. - IF sy-subrc = 0. - DELETE rt_includes INDEX lv_tabix. - CONTINUE. - ENDIF. - -* also make sure the include exists - SELECT SINGLE cnam FROM reposrc INTO lv_cnam - WHERE progname = - AND r3state = 'A'. - IF sy-subrc <> 0. - DELETE rt_includes INDEX lv_tabix. - ENDIF. - - ENDLOOP. - - APPEND lv_program TO rt_includes. - - ENDMETHOD. "includes - - METHOD functions. - - DATA: lv_area TYPE rs38l-area. - - - lv_area = ms_item-obj_name. - - CALL FUNCTION 'RS_FUNCTION_POOL_CONTENTS' - EXPORTING - function_pool = lv_area - TABLES - functab = rt_functab - EXCEPTIONS - function_pool_not_found = 1 - OTHERS = 2. - IF sy-subrc <> 0. - lcx_exception=>raise( 'Error from RS_FUNCTION_POOL_CONTENTS' ). - ENDIF. - - ENDMETHOD. "functions - - METHOD main_name. - - DATA: lv_area TYPE rs38l-area, - lv_namespace TYPE rs38l-namespace, - lv_group TYPE rs38l-area. - - - lv_area = ms_item-obj_name. - - CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' - EXPORTING - complete_area = lv_area - IMPORTING - namespace = lv_namespace - group = lv_group - EXCEPTIONS - include_not_exists = 1 - group_not_exists = 2 - no_selections = 3 - no_function_include = 4 - no_function_pool = 5 - delimiter_wrong_position = 6 - no_customer_function_group = 7 - no_customer_function_include = 8 - reserved_name_customer = 9 - namespace_too_long = 10 - area_length_error = 11 - OTHERS = 12. - IF sy-subrc <> 0. - lcx_exception=>raise( 'Error from FUNCTION_INCLUDE_SPLIT' ). - ENDIF. - - CONCATENATE lv_namespace 'SAPL' lv_group INTO rv_program. - - ENDMETHOD. "main_name - - METHOD serialize_functions. - - DATA: - lt_source TYPE TABLE OF rssource, - lt_functab TYPE ty_rs38l_incl_tt, - lt_new_source TYPE rsfb_source. - - FIELD-SYMBOLS: LIKE LINE OF lt_functab, - LIKE LINE OF rt_functions. - - - lt_functab = functions( ). - - LOOP AT lt_functab ASSIGNING . -* fm RPY_FUNCTIONMODULE_READ does not support source code -* lines longer than 72 characters - APPEND INITIAL LINE TO rt_functions ASSIGNING . - MOVE-CORRESPONDING TO . - - CALL FUNCTION 'RPY_FUNCTIONMODULE_READ_NEW' - EXPORTING - functionname = -funcname - IMPORTING - global_flag = -global_flag - remote_call = -remote_call - update_task = -update_task - short_text = -short_text - remote_basxml_supported = -remote_basxml - TABLES - import_parameter = -import - changing_parameter = -changing - export_parameter = -export - tables_parameter = -tables - exception_list = -exception - documentation = -documentation - source = lt_source - CHANGING - new_source = lt_new_source - EXCEPTIONS - error_message = 1 - function_not_found = 2 - invalid_name = 3 - OTHERS = 4. - IF sy-subrc <> 0. - lcx_exception=>raise( 'Error from RPY_FUNCTIONMODULE_READ_NEW' ). - ENDIF. - - IF NOT lt_new_source IS INITIAL. - mo_files->add_abap( iv_extra = -funcname - it_abap = lt_new_source ). - ELSE. - mo_files->add_abap( iv_extra = -funcname - it_abap = lt_source ). - ENDIF. - - ENDLOOP. - - ENDMETHOD. "serialize_functions - - METHOD serialize_includes. - - DATA: lt_includes TYPE rso_t_objnm. - - FIELD-SYMBOLS: LIKE LINE OF lt_includes. - - - lt_includes = includes( ). - - LOOP AT lt_includes ASSIGNING . - -* todo, filename is not correct, a include can be used in several programs - serialize_program( is_item = ms_item - io_files = mo_files - iv_program = - iv_extra = ). - - ENDLOOP. - - ENDMETHOD. "serialize_includes - - METHOD lif_object~serialize. - - DATA: lt_functions TYPE ty_function_tt, - ls_progdir TYPE ty_progdir, - lv_program_name TYPE programm, - lt_dynpros TYPE ty_dynpro_tt, - ls_cua TYPE ty_cua. - - IF lif_object~exists( ) = abap_false. - RETURN. - ENDIF. - - serialize_xml( io_xml ). - - lt_functions = serialize_functions( ). - io_xml->add( iv_name = 'FUNCTIONS' - ig_data = lt_functions ). - - serialize_includes( ). - - lv_program_name = main_name( ). - ls_progdir = read_progdir( lv_program_name ). - - IF ls_progdir-subc = 'F'. - lt_dynpros = serialize_dynpros( lv_program_name ). - io_xml->add( iv_name = 'DYNPROS' - ig_data = lt_dynpros ). - - ls_cua = serialize_cua( lv_program_name ). - io_xml->add( iv_name = 'CUA' - ig_data = ls_cua ). - ENDIF. - - ENDMETHOD. "serialize - - METHOD lif_object~deserialize. - - DATA: lv_program_name TYPE programm, - lt_functions TYPE ty_function_tt, - lt_dynpros TYPE ty_dynpro_tt, - ls_cua TYPE ty_cua. - - - deserialize_xml( - io_xml = io_xml - iv_package = iv_package ). - - io_xml->read( EXPORTING iv_name = 'FUNCTIONS' - CHANGING cg_data = lt_functions ). - deserialize_functions( lt_functions ). - - deserialize_includes( - io_xml = io_xml - iv_package = iv_package ). - - lv_program_name = main_name( ). - - io_xml->read( EXPORTING iv_name = 'DYNPROS' - CHANGING cg_data = lt_dynpros ). - deserialize_dynpros( it_dynpros = lt_dynpros ). - - io_xml->read( EXPORTING iv_name = 'CUA' - CHANGING cg_data = ls_cua ). - deserialize_cua( iv_program_name = lv_program_name - is_cua = ls_cua ). - - ENDMETHOD. "deserialize - - METHOD lif_object~delete. - - DATA: lv_area TYPE rs38l-area. - - - lv_area = ms_item-obj_name. - - CALL FUNCTION 'RS_FUNCTION_POOL_DELETE' - EXPORTING - area = lv_area - suppress_popups = abap_true - skip_progress_ind = abap_true - EXCEPTIONS - canceled_in_corr = 1 - enqueue_system_failure = 2 - function_exist = 3 - not_executed = 4 - no_modify_permission = 5 - no_show_permission = 6 - permission_failure = 7 - pool_not_exist = 8 - cancelled = 9 - OTHERS = 10. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from RS_FUNCTION_POOL_DELETE' ). - ENDIF. - - ENDMETHOD. "delete - - METHOD lif_object~jump. - - CALL FUNCTION 'RS_TOOL_ACCESS' - EXPORTING - operation = 'SHOW' - object_name = ms_item-obj_name - object_type = 'FUGR' - in_new_window = abap_true. - - ENDMETHOD. "jump - -ENDCLASS. "lcl_object_fugr IMPLEMENTATION - -*----------------------------------------------------------------------* -* CLASS lcl_object_prog DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_object_prog DEFINITION INHERITING FROM lcl_objects_program FINAL. - - PUBLIC SECTION. - INTERFACES lif_object. - ALIASES mo_files FOR lif_object~mo_files. - - PRIVATE SECTION. - - METHODS deserialize_textpool - IMPORTING it_tpool TYPE textpool_table - RAISING lcx_exception. - -ENDCLASS. "lcl_object_prog DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_object_prog IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_object_prog IMPLEMENTATION. - - METHOD lif_object~changed_by. - SELECT SINGLE unam FROM reposrc INTO rv_user - WHERE progname = ms_item-obj_name - AND r3state = 'A'. - IF sy-subrc <> 0. - rv_user = c_user_unknown. - ENDIF. - ENDMETHOD. - - METHOD lif_object~get_metadata. - rs_metadata = get_metadata( ). - ENDMETHOD. "lif_object~get_metadata - - METHOD lif_object~exists. - - DATA: lv_progname TYPE reposrc-progname. - - - SELECT SINGLE progname FROM reposrc INTO lv_progname - WHERE progname = ms_item-obj_name - AND r3state = 'A'. - rv_bool = boolc( sy-subrc = 0 ). - - ENDMETHOD. "lif_object~exists - - METHOD lif_object~jump. - - CALL FUNCTION 'RS_TOOL_ACCESS' - EXPORTING - operation = 'SHOW' - object_name = ms_item-obj_name - object_type = 'PROG' - in_new_window = abap_true. - - ENDMETHOD. "jump - - METHOD lif_object~delete. - - DATA: lv_program LIKE sy-repid. - - - lv_program = ms_item-obj_name. - - CALL FUNCTION 'RS_DELETE_PROGRAM' - EXPORTING - program = lv_program - suppress_popup = abap_true - EXCEPTIONS - enqueue_lock = 1 - object_not_found = 2 - permission_failure = 3 - reject_deletion = 4 - OTHERS = 5. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from RS_DELETE_PROGRAM' ). - ENDIF. - - ENDMETHOD. "delete - - METHOD deserialize_textpool. - - READ TABLE it_tpool WITH KEY id = 'R' TRANSPORTING NO FIELDS. - IF ( sy-subrc = 0 AND lines( it_tpool ) = 1 ) OR lines( it_tpool ) = 0. - RETURN. " no action for includes - ENDIF. - - INSERT TEXTPOOL ms_item-obj_name - FROM it_tpool - LANGUAGE mv_language - STATE 'I'. - IF sy-subrc <> 0. - lcx_exception=>raise( 'error from INSERT TEXTPOOL' ). - ENDIF. - - lcl_objects_activation=>add( iv_type = 'REPT' - iv_name = ms_item-obj_name ). - - ENDMETHOD. "deserialize_textpool - - METHOD lif_object~serialize. - - serialize_program( io_xml = io_xml - is_item = ms_item - io_files = mo_files ). - - ENDMETHOD. "lif_serialize~serialize - - METHOD lif_object~deserialize. - - DATA: lv_program_name TYPE programm, - ls_progdir TYPE ty_progdir, - lt_tpool TYPE textpool_table, - lt_dynpros TYPE ty_dynpro_tt, - lt_tpool_ext TYPE ty_tpool_tt, - ls_cua TYPE ty_cua, - lt_source TYPE abaptxt255_tab. - - lv_program_name = ms_item-obj_name. - - lt_source = mo_files->read_abap( ). - - io_xml->read( EXPORTING iv_name = 'TPOOL' - CHANGING cg_data = lt_tpool_ext ). - lt_tpool = read_tpool( lt_tpool_ext ). - - io_xml->read( EXPORTING iv_name = 'PROGDIR' - CHANGING cg_data = ls_progdir ). - deserialize_program( is_progdir = ls_progdir - it_source = lt_source - it_tpool = lt_tpool - iv_package = iv_package ). - - io_xml->read( EXPORTING iv_name = 'DYNPROS' - CHANGING cg_data = lt_dynpros ). - deserialize_dynpros( it_dynpros = lt_dynpros ). - - io_xml->read( EXPORTING iv_name = 'CUA' - CHANGING cg_data = ls_cua ). - deserialize_cua( iv_program_name = lv_program_name - is_cua = ls_cua ). - - deserialize_textpool( lt_tpool ). - - ENDMETHOD. "lif_serialize~deserialize - -ENDCLASS. "lcl_object_prog IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_acid.prog.abap b/src/zabapgit_object_acid.prog.abap index a840bd035..efc47f9e1 100644 --- a/src/zabapgit_object_acid.prog.abap +++ b/src/zabapgit_object_acid.prog.abap @@ -27,6 +27,10 @@ ENDCLASS. "lcl_object_acid DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_acid IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. "lif_object~get_metadata @@ -142,4 +146,8 @@ CLASS lcl_object_acid IMPLEMENTATION. ENDMETHOD. "lif_object~jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_acid IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_auth.prog.abap b/src/zabapgit_object_auth.prog.abap index de8abb6ff..f772b72ce 100644 --- a/src/zabapgit_object_auth.prog.abap +++ b/src/zabapgit_object_auth.prog.abap @@ -22,6 +22,10 @@ ENDCLASS. "lcl_object_auth DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_auth IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. "lif_object~get_metadata @@ -115,4 +119,8 @@ CLASS lcl_object_auth IMPLEMENTATION. ENDMETHOD. "lif_object~jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_auth IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_clas.prog.abap b/src/zabapgit_object_clas.prog.abap new file mode 100644 index 000000000..5549a80c8 --- /dev/null +++ b/src/zabapgit_object_clas.prog.abap @@ -0,0 +1,1076 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_OBJECT_CLAS +*&---------------------------------------------------------------------* + +*----------------------------------------------------------------------* +* CLASS lcl_object_clas DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_object_clas DEFINITION INHERITING FROM lcl_objects_program. + + PUBLIC SECTION. + INTERFACES lif_object. + ALIASES mo_files FOR lif_object~mo_files. + + PRIVATE SECTION. + TYPES: BEGIN OF ty_sotr, + header TYPE sotr_head, + entries TYPE sotr_text_tt, + END OF ty_sotr. + + TYPES: ty_sotr_tt TYPE STANDARD TABLE OF ty_sotr WITH DEFAULT KEY. + + TYPES: ty_seocompotx_tt TYPE STANDARD TABLE OF seocompotx WITH DEFAULT KEY. + + DATA mv_skip_testclass TYPE abap_bool. + + METHODS deserialize_abap + IMPORTING io_xml TYPE REF TO lcl_xml_input + iv_package TYPE devclass + RAISING lcx_exception. + + METHODS deserialize_textpool + IMPORTING io_xml TYPE REF TO lcl_xml_input + RAISING lcx_exception. + + METHODS deserialize_docu + IMPORTING io_xml TYPE REF TO lcl_xml_input + RAISING lcx_exception. + + METHODS deserialize_sotr + IMPORTING io_xml TYPE REF TO lcl_xml_input + iv_package TYPE devclass + RAISING lcx_exception. + + METHODS serialize_abap_old + IMPORTING is_clskey TYPE seoclskey + RETURNING VALUE(rt_source) TYPE ty_string_tt + RAISING lcx_exception. + + METHODS deserialize_abap_source_old + IMPORTING is_clskey TYPE seoclskey + it_source TYPE ty_string_tt + RAISING lcx_exception. + + METHODS deserialize_abap_source_new + IMPORTING is_clskey TYPE seoclskey + it_source TYPE ty_string_tt + RAISING lcx_exception + cx_sy_dyn_call_error. + + METHODS serialize_abap_new + IMPORTING is_clskey TYPE seoclskey + RETURNING VALUE(rt_source) TYPE ty_string_tt + RAISING lcx_exception + cx_sy_dyn_call_error. + + METHODS serialize_locals_imp + IMPORTING is_clskey TYPE seoclskey + RETURNING VALUE(rt_source) TYPE ty_string_tt + RAISING lcx_exception. + + METHODS serialize_locals_def + IMPORTING is_clskey TYPE seoclskey + RETURNING VALUE(rt_source) TYPE ty_string_tt + RAISING lcx_exception. + + METHODS read_include + IMPORTING is_clskey TYPE seoclskey + iv_type TYPE seop_include_ext_app + RETURNING VALUE(rt_source) TYPE seop_source_string. + + METHODS serialize_testclasses + IMPORTING is_clskey TYPE seoclskey + RETURNING VALUE(rt_source) TYPE ty_string_tt + RAISING lcx_exception. + + METHODS serialize_macros + IMPORTING is_clskey TYPE seoclskey + RETURNING VALUE(rt_source) TYPE ty_string_tt + RAISING lcx_exception. + + METHODS serialize_xml + IMPORTING io_xml TYPE REF TO lcl_xml_output + RAISING lcx_exception. + + METHODS read_sotr + RETURNING VALUE(rt_sotr) TYPE ty_sotr_tt + RAISING lcx_exception. + + METHODS remove_signatures + CHANGING ct_source TYPE ty_string_tt. + + METHODS reduce + CHANGING ct_source TYPE ty_string_tt. + + METHODS get_all_class_includes + RETURNING VALUE(rt_includes) TYPE seoincl_t. + +ENDCLASS. "lcl_object_dtel DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_object_intf DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_object_intf DEFINITION INHERITING FROM lcl_object_clas FINAL. +* todo, CLAS + INTF to be refactored, see: +* https://github.com/larshp/abapGit/issues/21 +ENDCLASS. "lcl_object_intf DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_object_clas IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_object_clas IMPLEMENTATION. + + METHOD get_all_class_includes. +* note: includes returned might not exist +* method cl_oo_classname_service=>GET_ALL_CLASS_INCLUDES does not exist in 702 + + DATA: lv_clsname TYPE seoclsname, + lt_methods TYPE seop_methods_w_include. + + FIELD-SYMBOLS: LIKE LINE OF lt_methods. + + + lv_clsname = ms_item-obj_name. + + APPEND cl_oo_classname_service=>get_ccdef_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_ccmac_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_ccimp_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_cl_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_ccau_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_pubsec_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_prosec_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_prisec_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_classpool_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_ct_name( lv_clsname ) TO rt_includes. + APPEND cl_oo_classname_service=>get_cs_name( lv_clsname ) TO rt_includes. + + lt_methods = cl_oo_classname_service=>get_all_method_includes( lv_clsname ). + LOOP AT lt_methods ASSIGNING . + APPEND -incname TO rt_includes. + ENDLOOP. + + ENDMETHOD. + + METHOD lif_object~has_changed_since. + + DATA: lv_clsname TYPE seoclsname, + lv_program TYPE program, + lt_incl TYPE seoincl_t. + + FIELD-SYMBOLS LIKE LINE OF lt_incl. + + lv_clsname = ms_item-obj_name. + + CASE ms_item-obj_type. + WHEN 'CLAS'. + TRY. + CALL METHOD cl_oo_classname_service=>('GET_ALL_CLASS_INCLUDES') + EXPORTING + class_name = lv_clsname + RECEIVING + result = lt_incl. + CATCH cx_sy_dyn_call_illegal_method. +* method does not exist in 702, just report everything as changed + rv_changed = abap_true. + ENDTRY. + LOOP AT lt_incl ASSIGNING . + rv_changed = check_prog_changed_since( + iv_program = + iv_timestamp = iv_timestamp + iv_skip_gui = abap_true ). + IF rv_changed = abap_true. + RETURN. + ENDIF. + ENDLOOP. + WHEN 'INTF'. + lv_program = cl_oo_classname_service=>get_interfacepool_name( lv_clsname ). + rv_changed = check_prog_changed_since( + iv_program = lv_program + iv_timestamp = iv_timestamp + iv_skip_gui = abap_true ). + WHEN OTHERS. + lcx_exception=>raise( 'class delete, unknown type' ). + ENDCASE. + + ENDMETHOD. "lif_object~has_changed_since + + METHOD lif_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. "lif_object~get_metadata + + METHOD lif_object~changed_by. + + TYPES: BEGIN OF ty_includes, + programm TYPE programm, + END OF ty_includes. + + TYPES: BEGIN OF ty_reposrc, + unam TYPE reposrc-unam, + udat TYPE reposrc-udat, + utime TYPE reposrc-utime, + END OF ty_reposrc. + + DATA: lt_reposrc TYPE STANDARD TABLE OF ty_reposrc, + ls_reposrc LIKE LINE OF lt_reposrc, + lt_includes TYPE STANDARD TABLE OF ty_includes, + lv_clsname TYPE seoclsname. + + + lv_clsname = ms_item-obj_name. + + CASE ms_item-obj_type. + WHEN 'CLAS'. + lt_includes = get_all_class_includes( ). + ASSERT lines( lt_includes ) > 0. + WHEN 'INTF'. + APPEND cl_oo_classname_service=>get_interfacepool_name( lv_clsname ) TO lt_includes. + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + + SELECT unam udat utime FROM reposrc + INTO TABLE lt_reposrc + FOR ALL ENTRIES IN lt_includes + WHERE progname = lt_includes-programm + AND r3state = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ELSE. + SORT lt_reposrc BY udat DESCENDING utime DESCENDING. + READ TABLE lt_reposrc INDEX 1 INTO ls_reposrc. + ASSERT sy-subrc = 0. + rv_user = ls_reposrc-unam. + ENDIF. + + ENDMETHOD. + + METHOD lif_object~exists. + + DATA: ls_clskey TYPE seoclskey. + + + ls_clskey-clsname = ms_item-obj_name. + + CALL FUNCTION 'SEO_CLASS_EXISTENCE_CHECK' + EXPORTING + clskey = ls_clskey + EXCEPTIONS + not_specified = 1 + not_existing = 2 + is_interface = 3 + no_text = 4 + inconsistent = 5 + OTHERS = 6. + rv_bool = boolc( sy-subrc <> 2 ). + + ENDMETHOD. "lif_object~exists + + METHOD lif_object~jump. + + CALL FUNCTION 'RS_TOOL_ACCESS' + EXPORTING + operation = 'SHOW' + object_name = ms_item-obj_name + object_type = 'CLAS' + in_new_window = abap_true. + + ENDMETHOD. "jump + + METHOD lif_object~delete. + + DATA: ls_clskey TYPE seoclskey. + + + ls_clskey-clsname = ms_item-obj_name. + + CASE ms_item-obj_type. + WHEN 'CLAS'. + CALL FUNCTION 'SEO_CLASS_DELETE_COMPLETE' + EXPORTING + clskey = ls_clskey + EXCEPTIONS + not_existing = 1 + is_interface = 2 + db_error = 3 + no_access = 4 + other = 5 + OTHERS = 6. + IF sy-subrc <> 0. + lcx_exception=>raise( 'Error from SEO_CLASS_DELETE_COMPLETE' ). + ENDIF. + WHEN 'INTF'. + CALL FUNCTION 'SEO_INTERFACE_DELETE_COMPLETE' + EXPORTING + intkey = ls_clskey + EXCEPTIONS + not_existing = 1 + is_class = 2 + db_error = 3 + no_access = 4 + other = 5 + OTHERS = 6. + IF sy-subrc <> 0. + lcx_exception=>raise( 'Error from SEO_INTERFACE_DELETE_COMPLETE' ). + ENDIF. + WHEN OTHERS. + lcx_exception=>raise( 'class delete, unknown type' ). + ENDCASE. + + ENDMETHOD. "delete + + METHOD reduce. + + DATA: lv_source LIKE LINE OF ct_source, + lv_found TYPE sap_bool. + + +* skip files that only contain the standard comments + lv_found = abap_false. + LOOP AT ct_source INTO lv_source. + IF strlen( lv_source ) >= 3 AND lv_source(3) <> '*"*'. + lv_found = abap_true. + ENDIF. + ENDLOOP. + IF lv_found = abap_false. + CLEAR ct_source[]. + ENDIF. + + ENDMETHOD. "reduce + + METHOD serialize_locals_imp. + + rt_source = read_include( is_clskey = is_clskey + iv_type = seop_ext_class_locals_imp ). + + reduce( CHANGING ct_source = rt_source ). + + ENDMETHOD. "serialize_local + + METHOD serialize_locals_def. + + rt_source = read_include( is_clskey = is_clskey + iv_type = seop_ext_class_locals_def ). + + reduce( CHANGING ct_source = rt_source ). + + ENDMETHOD. "serialize_locals_def + + METHOD read_include. + + DATA: ls_include TYPE progstruc. + + + ASSERT iv_type = seop_ext_class_locals_def + OR iv_type = seop_ext_class_locals_imp + OR iv_type = seop_ext_class_macros + OR iv_type = seop_ext_class_testclasses. + + ls_include-rootname = is_clskey-clsname. + TRANSLATE ls_include-rootname USING ' ='. + ls_include-categorya = iv_type(1). + ls_include-codea = iv_type+1(4). + +* it looks like there is an issue in function module SEO_CLASS_GET_INCLUDE_SOURCE +* on 750 kernels, where the READ REPORT without STATE addition does not +* return the active version, this method is a workaround for this issue + READ REPORT ls_include INTO rt_source STATE 'A'. + + ENDMETHOD. + + METHOD serialize_testclasses. + + DATA: lv_line1 LIKE LINE OF rt_source, + lv_line2 LIKE LINE OF rt_source. + + + rt_source = read_include( is_clskey = is_clskey + iv_type = seop_ext_class_testclasses ). + +* when creating classes in Eclipse it automatically generates the +* testclass include, but it is not needed, so skip to avoid +* creating an extra file in the repository. +* Also remove it if the content is manually removed, but +* the class still thinks it contains tests + mv_skip_testclass = abap_false. + IF lines( rt_source ) = 2. + READ TABLE rt_source INDEX 1 INTO lv_line1. + ASSERT sy-subrc = 0. + READ TABLE rt_source INDEX 2 INTO lv_line2. + ASSERT sy-subrc = 0. + IF lv_line1(3) = '*"*' AND lv_line2 IS INITIAL. + mv_skip_testclass = abap_true. + ENDIF. + ELSEIF lines( rt_source ) = 1. + READ TABLE rt_source INDEX 1 INTO lv_line1. + ASSERT sy-subrc = 0. + IF lv_line1(3) = '*"*' OR lv_line1 IS INITIAL. + mv_skip_testclass = abap_true. + ENDIF. + ELSEIF lines( rt_source ) = 0. + mv_skip_testclass = abap_true. + ENDIF. + + ENDMETHOD. "serialize_test + + METHOD serialize_macros. + + rt_source = read_include( is_clskey = is_clskey + iv_type = seop_ext_class_macros ). + + reduce( CHANGING ct_source = rt_source ). + + ENDMETHOD. "serialize_macro + + METHOD serialize_abap_old. +* for old ABAP AS versions + DATA: lo_source TYPE REF TO cl_oo_source. + + + CREATE OBJECT lo_source + EXPORTING + clskey = is_clskey + EXCEPTIONS + class_not_existing = 1 + OTHERS = 2. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from CL_OO_SOURCE' ). + ENDIF. + + lo_source->read( 'A' ). + rt_source = lo_source->get_old_source( ). + remove_signatures( CHANGING ct_source = rt_source ). + + ENDMETHOD. "serialize_abap + + METHOD serialize_abap_new. + + DATA: lo_source TYPE REF TO object, + lo_instance TYPE REF TO object. + +* do not call the class/methods statically, as it will +* give syntax errors on old versions + CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') + RECEIVING + result = lo_instance. + + CALL METHOD lo_instance->('CREATE_CLIF_SOURCE') + EXPORTING + clif_name = is_clskey-clsname + version = 'A' + RECEIVING + result = lo_source. + + CALL METHOD lo_source->('GET_SOURCE') + IMPORTING + source = rt_source. + + ENDMETHOD. + + METHOD remove_signatures. + +* signatures messes up in CL_OO_SOURCE when deserializing and serializing +* within same session + + DATA: lv_begin TYPE string, + lv_end TYPE string, + lv_remove TYPE sap_bool, + lv_source LIKE LINE OF ct_source. + + + CONCATENATE '* ------------------------------------' + '---------------------------------------------------+' + INTO lv_begin. + + CONCATENATE '* +------------------------------------------------' + '--------------------------------------' + INTO lv_end. + + lv_remove = abap_false. + LOOP AT ct_source INTO lv_source. + IF lv_source = lv_begin. + lv_remove = abap_true. + ENDIF. + IF lv_remove = abap_true. + DELETE ct_source INDEX sy-tabix. + ENDIF. + IF lv_source = lv_end. + lv_remove = abap_false. + ENDIF. + ENDLOOP. + + ENDMETHOD. "remove_signatures + + METHOD lif_object~serialize. + + DATA: lt_source TYPE seop_source_string, + ls_clskey TYPE seoclskey. + + + ls_clskey-clsname = ms_item-obj_name. + + IF lif_object~exists( ) = abap_false. + RETURN. + ENDIF. + + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + version = seoc_version_active + force = seox_true. + CALL FUNCTION 'SEO_BUFFER_REFRESH' + EXPORTING + version = seoc_version_inactive + force = seox_true. + + TRY. + lt_source = serialize_abap_new( ls_clskey ). + CATCH cx_sy_dyn_call_error. + lt_source = serialize_abap_old( ls_clskey ). + ENDTRY. + + mo_files->add_abap( lt_source ). + + IF ms_item-obj_type = 'CLAS'. + lt_source = serialize_locals_def( ls_clskey ). + IF NOT lt_source[] IS INITIAL. + mo_files->add_abap( iv_extra = 'locals_def' + it_abap = lt_source ). "#EC NOTEXT + ENDIF. + + lt_source = serialize_locals_imp( ls_clskey ). + IF NOT lt_source[] IS INITIAL. + mo_files->add_abap( iv_extra = 'locals_imp' + it_abap = lt_source ). "#EC NOTEXT + ENDIF. + + lt_source = serialize_testclasses( ls_clskey ). + IF NOT lt_source[] IS INITIAL AND mv_skip_testclass = abap_false. + mo_files->add_abap( iv_extra = 'testclasses' + it_abap = lt_source ). "#EC NOTEXT + ENDIF. + + lt_source = serialize_macros( ls_clskey ). + IF NOT lt_source[] IS INITIAL. + mo_files->add_abap( iv_extra = 'macros' + it_abap = lt_source ). "#EC NOTEXT + ENDIF. + ENDIF. + + serialize_xml( io_xml ). + + ENDMETHOD. "serialize + + METHOD read_sotr. + + DATA: lv_concept TYPE sotr_head-concept, + lt_seocompodf TYPE STANDARD TABLE OF seocompodf WITH DEFAULT KEY, + ls_header TYPE sotr_head, + lt_entries TYPE sotr_text_tt. + + FIELD-SYMBOLS: LIKE LINE OF rt_sotr, + LIKE LINE OF lt_seocompodf, + LIKE LINE OF lt_entries. + + + SELECT * FROM seocompodf + INTO TABLE lt_seocompodf + WHERE clsname = ms_item-obj_name + AND version = '1' + AND exposure = '2' + AND attdecltyp = '2' + AND type = 'SOTR_CONC' + ORDER BY PRIMARY KEY. + + LOOP AT lt_seocompodf ASSIGNING . + + lv_concept = translate( val = -attvalue from = '''' to = '' ). + + CALL FUNCTION 'SOTR_GET_CONCEPT' + EXPORTING + concept = lv_concept + IMPORTING + header = ls_header + TABLES + entries = lt_entries + EXCEPTIONS + no_entry_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from SOTR_GET_CONCEPT' ). + ENDIF. + + CLEAR: ls_header-paket, + ls_header-crea_name, + ls_header-crea_tstut, + ls_header-chan_name, + ls_header-chan_tstut. + + LOOP AT lt_entries ASSIGNING . + CLEAR: -version, + -crea_name, + -crea_tstut, + -chan_name, + -chan_tstut. + ENDLOOP. + + APPEND INITIAL LINE TO rt_sotr ASSIGNING . + -header = ls_header. + -entries = lt_entries. + + ENDLOOP. + + ENDMETHOD. + + METHOD serialize_xml. + + DATA: ls_vseoclass TYPE vseoclass, + lv_cp TYPE program, + lt_tpool TYPE textpool_table, + lv_object TYPE dokhl-object, + lv_state TYPE dokhl-dokstate, + lt_descriptions TYPE ty_seocompotx_tt, + ls_vseointerf TYPE vseointerf, + ls_clskey TYPE seoclskey, + lt_sotr TYPE ty_sotr_tt, + lt_lines TYPE tlinetab. + + + ls_clskey-clsname = ms_item-obj_name. + + CALL FUNCTION 'SEO_CLIF_GET' + EXPORTING + cifkey = ls_clskey + version = seoc_version_active + IMPORTING + class = ls_vseoclass + interface = ls_vseointerf + EXCEPTIONS + not_existing = 1 + deleted = 2 + model_only = 3 + OTHERS = 4. + IF sy-subrc = 1. + RETURN. " in case only inactive version exists + ELSEIF sy-subrc <> 0. + lcx_exception=>raise( 'error from seo_clif_get' ). + ENDIF. + + CLEAR: ls_vseoclass-uuid, + ls_vseoclass-author, + ls_vseoclass-createdon, + ls_vseoclass-changedby, + ls_vseoclass-changedon, + ls_vseoclass-r3release, + ls_vseoclass-chgdanyby, + ls_vseoclass-chgdanyon. + + IF mv_skip_testclass = abap_true. + CLEAR ls_vseoclass-with_unit_tests. + ENDIF. + + CLEAR: ls_vseointerf-uuid, + ls_vseointerf-author, + ls_vseointerf-createdon, + ls_vseointerf-changedby, + ls_vseointerf-changedon, + ls_vseointerf-r3release. + + CASE ms_item-obj_type. + WHEN 'CLAS'. + io_xml->add( iv_name = 'VSEOCLASS' + ig_data = ls_vseoclass ). + + lv_cp = cl_oo_classname_service=>get_classpool_name( ls_clskey-clsname ). + READ TEXTPOOL lv_cp INTO lt_tpool LANGUAGE mv_language. "#EC CI_READ_REP + io_xml->add( iv_name = 'TPOOL' + ig_data = add_tpool( lt_tpool ) ). + + IF ls_vseoclass-category = seoc_category_exception. + lt_sotr = read_sotr( ). + IF lines( lt_sotr ) > 0. + io_xml->add( iv_name = 'SOTR' + ig_data = lt_sotr ). + ENDIF. + ENDIF. + WHEN 'INTF'. + io_xml->add( iv_name = 'VSEOINTERF' + ig_data = ls_vseointerf ). + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + + lv_object = ls_clskey-clsname. + CALL FUNCTION 'DOCU_GET' + EXPORTING + id = 'CL' + langu = mv_language + object = lv_object + IMPORTING + dokstate = lv_state + TABLES + line = lt_lines + EXCEPTIONS + no_docu_on_screen = 1 + no_docu_self_def = 2 + no_docu_temp = 3 + ret_code = 4 + OTHERS = 5. + IF sy-subrc = 0 AND lv_state = 'R'. + io_xml->add( iv_name = 'LINES' + ig_data = lt_lines ). + ENDIF. + + SELECT * FROM seocompotx INTO TABLE lt_descriptions + WHERE clsname = ls_clskey-clsname. + DELETE lt_descriptions WHERE descript IS INITIAL. + IF lines( lt_descriptions ) > 0. + io_xml->add( iv_name = 'DESCRIPTIONS' + ig_data = lt_descriptions ). + ENDIF. + + ENDMETHOD. "serialize_xml + + METHOD lif_object~deserialize. + +* function group SEOK +* function group SEOQ +* function group SEOP +* class CL_OO_CLASSNAME_SERVICE +* class CL_OO_SOURCE + + deserialize_abap( io_xml = io_xml + iv_package = iv_package ). + + IF ms_item-obj_type = 'CLAS'. + deserialize_textpool( io_xml ). + + deserialize_sotr( io_xml = io_xml + iv_package = iv_package ). + ENDIF. + + deserialize_docu( io_xml ). + + ENDMETHOD. "deserialize + + METHOD deserialize_sotr. + + DATA: lt_sotr TYPE ty_sotr_tt, + lt_objects TYPE sotr_objects, + ls_paket TYPE sotr_pack, + lv_object LIKE LINE OF lt_objects. + + FIELD-SYMBOLS: LIKE LINE OF lt_sotr. + + + io_xml->read( EXPORTING iv_name = 'SOTR' + CHANGING cg_data = lt_sotr ). + + IF lines( lt_sotr ) = 0. + RETURN. + ENDIF. + + LOOP AT lt_sotr ASSIGNING . + CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' + EXPORTING + object_vector = -header-objid_vec + IMPORTING + objects = lt_objects + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from SOTR_OBJECT_GET_OBJECTS' ). + ENDIF. + + READ TABLE lt_objects INDEX 1 INTO lv_object. + ASSERT sy-subrc = 0. + + ls_paket-paket = iv_package. + + CALL FUNCTION 'SOTR_CREATE_CONCEPT' + EXPORTING + paket = ls_paket + crea_lan = -header-crea_lan + alias_name = -header-alias_name + object = lv_object + entries = -entries + concept_default = -header-concept + EXCEPTIONS + package_missing = 1 + crea_lan_missing = 2 + object_missing = 3 + paket_does_not_exist = 4 + alias_already_exist = 5 + object_type_not_found = 6 + langu_missing = 7 + identical_context_not_allowed = 8 + text_too_long = 9 + error_in_update = 10 + no_master_langu = 11 + error_in_concept_id = 12 + alias_not_allowed = 13 + tadir_entry_creation_failed = 14 + internal_error = 15 + error_in_correction = 16 + user_cancelled = 17 + no_entry_found = 18 + OTHERS = 19. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from SOTR_CREATE_CONCEPT' ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + + METHOD deserialize_docu. + + DATA: lt_lines TYPE tlinetab, + lv_object TYPE dokhl-object. + + + io_xml->read( EXPORTING iv_name = 'LINES' + CHANGING cg_data = lt_lines ). + + IF lt_lines[] IS INITIAL. + RETURN. + ENDIF. + + lv_object = ms_item-obj_name. + CALL FUNCTION 'DOCU_UPD' + EXPORTING + id = 'CL' + langu = mv_language + object = lv_object + TABLES + line = lt_lines + EXCEPTIONS + ret_code = 1 + OTHERS = 2. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from DOCU_UPD' ). + ENDIF. + + ENDMETHOD. "deserialize_doku + + METHOD deserialize_textpool. + + DATA: lv_cp TYPE program, + lv_clsname TYPE seoclsname, + lt_tpool_ext TYPE ty_tpool_tt, + lt_tpool TYPE textpool_table. + + + io_xml->read( EXPORTING iv_name = 'TPOOL' + CHANGING cg_data = lt_tpool_ext ). + lt_tpool = read_tpool( lt_tpool_ext ). + + IF lt_tpool[] IS INITIAL. + RETURN. + ENDIF. + + lv_clsname = ms_item-obj_name. + lv_cp = cl_oo_classname_service=>get_classpool_name( lv_clsname ). + + INSERT TEXTPOOL lv_cp + FROM lt_tpool + LANGUAGE mv_language + STATE 'I'. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from INSERT TEXTPOOL' ). + ENDIF. + + lcl_objects_activation=>add( iv_type = 'REPT' + iv_name = lv_cp ). + + ENDMETHOD. "deserialize_textpool + + METHOD deserialize_abap. + + DATA: ls_vseoclass TYPE vseoclass, + ls_vseointerf TYPE vseointerf, + lt_source TYPE seop_source_string, + lt_locals_def TYPE seop_source_string, + lt_locals_imp TYPE seop_source_string, + lt_locals_mac TYPE seop_source_string, + lt_testclasses TYPE seop_source_string, + lt_descriptions TYPE ty_seocompotx_tt, + ls_clskey TYPE seoclskey. + + + lt_source = mo_files->read_abap( ). + + lt_locals_def = mo_files->read_abap( iv_extra = 'locals_def' + iv_error = abap_false ). "#EC NOTEXT + + lt_locals_imp = mo_files->read_abap( iv_extra = 'locals_imp' + iv_error = abap_false ). "#EC NOTEXT + + lt_locals_mac = mo_files->read_abap( iv_extra = 'macros' + iv_error = abap_false ). "#EC NOTEXT + + lt_testclasses = mo_files->read_abap( iv_extra = 'testclasses' + iv_error = abap_false ). "#EC NOTEXT + + ls_clskey-clsname = ms_item-obj_name. + + + CASE ms_item-obj_type. + WHEN 'CLAS'. + io_xml->read( EXPORTING iv_name = 'VSEOCLASS' + CHANGING cg_data = ls_vseoclass ). + + CALL FUNCTION 'SEO_CLASS_CREATE_COMPLETE' + EXPORTING + devclass = iv_package + overwrite = seox_true + CHANGING + class = ls_vseoclass + EXCEPTIONS + existing = 1 + is_interface = 2 + db_error = 3 + component_error = 4 + no_access = 5 + other = 6 + OTHERS = 7. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from SEO_CLASS_CREATE_COMPLETE' ). + ENDIF. + + WHEN 'INTF'. + io_xml->read( EXPORTING iv_name = 'VSEOINTERF' + CHANGING cg_data = ls_vseointerf ). + + CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' + EXPORTING + devclass = iv_package + overwrite = seox_true + CHANGING + interface = ls_vseointerf + EXCEPTIONS + existing = 1 + is_class = 2 + db_error = 3 + component_error = 4 + no_access = 5 + other = 6 + OTHERS = 7. + IF sy-subrc <> 0. + lcx_exception=>raise( 'Error from SEO_INTERFACE_CREATE_COMPLETE' ). + ENDIF. + + WHEN OTHERS. + ASSERT 0 = 1. + ENDCASE. + + IF ms_item-obj_type = 'CLAS'. + CALL FUNCTION 'SEO_CLASS_GENERATE_LOCALS' + EXPORTING + clskey = ls_clskey + force = seox_true + locals_def = lt_locals_def + locals_imp = lt_locals_imp + locals_mac = lt_locals_mac + locals_testclasses = lt_testclasses + EXCEPTIONS + not_existing = 1 + model_only = 2 + locals_not_generated = 3 + locals_not_initialised = 4 + OTHERS = 5. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from generate_locals' ). + ENDIF. + ENDIF. + + TRY. + deserialize_abap_source_new( + is_clskey = ls_clskey + it_source = lt_source ). + CATCH cx_sy_dyn_call_error. + deserialize_abap_source_old( + is_clskey = ls_clskey + it_source = lt_source ). + ENDTRY. + + io_xml->read( EXPORTING iv_name = 'DESCRIPTIONS' + CHANGING cg_data = lt_descriptions ). + DELETE FROM seocompotx WHERE clsname = ls_clskey-clsname. + INSERT seocompotx FROM TABLE lt_descriptions. + + lcl_objects_activation=>add_item( ms_item ). + + ENDMETHOD. "deserialize + + METHOD deserialize_abap_source_old. +* for backwards compatability down to 702 + + DATA: lo_source TYPE REF TO cl_oo_source. + + + CREATE OBJECT lo_source + EXPORTING + clskey = is_clskey + EXCEPTIONS + class_not_existing = 1 + OTHERS = 2. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from CL_OO_SOURCE' ). + ENDIF. + + TRY. + lo_source->access_permission( seok_access_modify ). + lo_source->set_source( it_source ). + lo_source->save( ). + lo_source->access_permission( seok_access_free ). + CATCH cx_oo_access_permission. + lcx_exception=>raise( 'permission error' ). + CATCH cx_oo_source_save_failure. + lcx_exception=>raise( 'save failure' ). + ENDTRY. + + ENDMETHOD. + + METHOD deserialize_abap_source_new. + + DATA: lo_factory TYPE REF TO object, + lo_source TYPE REF TO object. + + + CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') + RECEIVING + result = lo_factory. + + CALL METHOD lo_factory->('CREATE_CLIF_SOURCE') + EXPORTING + clif_name = is_clskey-clsname + RECEIVING + result = lo_source. + + TRY. + CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~LOCK'). + CATCH cx_oo_access_permission. + lcx_exception=>raise( 'source_new, access permission exception' ). + ENDTRY. + + CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~SET_SOURCE') + EXPORTING + source = it_source. + + CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~SAVE'). + + CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~UNLOCK'). + + ENDMETHOD. + + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + +ENDCLASS. "lcl_object_CLAS IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_clas.prog.xml b/src/zabapgit_object_clas.prog.xml new file mode 100644 index 000000000..5b52c65de --- /dev/null +++ b/src/zabapgit_object_clas.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_OBJECT_CLAS + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_OBJECT_CLAS + 28 + + + + + + diff --git a/src/zabapgit_object_doct.prog.abap b/src/zabapgit_object_doct.prog.abap index 27f2b2fa1..76ed284a4 100644 --- a/src/zabapgit_object_doct.prog.abap +++ b/src/zabapgit_object_doct.prog.abap @@ -32,8 +32,13 @@ ENDCLASS. "lcl_object_msag DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_doct IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). + rs_metadata-delete_tadir = abap_true. ENDMETHOD. "lif_object~get_metadata METHOD read. @@ -146,4 +151,8 @@ CLASS lcl_object_doct IMPLEMENTATION. ENDMETHOD. "serialize + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_msag IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_docv.prog.abap b/src/zabapgit_object_docv.prog.abap index 6416fc0ec..c54655a2e 100644 --- a/src/zabapgit_object_docv.prog.abap +++ b/src/zabapgit_object_docv.prog.abap @@ -31,6 +31,10 @@ ENDCLASS. "lcl_object_msag DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_docv IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = read( )-head-tdluser. ENDMETHOD. "lif_object~changed_by @@ -61,6 +65,7 @@ CLASS lcl_object_docv IMPLEMENTATION. METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). + rs_metadata-delete_tadir = abap_true. ENDMETHOD. "lif_object~get_metadata METHOD lif_object~exists. @@ -150,4 +155,8 @@ CLASS lcl_object_docv IMPLEMENTATION. ENDMETHOD. "serialize + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_msag IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_doma.prog.abap b/src/zabapgit_object_doma.prog.abap index cce6ddc68..1864422a2 100644 --- a/src/zabapgit_object_doma.prog.abap +++ b/src/zabapgit_object_doma.prog.abap @@ -13,6 +13,34 @@ CLASS lcl_object_doma DEFINITION INHERITING FROM lcl_objects_super FINAL. INTERFACES lif_object. ALIASES mo_files FOR lif_object~mo_files. + PRIVATE SECTION. + + TYPES: BEGIN OF ty_dd01_texts, + ddlanguage TYPE dd01v-ddlanguage, + ddtext TYPE dd01v-ddtext, + END OF ty_dd01_texts, + BEGIN OF ty_dd07_texts, + valpos TYPE dd07v-valpos, + ddlanguage TYPE dd07v-ddlanguage, + domvalue_l TYPE dd07v-domvalue_l, + domvalue_h TYPE dd07v-domvalue_h, + ddtext TYPE dd07v-ddtext, + domval_ld TYPE dd07v-domval_ld, + domval_hd TYPE dd07v-domval_hd, + END OF ty_dd07_texts, + tt_dd01_texts TYPE STANDARD TABLE OF ty_dd01_texts, + tt_dd07_texts TYPE STANDARD TABLE OF ty_dd07_texts. + + METHODS: + serialize_texts + IMPORTING io_xml TYPE REF TO lcl_xml_output + RAISING lcx_exception, + deserialize_texts + IMPORTING io_xml TYPE REF TO lcl_xml_input + is_dd01v TYPE dd01v + it_dd07v TYPE dd07v_tab + RAISING lcx_exception. + ENDCLASS. "lcl_object_doma DEFINITION *----------------------------------------------------------------------* @@ -22,6 +50,22 @@ ENDCLASS. "lcl_object_doma DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_doma IMPLEMENTATION. + METHOD lif_object~has_changed_since. + + DATA: lv_date TYPE dats, + lv_time TYPE tims, + lv_ts TYPE timestamp. + + SELECT SINGLE as4date as4time FROM dd01l + INTO (lv_date, lv_time) + WHERE domname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + + _object_check_timestamp lv_date lv_time. + + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE as4user FROM dd01l INTO rv_user @@ -102,12 +146,9 @@ CLASS lcl_object_doma IMPLEMENTATION. EXCEPTIONS illegal_input = 1 OTHERS = 2. - IF sy-subrc <> 0. + IF sy-subrc <> 0 OR ls_dd01v IS INITIAL. lcx_exception=>raise( 'error from DDIF_DOMA_GET' ). ENDIF. - IF ls_dd01v IS INITIAL. - RETURN. " does not exist - ENDIF. CLEAR: ls_dd01v-as4user, ls_dd01v-as4date, @@ -118,6 +159,8 @@ CLASS lcl_object_doma IMPLEMENTATION. io_xml->add( iv_name = 'DD07V_TAB' ig_data = lt_dd07v ). + serialize_texts( io_xml ). + ENDMETHOD. "serialize METHOD lif_object~deserialize. @@ -128,8 +171,8 @@ CLASS lcl_object_doma IMPLEMENTATION. * fm TR_TADIR_INTERFACE * fm RS_CORR_INSERT ? - DATA: ls_dd01v TYPE dd01v, - lv_name TYPE ddobjname, + DATA: lv_name TYPE ddobjname, + ls_dd01v TYPE dd01v, lt_dd07v TYPE TABLE OF dd07v. @@ -159,8 +202,153 @@ CLASS lcl_object_doma IMPLEMENTATION. lcx_exception=>raise( 'error from DDIF_DOMA_PUT' ). ENDIF. + deserialize_texts( io_xml = io_xml + is_dd01v = ls_dd01v + it_dd07v = lt_dd07v ). + lcl_objects_activation=>add_item( ms_item ). ENDMETHOD. "deserialize + METHOD serialize_texts. + + DATA: lv_name TYPE ddobjname, + lv_index TYPE i, + ls_dd01v TYPE dd01v, + lt_dd07v TYPE TABLE OF dd07v, + lt_i18n_langs TYPE TABLE OF langu, + lt_dd01_texts TYPE tt_dd01_texts, + lt_dd07_texts TYPE tt_dd07_texts. + + FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, + LIKE LINE OF lt_dd07v, + LIKE LINE OF lt_dd01_texts, + LIKE LINE OF lt_dd07_texts. + + lv_name = ms_item-obj_name. + + " Collect additional languages + SELECT DISTINCT ddlanguage AS langu INTO TABLE lt_i18n_langs + FROM dd01v + WHERE domname = lv_name + AND ddlanguage <> mv_language. " Skip master lang - it was serialized already + + LOOP AT lt_i18n_langs ASSIGNING . + lv_index = sy-tabix. + + CALL FUNCTION 'DDIF_DOMA_GET' + EXPORTING + name = lv_name + langu = + IMPORTING + dd01v_wa = ls_dd01v + TABLES + dd07v_tab = lt_dd07v + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0 OR ls_dd01v-ddlanguage IS INITIAL. + DELETE lt_i18n_langs INDEX lv_index. " Don't save this lang + CONTINUE. + ENDIF. + + APPEND INITIAL LINE TO lt_dd01_texts ASSIGNING . + MOVE-CORRESPONDING ls_dd01v TO . + + LOOP AT lt_dd07v ASSIGNING . + APPEND INITIAL LINE TO lt_dd07_texts ASSIGNING . + MOVE-CORRESPONDING TO . + ENDLOOP. + + ENDLOOP. + + SORT lt_i18n_langs ASCENDING. + SORT lt_dd01_texts BY ddlanguage ASCENDING. + SORT lt_dd07_texts BY ddlanguage ASCENDING. + + IF lines( lt_i18n_langs ) > 1. + io_xml->add( iv_name = 'I18N_LANGS' + ig_data = lt_i18n_langs ). + + io_xml->add( iv_name = 'DD01_TEXTS' + ig_data = lt_dd01_texts ). + + io_xml->add( iv_name = 'DD07_TEXTS' + ig_data = lt_dd07_texts ). + ENDIF. + + ENDMETHOD. "serialize_texts + + METHOD deserialize_texts. + + DATA: lv_name TYPE ddobjname, + ls_dd01v_tmp TYPE dd01v, + lt_dd07v_tmp TYPE TABLE OF dd07v, + lt_i18n_langs TYPE TABLE OF langu, + lt_dd01_texts TYPE tt_dd01_texts, + lt_dd07_texts TYPE tt_dd07_texts. + + FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, + LIKE LINE OF it_dd07v, + LIKE LINE OF lt_dd01_texts, + LIKE LINE OF lt_dd07_texts. + + lv_name = ms_item-obj_name. + + io_xml->read( EXPORTING iv_name = 'I18N_LANGS' + CHANGING cg_data = lt_i18n_langs ). + + io_xml->read( EXPORTING iv_name = 'DD01_TEXTS' + CHANGING cg_data = lt_dd01_texts ). + + io_xml->read( EXPORTING iv_name = 'DD07_TEXTS' + CHANGING cg_data = lt_dd07_texts ). + + SORT lt_i18n_langs. + SORT lt_dd07_texts BY ddlanguage. " Optimization + + LOOP AT lt_i18n_langs ASSIGNING . + + " Domain description + ls_dd01v_tmp = is_dd01v. + READ TABLE lt_dd01_texts ASSIGNING WITH KEY ddlanguage = . + IF sy-subrc > 0. + lcx_exception=>raise( |DD01_TEXTS cannot find lang { } in XML| ). + ENDIF. + MOVE-CORRESPONDING TO ls_dd01v_tmp. + + " Domain values + lt_dd07v_tmp = it_dd07v. + LOOP AT lt_dd07v_tmp ASSIGNING . + READ TABLE lt_dd07_texts ASSIGNING + WITH KEY ddlanguage = valpos = -valpos. + CHECK sy-subrc = 0. " ! no translation -> master translation remain (maybe not OK) + MOVE-CORRESPONDING TO . + DELETE lt_dd07_texts INDEX sy-tabix. " Optimization + ENDLOOP. + + CALL FUNCTION 'DDIF_DOMA_PUT' + EXPORTING + name = lv_name + dd01v_wa = ls_dd01v_tmp + TABLES + dd07v_tab = lt_dd07v_tmp + EXCEPTIONS + doma_not_found = 1 + name_inconsistent = 2 + doma_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from DDIF_DOMA_PUT @TEXTS' ). + ENDIF. + ENDLOOP. + + ENDMETHOD. "deserialize_texts + + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_doma IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_dtel.prog.abap b/src/zabapgit_object_dtel.prog.abap index 22f1f0baa..024786107 100644 --- a/src/zabapgit_object_dtel.prog.abap +++ b/src/zabapgit_object_dtel.prog.abap @@ -13,6 +13,27 @@ CLASS lcl_object_dtel DEFINITION INHERITING FROM lcl_objects_super FINAL. INTERFACES lif_object. ALIASES mo_files FOR lif_object~mo_files. + PRIVATE SECTION. + + TYPES: BEGIN OF ty_dd04_texts, + ddlanguage TYPE dd04t-ddlanguage, + ddtext TYPE dd04t-ddtext, + reptext TYPE dd04t-reptext, + scrtext_s TYPE dd04t-scrtext_s, + scrtext_m TYPE dd04t-scrtext_m, + scrtext_l TYPE dd04t-scrtext_l, + END OF ty_dd04_texts, + tt_dd04_texts TYPE STANDARD TABLE OF ty_dd04_texts. + + METHODS: + serialize_texts + IMPORTING io_xml TYPE REF TO lcl_xml_output + RAISING lcx_exception, + deserialize_texts + IMPORTING io_xml TYPE REF TO lcl_xml_input + is_dd04v TYPE dd04v + RAISING lcx_exception. + ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* @@ -22,6 +43,22 @@ ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_dtel IMPLEMENTATION. + METHOD lif_object~has_changed_since. + + DATA: lv_date TYPE dats, + lv_time TYPE tims, + lv_ts TYPE timestamp. + + SELECT SINGLE as4date as4time FROM dd04l + INTO (lv_date, lv_time) + WHERE rollname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + + _object_check_timestamp lv_date lv_time. + + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE as4user FROM dd04l INTO rv_user @@ -62,9 +99,9 @@ CLASS lcl_object_dtel IMPLEMENTATION. DATA: lv_objname TYPE rsedd0-ddobjname. - lv_objname = ms_item-obj_name. + CALL FUNCTION 'RS_DD_DELETE_OBJ' EXPORTING no_ask = abap_true @@ -87,9 +124,9 @@ CLASS lcl_object_dtel IMPLEMENTATION. ls_dd04v TYPE dd04v, ls_tpara TYPE tpara. - lv_name = ms_item-obj_name. + CALL FUNCTION 'DDIF_DTEL_GET' EXPORTING name = lv_name @@ -100,22 +137,34 @@ CLASS lcl_object_dtel IMPLEMENTATION. EXCEPTIONS illegal_input = 1 OTHERS = 2. - IF sy-subrc <> 0. + IF sy-subrc <> 0 OR ls_dd04v IS INITIAL. lcx_exception=>raise( 'Error from DDIF_DTEL_GET' ). ENDIF. - IF ls_dd04v IS INITIAL. - RETURN. " does not exist - ENDIF. CLEAR: ls_dd04v-as4user, ls_dd04v-as4date, ls_dd04v-as4time. + IF ls_dd04v-refkind = 'D'. +* clear values inherited from domain + CLEAR: ls_dd04v-datatype, + ls_dd04v-leng, + ls_dd04v-decimals, + ls_dd04v-outputlen, + ls_dd04v-valexi, + ls_dd04v-lowercase, + ls_dd04v-signflag, + ls_dd04v-convexit, + ls_dd04v-entitytab. + ENDIF. + io_xml->add( iv_name = 'DD04V' ig_data = ls_dd04v ). io_xml->add( iv_name = 'TPARA' ig_data = ls_tpara ). + serialize_texts( io_xml ). + ENDMETHOD. "serialize METHOD lif_object~deserialize. @@ -149,8 +198,116 @@ CLASS lcl_object_dtel IMPLEMENTATION. lcx_exception=>raise( 'error from DDIF_DTEL_PUT' ). ENDIF. + deserialize_texts( io_xml = io_xml + is_dd04v = ls_dd04v ). + lcl_objects_activation=>add_item( ms_item ). ENDMETHOD. "deserialize + METHOD serialize_texts. + + DATA: lv_name TYPE ddobjname, + lv_index TYPE i, + ls_dd04v TYPE dd04v, + lt_dd04_texts TYPE tt_dd04_texts, + lt_i18n_langs TYPE TABLE OF langu. + + FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, + TYPE ty_dd04_texts. + + lv_name = ms_item-obj_name. + + " Collect additional languages + SELECT DISTINCT ddlanguage AS langu INTO TABLE lt_i18n_langs + FROM dd04v + WHERE rollname = lv_name + AND ddlanguage <> mv_language. " Skip master lang - it was serialized already + + LOOP AT lt_i18n_langs ASSIGNING . + lv_index = sy-tabix. + CALL FUNCTION 'DDIF_DTEL_GET' + EXPORTING + name = lv_name + langu = + IMPORTING + dd04v_wa = ls_dd04v +* tpara_wa = ls_tpara + EXCEPTIONS + illegal_input = 1 + OTHERS = 2. + IF sy-subrc <> 0 OR ls_dd04v-ddlanguage IS INITIAL. + DELETE lt_i18n_langs INDEX lv_index. " Don't save this lang + CONTINUE. + ENDIF. + + APPEND INITIAL LINE TO lt_dd04_texts ASSIGNING . + MOVE-CORRESPONDING ls_dd04v TO . + + ENDLOOP. + + SORT lt_i18n_langs ASCENDING. + SORT lt_dd04_texts BY ddlanguage ASCENDING. + + IF lines( lt_i18n_langs ) > 0. + io_xml->add( iv_name = 'I18N_LANGS' + ig_data = lt_i18n_langs ). + + io_xml->add( iv_name = 'DD04_TEXTS' + ig_data = lt_dd04_texts ). + ENDIF. + + ENDMETHOD. + + METHOD deserialize_texts. + + DATA: lv_name TYPE ddobjname, + ls_dd04v_tmp TYPE dd04v, + lt_i18n_langs TYPE TABLE OF langu, + lt_dd04_texts TYPE tt_dd04_texts. + FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, + TYPE ty_dd04_texts. + + lv_name = ms_item-obj_name. + + io_xml->read( EXPORTING iv_name = 'I18N_LANGS' + CHANGING cg_data = lt_i18n_langs ). + + io_xml->read( EXPORTING iv_name = 'DD04_TEXTS' + CHANGING cg_data = lt_dd04_texts ). + + SORT lt_i18n_langs. + SORT lt_dd04_texts BY ddlanguage. " Optimization + + LOOP AT lt_i18n_langs ASSIGNING . + + " Data element description + ls_dd04v_tmp = is_dd04v. + READ TABLE lt_dd04_texts ASSIGNING WITH KEY ddlanguage = . + IF sy-subrc > 0. + lcx_exception=>raise( |DD04_TEXTS cannot find lang { } in XML| ). + ENDIF. + MOVE-CORRESPONDING TO ls_dd04v_tmp. + CALL FUNCTION 'DDIF_DTEL_PUT' + EXPORTING + name = lv_name + dd04v_wa = ls_dd04v_tmp + EXCEPTIONS + dtel_not_found = 1 + name_inconsistent = 2 + dtel_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from DDIF_DTEL_PUT @TEXTS' ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_dtel IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_enho.prog.abap b/src/zabapgit_object_enho.prog.abap index d895fb6cd..95ba504f9 100644 --- a/src/zabapgit_object_enho.prog.abap +++ b/src/zabapgit_object_enho.prog.abap @@ -14,6 +14,13 @@ CLASS lcl_object_enho DEFINITION INHERITING FROM lcl_objects_super FINAL. ALIASES mo_files FOR lif_object~mo_files. PRIVATE SECTION. + TYPES: BEGIN OF ty_spaces, + full_name TYPE string. + TYPES: spaces TYPE STANDARD TABLE OF i WITH DEFAULT KEY, + END OF ty_spaces. + + TYPES: ty_spaces_tt TYPE STANDARD TABLE OF ty_spaces WITH DEFAULT KEY. + METHODS deserialize_badi IMPORTING io_xml TYPE REF TO lcl_xml_input iv_package TYPE devclass @@ -34,6 +41,15 @@ CLASS lcl_object_enho DEFINITION INHERITING FROM lcl_objects_super FINAL. ii_enh_tool TYPE REF TO if_enh_tool RAISING lcx_exception. + METHODS hook_impl_serialize + EXPORTING et_spaces TYPE ty_spaces_tt + CHANGING ct_impl TYPE enh_hook_impl_it + RAISING lcx_exception. + METHODS hook_impl_deserialize + IMPORTING it_spaces TYPE ty_spaces_tt + CHANGING ct_impl TYPE enh_hook_impl_it + RAISING lcx_exception. + ENDCLASS. "lcl_object_enho DEFINITION *----------------------------------------------------------------------* @@ -43,6 +59,10 @@ ENDCLASS. "lcl_object_enho DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_enho IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. "lif_object~get_metadata @@ -51,6 +71,53 @@ CLASS lcl_object_enho IMPLEMENTATION. rv_user = c_user_unknown. " todo ENDMETHOD. + METHOD hook_impl_serialize. +* handle normalization of XML values +* i.e. remove leading spaces + + FIELD-SYMBOLS: LIKE LINE OF ct_impl, + LIKE LINE OF et_spaces, + TYPE i, + TYPE string. + + + LOOP AT ct_impl ASSIGNING . + APPEND INITIAL LINE TO et_spaces ASSIGNING . + -full_name = -full_name. + LOOP AT -source ASSIGNING . + APPEND INITIAL LINE TO -spaces ASSIGNING . + WHILE strlen( ) >= 1 AND (1) = ` `. + = +1. + = + 1. + ENDWHILE. + ENDLOOP. + ENDLOOP. + ENDMETHOD. + + METHOD hook_impl_deserialize. + + FIELD-SYMBOLS: LIKE LINE OF ct_impl, + TYPE string, + TYPE i, + LIKE LINE OF it_spaces. + + + LOOP AT ct_impl ASSIGNING . + READ TABLE it_spaces ASSIGNING WITH KEY full_name = -full_name. + IF sy-subrc = 0. + LOOP AT -source ASSIGNING . + READ TABLE -spaces ASSIGNING INDEX sy-tabix. + IF sy-subrc = 0 AND > 0. + DO TIMES. + CONCATENATE space INTO RESPECTING BLANKS. + ENDDO. + ENDIF. + ENDLOOP. + ENDIF. + ENDLOOP. + + ENDMETHOD. + METHOD lif_object~exists. DATA: ls_tadir TYPE tadir. @@ -78,7 +145,9 @@ CLASS lcl_object_enho IMPLEMENTATION. lv_enh_id = ms_item-obj_name. TRY. - li_enh_tool = cl_enh_factory=>get_enhancement( lv_enh_id ). + li_enh_tool = cl_enh_factory=>get_enhancement( + enhancement_id = lv_enh_id + bypassing_buffer = abap_true ). CATCH cx_enh_root. lcx_exception=>raise( 'Error from CL_ENH_FACTORY' ). ENDTRY. @@ -100,7 +169,7 @@ CLASS lcl_object_enho IMPLEMENTATION. * WHEN cl_wdr_cfg_enhancement=>tooltype. * WHEN 'ENHWDYN'. "cl_enh_tool_wdy WHEN OTHERS. - lcx_exception=>raise( 'Unsupported ENHO type' ). + lcx_exception=>raise( |Unsupported ENHO type { lv_tool }| ). ENDCASE. ENDMETHOD. "serialize @@ -130,7 +199,7 @@ CLASS lcl_object_enho IMPLEMENTATION. * WHEN cl_wdr_cfg_enhancement=>tooltype. * WHEN 'ENHWDYN'. "cl_enh_tool_wdy WHEN OTHERS. - lcx_exception=>raise( 'Unsupported ENHO type' ). + lcx_exception=>raise( |Unsupported ENHO type { lv_tool }| ). ENDCASE. lcl_objects_activation=>add_item( ms_item ). @@ -192,6 +261,7 @@ CLASS lcl_object_enho IMPLEMENTATION. lv_enhname TYPE enhname, lv_package TYPE devclass, ls_original_object TYPE enh_hook_admin, + lt_spaces TYPE ty_spaces_tt, lt_enhancements TYPE enh_hook_impl_it. FIELD-SYMBOLS: LIKE LINE OF lt_enhancements. @@ -203,6 +273,11 @@ CLASS lcl_object_enho IMPLEMENTATION. CHANGING cg_data = ls_original_object ). io_xml->read( EXPORTING iv_name = 'ENHANCEMENTS' CHANGING cg_data = lt_enhancements ). + io_xml->read( EXPORTING iv_name = 'SPACES' + CHANGING cg_data = lt_spaces ). + + hook_impl_deserialize( EXPORTING it_spaces = lt_spaces + CHANGING ct_impl = lt_enhancements ). lv_enhname = ms_item-obj_name. lv_package = iv_package. @@ -275,6 +350,7 @@ CLASS lcl_object_enho IMPLEMENTATION. DATA: lv_shorttext TYPE string, lo_hook_impl TYPE REF TO cl_enh_tool_hook_impl, ls_original_object TYPE enh_hook_admin, + lt_spaces TYPE ty_spaces_tt, lt_enhancements TYPE enh_hook_impl_it. @@ -292,6 +368,10 @@ CLASS lcl_object_enho IMPLEMENTATION. ls_original_object-include_bound = lo_hook_impl->get_include_bound( ). lt_enhancements = lo_hook_impl->get_hook_impls( ). + hook_impl_serialize( + IMPORTING et_spaces = lt_spaces + CHANGING ct_impl = lt_enhancements ). + io_xml->add( iv_name = 'TOOL' ig_data = iv_tool ). io_xml->add( ig_data = lv_shorttext @@ -300,6 +380,8 @@ CLASS lcl_object_enho IMPLEMENTATION. iv_name = 'ORIGINAL_OBJECT' ). io_xml->add( iv_name = 'ENHANCEMENTS' ig_data = lt_enhancements ). + io_xml->add( iv_name = 'SPACES' + ig_data = lt_spaces ). ENDMETHOD. "serialize_hook @@ -334,4 +416,8 @@ CLASS lcl_object_enho IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_enho IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_enhs.prog.abap b/src/zabapgit_object_enhs.prog.abap index 10d60f91b..e3e021e3a 100644 --- a/src/zabapgit_object_enhs.prog.abap +++ b/src/zabapgit_object_enhs.prog.abap @@ -6,6 +6,7 @@ * CLASS lcl_object_enhs DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_enhs DEFINITION INHERITING FROM lcl_objects_super FINAL. + PUBLIC SECTION. INTERFACES lif_object. ALIASES mo_files FOR lif_object~mo_files. @@ -17,11 +18,29 @@ ENDCLASS. "lcl_object_enhs *----------------------------------------------------------------------* CLASS lcl_object_enhs IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. - rv_user = c_user_unknown. " todo + + DATA: lv_spot_name TYPE enhspotname, + li_spot_ref TYPE REF TO if_enh_spot_tool. + + + lv_spot_name = ms_item-obj_name. + + TRY. + li_spot_ref = cl_enh_factory=>get_enhancement_spot( lv_spot_name ). + li_spot_ref->get_attributes( IMPORTING changedby = rv_user ). + CATCH cx_enh_root. + rv_user = c_user_unknown. + ENDTRY. + ENDMETHOD. METHOD lif_object~deserialize. + DATA: lv_message TYPE string, lv_parent TYPE enhspotcompositename, lv_spot_name TYPE enhspotname, @@ -82,22 +101,24 @@ CLASS lcl_object_enhs IMPLEMENTATION. ENDMETHOD. "deserialize METHOD lif_object~serialize. - DATA: lv_message TYPE string, - lv_spot_name TYPE enhspotname, + + DATA: lv_spot_name TYPE enhspotname, lv_enh_shtext TYPE string, lv_parent TYPE enhspotcompositename, lt_enh_badi TYPE enh_badi_data_it, + lv_tool TYPE enhspottooltype, lx_root TYPE REF TO cx_root, li_spot_ref TYPE REF TO if_enh_spot_tool, lo_badidef_tool TYPE REF TO cl_enh_tool_badi_def. + lv_spot_name = ms_item-obj_name. TRY. li_spot_ref = cl_enh_factory=>get_enhancement_spot( lv_spot_name ). + lv_tool = li_spot_ref->get_tool( ). lo_badidef_tool ?= li_spot_ref. - lv_enh_shtext = lo_badidef_tool->if_enh_object_docu~get_shorttext( ). "get parent = composite enhs (ENHC) @@ -105,6 +126,8 @@ CLASS lcl_object_enhs IMPLEMENTATION. "get subsequent BADI definitions lt_enh_badi = lo_badidef_tool->get_badi_defs( ). + io_xml->add( ig_data = lv_tool + iv_name = 'TOOL' ). io_xml->add( ig_data = lv_parent iv_name = 'PARENT_COMP' ). io_xml->add( ig_data = lv_enh_shtext @@ -113,9 +136,8 @@ CLASS lcl_object_enhs IMPLEMENTATION. iv_name = 'BADI_DATA' ). CATCH cx_enh_root INTO lx_root. - lv_message = `Error occured while serializing EHNS: ` - && lx_root->get_text( ) ##NO_TEXT. - lcx_exception=>raise( lv_message ). + lcx_exception=>raise( `Error occured while serializing EHNS: ` + && lx_root->get_text( ) ) ##NO_TEXT. ENDTRY. ENDMETHOD. "serialize @@ -123,6 +145,7 @@ CLASS lcl_object_enhs IMPLEMENTATION. METHOD lif_object~exists. DATA: lv_spot_name TYPE enhspotname, + lv_tool TYPE enhspottooltype, li_spot_ref TYPE REF TO if_enh_spot_tool. @@ -131,12 +154,14 @@ CLASS lcl_object_enhs IMPLEMENTATION. TRY. li_spot_ref = cl_enh_factory=>get_enhancement_spot( lv_spot_name ). -* Check that is is realy a BAdI - IF li_spot_ref->get_tool( ) = cl_enh_tool_badi_def=>tooltype. - rv_bool = abap_true. - ELSE. - rv_bool = abap_false. - ENDIF. + lv_tool = li_spot_ref->get_tool( ). + CASE lv_tool. + WHEN cl_enh_tool_badi_def=>tooltype. + rv_bool = abap_true. + WHEN OTHERS. +* todo: implement additional tool types + rv_bool = abap_false. + ENDCASE. CATCH cx_enh_root. rv_bool = abap_false. ENDTRY. @@ -144,8 +169,8 @@ CLASS lcl_object_enhs IMPLEMENTATION. ENDMETHOD. "exists METHOD lif_object~delete. + DATA: lv_spot_name TYPE enhspotname, - lv_message TYPE string, lx_root TYPE REF TO cx_root, li_spot_ref TYPE REF TO if_enh_spot_tool, lo_badidef_tool TYPE REF TO cl_enh_tool_badi_def. @@ -155,19 +180,18 @@ CLASS lcl_object_enhs IMPLEMENTATION. TRY. li_spot_ref = cl_enh_factory=>get_enhancement_spot( spot_name = lv_spot_name - lock = 'X' ). + lock = abap_true ). IF li_spot_ref IS BOUND. lo_badidef_tool ?= li_spot_ref. lo_badidef_tool->if_enh_object~delete( - nevertheless_delete = 'X' - run_dark = 'X' ). + nevertheless_delete = abap_true + run_dark = abap_true ). ENDIF. lo_badidef_tool->if_enh_object~unlock( ). CATCH cx_enh_root INTO lx_root. - lv_message = `Error occured while deleting EHNS: ` - && lx_root->get_text( ) ##NO_TEXT. - lcx_exception=>raise( lv_message ). + lcx_exception=>raise( `Error occured while deleting EHNS: ` + && lx_root->get_text( ) ) ##NO_TEXT. ENDTRY. ENDMETHOD. "delete @@ -187,4 +211,8 @@ CLASS lcl_object_enhs IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_enhs \ No newline at end of file diff --git a/src/zabapgit_object_enqu.prog.abap b/src/zabapgit_object_enqu.prog.abap index 1177b01fc..53d08681f 100644 --- a/src/zabapgit_object_enqu.prog.abap +++ b/src/zabapgit_object_enqu.prog.abap @@ -22,8 +22,33 @@ ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_enqu IMPLEMENTATION. + METHOD lif_object~has_changed_since. + + DATA: lv_date TYPE dats, + lv_time TYPE tims, + lv_ts TYPE timestamp. + + SELECT SINGLE as4date as4time FROM dd25l + INTO (lv_date, lv_time) + WHERE viewname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + + _object_check_timestamp lv_date lv_time. + + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. - rv_user = c_user_unknown. " todo + + SELECT SINGLE AS4USER FROM dd25l + INTO rv_user + WHERE viewname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. METHOD lif_object~get_metadata. @@ -157,4 +182,8 @@ CLASS lcl_object_enqu IMPLEMENTATION. ENDMETHOD. "deserialize + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_enqu IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_ensc.prog.abap b/src/zabapgit_object_ensc.prog.abap index 2379dd1f6..cc29f012f 100644 --- a/src/zabapgit_object_ensc.prog.abap +++ b/src/zabapgit_object_ensc.prog.abap @@ -14,6 +14,10 @@ ENDCLASS. "lcl_object_ensc *----------------------------------------------------------------------* CLASS lcl_object_ensc IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -86,7 +90,6 @@ CLASS lcl_object_ensc IMPLEMENTATION. DATA: lv_spot_name TYPE enhspotcompositename, lv_message TYPE string, lv_enh_shtext TYPE string, - lv_parent TYPE enhspotcompositename, lt_enh_spots TYPE enhspotname_it, lt_comp_spots TYPE enhspotname_it, lx_root TYPE REF TO cx_root, @@ -105,7 +108,7 @@ CLASS lcl_object_ensc IMPLEMENTATION. lv_enh_shtext = li_spot_ref->if_enh_object_docu~get_shorttext( ). "find parent = composite enhancement (ENSC) - lv_parent = cl_r3standard_persistence=>enh_find_parent_composite( lv_spot_name ). +* lv_parent = cl_r3standard_persistence=>enh_find_parent_composite( lv_spot_name ). "find subsequent enhancement spots lt_enh_spots = lo_spot_ref->if_enh_spot_composite~get_enh_spot_childs( ). "find subsequent composite enhancement spots @@ -187,4 +190,8 @@ CLASS lcl_object_ensc IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_ensc \ No newline at end of file diff --git a/src/zabapgit_object_fugr.prog.abap b/src/zabapgit_object_fugr.prog.abap new file mode 100644 index 000000000..97aaf4f86 --- /dev/null +++ b/src/zabapgit_object_fugr.prog.abap @@ -0,0 +1,726 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_OBJECT_FUGR +*&---------------------------------------------------------------------* + +*----------------------------------------------------------------------* +* CLASS lcl_object_fugr DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_object_fugr DEFINITION INHERITING FROM lcl_objects_program FINAL. + + PUBLIC SECTION. + INTERFACES lif_object. + ALIASES mo_files FOR lif_object~mo_files. + + PRIVATE SECTION. + TYPES: ty_rs38l_incl_tt TYPE STANDARD TABLE OF rs38l_incl WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_function, + funcname TYPE rs38l_fnam, + include TYPE progname, + global_flag TYPE rs38l-global, + remote_call TYPE rs38l-remote, + update_task TYPE rs38l-utask, + short_text TYPE tftit-stext, + remote_basxml TYPE rs38l-basxml_enabled, + import TYPE STANDARD TABLE OF rsimp WITH DEFAULT KEY, + changing TYPE STANDARD TABLE OF rscha WITH DEFAULT KEY, + export TYPE STANDARD TABLE OF rsexp WITH DEFAULT KEY, + tables TYPE STANDARD TABLE OF rstbl WITH DEFAULT KEY, + exception TYPE STANDARD TABLE OF rsexc WITH DEFAULT KEY, + documentation TYPE STANDARD TABLE OF rsfdo WITH DEFAULT KEY, + END OF ty_function. + + TYPES: ty_function_tt TYPE STANDARD TABLE OF ty_function WITH DEFAULT KEY. + + METHODS main_name + RETURNING VALUE(rv_program) TYPE program + RAISING lcx_exception. + + METHODS functions + RETURNING VALUE(rt_functab) TYPE ty_rs38l_incl_tt + RAISING lcx_exception. + + METHODS includes + RETURNING VALUE(rt_includes) TYPE rso_t_objnm + RAISING lcx_exception. + + METHODS serialize_functions + RETURNING VALUE(rt_functions) TYPE ty_function_tt + RAISING lcx_exception. + + METHODS deserialize_functions + IMPORTING it_functions TYPE ty_function_tt + RAISING lcx_exception. + + METHODS serialize_xml + IMPORTING io_xml TYPE REF TO lcl_xml_output + RAISING lcx_exception. + + METHODS deserialize_xml + IMPORTING io_xml TYPE REF TO lcl_xml_input + iv_package TYPE devclass + RAISING lcx_exception. + + METHODS serialize_includes + RAISING lcx_exception. + + METHODS deserialize_includes + IMPORTING io_xml TYPE REF TO lcl_xml_input + iv_package TYPE devclass + RAISING lcx_exception. + +ENDCLASS. "lcl_object_fugr DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_object_dtel IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_object_fugr IMPLEMENTATION. + +* function group SEUF +* function group SIFP +* function group SUNI + + METHOD lif_object~has_changed_since. + + DATA: lt_functab TYPE ty_rs38l_incl_tt, + lt_includes TYPE rso_t_objnm. + + FIELD-SYMBOLS: LIKE LINE OF lt_functab, + LIKE LINE OF lt_includes. + + lt_includes = includes( ). " Main prog also included here + + LOOP AT lt_includes ASSIGNING . + rv_changed = check_prog_changed_since( + iv_program = + iv_timestamp = iv_timestamp ). + IF rv_changed = abap_true. + RETURN. + ENDIF. + ENDLOOP. + + lt_functab = functions( ). + + LOOP AT lt_functab ASSIGNING . + rv_changed = check_prog_changed_since( + iv_program = -include + iv_timestamp = iv_timestamp ). + IF rv_changed = abap_true. + RETURN. + ENDIF. + ENDLOOP. + + ENDMETHOD. "lif_object~has_changed_since + + METHOD lif_object~changed_by. + + TYPES: BEGIN OF ty_stamps, + user TYPE xubname, + date TYPE d, + time TYPE t, + END OF ty_stamps. + + DATA: lt_stamps TYPE STANDARD TABLE OF ty_stamps WITH DEFAULT KEY, + lv_program TYPE program, + lt_includes TYPE rso_t_objnm. + + FIELD-SYMBOLS: LIKE LINE OF lt_stamps, + LIKE LINE OF lt_includes. + + + lv_program = main_name( ). + + CALL FUNCTION 'RS_GET_ALL_INCLUDES' + EXPORTING + program = lv_program + TABLES + includetab = lt_includes + EXCEPTIONS + not_existent = 1 + no_program = 2 + OTHERS = 3. + IF sy-subrc <> 0. + lcx_exception=>raise( 'Error from RS_GET_ALL_INCLUDES' ). + ENDIF. + + SELECT unam AS user udat AS date utime AS time FROM reposrc + APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps + WHERE progname = lv_program + AND r3state = 'A'. + + LOOP AT lt_includes ASSIGNING . + SELECT unam AS user udat AS date utime AS time FROM reposrc + APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps + WHERE progname = + AND r3state = 'A'. + ENDLOOP. + + SELECT unam AS user udat AS date utime AS time FROM repotext " Program text pool + APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps + WHERE progname = lv_program + AND r3state = 'A'. + + SELECT vautor AS user vdatum AS date vzeit AS time FROM eudb " GUI + APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps + WHERE relid = 'CU' + AND name = lv_program + AND srtf2 = 0 ##TOO_MANY_ITAB_FIELDS. + +* Screens: username not stored in D020S database table + + SORT lt_stamps BY date DESCENDING time DESCENDING. + + READ TABLE lt_stamps INDEX 1 ASSIGNING . + IF sy-subrc = 0. + rv_user = -user. + ELSE. + rv_user = c_user_unknown. + ENDIF. + + ENDMETHOD. + + METHOD lif_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. "lif_object~get_metadata + + METHOD lif_object~exists. + + DATA: lv_pool TYPE tlibg-area. + + + lv_pool = ms_item-obj_name. + CALL FUNCTION 'RS_FUNCTION_POOL_EXISTS' + EXPORTING + function_pool = lv_pool + EXCEPTIONS + pool_not_exists = 1. + rv_bool = boolc( sy-subrc <> 1 ). + + ENDMETHOD. "lif_object~exists + + METHOD deserialize_functions. + + DATA: lv_include TYPE rs38l-include, + lv_area TYPE rs38l-area, + lt_source TYPE TABLE OF abaptxt255. + + FIELD-SYMBOLS: LIKE LINE OF it_functions. + + + LOOP AT it_functions ASSIGNING . + + lt_source = mo_files->read_abap( iv_extra = -funcname ). + + lv_area = ms_item-obj_name. + + CALL FUNCTION 'FUNCTION_EXISTS' + EXPORTING + funcname = -funcname + IMPORTING + include = lv_include + EXCEPTIONS + function_not_exist = 1. + IF sy-subrc = 0. +* delete the function module to make sure the parameters are updated +* havent found a nice way to update the paramters + CALL FUNCTION 'FUNCTION_DELETE' + EXPORTING + funcname = -funcname + suppress_success_message = abap_true + EXCEPTIONS + error_message = 1 + OTHERS = 2. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from FUNCTION_DELETE' ). + ENDIF. + ENDIF. + + CALL FUNCTION 'RS_FUNCTIONMODULE_INSERT' + EXPORTING + funcname = -funcname + function_pool = lv_area + interface_global = -global_flag + remote_call = -remote_call + short_text = -short_text + update_task = -update_task +* NAMESPACE = ' ' todo + remote_basxml_supported = -remote_basxml + IMPORTING + function_include = lv_include + TABLES + import_parameter = -import + export_parameter = -export + tables_parameter = -tables + changing_parameter = -changing + exception_list = -exception + parameter_docu = -documentation + EXCEPTIONS + double_task = 1 + error_message = 2 + function_already_exists = 3 + invalid_function_pool = 4 + invalid_name = 5 + too_many_functions = 6 + no_modify_permission = 7 + no_show_permission = 8 + enqueue_system_failure = 9 + canceled_in_corr = 10 + OTHERS = 11. + IF sy-subrc <> 0. + lcx_exception=>raise( |error from RS_FUNCTIONMODULE_INSERT: { + sy-subrc } { sy-msgid }{ sy-msgno }| ). + ENDIF. + + INSERT REPORT lv_include FROM lt_source. + +* lcl_objects_activation=>add( iv_type = 'FUNC' +* iv_name = -funcname ). + + ENDLOOP. + + ENDMETHOD. "deserialize_functions + + METHOD deserialize_includes. + + DATA: lo_xml TYPE REF TO lcl_xml_input, + ls_progdir TYPE ty_progdir, + lt_includes TYPE rso_t_objnm, + lt_tpool TYPE textpool_table, + lt_tpool_ext TYPE ty_tpool_tt, + lt_source TYPE TABLE OF abaptxt255. + + FIELD-SYMBOLS: LIKE LINE OF lt_includes. + + + io_xml->read( EXPORTING iv_name = 'INCLUDES' + CHANGING cg_data = lt_includes ). + + LOOP AT lt_includes ASSIGNING . + + lt_source = mo_files->read_abap( iv_extra = ). + + lo_xml = mo_files->read_xml( ). + + lo_xml->read( EXPORTING iv_name = 'PROGDIR' + CHANGING cg_data = ls_progdir ). + + lo_xml->read( EXPORTING iv_name = 'TPOOL' + CHANGING cg_data = lt_tpool_ext ). + lt_tpool = read_tpool( lt_tpool_ext ). + + deserialize_program( is_progdir = ls_progdir + it_source = lt_source + it_tpool = lt_tpool + iv_package = iv_package ). + + ENDLOOP. + + ENDMETHOD. "deserialize_includes + + METHOD deserialize_xml. + + DATA: lv_complete TYPE rs38l-area, + lv_namespace TYPE rs38l-namespace, + lv_areat TYPE tlibt-areat, + lv_stext TYPE tftit-stext, + lv_group TYPE rs38l-area. + + + lv_complete = ms_item-obj_name. + + CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' + EXPORTING + complete_area = lv_complete + IMPORTING + namespace = lv_namespace + group = lv_group + EXCEPTIONS + include_not_exists = 1 + group_not_exists = 2 + no_selections = 3 + no_function_include = 4 + no_function_pool = 5 + delimiter_wrong_position = 6 + no_customer_function_group = 7 + no_customer_function_include = 8 + reserved_name_customer = 9 + namespace_too_long = 10 + area_length_error = 11 + OTHERS = 12. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from FUNCTION_INCLUDE_SPLIT' ). + ENDIF. + + io_xml->read( EXPORTING iv_name = 'AREAT' + CHANGING cg_data = lv_areat ). + lv_stext = lv_areat. + + CALL FUNCTION 'RS_FUNCTION_POOL_INSERT' + EXPORTING + function_pool = lv_group + short_text = lv_stext + namespace = lv_namespace + devclass = iv_package + EXCEPTIONS + name_already_exists = 1 + name_not_correct = 2 + function_already_exists = 3 + invalid_function_pool = 4 + invalid_name = 5 + too_many_functions = 6 + no_modify_permission = 7 + no_show_permission = 8 + enqueue_system_failure = 9 + canceled_in_corr = 10 + undefined_error = 11 + OTHERS = 12. + IF sy-subrc <> 0 AND sy-subrc <> 1 AND sy-subrc <> 3. +* todo, change description + lcx_exception=>raise( 'error from RS_FUNCTION_POOL_INSERT' ). + ENDIF. + + ENDMETHOD. "deserialize_xml + + METHOD serialize_xml. + + DATA: lt_functab TYPE ty_rs38l_incl_tt, + lt_includes TYPE rso_t_objnm, + lv_areat TYPE tlibt-areat. + + + SELECT SINGLE areat INTO lv_areat + FROM tlibt + WHERE spras = mv_language + AND area = ms_item-obj_name. "#EC CI_GENBUFF + IF sy-subrc <> 0. + lcx_exception=>raise( 'not found in TLIBT' ). + ENDIF. + + lt_functab = functions( ). + lt_includes = includes( ). + + io_xml->add( iv_name = 'AREAT' + ig_data = lv_areat ). + io_xml->add( iv_name = 'INCLUDES' + ig_data = lt_includes ). + + ENDMETHOD. "serialize_xml + + METHOD includes. + + DATA: lv_program TYPE program, + lv_cnam TYPE reposrc-cnam, + lv_tabix LIKE sy-tabix, + lt_functab TYPE ty_rs38l_incl_tt. + + FIELD-SYMBOLS: LIKE LINE OF rt_includes, + LIKE LINE OF lt_functab. + + + lv_program = main_name( ). + lt_functab = functions( ). + + CALL FUNCTION 'RS_GET_ALL_INCLUDES' + EXPORTING + program = lv_program +* WITH_RESERVED_INCLUDES = +* WITH_CLASS_INCLUDES = ' ' hmm, todo + TABLES + includetab = rt_includes + EXCEPTIONS + not_existent = 1 + no_program = 2 + OTHERS = 3. + IF sy-subrc <> 0. + lcx_exception=>raise( 'Error from RS_GET_ALL_INCLUDES' ). + ENDIF. + + LOOP AT lt_functab ASSIGNING . + DELETE TABLE rt_includes FROM -include. + ENDLOOP. + + + LOOP AT rt_includes ASSIGNING . + lv_tabix = sy-tabix. + +* skip SAP standard includes + SELECT SINGLE cnam FROM reposrc INTO lv_cnam + WHERE progname = + AND r3state = 'A' + AND cnam = 'SAP'. + IF sy-subrc = 0. + DELETE rt_includes INDEX lv_tabix. + CONTINUE. + ENDIF. + +* also make sure the include exists + SELECT SINGLE cnam FROM reposrc INTO lv_cnam + WHERE progname = + AND r3state = 'A'. + IF sy-subrc <> 0. + DELETE rt_includes INDEX lv_tabix. + ENDIF. + + ENDLOOP. + + APPEND lv_program TO rt_includes. + + ENDMETHOD. "includes + + METHOD functions. + + DATA: lv_area TYPE rs38l-area. + + + lv_area = ms_item-obj_name. + + CALL FUNCTION 'RS_FUNCTION_POOL_CONTENTS' + EXPORTING + function_pool = lv_area + TABLES + functab = rt_functab + EXCEPTIONS + function_pool_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0. + lcx_exception=>raise( 'Error from RS_FUNCTION_POOL_CONTENTS' ). + ENDIF. + + ENDMETHOD. "functions + + METHOD main_name. + + DATA: lv_area TYPE rs38l-area, + lv_namespace TYPE rs38l-namespace, + lv_group TYPE rs38l-area. + + + lv_area = ms_item-obj_name. + + CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' + EXPORTING + complete_area = lv_area + IMPORTING + namespace = lv_namespace + group = lv_group + EXCEPTIONS + include_not_exists = 1 + group_not_exists = 2 + no_selections = 3 + no_function_include = 4 + no_function_pool = 5 + delimiter_wrong_position = 6 + no_customer_function_group = 7 + no_customer_function_include = 8 + reserved_name_customer = 9 + namespace_too_long = 10 + area_length_error = 11 + OTHERS = 12. + IF sy-subrc <> 0. + lcx_exception=>raise( 'Error from FUNCTION_INCLUDE_SPLIT' ). + ENDIF. + + CONCATENATE lv_namespace 'SAPL' lv_group INTO rv_program. + + ENDMETHOD. "main_name + + METHOD serialize_functions. + + DATA: + lt_source TYPE TABLE OF rssource, + lt_functab TYPE ty_rs38l_incl_tt, + lt_new_source TYPE rsfb_source. + + FIELD-SYMBOLS: LIKE LINE OF lt_functab, + LIKE LINE OF rt_functions. + + + lt_functab = functions( ). + + LOOP AT lt_functab ASSIGNING . +* fm RPY_FUNCTIONMODULE_READ does not support source code +* lines longer than 72 characters + APPEND INITIAL LINE TO rt_functions ASSIGNING . + MOVE-CORRESPONDING TO . + + CLEAR lt_new_source. + CLEAR lt_source. + + CALL FUNCTION 'RPY_FUNCTIONMODULE_READ_NEW' + EXPORTING + functionname = -funcname + IMPORTING + global_flag = -global_flag + remote_call = -remote_call + update_task = -update_task + short_text = -short_text + remote_basxml_supported = -remote_basxml + TABLES + import_parameter = -import + changing_parameter = -changing + export_parameter = -export + tables_parameter = -tables + exception_list = -exception + documentation = -documentation + source = lt_source + CHANGING + new_source = lt_new_source + EXCEPTIONS + error_message = 1 + function_not_found = 2 + invalid_name = 3 + OTHERS = 4. + IF sy-subrc <> 0. + lcx_exception=>raise( 'Error from RPY_FUNCTIONMODULE_READ_NEW' ). + ENDIF. + + IF NOT lt_new_source IS INITIAL. + mo_files->add_abap( iv_extra = -funcname + it_abap = lt_new_source ). + ELSE. + mo_files->add_abap( iv_extra = -funcname + it_abap = lt_source ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. "serialize_functions + + METHOD serialize_includes. + + DATA: lt_includes TYPE rso_t_objnm. + + FIELD-SYMBOLS: LIKE LINE OF lt_includes. + + + lt_includes = includes( ). + + LOOP AT lt_includes ASSIGNING . + +* todo, filename is not correct, a include can be used in several programs + serialize_program( is_item = ms_item + io_files = mo_files + iv_program = + iv_extra = ). + + ENDLOOP. + + ENDMETHOD. "serialize_includes + + METHOD lif_object~serialize. + + DATA: lt_functions TYPE ty_function_tt, + ls_progdir TYPE ty_progdir, + lv_program_name TYPE programm, + lt_dynpros TYPE ty_dynpro_tt, + ls_cua TYPE ty_cua. + + IF lif_object~exists( ) = abap_false. + RETURN. + ENDIF. + + serialize_xml( io_xml ). + + lt_functions = serialize_functions( ). + io_xml->add( iv_name = 'FUNCTIONS' + ig_data = lt_functions ). + + serialize_includes( ). + + lv_program_name = main_name( ). + ls_progdir = read_progdir( lv_program_name ). + + IF ls_progdir-subc = 'F'. + lt_dynpros = serialize_dynpros( lv_program_name ). + io_xml->add( iv_name = 'DYNPROS' + ig_data = lt_dynpros ). + + ls_cua = serialize_cua( lv_program_name ). + io_xml->add( iv_name = 'CUA' + ig_data = ls_cua ). + ENDIF. + + ENDMETHOD. "serialize + + METHOD lif_object~deserialize. + + DATA: lv_program_name TYPE programm, + lt_functions TYPE ty_function_tt, + lt_dynpros TYPE ty_dynpro_tt, + ls_cua TYPE ty_cua. + + + deserialize_xml( + io_xml = io_xml + iv_package = iv_package ). + + io_xml->read( EXPORTING iv_name = 'FUNCTIONS' + CHANGING cg_data = lt_functions ). + deserialize_functions( lt_functions ). + + deserialize_includes( + io_xml = io_xml + iv_package = iv_package ). + + lv_program_name = main_name( ). + + io_xml->read( EXPORTING iv_name = 'DYNPROS' + CHANGING cg_data = lt_dynpros ). + deserialize_dynpros( it_dynpros = lt_dynpros ). + + io_xml->read( EXPORTING iv_name = 'CUA' + CHANGING cg_data = ls_cua ). + deserialize_cua( iv_program_name = lv_program_name + is_cua = ls_cua ). + + ENDMETHOD. "deserialize + + METHOD lif_object~delete. + + DATA: lv_area TYPE rs38l-area. + + + lv_area = ms_item-obj_name. + + CALL FUNCTION 'RS_FUNCTION_POOL_DELETE' + EXPORTING + area = lv_area + suppress_popups = abap_true + skip_progress_ind = abap_true + EXCEPTIONS + canceled_in_corr = 1 + enqueue_system_failure = 2 + function_exist = 3 + not_executed = 4 + no_modify_permission = 5 + no_show_permission = 6 + permission_failure = 7 + pool_not_exist = 8 + cancelled = 9 + OTHERS = 10. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from RS_FUNCTION_POOL_DELETE' ). + ENDIF. + + ENDMETHOD. "delete + + METHOD lif_object~jump. + + CALL FUNCTION 'RS_TOOL_ACCESS' + EXPORTING + operation = 'SHOW' + object_name = ms_item-obj_name + object_type = 'FUGR' + in_new_window = abap_true. + + ENDMETHOD. "jump + + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + +ENDCLASS. "lcl_object_fugr IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_fugr.prog.xml b/src/zabapgit_object_fugr.prog.xml new file mode 100644 index 000000000..1d911fdc1 --- /dev/null +++ b/src/zabapgit_object_fugr.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_OBJECT_FUGR + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_OBJECT_FUGR + 28 + + + + + + diff --git a/src/zabapgit_object_iarp.prog.abap b/src/zabapgit_object_iarp.prog.abap index 356326b09..9d6fb5bed 100644 --- a/src/zabapgit_object_iarp.prog.abap +++ b/src/zabapgit_object_iarp.prog.abap @@ -33,6 +33,10 @@ ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_iarp IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -184,4 +188,8 @@ CLASS lcl_object_iarp IMPLEMENTATION. lcx_exception=>raise( 'todo, IARP, jump' ). ENDMETHOD. "lif_object~jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_iarp IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_iasp.prog.abap b/src/zabapgit_object_iasp.prog.abap index add9d0522..30ee4e5f7 100644 --- a/src/zabapgit_object_iasp.prog.abap +++ b/src/zabapgit_object_iasp.prog.abap @@ -33,6 +33,10 @@ ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_iasp IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -184,4 +188,8 @@ CLASS lcl_object_iasp IMPLEMENTATION. lcx_exception=>raise( 'todo, IASP, jump' ). ENDMETHOD. "lif_object~jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_iasp IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_iatu.prog.abap b/src/zabapgit_object_iatu.prog.abap index 9cddad81e..2373edf40 100644 --- a/src/zabapgit_object_iatu.prog.abap +++ b/src/zabapgit_object_iatu.prog.abap @@ -33,6 +33,10 @@ ENDCLASS. "lcl_object_iatu DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_iatu IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -201,4 +205,8 @@ CLASS lcl_object_iatu IMPLEMENTATION. lcx_exception=>raise( 'todo, IATU, jump' ). ENDMETHOD. "lif_object~jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_iatu IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_msag.prog.abap b/src/zabapgit_object_msag.prog.abap index 0206b22fe..bfb8d2837 100644 --- a/src/zabapgit_object_msag.prog.abap +++ b/src/zabapgit_object_msag.prog.abap @@ -13,6 +13,23 @@ CLASS lcl_object_msag DEFINITION INHERITING FROM lcl_objects_super FINAL. INTERFACES lif_object. ALIASES mo_files FOR lif_object~mo_files. + PRIVATE SECTION. + TYPES: BEGIN OF ty_t100_texts, + sprsl TYPE t100-sprsl, + msgnr TYPE t100-msgnr, + text TYPE t100-text, + END OF ty_t100_texts, + tt_t100_texts TYPE STANDARD TABLE OF ty_t100_texts. + + METHODS: + serialize_texts + IMPORTING io_xml TYPE REF TO lcl_xml_output + RAISING lcx_exception, + deserialize_texts + IMPORTING io_xml TYPE REF TO lcl_xml_input + RAISING lcx_exception. + + ENDCLASS. "lcl_object_msag DEFINITION *----------------------------------------------------------------------* @@ -22,6 +39,10 @@ ENDCLASS. "lcl_object_msag DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_msag IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE lastuser FROM t100a INTO rv_user @@ -78,10 +99,11 @@ CLASS lcl_object_msag IMPLEMENTATION. METHOD lif_object~deserialize. * fm RPY_MESSAGE_ID_INSERT almost works, but not in older versions - DATA: ls_t100a TYPE t100a, - ls_t100t TYPE t100t, - ls_t100u TYPE t100u, - lt_t100 TYPE TABLE OF t100. + DATA: ls_t100a TYPE t100a, + ls_t100t TYPE t100t, + ls_t100u TYPE t100u, + lt_t100 TYPE TABLE OF t100, + lt_before TYPE TABLE OF t100u. FIELD-SYMBOLS: LIKE LINE OF lt_t100. @@ -106,17 +128,24 @@ CLASS lcl_object_msag IMPLEMENTATION. lcx_exception=>raise( 'Error from RS_CORR_INSERT' ). ENDIF. - LOOP AT lt_t100 ASSIGNING . - MODIFY t100 FROM . "#EC CI_SUBRC - ASSERT sy-subrc = 0. + SELECT * FROM t100u INTO TABLE lt_before + WHERE arbgb = ls_t100a-arbgb ORDER BY msgnr. "#EC CI_GENBUFF "#EC CI_BYPASS + LOOP AT lt_t100 ASSIGNING . + DELETE lt_before WHERE msgnr = -msgnr. + MODIFY t100 FROM . "#EC CI_SUBRC + IF sy-subrc <> 0. + lcx_exception=>raise( 'MSAG: Table T100 modify failed' ). + ENDIF. CLEAR ls_t100u. MOVE-CORRESPONDING TO ls_t100u ##enh_ok. ls_t100u-name = sy-uname. ls_t100u-datum = sy-datum. ls_t100u-selfdef = '3'. MODIFY t100u FROM ls_t100u. "#EC CI_SUBRC - ASSERT sy-subrc = 0. + IF sy-subrc <> 0. + lcx_exception=>raise( 'MSAG: Table T100U modify failed' ). + ENDIF. ENDLOOP. ls_t100a-masterlang = mv_language. @@ -125,13 +154,25 @@ CLASS lcl_object_msag IMPLEMENTATION. ls_t100a-ldate = sy-datum. ls_t100a-ltime = sy-uzeit. MODIFY t100a FROM ls_t100a. "#EC CI_SUBRC - ASSERT sy-subrc = 0. + IF sy-subrc <> 0. + lcx_exception=>raise( 'MSAG: Table T100A modify failed' ). + ENDIF. ls_t100t-sprsl = mv_language. ls_t100t-arbgb = ls_t100a-arbgb. ls_t100t-stext = ls_t100a-stext. MODIFY t100t FROM ls_t100t. "#EC CI_SUBRC - ASSERT sy-subrc = 0. + IF sy-subrc <> 0. + lcx_exception=>raise( 'MSAG: Table T100T modify failed' ). + ENDIF. + + LOOP AT lt_before INTO ls_t100u. + DELETE FROM t100 WHERE arbgb = ls_t100u-arbgb AND msgnr = ls_t100u-msgnr. + DELETE FROM t100u WHERE arbgb = ls_t100u-arbgb AND msgnr = ls_t100u-msgnr. + ENDLOOP. + + deserialize_texts( io_xml = io_xml ). + ENDMETHOD. "deserialize @@ -154,7 +195,7 @@ CLASS lcl_object_msag IMPLEMENTATION. SELECT * FROM t100 INTO TABLE lt_source WHERE sprsl = mv_language AND arbgb = lv_msg_id - ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF + ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF CLEAR: ls_inf-lastuser, ls_inf-ldate, @@ -165,6 +206,98 @@ CLASS lcl_object_msag IMPLEMENTATION. io_xml->add( ig_data = lt_source iv_name = 'T100' ). + serialize_texts( io_xml ). + ENDMETHOD. "serialize + METHOD serialize_texts. + + DATA: lv_msg_id TYPE rglif-message_id, + lt_t100_texts TYPE tt_t100_texts, + lt_t100t TYPE table of t100t, + lt_i18n_langs TYPE TABLE OF langu. + + lv_msg_id = ms_item-obj_name. + + " Collect additional languages + " Skip master lang - it has been already serialized + SELECT DISTINCT sprsl AS langu INTO TABLE lt_i18n_langs + FROM t100t + WHERE arbgb = lv_msg_id + AND sprsl <> mv_language. "#EC CI_BYPASS "#EC CI_GENBUFF. + + SORT lt_i18n_langs ASCENDING. + + IF LINES( lt_i18n_langs ) > 0. + + SELECT * FROM t100t INTO CORRESPONDING FIELDS OF TABLE lt_t100t + WHERE sprsl <> mv_language + AND arbgb = lv_msg_id. "#EC CI_GENBUFF + + SELECT * FROM t100 INTO CORRESPONDING FIELDS OF TABLE lt_t100_texts + FOR ALL ENTRIES IN lt_i18n_langs + WHERE sprsl = lt_i18n_langs-table_line + AND arbgb = lv_msg_id + ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF + + SORT lt_t100t BY sprsl ASCENDING. + SORT lt_t100_texts BY sprsl msgnr ASCENDING. + + io_xml->add( iv_name = 'I18N_LANGS' + ig_data = lt_i18n_langs ). + + io_xml->add( iv_name = 'T100T' + ig_data = lt_t100t ). + + io_xml->add( iv_name = 'T100_TEXTS' + ig_data = lt_t100_texts ). + + ENDIF. + + ENDMETHOD. + + METHOD deserialize_texts. + + DATA: lv_msg_id TYPE rglif-message_id, + ls_t100 TYPE t100, + lt_t100t TYPE table of t100t, + lt_t100_texts TYPE tt_t100_texts, + lt_t100u TYPE TABLE OF t100u. + + FIELD-SYMBOLS: TYPE ty_t100_texts. + + + lv_msg_id = ms_item-obj_name. + + SELECT * FROM t100u INTO TABLE lt_t100u + WHERE arbgb = lv_msg_id ORDER BY PRIMARY KEY. "#EC CI_GENBUFF + + io_xml->read( EXPORTING iv_name = 'T100_TEXTS' + CHANGING cg_data = lt_t100_texts ). + + io_xml->read( EXPORTING iv_name = 'T100T' + CHANGING cg_data = lt_t100t ). + + MODIFY t100t FROM TABLE lt_t100t. "#EC CI_SUBRC + + LOOP AT lt_t100_texts ASSIGNING . + "check if message exists + READ TABLE lt_t100u TRANSPORTING NO FIELDS + WITH KEY arbgb = lv_msg_id msgnr = -msgnr BINARY SEARCH. + CHECK sy-subrc = 0. "if original message doesn't exist no translations added + + MOVE-CORRESPONDING TO ls_t100. + ls_t100-arbgb = lv_msg_id. + MODIFY t100 FROM ls_t100. "#EC CI_SUBRC + IF sy-subrc <> 0. + lcx_exception=>raise( 'MSAG: Table T100 modify failed' ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_msag IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_nrob.prog.abap b/src/zabapgit_object_nrob.prog.abap index e3934a7ff..47edb4254 100644 --- a/src/zabapgit_object_nrob.prog.abap +++ b/src/zabapgit_object_nrob.prog.abap @@ -13,6 +13,11 @@ CLASS lcl_object_nrob DEFINITION INHERITING FROM lcl_objects_super FINAL. INTERFACES lif_object. ALIASES mo_files FOR lif_object~mo_files. + PRIVATE SECTION. + METHODS: + delete_intervals IMPORTING iv_object TYPE inri-object + RAISING lcx_exception. + ENDCLASS. "lcl_object_nrob DEFINITION *----------------------------------------------------------------------* @@ -22,6 +27,10 @@ ENDCLASS. "lcl_object_nrob DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_nrob IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. DATA: lv_objectid TYPE cdhdr-objectid, @@ -59,6 +68,7 @@ CLASS lcl_object_nrob IMPLEMENTATION. METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). + rs_metadata-late_deser = abap_true. ENDMETHOD. "lif_object~get_metadata METHOD lif_object~exists. @@ -161,6 +171,73 @@ CLASS lcl_object_nrob IMPLEMENTATION. ENDMETHOD. "deserialize + METHOD delete_intervals. + + DATA: lv_error TYPE c LENGTH 1, + ls_error TYPE inrer, + lt_list TYPE STANDARD TABLE OF inriv WITH DEFAULT KEY, + lt_error_iv TYPE STANDARD TABLE OF inriv WITH DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF lt_list. + + + CALL FUNCTION 'NUMBER_RANGE_INTERVAL_LIST' + EXPORTING + object = iv_object + TABLES + interval = lt_list + EXCEPTIONS + nr_range_nr1_not_found = 1 + nr_range_nr1_not_intern = 2 + nr_range_nr2_must_be_space = 3 + nr_range_nr2_not_extern = 4 + nr_range_nr2_not_found = 5 + object_not_found = 6 + subobject_must_be_space = 7 + subobject_not_found = 8 + OTHERS = 9. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from NUMBER_RANGE_INTERVAL_LIST' ). + ENDIF. + + IF lines( lt_list ) = 0. + RETURN. + ENDIF. + + LOOP AT lt_list ASSIGNING . + CLEAR -nrlevel. + -procind = 'D'. + ENDLOOP. + + CALL FUNCTION 'NUMBER_RANGE_INTERVAL_UPDATE' + EXPORTING + object = iv_object + IMPORTING + error = ls_error + error_occured = lv_error + TABLES + error_iv = lt_error_iv + interval = lt_list + EXCEPTIONS + object_not_found = 1 + OTHERS = 2. + IF sy-subrc <> 0 OR lv_error = abap_true. + lcx_exception=>raise( 'error from NUMBER_RANGE_INTERVAL_UPDATE' ). + ENDIF. + + CALL FUNCTION 'NUMBER_RANGE_UPDATE_CLOSE' + EXPORTING + object = iv_object + EXCEPTIONS + no_changes_made = 1 + object_not_initialized = 2 + OTHERS = 3. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from NUMBER_RANGE_UPDATE_CLOSE' ). + ENDIF. + + ENDMETHOD. + METHOD lif_object~delete. DATA: lv_object TYPE tnro-object. @@ -168,6 +245,8 @@ CLASS lcl_object_nrob IMPLEMENTATION. lv_object = ms_item-obj_name. + delete_intervals( lv_object ). + CALL FUNCTION 'NUMBER_RANGE_OBJECT_DELETE' EXPORTING language = mv_language @@ -189,4 +268,8 @@ CLASS lcl_object_nrob IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_nrob IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_para.prog.abap b/src/zabapgit_object_para.prog.abap index 968f87445..585093d68 100644 --- a/src/zabapgit_object_para.prog.abap +++ b/src/zabapgit_object_para.prog.abap @@ -22,6 +22,10 @@ ENDCLASS. "lcl_object_para DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_para IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. * looks like "changed by user" is not stored in the database rv_user = c_user_unknown. @@ -143,4 +147,8 @@ CLASS lcl_object_para IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_para IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_pinf.prog.abap b/src/zabapgit_object_pinf.prog.abap index 6275f2149..727fd1fb1 100644 --- a/src/zabapgit_object_pinf.prog.abap +++ b/src/zabapgit_object_pinf.prog.abap @@ -47,6 +47,10 @@ ENDCLASS. "lcl_object_PINF DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_pinf IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE changed_by FROM intf INTO rv_user @@ -189,18 +193,18 @@ CLASS lcl_object_pinf IMPLEMENTATION. lt_add TYPE scomeldata, lv_index TYPE i, lv_found TYPE abap_bool, - ls_sign TYPE scomelsign, +* ls_sign TYPE scomelsign, ls_attr TYPE scomeldtln. FIELD-SYMBOLS: LIKE LINE OF lt_existing, LIKE LINE OF is_pinf-elements. - ls_sign-usag_restr = abap_true. - ls_sign-stability = abap_true. - ls_sign-no_check = abap_true. - ls_sign-useastype = abap_true. - ls_sign-asforgnkey = abap_true. +* ls_sign-usag_restr = abap_true. +* ls_sign-stability = abap_true. +* ls_sign-no_check = abap_true. +* ls_sign-useastype = abap_true. +* ls_sign-asforgnkey = abap_true. * ls_sign-deprecation_type = abap_true. backport * ls_sign-replacement_object_type = abap_true. backport * ls_sign-replacement_object_name = abap_true. backport @@ -219,11 +223,8 @@ CLASS lcl_object_pinf IMPLEMENTATION. ->get_all_attributes( IMPORTING e_element_data = ls_attr ). IF -elem_type = ls_attr-elem_type AND -elem_key = ls_attr-elem_key. - ->set_all_attributes( - i_element_data = - i_data_sign = ls_sign ). - lv_found = abap_true. - EXIT. " current loop + DELETE lt_existing INDEX lv_index. + CONTINUE. " current loop ENDIF. ENDLOOP. @@ -232,10 +233,10 @@ CLASS lcl_object_pinf IMPLEMENTATION. ENDIF. ENDLOOP. - ii_interface->add_elements( lt_add ). - ii_interface->remove_elements( lt_existing ). + ii_interface->add_elements( lt_add ). + ii_interface->save_elements( ). ii_interface->set_elements_changeable( abap_false ). @@ -347,4 +348,8 @@ CLASS lcl_object_pinf IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_PINF IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_prog.prog.abap b/src/zabapgit_object_prog.prog.abap new file mode 100644 index 000000000..d3b29e3c8 --- /dev/null +++ b/src/zabapgit_object_prog.prog.abap @@ -0,0 +1,168 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_OBJECT_PROG +*&---------------------------------------------------------------------* + +*----------------------------------------------------------------------* +* CLASS lcl_object_prog DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_object_prog DEFINITION INHERITING FROM lcl_objects_program FINAL. + + PUBLIC SECTION. + INTERFACES lif_object. + ALIASES mo_files FOR lif_object~mo_files. + + PRIVATE SECTION. + + METHODS deserialize_textpool + IMPORTING it_tpool TYPE textpool_table + RAISING lcx_exception. + +ENDCLASS. "lcl_object_prog DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_object_prog IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_object_prog IMPLEMENTATION. + + METHOD lif_object~has_changed_since. + + rv_changed = check_prog_changed_since( + iv_program = ms_item-obj_name + iv_timestamp = iv_timestamp ). + + ENDMETHOD. "lif_object~has_changed_since + + METHOD lif_object~changed_by. + SELECT SINGLE unam FROM reposrc INTO rv_user + WHERE progname = ms_item-obj_name + AND r3state = 'A'. + IF sy-subrc <> 0. + rv_user = c_user_unknown. + ENDIF. + ENDMETHOD. + + METHOD lif_object~get_metadata. + rs_metadata = get_metadata( ). + ENDMETHOD. "lif_object~get_metadata + + METHOD lif_object~exists. + + DATA: lv_progname TYPE reposrc-progname. + + + SELECT SINGLE progname FROM reposrc INTO lv_progname + WHERE progname = ms_item-obj_name + AND r3state = 'A'. + rv_bool = boolc( sy-subrc = 0 ). + + ENDMETHOD. "lif_object~exists + + METHOD lif_object~jump. + + CALL FUNCTION 'RS_TOOL_ACCESS' + EXPORTING + operation = 'SHOW' + object_name = ms_item-obj_name + object_type = 'PROG' + in_new_window = abap_true. + + ENDMETHOD. "jump + + METHOD lif_object~delete. + + DATA: lv_program LIKE sy-repid. + + + lv_program = ms_item-obj_name. + + CALL FUNCTION 'RS_DELETE_PROGRAM' + EXPORTING + program = lv_program + suppress_popup = abap_true + EXCEPTIONS + enqueue_lock = 1 + object_not_found = 2 + permission_failure = 3 + reject_deletion = 4 + OTHERS = 5. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from RS_DELETE_PROGRAM' ). + ENDIF. + + ENDMETHOD. "delete + + METHOD deserialize_textpool. + + READ TABLE it_tpool WITH KEY id = 'R' TRANSPORTING NO FIELDS. + IF ( sy-subrc = 0 AND lines( it_tpool ) = 1 ) OR lines( it_tpool ) = 0. + RETURN. " no action for includes + ENDIF. + + INSERT TEXTPOOL ms_item-obj_name + FROM it_tpool + LANGUAGE mv_language + STATE 'I'. + IF sy-subrc <> 0. + lcx_exception=>raise( 'error from INSERT TEXTPOOL' ). + ENDIF. + + lcl_objects_activation=>add( iv_type = 'REPT' + iv_name = ms_item-obj_name ). + + ENDMETHOD. "deserialize_textpool + + METHOD lif_object~serialize. + + serialize_program( io_xml = io_xml + is_item = ms_item + io_files = mo_files ). + + ENDMETHOD. "lif_serialize~serialize + + METHOD lif_object~deserialize. + + DATA: lv_program_name TYPE programm, + ls_progdir TYPE ty_progdir, + lt_tpool TYPE textpool_table, + lt_dynpros TYPE ty_dynpro_tt, + lt_tpool_ext TYPE ty_tpool_tt, + ls_cua TYPE ty_cua, + lt_source TYPE abaptxt255_tab. + + lv_program_name = ms_item-obj_name. + + lt_source = mo_files->read_abap( ). + + io_xml->read( EXPORTING iv_name = 'TPOOL' + CHANGING cg_data = lt_tpool_ext ). + lt_tpool = read_tpool( lt_tpool_ext ). + + io_xml->read( EXPORTING iv_name = 'PROGDIR' + CHANGING cg_data = ls_progdir ). + deserialize_program( is_progdir = ls_progdir + it_source = lt_source + it_tpool = lt_tpool + iv_package = iv_package ). + + io_xml->read( EXPORTING iv_name = 'DYNPROS' + CHANGING cg_data = lt_dynpros ). + deserialize_dynpros( it_dynpros = lt_dynpros ). + + io_xml->read( EXPORTING iv_name = 'CUA' + CHANGING cg_data = ls_cua ). + deserialize_cua( iv_program_name = lv_program_name + is_cua = ls_cua ). + + deserialize_textpool( lt_tpool ). + + ENDMETHOD. "lif_serialize~deserialize + + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + +ENDCLASS. "lcl_object_prog IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_prog.prog.xml b/src/zabapgit_object_prog.prog.xml new file mode 100644 index 000000000..508c79fd4 --- /dev/null +++ b/src/zabapgit_object_prog.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_OBJECT_PROG + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_OBJECT_PROG + 28 + + + + + + diff --git a/src/zabapgit_object_serializing.prog.abap b/src/zabapgit_object_serializing.prog.abap new file mode 100644 index 000000000..0536d687c --- /dev/null +++ b/src/zabapgit_object_serializing.prog.abap @@ -0,0 +1,51 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_OBJECT_SERIALIZATION +*&---------------------------------------------------------------------* + +* All object serializing classes + +INCLUDE zabapgit_object_acid. +INCLUDE zabapgit_object_auth. +INCLUDE zabapgit_object_clas. +INCLUDE zabapgit_object_doct. +INCLUDE zabapgit_object_docv. +INCLUDE zabapgit_object_doma. +INCLUDE zabapgit_object_dtel. +INCLUDE zabapgit_object_enho. +INCLUDE zabapgit_object_enhs. +INCLUDE zabapgit_object_enqu. +INCLUDE zabapgit_object_ensc. +INCLUDE zabapgit_object_fugr. +INCLUDE zabapgit_object_iarp. +INCLUDE zabapgit_object_iasp. +INCLUDE zabapgit_object_iatu. +INCLUDE zabapgit_object_msag. +INCLUDE zabapgit_object_nrob. +INCLUDE zabapgit_object_para. +INCLUDE zabapgit_object_pinf. +INCLUDE zabapgit_object_prog. +INCLUDE zabapgit_object_sfbf. +INCLUDE zabapgit_object_sfbs. +INCLUDE zabapgit_object_sfsw. +INCLUDE zabapgit_object_shi3. +INCLUDE zabapgit_object_shlp. +INCLUDE zabapgit_object_sicf. +INCLUDE zabapgit_object_smim. +INCLUDE zabapgit_object_splo. +INCLUDE zabapgit_object_ssfo. +INCLUDE zabapgit_object_ssst. +INCLUDE zabapgit_object_susc. +INCLUDE zabapgit_object_suso. +INCLUDE zabapgit_object_tabl_valid. +INCLUDE zabapgit_object_tabl. +INCLUDE zabapgit_object_tobj. +INCLUDE zabapgit_object_tran. +INCLUDE zabapgit_object_ttyp. +INCLUDE zabapgit_object_type. +INCLUDE zabapgit_object_vcls. +INCLUDE zabapgit_object_view. +INCLUDE zabapgit_object_w3xx. +INCLUDE zabapgit_object_wdya. +INCLUDE zabapgit_object_wdyn. +INCLUDE zabapgit_object_webi. +INCLUDE zabapgit_object_xslt. \ No newline at end of file diff --git a/src/zabapgit_object_serializing.prog.xml b/src/zabapgit_object_serializing.prog.xml new file mode 100644 index 000000000..cfd9247d6 --- /dev/null +++ b/src/zabapgit_object_serializing.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_OBJECT_SERIALIZING + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_OBJECT_SERIALIZATION + 37 + + + + + + diff --git a/src/zabapgit_object_sfbf.prog.abap b/src/zabapgit_object_sfbf.prog.abap index 22700d2cc..5caaf627a 100644 --- a/src/zabapgit_object_sfbf.prog.abap +++ b/src/zabapgit_object_sfbf.prog.abap @@ -27,6 +27,10 @@ ENDCLASS. "lcl_object_SFBF DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_sfbf IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = get( )->get_header_data( )-changedby. @@ -229,4 +233,8 @@ CLASS lcl_object_sfbf IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_SFBF IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_sfbs.prog.abap b/src/zabapgit_object_sfbs.prog.abap index fe506fbd3..4bbd85222 100644 --- a/src/zabapgit_object_sfbs.prog.abap +++ b/src/zabapgit_object_sfbs.prog.abap @@ -27,6 +27,10 @@ ENDCLASS. "lcl_object_SFBS DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_sfbs IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = get( )->get_header_data( )-changedby. @@ -203,4 +207,10 @@ CLASS lcl_object_sfbs IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + + + ENDCLASS. "lcl_object_SFBS IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_sfsw.prog.abap b/src/zabapgit_object_sfsw.prog.abap index e3808237d..33e9c21ff 100644 --- a/src/zabapgit_object_sfsw.prog.abap +++ b/src/zabapgit_object_sfsw.prog.abap @@ -27,6 +27,10 @@ ENDCLASS. "lcl_object_sfsw DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_sfsw IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = get( )->get_header_data( )-changedby. @@ -197,4 +201,8 @@ CLASS lcl_object_sfsw IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_sfsw IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_shi3.prog.abap b/src/zabapgit_object_shi3.prog.abap index 4201d8f6d..d7789e964 100644 --- a/src/zabapgit_object_shi3.prog.abap +++ b/src/zabapgit_object_shi3.prog.abap @@ -54,6 +54,10 @@ ENDCLASS. "lcl_object_shi3 DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_shi3 IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -326,4 +330,8 @@ CLASS lcl_object_shi3 IMPLEMENTATION. ENDMETHOD. "deserialize + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_shi3 IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_shlp.prog.abap b/src/zabapgit_object_shlp.prog.abap index b2e9287b4..9d32eb6db 100644 --- a/src/zabapgit_object_shlp.prog.abap +++ b/src/zabapgit_object_shlp.prog.abap @@ -22,6 +22,21 @@ ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_shlp IMPLEMENTATION. + METHOD lif_object~has_changed_since. + + DATA: lv_date TYPE dats, + lv_time TYPE tims, + lv_ts TYPE timestamp. + + SELECT SINGLE as4date as4time FROM dd30l + INTO (lv_date, lv_time) + WHERE shlpname = ms_item-obj_name + AND as4local = 'A'. + + _object_check_timestamp lv_date lv_time. + + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE as4user FROM dd30l INTO rv_user @@ -87,6 +102,8 @@ CLASS lcl_object_shlp IMPLEMENTATION. lt_dd32p TYPE TABLE OF dd32p, lt_dd33v TYPE TABLE OF dd33v. + FIELD-SYMBOLS: LIKE LINE OF lt_dd32p. + lv_name = ms_item-obj_name. @@ -115,6 +132,21 @@ CLASS lcl_object_shlp IMPLEMENTATION. ls_dd30v-as4date, ls_dd30v-as4time. + LOOP AT lt_dd32p ASSIGNING . +* clear information inherited from domain + CLEAR: -domname, + -headlen, + -scrlen1, + -scrlen2, + -datatype, + -leng, + -outputlen, + -decimals, + -lowercase, + -signflag, + -convexit. + ENDLOOP. + io_xml->add( iv_name = 'DD30V' ig_data = ls_dd30v ). io_xml->add( ig_data = lt_dd31v @@ -171,4 +203,8 @@ CLASS lcl_object_shlp IMPLEMENTATION. ENDMETHOD. "deserialize + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_shlp IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_sicf.prog.abap b/src/zabapgit_object_sicf.prog.abap index f52120d69..3ff67774b 100644 --- a/src/zabapgit_object_sicf.prog.abap +++ b/src/zabapgit_object_sicf.prog.abap @@ -62,6 +62,10 @@ ENDCLASS. "lcl_object_sicf DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_sicf IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. DATA: ls_icfservice TYPE icfservice. @@ -414,4 +418,8 @@ CLASS lcl_object_sicf IMPLEMENTATION. lcx_exception=>raise( 'todo, SICF, jump' ). ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_sicf IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_smim.prog.abap b/src/zabapgit_object_smim.prog.abap index 4155ca697..b03edb856 100644 --- a/src/zabapgit_object_smim.prog.abap +++ b/src/zabapgit_object_smim.prog.abap @@ -42,6 +42,10 @@ ENDCLASS. "lcl_object_smim DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_smim IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. DATA: lv_loio TYPE sdok_docid. @@ -188,7 +192,7 @@ CLASS lcl_object_smim IMPLEMENTATION. permission_failure = 4 OTHERS = 5 ). IF sy-subrc <> 0. - lcx_exception=>raise( 'error from mime api->get' ). + lcx_exception=>raise( 'error from mime api->get:' && sy-msgv1 ). ENDIF. lv_filename = get_filename( lv_url ). @@ -313,4 +317,8 @@ CLASS lcl_object_smim IMPLEMENTATION. lcx_exception=>raise( 'todo, SMIM, jump' ). ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_smim IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_splo.prog.abap b/src/zabapgit_object_splo.prog.abap index 929c4579a..c8a958482 100644 --- a/src/zabapgit_object_splo.prog.abap +++ b/src/zabapgit_object_splo.prog.abap @@ -22,6 +22,10 @@ ENDCLASS. "lcl_object_splo DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_splo IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE chgname1 FROM tsp1d INTO rv_user @@ -34,6 +38,7 @@ CLASS lcl_object_splo IMPLEMENTATION. METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). + rs_metadata-delete_tadir = abap_true. ENDMETHOD. "lif_object~get_metadata METHOD lif_object~serialize. @@ -105,14 +110,6 @@ CLASS lcl_object_splo IMPLEMENTATION. DELETE FROM tsp1d WHERE papart = ms_item-obj_name. "#EC CI_SUBRC DELETE FROM tsp0p WHERE pdpaper = ms_item-obj_name. "#EC CI_SUBRC - CALL FUNCTION 'TR_TADIR_INTERFACE' - EXPORTING - wi_delete_tadir_entry = abap_true - wi_tadir_pgmid = 'R3TR' - wi_tadir_object = ms_item-obj_type - wi_tadir_obj_name = ms_item-obj_name - wi_test_modus = abap_false. - ENDMETHOD. "lif_object~delete METHOD lif_object~exists. @@ -130,4 +127,8 @@ CLASS lcl_object_splo IMPLEMENTATION. lcx_exception=>raise( 'todo, jump, SPLO' ). ENDMETHOD. "lif_object~jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_splo IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_ssfo.prog.abap b/src/zabapgit_object_ssfo.prog.abap index a8f62b563..efef1e0c8 100644 --- a/src/zabapgit_object_ssfo.prog.abap +++ b/src/zabapgit_object_ssfo.prog.abap @@ -22,6 +22,10 @@ ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_ssfo IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE lastuser FROM stxfadm INTO rv_user @@ -34,6 +38,7 @@ CLASS lcl_object_ssfo IMPLEMENTATION. METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). + rs_metadata-delete_tadir = abap_true. ENDMETHOD. "lif_object~get_metadata METHOD lif_object~exists. @@ -233,4 +238,8 @@ CLASS lcl_object_ssfo IMPLEMENTATION. ENDMETHOD. "deserialize + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_ssfo IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_ssst.prog.abap b/src/zabapgit_object_ssst.prog.abap index c4817f1f8..40dced694 100644 --- a/src/zabapgit_object_ssst.prog.abap +++ b/src/zabapgit_object_ssst.prog.abap @@ -27,6 +27,10 @@ ENDCLASS. "lcl_object_ssst DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_ssst IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE lastuser FROM stxsadm INTO rv_user @@ -39,6 +43,7 @@ CLASS lcl_object_ssst IMPLEMENTATION. METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). + rs_metadata-delete_tadir = abap_true. ENDMETHOD. "lif_object~get_metadata METHOD lif_object~exists. @@ -198,4 +203,8 @@ CLASS lcl_object_ssst IMPLEMENTATION. lcx_exception=>raise( 'todo' ). ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_ssst IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_susc.prog.abap b/src/zabapgit_object_susc.prog.abap index 863dc6cfb..5830bc7b4 100644 --- a/src/zabapgit_object_susc.prog.abap +++ b/src/zabapgit_object_susc.prog.abap @@ -22,12 +22,17 @@ ENDCLASS. "lcl_object_susc DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_susc IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. METHOD lif_object~get_metadata. rs_metadata = get_metadata( ). + rs_metadata-delete_tadir = abap_true. ENDMETHOD. "lif_object~get_metadata METHOD lif_object~exists. @@ -118,4 +123,8 @@ CLASS lcl_object_susc IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_susc IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_suso.prog.abap b/src/zabapgit_object_suso.prog.abap index 06f9e0d12..09eace64a 100644 --- a/src/zabapgit_object_suso.prog.abap +++ b/src/zabapgit_object_suso.prog.abap @@ -22,6 +22,10 @@ ENDCLASS. "lcl_object_suso DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_suso IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -165,4 +169,8 @@ CLASS lcl_object_suso IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_suso IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_tabl.prog.abap b/src/zabapgit_object_tabl.prog.abap index c37109e43..fcd1c4dac 100644 --- a/src/zabapgit_object_tabl.prog.abap +++ b/src/zabapgit_object_tabl.prog.abap @@ -7,6 +7,7 @@ *----------------------------------------------------------------------* * *----------------------------------------------------------------------* + CLASS lcl_object_tabl DEFINITION INHERITING FROM lcl_objects_super FINAL. PUBLIC SECTION. @@ -22,6 +23,43 @@ ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_tabl IMPLEMENTATION. + METHOD lif_object~has_changed_since. + + DATA: lv_date TYPE dats, + lv_time TYPE tims, + lv_ts TYPE timestamp, + lt_indexes TYPE STANDARD TABLE OF dd09l. + + FIELD-SYMBOLS LIKE LINE OF lt_indexes. + + SELECT SINGLE as4date as4time FROM dd02l " Table + INTO (lv_date, lv_time) + WHERE tabname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + + _object_check_timestamp lv_date lv_time. + + SELECT SINGLE as4date as4time FROM dd09l " Table tech settings + INTO (lv_date, lv_time) + WHERE tabname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + + _object_check_timestamp lv_date lv_time. + + SELECT as4date as4time FROM dd12l " Table tech settings + INTO CORRESPONDING FIELDS OF TABLE lt_indexes + WHERE sqltab = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000' ##TOO_MANY_ITAB_FIELDS. + + LOOP AT lt_indexes ASSIGNING . + _object_check_timestamp -as4date -as4time. + ENDLOOP. + + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE as4user FROM dd02l INTO rv_user @@ -92,9 +130,12 @@ CLASS lcl_object_tabl IMPLEMENTATION. lt_dd12v TYPE dd12vtab, lt_dd17v TYPE dd17vtab, lt_dd35v TYPE TABLE OF dd35v, + lv_index LIKE sy-index, lt_dd36m TYPE dd36mttyp. FIELD-SYMBOLS: LIKE LINE OF lt_dd12v, + LIKE LINE OF lt_dd05m, + LIKE LINE OF lt_dd36m, LIKE LINE OF lt_dd03p. @@ -139,9 +180,15 @@ CLASS lcl_object_tabl IMPLEMENTATION. -as4time. ENDLOOP. +* remove nested structures + DELETE lt_dd03p WHERE depth <> '00'. +* remove fields from .INCLUDEs + DELETE lt_dd03p WHERE adminfield <> '0'. + LOOP AT lt_dd03p ASSIGNING WHERE NOT rollname IS INITIAL. CLEAR: -ddlanguage, -dtelmaster, + -logflag, -ddtext, -reptext, -scrtext_s, @@ -162,6 +209,8 @@ CLASS lcl_object_tabl IMPLEMENTATION. -datatype, -leng, -outputlen, + -deffdname, + -convexit, -entitytab, -dommaster, -domname3l. @@ -179,10 +228,32 @@ CLASS lcl_object_tabl IMPLEMENTATION. ENDIF. ENDLOOP. +* remove foreign keys inherited from .INCLUDEs + DELETE lt_dd08v WHERE noinherit = 'N'. + LOOP AT lt_dd05m ASSIGNING . + lv_index = sy-tabix. + READ TABLE lt_dd08v WITH KEY fieldname = -fieldname TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + DELETE lt_dd05m INDEX lv_index. + ENDIF. + ENDLOOP. + +* remove inherited search helps + DELETE lt_dd35v WHERE shlpinher = abap_true. + LOOP AT lt_dd36m ASSIGNING . + lv_index = sy-tabix. + READ TABLE lt_dd35v WITH KEY fieldname = -fieldname TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + DELETE lt_dd36m INDEX lv_index. + ENDIF. + ENDLOOP. + io_xml->add( iv_name = 'DD02V' ig_data = ls_dd02v ). - io_xml->add( iv_name = 'DD09L' - ig_data = ls_dd09l ). + IF NOT ls_dd09l IS INITIAL. + io_xml->add( iv_name = 'DD09L' + ig_data = ls_dd09l ). + ENDIF. io_xml->add( ig_data = lt_dd03p iv_name = 'DD03P_TABLE' ). io_xml->add( ig_data = lt_dd05m @@ -309,4 +380,32 @@ CLASS lcl_object_tabl IMPLEMENTATION. ENDMETHOD. "deserialize + METHOD lif_object~compare_to_remote_version. + DATA: lo_table_validation TYPE REF TO lcl_object_tabl_validation, + lo_local_version_output TYPE REF TO lcl_xml_output, + lo_local_version_input TYPE REF TO lcl_xml_input, + lv_validation_text TYPE string. + + CREATE OBJECT lo_local_version_output. + me->lif_object~serialize( lo_local_version_output ). + + CREATE OBJECT lo_local_version_input + EXPORTING + iv_xml = lo_local_version_output->render( ). + + CREATE OBJECT lo_table_validation. + + lv_validation_text = lo_table_validation->validate( + io_remote_version = io_remote_version_xml + io_local_version = lo_local_version_input ). + IF lv_validation_text IS NOT INITIAL. + lv_validation_text = |Database Table { ms_item-obj_name }: { lv_validation_text }|. + CREATE OBJECT ro_comparison_result TYPE lcl_tabl_validation_dialog + EXPORTING + iv_message = lv_validation_text. + ELSE. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDIF. + ENDMETHOD. + ENDCLASS. "lcl_object_TABL IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_tabl_valid.prog.abap b/src/zabapgit_object_tabl_valid.prog.abap new file mode 100644 index 000000000..58d0aa20a --- /dev/null +++ b/src/zabapgit_object_tabl_valid.prog.abap @@ -0,0 +1,225 @@ +*&---------------------------------------------------------------------* +*& Include zabapgit_object_tabl_valid +*&---------------------------------------------------------------------* + +CLASS lcl_object_tabl_validation DEFINITION FINAL. + PUBLIC SECTION. + METHODS validate + IMPORTING + io_remote_version TYPE REF TO lcl_xml_input + io_local_version TYPE REF TO lcl_xml_input + RETURNING + VALUE(rv_message) TYPE string + RAISING + lcx_exception. +ENDCLASS. + +CLASS lcl_tabl_validation_dialog DEFINITION FINAL. + PUBLIC SECTION. + METHODS: + constructor + IMPORTING + iv_message TYPE string. + INTERFACES: lif_object_comparison_result. + PRIVATE SECTION. + DATA mv_message TYPE string. + DATA mv_halt TYPE string. + +ENDCLASS. + +CLASS lcl_object_tabl_validation IMPLEMENTATION. + + METHOD validate. + DATA: lt_previous_table_fields TYPE TABLE OF dd03p, + ls_previous_table_field LIKE LINE OF lt_previous_table_fields, + lt_current_table_fields TYPE TABLE OF dd03p, + ls_current_table_field LIKE LINE OF lt_current_table_fields. + io_remote_version->read( + EXPORTING + iv_name = 'DD03P_TABLE' + CHANGING + cg_data = lt_previous_table_fields ). + io_local_version->read( + EXPORTING + iv_name = 'DD03P_TABLE' + CHANGING + cg_data = lt_current_table_fields ). + + LOOP AT lt_previous_table_fields INTO ls_previous_table_field. + READ TABLE lt_current_table_fields WITH KEY fieldname = ls_previous_table_field-fieldname + INTO ls_current_table_field. + IF sy-subrc = 0. + IF ls_current_table_field-rollname <> ls_previous_table_field-rollname. + rv_message = 'Fields were changed. This may lead to inconsistencies.'. + ENDIF. + ELSE. + rv_message = 'Fields were changed. This may lead to inconsistencies.'. + ENDIF. + ENDLOOP. + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_tabl_validation_dialog IMPLEMENTATION. + METHOD constructor. + mv_message = iv_message. + ENDMETHOD. + METHOD lif_object_comparison_result~is_result_complete_halt. + rv_response = mv_halt. + ENDMETHOD. + + METHOD lif_object_comparison_result~show_confirmation_dialog. + DATA lv_answer TYPE string. + TRY. + lv_answer = lcl_popups=>popup_to_confirm( + titlebar = 'Warning' + text_question = mv_message + text_button_1 = 'Abort' + icon_button_1 = 'ICON_CANCEL' + text_button_2 = 'Pull anyway' + icon_button_2 = 'ICON_OKAY' + default_button = '2' + display_cancel_button = abap_false ). + CATCH lcx_exception. + mv_halt = abap_true. + ENDTRY. + + IF lv_answer = 1. + mv_halt = abap_true. + ENDIF. + ENDMETHOD. +ENDCLASS. + + +CLASS lct_table_validation DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL. + PRIVATE SECTION. + METHODS: + setup, + type_changed FOR TESTING RAISING lcx_exception, + no_type_changes FOR TESTING RAISING lcx_exception, + field_not_found FOR TESTING RAISING lcx_exception, + no_fields_no_message FOR TESTING RAISING lcx_exception, + create_xmls + RAISING + lcx_exception. + DATA: mo_table_validator TYPE REF TO lcl_object_tabl_validation, + mo_previous_version_out_xml TYPE REF TO lcl_xml_output, + mo_previous_version_input_xml TYPE REF TO lcl_xml_input, + mo_current_version_out_xml TYPE REF TO lcl_xml_output, + mo_current_version_input_xml TYPE REF TO lcl_xml_input, + mt_previous_table_fields TYPE TABLE OF dd03p, + mt_current_table_fields TYPE TABLE OF dd03p, + mv_validation_message TYPE string. + +ENDCLASS. + +CLASS lct_table_validation IMPLEMENTATION. + METHOD setup. + CREATE OBJECT mo_table_validator. + ENDMETHOD. + METHOD type_changed. + DATA: + ls_previous_table_field LIKE LINE OF mt_previous_table_fields, + ls_current_table_field LIKE LINE OF mt_current_table_fields. + + ls_previous_table_field-fieldname = 'FIELD1'. + ls_previous_table_field-rollname = 'INT4'. + APPEND ls_previous_table_field TO mt_previous_table_fields. + + ls_current_table_field-fieldname = 'FIELD1'. + ls_current_table_field-rollname = 'CHAR30'. + APPEND ls_current_table_field TO mt_current_table_fields. + + create_xmls( ). + + mv_validation_message = mo_table_validator->validate( + io_remote_version = mo_previous_version_input_xml + io_local_version = mo_current_version_input_xml ). + + cl_abap_unit_assert=>assert_equals( + act = mv_validation_message + exp = 'Fields were changed. This may lead to inconsistencies.' ). + ENDMETHOD. + + METHOD no_type_changes. + DATA: + ls_previous_table_field LIKE LINE OF mt_previous_table_fields. + + ls_previous_table_field-fieldname = 'FIELD1'. + ls_previous_table_field-rollname = 'INT4'. + APPEND ls_previous_table_field TO mt_previous_table_fields. + + mt_current_table_fields = mt_previous_table_fields. + + create_xmls( ). + + mv_validation_message = mo_table_validator->validate( + io_remote_version = mo_previous_version_input_xml + io_local_version = mo_current_version_input_xml ). + + cl_abap_unit_assert=>assert_equals( + act = mv_validation_message + exp = '' ). + ENDMETHOD. + + METHOD field_not_found. + DATA: + ls_previous_table_field LIKE LINE OF mt_previous_table_fields, + ls_current_table_field LIKE LINE OF mt_current_table_fields. + + ls_previous_table_field-fieldname = 'FIELD1'. + ls_previous_table_field-rollname = 'INT4'. + APPEND ls_previous_table_field TO mt_previous_table_fields. + + ls_current_table_field-fieldname = 'ANOTHER_FIELD'. + ls_current_table_field-rollname = 'CHAR30'. + APPEND ls_current_table_field TO mt_current_table_fields. + + create_xmls( ). + + mv_validation_message = mo_table_validator->validate( + io_remote_version = mo_previous_version_input_xml + io_local_version = mo_current_version_input_xml ). + + cl_abap_unit_assert=>assert_equals( + act = mv_validation_message + exp = 'Fields were changed. This may lead to inconsistencies.' ). + ENDMETHOD. + + METHOD no_fields_no_message. + DATA: + ls_current_table_field LIKE LINE OF mt_current_table_fields. + + create_xmls( ). + + mv_validation_message = mo_table_validator->validate( + io_remote_version = mo_previous_version_input_xml + io_local_version = mo_current_version_input_xml ). + + cl_abap_unit_assert=>assert_initial( mv_validation_message ). + ENDMETHOD. + + + METHOD create_xmls. + CREATE OBJECT mo_previous_version_out_xml. + mo_previous_version_out_xml->add( + iv_name = 'DD03P_TABLE' + ig_data = mt_previous_table_fields ). + + CREATE OBJECT mo_previous_version_input_xml + EXPORTING + iv_xml = mo_previous_version_out_xml->render( ). + + CREATE OBJECT mo_current_version_out_xml. + mo_current_version_out_xml->add( + iv_name = 'DD03P_TABLE' + ig_data = mt_current_table_fields ). + + CREATE OBJECT mo_current_version_input_xml + EXPORTING + iv_xml = mo_current_version_out_xml->render( ). + ENDMETHOD. + + + +ENDCLASS. \ No newline at end of file diff --git a/src/zabapgit_object_tabl_valid.prog.xml b/src/zabapgit_object_tabl_valid.prog.xml new file mode 100644 index 000000000..0a56f24a3 --- /dev/null +++ b/src/zabapgit_object_tabl_valid.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_OBJECT_TABL_VALID + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_OBJECT_TABL_VALID + 34 + + + + + + diff --git a/src/zabapgit_object_tobj.prog.abap b/src/zabapgit_object_tobj.prog.abap index 2dd8e159c..3319bbee6 100644 --- a/src/zabapgit_object_tobj.prog.abap +++ b/src/zabapgit_object_tobj.prog.abap @@ -22,6 +22,10 @@ ENDCLASS. "lcl_object_tobj DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_tobj IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -179,4 +183,8 @@ CLASS lcl_object_tobj IMPLEMENTATION. lcx_exception=>raise( 'todo, TOBJ jump' ). ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_tobj IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_tran.prog.abap b/src/zabapgit_object_tran.prog.abap index eba7dc246..5f4b9cbff 100644 --- a/src/zabapgit_object_tran.prog.abap +++ b/src/zabapgit_object_tran.prog.abap @@ -47,6 +47,10 @@ ENDCLASS. "lcl_object_TRAN DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_tran IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -409,4 +413,8 @@ CLASS lcl_object_tran IMPLEMENTATION. ENDMETHOD. "serialize + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_tran IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_ttyp.prog.abap b/src/zabapgit_object_ttyp.prog.abap index 1c7ca97ab..b85104ebc 100644 --- a/src/zabapgit_object_ttyp.prog.abap +++ b/src/zabapgit_object_ttyp.prog.abap @@ -22,6 +22,21 @@ ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_ttyp IMPLEMENTATION. + METHOD lif_object~has_changed_since. + + DATA: lv_date TYPE dats, + lv_time TYPE tims, + lv_ts TYPE timestamp. + + SELECT SINGLE as4date as4time FROM dd40l + INTO (lv_date, lv_time) + WHERE typename = ms_item-obj_name + AND as4local = 'A'. + + _object_check_timestamp lv_date lv_time. + + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE as4user FROM dd40l INTO rv_user @@ -113,6 +128,10 @@ CLASS lcl_object_ttyp IMPLEMENTATION. ls_dd40v-as4date, ls_dd40v-as4time. + IF NOT ls_dd40v-rowkind IS INITIAL. + CLEAR ls_dd40v-typelen. + ENDIF. + io_xml->add( iv_name = 'DD40V' ig_data = ls_dd40v ). io_xml->add( iv_name = 'DD42V' @@ -163,4 +182,8 @@ CLASS lcl_object_ttyp IMPLEMENTATION. ENDMETHOD. "deserialize + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_ttyp IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_type.prog.abap b/src/zabapgit_object_type.prog.abap index b03973692..8c7273888 100644 --- a/src/zabapgit_object_type.prog.abap +++ b/src/zabapgit_object_type.prog.abap @@ -35,6 +35,10 @@ ENDCLASS. "lcl_object_type DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_type IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -201,4 +205,8 @@ CLASS lcl_object_type IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_type IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_vcls.prog.abap b/src/zabapgit_object_vcls.prog.abap index 49fce52fc..0fad2048b 100644 --- a/src/zabapgit_object_vcls.prog.abap +++ b/src/zabapgit_object_vcls.prog.abap @@ -26,6 +26,10 @@ ENDCLASS. "lcl_object_vcls DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_vcls IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -185,4 +189,8 @@ CLASS lcl_object_vcls IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_vcls IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_view.prog.abap b/src/zabapgit_object_view.prog.abap index 987bf43f2..31481e426 100644 --- a/src/zabapgit_object_view.prog.abap +++ b/src/zabapgit_object_view.prog.abap @@ -22,6 +22,30 @@ ENDCLASS. "lcl_object_dtel DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_view IMPLEMENTATION. + METHOD lif_object~has_changed_since. + + DATA: lv_date TYPE dats, + lv_time TYPE tims, + lv_ts TYPE timestamp. + + SELECT SINGLE as4date as4time FROM dd25l " View + INTO (lv_date, lv_time) + WHERE viewname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + + _object_check_timestamp lv_date lv_time. + + SELECT SINGLE as4date as4time FROM dd09l " Table tech settings + INTO (lv_date, lv_time) + WHERE tabname = ms_item-obj_name + AND as4local = 'A' + AND as4vers = '0000'. + + _object_check_timestamp lv_date lv_time. + + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. SELECT SINGLE as4user FROM dd25l INTO rv_user @@ -193,4 +217,8 @@ CLASS lcl_object_view IMPLEMENTATION. ENDMETHOD. "deserialize + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_view IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_w3xx.prog.abap b/src/zabapgit_object_w3xx.prog.abap index 6c4b83b37..c14bdc062 100644 --- a/src/zabapgit_object_w3xx.prog.abap +++ b/src/zabapgit_object_w3xx.prog.abap @@ -12,8 +12,48 @@ CLASS lcl_object_w3super DEFINITION INHERITING FROM lcl_objects_super ABSTRACT. PUBLIC SECTION. INTERFACES lif_object. + TYPES ty_wwwparams_tt TYPE STANDARD TABLE OF wwwparams WITH DEFAULT KEY. + + CONSTANTS: BEGIN OF c_param_names, + version TYPE w3_name VALUE 'version', + fileext TYPE w3_name VALUE 'fileextension', + filesize TYPE w3_name VALUE 'filesize', + filename TYPE w3_name VALUE 'filename', + mimetype TYPE w3_name VALUE 'mimetype', + END OF c_param_names. + + METHODS constructor + IMPORTING + is_item TYPE ty_item + iv_language TYPE spras. + + PROTECTED SECTION. + + METHODS get_metadata REDEFINITION. + PRIVATE SECTION. - METHODS init_key RETURNING VALUE(rs_key) TYPE wwwdatatab. + + DATA ms_key TYPE wwwdatatab. + + METHODS get_ext + IMPORTING it_params TYPE ty_wwwparams_tt + RETURNING VALUE(rv_ext) TYPE string + RAISING lcx_exception. + + METHODS normalize_params + IMPORTING iv_size TYPE i + CHANGING ct_params TYPE ty_wwwparams_tt " Param table to patch + RAISING lcx_exception. + + METHODS strip_params + CHANGING ct_params TYPE ty_wwwparams_tt + RAISING lcx_exception. + + METHODS find_param + IMPORTING it_params TYPE ty_wwwparams_tt + iv_name TYPE w3_name + RETURNING VALUE(rv_value) TYPE string + RAISING lcx_exception. ENDCLASS. "lcl_object_W3SUPER DEFINITION @@ -24,17 +64,22 @@ ENDCLASS. "lcl_object_W3SUPER DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_w3super IMPLEMENTATION. + METHOD constructor. + super->constructor( is_item = is_item iv_language = iv_language ). + ms_key-relid = ms_item-obj_type+2(2). + ms_key-objid = ms_item-obj_name. + ENDMETHOD. " constructor. + + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. - METHOD init_key. - rs_key-relid = ms_item-obj_type+2(2). - rs_key-objid = ms_item-obj_name. - ENDMETHOD. " init_key - METHOD lif_object~jump. - " No idea how to just to SMW0 + " No idea how to jump to SMW0 lcx_exception=>raise( 'Please go to SMW0 for W3MI object' ). ENDMETHOD. "jump @@ -42,18 +87,17 @@ CLASS lcl_object_w3super IMPLEMENTATION. rs_metadata = get_metadata( ). ENDMETHOD. "lif_object~get_metadata - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - " W3xx EXISTS - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + METHOD get_metadata. "Redefinition + rs_metadata = super->get_metadata( ). + rs_metadata-version = 'v2.0.0'. " Seriazation v2, separate data file + ENDMETHOD. " get_metadata. "Redefinition + METHOD lif_object~exists. - DATA ls_key TYPE wwwdatatab. - ls_key = init_key( ). - - SELECT SINGLE objid INTO ls_key-objid + SELECT SINGLE objid INTO ms_key-objid FROM wwwdata - WHERE relid = ls_key-relid - AND objid = ls_key-objid + WHERE relid = ms_key-relid + AND objid = ms_key-objid AND srtf2 = 0. IF sy-subrc IS NOT INITIAL. @@ -64,26 +108,18 @@ CLASS lcl_object_w3super IMPLEMENTATION. ENDMETHOD. "lif_object~exists - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - " W3xx SERIALIZE - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" METHOD lif_object~serialize. - DATA ls_key TYPE wwwdatatab. + DATA lt_w3mime TYPE STANDARD TABLE OF w3mime. DATA lt_w3html TYPE STANDARD TABLE OF w3html. DATA lt_w3params TYPE STANDARD TABLE OF wwwparams. DATA lv_xstring TYPE xstring. - DATA ls_wwwparam LIKE LINE OF lt_w3params. DATA lv_size TYPE int4. - DATA lv_base64str TYPE string. - DATA lo_utility TYPE REF TO cl_http_utility. - ls_key = init_key( ). - - SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_key + SELECT SINGLE * INTO CORRESPONDING FIELDS OF ms_key FROM wwwdata - WHERE relid = ls_key-relid - AND objid = ls_key-objid + WHERE relid = ms_key-relid + AND objid = ms_key-objid AND srtf2 = 0. IF sy-subrc IS NOT INITIAL. @@ -92,7 +128,7 @@ CLASS lcl_object_w3super IMPLEMENTATION. CALL FUNCTION 'WWWDATA_IMPORT' EXPORTING - key = ls_key + key = ms_key TABLES mime = lt_w3mime html = lt_w3html @@ -106,8 +142,8 @@ CLASS lcl_object_w3super IMPLEMENTATION. CALL FUNCTION 'WWWPARAMS_READ_ALL' EXPORTING - type = ls_key-relid - objid = ls_key-objid + type = ms_key-relid + objid = ms_key-objid TABLES params = lt_w3params EXCEPTIONS @@ -117,14 +153,11 @@ CLASS lcl_object_w3super IMPLEMENTATION. lcx_exception=>raise( 'Cannot read W3xx data' ). ENDIF. - READ TABLE lt_w3params INTO ls_wwwparam WITH KEY name = 'filesize' ##NO_TEXT. - IF sy-subrc IS NOT INITIAL. - lcx_exception=>raise( 'Cannot read W3xx filesize' ). - ENDIF. + lv_size = find_param( it_params = lt_w3params iv_name = c_param_names-filesize ). + " Clean params (remove version, filesize & clear filename from path) + strip_params( CHANGING ct_params = lt_w3params ). - lv_size = ls_wwwparam-value. - - CASE ls_key-relid. + CASE ms_key-relid. WHEN 'MI'. CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' EXPORTING @@ -151,53 +184,52 @@ CLASS lcl_object_w3super IMPLEMENTATION. lcx_exception=>raise( 'Cannot convert W3xx to xstring' ). ENDIF. - CREATE OBJECT lo_utility. - lv_base64str = lo_utility->encode_x_base64( lv_xstring ). - io_xml->add( iv_name = 'NAME' - ig_data = ls_key-objid ). + ig_data = ms_key-objid ). io_xml->add( iv_name = 'TEXT' - ig_data = ls_key-text ). - - io_xml->add( iv_name = 'DATA' - ig_data = lv_base64str ). + ig_data = ms_key-text ). io_xml->add( iv_name = 'PARAMS' ig_data = lt_w3params ). + " Seriazation v2, separate data file. 'extra' added to prevent conflict with .xml + lif_object~mo_files->add_raw( iv_data = lv_xstring + iv_extra = 'data' + iv_ext = get_ext( lt_w3params ) ). + ENDMETHOD. "serialize - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - " W3xx DESERIALIZE - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" METHOD lif_object~deserialize. - DATA ls_key TYPE wwwdatatab. DATA lv_base64str TYPE string. DATA lt_w3params TYPE STANDARD TABLE OF wwwparams. DATA lv_xstring TYPE xstring. - DATA lo_utility TYPE REF TO cl_http_utility. DATA lt_w3mime TYPE STANDARD TABLE OF w3mime. DATA lt_w3html TYPE STANDARD TABLE OF w3html. DATA lv_size TYPE int4. DATA lv_tadir_obj TYPE tadir-object. - ls_key = init_key( ). io_xml->read( EXPORTING iv_name = 'TEXT' - CHANGING cg_data = ls_key-text ). - - io_xml->read( EXPORTING iv_name = 'DATA' - CHANGING cg_data = lv_base64str ). + CHANGING cg_data = ms_key-text ). io_xml->read( EXPORTING iv_name = 'PARAMS' CHANGING cg_data = lt_w3params ). - CREATE OBJECT lo_utility. - lv_xstring = lo_utility->decode_x_base64( lv_base64str ). + CASE io_xml->get_metadata( )-version. + WHEN 'v1.0.0'. + io_xml->read( EXPORTING iv_name = 'DATA' + CHANGING cg_data = lv_base64str ). + lv_xstring = cl_http_utility=>decode_x_base64( lv_base64str ). + WHEN 'v2.0.0'. + lv_xstring = lif_object~mo_files->read_raw( iv_extra = 'data' + iv_ext = get_ext( lt_w3params ) ). + WHEN OTHERS. + lcx_exception=>raise( 'W3xx: Unknown serializer version' ). + ENDCASE. - CASE ls_key-relid. + CASE ms_key-relid. WHEN 'MI'. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING @@ -234,6 +266,10 @@ CLASS lcl_object_w3super IMPLEMENTATION. lcx_exception=>raise( 'Wrong W3xx type' ). ENDCASE. + " Update size of file based on actual data file size, prove param object name + normalize_params( EXPORTING iv_size = lv_size + CHANGING ct_params = lt_w3params ). + CALL FUNCTION 'WWWPARAMS_UPDATE' TABLES params = lt_w3params @@ -244,14 +280,14 @@ CLASS lcl_object_w3super IMPLEMENTATION. lcx_exception=>raise( 'Cannot update W3xx params' ). ENDIF. - ls_key-tdate = sy-datum. - ls_key-ttime = sy-uzeit. - ls_key-chname = sy-uname. - ls_key-devclass = iv_package. + ms_key-tdate = sy-datum. + ms_key-ttime = sy-uzeit. + ms_key-chname = sy-uname. + ms_key-devclass = iv_package. CALL FUNCTION 'WWWDATA_EXPORT' EXPORTING - key = ls_key + key = ms_key TABLES mime = lt_w3mime html = lt_w3html @@ -263,14 +299,14 @@ CLASS lcl_object_w3super IMPLEMENTATION. lcx_exception=>raise( 'Cannot upload W3xx data' ). ENDIF. - CONCATENATE 'W3' ls_key-relid INTO lv_tadir_obj. + CONCATENATE 'W3' ms_key-relid INTO lv_tadir_obj. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_tadir_pgmid = 'R3TR' wi_tadir_object = lv_tadir_obj wi_tadir_devclass = iv_package - wi_tadir_obj_name = ls_key-objid + wi_tadir_obj_name = ms_key-objid wi_test_modus = space EXCEPTIONS tadir_entry_not_existing = 1 @@ -305,17 +341,11 @@ CLASS lcl_object_w3super IMPLEMENTATION. ENDMETHOD. "lif_object~deserialize - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - " W3xx DELETE - """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" METHOD lif_object~delete. - DATA ls_key TYPE wwwdatatab. - - ls_key = init_key( ). CALL FUNCTION 'WWWDATA_DELETE' EXPORTING - key = ls_key + key = ms_key EXCEPTIONS wrong_object_type = 1 delete_error = 2. @@ -326,7 +356,7 @@ CLASS lcl_object_w3super IMPLEMENTATION. CALL FUNCTION 'WWWPARAMS_DELETE_ALL' EXPORTING - key = ls_key + key = ms_key EXCEPTIONS delete_error = 1. @@ -336,6 +366,67 @@ CLASS lcl_object_w3super IMPLEMENTATION. ENDMETHOD. "lif_object~delete + METHOD get_ext. + + rv_ext = find_param( it_params = it_params iv_name = c_param_names-fileext ). + SHIFT rv_ext LEFT DELETING LEADING '.'. + + ENDMETHOD. " get_ext. + + METHOD normalize_params. + + FIELD-SYMBOLS LIKE LINE OF ct_params. + + " Ensure filesize param exists + READ TABLE ct_params ASSIGNING WITH KEY name = c_param_names-filesize. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO ct_params ASSIGNING . + -name = c_param_names-filesize. + ENDIF. + + LOOP AT ct_params ASSIGNING . + -relid = ms_key-relid. " Ensure param key = object key + -objid = ms_key-objid. + IF -name = c_param_names-filesize. " Patch filesize = real file size + -value = iv_size. + CONDENSE -value. + ENDIF. + ENDLOOP. + + ENDMETHOD. " normalize_params. + + METHOD strip_params. + + FIELD-SYMBOLS LIKE LINE OF ct_params. + + " Remove path from filename + find_param( it_params = ct_params iv_name = c_param_names-filename ). " Check exists + READ TABLE ct_params ASSIGNING WITH KEY name = c_param_names-filename. + -value = lcl_path=>get_filename_from_syspath( |{ -value }| ). + + " Clear version & filesize + DELETE ct_params WHERE name = c_param_names-version. + DELETE ct_params WHERE name = c_param_names-filesize. + + ENDMETHOD. " strip_params. + + METHOD find_param. + + FIELD-SYMBOLS LIKE LINE OF it_params. + + READ TABLE it_params ASSIGNING WITH KEY name = iv_name. + IF sy-subrc > 0. + lcx_exception=>raise( |W3xx: Cannot find { iv_name } for { ms_key-objid }| ). + ENDIF. + + rv_value = -value. + + ENDMETHOD. " find_param. + + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_W3SUPER IMPLEMENTATION *----------------------------------------------------------------------* diff --git a/src/zabapgit_object_wdya.prog.abap b/src/zabapgit_object_wdya.prog.abap index 47953fccd..3d1defc49 100644 --- a/src/zabapgit_object_wdya.prog.abap +++ b/src/zabapgit_object_wdya.prog.abap @@ -34,6 +34,10 @@ ENDCLASS. "lcl_object_wdya DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_wdya IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -207,4 +211,8 @@ CLASS lcl_object_wdya IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_wdya IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_wdyn.prog.abap b/src/zabapgit_object_wdyn.prog.abap index 53e05e70a..41e34d645 100644 --- a/src/zabapgit_object_wdyn.prog.abap +++ b/src/zabapgit_object_wdyn.prog.abap @@ -68,6 +68,10 @@ ENDCLASS. "lcl_object_wdyn DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_wdyn IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -518,8 +522,8 @@ CLASS lcl_object_wdyn IMPLEMENTATION. ls_component_key TYPE wdy_md_component_key, ls_view_key TYPE wdy_md_view_key. - FIELD-SYMBOLS: LIKE LINE OF lt_objects. - + FIELD-SYMBOLS: LIKE LINE OF lt_objects, + LIKE LINE OF rs_component-ctlr_metadata. CLEAR mt_components. CLEAR mt_sources. @@ -546,6 +550,21 @@ CLASS lcl_object_wdyn IMPLEMENTATION. definition-component_name ASCENDING definition-controller_name ASCENDING. + LOOP AT rs_component-ctlr_metadata ASSIGNING . + SORT -descriptions. + SORT -controller_usages. + SORT -controller_components. + SORT -controller_component_texts. + SORT -controller_parameters. + SORT -controller_parameter_texts. + SORT -context_nodes. + SORT -context_attributes. + SORT -context_mappings. + SORT -fieldgroups. + SORT -controller_exceptions. + SORT -controller_exception_texts. + ENDLOOP. + SORT mt_components BY component_name ASCENDING controller_name ASCENDING @@ -643,4 +662,8 @@ CLASS lcl_object_wdyn IMPLEMENTATION. ENDMETHOD. "jump + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_wdyn IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_webi.prog.abap b/src/zabapgit_object_webi.prog.abap index 8c4026924..e3a690dbb 100644 --- a/src/zabapgit_object_webi.prog.abap +++ b/src/zabapgit_object_webi.prog.abap @@ -62,6 +62,10 @@ ENDCLASS. "lcl_object_SFBS DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_webi IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. "lif_object~changed_by @@ -439,4 +443,8 @@ CLASS lcl_object_webi IMPLEMENTATION. rs_metadata = get_metadata( ). ENDMETHOD. "lif_object~get_metadata + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_webi IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object_xslt.prog.abap b/src/zabapgit_object_xslt.prog.abap index 5afd418da..dc359b965 100644 --- a/src/zabapgit_object_xslt.prog.abap +++ b/src/zabapgit_object_xslt.prog.abap @@ -28,6 +28,10 @@ ENDCLASS. "lcl_object_xslt DEFINITION *----------------------------------------------------------------------* CLASS lcl_object_xslt IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. @@ -121,6 +125,8 @@ CLASS lcl_object_xslt IMPLEMENTATION. lcx_exception=>raise( 'error from cl_o2_api_xsltdesc=>create_new_from_string' ). ENDIF. + lo_xslt->activate( ). + lo_xslt->save( ). lo_xslt->set_changeable( abap_false ). @@ -182,4 +188,8 @@ CLASS lcl_object_xslt IMPLEMENTATION. rs_metadata = get_metadata( ). ENDMETHOD. "lif_object~get_metadata + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_object_xslt IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_objects.prog.abap b/src/zabapgit_objects.prog.abap index 1032af602..30887800b 100644 --- a/src/zabapgit_objects.prog.abap +++ b/src/zabapgit_objects.prog.abap @@ -25,6 +25,10 @@ CLASS lcl_objects_activation DEFINITION FINAL. CLASS-METHODS clear. PRIVATE SECTION. + CLASS-METHODS fix_class_methods + IMPORTING iv_obj_name TYPE trobj_name + CHANGING ct_objects TYPE dwinactiv_tab. + CLASS-DATA: gt_ddic TYPE TABLE OF dwinactiv, gt_programs TYPE TABLE OF dwinactiv. @@ -87,6 +91,40 @@ CLASS lcl_objects_activation IMPLEMENTATION. ENDMETHOD. "activate + METHOD fix_class_methods. +* function module RS_WORKING_OBJECTS_ACTIVATE assumes that +* METH lines contains spaces between class and method name +* however, classes named with 30 characters +* eg. ZCL_CLAS_TESTTESTTESTTESTTESTT +* this will not be true, so find all the method includes instead + + DATA: lt_methods TYPE seop_methods_w_include, + lv_class TYPE seoclsname. + + FIELD-SYMBOLS: LIKE LINE OF lt_methods, + LIKE LINE OF ct_objects. + + + lv_class = iv_obj_name. + + cl_oo_classname_service=>get_all_method_includes( + EXPORTING + clsname = lv_class + RECEIVING + result = lt_methods + EXCEPTIONS + class_not_existing = 1 + OTHERS = 2 ). + ASSERT sy-subrc = 0. + DELETE ct_objects WHERE object = 'METH'. + LOOP AT lt_methods ASSIGNING . + APPEND INITIAL LINE TO ct_objects ASSIGNING . + -object = 'METH'. + -obj_name = -incname. + ENDLOOP. + + ENDMETHOD. + METHOD add. * function group SEWORKINGAREA @@ -117,6 +155,11 @@ CLASS lcl_objects_activation IMPLEMENTATION. lcx_exception=>raise( 'Error from RS_INACTIVE_OBJECTS_IN_OBJECT' ). ENDIF. + IF iv_type = 'CLAS'. + fix_class_methods( EXPORTING iv_obj_name = lv_obj_name + CHANGING ct_objects = lt_objects ). + ENDIF. + APPEND LINES OF lt_objects TO gt_programs. WHEN 'DOMA' OR 'DTEL' OR 'TABL' OR 'INDX' OR 'TTYP' OR 'VIEW' OR 'SHLP' OR 'ENQU' @@ -187,16 +230,34 @@ CLASS lcl_objects_files DEFINITION FINAL. RAISING lcx_exception, add IMPORTING is_file TYPE ty_file, + add_raw + IMPORTING iv_extra TYPE clike OPTIONAL + iv_ext TYPE string + iv_data TYPE xstring + RAISING lcx_exception, + read_raw + IMPORTING iv_extra TYPE clike OPTIONAL + iv_ext TYPE string + RETURNING VALUE(rv_data) TYPE xstring + RAISING lcx_exception, get_files RETURNING VALUE(rt_files) TYPE ty_files_tt, set_files - IMPORTING it_files TYPE ty_files_tt. + IMPORTING it_files TYPE ty_files_tt, + get_accessed_files + RETURNING VALUE(rt_files) TYPE ty_file_signatures_tt. PRIVATE SECTION. - DATA: ms_item TYPE ty_item, - mt_files TYPE ty_files_tt. + DATA: ms_item TYPE ty_item, + mt_accessed_files TYPE ty_file_signatures_tt, + mt_files TYPE ty_files_tt. METHODS: + read_file + IMPORTING iv_filename TYPE string + iv_error TYPE abap_bool DEFAULT abap_true + EXPORTING ev_data TYPE xstring + RAISING lcx_exception, filename IMPORTING iv_extra TYPE clike OPTIONAL iv_ext TYPE string @@ -204,6 +265,31 @@ CLASS lcl_objects_files DEFINITION FINAL. ENDCLASS. "lcl_objects_files DEFINITION +INTERFACE lif_object_comparison_result. + METHODS: + show_confirmation_dialog, + is_result_complete_halt + RETURNING VALUE(rv_response) TYPE abap_bool. + +ENDINTERFACE. + +"Null Object Pattern +CLASS lcl_null_comparison_result DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES lif_object_comparison_result. +ENDCLASS. +CLASS lcl_null_comparison_result IMPLEMENTATION. + + METHOD lif_object_comparison_result~is_result_complete_halt. + rv_response = abap_false. + ENDMETHOD. + + METHOD lif_object_comparison_result~show_confirmation_dialog. + RETURN. + ENDMETHOD. + +ENDCLASS. + *----------------------------------------------------------------------* * INTERFACE lif_object DEFINITION *----------------------------------------------------------------------* @@ -230,7 +316,16 @@ INTERFACE lif_object. jump RAISING lcx_exception, get_metadata - RETURNING VALUE(rs_metadata) TYPE ty_metadata. + RETURNING VALUE(rs_metadata) TYPE ty_metadata, + has_changed_since + IMPORTING iv_timestamp TYPE timestamp + RETURNING VALUE(rv_changed) TYPE abap_bool + RAISING lcx_exception. + METHODS: + compare_to_remote_version + IMPORTING io_remote_version_xml TYPE REF TO lcl_xml_input + RETURNING VALUE(ro_comparison_result) TYPE REF TO lif_object_comparison_result + RAISING lcx_exception. DATA: mo_files TYPE REF TO lcl_objects_files. @@ -259,47 +354,44 @@ CLASS lcl_objects_files IMPLEMENTATION. mt_files = it_files. ENDMETHOD. "set_files + METHOD get_accessed_files. + rt_files = mt_accessed_files. + ENDMETHOD. " get_accessed_files. + METHOD read_string. - DATA: lv_filename TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF mt_files. - + DATA: lv_filename TYPE string, + lv_data TYPE xstring. lv_filename = filename( iv_extra = iv_extra iv_ext = iv_ext ). "#EC NOTEXT - READ TABLE mt_files ASSIGNING WITH KEY filename = lv_filename. - IF sy-subrc <> 0. - lcx_exception=>raise( 'html not found' ). - ENDIF. + read_file( EXPORTING iv_filename = lv_filename + IMPORTING ev_data = lv_data ). - rv_string = lcl_convert=>xstring_to_string_utf8( -data ). + rv_string = lcl_convert=>xstring_to_string_utf8( lv_data ). ENDMETHOD. "read_string METHOD read_abap. DATA: lv_filename TYPE string, + lv_data TYPE xstring, lv_abap TYPE string. - FIELD-SYMBOLS: LIKE LINE OF mt_files. - - - CLEAR rt_abap. lv_filename = filename( iv_extra = iv_extra iv_ext = 'abap' ). "#EC NOTEXT - READ TABLE mt_files ASSIGNING WITH KEY filename = lv_filename. - IF sy-subrc <> 0. - IF iv_error = abap_true. - lcx_exception=>raise( 'abap not found' ). - ELSE. - RETURN. - ENDIF. + read_file( EXPORTING iv_filename = lv_filename + iv_error = iv_error + IMPORTING ev_data = lv_data ). + + IF lv_data IS INITIAL. " Post-handling of iv_error = false + RETURN. ENDIF. - lv_abap = lcl_convert=>xstring_to_string_utf8( -data ). + + lv_abap = lcl_convert=>xstring_to_string_utf8( lv_data ). SPLIT lv_abap AT gc_newline INTO TABLE rt_abap. @@ -363,20 +455,16 @@ CLASS lcl_objects_files IMPLEMENTATION. METHOD read_xml. DATA: lv_filename TYPE string, + lv_data TYPE xstring, lv_xml TYPE string. - FIELD-SYMBOLS: LIKE LINE OF mt_files. - - lv_filename = filename( iv_extra = iv_extra iv_ext = 'xml' ). "#EC NOTEXT - READ TABLE mt_files ASSIGNING WITH KEY filename = lv_filename. - IF sy-subrc <> 0. - lcx_exception=>raise( 'xml not found' ). - ENDIF. + read_file( EXPORTING iv_filename = lv_filename + IMPORTING ev_data = lv_data ). - lv_xml = lcl_convert=>xstring_to_string_utf8( -data ). + lv_xml = lcl_convert=>xstring_to_string_utf8( lv_data ). CREATE OBJECT ro_xml EXPORTING @@ -425,6 +513,59 @@ CLASS lcl_objects_files IMPLEMENTATION. ENDMETHOD. "add_xml_from_plugin + METHOD read_file. + + FIELD-SYMBOLS: LIKE LINE OF mt_files, + LIKE LINE OF mt_accessed_files. + + CLEAR ev_data. + READ TABLE mt_files ASSIGNING WITH KEY filename = iv_filename. + + IF sy-subrc <> 0. + IF iv_error = abap_true. + lcx_exception=>raise( |File not found: { iv_filename }| ). + ELSE. + RETURN. + ENDIF. + ENDIF. + + " Update access table + READ TABLE mt_accessed_files TRANSPORTING NO FIELDS + WITH KEY path = -path filename = -filename. + IF sy-subrc > 0. " Not found ? -> Add + APPEND INITIAL LINE TO mt_accessed_files ASSIGNING . + MOVE-CORRESPONDING TO . + ENDIF. + + ev_data = -data. + + ENDMETHOD. " read_file. + + METHOD add_raw. + + DATA: ls_file TYPE ty_file. + + ls_file-path = '/'. + ls_file-data = iv_data. + ls_file-filename = filename( iv_extra = iv_extra + iv_ext = iv_ext ). + + APPEND ls_file TO mt_files. + + ENDMETHOD. "add_raw + + METHOD read_raw. + + DATA: lv_filename TYPE string. + + lv_filename = filename( iv_extra = iv_extra + iv_ext = iv_ext ). + + read_file( EXPORTING iv_filename = lv_filename + IMPORTING ev_data = rv_data ). + + ENDMETHOD. "read_raw + ENDCLASS. "lcl_objects_files IMPLEMENTATION *----------------------------------------------------------------------* @@ -435,16 +576,17 @@ ENDCLASS. "lcl_objects_files IMPLEMENTATION CLASS lcl_objects_super DEFINITION ABSTRACT. PUBLIC SECTION. + METHODS: constructor IMPORTING is_item TYPE ty_item iv_language TYPE spras. - PROTECTED SECTION. - CONSTANTS: c_user_unknown TYPE xubname VALUE 'UNKNOWN'. + PROTECTED SECTION. + DATA: ms_item TYPE ty_item, mv_language TYPE spras. @@ -497,6 +639,10 @@ ENDCLASS. "lcl_objects_bridge DEFINITION *----------------------------------------------------------------------* CLASS lcl_objects_bridge IMPLEMENTATION. + METHOD lif_object~has_changed_since. + rv_changed = abap_true. + ENDMETHOD. "lif_object~has_changed_since + METHOD lif_object~get_metadata. CALL METHOD mo_plugin->('ZIF_ABAPGIT_PLUGIN~GET_METADATA') @@ -646,6 +792,10 @@ CLASS lcl_objects_bridge IMPLEMENTATION. ENDMETHOD. "class_constructor + METHOD lif_object~compare_to_remote_version. + CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result. + ENDMETHOD. + ENDCLASS. "lcl_objects_bridge IMPLEMENTATION ********************************************************************** @@ -706,10 +856,11 @@ CLASS lcl_objects_program DEFINITION INHERITING FROM lcl_objects_super. RAISING lcx_exception. PROTECTED SECTION. + TYPES: ty_spaces_tt TYPE STANDARD TABLE OF i WITH DEFAULT KEY. TYPES: BEGIN OF ty_tpool. - INCLUDE TYPE textpool. + INCLUDE TYPE textpool. TYPES: split TYPE c LENGTH 8. TYPES: END OF ty_tpool. @@ -759,6 +910,12 @@ CLASS lcl_objects_program DEFINITION INHERITING FROM lcl_objects_super. is_cua TYPE ty_cua RAISING lcx_exception. + METHODS check_prog_changed_since + IMPORTING iv_program TYPE programm + iv_timestamp TYPE timestamp + iv_skip_gui TYPE abap_bool DEFAULT abap_false + RETURNING VALUE(rv_changed) TYPE abap_bool. + CLASS-METHODS: add_tpool IMPORTING it_tpool TYPE textpool_table @@ -880,8 +1037,10 @@ CLASS lcl_objects_program IMPLEMENTATION. ig_data = lt_dynpros ). ls_cua = serialize_cua( lv_program_name ). - lo_xml->add( iv_name = 'CUA' - ig_data = ls_cua ). + IF NOT ls_cua IS INITIAL. + lo_xml->add( iv_name = 'CUA' + ig_data = ls_cua ). + ENDIF. ENDIF. IF lines( lt_tpool ) = 1. @@ -1034,6 +1193,16 @@ CLASS lcl_objects_program IMPLEMENTATION. lcx_exception=>raise( 'PROG, error inserting' ). ENDIF. + SELECT SINGLE * FROM progdir INTO ls_progdir_new + WHERE name = ls_progdir_new-name + AND state = ls_progdir_new-state. + IF sy-subrc = 0 AND is_progdir-varcl = space AND ls_progdir_new-varcl = abap_true. +* function module UPDATE_PROGDIR does not update VARCL + UPDATE progdir SET varcl = is_progdir-varcl + WHERE name = ls_progdir_new-name + AND state = ls_progdir_new-state. + ENDIF. + lcl_objects_activation=>add( iv_type = 'REPS' iv_name = is_progdir-name ). @@ -1309,6 +1478,57 @@ CLASS lcl_objects_program IMPLEMENTATION. ENDMETHOD. "deserialize_cua + METHOD check_prog_changed_since. + + DATA: lv_date TYPE dats, + lv_time TYPE tims, + lv_ts TYPE timestamp, + lt_screens TYPE STANDARD TABLE OF d020s, + lt_eudb TYPE STANDARD TABLE OF eudb. + + FIELD-SYMBOLS: LIKE LINE OF lt_screens, + LIKE LINE OF lt_eudb. + + SELECT SINGLE udat utime FROM reposrc " Program + INTO (lv_date, lv_time) + WHERE progname = iv_program + AND r3state = 'A'. + + _object_check_timestamp lv_date lv_time. + + SELECT SINGLE udat utime FROM repotext " Program text pool + INTO (lv_date, lv_time) + WHERE progname = iv_program + AND r3state = 'A'. + + IF sy-subrc = 0. " Text not found ? Assuming no changes, see #404 + _object_check_timestamp lv_date lv_time. + ENDIF. + + IF iv_skip_gui = abap_true. + RETURN. + ENDIF. + + SELECT dgen tgen FROM d020s " Screens + INTO CORRESPONDING FIELDS OF TABLE lt_screens + WHERE prog = iv_program ##TOO_MANY_ITAB_FIELDS. + + LOOP AT lt_screens ASSIGNING . + _object_check_timestamp -dgen -tgen. + ENDLOOP. + + SELECT vdatum vzeit FROM eudb " GUI + INTO CORRESPONDING FIELDS OF TABLE lt_eudb + WHERE relid = 'CU' + AND name = iv_program + AND srtf2 = 0 ##TOO_MANY_ITAB_FIELDS. + + LOOP AT lt_eudb ASSIGNING . + _object_check_timestamp -vdatum -vzeit. + ENDLOOP. + + ENDMETHOD. "check_prog_changed_since + ENDCLASS. "lcl_objects_program IMPLEMENTATION *----------------------------------------------------------------------* @@ -1411,6 +1631,12 @@ CLASS lcl_objects DEFINITION FINAL. PUBLIC SECTION. TYPES: ty_types_tt TYPE STANDARD TABLE OF tadir-object WITH DEFAULT KEY. + TYPES: BEGIN OF ty_late, + obj TYPE REF TO lif_object, + xml TYPE REF TO lcl_xml_input, + package TYPE devclass, + END OF ty_late. + CLASS-METHODS serialize IMPORTING is_item TYPE ty_item iv_language TYPE spras @@ -1419,7 +1645,8 @@ CLASS lcl_objects DEFINITION FINAL. RAISING lcx_exception. CLASS-METHODS deserialize - IMPORTING io_repo TYPE REF TO lcl_repo + IMPORTING io_repo TYPE REF TO lcl_repo + RETURNING VALUE(rt_accessed_files) TYPE ty_file_signatures_tt RAISING lcx_exception. CLASS-METHODS delete @@ -1435,8 +1662,15 @@ CLASS lcl_objects DEFINITION FINAL. RETURNING VALUE(rv_user) TYPE xubname RAISING lcx_exception. + CLASS-METHODS has_changed_since + IMPORTING is_item TYPE ty_item + iv_timestamp TYPE timestamp + RETURNING VALUE(rv_changed) TYPE abap_bool + RAISING lcx_exception. + CLASS-METHODS is_supported IMPORTING is_item TYPE ty_item + iv_native_only TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_bool) TYPE abap_bool. CLASS-METHODS exists @@ -1446,16 +1680,24 @@ CLASS lcl_objects DEFINITION FINAL. CLASS-METHODS supported_list RETURNING VALUE(rt_types) TYPE ty_types_tt. + CLASS-METHODS is_language_installed + IMPORTING iv_language TYPE langu + RETURNING VALUE(rv_yes) TYPE abap_bool. + PRIVATE SECTION. + + CLASS-DATA: mv_langs_installed TYPE scplangs. + CLASS-METHODS check_duplicates IMPORTING it_files TYPE ty_files_tt RAISING lcx_exception. CLASS-METHODS create_object - IMPORTING is_item TYPE ty_item - iv_language TYPE spras - is_metadata TYPE ty_metadata OPTIONAL - RETURNING VALUE(ri_obj) TYPE REF TO lif_object + IMPORTING is_item TYPE ty_item + iv_language TYPE spras + is_metadata TYPE ty_metadata OPTIONAL + iv_native_only TYPE abap_bool DEFAULT abap_false + RETURNING VALUE(ri_obj) TYPE REF TO lif_object RAISING lcx_exception. CLASS-METHODS @@ -1497,4 +1739,12 @@ CLASS lcl_objects DEFINITION FINAL. IMPORTING is_item TYPE ty_item RAISING lcx_exception. + CLASS-METHODS compare_remote_to_local + IMPORTING + io_object TYPE REF TO lif_object + it_remote TYPE ty_files_tt + is_result TYPE ty_result + RAISING + lcx_exception. + ENDCLASS. "lcl_object DEFINITION \ No newline at end of file diff --git a/src/zabapgit_objects_impl.prog.abap b/src/zabapgit_objects_impl.prog.abap new file mode 100644 index 000000000..c90be83ba --- /dev/null +++ b/src/zabapgit_objects_impl.prog.abap @@ -0,0 +1,728 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_OBJECT +*&---------------------------------------------------------------------* + +*----------------------------------------------------------------------* +* CLASS lcl_objects IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_objects IMPLEMENTATION. + + METHOD warning_overwrite. + + DATA: lv_index TYPE i, + lv_answer TYPE c, + lv_question TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF ct_results. + + + LOOP AT ct_results ASSIGNING + WHERE NOT obj_type IS INITIAL. + + lv_index = sy-tabix. + + IF -lstate IS NOT INITIAL + AND -lstate <> gc_state-deleted + AND NOT ( -lstate = gc_state-added + AND -rstate IS INITIAL ). + lv_question = |It looks like object { + -obj_type } { -obj_name + } has been modified locally, overwrite object?|. + + lv_answer = lcl_popups=>popup_to_confirm( + titlebar = 'Warning' + text_question = lv_question + display_cancel_button = abap_false ). "#EC NOTEXT + + IF lv_answer = '2'. + DELETE ct_results INDEX lv_index. + ENDIF. + + ENDIF. + + ENDLOOP. + + ENDMETHOD. + + METHOD warning_package. + + DATA: lv_question TYPE c LENGTH 200, + lv_answer TYPE c, + ls_tadir TYPE tadir. + + + ls_tadir = lcl_tadir=>read_single( iv_object = is_item-obj_type + iv_obj_name = is_item-obj_name ). + IF NOT ls_tadir IS INITIAL AND ls_tadir-devclass <> iv_package. + CONCATENATE 'Overwrite object' is_item-obj_type is_item-obj_name + 'from package' ls_tadir-devclass + INTO lv_question SEPARATED BY space. "#EC NOTEXT + + lv_answer = lcl_popups=>popup_to_confirm( + titlebar = 'Warning' + text_question = lv_question + text_button_1 = 'Ok' + icon_button_1 = 'ICON_DELETE' + text_button_2 = 'Cancel' + icon_button_2 = 'ICON_CANCEL' + default_button = '2' + display_cancel_button = abap_false ). "#EC NOTEXT + + IF lv_answer = '2'. + rv_cancel = abap_true. + ENDIF. + + ENDIF. + + ENDMETHOD. "check_warning + + METHOD update_package_tree. + + DATA: lt_packages TYPE lcl_sap_package=>ty_devclass_tt, + lv_package LIKE LINE OF lt_packages, + lv_tree TYPE dirtree-tname. + + + lt_packages = lcl_sap_package=>list_subpackages( iv_package ). + APPEND iv_package TO lt_packages. + + LOOP AT lt_packages INTO lv_package. +* update package tree for SE80 + lv_tree = 'EU_' && lv_package. + CALL FUNCTION 'WB_TREE_ACTUALIZE' + EXPORTING + tree_name = lv_tree + without_crossreference = abap_true + with_tcode_index = abap_true. + ENDLOOP. + + ENDMETHOD. "update_package_tree + + METHOD create_object. + + TYPES: BEGIN OF ty_obj_serializer_map, + item LIKE is_item, + metadata LIKE is_metadata, + END OF ty_obj_serializer_map. + + STATICS st_obj_serializer_map + TYPE SORTED TABLE OF ty_obj_serializer_map WITH UNIQUE KEY item. + + DATA: lv_message TYPE string, + lv_class_name TYPE string, + ls_obj_serializer_map LIKE LINE OF st_obj_serializer_map. + + + READ TABLE st_obj_serializer_map + INTO ls_obj_serializer_map WITH KEY item = is_item. + IF sy-subrc = 0. + lv_class_name = ls_obj_serializer_map-metadata-class. + ELSEIF is_metadata IS NOT INITIAL. +* Metadata is provided only on serialization +* Once this has been triggered, the same serializer shall be used +* for subsequent processes. +* Thus, buffer the metadata afterwards + ls_obj_serializer_map-item = is_item. + ls_obj_serializer_map-metadata = is_metadata. + INSERT ls_obj_serializer_map INTO TABLE st_obj_serializer_map. + + lv_class_name = is_metadata-class. + ELSE. + lv_class_name = class_name( is_item ). + ENDIF. + + TRY. + CREATE OBJECT ri_obj TYPE (lv_class_name) + EXPORTING + is_item = is_item + iv_language = iv_language. + CATCH cx_sy_create_object_error. + lv_message = |Object type { is_item-obj_type } not supported, serialize|. "#EC NOTEXT + IF iv_native_only = abap_false. + TRY. " 2nd step, try looking for plugins + CREATE OBJECT ri_obj TYPE lcl_objects_bridge + EXPORTING + is_item = is_item. + CATCH cx_sy_create_object_error. + lcx_exception=>raise( lv_message ). + ENDTRY. + ELSE. " No native support? -> fail + lcx_exception=>raise( lv_message ). + ENDIF. + ENDTRY. + + ENDMETHOD. "create_object + + METHOD has_changed_since. + rv_changed = abap_true. " Assume changed + + IF is_supported( is_item ) = abap_false. + RETURN. " Will requre serialize which will log the error + ENDIF. + + rv_changed = create_object( + is_item = is_item + iv_language = gc_english )->has_changed_since( iv_timestamp ). + + ENDMETHOD. "has_changed_since + + METHOD is_supported. + + TRY. + create_object( is_item = is_item + iv_language = gc_english + iv_native_only = iv_native_only ). + rv_bool = abap_true. + CATCH lcx_exception. + rv_bool = abap_false. + ENDTRY. + + ENDMETHOD. "is_supported + + METHOD supported_list. + + DATA: lv_type LIKE LINE OF rt_types, + lt_snode TYPE TABLE OF snode. + + FIELD-SYMBOLS: LIKE LINE OF lt_snode. + + + CALL FUNCTION 'WB_TREE_ACTUALIZE' + EXPORTING + tree_name = 'PG_ZABAPGIT' + without_crossreference = abap_true + with_tcode_index = abap_true + TABLES + p_tree = lt_snode. + + DELETE lt_snode WHERE type <> 'OPL' + OR name NP 'LCL_OBJECT_++++'. + + LOOP AT lt_snode ASSIGNING . + lv_type = -name+11. + APPEND lv_type TO rt_types. + ENDLOOP. + + ENDMETHOD. "supported_list + + METHOD is_language_installed. + + IF mv_langs_installed IS INITIAL. + CALL FUNCTION 'RSAQ_READ_INSTALLED_LANGUAGES' + IMPORTING + inst_languages = mv_langs_installed. + ENDIF. + + rv_yes = boolc( mv_langs_installed CA iv_language ). + + ENDMETHOD. "is_language_installed + + METHOD exists. + + DATA: li_obj TYPE REF TO lif_object. + + + TRY. + li_obj = create_object( is_item = is_item + iv_language = gc_english ). + rv_bool = li_obj->exists( ). + CATCH lcx_exception. +* ignore all errors and assume the object exists + rv_bool = abap_true. + ENDTRY. + + ENDMETHOD. "exists + + METHOD path_to_package. + + DATA: lv_length TYPE i, + lv_path TYPE string. + + + lv_length = strlen( iv_start ) - 1. + lv_path = iv_path+lv_length. + + CONCATENATE iv_top lv_path INTO rv_package. + + TRANSLATE rv_package USING '/_'. + + lv_length = strlen( rv_package ) - 1. + + rv_package = rv_package(lv_length). + + TRANSLATE rv_package TO UPPER CASE. + + IF lcl_sap_package=>exists( rv_package ) = abap_false. + lcl_sap_package=>create_child( iv_parent = iv_top + iv_child = rv_package ). + ENDIF. + + ENDMETHOD. + + METHOD class_name. + + CONCATENATE 'LCL_OBJECT_' is_item-obj_type INTO rv_class_name. "#EC NOTEXT + + ENDMETHOD. "class_name + + METHOD jump. + + DATA: li_obj TYPE REF TO lif_object. + + + li_obj = create_object( is_item = is_item + iv_language = gc_english ). + + li_obj->jump( ). + + ENDMETHOD. "jump + + METHOD changed_by. + + DATA: li_obj TYPE REF TO lif_object. + + + IF is_item IS INITIAL. +* eg. ".abapgit.xml" file + rv_user = lcl_objects_super=>c_user_unknown. + ELSE. + li_obj = create_object( is_item = is_item + iv_language = gc_english ). + rv_user = li_obj->changed_by( ). + ENDIF. + + ASSERT NOT rv_user IS INITIAL. + +* todo, fallback to looking at transports if rv_user = 'UNKNOWN'? + + ENDMETHOD. + + METHOD delete. + + DATA: ls_item TYPE ty_item, + lv_tabclass TYPE dd02l-tabclass, + lt_tadir LIKE it_tadir. + + FIELD-SYMBOLS: LIKE LINE OF it_tadir. + + +* misuse field KORRNUM to fix deletion sequence + + lt_tadir[] = it_tadir[]. + + LOOP AT lt_tadir ASSIGNING . + CASE -object. + WHEN 'IATU'. + -korrnum = '5500'. + WHEN 'IARP'. + -korrnum = '5510'. + WHEN 'IASP'. + -korrnum = '5520'. + WHEN 'SUSC'. + -korrnum = '5000'. + WHEN 'TTYP' OR 'TABL' OR 'VIEW'. + SELECT SINGLE tabclass FROM dd02l + INTO lv_tabclass + WHERE tabname = -obj_name + AND as4local = 'A' + AND as4vers = '0000'. + IF sy-subrc = 0 AND lv_tabclass = 'APPEND'. +* delete append structures before database tables + -korrnum = '6500'. + ELSE. + -korrnum = '7000'. + ENDIF. + WHEN 'DTEL'. + -korrnum = '8000'. + WHEN 'DOMA'. + -korrnum = '9000'. + WHEN 'PROG'. +* delete includes after main programs + SELECT COUNT(*) FROM reposrc + WHERE progname = -obj_name + AND r3state = 'A' + AND subc = 'I'. + IF sy-subrc = 0. + -korrnum = '2000'. + ELSE. + -korrnum = '1000'. + ENDIF. + WHEN OTHERS. + -korrnum = '1000'. + ENDCASE. + ENDLOOP. + + resolve_ddic( CHANGING ct_tadir = lt_tadir ). + + SORT lt_tadir BY korrnum ASCENDING. + + LOOP AT lt_tadir ASSIGNING . + lcl_progress=>show( iv_key = 'Delete' + iv_current = sy-tabix + iv_total = lines( lt_tadir ) + iv_text = -obj_name ) ##NO_TEXT. + + CLEAR ls_item. + ls_item-obj_type = -object. + ls_item-obj_name = -obj_name. + delete_obj( ls_item ). + ENDLOOP. + + ENDMETHOD. "delete + + METHOD resolve_ddic. +* this will make sure the deletion sequence of structures/tables work +* in case they have dependencies with .INCLUDE + + TYPES: BEGIN OF ty_edge, + from TYPE ty_item, + to TYPE ty_item, + END OF ty_edge. + + DATA: lt_nodes TYPE TABLE OF ty_item, + lt_edges TYPE TABLE OF ty_edge, + lt_findstrings TYPE TABLE OF rsfind, + lv_plus TYPE i VALUE 1, + lv_find_obj_cls TYPE euobj-id, + lv_index TYPE i, + lv_before TYPE i, + lt_founds TYPE TABLE OF rsfindlst, + lt_scope TYPE STANDARD TABLE OF seu_obj. + + FIELD-SYMBOLS: LIKE LINE OF ct_tadir, + LIKE LINE OF lt_edges, + LIKE LINE OF lt_founds, + LIKE LINE OF lt_nodes. + + +* build nodes + LOOP AT ct_tadir ASSIGNING + WHERE object = 'TABL' + OR object = 'TTYP'. + APPEND INITIAL LINE TO lt_nodes ASSIGNING . + -obj_name = -obj_name. + -obj_type = -object. + ENDLOOP. + + APPEND 'TABL' TO lt_scope. + APPEND 'STRU' TO lt_scope. + APPEND 'TTYP' TO lt_scope. + +* build edges + LOOP AT lt_nodes ASSIGNING . + + CLEAR lt_findstrings. + APPEND -obj_name TO lt_findstrings. + lv_find_obj_cls = -obj_type. + + CALL FUNCTION 'RS_EU_CROSSREF' + EXPORTING + i_find_obj_cls = lv_find_obj_cls + TABLES + i_findstrings = lt_findstrings + o_founds = lt_founds + i_scope_object_cls = lt_scope + EXCEPTIONS + not_executed = 1 + not_found = 2 + illegal_object = 3 + no_cross_for_this_object = 4 + batch = 5 + batchjob_error = 6 + wrong_type = 7 + object_not_exist = 8 + OTHERS = 9. + IF sy-subrc <> 0. + CONTINUE. + ENDIF. + + LOOP AT lt_founds ASSIGNING . + APPEND INITIAL LINE TO lt_edges ASSIGNING . + -from = . + + -to-obj_name = -object. + CASE -object_cls. + WHEN 'DS' + OR 'DT'. + -to-obj_type = 'TABL'. + WHEN 'DA'. + -to-obj_type = 'TTYP'. + WHEN OTHERS. + lcx_exception=>raise( 'resolve_ddic, unknown object_cls' ). + ENDCASE. + ENDLOOP. + + ENDLOOP. + + DO. + lv_before = lines( lt_nodes ). + LOOP AT lt_nodes ASSIGNING . + lv_index = sy-tabix. + READ TABLE lt_edges WITH KEY + from-obj_name = -obj_name + from-obj_type = -obj_type + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + LOOP AT ct_tadir ASSIGNING + WHERE obj_name = -obj_name + AND object = -obj_type. + -korrnum = -korrnum + lv_plus. + CONDENSE -korrnum. + ENDLOOP. + DELETE lt_edges + WHERE to-obj_name = -obj_name + AND to-obj_type = -obj_type. + DELETE lt_nodes INDEX lv_index. + EXIT. " make sure the sequence is fixed + ENDIF. + ENDLOOP. + IF lv_before = lines( lt_nodes ). + EXIT. + ENDIF. + lv_plus = lv_plus + 1. + ENDDO. + + ENDMETHOD. "resolve_ddic + + METHOD delete_obj. + + DATA: li_obj TYPE REF TO lif_object. + + + IF is_supported( is_item ) = abap_true. + li_obj = create_object( is_item = is_item + iv_language = gc_english ). + + li_obj->delete( ). + + IF li_obj->get_metadata( )-delete_tadir = abap_true. + CALL FUNCTION 'TR_TADIR_INTERFACE' + EXPORTING + wi_delete_tadir_entry = abap_true + wi_tadir_pgmid = 'R3TR' + wi_tadir_object = is_item-obj_type + wi_tadir_obj_name = is_item-obj_name + wi_test_modus = abap_false. + ENDIF. + ENDIF. + + ENDMETHOD. "delete + + METHOD serialize. + + DATA: li_obj TYPE REF TO lif_object, + lo_xml TYPE REF TO lcl_xml_output, + lo_files TYPE REF TO lcl_objects_files. + + + IF is_supported( is_item ) = abap_false. + IF NOT io_log IS INITIAL. + io_log->add( iv_msgv1 = 'Object type ignored, not supported:' + iv_msgv2 = is_item-obj_type + iv_msgv3 = '-' + iv_msgv4 = is_item-obj_name ) ##no_text. + ENDIF. + RETURN. + ENDIF. + + CREATE OBJECT lo_files + EXPORTING + is_item = is_item. + + li_obj = create_object( is_item = is_item + iv_language = iv_language ). + li_obj->mo_files = lo_files. + CREATE OBJECT lo_xml. + li_obj->serialize( lo_xml ). + lo_files->add_xml( io_xml = lo_xml + is_metadata = li_obj->get_metadata( ) ). + + rt_files = lo_files->get_files( ). + + check_duplicates( rt_files ). + + ENDMETHOD. "serialize + + METHOD check_duplicates. + + DATA: lt_files TYPE ty_files_tt. + + + lt_files[] = it_files[]. + SORT lt_files BY path ASCENDING filename ASCENDING. + DELETE ADJACENT DUPLICATES FROM lt_files COMPARING path filename. + IF lines( lt_files ) <> lines( it_files ). + lcx_exception=>raise( 'Duplicates' ). + ENDIF. + + ENDMETHOD. + + METHOD prioritize_deser. + + FIELD-SYMBOLS: LIKE LINE OF it_results. + +* XSLT has to be handled before CLAS/PROG + LOOP AT it_results ASSIGNING WHERE obj_type = 'XSLT'. + APPEND TO rt_results. + ENDLOOP. + +* PROG before internet services, as the services might use the screens + LOOP AT it_results ASSIGNING WHERE obj_type = 'PROG'. + APPEND TO rt_results. + ENDLOOP. + +* ISAP has to be handled before ISRP + LOOP AT it_results ASSIGNING WHERE obj_type = 'IASP'. + APPEND TO rt_results. + ENDLOOP. + + LOOP AT it_results ASSIGNING + WHERE obj_type <> 'IASP' + AND obj_type <> 'PROG' + AND obj_type <> 'XSLT'. + APPEND TO rt_results. + ENDLOOP. + + ENDMETHOD. "prioritize_deser + + METHOD deserialize. + + DATA: ls_item TYPE ty_item, + lv_cancel TYPE abap_bool, + li_obj TYPE REF TO lif_object, + lt_remote TYPE ty_files_tt, + lv_package TYPE devclass, + lo_files TYPE REF TO lcl_objects_files, + lo_xml TYPE REF TO lcl_xml_input, + lt_results TYPE ty_results_tt, + lt_late TYPE TABLE OF ty_late. + + FIELD-SYMBOLS: TYPE ty_result, + LIKE LINE OF lt_late. + + + lcl_objects_activation=>clear( ). + + lt_remote = io_repo->get_files_remote( ). + + lt_results = lcl_file_status=>status( io_repo ). + DELETE lt_results WHERE + match = abap_true. " Full match +* OR rstate IS INITIAL. " no remote changes, only local + SORT lt_results BY obj_type ASCENDING obj_name ASCENDING. + DELETE ADJACENT DUPLICATES FROM lt_results COMPARING obj_type obj_name. + + lt_results = prioritize_deser( lt_results ). + + warning_overwrite( EXPORTING io_repo = io_repo + CHANGING ct_results = lt_results ). + + LOOP AT lt_results ASSIGNING WHERE obj_type IS NOT INITIAL + AND NOT ( lstate = gc_state-added AND rstate IS INITIAL ). + lcl_progress=>show( iv_key = 'Deserialize' + iv_current = sy-tabix + iv_total = lines( lt_results ) + iv_text = -obj_name ) ##NO_TEXT. + + CLEAR ls_item. + ls_item-obj_type = -obj_type. + ls_item-obj_name = -obj_name. +* handle namespaces + REPLACE ALL OCCURRENCES OF '#' IN ls_item-obj_name WITH '/'. + + lv_package = path_to_package( + iv_top = io_repo->get_package( ) + iv_start = io_repo->get_dot_abapgit( )->get_starting_folder( ) + iv_path = -path ). + + lv_cancel = warning_package( is_item = ls_item + iv_package = lv_package ). + IF lv_cancel = abap_true. + lcx_exception=>raise( 'cancelled' ). + ENDIF. + + CREATE OBJECT lo_files + EXPORTING + is_item = ls_item. + lo_files->set_files( lt_remote ). + +* Analyze XML in order to instantiate the proper serializer + lo_xml = lo_files->read_xml( ). + + li_obj = create_object( is_item = ls_item + iv_language = io_repo->get_master_language( ) + is_metadata = lo_xml->get_metadata( ) ). + + compare_remote_to_local( + io_object = li_obj + it_remote = lt_remote + is_result = ). + + li_obj->mo_files = lo_files. + + IF li_obj->get_metadata( )-late_deser = abap_true. + APPEND INITIAL LINE TO lt_late ASSIGNING . + -obj = li_obj. + -xml = lo_xml. + -package = lv_package. + CONTINUE. + ENDIF. + + + li_obj->deserialize( iv_package = lv_package + io_xml = lo_xml ). + + " Remember accessed files + APPEND LINES OF lo_files->get_accessed_files( ) TO rt_accessed_files. + ENDLOOP. + + lcl_objects_activation=>activate( ). + + LOOP AT lt_late ASSIGNING . + -obj->deserialize( iv_package = -package + io_xml = -xml ). + ENDLOOP. + + update_package_tree( io_repo->get_package( ) ). + + SORT rt_accessed_files BY path ASCENDING filename ASCENDING. + DELETE ADJACENT DUPLICATES FROM rt_accessed_files. " Just in case + + ENDMETHOD. "deserialize + + + METHOD compare_remote_to_local. + + DATA: ls_remote_file TYPE ty_file, + lo_remote_version TYPE REF TO lcl_xml_input, + lo_comparison_result TYPE REF TO lif_object_comparison_result. + + + IF is_result-filename CS '.XML'. + IF io_object->exists( ) = abap_false. + RETURN. + ENDIF. + + READ TABLE it_remote WITH KEY filename = is_result-filename INTO ls_remote_file. + + "if file does not exist in remote, we don't need to validate + IF sy-subrc = 0. + CREATE OBJECT lo_remote_version + EXPORTING + iv_xml = lcl_convert=>xstring_to_string_utf8( ls_remote_file-data ). + lo_comparison_result = io_object->compare_to_remote_version( lo_remote_version ). + lo_comparison_result->show_confirmation_dialog( ). + + IF lo_comparison_result->is_result_complete_halt( ) = abap_true. + RAISE EXCEPTION TYPE lcx_exception + EXPORTING + iv_text = 'Deserialization aborted by user'. + ENDIF. + ENDIF. + ENDIF. + + ENDMETHOD. + +ENDCLASS. "lcl_objects IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_object.prog.xml b/src/zabapgit_objects_impl.prog.xml similarity index 95% rename from src/zabapgit_object.prog.xml rename to src/zabapgit_objects_impl.prog.xml index a49cedadd..f426626b7 100644 --- a/src/zabapgit_object.prog.xml +++ b/src/zabapgit_objects_impl.prog.xml @@ -3,7 +3,7 @@ - ZABAPGIT_OBJECT + ZABAPGIT_OBJECTS_IMPL A diff --git a/src/zabapgit_page.prog.abap b/src/zabapgit_page.prog.abap index 47b5564cc..0f5d31f6f 100644 --- a/src/zabapgit_page.prog.abap +++ b/src/zabapgit_page.prog.abap @@ -8,26 +8,28 @@ INTERFACE lif_gui_page. METHODS on_event - 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. + IMPORTING iv_action TYPE clike + iv_prev_page 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 lcx_cancel. METHODS render RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper RAISING lcx_exception. - METHODS get_assets - RETURNING VALUE(rt_assets) TYPE tt_web_assets. - ENDINTERFACE. CLASS lcl_gui_page_super DEFINITION ABSTRACT. PUBLIC SECTION. INTERFACES lif_gui_page ABSTRACT METHODS render. + CLASS-METHODS render_error + IMPORTING ix_error TYPE REF TO lcx_exception + RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. + PROTECTED SECTION. METHODS render_repo_top IMPORTING io_repo TYPE REF TO lcl_repo @@ -38,6 +40,11 @@ CLASS lcl_gui_page_super DEFINITION ABSTRACT. RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper RAISING lcx_exception. + METHODS render_item_state + IMPORTING iv1 TYPE char1 + iv2 TYPE char1 + RETURNING VALUE(rv_html) TYPE string. + METHODS render_branch_span IMPORTING iv_branch TYPE string io_repo TYPE REF TO lcl_repo_online @@ -62,9 +69,6 @@ CLASS lcl_gui_page_super DEFINITION ABSTRACT. IMPORTING iv_url TYPE string RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. - PRIVATE SECTION. - METHODS styles RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. - ENDCLASS. CLASS lcl_gui_page_super IMPLEMENTATION. @@ -72,10 +76,12 @@ CLASS lcl_gui_page_super IMPLEMENTATION. METHOD render_repo_top. DATA: lo_repo_online TYPE REF TO lcl_repo_online, + lo_pback TYPE REF TO lcl_persistence_background, lv_icon TYPE string. CREATE OBJECT ro_html. + CREATE OBJECT lo_pback. IF io_repo->is_offline( ) = abap_true. lv_icon = 'img/repo_offline' ##NO_TEXT. @@ -97,10 +103,26 @@ CLASS lcl_gui_page_super IMPLEMENTATION. ro_html->add( '' ). + IF abap_true = lcl_app=>user( )->is_favorite_repo( io_repo->get_key( ) ). + lv_icon = 'img/star' ##NO_TEXT. + ELSE. + lv_icon = 'img/star-grey' ##NO_TEXT. + ENDIF. + lv_icon = ||. + ro_html->add_anchor( iv_act = |{ gc_action-repo_toggle_fav }?{ io_repo->get_key( ) }| + iv_txt = lv_icon ). + + IF lo_pback->exists( io_repo->get_key( ) ) = abap_true. + ro_html->add( 'BG' ). + ENDIF. + + IF io_repo->is_write_protected( ) = abap_true. + ro_html->add( '' ). + ENDIF. + IF io_repo->is_offline( ) = abap_false. lo_repo_online ?= io_repo. IF iv_show_branch = abap_true. - ro_html->add( '' ). IF iv_branch IS INITIAL. ro_html->add( render_branch_span( iv_branch = lo_repo_online->get_branch_name( ) io_repo = lo_repo_online @@ -115,7 +137,10 @@ CLASS lcl_gui_page_super IMPLEMENTATION. IF iv_show_package = abap_true. ro_html->add( '' ). - ro_html->add( |{ io_repo->get_package( ) }| ). + ro_html->add( '' ). + ro_html->add_anchor( iv_txt = io_repo->get_package( ) + iv_act = |{ gc_action-jump_pkg }?{ io_repo->get_package( ) }| ). + ro_html->add( '' ). ENDIF. ro_html->add( '' ). @@ -123,27 +148,71 @@ CLASS lcl_gui_page_super IMPLEMENTATION. ENDMETHOD. + METHOD render_item_state. + + DATA: lv_system TYPE string. + + FIELD-SYMBOLS TYPE char1. + + + rv_html = ''. + + DO 2 TIMES. + CASE sy-index. + WHEN 1. + ASSIGN iv1 TO . + lv_system = 'Local:'. + WHEN 2. + ASSIGN iv2 TO . + lv_system = 'Remote:'. + ENDCASE. + + CASE . + WHEN gc_state-unchanged. "None or unchanged + IF iv1 = gc_state-added OR iv2 = gc_state-added. + rv_html = rv_html && |X|. + ELSE. + rv_html = rv_html && | |. + ENDIF. + WHEN gc_state-modified. "Changed + rv_html = rv_html && |M|. + WHEN gc_state-added. "Added new + rv_html = rv_html && |A|. + WHEN gc_state-mixed. "Multiple changes (multifile) + rv_html = rv_html && ||. + WHEN gc_state-deleted. "Deleted + rv_html = rv_html && |D|. + ENDCASE. + ENDDO. + + rv_html = rv_html && ''. + + ENDMETHOD. "render_item_state + METHOD render_branch_span. DATA: lv_text TYPE string, lv_class TYPE string. lv_text = lcl_git_branch_list=>get_display_name( iv_branch ). - CASE lcl_git_branch_list=>get_type( iv_branch ). "TODO - WHEN lcl_git_branch_list=>c_type-branch. - WHEN lcl_git_branch_list=>c_type-tag. - WHEN OTHERS. - ENDCASE. + IF iv_branch = io_repo->get_head_branch_name( ) OR iv_branch = lcl_git_branch_list=>head_name. + lv_class = 'branch branch_head'. + ELSEIF lcl_git_branch_list=>get_type( iv_branch ) = lcl_git_branch_list=>c_type-branch. + lv_class = 'branch branch_branch'. + ELSE. + lv_class = 'branch'. + ENDIF. CREATE OBJECT ro_html. + ro_html->add( || ). + ro_html->add( '' ). IF iv_interactive = abap_true. - ro_html->add( || ). - ro_html->add_anchor( iv_act = |switch_branch?{ io_repo->get_key( ) }| - iv_txt = lv_text ). "TODO refactor - ro_html->add( '' ). + ro_html->add_anchor( iv_act = |{ gc_action-git_branch_switch }?{ io_repo->get_key( ) }| + iv_txt = lv_text ). ELSE. - ro_html->add( |{ lv_text }| ). + ro_html->add( lv_text ). ENDIF. + ro_html->add( '' ). ENDMETHOD. "render_branch_span @@ -155,15 +224,9 @@ CLASS lcl_gui_page_super IMPLEMENTATION. ro_html->add( '' ). "#EC NOTEXT ro_html->add( '' ). "#EC NOTEXT ro_html->add( 'abapGit' ). "#EC NOTEXT - ro_html->add( styles( ) ). - - IF io_include_style IS BOUND. - ro_html->add( '' ). "#EC NOTEXT - ENDIF. - + ro_html->add( '' ). ro_html->add( '' ). "#EC NOTEXT + ro_html->add( '' ). "#EC NOTEXT ro_html->add( '' ). "#EC NOTEXT ro_html->add( '' ). "#EC NOTEXT @@ -177,7 +240,7 @@ CLASS lcl_gui_page_super IMPLEMENTATION. ro_html->add( '' ). "#EC NOTEXT ro_html->add( '' ). "#EC NOTEXT @@ -203,13 +266,16 @@ CLASS lcl_gui_page_super IMPLEMENTATION. ro_html->add( '
' ). "#EC NOTEXT ro_html->add( |{ gc_abap_version }| ). "#EC NOTEXT + ro_html->add( '
' ). "#EC NOTEXT ro_html->add( '' ). "#EC NOTEXT ro_html->add( '' ). "#EC NOTEXT IF io_include_script IS BOUND. ro_html->add( '' ). ENDIF. @@ -217,6 +283,16 @@ CLASS lcl_gui_page_super IMPLEMENTATION. ENDMETHOD. "render html footer & logo + METHOD render_error. + + CREATE OBJECT ro_html. + + ro_html->add( '
' ). + ro_html->add( |Error: { ix_error->mv_text }| ). + ro_html->add( '
' ). + + ENDMETHOD. "render_error + METHOD redirect. CREATE OBJECT ro_html. @@ -228,285 +304,6 @@ CLASS lcl_gui_page_super IMPLEMENTATION. ENDMETHOD. - METHOD styles. - - CREATE OBJECT ro_html. - - _add ''. - - ENDMETHOD. "common styles - - METHOD lif_gui_page~get_assets. " Common images here - - DATA ls_image TYPE ty_web_asset. - -* see https://github.com/larshp/abapGit/issues/201 for source SVG - ls_image-url = 'img/logo' ##NO_TEXT. - ls_image-content = - 'iVBORw0KGgoAAAANSUhEUgAAAKMAAAAoCAYAAACSG0qbAAAABHNCSVQICAgIfAhkiAAA' - && 'AAlwSFlzAAAEJQAABCUBprHeCQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9y' - && 'Z5vuPBoAAA8VSURBVHic7Zx7cJzVeYef31nJAtvYko1JjM3FYHlXimwZkLWyLEMcwIGQ' - && 'cEkDJWmTltLStGkoDCkzwBAuCemUlksDNCkhJTTTljJpZhIuBQxxAWPvyuYiW7UkG8Il' - && 'UByIsS1sLEu75+0fu5JXu9/etAJz0TOzM/rOec85765+37m+3yczY8w0NU3qrwv9npfa' - && 'Hfx02pPPd469sgk+7misYnyjpWXy5IOG7kd8ZjjNjEtr13TdOm7eTfCxwo2lUJAQASRu' - && '2dnRfMn4uDbBx42yxZhPiMNMCHKCsVK2GGuqqqoQUwrZTAhygrFQshjfaGmZ/M7yxQtm' - && 'xGL9/qDqzwLxQvYTgpygXEoS4/DQ7LE1O05atLBu1YZdE4KcYLwpupoOmCO+5Z2dXPfE' - && 'xk07Tm2ZroGhBwX1wAygKqiOiVX2Rw9Jam/gyH0wuGGzvTEudRYSY4HFyogghxN2n7Sw' - && 'IendvcCioLoOtCCXNeqohOf0oDwPq9f3Wt/77dOHlWhYzUj/BRybTnrGEnZO5wv2m0rq' - && 'DezJoOiqeZbzegzpk6TVPPWJTT39y5svMogF1ZcesjlQgkwYp4F+EJQXwv4E+MiLUZJa' - && 'F7AIcRq4hWZ2mMRhQD/oZcErXv7FScaja3rt/wpU9E/sFyLACQq57wB/XIl/gWIstn2T' - && 'xpHVre7ZW71p8sFDeQscSEHKu3pTBadNH2Lq61VT57iwNazLgaNSqYaUaWXLDZCJIbBo' - && 'g3tK2A2xHns0oMrm3CRrqdTPnAVMiUIEmLlz2XGLMxNmH7YrifFcoUIHalHj8f8p6UfA' - && 'O+932weStno1zghps6Q7GBFiUYRxopkeaZ2vIwLyfxtQ4vV8lbWHNScacf+T/vwqn90o' - && 'MZYhRADJ+bv725vmj6Q8tHWffPKUD6IgO/tsfawneRHYd97Pdg8kSyJaZiGtBY4pYPYO' - && 'kH84C0Cyv8tKSiK7OZ99EpYAJ2V8AhkRY5lCHGaxhaq+BLCzY/EXd5y0aOG0td1vf1AF' - && 'CWCw7/1u80DQEtahQvcB03MyjQfM7Hwnmxfv9dPivX5SssqOwuzPSqk71mN3ymw5ZtdK' - && 'dmVIdly8xx7JZ29yy0qptwrGLMRRCA6T1w93nLTo5Lq13Zv625tOMRd6DLF4v0lWmQO8' - && 'qPko45y7TWaHZyUnwa6M99mN2fYbuu1V4K5oxF1B4Z4UgFifrQHWFLNbvkh1QheV5DNN' - && 'TZMqFWIGs5zX48M95PTqGa3TZ4erzbvj8/WUErf0L2++uNyGJLn2Js1oDeuYlkbNbmlR' - && 'deXup2hq0qS2es2VlHMDFaOlRdXL5uuwlnodG23QTEljCkbJV3d7WHOK+dXWqHqZnZeb' - && 'Y1fGe3OFOArRU5GTGbSHNWdwUL8Epo1qIQ9V/bXu3HES4jCznNfjb7e1zZ8Ri/UD1MLz' - && 'u05s/huMx4IKGNy4+8Tj/2Pqk8++Vaji86TQqxEuNNM5rWGtSCaokSDkgd0QjbidoPvN' - && '+5s7t9jz5TgdbdBMvLsG2cop6FgLUdUaZk804jYKuyrWa6vzlT2+XrOqQnxd6KwQOj5R' - && 'hULpL9Yaxkcj7g3QT6zK397ZbdtGtbtAZ+B0U3adkt0c67E7OyI6fFDuSpktC6HGpJjU' - && 'GmZ3NOI2mdnVnX32eHZZ7903hGXfBG8mp3J7sd/B0DPCTgUmBf9O7lmMybk56or3Jn8f' - && 'oLVB7Q5dZ9Iy4OBsw2jYbUUk96fwQrzHf955iBZzsDA+aL9k1owZ20fNzaY/tfFXwK48' - && 'ldQkSZ5YqJXmZk15JaJfmOmfgdOAmgCzWrCvyum5aIO+Uor3AIbOx7QV2TeBMPu3vKYA' - && 'Sw091hbWt4PKRhu0oDqkmND1wAnk3vkOmAN2lRLa2hrWMVm5Tek2R3286YzWiK4eQltk' - && '9g1gMfsFMhVYKunR1obQddk+SXZqwLe8acMGe7fYb9HZk7wm3utrBmpsqiXsyClHMHK6' - && '0hLWoRjHBfmLbP9K3bPYjFPIFWLaQeZnlZ8H4JyFflrMwcK4wG63v3/ycZnXOzqalxE0' - && 'mU7x9rvvVv93oVZqBtzNGGeU7Jbp9pZGzS7ReiVQVyDfmXRda4PaA9p5mBLmWGmmSron' - && 'M0FytUGGgjPTAi8UIeVk9u1og5YOJ0QbNBOjIac+Y22JPgLQ1WV7Ol+w36xebYnhtGpj' - && 'FjBYTj3l4KY9/dx6My4d74pN/Ki/Y9HpSG5HR/Nyh/1DHtO9OM6dvWFDwbtWslOykt6U' - && 's5VWZbOFnQtsyMqvc56Ty3T7NeBhLGAfDZDpe5nX6V5uXpbZ43K2NGQ2V9glwLas/I62' - && 'hfrE8EWsJ3mFsGYs+OQqze+A1cBLgbmma4f/9AmOJGBe5vKVLYN1W6wnOWSHmdkVhexM' - && 'PG6yC0x2AbmjoQ3njdh4uwrSw1Htmq5bd3Y0I3FLpQ5n0GTSQ7s6Fva70RPYTPbi+Pz0' - && 'J7ryboRC+m5PnRfsJjVEAfp5bLNflTb52dKIBj36RWY5ZyX2WCLukvbX67ZYHFLHZtGw' - && '+1fD/jDL8qQljWpav9m6Uw3wKYzXgUNJTxsk+0Fssw0L6x+j4dCx6eF/BEtwDBkbx7Fe' - && '29gWCa0yrC2rvXXO26WZfrWG3V2kji8zWbm0QUev67GX5ZgZ8A0H121hXIIZNrxou9oW' - && '6m4b4m/z2aTP+fsAohF3PaNHROvssZ8ElRs5DnyPBAkovxDFF4oJESDeY9tJD4Ur5umg' - && 'PSFm1Uy23Zk2SaM7e43p5Y4uxUMzu2f4H56+tuZmff2gfTqHrGEy5DkW6Abo7LH7gfsB' - && '2uo1LQGzBmoYFSwg57vNcjqqo4F1JXh2S7Zfx83TZZNqdD6MXkQkU369jONgcmfxe83M' - && 'B7XQEdEhg1B0HzDk2ZHpy3vBqLPpMQhyi/f2AIA3WyPZG6KkeVpKiE925awEi7H6JRsA' - && 'cqJDfIi9oayfW8ZB5dY/TFeX7YlGQg+RmgJkcnSQfWyr9QP92enmGcgeNCvx67mXbGdb' - && 'xD1hjI5AklJ+ydgTUGz6iiZNXd09+gYGGIRlQgXn6wDesZYSRFsJOYES5QjSw7fqnu7q' - && 'Bqh7uqu7f3nzdw3uKFJszEIcpqVRs12SRuAYiTrJ1YXMzSGgS6iQnHmWyQWe70pySz/F' - && 'MZagMWnMlaiTuTqTTih7s7IIHm1T1ncVI37l3BAAA4McAYF7iAvG17uxExi1U6Igd9XN' - && 'Dj+UmZA8qPrf3MDQbeSPIN8Ldub0JzeWLcT2I3Swn8JFhr4VQnMze5uKnv0ugOHfUXa3' - && 'ZhySedkR0eGDuMtbw/rTZCI1pA9PF0yWf4e3MnJ7YKXm0pOr6H03QRIIZeYnUj1njhid' - && '8aaRscKX/VGWSRLsCjnK2rcdC3njGUsQ5PSdv92yqJaMk5WBoRMpJsSnNgZufBdCkmsN' - && '60FgRbllK8PNzOlttT/qpz2sOUnpeWGHvq9ewcyc28/7XQCru213NOL+l6wgZ0kXAjnD' - && 'cazP7gXuTdu41rCyxbgr3mt/P16+F6LgUVXtmq5bC237yNsNu5YtPBZgx4kLFznZ1XlM' - && 'BzB/1liECBAN801yhfiq0HflbKXz1ojZ4qCylSBsbm6q/93wX0n0Q1Ir6UzWYXaZyZaF' - && 'qqxeZn813n4ZlhPWJWXMo00P5OTDF5c0qmm8fRlPip6bFhHk6Ti3ddfy5i3OXBemJQE2' - && 'A5g/c/qaTasC8krC0KdzE+3qWG/y6thmW7Vui/UkQ7w51vqDaGnRZFInPdlshNQ2C8oJ' - && 'h0oqaefF++zmzh5bu7bbXrBxjp88bp5qgZzNdyfWD/9t+B+TO4GW8/p+R0SHcGBxLWEF' - && 'jiQlHeIXEaRIPZAVRMVCTDcQCUh8LfOyaqjgCcr+YpY7NRFa2VY/egsqtNtdw8ie5gjJ' - && 'oUTqicjofOYA2f/YgcR03s5MMBF4wlIa7rMr5mnUyru6xl0LZAeFvDG3l83DF5199muk' - && 'oJO1FUMoviSi8Nh9Kg+Ru7qvUvCqPO+cMZsxbPsM4HXW9KcrEyKApTa7s9BVSyLaF3Ik' - && 'SbLSQros18RyInkkV2u5q+6zLaS+aCT0oJl/QVI78IWcsvDos1vtLYCE551QKNuCKW63' - && '+157g36cMOYI9yWhC3K+j4KDEHKxC9+t0altDaFHwL/kvVZIBJw761/uM5/MTJlU7S/Z' - && 'N6hTBNlhZA0OPReNuGdM6nL4jR4G5ZnRusAtKmVHwg1Slcxe11nODZJKh1fJ6kwM3dQa' - && 'VgOw3omjkGuL9/o/L/vFTzs7mi8pQZBpIT4f9PxE2bRFQncY9pdjKDoExDH7ebzPbgFo' - && 'bQjdng48KBfvzZau77ORN61FI66PsW2N7ARiZnZTZ589BtAWCV1v5J1zF+JNVdui2CbL' - && 'OcJsq1ejD2lVgCDL4e14r58J0N6k+cmEu0HYIssdrbxgnaGeeG9yJEg32hC6GbOix81y' - && 'trTsWLtiixpgQNLZ4yVEgCT++xSP0H7C0N1ZadVAh6SR3kRm2WfJO0H/XqTuQcn+IlOI' - && 'AFjRVaZhus3g2az0WuA0wcIi5QP3DDNIIPtakBABYltts7AO4OEi9eTFYGCksSRzwM4L' - && 'ECKAM1gG9tVR5UP+RkqZN5s7a0yBnwUEOSDp7GlPPp83BH0srO+1PmQrDIIen9wOdnln' - && 'n31G5n9ZtDLL6ck2x3uTf6DUee8rASX6vNnyWI/dmZ0R77O7LNXLBkWy9CE7Pd6XvNih' - && 'QkEQeZHZl9PBFtsDstebtyWFwv0B4r32UrzXn+6xDtBdwIslNL0N+JnMvravxiraFO/s' - && 'tm0y+xzQlcfkddCNCe/vGfP7GQH6lzdfbHAjqSCBHZK+PN5CzESSlixgnhMLzXAeXp+3' - && 'hWfuM0sWL10abQv1CdtHixzvmtiYPhcvSFOTJk1NEPEQkWdPUry4oc96y2o3YJiWs5Wx' - && 'zbYq83THHHu9Y1N2kG45tDRqdsgzxxuznKPOGbsTsN2M7d6zfXhePJ5Ici1h6mUcAcw0' - && '8Zo5fp35NoqKxAjwTrRhZmLSpPY9ySmPzV27dm+lTn9cKSTGA+XT+03Jq+l8HBLv2Q7c' - && 'X9K+ygQTFGDcHhaaoGJyouDNV7JH+eGj4mF6gspoC+tzJt1ObsT4MDsF2zxs886+Ml5v' - && '/PogUvEwPUGFiE+SX4gAtQa1gkhV7onQR4oJMR5oxC6stDeghd7Dh6E+CPw/HL4vVO2f' - && 'cpUAAAAASUVORK5CYII='. - APPEND ls_image TO rt_assets. - - ENDMETHOD. "lif_gui_page~get_assets - METHOD lif_gui_page~on_event. ev_state = gc_event_state-not_handled. ENDMETHOD. "lif_gui_page~on_event diff --git a/src/zabapgit_page_background.prog.abap b/src/zabapgit_page_background.prog.abap index 570a8769e..56e9fd0c0 100644 --- a/src/zabapgit_page_background.prog.abap +++ b/src/zabapgit_page_background.prog.abap @@ -85,14 +85,8 @@ CLASS lcl_gui_page_background DEFINITION FINAL mv_key TYPE lcl_persistence_repo=>ty_repo-key. METHODS: - parse_fields - IMPORTING iv_getdata TYPE clike - RETURNING VALUE(rs_fields) TYPE lcl_persistence_background=>ty_background, render_data RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper - RAISING lcx_exception, - save - IMPORTING iv_getdata TYPE clike RAISING lcx_exception. ENDCLASS. @@ -104,68 +98,20 @@ CLASS lcl_gui_page_background IMPLEMENTATION. mv_key = iv_key. ENDMETHOD. - METHOD parse_fields. - - DEFINE _field. - READ TABLE lt_fields ASSIGNING WITH KEY name = &1 ##NO_TEXT. - IF sy-subrc = 0. - rs_fields-&2 = -value. - ENDIF. - END-OF-DEFINITION. - - DATA: lt_fields TYPE tihttpnvp, - lv_string TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields. - - - lv_string = iv_getdata. " type conversion - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - _field 'method' method. - _field 'username' username. - _field 'password' password. - _field 'amethod' amethod. - _field 'aname' aname. - _field 'amail' amail. - - ASSERT NOT rs_fields IS INITIAL. - - ENDMETHOD. - METHOD lif_gui_page~on_event. + DATA ls_bg_task TYPE lcl_persistence_background=>ty_background. + CASE iv_action. - WHEN 'save'. - save( iv_getdata ). + WHEN gc_action-bg_update. + ls_bg_task = lcl_html_action_utils=>decode_bg_update( iv_getdata ). + ls_bg_task-key = mv_key. + lcl_services_background=>update_task( ls_bg_task ). ev_state = gc_event_state-re_render. ENDCASE. ENDMETHOD. - METHOD save. - - DATA: ls_fields TYPE lcl_persistence_background=>ty_background, - lo_persistence TYPE REF TO lcl_persistence_background. - - - ls_fields = parse_fields( iv_getdata ). - ls_fields-key = mv_key. - - CREATE OBJECT lo_persistence. - - IF ls_fields-method = lcl_persistence_background=>c_method-nothing. - lo_persistence->delete( ls_fields-key ). - ELSE. - lo_persistence->modify( ls_fields ). - ENDIF. - - MESSAGE 'Saved' TYPE 'S' ##NO_TEXT. - - COMMIT WORK. - - ENDMETHOD. - METHOD render_data. DATA: lo_repo TYPE REF TO lcl_repo_online, @@ -176,8 +122,7 @@ CLASS lcl_gui_page_background IMPLEMENTATION. lv_push TYPE string, lv_pull TYPE string, lv_afixed TYPE string, - lv_aauto TYPE string, - lt_list TYPE lcl_repo_srv=>ty_repo_tt. + lv_aauto TYPE string. CREATE OBJECT ro_html. @@ -221,7 +166,7 @@ CLASS lcl_gui_page_background IMPLEMENTATION. ro_html->add( '
' ). ro_html->add( 'Method
' ) ##NO_TEXT. - ro_html->add( '
' ). + ro_html->add( || ). ro_html->add( 'Do nothing
' ) ##NO_TEXT. ro_html->add( 'add( iv_txt = 'Run background logic' - iv_act = 'background_run' ) ##NO_TEXT. + iv_act = gc_action-go_background_run ) ##NO_TEXT. ro_html->add( header( ) ). ro_html->add( title( iv_title = 'BACKGROUND' io_menu = lo_toolbar ) ). diff --git a/src/zabapgit_page_branch_overview.prog.abap b/src/zabapgit_page_branch_overview.prog.abap index bd6bfd4a9..0873eea5c 100644 --- a/src/zabapgit_page_branch_overview.prog.abap +++ b/src/zabapgit_page_branch_overview.prog.abap @@ -193,7 +193,7 @@ CLASS lcl_branch_overview IMPLEMENTATION. SPLIT ls_raw-body AT gc_newline INTO ls_commit-message lv_trash. * unix time stamps are in same time zone, so ignore the zone, - FIND REGEX '^([\w\s]+) <(.*)> (\d{10}) .\d{4}$' IN ls_raw-author + FIND REGEX gc_author_regex IN ls_raw-author SUBMATCHES ls_commit-author ls_commit-email diff --git a/src/zabapgit_page_commit.prog.abap b/src/zabapgit_page_commit.prog.abap index 1e04d19ee..434b154c1 100644 --- a/src/zabapgit_page_commit.prog.abap +++ b/src/zabapgit_page_commit.prog.abap @@ -5,6 +5,12 @@ CLASS lcl_gui_page_commit DEFINITION FINAL INHERITING FROM lcl_gui_page_super. PUBLIC SECTION. + + CONSTANTS: BEGIN OF c_action, + commit_post TYPE string VALUE 'commit_post', + commit_cancel TYPE string VALUE 'commit_cancel', + END OF c_action. + METHODS: constructor IMPORTING io_repo TYPE REF TO lcl_repo_online @@ -26,13 +32,8 @@ CLASS lcl_gui_page_commit DEFINITION FINAL INHERITING FROM lcl_gui_page_super. render_form RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper RAISING lcx_exception, - styles - RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper, scripts - RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper, - commit_push - IMPORTING it_postdata TYPE cnht_post_data_tab - RAISING lcx_exception. + RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. ENDCLASS. @@ -45,6 +46,50 @@ CLASS lcl_gui_page_commit IMPLEMENTATION. mo_stage = io_stage. ENDMETHOD. + METHOD lif_gui_page~on_event. + + DATA: ls_commit TYPE lcl_services_git=>ty_commit_fields. + + CASE iv_action. + WHEN c_action-commit_post. + + lcl_html_action_utils=>parse_commit_request( EXPORTING it_postdata = it_postdata + IMPORTING es_fields = ls_commit ). + + lcl_services_git=>commit( is_commit = ls_commit + io_repo = mo_repo + io_stage = mo_stage ). + + ev_state = gc_event_state-go_back_to_bookmark. + + WHEN c_action-commit_cancel. + ev_state = gc_event_state-go_back. + ENDCASE. + + ENDMETHOD. + + METHOD lif_gui_page~render. + + CREATE OBJECT ro_html. + + ro_html->add( header( ) ). + ro_html->add( title( 'COMMIT' ) ). + + ro_html->add( '
' ). + ro_html->add( render_repo_top( + io_repo = mo_repo + iv_show_package = abap_false + iv_branch = mo_stage->get_branch_name( ) ) ). + + ro_html->add( render_menu( ) ). + ro_html->add( render_form( ) ). + ro_html->add( render_stage( ) ). + ro_html->add( '
' ). + + ro_html->add( footer( io_include_script = scripts( ) ) ). + + ENDMETHOD. "lif_gui_page~render + METHOD render_stage. DATA: lt_stage TYPE lcl_stage=>ty_stage_tt. @@ -104,7 +149,7 @@ CLASS lcl_gui_page_commit IMPLEMENTATION. ro_html->add( '
' ). ro_html->add( '' ). - ro_html->add( || ). + ro_html->add( || ). ro_html->add( '' ). ro_html->add( '' ). @@ -153,7 +198,7 @@ CLASS lcl_gui_page_commit IMPLEMENTATION. CREATE OBJECT ro_html. CREATE OBJECT lo_toolbar. - lo_toolbar->add( iv_act = 'submitCommit();' + lo_toolbar->add( iv_act = 'submitFormById(''commit_form'');' iv_txt = 'Commit' iv_typ = gc_action_type-onclick iv_opt = gc_html_opt-emphas ) ##NO_TEXT. @@ -168,129 +213,10 @@ CLASS lcl_gui_page_commit IMPLEMENTATION. ENDMETHOD. "render_menu - METHOD lif_gui_page~on_event. - - CASE iv_action. - WHEN 'commit_post'. - commit_push( it_postdata ). - ev_state = gc_event_state-go_back_to_bookmark. - WHEN 'commit_cancel'. - ev_state = gc_event_state-go_back. - ENDCASE. - - ENDMETHOD. - - 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( '
' ). - ro_html->add( render_repo_top( - io_repo = mo_repo - iv_show_package = abap_false - iv_branch = mo_stage->get_branch_name( ) ) ). - - ro_html->add( render_menu( ) ). - ro_html->add( render_form( ) ). - ro_html->add( render_stage( ) ). - ro_html->add( '
' ). - - 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 commit_push. - - DATA: ls_fields TYPE lcl_html_action_utils=>ty_commit_fields, - ls_comment TYPE ty_comment, - lo_user TYPE REF TO lcl_persistence_user. - - - ls_fields = lcl_html_action_utils=>parse_commit_request( it_postdata ). - - lo_user = lcl_app=>user( ). - lo_user->set_repo_username( iv_url = mo_repo->get_url( ) iv_username = ls_fields-username ). - lo_user->set_repo_email( iv_url = mo_repo->get_url( ) iv_email = ls_fields-email ). - - IF ls_fields-username IS INITIAL. - lcx_exception=>raise( 'empty username' ). - ELSEIF ls_fields-email IS INITIAL. - lcx_exception=>raise( 'empty email' ). - ELSEIF ls_fields-comment IS INITIAL. - lcx_exception=>raise( 'empty comment' ). - ENDIF. - - ls_comment-username = ls_fields-username. - ls_comment-email = ls_fields-email. - ls_comment-comment = ls_fields-comment. - - IF NOT ls_fields-body IS INITIAL. - CONCATENATE ls_comment-comment gc_newline ls_fields-body - INTO ls_comment-comment. - ENDIF. - - mo_repo->push( is_comment = ls_comment - io_stage = mo_stage ). - - COMMIT WORK. - - ENDMETHOD. "commit_push - 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();'. + _add 'setInitialFocus("commit_msg");'. ENDMETHOD. "scripts diff --git a/src/zabapgit_page_db.prog.abap b/src/zabapgit_page_db.prog.abap index 36b057a0a..6f8ccf02c 100644 --- a/src/zabapgit_page_db.prog.abap +++ b/src/zabapgit_page_db.prog.abap @@ -2,17 +2,6 @@ *& Include ZABAPGIT_PAGE_DB *&---------------------------------------------------------------------* -CLASS lcl_gui_page_db DEFINITION FINAL INHERITING FROM lcl_gui_page_super. - - PUBLIC SECTION. - METHODS lif_gui_page~render REDEFINITION. - - PRIVATE SECTION. - METHODS styles - RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. - -ENDCLASS. - CLASS lcl_gui_page_db_display DEFINITION FINAL INHERITING FROM lcl_gui_page_super. PUBLIC SECTION. @@ -24,9 +13,6 @@ CLASS lcl_gui_page_db_display DEFINITION FINAL INHERITING FROM lcl_gui_page_supe PRIVATE SECTION. DATA: ms_key TYPE lcl_persistence_db=>ty_content. - METHODS styles - RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. - ENDCLASS. CLASS lcl_gui_page_db_display IMPLEMENTATION. @@ -38,7 +24,9 @@ CLASS lcl_gui_page_db_display IMPLEMENTATION. METHOD lif_gui_page~render. - DATA: lv_data TYPE lcl_persistence_db=>ty_content-data_str. + DATA: lv_data TYPE lcl_persistence_db=>ty_content-data_str, + ls_action TYPE lcl_persistence_db=>ty_content, + lv_action TYPE string. TRY. lv_data = lcl_app=>db( )->read( @@ -47,20 +35,30 @@ CLASS lcl_gui_page_db_display IMPLEMENTATION. CATCH lcx_not_found ##NO_HANDLER. ENDTRY. - lv_data = lcl_xml_pretty=>print( lv_data ). + ls_action-type = ms_key-type. + ls_action-value = ms_key-value. + lv_action = lcl_html_action_utils=>dbkey_encode( ls_action ). - lv_data = escape( val = lv_data - format = cl_abap_format=>e_html_attr ). + lv_data = lcl_xml_pretty=>print( lv_data ). + lv_data = escape( val = lv_data + format = cl_abap_format=>e_html_attr ). CREATE OBJECT ro_html. - ro_html->add( header( io_include_style = styles( ) ) ). + ro_html->add( header( ) ). ro_html->add( title( 'CONFIG DISPLAY' ) ). ro_html->add( '
' ). + ro_html->add( '
' ). + ro_html->add( || && |
Type:{ ms_key-type }
| ). - ro_html->add( || && + ro_html->add( |
Value:
| && |
Key:{ ms_key-value }
| ). + + ro_html->add( '
' ). + ro_html->add_anchor( iv_txt = 'Edit' iv_act = |{ gc_action-db_edit }?{ lv_action }| ). + ro_html->add( '
' ). + ro_html->add( |
{ lv_data }
| ). ro_html->add( '
' ). @@ -68,37 +66,6 @@ CLASS lcl_gui_page_db_display IMPLEMENTATION. ENDMETHOD. - METHOD styles. - - CREATE OBJECT ro_html. - - _add '/* DB ENTRY DISPLAY */'. - _add 'div.db_entry {'. - _add ' background-color: #f2f2f2;'. - _add ' padding: 0.5em;'. - _add '}'. - - _add 'div.db_entry pre {'. - _add ' display: block;'. - _add ' overflow: hidden;'. - _add ' word-wrap:break-word;'. - _add ' white-space: pre-wrap;'. - _add ' background-color: #eaeaea;'. - _add ' padding: 0.5em;'. - _add ' width: 50em;'. - _add '}'. - - _add 'table.tag {'. - _add ' display: inline-block;'. - _add ' border: 1px #b3c1cc solid;'. - _add ' background-color: #eee;'. - _add ' margin-right: 0.5em; '. - _add '}'. - _add 'table.tag td { padding: 0.2em 0.5em; }'. - _add 'table.tag td.label { background-color: #b3c1cc; }'. - - ENDMETHOD. "styles - ENDCLASS. CLASS lcl_gui_page_db_edit DEFINITION FINAL INHERITING FROM lcl_gui_page_super. @@ -112,12 +79,6 @@ CLASS lcl_gui_page_db_edit DEFINITION FINAL INHERITING FROM lcl_gui_page_super. PRIVATE SECTION. DATA: ms_key TYPE lcl_persistence_db=>ty_content. - 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_db_edit IMPLEMENTATION. @@ -151,7 +112,7 @@ CLASS lcl_gui_page_db_edit IMPLEMENTATION. CREATE OBJECT ro_html. CREATE OBJECT lo_toolbar. - ro_html->add( header( io_include_style = styles( ) ) ). + ro_html->add( header( ) ). ro_html->add( title( 'CONFIG EDIT' ) ). ro_html->add( '
' ). @@ -159,11 +120,11 @@ CLASS lcl_gui_page_db_edit IMPLEMENTATION. " Banners ro_html->add( || && |
Type:{ ms_key-type }
| ). - ro_html->add( || && + ro_html->add( |
Value:
| && |
Key:{ ms_key-value }
| ). " Form - ro_html->add( '' ). + ro_html->add( || ). ro_html->add( || ). ro_html->add( || ). ro_html->add( |