Package org.eclipse.jgit.patch

Source Code of org.eclipse.jgit.patch.CombinedHunkHeader$CombinedOldImage

/*
* Copyright (C) 2008, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
*   notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
*   copyright notice, this list of conditions and the following
*   disclaimer in the documentation and/or other materials provided
*   with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
*   names of its contributors may be used to endorse or promote
*   products derived from this software without specific prior
*   written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.patch;

import static org.eclipse.jgit.util.RawParseUtils.nextLF;
import static org.eclipse.jgit.util.RawParseUtils.parseBase10;

import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;

import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.util.MutableInteger;

/** Hunk header for a hunk appearing in a "diff --cc" style patch. */
public class CombinedHunkHeader extends HunkHeader {
  private static abstract class CombinedOldImage extends OldImage {
    int nContext;
  }

  private CombinedOldImage[] old;

  CombinedHunkHeader(final CombinedFileHeader fh, final int offset) {
    super(fh, offset, null);
    old = new CombinedOldImage[fh.getParentCount()];
    for (int i = 0; i < old.length; i++) {
      final int imagePos = i;
      old[i] = new CombinedOldImage() {
        @Override
        public AbbreviatedObjectId getId() {
          return fh.getOldId(imagePos);
        }
      };
    }
  }

  @Override
  public CombinedFileHeader getFileHeader() {
    return (CombinedFileHeader) super.getFileHeader();
  }

  @Override
  public OldImage getOldImage() {
    return getOldImage(0);
  }

  /**
   * Get the OldImage data related to the nth ancestor
   *
   * @param nthParent
   *            the ancestor to get the old image data of
   * @return image data of the requested ancestor.
   */
  public OldImage getOldImage(final int nthParent) {
    return old[nthParent];
  }

  @Override
  void parseHeader() {
    // Parse "@@@ -55,12 -163,13 +163,15 @@@ protected boolean"
    //
    final byte[] buf = file.buf;
    final MutableInteger ptr = new MutableInteger();
    ptr.value = nextLF(buf, startOffset, ' ');

    for (int n = 0; n < old.length; n++) {
      old[n].startLine = -parseBase10(buf, ptr.value, ptr);
      if (buf[ptr.value] == ',')
        old[n].lineCount = parseBase10(buf, ptr.value + 1, ptr);
      else
        old[n].lineCount = 1;
    }

    newStartLine = parseBase10(buf, ptr.value + 1, ptr);
    if (buf[ptr.value] == ',')
      newLineCount = parseBase10(buf, ptr.value + 1, ptr);
    else
      newLineCount = 1;
  }

  @Override
  int parseBody(final Patch script, final int end) {
    final byte[] buf = file.buf;
    int c = nextLF(buf, startOffset);

    for (final CombinedOldImage o : old) {
      o.nDeleted = 0;
      o.nAdded = 0;
      o.nContext = 0;
    }
    nContext = 0;
    int nAdded = 0;

    SCAN: for (int eol; c < end; c = eol) {
      eol = nextLF(buf, c);

      if (eol - c < old.length + 1) {
        // Line isn't long enough to mention the state of each
        // ancestor. It must be the end of the hunk.
        break SCAN;
      }

      switch (buf[c]) {
      case ' ':
      case '-':
      case '+':
        break;

      default:
        // Line can't possibly be part of this hunk; the first
        // ancestor information isn't recognizable.
        //
        break SCAN;
      }

      int localcontext = 0;
      for (int ancestor = 0; ancestor < old.length; ancestor++) {
        switch (buf[c + ancestor]) {
        case ' ':
          localcontext++;
          old[ancestor].nContext++;
          continue;

        case '-':
          old[ancestor].nDeleted++;
          continue;

        case '+':
          old[ancestor].nAdded++;
          nAdded++;
          continue;

        default:
          break SCAN;
        }
      }
      if (localcontext == old.length)
        nContext++;
    }

    for (int ancestor = 0; ancestor < old.length; ancestor++) {
      final CombinedOldImage o = old[ancestor];
      final int cmp = o.nContext + o.nDeleted;
      if (cmp < o.lineCount) {
        final int missingCnt = o.lineCount - cmp;
        script.error(buf, startOffset, MessageFormat.format(
            JGitText.get().truncatedHunkLinesMissingForAncestor, missingCnt, (ancestor + 1)));
      }
    }

    if (nContext + nAdded < newLineCount) {
      final int missingCount = newLineCount - (nContext + nAdded);
      script.error(buf, startOffset, MessageFormat.format(JGitText.get().truncatedHunkNewLinesMissing, missingCount));
    }

    return c;
  }

  @Override
  void extractFileLines(final OutputStream[] out) throws IOException {
    final byte[] buf = file.buf;
    int ptr = startOffset;
    int eol = nextLF(buf, ptr);
    if (endOffset <= eol)
      return;

    // Treat the hunk header as though it were from the ancestor,
    // as it may have a function header appearing after it which
    // was copied out of the ancestor file.
    //
    out[0].write(buf, ptr, eol - ptr);

    SCAN: for (ptr = eol; ptr < endOffset; ptr = eol) {
      eol = nextLF(buf, ptr);

      if (eol - ptr < old.length + 1) {
        // Line isn't long enough to mention the state of each
        // ancestor. It must be the end of the hunk.
        break SCAN;
      }

      switch (buf[ptr]) {
      case ' ':
      case '-':
      case '+':
        break;

      default:
        // Line can't possibly be part of this hunk; the first
        // ancestor information isn't recognizable.
        //
        break SCAN;
      }

      int delcnt = 0;
      for (int ancestor = 0; ancestor < old.length; ancestor++) {
        switch (buf[ptr + ancestor]) {
        case '-':
          delcnt++;
          out[ancestor].write(buf, ptr, eol - ptr);
          continue;

        case ' ':
          out[ancestor].write(buf, ptr, eol - ptr);
          continue;

        case '+':
          continue;

        default:
          break SCAN;
        }
      }
      if (delcnt < old.length) {
        // This line appears in the new file if it wasn't deleted
        // relative to all ancestors.
        //
        out[old.length].write(buf, ptr, eol - ptr);
      }
    }
  }

  void extractFileLines(final StringBuilder sb, final String[] text,
      final int[] offsets) {
    final byte[] buf = file.buf;
    int ptr = startOffset;
    int eol = nextLF(buf, ptr);
    if (endOffset <= eol)
      return;
    copyLine(sb, text, offsets, 0);
    SCAN: for (ptr = eol; ptr < endOffset; ptr = eol) {
      eol = nextLF(buf, ptr);

      if (eol - ptr < old.length + 1) {
        // Line isn't long enough to mention the state of each
        // ancestor. It must be the end of the hunk.
        break SCAN;
      }

      switch (buf[ptr]) {
      case ' ':
      case '-':
      case '+':
        break;

      default:
        // Line can't possibly be part of this hunk; the first
        // ancestor information isn't recognizable.
        //
        break SCAN;
      }

      boolean copied = false;
      for (int ancestor = 0; ancestor < old.length; ancestor++) {
        switch (buf[ptr + ancestor]) {
        case ' ':
        case '-':
          if (copied)
            skipLine(text, offsets, ancestor);
          else {
            copyLine(sb, text, offsets, ancestor);
            copied = true;
          }
          continue;

        case '+':
          continue;

        default:
          break SCAN;
        }
      }
      if (!copied) {
        // If none of the ancestors caused the copy then this line
        // must be new across the board, so it only appears in the
        // text of the new file.
        //
        copyLine(sb, text, offsets, old.length);
      }
    }
  }
}
TOP

Related Classes of org.eclipse.jgit.patch.CombinedHunkHeader$CombinedOldImage

TOP
Copyright © 2018 www.massapi.com. 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.