Line data Source code
1 : // Copyright (C) 2016 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.notedb; 16 : 17 : import static com.google.common.base.Preconditions.checkArgument; 18 : import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_ATTENTION; 19 : import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_PATCH_SET; 20 : 21 : import com.google.common.collect.ListMultimap; 22 : import com.google.common.collect.MultimapBuilder; 23 : import com.google.common.collect.Sets; 24 : import com.google.gerrit.server.git.InMemoryInserter; 25 : import com.google.gerrit.server.git.InsertedObject; 26 : import java.io.IOException; 27 : import java.util.List; 28 : import org.eclipse.jgit.errors.IncorrectObjectTypeException; 29 : import org.eclipse.jgit.errors.MissingObjectException; 30 : import org.eclipse.jgit.lib.AnyObjectId; 31 : import org.eclipse.jgit.lib.ObjectReader; 32 : import org.eclipse.jgit.lib.Repository; 33 : import org.eclipse.jgit.revwalk.FooterKey; 34 : import org.eclipse.jgit.revwalk.FooterLine; 35 : import org.eclipse.jgit.revwalk.RevCommit; 36 : import org.eclipse.jgit.revwalk.RevWalk; 37 : 38 : /** 39 : * Commit implementation with some optimizations for change notes parsing. 40 : * 41 : * <p> 42 : * 43 : * <ul> 44 : * <li>Caches the result of {@link #getFooterLines()}, which is otherwise very wasteful with 45 : * allocations. 46 : * </ul> 47 : */ 48 : public class ChangeNotesCommit extends RevCommit { 49 : 50 : /** A {@link RevWalk} producing {@link ChangeNotesCommit}s. */ 51 : public static ChangeNotesRevWalk newRevWalk(Repository repo) { 52 103 : return new ChangeNotesRevWalk(repo); 53 : } 54 : 55 : public static ChangeNotesRevWalk newStagedRevWalk( 56 : Repository repo, Iterable<InsertedObject> stagedObjs) { 57 0 : final InMemoryInserter ins = new InMemoryInserter(repo); 58 0 : for (InsertedObject obj : stagedObjs) { 59 0 : ins.insert(obj); 60 0 : } 61 0 : return new ChangeNotesRevWalk(ins.newReader()) { 62 : @Override 63 : public void close() { 64 0 : ins.close(); 65 0 : super.close(); 66 0 : } 67 : }; 68 : } 69 : 70 : /** A {@link RevWalk} that creates {@link ChangeNotesCommit}s rather than {@link RevCommit}s */ 71 : public static class ChangeNotesRevWalk extends RevWalk { 72 : private ChangeNotesRevWalk(Repository repo) { 73 103 : super(repo); 74 103 : } 75 : 76 : private ChangeNotesRevWalk(ObjectReader reader) { 77 0 : super(reader); 78 0 : } 79 : 80 : @Override 81 : protected ChangeNotesCommit createCommit(AnyObjectId id) { 82 103 : return new ChangeNotesCommit(id); 83 : } 84 : 85 : @Override 86 : public ChangeNotesCommit next() 87 : throws MissingObjectException, IncorrectObjectTypeException, IOException { 88 103 : return (ChangeNotesCommit) super.next(); 89 : } 90 : 91 : @Override 92 : public void markStart(RevCommit c) 93 : throws MissingObjectException, IncorrectObjectTypeException, IOException { 94 103 : checkArgument(c instanceof ChangeNotesCommit); 95 103 : super.markStart(c); 96 103 : } 97 : 98 : @Override 99 : public void markUninteresting(RevCommit c) 100 : throws MissingObjectException, IncorrectObjectTypeException, IOException { 101 0 : checkArgument(c instanceof ChangeNotesCommit); 102 0 : super.markUninteresting(c); 103 0 : } 104 : 105 : @Override 106 : public ChangeNotesCommit lookupCommit(AnyObjectId id) { 107 90 : return (ChangeNotesCommit) super.lookupCommit(id); 108 : } 109 : 110 : @Override 111 : public ChangeNotesCommit parseCommit(AnyObjectId id) 112 : throws MissingObjectException, IncorrectObjectTypeException, IOException { 113 103 : return (ChangeNotesCommit) super.parseCommit(id); 114 : } 115 : } 116 : 117 : private ListMultimap<String, String> footerLines; 118 : 119 : public ChangeNotesCommit(AnyObjectId id) { 120 103 : super(id); 121 103 : } 122 : 123 : public List<String> getFooterLineValues(FooterKey key) { 124 103 : if (footerLines == null) { 125 103 : List<FooterLine> src = getFooterLines(); 126 103 : footerLines = MultimapBuilder.hashKeys(src.size()).arrayListValues(1).build(); 127 103 : for (FooterLine fl : src) { 128 103 : footerLines.put(fl.getKey().toLowerCase(), fl.getValue()); 129 103 : } 130 : } 131 103 : return footerLines.get(key.getName().toLowerCase()); 132 : } 133 : 134 : public boolean isAttentionSetCommitOnly(boolean hasChangeMessage) { 135 103 : return !hasChangeMessage 136 : && footerLines 137 44 : .keySet() 138 103 : .equals( 139 44 : Sets.newHashSet( 140 44 : FOOTER_PATCH_SET.getName().toLowerCase(), 141 44 : FOOTER_ATTENTION.getName().toLowerCase())); 142 : } 143 : }