| // Copyright (C) 2015 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.googlesource.gerrit.plugins.importer; |
| |
| import static java.lang.String.format; |
| |
| import com.google.gerrit.extensions.annotations.PluginData; |
| import com.google.gerrit.extensions.annotations.RequiresCapability; |
| import com.google.gerrit.extensions.registration.DynamicMap; |
| import com.google.gerrit.extensions.restapi.AcceptsCreate; |
| import com.google.gerrit.extensions.restapi.ChildCollection; |
| import com.google.gerrit.extensions.restapi.IdString; |
| import com.google.gerrit.extensions.restapi.ResourceNotFoundException; |
| import com.google.gerrit.extensions.restapi.RestApiException; |
| import com.google.gerrit.extensions.restapi.RestView; |
| import com.google.gerrit.reviewdb.client.Project; |
| import com.google.gerrit.server.config.ConfigResource; |
| import com.google.inject.Inject; |
| import com.google.inject.Provider; |
| import com.google.inject.Singleton; |
| import java.io.File; |
| import java.io.IOException; |
| import java.nio.file.Path; |
| |
| @Singleton |
| @RequiresCapability(ImportCapability.ID) |
| public class ProjectsCollection |
| implements ChildCollection<ConfigResource, ImportProjectResource>, |
| AcceptsCreate<ConfigResource> { |
| |
| class FileSystemLayout { |
| |
| private String SUFFIX_IMPORT_STATUS_FILE = ".$importstatus"; |
| |
| public File getLockRoot() { |
| return lockRoot; |
| } |
| |
| File getImportStatusFile(String id) { |
| return new File(lockRoot, format("%s%s", id, SUFFIX_IMPORT_STATUS_FILE)); |
| } |
| |
| String resolveProjectName(File f) throws IOException { |
| if (!f.isFile()) { |
| throw new RuntimeException( |
| format( |
| "'%s' is not a file. Project names" |
| + "can only be resolved for existing files, not for directories.", |
| f)); |
| } |
| |
| if (!f.getName().endsWith(SUFFIX_IMPORT_STATUS_FILE)) { |
| throw new RuntimeException( |
| format( |
| "'%s' is not a valid import status" + "file. Invalid appendix. Should be '%s'.", |
| f, SUFFIX_IMPORT_STATUS_FILE)); |
| } |
| String diff = diff(lockRoot, f); |
| return diff.substring(0, diff.length() - SUFFIX_IMPORT_STATUS_FILE.length()); |
| } |
| |
| /** |
| * Returns the path between two file instances. The child instance is expected to be a child of |
| * the parent instance. |
| * |
| * @param parent |
| * @param child |
| * @return The path between parent and child. |
| * @throws IOException in case <code>child</code> is not a child of <code>parent</code>. |
| */ |
| private String diff(File parent, File child) throws IOException { |
| Path parentPath = parent.getAbsoluteFile().toPath(); |
| Path childPath = child.getAbsoluteFile().toPath(); |
| if (childPath.startsWith(parentPath)) { |
| return parentPath.relativize(childPath).toString(); |
| } |
| throw new IOException(String.format("'%s' is not a child of '%s'.", child, parent)); |
| } |
| } |
| |
| public final FileSystemLayout FS_LAYOUT = new FileSystemLayout(); |
| |
| private final DynamicMap<RestView<ImportProjectResource>> views; |
| private final ImportProject.Factory importProjectFactory; |
| private final Provider<ListImportedProjects> list; |
| private final File lockRoot; |
| |
| @Inject |
| ProjectsCollection( |
| DynamicMap<RestView<ImportProjectResource>> views, |
| ImportProject.Factory importProjectFactory, |
| Provider<ListImportedProjects> list, |
| @PluginData File data) { |
| this.views = views; |
| this.importProjectFactory = importProjectFactory; |
| this.list = list; |
| this.lockRoot = data; |
| } |
| |
| @Override |
| public RestView<ConfigResource> list() { |
| return list.get(); |
| } |
| |
| @Override |
| public ImportProjectResource parse(ConfigResource parent, IdString id) |
| throws ResourceNotFoundException { |
| return parse(id.get()); |
| } |
| |
| public ImportProjectResource parse(String id) throws ResourceNotFoundException { |
| File f = FS_LAYOUT.getImportStatusFile(id); |
| if (!f.exists()) { |
| throw new ResourceNotFoundException(id); |
| } |
| |
| return new ImportProjectResource(id, f); |
| } |
| |
| @Override |
| public DynamicMap<RestView<ImportProjectResource>> views() { |
| return views; |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public ImportProject create(ConfigResource parent, IdString id) throws RestApiException { |
| return importProjectFactory.create(new Project.NameKey(id.get())); |
| } |
| } |