Package org.eclipse.jgit.diff

Examples of org.eclipse.jgit.diff.Edit


      //
      return b;
    }

    for (int i = 0; i < edits.size(); i++) {
      final Edit e = edits.get(i);
      if (b < e.getBeginB()) {
        if (i == 0) {
          // Special case of context at start of file.
          //
          return b;
        }
        return e.getBeginA() - (e.getBeginB() - b);
      }
      if (e.getBeginB() <= b && b <= e.getEndB()) {
        return -1;
      }
    }

    final Edit last = edits.get(edits.size() - 1);
    return last.getBeginA() + (b - last.getEndB());
  }
View Full Code Here


    Text aContent = key.getTextA();
    Text bContent = key.getTextB();
    combineLineEdits(edits, aContent, bContent);

    for (int i = 0; i < edits.size(); i++) {
      Edit e = edits.get(i);

      if (e.getType() == Edit.Type.REPLACE) {
        CharText a = new CharText(aContent, e.getBeginA(), e.getEndA());
        CharText b = new CharText(bContent, e.getBeginB(), e.getEndB());
        CharTextComparator cmp = new CharTextComparator();

        List<Edit> wordEdits = MyersDiff.INSTANCE.diff(cmp, a, b);

        // Combine edits that are really close together. If they are
        // just a few characters apart we tend to get better results
        // by joining them together and taking the whole span.
        //
        for (int j = 0; j < wordEdits.size() - 1;) {
          Edit c = wordEdits.get(j);
          Edit n = wordEdits.get(j + 1);

          if (n.getBeginA() - c.getEndA() <= 5
              || n.getBeginB() - c.getEndB() <= 5) {
            int ab = c.getBeginA();
            int ae = n.getEndA();

            int bb = c.getBeginB();
            int be = n.getEndB();

            if (canCoalesce(a, c.getEndA(), n.getBeginA())
                && canCoalesce(b, c.getEndB(), n.getBeginB())) {
              wordEdits.set(j, new Edit(ab, ae, bb, be));
              wordEdits.remove(j + 1);
              continue;
            }
          }

          j++;
        }

        // Apply some simple rules to fix up some of the edits. Our
        // logic above, along with our per-character difference tends
        // to produce some crazy stuff.
        //
        for (int j = 0; j < wordEdits.size(); j++) {
          Edit c = wordEdits.get(j);
          int ab = c.getBeginA();
          int ae = c.getEndA();

          int bb = c.getBeginB();
          int be = c.getEndB();

          // Sometimes the diff generator produces an INSERT or DELETE
          // right up against a REPLACE, but we only find this after
          // we've also played some shifting games on the prior edit.
          // If that happened to us, coalesce them together so we can
          // correct this mess for the user. If we don't we wind up
          // with silly stuff like "es" -> "es = Addresses".
          //
          if (1 < j) {
            Edit p = wordEdits.get(j - 1);
            if (p.getEndA() == ab || p.getEndB() == bb) {
              if (p.getEndA() == ab && p.getBeginA() < p.getEndA()) {
                ab = p.getBeginA();
              }
              if (p.getEndB() == bb && p.getBeginB() < p.getEndB()) {
                bb = p.getBeginB();
              }
              wordEdits.remove(--j);
            }
          }

          // We sometimes collapsed an edit together in a strange way,
          // such that the edges of each text is identical. Fix by
          // by dropping out that incorrectly replaced region.
          //
          while (ab < ae && bb < be && cmp.equals(a, ab, b, bb)) {
            ab++;
            bb++;
          }
          while (ab < ae && bb < be && cmp.equals(a, ae - 1, b, be - 1)) {
            ae--;
            be--;
          }

          // The leading part of an edit and its trailing part in the same
          // text might be identical. Slide down that edit and use the tail
          // rather than the leading bit. If however the edit is only on a
          // whitespace block try to shift it to the left margin, assuming
          // that it is an indentation change.
          //
          boolean aShift = true;
          if (ab < ae && isOnlyWhitespace(a, ab, ae)) {
            int lf = findLF(wordEdits, j, a, ab);
            if (lf < ab && a.charAt(lf) == '\n') {
              int nb = lf + 1;
              int p = 0;
              while (p < ae - ab) {
                if (cmp.equals(a, ab + p, a, ab + p))
                  p++;
                else
                  break;
              }
              if (p == ae - ab) {
                ab = nb;
                ae = nb + p;
                aShift = false;
              }
            }
          }
          if (aShift) {
            while (0 < ab && ab < ae && a.charAt(ab - 1) != '\n'
                && cmp.equals(a, ab - 1, a, ae - 1)) {
              ab--;
              ae--;
            }
            if (!a.isLineStart(ab) || !a.contains(ab, ae, '\n')) {
              while (ab < ae && ae < a.size() && cmp.equals(a, ab, a, ae)) {
                ab++;
                ae++;
                if (a.charAt(ae - 1) == '\n') {
                  break;
                }
              }
            }
          }

          boolean bShift = true;
          if (bb < be && isOnlyWhitespace(b, bb, be)) {
            int lf = findLF(wordEdits, j, b, bb);
            if (lf < bb && b.charAt(lf) == '\n') {
              int nb = lf + 1;
              int p = 0;
              while (p < be - bb) {
                if (cmp.equals(b, bb + p, b, bb + p))
                  p++;
                else
                  break;
              }
              if (p == be - bb) {
                bb = nb;
                be = nb + p;
                bShift = false;
              }
            }
          }
          if (bShift) {
            while (0 < bb && bb < be && b.charAt(bb - 1) != '\n'
                && cmp.equals(b, bb - 1, b, be - 1)) {
              bb--;
              be--;
            }
            if (!b.isLineStart(bb) || !b.contains(bb, be, '\n')) {
              while (bb < be && be < b.size() && cmp.equals(b, bb, b, be)) {
                bb++;
                be++;
                if (b.charAt(be - 1) == '\n') {
                  break;
                }
              }
            }
          }

          // If most of a line was modified except the LF was common, make
          // the LF part of the modification region. This is easier to read.
          //
          if (ab < ae //
              && (ab == 0 || a.charAt(ab - 1) == '\n') //
              && ae < a.size() && a.charAt(ae) == '\n') {
            ae++;
          }
          if (bb < be //
              && (bb == 0 || b.charAt(bb - 1) == '\n') //
              && be < b.size() && b.charAt(be) == '\n') {
            be++;
          }

          wordEdits.set(j, new Edit(ab, ae, bb, be));
        }

        edits.set(i, new ReplaceEdit(e, wordEdits));
      }
    }
View Full Code Here

    return new IntraLineDiff(edits);
  }

  private static void combineLineEdits(List<Edit> edits, Text a, Text b) {
    for (int j = 0; j < edits.size() - 1;) {
      Edit c = edits.get(j);
      Edit n = edits.get(j + 1);

      // Combine edits that are really close together. Right now our rule
      // is, coalesce two line edits which are only one line apart if that
      // common context line is either a "pointless line", or is identical
      // on both sides and starts a new block of code. These are mostly
      // block reindents to add or remove control flow operators.
      //
      final int ad = n.getBeginA() - c.getEndA();
      final int bd = n.getBeginB() - c.getEndB();
      if ((1 <= ad && isBlankLineGap(a, c.getEndA(), n.getBeginA()))
          || (1 <= bd && isBlankLineGap(b, c.getEndB(), n.getBeginB()))
          || (ad == 1 && bd == 1 && isControlBlockStart(a, c.getEndA()))) {
        int ab = c.getBeginA();
        int ae = n.getEndA();

        int bb = c.getBeginB();
        int be = n.getEndB();

        edits.set(j, new Edit(ab, ae, bb, be));
        edits.remove(j + 1);
        continue;
      }

      j++;
View Full Code Here

      // more responsibility for the result. Remaining edits can
      // be safely ignored.
      if (r == null)
        return;

      Edit e = editList.get(eIdx);

      // Edit ends before the next candidate region. Skip the edit.
      if (e.getEndB() <= r.sourceStart) {
        eIdx++;
        continue;
      }

      // Next candidate region starts before the edit. Assign some
      // of the blame onto A, but possibly split and also on B.
      if (r.sourceStart < e.getBeginB()) {
        int d = e.getBeginB() - r.sourceStart;
        if (r.length <= d) {
          // Pass the blame for this region onto A.
          Region next = r.next;
          r.sourceStart = e.getBeginA() - d;
          aTail = add(aTail, a, r);
          r = next;
          continue;
        }

        // Split the region and assign some to A, some to B.
        aTail = add(aTail, a, r.splitFirst(e.getBeginA() - d, d));
        r.slideAndShrink(d);
      }

      // At this point e.getBeginB() <= r.sourceStart.

      // An empty edit on the B side isn't relevant to this split,
      // as it does not overlap any candidate region.
      if (e.getLengthB() == 0) {
        eIdx++;
        continue;
      }

      // If the region ends before the edit, blame on B.
      int rEnd = r.sourceStart + r.length;
      if (rEnd <= e.getEndB()) {
        Region next = r.next;
        bTail = add(bTail, b, r);
        r = next;
        if (rEnd == e.getEndB())
          eIdx++;
        continue;
      }

      // This region extends beyond the edit. Blame the first
      // half of the region on B, and process the rest after.
      int len = e.getEndB() - r.sourceStart;
      bTail = add(bTail, b, r.splitFirst(r.sourceStart, len));
      r.slideAndShrink(len);
      eIdx++;
    }

    if (r == null)
      return;

    // For any remaining region, pass the blame onto A after shifting
    // the source start to account for the difference between the two.
    Edit e = editList.get(editList.size() - 1);
    int endB = e.getEndB();
    int d = endB - e.getEndA();
    if (aTail == null)
      a.regionList = r;
    else
      aTail.next = r;
    do {
View Full Code Here

    Iterator<Edit> baseToOurs = oursEdits.iterator();
    EditList theirsEdits = diffAlg.diff(cmp, base, theirs);
    Iterator<Edit> baseToTheirs = theirsEdits.iterator();
    int current = 0; // points to the next line (first line is 0) of base
                     // which was not handled yet
    Edit oursEdit = nextEdit(baseToOurs);
    Edit theirsEdit = nextEdit(baseToTheirs);

    // iterate over all edits from base to ours and from base to theirs
    // leave the loop when there are no edits more for ours or for theirs
    // (or both)
    while (theirsEdit != END_EDIT || oursEdit != END_EDIT) {
      if (oursEdit.getEndA() < theirsEdit.getBeginA()) {
        // something was changed in ours not overlapping with any change
        // from theirs. First add the common part in front of the edit
        // then the edit.
        if (current != oursEdit.getBeginA()) {
          result.add(0, current, oursEdit.getBeginA(),
              ConflictState.NO_CONFLICT);
        }
        result.add(1, oursEdit.getBeginB(), oursEdit.getEndB(),
            ConflictState.NO_CONFLICT);
        current = oursEdit.getEndA();
        oursEdit = nextEdit(baseToOurs);
      } else if (theirsEdit.getEndA() < oursEdit.getBeginA()) {
        // something was changed in theirs not overlapping with any
        // from ours. First add the common part in front of the edit
        // then the edit.
        if (current != theirsEdit.getBeginA()) {
          result.add(0, current, theirsEdit.getBeginA(),
              ConflictState.NO_CONFLICT);
        }
        result.add(2, theirsEdit.getBeginB(), theirsEdit.getEndB(),
            ConflictState.NO_CONFLICT);
        current = theirsEdit.getEndA();
        theirsEdit = nextEdit(baseToTheirs);
      } else {
        // here we found a real overlapping modification

        // if there is a common part in front of the conflict add it
        if (oursEdit.getBeginA() != current
            && theirsEdit.getBeginA() != current) {
          result.add(0, current, Math.min(oursEdit.getBeginA(),
              theirsEdit.getBeginA()), ConflictState.NO_CONFLICT);
        }

        // set some initial values for the ranges in A and B which we
        // want to handle
        int oursBeginB = oursEdit.getBeginB();
        int theirsBeginB = theirsEdit.getBeginB();
        // harmonize the start of the ranges in A and B
        if (oursEdit.getBeginA() < theirsEdit.getBeginA()) {
          theirsBeginB -= theirsEdit.getBeginA()
              - oursEdit.getBeginA();
        } else {
          oursBeginB -= oursEdit.getBeginA() - theirsEdit.getBeginA();
        }

        // combine edits:
        // Maybe an Edit on one side corresponds to multiple Edits on
        // the other side. Then we have to combine the Edits of the
        // other side - so in the end we can merge together two single
        // edits.
        //
        // It is important to notice that this combining will extend the
        // ranges of our conflict always downwards (towards the end of
        // the content). The starts of the conflicting ranges in ours
        // and theirs are not touched here.
        //
        // This combining is an iterative process: after we have
        // combined some edits we have to do the check again. The
        // combined edits could now correspond to multiple edits on the
        // other side.
        //
        // Example: when this combining algorithm works on the following
        // edits
        // oursEdits=((0-5,0-5),(6-8,6-8),(10-11,10-11)) and
        // theirsEdits=((0-1,0-1),(2-3,2-3),(5-7,5-7))
        // it will merge them into
        // oursEdits=((0-8,0-8),(10-11,10-11)) and
        // theirsEdits=((0-7,0-7))
        //
        // Since the only interesting thing to us is how in ours and
        // theirs the end of the conflicting range is changing we let
        // oursEdit and theirsEdit point to the last conflicting edit
        Edit nextOursEdit = nextEdit(baseToOurs);
        Edit nextTheirsEdit = nextEdit(baseToTheirs);
        for (;;) {
          if (oursEdit.getEndA() >= nextTheirsEdit.getBeginA()) {
            theirsEdit = nextTheirsEdit;
            nextTheirsEdit = nextEdit(baseToTheirs);
          } else if (theirsEdit.getEndA() >= nextOursEdit.getBeginA()) {
            oursEdit = nextOursEdit;
            nextOursEdit = nextEdit(baseToOurs);
View Full Code Here

    if (editList.isEmpty()) {
      newStartLine = 0;
      newLineCount = 0;
    } else {
      newStartLine = editList.get(0).getBeginB();
      Edit last = editList.get(editList.size() - 1);
      newLineCount = last.getEndB() - newStartLine;
    }
  }
View Full Code Here

      editList = new EditList();
      final byte[] buf = file.buf;
      int c = nextLF(buf, startOffset);
      int oLine = old.startLine;
      int nLine = newStartLine;
      Edit in = null;

      SCAN: for (; c < endOffset; c = nextLF(buf, c)) {
        switch (buf[c]) {
        case ' ':
        case '\n':
          in = null;
          oLine++;
          nLine++;
          continue;

        case '-':
          if (in == null) {
            in = new Edit(oLine - 1, nLine - 1);
            editList.add(in);
          }
          oLine++;
          in.extendA();
          continue;

        case '+':
          if (in == null) {
            in = new Edit(oLine - 1, nLine - 1);
            editList.add(in);
          }
          nLine++;
          in.extendB();
          continue;

        case '\\': // Matches "\ No newline at end of file"
          continue;
View Full Code Here

      // more responsibility for the result. Remaining edits can
      // be safely ignored.
      if (r == null)
        return;

      Edit e = editList.get(eIdx);

      // Edit ends before the next candidate region. Skip the edit.
      if (e.getEndB() <= r.sourceStart) {
        eIdx++;
        continue;
      }

      // Next candidate region starts before the edit. Assign some
      // of the blame onto A, but possibly split and also on B.
      if (r.sourceStart < e.getBeginB()) {
        int d = e.getBeginB() - r.sourceStart;
        if (r.length <= d) {
          // Pass the blame for this region onto A.
          Region next = r.next;
          r.sourceStart = e.getBeginA() - d;
          aTail = add(aTail, a, r);
          r = next;
          continue;
        }

        // Split the region and assign some to A, some to B.
        aTail = add(aTail, a, r.splitFirst(e.getBeginA() - d, d));
        r.slideAndShrink(d);
      }

      // At this point e.getBeginB() <= r.sourceStart.

      // An empty edit on the B side isn't relevant to this split,
      // as it does not overlap any candidate region.
      if (e.getLengthB() == 0) {
        eIdx++;
        continue;
      }

      // If the region ends before the edit, blame on B.
      int rEnd = r.sourceStart + r.length;
      if (rEnd <= e.getEndB()) {
        Region next = r.next;
        bTail = add(bTail, b, r);
        r = next;
        if (rEnd == e.getEndB())
          eIdx++;
        continue;
      }

      // This region extends beyond the edit. Blame the first
      // half of the region on B, and process the rest after.
      int len = e.getEndB() - r.sourceStart;
      bTail = add(bTail, b, r.splitFirst(r.sourceStart, len));
      r.slideAndShrink(len);
      eIdx++;
    }

    if (r == null)
      return;

    // For any remaining region, pass the blame onto A after shifting
    // the source start to account for the difference between the two.
    Edit e = editList.get(editList.size() - 1);
    int endB = e.getEndB();
    int d = endB - e.getEndA();
    if (aTail == null)
      a.regionList = r;
    else
      aTail.next = r;
    do {
View Full Code Here

    Iterator<Edit> baseToOurs = oursEdits.iterator();
    EditList theirsEdits = diffAlg.diff(cmp, base, theirs);
    Iterator<Edit> baseToTheirs = theirsEdits.iterator();
    int current = 0; // points to the next line (first line is 0) of base
                     // which was not handled yet
    Edit oursEdit = nextEdit(baseToOurs);
    Edit theirsEdit = nextEdit(baseToTheirs);

    // iterate over all edits from base to ours and from base to theirs
    // leave the loop when there are no edits more for ours or for theirs
    // (or both)
    while (theirsEdit != END_EDIT || oursEdit != END_EDIT) {
      if (oursEdit.getEndA() < theirsEdit.getBeginA()) {
        // something was changed in ours not overlapping with any change
        // from theirs. First add the common part in front of the edit
        // then the edit.
        if (current != oursEdit.getBeginA()) {
          result.add(0, current, oursEdit.getBeginA(),
              ConflictState.NO_CONFLICT);
        }
        result.add(1, oursEdit.getBeginB(), oursEdit.getEndB(),
            ConflictState.NO_CONFLICT);
        current = oursEdit.getEndA();
        oursEdit = nextEdit(baseToOurs);
      } else if (theirsEdit.getEndA() < oursEdit.getBeginA()) {
        // something was changed in theirs not overlapping with any
        // from ours. First add the common part in front of the edit
        // then the edit.
        if (current != theirsEdit.getBeginA()) {
          result.add(0, current, theirsEdit.getBeginA(),
              ConflictState.NO_CONFLICT);
        }
        result.add(2, theirsEdit.getBeginB(), theirsEdit.getEndB(),
            ConflictState.NO_CONFLICT);
        current = theirsEdit.getEndA();
        theirsEdit = nextEdit(baseToTheirs);
      } else {
        // here we found a real overlapping modification

        // if there is a common part in front of the conflict add it
        if (oursEdit.getBeginA() != current
            && theirsEdit.getBeginA() != current) {
          result.add(0, current, Math.min(oursEdit.getBeginA(),
              theirsEdit.getBeginA()), ConflictState.NO_CONFLICT);
        }

        // set some initial values for the ranges in A and B which we
        // want to handle
        int oursBeginB = oursEdit.getBeginB();
        int theirsBeginB = theirsEdit.getBeginB();
        // harmonize the start of the ranges in A and B
        if (oursEdit.getBeginA() < theirsEdit.getBeginA()) {
          theirsBeginB -= theirsEdit.getBeginA()
              - oursEdit.getBeginA();
        } else {
          oursBeginB -= oursEdit.getBeginA() - theirsEdit.getBeginA();
        }

        // combine edits:
        // Maybe an Edit on one side corresponds to multiple Edits on
        // the other side. Then we have to combine the Edits of the
        // other side - so in the end we can merge together two single
        // edits.
        //
        // It is important to notice that this combining will extend the
        // ranges of our conflict always downwards (towards the end of
        // the content). The starts of the conflicting ranges in ours
        // and theirs are not touched here.
        //
        // This combining is an iterative process: after we have
        // combined some edits we have to do the check again. The
        // combined edits could now correspond to multiple edits on the
        // other side.
        //
        // Example: when this combining algorithm works on the following
        // edits
        // oursEdits=((0-5,0-5),(6-8,6-8),(10-11,10-11)) and
        // theirsEdits=((0-1,0-1),(2-3,2-3),(5-7,5-7))
        // it will merge them into
        // oursEdits=((0-8,0-8),(10-11,10-11)) and
        // theirsEdits=((0-7,0-7))
        //
        // Since the only interesting thing to us is how in ours and
        // theirs the end of the conflicting range is changing we let
        // oursEdit and theirsEdit point to the last conflicting edit
        Edit nextOursEdit = nextEdit(baseToOurs);
        Edit nextTheirsEdit = nextEdit(baseToTheirs);
        for (;;) {
          if (oursEdit.getEndA() >= nextTheirsEdit.getBeginA()) {
            theirsEdit = nextTheirsEdit;
            nextTheirsEdit = nextEdit(baseToTheirs);
          } else if (theirsEdit.getEndA() >= nextOursEdit.getBeginA()) {
            oursEdit = nextOursEdit;
            nextOursEdit = nextEdit(baseToOurs);
View Full Code Here

    final Patch p = parseTestPatchFile("testGetText_BothISO88591.patch");
    final FileHeader fh = p.getFiles().get(0);

    final EditList list0 = fh.getHunks().get(0).toEditList();
    assertEquals(1, list0.size());
    assertEquals(new Edit(4 - 1, 5 - 1, 4 - 1, 5 - 1), list0.get(0));

    final EditList list1 = fh.getHunks().get(1).toEditList();
    assertEquals(1, list1.size());
    assertEquals(new Edit(16 - 1, 17 - 1, 16 - 1, 17 - 1), list1.get(0));
  }
View Full Code Here

TOP

Related Classes of org.eclipse.jgit.diff.Edit

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.