diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardResource.java index 5f578650e2..c18648db55 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardResource.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardResource.java @@ -30,17 +30,20 @@ public class DashboardResource implements RestResource { private final String pathName; private final ObjectId objId; private final Config config; + private final boolean projectDefault; DashboardResource(ProjectControl control, String refName, String pathName, ObjectId objId, - Config config) { + Config config, + boolean projectDefault) { this.control = control; this.refName = refName; this.pathName = pathName; this.objId = objId; this.config = config; + this.projectDefault = projectDefault; } public ProjectControl getControl() { @@ -62,4 +65,8 @@ public class DashboardResource implements RestResource { public Config getConfig() { return config; } + + public boolean isProjectDefault() { + return projectDefault; + } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardsCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardsCollection.java index f54c663a0f..989615d5f7 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardsCollection.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardsCollection.java @@ -22,8 +22,11 @@ import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.Lists; 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.ResourceNotFoundException; +import com.google.gerrit.extensions.restapi.RestApiException; +import com.google.gerrit.extensions.restapi.RestModifyView; import com.google.gerrit.extensions.restapi.RestView; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.UrlEncoded; @@ -46,18 +49,22 @@ import java.net.URLEncoder; import java.util.List; class DashboardsCollection implements - ChildCollection { + ChildCollection, + AcceptsCreate{ private final GitRepositoryManager gitManager; private final DynamicMap> views; private final Provider list; + private final Provider createDefault; @Inject DashboardsCollection(GitRepositoryManager gitManager, DynamicMap> views, - Provider list) { + Provider list, + Provider createDefault) { this.gitManager = gitManager; this.views = views; this.list = list; + this.createDefault = createDefault; } @Override @@ -65,12 +72,24 @@ class DashboardsCollection implements return list.get(); } + @SuppressWarnings("unchecked") + @Override + public RestModifyView create(ProjectResource parent, + String id) throws RestApiException { + if ("default".equals(id)) { + return createDefault.get(); + } + throw new ResourceNotFoundException(id); + } + @Override public DashboardResource parse(ProjectResource parent, String id) throws ResourceNotFoundException, Exception { ProjectControl ctl = parent.getControl(); + boolean def = false; if ("default".equals(id)) { id = defaultOf(ctl.getProject()); + def = true; } List parts = Lists.newArrayList( @@ -108,7 +127,7 @@ class DashboardsCollection implements throw new ResourceNotFoundException(); } BlobBasedConfig cfg = new BlobBasedConfig(null, git, objId); - return new DashboardResource(ctl, ref, path, objId, cfg); + return new DashboardResource(ctl, ref, path, objId, cfg, def); } finally { git.close(); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteDashboard.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteDashboard.java new file mode 100644 index 0000000000..84473f4fdb --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteDashboard.java @@ -0,0 +1,56 @@ +// Copyright (C) 2012 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.google.gerrit.server.project; + +import com.google.gerrit.extensions.restapi.AuthException; +import com.google.gerrit.extensions.restapi.BadRequestException; +import com.google.gerrit.extensions.restapi.MethodNotAllowedException; +import com.google.gerrit.extensions.restapi.ResourceConflictException; +import com.google.gerrit.extensions.restapi.RestModifyView; +import com.google.gerrit.server.project.DeleteDashboard.Input; +import com.google.inject.Inject; +import com.google.inject.Provider; + +class DeleteDashboard implements RestModifyView { + static class Input { + String commitMessage; + } + + private final Provider defaultSetter; + + @Inject + DeleteDashboard(Provider defaultSetter) { + this.defaultSetter = defaultSetter; + } + + @Override + public Class inputType() { + return Input.class; + } + + @Override + public Object apply(DashboardResource resource, Input input) + throws AuthException, BadRequestException, ResourceConflictException, + Exception { + if (resource.isProjectDefault()) { + SetDashboard.Input in = new SetDashboard.Input(); + in.commitMessage = input != null ? input.commitMessage : null; + return defaultSetter.get().apply(resource, in); + } + + // TODO: Implement delete of dashboards by API. + throw new MethodNotAllowedException(); + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDashboard.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDashboard.java index 612a8854cc..92bcc64c18 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDashboard.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDashboard.java @@ -17,12 +17,13 @@ package com.google.gerrit.server.project; import static com.google.gerrit.server.git.GitRepositoryManager.REFS_DASHBOARDS; import com.google.gerrit.extensions.restapi.RestReadView; +import com.google.gerrit.server.project.DashboardsCollection.DashboardInfo; import java.io.UnsupportedEncodingException; class GetDashboard implements RestReadView { @Override - public Object apply(DashboardResource resource) + public DashboardInfo apply(DashboardResource resource) throws UnsupportedEncodingException { return DashboardsCollection.parse( resource.getControl().getProject(), diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java index 651cb80207..2fc94670ee 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java @@ -36,5 +36,7 @@ public class Module extends RestApiModule { child(PROJECT_KIND, "dashboards").to(DashboardsCollection.class); get(DASHBOARD_KIND).to(GetDashboard.class); + put(DASHBOARD_KIND).to(SetDashboard.class); + delete(DASHBOARD_KIND).to(DeleteDashboard.class); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDashboard.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDashboard.java new file mode 100644 index 0000000000..7c4c886662 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDashboard.java @@ -0,0 +1,57 @@ +// Copyright (C) 2012 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.google.gerrit.server.project; + +import com.google.gerrit.extensions.restapi.AuthException; +import com.google.gerrit.extensions.restapi.BadRequestException; +import com.google.gerrit.extensions.restapi.DefaultInput; +import com.google.gerrit.extensions.restapi.MethodNotAllowedException; +import com.google.gerrit.extensions.restapi.ResourceConflictException; +import com.google.gerrit.extensions.restapi.RestModifyView; +import com.google.gerrit.server.project.SetDashboard.Input; +import com.google.inject.Inject; +import com.google.inject.Provider; + +class SetDashboard implements RestModifyView { + static class Input { + @DefaultInput + String id; + String commitMessage; + } + + private final Provider defaultSetter; + + @Inject + SetDashboard(Provider defaultSetter) { + this.defaultSetter = defaultSetter; + } + + @Override + public Class inputType() { + return Input.class; + } + + @Override + public Object apply(DashboardResource resource, Input input) + throws AuthException, BadRequestException, ResourceConflictException, + Exception { + if (resource.isProjectDefault()) { + return defaultSetter.get().apply(resource, input); + } + + // TODO: Implement creation/update of dashboards by API. + throw new MethodNotAllowedException(); + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java new file mode 100644 index 0000000000..ed7e77bffe --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java @@ -0,0 +1,142 @@ +// Copyright (C) 2012 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.google.gerrit.server.project; + +import com.google.common.base.Objects; +import com.google.common.base.Strings; +import com.google.gerrit.extensions.restapi.AuthException; +import com.google.gerrit.extensions.restapi.BadRequestException; +import com.google.gerrit.extensions.restapi.ResourceConflictException; +import com.google.gerrit.extensions.restapi.ResourceNotFoundException; +import com.google.gerrit.extensions.restapi.RestModifyView; +import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.server.IdentifiedUser; +import com.google.gerrit.server.git.MetaDataUpdate; +import com.google.gerrit.server.git.ProjectConfig; +import com.google.gerrit.server.project.DashboardsCollection.DashboardInfo; +import com.google.gerrit.server.project.SetDashboard.Input; +import com.google.inject.Inject; +import com.google.inject.Provider; + +import org.eclipse.jgit.errors.ConfigInvalidException; +import org.eclipse.jgit.errors.RepositoryNotFoundException; + +class SetDefaultDashboard implements RestModifyView { + private final ProjectCache cache; + private final MetaDataUpdate.Server updateFactory; + private final DashboardsCollection dashboards; + private final Provider get; + + @Inject + SetDefaultDashboard(ProjectCache cache, + MetaDataUpdate.Server updateFactory, + DashboardsCollection dashboards, + Provider get) { + this.cache = cache; + this.updateFactory = updateFactory; + this.dashboards = dashboards; + this.get = get; + } + + @Override + public Class inputType() { + return Input.class; + } + + @Override + public Object apply(DashboardResource resource, Input input) + throws AuthException, BadRequestException, ResourceConflictException, + Exception { + if (input == null) { + input = new Input(); // Delete would set input to null. + } + input.id = Strings.emptyToNull(input.id); + + ProjectControl ctl = resource.getControl(); + IdentifiedUser user = (IdentifiedUser) ctl.getCurrentUser(); + if (!ctl.isOwner()) { + throw new AuthException("not project owner"); + } + + DashboardResource target = null; + if (input.id != null) { + try { + target = dashboards.parse(new ProjectResource(ctl), input.id); + } catch (ResourceNotFoundException e) { + throw new BadRequestException("dashboard " + input.id + " not found"); + } + } + + try { + MetaDataUpdate md = updateFactory.create(ctl.getProject().getNameKey()); + try { + ProjectConfig config = ProjectConfig.read(md); + Project project = config.getProject(); + project.setLocalDefaultDashboard(input.id); + + String msg = Objects.firstNonNull( + Strings.emptyToNull(input.commitMessage), + input.id == null + ? "Removed default dashboard.\n" + : String.format("Changed default dashboard to %s.\n", input.id)); + if (!msg.endsWith("\n")) { + msg += "\n"; + } + md.setAuthor(user); + md.setMessage(msg); + config.commit(md); + cache.evict(ctl.getProject()); + + if (target != null) { + DashboardInfo info = get.get().apply(target); + info.isDefault = true; + return info; + } + return new Object(); + } finally { + md.close(); + } + } catch (RepositoryNotFoundException notFound) { + throw new ResourceNotFoundException(ctl.getProject().getName()); + } catch (ConfigInvalidException e) { + throw new ResourceConflictException(String.format( + "invalid project.config: %s", e.getMessage())); + } + } + + static class CreateDefault implements + RestModifyView { + private final Provider setDefault; + + @Inject + CreateDefault(Provider setDefault) { + this.setDefault = setDefault; + } + + @Override + public Class inputType() { + return SetDashboard.Input.class; + } + + @Override + public Object apply(ProjectResource resource, Input input) + throws AuthException, BadRequestException, ResourceConflictException, + Exception { + ProjectControl ctl = resource.getControl(); + return setDefault.get().apply( + new DashboardResource(ctl, null, null, null, null, true), input); + } + } +}