Add REST API for 'create project'
Change-Id: Ifbeb2b02ece00bf7210cb21bdd41a26d2e10450d
This commit is contained in:
parent
1d028b8f60
commit
798ea128a4
@ -129,6 +129,50 @@ describes the project.
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
[[create-project]]
|
||||||
|
Create Project
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
[verse]
|
||||||
|
'PUT /projects/link:#project-name[\{project-name\}]'
|
||||||
|
|
||||||
|
Creates a new project.
|
||||||
|
|
||||||
|
In the request body additional data for the project can be provided as
|
||||||
|
link:#project-input[ProjectInput].
|
||||||
|
|
||||||
|
.Request
|
||||||
|
----
|
||||||
|
PUT /projects/MyProject HTTP/1.0
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
|
||||||
|
{
|
||||||
|
"description": "This is a demo project.",
|
||||||
|
"submit_type": "CHERRY_PICK",
|
||||||
|
"owners": [
|
||||||
|
"MyProject-Owners"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
As response the link:#project-info[ProjectInfo] entity is returned that
|
||||||
|
describes the created project.
|
||||||
|
|
||||||
|
.Response
|
||||||
|
----
|
||||||
|
HTTP/1.1 201 Created
|
||||||
|
Content-Disposition: attachment
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
|
||||||
|
)]}'
|
||||||
|
{
|
||||||
|
"kind": "gerritcodereview#project",
|
||||||
|
"id": "MyProject",
|
||||||
|
"name": "MyProject",
|
||||||
|
"parent": "All-Projects",
|
||||||
|
"description": "This is a demo project."
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
[[get-project-description]]
|
[[get-project-description]]
|
||||||
Get Project Description
|
Get Project Description
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -627,6 +671,56 @@ is increased for each non-visible project).
|
|||||||
|`branches` |optional|Map of branch names to HEAD revisions.
|
|`branches` |optional|Map of branch names to HEAD revisions.
|
||||||
|===========================
|
|===========================
|
||||||
|
|
||||||
|
[[project-input]]
|
||||||
|
ProjectInput
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
The `ProjectInput` entity contains information for the creation of
|
||||||
|
a new project.
|
||||||
|
|
||||||
|
[options="header",width="50%",cols="1,^2,4"]
|
||||||
|
|=========================================
|
||||||
|
|Field Name ||Description
|
||||||
|
|`name` |optional|
|
||||||
|
The name of the project (not encoded). +
|
||||||
|
If set, must match the project name in the URL.
|
||||||
|
|`parent` |optional|
|
||||||
|
The name of the parent project. +
|
||||||
|
If not set, the `All-Projects` project will be the parent project.
|
||||||
|
|`description` |optional|The description of the project.
|
||||||
|
|`permissions_only` |`false` if not set|
|
||||||
|
Whether a permission-only project should be created.
|
||||||
|
|`create_empty_commit` |`false` if not set|
|
||||||
|
Whether an empty initial commit should be created.
|
||||||
|
|`submit_type` |optional|
|
||||||
|
The submit type that should be set for the project
|
||||||
|
(`MERGE_IF_NECESSARY`, `REBASE_IF_NECESSARY`, `FAST_FORWARD_ONLY`,
|
||||||
|
`MERGE_ALWAYS`, `CHERRY_PICK`). +
|
||||||
|
If not set, `MERGE_IF_NECESSARY` is set as submit type.
|
||||||
|
|`branches` |optional|
|
||||||
|
A list of branches that should be initially created. +
|
||||||
|
For the branch names the `refs/heads/` prefix can be omitted.
|
||||||
|
|`owners` |optional|
|
||||||
|
A list of groups that should be assigned as project owner. +
|
||||||
|
Each group in the list must be specified as
|
||||||
|
link:rest-api-groups.html#group-id[group-id]. +
|
||||||
|
If not set, the link:config-gerrit.html#repository.name.ownerGroup[
|
||||||
|
groups that are configured as default owners] are set as project
|
||||||
|
owners.
|
||||||
|
|`use_contributor_agreements`|`INHERIT` if not set|
|
||||||
|
Whether contributor agreements should be used for the project (`TRUE`,
|
||||||
|
`FALSE`, `INHERIT`).
|
||||||
|
|`use_signed_off_by` |`INHERIT` if not set|
|
||||||
|
Whether the usage of 'Signed-Off-By' footers is required for the
|
||||||
|
project (`TRUE`, `FALSE`, `INHERIT`).
|
||||||
|
|`use_content_merge` |`INHERIT` if not set|
|
||||||
|
Whether content merge should be enabled for the project (`TRUE`,
|
||||||
|
`FALSE`, `INHERIT`). +
|
||||||
|
`FALSE`, if the `submit_type` is `FAST_FORWARD_ONLY`.
|
||||||
|
|`require_change_id` |`INHERIT` if not set|
|
||||||
|
Whether the usage of Change-Ids is required for the project (`TRUE`,
|
||||||
|
`FALSE`, `INHERIT`).
|
||||||
|
|=========================================
|
||||||
|
|
||||||
[[project-parent-input]]
|
[[project-parent-input]]
|
||||||
ProjectParentInput
|
ProjectParentInput
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (C) 2013 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.extensions.restapi;
|
||||||
|
|
||||||
|
/** Resource referenced in the request body is not found (HTTP 422 Unprocessable Entity). */
|
||||||
|
public class UnprocessableEntityException extends RestApiException {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UnprocessableEntityException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,9 @@ import com.google.gerrit.client.Dispatcher;
|
|||||||
import com.google.gerrit.client.ErrorDialog;
|
import com.google.gerrit.client.ErrorDialog;
|
||||||
import com.google.gerrit.client.Gerrit;
|
import com.google.gerrit.client.Gerrit;
|
||||||
import com.google.gerrit.client.NotFoundScreen;
|
import com.google.gerrit.client.NotFoundScreen;
|
||||||
|
import com.google.gerrit.client.VoidResult;
|
||||||
import com.google.gerrit.client.account.AccountCapabilities;
|
import com.google.gerrit.client.account.AccountCapabilities;
|
||||||
|
import com.google.gerrit.client.projects.ProjectApi;
|
||||||
import com.google.gerrit.client.projects.ProjectInfo;
|
import com.google.gerrit.client.projects.ProjectInfo;
|
||||||
import com.google.gerrit.client.projects.ProjectMap;
|
import com.google.gerrit.client.projects.ProjectMap;
|
||||||
import com.google.gerrit.client.rpc.GerritCallback;
|
import com.google.gerrit.client.rpc.GerritCallback;
|
||||||
@ -38,6 +40,7 @@ import com.google.gwt.event.dom.client.KeyCodes;
|
|||||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||||
import com.google.gwt.event.dom.client.KeyPressHandler;
|
import com.google.gwt.event.dom.client.KeyPressHandler;
|
||||||
import com.google.gwt.user.client.History;
|
import com.google.gwt.user.client.History;
|
||||||
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
import com.google.gwt.user.client.ui.Anchor;
|
import com.google.gwt.user.client.ui.Anchor;
|
||||||
import com.google.gwt.user.client.ui.Button;
|
import com.google.gwt.user.client.ui.Button;
|
||||||
import com.google.gwt.user.client.ui.CheckBox;
|
import com.google.gwt.user.client.ui.CheckBox;
|
||||||
@ -45,7 +48,6 @@ import com.google.gwt.user.client.ui.Grid;
|
|||||||
import com.google.gwt.user.client.ui.SuggestBox;
|
import com.google.gwt.user.client.ui.SuggestBox;
|
||||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||||
import com.google.gwtexpui.globalkey.client.NpTextBox;
|
import com.google.gwtexpui.globalkey.client.NpTextBox;
|
||||||
import com.google.gwtjsonrpc.common.VoidResult;
|
|
||||||
|
|
||||||
public class CreateProjectScreen extends Screen {
|
public class CreateProjectScreen extends Screen {
|
||||||
private Grid grid;
|
private Grid grid;
|
||||||
@ -231,9 +233,8 @@ public class CreateProjectScreen extends Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enableForm(false);
|
enableForm(false);
|
||||||
Util.PROJECT_SVC.createNewProject(projectName, parentName,
|
ProjectApi.createProject(projectName, parentName, emptyCommit.getValue(),
|
||||||
emptyCommit.getValue(), permissionsOnly.getValue(),
|
permissionsOnly.getValue(), new AsyncCallback<VoidResult>() {
|
||||||
new GerritCallback<VoidResult>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(VoidResult result) {
|
public void onSuccess(VoidResult result) {
|
||||||
String nameWithoutSuffix = ProjectUtil.stripGitSuffix(projectName);
|
String nameWithoutSuffix = ProjectUtil.stripGitSuffix(projectName);
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright (C) 2013 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.client.projects;
|
||||||
|
|
||||||
|
import com.google.gerrit.client.VoidResult;
|
||||||
|
import com.google.gerrit.client.rpc.RestApi;
|
||||||
|
import com.google.gwt.core.client.JavaScriptObject;
|
||||||
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
|
|
||||||
|
public class ProjectApi {
|
||||||
|
/** Create a new project */
|
||||||
|
public static void createProject(String projectName, String parent,
|
||||||
|
Boolean createEmptyCcommit, Boolean permissionsOnly,
|
||||||
|
AsyncCallback<VoidResult> asyncCallback) {
|
||||||
|
ProjectInput input = ProjectInput.create();
|
||||||
|
input.setName(projectName);
|
||||||
|
input.setParent(parent);
|
||||||
|
input.setPermissionsOnly(permissionsOnly);
|
||||||
|
input.setCreateEmptyCommit(createEmptyCcommit);
|
||||||
|
new RestApi("/projects/").id(projectName).ifNoneMatch()
|
||||||
|
.put(input, asyncCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ProjectInput extends JavaScriptObject {
|
||||||
|
static ProjectInput create() {
|
||||||
|
return (ProjectInput) createObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ProjectInput() {
|
||||||
|
}
|
||||||
|
|
||||||
|
final native void setName(String n) /*-{ if(n)this.name=n; }-*/;
|
||||||
|
|
||||||
|
final native void setParent(String p) /*-{ if(p)this.parent=p; }-*/;
|
||||||
|
|
||||||
|
final native void setPermissionsOnly(boolean po) /*-{ if(po)this.permissions_only=po; }-*/;
|
||||||
|
|
||||||
|
final native void setCreateEmptyCommit(boolean cc) /*-{ if(cc)this.create_empty_commit=cc; }-*/;
|
||||||
|
}
|
||||||
|
}
|
@ -62,6 +62,7 @@ import com.google.gerrit.extensions.restapi.RestReadView;
|
|||||||
import com.google.gerrit.extensions.restapi.RestResource;
|
import com.google.gerrit.extensions.restapi.RestResource;
|
||||||
import com.google.gerrit.extensions.restapi.RestView;
|
import com.google.gerrit.extensions.restapi.RestView;
|
||||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||||
|
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
|
||||||
import com.google.gerrit.httpd.WebSession;
|
import com.google.gerrit.httpd.WebSession;
|
||||||
import com.google.gerrit.server.AccessPath;
|
import com.google.gerrit.server.AccessPath;
|
||||||
import com.google.gerrit.server.AnonymousUser;
|
import com.google.gerrit.server.AnonymousUser;
|
||||||
@ -319,6 +320,9 @@ public class RestApiServlet extends HttpServlet {
|
|||||||
Objects.firstNonNull(e.getMessage(), "Precondition failed"));
|
Objects.firstNonNull(e.getMessage(), "Precondition failed"));
|
||||||
} catch (ResourceNotFoundException e) {
|
} catch (ResourceNotFoundException e) {
|
||||||
replyError(res, status = SC_NOT_FOUND, "Not found");
|
replyError(res, status = SC_NOT_FOUND, "Not found");
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
replyError(res, status = 422,
|
||||||
|
Objects.firstNonNull(e.getMessage(), "Unprocessable Entity"));
|
||||||
} catch (AmbiguousViewException e) {
|
} catch (AmbiguousViewException e) {
|
||||||
replyError(res, status = SC_NOT_FOUND, e.getMessage());
|
replyError(res, status = SC_NOT_FOUND, e.getMessage());
|
||||||
} catch (MalformedJsonException e) {
|
} catch (MalformedJsonException e) {
|
||||||
|
@ -91,6 +91,7 @@ import com.google.gerrit.server.patch.PatchListCacheImpl;
|
|||||||
import com.google.gerrit.server.patch.PatchSetInfoFactory;
|
import com.google.gerrit.server.patch.PatchSetInfoFactory;
|
||||||
import com.google.gerrit.server.project.AccessControlModule;
|
import com.google.gerrit.server.project.AccessControlModule;
|
||||||
import com.google.gerrit.server.project.ChangeControl;
|
import com.google.gerrit.server.project.ChangeControl;
|
||||||
|
import com.google.gerrit.server.project.PerformCreateProject;
|
||||||
import com.google.gerrit.server.project.PermissionCollection;
|
import com.google.gerrit.server.project.PermissionCollection;
|
||||||
import com.google.gerrit.server.project.ProjectCacheImpl;
|
import com.google.gerrit.server.project.ProjectCacheImpl;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
@ -185,6 +186,7 @@ public class GerritGlobalModule extends FactoryModule {
|
|||||||
factory(ProjectState.Factory.class);
|
factory(ProjectState.Factory.class);
|
||||||
factory(RebasedPatchSetSender.Factory.class);
|
factory(RebasedPatchSetSender.Factory.class);
|
||||||
factory(ReplacePatchSetSender.Factory.class);
|
factory(ReplacePatchSetSender.Factory.class);
|
||||||
|
factory(PerformCreateProject.Factory.class);
|
||||||
bind(PermissionCollection.Factory.class);
|
bind(PermissionCollection.Factory.class);
|
||||||
bind(AccountVisibility.class)
|
bind(AccountVisibility.class)
|
||||||
.toProvider(AccountVisibilityProvider.class)
|
.toProvider(AccountVisibilityProvider.class)
|
||||||
|
@ -23,11 +23,9 @@ import com.google.gerrit.server.changedetail.DeleteDraftPatchSet;
|
|||||||
import com.google.gerrit.server.changedetail.PublishDraft;
|
import com.google.gerrit.server.changedetail.PublishDraft;
|
||||||
import com.google.gerrit.server.git.BanCommit;
|
import com.google.gerrit.server.git.BanCommit;
|
||||||
import com.google.gerrit.server.git.MergeOp;
|
import com.google.gerrit.server.git.MergeOp;
|
||||||
import com.google.gerrit.server.git.MetaDataUpdate;
|
|
||||||
import com.google.gerrit.server.git.SubmoduleOp;
|
import com.google.gerrit.server.git.SubmoduleOp;
|
||||||
import com.google.gerrit.server.patch.RemoveReviewer;
|
import com.google.gerrit.server.patch.RemoveReviewer;
|
||||||
import com.google.gerrit.server.project.ChangeControl;
|
import com.google.gerrit.server.project.ChangeControl;
|
||||||
import com.google.gerrit.server.project.PerformCreateProject;
|
|
||||||
import com.google.gerrit.server.project.PerRequestProjectControlCache;
|
import com.google.gerrit.server.project.PerRequestProjectControlCache;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gerrit.server.project.SuggestParentCandidates;
|
import com.google.gerrit.server.project.SuggestParentCandidates;
|
||||||
@ -40,7 +38,6 @@ public class GerritRequestModule extends FactoryModule {
|
|||||||
bind(RequestCleanup.class).in(RequestScoped.class);
|
bind(RequestCleanup.class).in(RequestScoped.class);
|
||||||
bind(RequestScopedReviewDbProvider.class);
|
bind(RequestScopedReviewDbProvider.class);
|
||||||
bind(IdentifiedUser.RequestFactory.class).in(SINGLETON);
|
bind(IdentifiedUser.RequestFactory.class).in(SINGLETON);
|
||||||
bind(MetaDataUpdate.User.class).in(RequestScoped.class);
|
|
||||||
bind(ApprovalsUtil.class);
|
bind(ApprovalsUtil.class);
|
||||||
|
|
||||||
bind(PerRequestProjectControlCache.class).in(RequestScoped.class);
|
bind(PerRequestProjectControlCache.class).in(RequestScoped.class);
|
||||||
@ -56,7 +53,6 @@ public class GerritRequestModule extends FactoryModule {
|
|||||||
factory(DeleteDraftPatchSet.Factory.class);
|
factory(DeleteDraftPatchSet.Factory.class);
|
||||||
factory(PublishDraft.Factory.class);
|
factory(PublishDraft.Factory.class);
|
||||||
factory(RemoveReviewer.Factory.class);
|
factory(RemoveReviewer.Factory.class);
|
||||||
factory(PerformCreateProject.Factory.class);
|
|
||||||
factory(SuggestParentCandidates.Factory.class);
|
factory(SuggestParentCandidates.Factory.class);
|
||||||
factory(BanCommit.Factory.class);
|
factory(BanCommit.Factory.class);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,136 @@
|
|||||||
|
// Copyright (C) 2013 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.common.collect.Lists;
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
|
import com.google.gerrit.common.errors.ProjectCreationFailedException;
|
||||||
|
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||||
|
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||||
|
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||||
|
import com.google.gerrit.extensions.restapi.Response;
|
||||||
|
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||||
|
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||||
|
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
|
||||||
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||||
|
import com.google.gerrit.server.group.GroupsCollection;
|
||||||
|
import com.google.gerrit.server.project.CreateProject.Input;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RequiresCapability(GlobalCapability.CREATE_PROJECT)
|
||||||
|
class CreateProject implements RestModifyView<TopLevelResource, Input> {
|
||||||
|
static class Input {
|
||||||
|
String name;
|
||||||
|
String parent;
|
||||||
|
String description;
|
||||||
|
boolean permissionsOnly;
|
||||||
|
boolean createEmptyCommit;
|
||||||
|
SubmitType submitType;
|
||||||
|
List<String> branches;
|
||||||
|
List<String> owners;
|
||||||
|
InheritableBoolean useContributorAgreements;
|
||||||
|
InheritableBoolean useSignedOffBy;
|
||||||
|
InheritableBoolean useContentMerge;
|
||||||
|
InheritableBoolean requireChangeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
static interface Factory {
|
||||||
|
CreateProject create(String name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final PerformCreateProject.Factory createProjectFactory;
|
||||||
|
private final Provider<ProjectsCollection> projectsCollection;
|
||||||
|
private final Provider<GroupsCollection> groupsCollection;
|
||||||
|
private final ProjectJson json;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CreateProject(PerformCreateProject.Factory performCreateProjectFactory,
|
||||||
|
Provider<ProjectsCollection> projectsCollection,
|
||||||
|
Provider<GroupsCollection> groupsCollection, ProjectJson json,
|
||||||
|
@Assisted String name) {
|
||||||
|
this.createProjectFactory = performCreateProjectFactory;
|
||||||
|
this.projectsCollection = projectsCollection;
|
||||||
|
this.groupsCollection = groupsCollection;
|
||||||
|
this.json = json;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object apply(TopLevelResource resource, Input input)
|
||||||
|
throws BadRequestException, UnprocessableEntityException,
|
||||||
|
ProjectCreationFailedException {
|
||||||
|
if (input == null) {
|
||||||
|
input = new Input();
|
||||||
|
}
|
||||||
|
if (input.name != null && !name.equals(input.name)) {
|
||||||
|
throw new BadRequestException("name must match URL");
|
||||||
|
}
|
||||||
|
|
||||||
|
final CreateProjectArgs args = new CreateProjectArgs();
|
||||||
|
args.setProjectName(name);
|
||||||
|
if (!Strings.isNullOrEmpty(input.parent)) {
|
||||||
|
try {
|
||||||
|
args.newParent =
|
||||||
|
projectsCollection.get().parse(input.parent).getControl();
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
throw new UnprocessableEntityException(String.format(
|
||||||
|
"parent project \"%s\" not found", input.parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args.createEmptyCommit = input.createEmptyCommit;
|
||||||
|
args.permissionsOnly = input.permissionsOnly;
|
||||||
|
args.projectDescription = Strings.emptyToNull(input.description);
|
||||||
|
args.submitType =
|
||||||
|
Objects.firstNonNull(input.submitType, SubmitType.MERGE_IF_NECESSARY);
|
||||||
|
args.branch = input.branches;
|
||||||
|
if (input.owners != null) {
|
||||||
|
List<AccountGroup.UUID> ownerIds =
|
||||||
|
Lists.newArrayListWithCapacity(input.owners.size());
|
||||||
|
for (String owner : input.owners) {
|
||||||
|
try {
|
||||||
|
ownerIds.add(groupsCollection.get().parse(owner).getGroupUUID());
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
throw new UnprocessableEntityException(String.format(
|
||||||
|
"group \"%s\" not found", owner));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args.ownerIds = ownerIds;
|
||||||
|
}
|
||||||
|
args.contributorAgreements =
|
||||||
|
Objects.firstNonNull(input.useContributorAgreements,
|
||||||
|
InheritableBoolean.INHERIT);
|
||||||
|
args.signedOffBy =
|
||||||
|
Objects.firstNonNull(input.useSignedOffBy, InheritableBoolean.INHERIT);
|
||||||
|
args.contentMerge =
|
||||||
|
input.submitType == SubmitType.FAST_FORWARD_ONLY
|
||||||
|
? InheritableBoolean.FALSE : Objects.firstNonNull(
|
||||||
|
input.useContentMerge, InheritableBoolean.INHERIT);
|
||||||
|
args.changeIdRequired =
|
||||||
|
Objects.firstNonNull(input.requireChangeId, InheritableBoolean.INHERIT);
|
||||||
|
|
||||||
|
Project p = createProjectFactory.create(args).createProject();
|
||||||
|
return Response.created(json.format(p));
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,7 @@ public class CreateProjectArgs {
|
|||||||
signedOffBy = InheritableBoolean.INHERIT;
|
signedOffBy = InheritableBoolean.INHERIT;
|
||||||
contentMerge = InheritableBoolean.INHERIT;
|
contentMerge = InheritableBoolean.INHERIT;
|
||||||
changeIdRequired = InheritableBoolean.INHERIT;
|
changeIdRequired = InheritableBoolean.INHERIT;
|
||||||
|
submitType = SubmitType.MERGE_IF_NECESSARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Project.NameKey getProject() {
|
public Project.NameKey getProject() {
|
||||||
|
@ -14,43 +14,20 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.project;
|
package com.google.gerrit.server.project;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
import com.google.gerrit.extensions.restapi.Url;
|
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
|
||||||
import com.google.gerrit.server.config.AllProjectsName;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
class GetProject implements RestReadView<ProjectResource> {
|
class GetProject implements RestReadView<ProjectResource> {
|
||||||
|
|
||||||
private final AllProjectsName allProjects;
|
private final ProjectJson json;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GetProject(AllProjectsName allProjects) {
|
GetProject(ProjectJson json) {
|
||||||
this.allProjects = allProjects;
|
this.json = json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object apply(ProjectResource resource) {
|
public Object apply(ProjectResource rsrc) {
|
||||||
Project project = resource.getControl().getProject();
|
return json.format(rsrc);
|
||||||
ProjectInfo info = new ProjectInfo();
|
|
||||||
info.name = resource.getName();
|
|
||||||
Project.NameKey parentName = project.getParent(allProjects);
|
|
||||||
info.parent = parentName != null ? parentName.get() : null;
|
|
||||||
info.description = Strings.emptyToNull(project.getDescription());
|
|
||||||
info.finish();
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ProjectInfo {
|
|
||||||
final String kind = "gerritcodereview#project";
|
|
||||||
String id;
|
|
||||||
String name;
|
|
||||||
String parent;
|
|
||||||
String description;
|
|
||||||
|
|
||||||
void finish() {
|
|
||||||
id = Url.encode(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ import static com.google.gerrit.server.project.ProjectResource.PROJECT_KIND;
|
|||||||
|
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||||
import com.google.gerrit.extensions.restapi.RestApiModule;
|
import com.google.gerrit.extensions.restapi.RestApiModule;
|
||||||
|
import com.google.gerrit.server.project.CreateProject;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
|
||||||
public class Module extends RestApiModule {
|
public class Module extends RestApiModule {
|
||||||
@Override
|
@Override
|
||||||
@ -29,6 +31,7 @@ public class Module extends RestApiModule {
|
|||||||
DynamicMap.mapOf(binder(), PROJECT_KIND);
|
DynamicMap.mapOf(binder(), PROJECT_KIND);
|
||||||
DynamicMap.mapOf(binder(), DASHBOARD_KIND);
|
DynamicMap.mapOf(binder(), DASHBOARD_KIND);
|
||||||
|
|
||||||
|
put(PROJECT_KIND).to(PutProject.class);
|
||||||
get(PROJECT_KIND).to(GetProject.class);
|
get(PROJECT_KIND).to(GetProject.class);
|
||||||
get(PROJECT_KIND, "description").to(GetDescription.class);
|
get(PROJECT_KIND, "description").to(GetDescription.class);
|
||||||
put(PROJECT_KIND, "description").to(PutDescription.class);
|
put(PROJECT_KIND, "description").to(PutDescription.class);
|
||||||
@ -41,5 +44,6 @@ public class Module extends RestApiModule {
|
|||||||
get(DASHBOARD_KIND).to(GetDashboard.class);
|
get(DASHBOARD_KIND).to(GetDashboard.class);
|
||||||
put(DASHBOARD_KIND).to(SetDashboard.class);
|
put(DASHBOARD_KIND).to(SetDashboard.class);
|
||||||
delete(DASHBOARD_KIND).to(DeleteDashboard.class);
|
delete(DASHBOARD_KIND).to(DeleteDashboard.class);
|
||||||
|
install(new FactoryModuleBuilder().build(CreateProject.Factory.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ public class PerformCreateProject {
|
|||||||
this.metaDataUpdateFactory = metaDataUpdateFactory;
|
this.metaDataUpdateFactory = metaDataUpdateFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createProject() throws ProjectCreationFailedException {
|
public Project createProject() throws ProjectCreationFailedException {
|
||||||
validateParameters();
|
validateParameters();
|
||||||
final Project.NameKey nameKey = createProjectArgs.getProject();
|
final Project.NameKey nameKey = createProjectArgs.getProject();
|
||||||
try {
|
try {
|
||||||
@ -133,6 +133,8 @@ public class PerformCreateProject {
|
|||||||
&& createProjectArgs.createEmptyCommit) {
|
&& createProjectArgs.createEmptyCommit) {
|
||||||
createEmptyCommits(repo, nameKey, createProjectArgs.branch);
|
createEmptyCommits(repo, nameKey, createProjectArgs.branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return projectCache.get(nameKey).getProject();
|
||||||
} finally {
|
} finally {
|
||||||
repo.close();
|
repo.close();
|
||||||
}
|
}
|
||||||
@ -150,6 +152,7 @@ public class PerformCreateProject {
|
|||||||
if (repo.getObjectDatabase().exists()) {
|
if (repo.getObjectDatabase().exists()) {
|
||||||
throw new ProjectCreationFailedException("project \"" + nameKey + "\" exists");
|
throw new ProjectCreationFailedException("project \"" + nameKey + "\" exists");
|
||||||
}
|
}
|
||||||
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
repo.close();
|
repo.close();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright (C) 2013 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.Strings;
|
||||||
|
import com.google.gerrit.extensions.restapi.Url;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
public class ProjectJson {
|
||||||
|
|
||||||
|
private final AllProjectsName allProjects;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ProjectJson(AllProjectsName allProjects) {
|
||||||
|
this.allProjects = allProjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProjectInfo format(ProjectResource rsrc) {
|
||||||
|
return format(rsrc.getControl().getProject());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProjectInfo format(Project p) {
|
||||||
|
ProjectInfo info = new ProjectInfo();
|
||||||
|
info.name = p.getName();
|
||||||
|
Project.NameKey parentName = p.getParent(allProjects);
|
||||||
|
info.parent = parentName != null ? parentName.get() : null;
|
||||||
|
info.description = Strings.emptyToNull(p.getDescription());
|
||||||
|
info.finish();
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ProjectInfo {
|
||||||
|
final String kind = "gerritcodereview#project";
|
||||||
|
String id;
|
||||||
|
String name;
|
||||||
|
String parent;
|
||||||
|
String description;
|
||||||
|
|
||||||
|
void finish() {
|
||||||
|
id = Url.encode(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@
|
|||||||
package com.google.gerrit.server.project;
|
package com.google.gerrit.server.project;
|
||||||
|
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||||
|
import com.google.gerrit.extensions.restapi.AcceptsCreate;
|
||||||
import com.google.gerrit.extensions.restapi.IdString;
|
import com.google.gerrit.extensions.restapi.IdString;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||||
import com.google.gerrit.extensions.restapi.RestCollection;
|
import com.google.gerrit.extensions.restapi.RestCollection;
|
||||||
@ -27,21 +28,24 @@ import com.google.inject.Inject;
|
|||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
public class ProjectsCollection implements
|
public class ProjectsCollection implements
|
||||||
RestCollection<TopLevelResource, ProjectResource> {
|
RestCollection<TopLevelResource, ProjectResource>,
|
||||||
|
AcceptsCreate<TopLevelResource> {
|
||||||
private final DynamicMap<RestView<ProjectResource>> views;
|
private final DynamicMap<RestView<ProjectResource>> views;
|
||||||
private final Provider<ListProjects> list;
|
private final Provider<ListProjects> list;
|
||||||
private final ProjectControl.GenericFactory controlFactory;
|
private final ProjectControl.GenericFactory controlFactory;
|
||||||
private final Provider<CurrentUser> user;
|
private final Provider<CurrentUser> user;
|
||||||
|
private final CreateProject.Factory createProjectFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ProjectsCollection(DynamicMap<RestView<ProjectResource>> views,
|
ProjectsCollection(DynamicMap<RestView<ProjectResource>> views,
|
||||||
Provider<ListProjects> list,
|
Provider<ListProjects> list,
|
||||||
ProjectControl.GenericFactory controlFactory,
|
ProjectControl.GenericFactory controlFactory,
|
||||||
Provider<CurrentUser> user) {
|
CreateProject.Factory factory, Provider<CurrentUser> user) {
|
||||||
this.views = views;
|
this.views = views;
|
||||||
this.list = list;
|
this.list = list;
|
||||||
this.controlFactory = controlFactory;
|
this.controlFactory = controlFactory;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
this.createProjectFactory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -52,10 +56,15 @@ public class ProjectsCollection implements
|
|||||||
@Override
|
@Override
|
||||||
public ProjectResource parse(TopLevelResource parent, IdString id)
|
public ProjectResource parse(TopLevelResource parent, IdString id)
|
||||||
throws ResourceNotFoundException {
|
throws ResourceNotFoundException {
|
||||||
|
return parse(id.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProjectResource parse(String id)
|
||||||
|
throws ResourceNotFoundException {
|
||||||
ProjectControl ctl;
|
ProjectControl ctl;
|
||||||
try {
|
try {
|
||||||
ctl = controlFactory.controlFor(
|
ctl = controlFactory.controlFor(
|
||||||
new Project.NameKey(id.get()),
|
new Project.NameKey(id),
|
||||||
user.get());
|
user.get());
|
||||||
} catch (NoSuchProjectException e) {
|
} catch (NoSuchProjectException e) {
|
||||||
throw new ResourceNotFoundException(id);
|
throw new ResourceNotFoundException(id);
|
||||||
@ -70,4 +79,10 @@ public class ProjectsCollection implements
|
|||||||
public DynamicMap<RestView<ProjectResource>> views() {
|
public DynamicMap<RestView<ProjectResource>> views() {
|
||||||
return views;
|
return views;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public CreateProject create(TopLevelResource parent, IdString name) {
|
||||||
|
return createProjectFactory.create(name.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (C) 2013 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.ResourceConflictException;
|
||||||
|
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||||
|
import com.google.gerrit.server.project.CreateProject.Input;
|
||||||
|
|
||||||
|
public class PutProject implements RestModifyView<ProjectResource, Input> {
|
||||||
|
@Override
|
||||||
|
public Object apply(ProjectResource resource, Input input)
|
||||||
|
throws ResourceConflictException {
|
||||||
|
throw new ResourceConflictException("Project \"" + resource.getName()
|
||||||
|
+ "\" already exists");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user