Line data Source code
1 : // Copyright (C) 2012 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.sshd.commands; 16 : 17 : import static com.google.gerrit.common.data.GlobalCapability.MAINTAIN_SERVER; 18 : import static com.google.gerrit.common.data.GlobalCapability.RUN_GC; 19 : import static com.google.gerrit.sshd.CommandMetaData.Mode.MASTER_OR_SLAVE; 20 : import static java.util.stream.Collectors.toList; 21 : 22 : import com.google.common.collect.Lists; 23 : import com.google.gerrit.common.data.GarbageCollectionResult; 24 : import com.google.gerrit.common.data.GarbageCollectionResult.GcError; 25 : import com.google.gerrit.entities.Project; 26 : import com.google.gerrit.extensions.annotations.RequiresAnyCapability; 27 : import com.google.gerrit.server.git.GarbageCollection; 28 : import com.google.gerrit.server.project.ProjectCache; 29 : import com.google.gerrit.server.project.ProjectState; 30 : import com.google.gerrit.sshd.CommandMetaData; 31 : import com.google.gerrit.sshd.SshCommand; 32 : import com.google.inject.Inject; 33 : import java.util.ArrayList; 34 : import java.util.List; 35 : import org.kohsuke.args4j.Argument; 36 : import org.kohsuke.args4j.Option; 37 : 38 : /** Runs the Git garbage collection. */ 39 : @RequiresAnyCapability({RUN_GC, MAINTAIN_SERVER}) 40 : @CommandMetaData(name = "gc", description = "Run Git garbage collection", runsAt = MASTER_OR_SLAVE) 41 1 : public class GarbageCollectionCommand extends SshCommand { 42 : 43 : @Option(name = "--all", usage = "runs the Git garbage collection for all projects") 44 : private boolean all; 45 : 46 : @Option(name = "--show-progress", usage = "progress information is shown") 47 : private boolean showProgress; 48 : 49 : @Option(name = "--aggressive", usage = "run aggressive garbage collection") 50 : private boolean aggressive; 51 : 52 1 : @Argument( 53 : index = 0, 54 : required = false, 55 : multiValued = true, 56 : metaVar = "NAME", 57 : usage = "projects for which the Git garbage collection should be run") 58 : private List<ProjectState> projects = new ArrayList<>(); 59 : 60 : @Inject private ProjectCache projectCache; 61 : 62 : @Inject private GarbageCollection.Factory garbageCollectionFactory; 63 : 64 : @Override 65 : public void run() throws Exception { 66 1 : enableGracefulStop(); 67 1 : verifyCommandLine(); 68 1 : runGC(); 69 1 : } 70 : 71 : private void verifyCommandLine() throws UnloggedFailure { 72 1 : if (!all && projects.isEmpty()) { 73 0 : throw die("needs projects as command arguments or --all option"); 74 : } 75 1 : if (all && !projects.isEmpty()) { 76 0 : throw die("either specify projects as command arguments or use --all option"); 77 : } 78 1 : } 79 : 80 : private void runGC() { 81 : List<Project.NameKey> projectNames; 82 1 : if (all) { 83 1 : projectNames = Lists.newArrayList(projectCache.all()); 84 : } else { 85 1 : projectNames = projects.stream().map(ProjectState::getNameKey).collect(toList()); 86 : } 87 : 88 1 : GarbageCollectionResult result = 89 : garbageCollectionFactory 90 1 : .create() 91 1 : .run(projectNames, aggressive, showProgress ? stdout : null); 92 1 : if (result.hasErrors()) { 93 0 : for (GcError e : result.getErrors()) { 94 : String msg; 95 0 : switch (e.getType()) { 96 : case REPOSITORY_NOT_FOUND: 97 0 : msg = "error: project \"" + e.getProjectName() + "\" not found"; 98 0 : break; 99 : case GC_ALREADY_SCHEDULED: 100 0 : msg = 101 : "error: garbage collection for project \"" 102 0 : + e.getProjectName() 103 : + "\" was already scheduled"; 104 0 : break; 105 : case GC_FAILED: 106 0 : msg = "error: garbage collection for project \"" + e.getProjectName() + "\" failed"; 107 0 : break; 108 : default: 109 0 : msg = 110 : "error: garbage collection for project \"" 111 0 : + e.getProjectName() 112 : + "\" failed: " 113 0 : + e.getType(); 114 : } 115 0 : stdout.print(msg + "\n"); 116 0 : } 117 : } 118 1 : } 119 : }