1. 16 10月, 2017 1 次提交
    • J
      diff: fix infinite loop with --color-moved --ignore-space-change · fa5ba2c1
      Jeff King 提交于
      The --color-moved code uses next_byte() to advance through
      the blob contents. When the user has asked to ignore
      whitespace changes, we try to collapse any whitespace change
      down to a single space.
      
      However, we enter the conditional block whenever we see the
      IGNORE_WHITESPACE_CHANGE flag, even if the next byte isn't
      whitespace.
      
      This means that the combination of "--color-moved and
      --ignore-space-change" was completely broken. Worse, because
      we return from next_byte() without having advanced our
      pointer, the function makes no forward progress in the
      buffer and loops infinitely.
      
      Fix this by entering the conditional only when we actually
      see whitespace. We can apply this also to the
      IGNORE_WHITESPACE change. That code path isn't buggy
      (because it falls through to returning the next
      non-whitespace byte), but it makes the logic more clear if
      we only bother to look at whitespace flags after seeing that
      the next byte is whitespace.
      Reported-by: NOrgad Shaneh <orgads@gmail.com>
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      fa5ba2c1
  2. 28 9月, 2017 1 次提交
  3. 01 7月, 2017 29 次提交
    • S
      diff: document the new --color-moved setting · 61e89eaa
      Stefan Beller 提交于
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      61e89eaa
    • S
      diff.c: add dimming to moved line detection · 86b452e2
      Stefan Beller 提交于
      Any lines inside a moved block of code are not interesting. Boundaries
      of blocks are only interesting if they are next to another block of moved
      code.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      86b452e2
    • S
      diff.c: color moved lines differently, plain mode · 176841f0
      Stefan Beller 提交于
      Add the 'plain' mode for move detection of code. This omits the checking
      for adjacent blocks, so it is not as useful. If you have a lot of the
      same blocks moved in the same patch, the 'Zebra' would end up slow as it
      is O(n^2) (n is number of same blocks). So this may be useful there and
      is generally easy to add. Instead be very literal at the move detection,
      do not skip over short blocks here.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      176841f0
    • S
      diff.c: color moved lines differently · 2e2d5ac1
      Stefan Beller 提交于
      When a patch consists mostly of moving blocks of code around, it can
      be quite tedious to ensure that the blocks are moved verbatim, and not
      undesirably modified in the move. To that end, color blocks that are
      moved within the same patch differently. For example (OM, del, add,
      and NM are different colors):
      
          [OM]  -void sensitive_stuff(void)
          [OM]  -{
          [OM]  -        if (!is_authorized_user())
          [OM]  -                die("unauthorized");
          [OM]  -        sensitive_stuff(spanning,
          [OM]  -                        multiple,
          [OM]  -                        lines);
          [OM]  -}
      
                 void another_function()
                 {
          [del] -        printf("foo");
          [add] +        printf("bar");
                 }
      
          [NM]  +void sensitive_stuff(void)
          [NM]  +{
          [NM]  +        if (!is_authorized_user())
          [NM]  +                die("unauthorized");
          [NM]  +        sensitive_stuff(spanning,
          [NM]  +                        multiple,
          [NM]  +                        lines);
          [NM]  +}
      
      However adjacent blocks may be problematic. For example, in this
      potentially malicious patch, the swapping of blocks can be spotted:
      
          [OM]  -void sensitive_stuff(void)
          [OM]  -{
          [OMA] -        if (!is_authorized_user())
          [OMA] -                die("unauthorized");
          [OM]  -        sensitive_stuff(spanning,
          [OM]  -                        multiple,
          [OM]  -                        lines);
          [OMA] -}
      
                 void another_function()
                 {
          [del] -        printf("foo");
          [add] +        printf("bar");
                 }
      
          [NM]  +void sensitive_stuff(void)
          [NM]  +{
          [NMA] +        sensitive_stuff(spanning,
          [NMA] +                        multiple,
          [NMA] +                        lines);
          [NM]  +        if (!is_authorized_user())
          [NM]  +                die("unauthorized");
          [NMA] +}
      
      If the moved code is larger, it is easier to hide some permutation in the
      code, which is why some alternative coloring is needed.
      
      This patch implements the first mode:
      * basic alternating 'Zebra' mode
        This conveys all information needed to the user.  Defer customization to
        later patches.
      
      First I implemented an alternative design, which would try to fingerprint
      a line by its neighbors to detect if we are in a block or at the boundary.
      This idea iss error prone as it inspected each line and its neighboring
      lines to determine if the line was (a) moved and (b) if was deep inside
      a hunk by having matching neighboring lines. This is unreliable as the
      we can construct hunks which have equal neighbors that just exceed the
      number of lines inspected. (Think of 'AXYZBXYZCXYZD..' with each letter
      as a line, that is permutated to AXYZCXYZBXYZD..').
      
      Instead this provides a dynamic programming greedy algorithm that finds
      the largest moved hunk and then has several modes on highlighting bounds.
      
      A note on the options '--submodule=diff' and '--color-words/--word-diff':
      In the conversion to use emit_line in the prior patches both submodules
      as well as word diff output carefully chose to call emit_line with sign=0.
      All output with sign=0 is ignored for move detection purposes in this
      patch, such that no weird looking output will be generated for these
      cases. This leads to another thought: We could pass on '--color-moved' to
      submodules such that they color up moved lines for themselves. If we'd do
      so only line moves within a repository boundary are marked up.
      
      It is useful to have moved lines colored, but there are annoying corner
      cases, such as a single line moved, that is very common. For example
      in a typical patch of C code, we have closing braces that end statement
      blocks or functions.
      
      While it is technically true that these lines are moved as they show up
      elsewhere, it is harmful for the review as the reviewers attention is
      drawn to such a minor side annoyance.
      
      For now let's have a simple solution of hardcoding the number of
      moved lines to be at least 3 before coloring them. Note, that the
      length is applied across all blocks to find the 'lonely' blocks
      that pollute new code, but do not interfere with a permutated
      block where each permutation has less lines than 3.
      Helped-by: NJonathan Tan <jonathantanmy@google.com>
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      2e2d5ac1
    • S
      diff.c: buffer all output if asked to · e6e045f8
      Stefan Beller 提交于
      Introduce a new option 'emitted_symbols' in the struct diff_options which
      controls whether all output is buffered up until all output is available.
      It is set internally in diff.c when necessary.
      
      We'll have a new struct 'emitted_string' in diff.c which will be used to
      buffer each line.  The emitted_string will duplicate the memory of the
      line to buffer as that is easiest to reason about for now. In a future
      patch we may want to decrease the memory usage by not duplicating all
      output for buffering but rather we may want to store offsets into the
      file or in case of hunk descriptions such as the similarity score, we
      could just store the relevant number and reproduce the text later on.
      
      This approach was chosen as a first step because it is quite simple
      compared to the alternative with less memory footprint.
      
      emit_diff_symbol factors out the emission part and depending on the
      diff_options->emitted_symbols the emission will be performed directly
      when calling emit_diff_symbol or after the whole process is done, i.e.
      by buffering we have add the possibility for a second pass over the
      whole output before doing the actual output.
      
      In 6440d341 (2012-03-14, diff: tweak a _copy_ of diff_options with
      word-diff) we introduced a duplicate diff options struct for word
      emissions as we may have different regex settings in there.
      When buffering the output, we need to operate on just one buffer,
      so we have to copy back the emissions of the word buffer into the
      main buffer.
      
      Unconditionally enable output via buffer in this patch as it yields
      a great opportunity for testing, i.e. all the diff tests from the
      test suite pass without having reordering issues (i.e. only parts
      of the output got buffered, and we forgot to buffer other parts).
      The test suite passes, which gives confidence that we converted all
      functions to use emit_string for output.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      e6e045f8
    • S
      146fdb0d
    • S
      30b7e1e7
    • S
      diff.c: convert word diffing to use emit_diff_symbol · bd033291
      Stefan Beller 提交于
      The word diffing is not line oriented and would need some serious
      effort to be transformed into a line oriented approach, so
      just go with a symbol DIFF_SYMBOL_WORD_DIFF that is a partial line.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      bd033291
    • S
      diff.c: convert show_stats to use emit_diff_symbol · 0911c475
      Stefan Beller 提交于
      We call print_stat_summary from builtin/apply, so we still
      need the version with a file pointer, so introduce
      print_stat_summary_0 that uses emit_string machinery and
      keep print_stat_summary with the same arguments around.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      0911c475
    • S
    • S
      submodule.c: migrate diff output to use emit_diff_symbol · f3597138
      Stefan Beller 提交于
      As the submodule process is no longer attached to the same file pointer
      'o->file' as the superprojects process, there is a different result in
      color.c::check_auto_color. That is why we need to pass coloring explicitly,
      such that the submodule coloring decision will be made by the child process
      processing the submodule. Only DIFF_SYMBOL_SUBMODULE_PIPETHROUGH contains
      color, the other symbols are for embedding the submodule output into the
      superprojects output.
      
      Remove the colors from the function signatures, as all the coloring
      decisions will be made either inside the child process or the final
      emit_diff_symbol, but not in the functions driving the submodule diff.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      f3597138
    • S
      5af6ea95
    • S
      diff.c: emit_diff_symbol learns about DIFF_SYMBOL_BINARY_FILES · 4acaaa7a
      Stefan Beller 提交于
      we could save a little bit of memory when buffering in a later mode
      by just passing the inner part ("%s and %s", file1, file 2), but
      those a just a few bytes, so instead let's reuse the implementation from
      DIFF_SYMBOL_HEADER and keep the whole line around.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      4acaaa7a
    • S
      diff.c: emit_diff_symbol learns DIFF_SYMBOL_HEADER · a29b0a13
      Stefan Beller 提交于
      The header is constructed lazily including line breaks, so just emit
      the raw string as is.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      a29b0a13
    • S
      diff.c: emit_diff_symbol learns DIFF_SYMBOL_FILEPAIR_{PLUS, MINUS} · 3ee8b7bf
      Stefan Beller 提交于
      We have to use fprintf instead of emit_line, because we want to emit the
      tab after the color. This is important for ancient versions of gnu patch
      AFAICT, although we probably do not want to feed colored output to the
      patch utility, such that it would not matter if the trailing tab is
      colored. Keep the corner case as-is though.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      3ee8b7bf
    • S
      diff.c: emit_diff_symbol learns DIFF_SYMBOL_CONTEXT_INCOMPLETE · f2bb1218
      Stefan Beller 提交于
      The context marker use the exact same output pattern, so reuse it.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      f2bb1218
    • S
    • S
      diff.c: migrate emit_line_checked to use emit_diff_symbol · 091f8e28
      Stefan Beller 提交于
      Add a new flags field to emit_diff_symbol, that will be used by
      context lines for:
      * white space rules that are applicable (The first 12 bits)
        Take a note in cahe.c as well, when this ws rules are extended we have
        to fix the bits in the flags field.
      * how the rules are evaluated (actually this double encodes the sign
        of the line, but the code is easier to keep this way, bits 13,14,15)
      * if the line a blank line at EOF (bit 16)
      
      The check if new lines need to be marked up as extra lines at the end of
      file, is now done unconditionally. That should be ok, as
      'new_blank_line_at_eof' has a quick early return.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      091f8e28
    • S
      b9cbfde6
    • S
    • S
      c64b420b
    • S
      diff.c: introduce emit_diff_symbol · 36a4cefd
      Stefan Beller 提交于
      In a later patch we want to buffer all output before emitting it as a
      new feature ("markup moved lines") conceptually cannot be implemented
      in a single pass over the output.
      
      There are different approaches to buffer all output such as:
      * Buffering on the char level, i.e. we'd have a char[] which would
        grow at approximately 80 characters a line. This would keep the
        output completely unstructured, but might be very easy to implement,
        such as redirecting all output to a temporary file and working off
        that. The later passes over the buffer are quite complicated though,
        because we have to parse back any output and then decide if it should
        be modified.
      
      * Buffer on a line level. As the output is mostly line oriented already,
        this would make sense, but it still is a bit awkward as we'd have to
        make sense of it again by looking at the first characters of a line
        to decide what part of a diff a line is.
      
      * Buffer semantically. Imagine there is a formal grammar for the diff
        output and we'd keep the symbols of this grammar around. This keeps
        the highest level of structure in the buffered data, such that the
        actual memory requirements are less than say the first option. Instead
        of buffering the characters of the line, we'll buffer what we intend
        to do plus additional information for the specifics. An output of
      
          diff --git a/new.txt b/new.txt
          index fa69b07..412428c 100644
          Binary files a/new.txt and b/new.txt differ
      
        could be buffered as
           DIFF_SYMBOL_DIFF_START + new.txt
           DIFF_SYMBOL_INDEX_MODE + fa69b07 412428c "non-executable" flag
           DIFF_SYMBOL_BINARY_FILES + new.txt
      
      This and the following patches introduce the third option of buffering
      by first moving any output to emit_diff_symbol, and then introducing the
      buffering in this function.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      36a4cefd
    • S
      diff.c: factor out diff_flush_patch_all_file_pairs · ec331506
      Stefan Beller 提交于
      In a later patch we want to do more things before and after all filepairs
      are flushed. So factor flushing out all file pairs into its own function
      that the new code can be plugged in easily.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      ec331506
    • S
      diff.c: move line ending check into emit_hunk_header · dfb7728f
      Stefan Beller 提交于
      The emit_hunk_header() function is responsible for assembling a
      hunk header and calling emit_line() to send the hunk header
      to the output file.  Its only caller fn_out_consume() needs
      to prepare for a case where the function emits an incomplete
      line and add the terminating LF.
      
      Instead make sure emit_hunk_header() to always send a
      completed line to emit_line().
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      dfb7728f
    • S
      diff.c: readability fix · f2d2a5de
      Stefan Beller 提交于
      We already have dereferenced 'p->two' into a local variable 'two'.
      Use that.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      f2d2a5de
    • J
      Merge branch 'sb/hashmap-customize-comparison' into sb/diff-color-move · 2cfb6cec
      Junio C Hamano 提交于
      * sb/hashmap-customize-comparison: (566 commits)
        hashmap: migrate documentation from Documentation/technical into header
        patch-ids.c: use hashmap correctly
        hashmap.h: compare function has access to a data field
        Twelfth batch for 2.14
        Git 2.13.2
        Eleventh batch for 2.14
        Revert "split-index: add and use unshare_split_index()"
        Tenth batch for 2.14
        add--interactive: quote commentChar regex
        add--interactive: handle EOF in prompt_yesno
        auto-correct: tweak phrasing
        docs: update 64-bit core.packedGitLimit default
        t7508: fix a broken indentation
        grep: fix erroneously copy/pasted variable in check/assert pattern
        Ninth batch for 2.14
        glossary: define 'stash entry'
        status: add optional stash count information
        stash: update documentation to use 'stash entry'
        for_each_bisect_ref(): don't trim refnames
        mergetools/meld: improve compatibiilty with Meld on macOS X
        ...
      2cfb6cec
    • S
      hashmap: migrate documentation from Documentation/technical into header · 1ecbf31d
      Stefan Beller 提交于
      While at it, clarify the use of `key`, `keydata`, `entry_or_key` as well
      as documenting the new data pointer for the compare function.
      
      Rework the example.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      1ecbf31d
    • S
      patch-ids.c: use hashmap correctly · 3da492f8
      Stefan Beller 提交于
      As alluded to in the previous patch, the code in patch-ids.c is
      using the hashmaps API wrong.
      
      Luckily we do not have a bug, as all hashmap functionality that we use
      here (hashmap_get) passes through the keydata.  If hashmap_get_next were
      to be used, a bug would occur as that passes NULL for the key_data.
      
      So instead use the hashmap API correctly and provide the caller required
      data in the compare function via the first argument that always gets
      passed and was setup via the hashmap_init function.
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      3da492f8
    • S
      hashmap.h: compare function has access to a data field · 7663cdc8
      Stefan Beller 提交于
      When using the hashmap a common need is to have access to caller provided
      data in the compare function. A couple of times we abuse the keydata field
      to pass in the data needed. This happens for example in patch-ids.c.
      
      This patch changes the function signature of the compare function
      to have one more void pointer available. The pointer given for each
      invocation of the compare function must be defined in the init function
      of the hashmap and is just passed through.
      
      Documentation of this new feature is deferred to a later patch.
      This is a rather mechanical conversion, just adding the new pass-through
      parameter.  However while at it improve the naming of the fields of all
      compare functions used by hashmaps by ensuring unused parameters are
      prefixed with 'unused_' and naming the parameters what they are (instead
      of 'unused' make it 'unused_keydata').
      Signed-off-by: NStefan Beller <sbeller@google.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      7663cdc8
  4. 27 6月, 2017 7 次提交
  5. 25 6月, 2017 2 次提交