Line data Source code
1 : // Copyright (C) 2022 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.restapi.change; 16 : 17 : import static com.google.common.base.Preconditions.checkNotNull; 18 : 19 : import com.google.gerrit.extensions.api.changes.ApplyPatchInput; 20 : import com.google.gerrit.extensions.restapi.BadRequestException; 21 : import com.google.gerrit.extensions.restapi.RestApiException; 22 : import java.io.ByteArrayInputStream; 23 : import java.io.IOException; 24 : import java.io.InputStream; 25 : import java.nio.charset.StandardCharsets; 26 : import org.eclipse.jgit.api.errors.PatchApplyException; 27 : import org.eclipse.jgit.api.errors.PatchFormatException; 28 : import org.eclipse.jgit.lib.ObjectId; 29 : import org.eclipse.jgit.lib.ObjectInserter; 30 : import org.eclipse.jgit.lib.Repository; 31 : import org.eclipse.jgit.patch.PatchApplier; 32 : import org.eclipse.jgit.revwalk.RevCommit; 33 : import org.eclipse.jgit.revwalk.RevTree; 34 : 35 : /** Utility for applying a patch. */ 36 : public final class ApplyPatchUtil { 37 : 38 : /** 39 : * Applies the given patch on top of the merge tip, using the given object inserter. 40 : * 41 : * @param repo to apply the patch in 42 : * @param oi to operate with 43 : * @param input the patch for applying 44 : * @param mergeTip the tip to apply the patch on 45 : * @return the tree ID with the applied patch 46 : * @throws IOException if unable to create the jgit PatchApplier object 47 : * @throws RestApiException for any other failure 48 : */ 49 : public static ObjectId applyPatch( 50 : Repository repo, ObjectInserter oi, ApplyPatchInput input, RevCommit mergeTip) 51 : throws IOException, RestApiException { 52 2 : checkNotNull(mergeTip); 53 2 : RevTree tip = mergeTip.getTree(); 54 2 : InputStream patchStream = 55 2 : new ByteArrayInputStream(input.patch.getBytes(StandardCharsets.UTF_8)); 56 : try { 57 2 : PatchApplier applier = new PatchApplier(repo, tip, oi); 58 2 : PatchApplier.Result applyResult = applier.applyPatch(patchStream); 59 2 : return applyResult.getTreeId(); 60 1 : } catch (PatchFormatException e) { 61 1 : throw new BadRequestException("Invalid patch format: " + input.patch, e); 62 2 : } catch (PatchApplyException e) { 63 2 : throw RestApiException.wrap("Cannot apply patch: " + input.patch, e); 64 : } 65 : } 66 : 67 : private ApplyPatchUtil() {} 68 : }