Line data Source code
1 : // Copyright (C) 2014 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.project; 16 : 17 : import com.google.common.collect.Lists; 18 : import com.google.common.flogger.FluentLogger; 19 : import com.google.gerrit.extensions.api.projects.ReflogEntryInfo; 20 : import com.google.gerrit.extensions.restapi.MethodNotAllowedException; 21 : import com.google.gerrit.extensions.restapi.ResourceNotFoundException; 22 : import com.google.gerrit.extensions.restapi.Response; 23 : import com.google.gerrit.extensions.restapi.RestApiException; 24 : import com.google.gerrit.extensions.restapi.RestReadView; 25 : import com.google.gerrit.server.CommonConverters; 26 : import com.google.gerrit.server.args4j.InstantHandler; 27 : import com.google.gerrit.server.git.GitRepositoryManager; 28 : import com.google.gerrit.server.permissions.PermissionBackend; 29 : import com.google.gerrit.server.permissions.PermissionBackendException; 30 : import com.google.gerrit.server.permissions.ProjectPermission; 31 : import com.google.gerrit.server.project.BranchResource; 32 : import com.google.inject.Inject; 33 : import java.io.IOException; 34 : import java.time.Instant; 35 : import java.util.ArrayList; 36 : import java.util.List; 37 : import org.eclipse.jgit.lib.ReflogEntry; 38 : import org.eclipse.jgit.lib.ReflogReader; 39 : import org.eclipse.jgit.lib.Repository; 40 : import org.kohsuke.args4j.Option; 41 : 42 : public class GetReflog implements RestReadView<BranchResource> { 43 38 : private static final FluentLogger logger = FluentLogger.forEnclosingClass(); 44 : 45 : private final GitRepositoryManager repoManager; 46 : private final PermissionBackend permissionBackend; 47 : 48 : @Option( 49 : name = "--limit", 50 : aliases = {"-n"}, 51 : metaVar = "CNT", 52 : usage = "maximum number of reflog entries to list") 53 : public GetReflog setLimit(int limit) { 54 0 : this.limit = limit; 55 0 : return this; 56 : } 57 : 58 : @Option( 59 : name = "--from", 60 : metaVar = "TIMESTAMP", 61 : usage = 62 : "timestamp from which the reflog entries should be listed (UTC, format: " 63 : + InstantHandler.TIMESTAMP_FORMAT 64 : + ")") 65 : public GetReflog setFrom(Instant from) { 66 0 : this.from = from; 67 0 : return this; 68 : } 69 : 70 : @Option( 71 : name = "--to", 72 : metaVar = "TIMESTAMP", 73 : usage = 74 : "timestamp until which the reflog entries should be listed (UTC, format: " 75 : + InstantHandler.TIMESTAMP_FORMAT 76 : + ")") 77 : public GetReflog setTo(Instant to) { 78 0 : this.to = to; 79 0 : return this; 80 : } 81 : 82 : private int limit; 83 : private Instant from; 84 : private Instant to; 85 : 86 : @Inject 87 38 : public GetReflog(GitRepositoryManager repoManager, PermissionBackend permissionBackend) { 88 38 : this.repoManager = repoManager; 89 38 : this.permissionBackend = permissionBackend; 90 38 : } 91 : 92 : @Override 93 : public Response<List<ReflogEntryInfo>> apply(BranchResource rsrc) 94 : throws RestApiException, IOException, PermissionBackendException { 95 4 : permissionBackend 96 4 : .user(rsrc.getUser()) 97 4 : .project(rsrc.getNameKey()) 98 4 : .check(ProjectPermission.READ_REFLOG); 99 : 100 4 : try (Repository repo = repoManager.openRepository(rsrc.getNameKey())) { 101 : ReflogReader r; 102 : try { 103 3 : r = repo.getReflogReader(rsrc.getRef()); 104 1 : } catch (UnsupportedOperationException e) { 105 1 : String msg = "reflog not supported on repo " + rsrc.getNameKey().get(); 106 1 : logger.atSevere().log("%s", msg); 107 1 : throw new MethodNotAllowedException(msg, e); 108 3 : } 109 3 : if (r == null) { 110 0 : throw new ResourceNotFoundException(rsrc.getRef()); 111 : } 112 : List<ReflogEntry> entries; 113 3 : if (from == null && to == null) { 114 3 : entries = limit > 0 ? r.getReverseEntries(limit) : r.getReverseEntries(); 115 : } else { 116 0 : entries = limit > 0 ? new ArrayList<>(limit) : new ArrayList<>(); 117 0 : for (ReflogEntry e : r.getReverseEntries()) { 118 0 : Instant timestamp = e.getWho().getWhenAsInstant(); 119 0 : if ((from == null || from.isBefore(timestamp)) && (to == null || to.isAfter(timestamp))) { 120 0 : entries.add(e); 121 : } 122 0 : if (limit > 0 && entries.size() >= limit) { 123 0 : break; 124 : } 125 0 : } 126 : } 127 3 : return Response.ok(Lists.transform(entries, this::newReflogEntryInfo)); 128 : } 129 : } 130 : 131 : private ReflogEntryInfo newReflogEntryInfo(ReflogEntry e) { 132 2 : return new ReflogEntryInfo( 133 2 : e.getOldId().getName(), 134 2 : e.getNewId().getName(), 135 2 : CommonConverters.toGitPerson(e.getWho()), 136 2 : e.getComment()); 137 : } 138 : }