All files / src/git zcl_abapgit_git_delta.clas.abap

85.79% Statements 157/183
8.33% Branches 1/12
100% Functions 0/0
85.79% Lines 157/183

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 1841x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 1x 1x 1x       1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x   1x       1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x     1x     1x     1x     1x 1x 1x 1x 1x 1x     1x     1x 1x     1x 1x 1x           1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
CLASS zcl_abapgit_git_delta DEFINITION PUBLIC.
  PUBLIC SECTION.
 
    CLASS-METHODS decode_deltas
      IMPORTING
        iv_show_progress TYPE abap_bool DEFAULT abap_true
      CHANGING
        !ct_objects      TYPE zif_abapgit_definitions=>ty_objects_tt
      RAISING
        zcx_abapgit_exception .
 
  PRIVATE SECTION.
    CLASS-METHODS delta
      IMPORTING
        !is_object  TYPE zif_abapgit_definitions=>ty_object
      CHANGING
        !ct_objects TYPE zif_abapgit_definitions=>ty_objects_tt
      RAISING
        zcx_abapgit_exception .
 
    CLASS-METHODS delta_header
      IMPORTING
        !io_stream TYPE REF TO lcl_stream.
 
ENDCLASS.
 
CLASS zcl_abapgit_git_delta IMPLEMENTATION.
 
  METHOD decode_deltas.
 
    DATA: ls_object   LIKE LINE OF ct_objects,
          li_progress TYPE REF TO zif_abapgit_progress,
          lt_deltas   LIKE ct_objects.
 
 
    LOOP AT ct_objects INTO ls_object
        USING KEY type
        WHERE type = zif_abapgit_git_definitions=>c_type-ref_d.
      INSERT ls_object INTO TABLE lt_deltas.
    ENDLOOP.
 
    DELETE ct_objects
      USING KEY type
      WHERE type = zif_abapgit_git_definitions=>c_type-ref_d.
 
    "Restore correct Delta Order
    SORT lt_deltas BY index.
 
    IF iv_show_progress = abap_true.
      li_progress = zcl_abapgit_progress=>get_instance( lines( lt_deltas ) ).
    ENDIF.
 
    LOOP AT lt_deltas INTO ls_object.
      IF li_progress IS NOT INITIAL.
        li_progress->show( iv_current = sy-tabix
                           iv_text    = 'Decode deltas' ).
      ENDIF.
 
      delta( EXPORTING is_object = ls_object
             CHANGING ct_objects = ct_objects ).
    ENDLOOP.
 
  ENDMETHOD.
 
  METHOD delta.
 
    CONSTANTS: lc_1   TYPE x VALUE '01',
               lc_2   TYPE x VALUE '02',
               lc_4   TYPE x VALUE '04',
               lc_8   TYPE x VALUE '08',
               lc_16  TYPE x VALUE '10',
               lc_32  TYPE x VALUE '20',
               lc_64  TYPE x VALUE '40',
               lc_128 TYPE x VALUE '80'.
 
    DATA: lv_base   TYPE xstring,
          lv_result TYPE xstring,
          lv_offset TYPE i,
          lo_stream TYPE REF TO lcl_stream,
          lv_sha1   TYPE zif_abapgit_git_definitions=>ty_sha1,
          ls_object LIKE LINE OF ct_objects,
          lv_len    TYPE i,
          lv_tmp    TYPE xstring,
          lv_org    TYPE x.
 
    FIELD-SYMBOLS: <ls_object> LIKE LINE OF ct_objects.
 
 
    CREATE OBJECT lo_stream
      EXPORTING
        iv_data = is_object-data.
 
* find base
    READ TABLE ct_objects ASSIGNING <ls_object>
      WITH KEY sha COMPONENTS sha1 = is_object-sha1.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Base not found, { is_object-sha1 }| ).
    ELSEIF <ls_object>-type = zif_abapgit_git_definitions=>c_type-ref_d.
* sanity check
      zcx_abapgit_exception=>raise( |Delta, base eq delta| ).
    ENDIF.
 
    lv_base = <ls_object>-data.
 
* skip the 2 headers
    delta_header( lo_stream ).
    delta_header( lo_stream ).
 
    WHILE lo_stream->has_data( ) = abap_true.
 
      lv_org = lo_stream->eat_byte( ).
 
      IF lv_org BIT-AND lc_128 = lc_128. " MSB = 1
 
        lv_offset = 0.
        IF lv_org BIT-AND lc_1 = lc_1.
          lv_offset = lo_stream->eat_byte( ).
        ENDIF.
        IF lv_org BIT-AND lc_2 = lc_2.
          lv_offset = lv_offset + lo_stream->eat_byte( ) * 256.
        ENDIF.
        IF lv_org BIT-AND lc_4 = lc_4.
          lv_offset = lv_offset + lo_stream->eat_byte( ) * 65536.
        ENDIF.
        IF lv_org BIT-AND lc_8 = lc_8.
          lv_offset = lv_offset + lo_stream->eat_byte( ) * 16777216. " hmm, overflow?
        ENDIF.
 
        lv_len = 0.
        IF lv_org BIT-AND lc_16 = lc_16.
          lv_len = lo_stream->eat_byte( ).
        ENDIF.
        IF lv_org BIT-AND lc_32 = lc_32.
          lv_len = lv_len + lo_stream->eat_byte( ) * 256.
        ENDIF.
        IF lv_org BIT-AND lc_64 = lc_64.
          lv_len = lv_len + lo_stream->eat_byte( ) * 65536.
        ENDIF.
 
        IF lv_len = 0.
          lv_len = 65536.
        ENDIF.
 
        CONCATENATE lv_result lv_base+lv_offset(lv_len) INTO lv_result IN BYTE MODE.
      ELSE. " lv_bitbyte(1) = '0'
* insert from delta
        lv_len = lv_org. " convert to int
        lv_tmp = lo_stream->eat_bytes( lv_len ).
        CONCATENATE lv_result lv_tmp INTO lv_result IN BYTE MODE.
      ENDIF.
 
    ENDWHILE.
 
    lv_sha1 = zcl_abapgit_hash=>sha1( iv_type = <ls_object>-type
                                      iv_data = lv_result ).
 
    CLEAR ls_object.
    ls_object-sha1 = lv_sha1.
    ls_object-type = <ls_object>-type.
    ls_object-data = lv_result.
    ls_object-index = <ls_object>-index. "Retain sort index
    APPEND ls_object TO ct_objects.
 
  ENDMETHOD.
 
 
  METHOD delta_header.
 
    DATA lv_x   TYPE x.
    DATA lv_bit TYPE c LENGTH 1.
 
* header is skipped for performance reasons
    DO.
      lv_x = io_stream->eat_byte( ).
      GET BIT 1 OF lv_x INTO lv_bit.
      IF lv_bit = '0'.
        EXIT. " current loop
      ENDIF.
    ENDDO.
 
  ENDMETHOD.
 
ENDCLASS.