Merge branch 'stable-2.12'

* stable-2.12:
  config-gerrit: Add missing database types
  config-gerrit: List database types in alphabetical order
  Submit: Eliminate confusing error message
  Fix submittabilty of merge commits that resolve conflicts
  Fix display of "Related changes" after change is rebased in web UI
  MergeValidators: Don't assume submitter record exists
  Add migration command for PostgreSQL in 2.12.1 release notes
  doc: fix link to cmd-index-activate.html page
  Update 2.12.1 release notes with more fixes
  Update 2.12.1 release notes
  Fix keyboard shortcuts for non-US keyboards
  SetParent: Explicitly set to All-Projects when not specified
  CreateProject: Explicitly set parent to All-Projects when not specified
  Organize imports
  Release notes for Gerrit 2.12.1
  Show submodule difference properly in side by side view
  Update JGit to 4.1.2.201602141800-r

The change done in I30f2f8a8e ("Fix submittabilty of merge commits that
resolve conflicts") is not compatible with the master branch due to the
database being migrated to notedb, and is reverted by this merge.

This reverts commit 126af24dd5.

Change-Id: I72fb5db6e9edbf2c97c9a3e33b8133887f71beed
This commit is contained in:
David Pursehouse
2016-02-29 18:10:51 +09:00
17 changed files with 271 additions and 63 deletions

View File

@@ -120,7 +120,7 @@ link:cmd-gc.html[gerrit gc]::
link:cmd-gsql.html[gerrit gsql]:: link:cmd-gsql.html[gerrit gsql]::
Administrative interface to active database. Administrative interface to active database.
link:cmd-index-index.html[gerrit index activate]:: link:cmd-index-activate.html[gerrit index activate]::
Activate the latest index version available. Activate the latest index version available.
link:cmd-index-start.html[gerrit index start]:: link:cmd-index-start.html[gerrit index start]::

View File

@@ -1394,21 +1394,37 @@ Type of database server to connect to. If set this value will be
used to automatically create correct database.driver and database.url used to automatically create correct database.driver and database.url
values to open the connection. values to open the connection.
+ +
* `POSTGRESQL` * `DB2`
+ +
Connect to a PostgreSQL database server. Connect to a DB2 database server.
+
* `DERBY`
+
Connect to an Apache Derby database server.
+ +
* `H2` * `H2`
+ +
Connect to a local embedded H2 database. Connect to a local embedded H2 database.
+ +
* `JDBC`
+
Connect using a JDBC driver class name and URL.
+
* `MAXDB`
+
Connect to an SAP MaxDb database server.
+
* `MYSQL` * `MYSQL`
+ +
Connect to a MySQL database server. Connect to a MySQL database server.
+ +
* `JDBC` * `ORACLE`
+ +
Connect using a JDBC driver class name and URL. Connect to an Oracle database server.
+
* `POSTGRESQL`
+
Connect to a PostgreSQL database server.
+ +
If not specified, database.driver and database.url are used as-is, If not specified, database.driver and database.url are used as-is,

View File

@@ -0,0 +1,189 @@
Release notes for Gerrit 2.12.1
===============================
Gerrit 2.12.1 is now available:
link:https://gerrit-releases.storage.googleapis.com/gerrit-2.12.1.war[
https://gerrit-releases.storage.googleapis.com/gerrit-2.12.1.war]
Gerrit 2.12.1 includes the bug fixes done with
link:ReleaseNotes-2.11.6.html[Gerrit 2.11.6] and
link:ReleaseNotes-2.11.7.html[Gerrit 2.11.7]. These bug fixes are *not*
listed in these release notes.
*WARNING:* This version includes a manual schema upgrade when upgrading
from 2.12.
+
If you have already upgraded to 2.12, you need to issue this SQL statement
manually (e.g. using the `gerrit gsql` SSH command or the `gqsl` site
program):
+
alter table patch_sets modify push_certficate clob;
+
Or with this command if the site is configured to use PostgreSQL:
+
alter table patch_sets alter column push_certficate type text;
+
Note that the misspelled `push_certficate` is the actual name of the
column.
+
If you are upgrading from a version earlier than 2.12, this manual step is
not necessary and should be omitted.
Bug Fixes
---------
General
^^^^^^^
* Fix column type for signed push certificates.
+
The column type `VARCHAR(255)` was too small, preventing some PGP push
certificates from being stored.
* Add the `DRAFT_COMMENTS` option to the list changes REST API endpoint
and mark it as deprecated.
+
It was removed in version 2.12 because it's not needed any more by the UI,
but this caused failures for clients that still use it.
+
Now it is added back, although it does not do anything and is marked as
deprecated.
* link:https://code.google.com/p/gerrit/issues/detail?id=3669[Issue 3669]:
Fix schema migration when migrating to 2.12.x directly from a version
earlier than 2.11.
* link:https://code.google.com/p/gerrit/issues/detail?id=3733[Issue 3733]:
Correctly detect symlinked log directory on startup.
+
If `$site_path/logs` was a symlink, the server would not start.
* link:https://code.google.com/p/gerrit/issues/detail?id=3871[Issue 3871]:
Throw an explicit exception when failing to load a change from the database.
+
If a change could not be loaded from the database, for example if it was
manually removed from the changes table but references to it were remaining
in other tables, a null change was returned which would then lead to an
'Internal Server Error' that was difficult to track down. Now an error is
raised earlier which will help administrators to find the root cause.
* https://code.google.com/p/gerrit/issues/detail?id=3743[Issue 3743]:
Use submitter identity as committer when using 'Rebase if Necessary' merge
strategy.
+
When submitting a change that required rebase, the committer was being
set to 'Gerrit Code Review' instead of the name of the submitter.
* link:https://code.google.com/p/gerrit/issues/detail?id=3758[Issue 3758]:
Fix serving of static resources when deployed in application container.
+
When deployed in a container, for example Tomcat, it was not possible to
load the UI because static content could not be loaded from the WAR file.
* link:https://code.google.com/p/gerrit/issues/detail?id=3790[Issue 3790]:
When deployed in a container, for example Tomcat, the 'Documentation' menu
was missing.
* link:https://code.google.com/p/gerrit/issues/detail?id=3786[Issue 3786]:
Fix SQL statement syntax in schema migration.
+
An extra semicolon was preventing migration from 2.11.x to 2.12 when using
an Oracle database.
* Send email using email queue instead of the default queue.
+
Some emails sent asynchronously were already being sent using that queue
but some were not. This was confusing for a gerrit administrator because
if there is a build up of `send-email` tasks in the queue, he would
think that increasing `sendemail.threadPoolSize` would help but it did not
because some of the email were sent using the default queue which is
configurable using `execution.defaultThreadPoolSize`.
* Fix XSRF token cookie to honor `auth.cookieSecure` setting.
* link:https://code.google.com/p/gerrit/issues/detail?id=3767[Issue 3767]:
Fix replication of first patch set for new changes.
+
When new changes were pushed from the command line, the first patch
set did not get replicated to destinations.
* link:https://code.google.com/p/gerrit/issues/detail?id=3771[Issue 3771]:
Remove `index.defaultMaxClauseCount` configuration option.
+
When `index.maxTerms` was either not set (thus no limit) or set to a value
higher than `index.defaultMaxClauseCount` it was possible that viewing the
related changes tab could cause a 'Too many clauses' error for changes that
have a lot of related changes.
+
The `index.defaultMaxClauseCount` configuration option is removed, and the
existing `index.maxTerms` is reused. The default value of `index.maxTerms`
is reduced from 'no limit' to 1024.
* link:https://code.google.com/p/gerrit/issues/detail?id=3919[Issue 3919]:
Explicitly set parent project to 'All-Projects' when a project is created
without giving the parent.
UI
^^
* link:https://code.google.com/p/gerrit/issues/detail?id=3071[Issue 3071]:
Fix display of submodule differences in side-by-side view.
* link:https://code.google.com/p/gerrit/issues/detail?id=3718[Issue 3718]:
Hide avatar images when no avatars are available.
+
The UI was showing a transparent empty image with a border.
* link:https://code.google.com/p/gerrit/issues/detail?id=3731[Issue 3731]:
Fix syntax higlighting of tcl files.
* link:https://code.google.com/p/gerrit/issues/detail?id=3863[Issue 3863]:
Fix display of active row marker in tag list.
+
Clicking on one of the rows would cause the tag name to disappear.
* link:https://code.google.com/p/gerrit/issues/detail?id=1207[Issue 1207]:
Fix keyboard shortcuts for non-US keyboards on side-by-side diff screen.
+
The forward/backward navigation keys `[` and `]` only worked on keyboards where
these characters could be typed without using any modifier key (like CTRL, ALT,
etc..).
+
Note that the problem still exists on the unified diff screen.
Plugins
^^^^^^^
* Allow plugins to get the caller in merge validation requests.
+
Plugins that implement the `MergeValidationListener` interface now get the
caller (the user who initiated the merge) in the `onPreMerge` method.
+
Existing plugins that implement this interface must be adapted to the new
method signature.
* link:https://code.google.com/p/gerrit/issues/detail?id=3741[Issue 3741]:
Fix handling of merge validation exceptions emitted by plugins.
+
If a plugin raised an exception, it was reported to the user as 'Change is
new', rather than 'Missing dependency'.
* link:https://code.google.com/p/gerrit/issues/detail?id=3821[Issue 3821]:
Fix repeated reloading of plugins when running on OpenJDK 8.
+
OpenJDK 8 uses nanotime precision for file modification time on systems that
are POSIX 2008 compatible. This leads to precision incompatibility when
comparing the plugin's JAR file timestamp, resulting in the plugin being
reloaded every minute.
Documentation
^^^^^^^^^^^^^
* Update documentation of `commentlink` to reflect changed search URL.
Upgrades
--------
* Upgrade JGit to 4.1.2.201602141800-r.

View File

@@ -9,6 +9,7 @@ Version 2.13.x
[[2_12]] [[2_12]]
Version 2.12.x Version 2.12.x
-------------- --------------
* link:ReleaseNotes-2.12.1.html[2.12.1]
* link:ReleaseNotes-2.12.html[2.12] * link:ReleaseNotes-2.12.html[2.12]
[[2_11]] [[2_11]]

View File

@@ -43,6 +43,8 @@ import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate; import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.RemoteRefUpdate.Status; import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
import java.util.List;
public class PushOneCommit { public class PushOneCommit {
public static final String SUBJECT = "test commit"; public static final String SUBJECT = "test commit";
public static final String FILE_NAME = "a.txt"; public static final String FILE_NAME = "a.txt";
@@ -179,6 +181,13 @@ public class PushOneCommit {
.committer(new PersonIdent(i, testRepo.getDate())); .committer(new PersonIdent(i, testRepo.getDate()));
} }
public void setParents(List<RevCommit> parents) throws Exception {
commitBuilder.noParents();
for (RevCommit p : parents) {
commitBuilder.parent(p);
}
}
public Result to(String ref) throws Exception { public Result to(String ref) throws Exception {
commitBuilder.add(fileName, content); commitBuilder.add(fileName, content);
return execute(ref); return execute(ref);
@@ -189,7 +198,7 @@ public class PushOneCommit {
return execute(ref); return execute(ref);
} }
private Result execute(String ref) throws Exception { public Result execute(String ref) throws Exception {
RevCommit c = commitBuilder.create(); RevCommit c = commitBuilder.create();
if (changeId == null) { if (changeId == null) {
changeId = GitUtil.getChangeId(testRepo, c).get(); changeId = GitUtil.getChangeId(testRepo, c).get();

View File

@@ -103,7 +103,7 @@ public class ActionsIT extends AbstractDaemonTest {
assertThat(info.label).isEqualTo("Submit whole topic"); assertThat(info.label).isEqualTo("Submit whole topic");
assertThat(info.method).isEqualTo("POST"); assertThat(info.method).isEqualTo("POST");
assertThat(info.title).isEqualTo( assertThat(info.title).isEqualTo(
"Clicking the button would fail for other changes"); "See the \"Submitted Together\" tab for problems");
} else { } else {
noSubmitWholeTopicAssertions(actions, 1); noSubmitWholeTopicAssertions(actions, 1);
} }

View File

@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import com.google.gerrit.acceptance.AbstractDaemonTest; import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.RestResponse; import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.project.SetParent; import com.google.gerrit.server.project.SetParent;
import org.junit.Test; import org.junit.Test;
@@ -49,6 +50,19 @@ public class SetParentIT extends AbstractDaemonTest {
newGson().fromJson(r.getReader(), String.class); newGson().fromJson(r.getReader(), String.class);
assertThat(newParent).isEqualTo(parent); assertThat(newParent).isEqualTo(parent);
r.consume(); r.consume();
// When the parent name is not explicitly set, it should be
// set to "All-Projects".
r = adminSession.put("/projects/" + project.get() + "/parent",
newParentInput(null));
r.assertOK();
r.consume();
r = adminSession.get("/projects/" + project.get() + "/parent");
r.assertOK();
newParent = newGson().fromJson(r.getReader(), String.class);
assertThat(newParent).isEqualTo(AllProjectsNameProvider.DEFAULT);
r.consume();
} }
@Test @Test

View File

@@ -136,15 +136,6 @@ public class KeyCommandSet implements KeyPressHandler {
if (mask == 0) { if (mask == 0) {
mask = event.getNativeEvent().getKeyCode(); mask = event.getNativeEvent().getKeyCode();
} }
if (event.isAltKeyDown()) {
mask |= KeyCommand.M_ALT;
}
if (event.isControlKeyDown()) {
mask |= KeyCommand.M_CTRL;
}
if (event.isMetaKeyDown()) {
mask |= KeyCommand.M_META;
}
return mask; return mask;
} }
} }

View File

@@ -368,8 +368,8 @@ public class SideBySide extends Screen {
KeyMap keyMap = KeyMap.create() KeyMap keyMap = KeyMap.create()
.on("A", upToChange(true)) .on("A", upToChange(true))
.on("U", upToChange(false)) .on("U", upToChange(false))
.on("[", header.navigate(Direction.PREV)) .on("'['", header.navigate(Direction.PREV))
.on("]", header.navigate(Direction.NEXT)) .on("']'", header.navigate(Direction.NEXT))
.on("R", header.toggleReviewed()) .on("R", header.toggleReviewed())
.on("O", commentManager.toggleOpenBox(cm)) .on("O", commentManager.toggleOpenBox(cm))
.on("Enter", commentManager.toggleOpenBox(cm)) .on("Enter", commentManager.toggleOpenBox(cm))

View File

@@ -85,8 +85,8 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
"This change depends on other hidden changes which are not ready"; "This change depends on other hidden changes which are not ready";
private static final String CLICK_FAILURE_TOOLTIP = private static final String CLICK_FAILURE_TOOLTIP =
"Clicking the button would fail"; "Clicking the button would fail";
private static final String CLICK_FAILURE_OTHER_TOOLTIP = private static final String CHANGES_NOT_MERGEABLE =
"Clicking the button would fail for other changes"; "See the \"Submitted Together\" tab for problems";
public static class Output { public static class Output {
transient Change change; transient Change change;
@@ -258,7 +258,7 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
return CLICK_FAILURE_TOOLTIP; return CLICK_FAILURE_TOOLTIP;
} }
if (!mergeable) { if (!mergeable) {
return CLICK_FAILURE_OTHER_TOOLTIP; return CHANGES_NOT_MERGEABLE;
} }
MergeOp.checkSubmitRule(c); MergeOp.checkSubmitRule(c);
} }

View File

@@ -20,11 +20,8 @@ import com.google.gerrit.extensions.registration.DynamicMap.Entry;
import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Branch; import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.AllProjectsName; import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.PluginConfig; import com.google.gerrit.server.config.PluginConfig;
@@ -97,9 +94,7 @@ public class MergeValidators {
+ "The change must be submitted by a Gerrit administrator."; + "The change must be submitted by a Gerrit administrator.";
private final AllProjectsName allProjectsName; private final AllProjectsName allProjectsName;
private final ReviewDb db;
private final ProjectCache projectCache; private final ProjectCache projectCache;
private final ApprovalsUtil approvalsUtil;
private final DynamicMap<ProjectConfigEntry> pluginConfigEntries; private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
public interface Factory { public interface Factory {
@@ -108,13 +103,10 @@ public class MergeValidators {
@Inject @Inject
public ProjectConfigValidator(AllProjectsName allProjectsName, public ProjectConfigValidator(AllProjectsName allProjectsName,
ReviewDb db, ProjectCache projectCache, ProjectCache projectCache,
ApprovalsUtil approvalsUtil,
DynamicMap<ProjectConfigEntry> pluginConfigEntries) { DynamicMap<ProjectConfigEntry> pluginConfigEntries) {
this.allProjectsName = allProjectsName; this.allProjectsName = allProjectsName;
this.db = db;
this.projectCache = projectCache; this.projectCache = projectCache;
this.approvalsUtil = approvalsUtil;
this.pluginConfigEntries = pluginConfigEntries; this.pluginConfigEntries = pluginConfigEntries;
} }
@@ -142,11 +134,6 @@ public class MergeValidators {
} }
} else { } else {
if (!oldParent.equals(newParent)) { if (!oldParent.equals(newParent)) {
PatchSetApproval psa =
approvalsUtil.getSubmitter(db, commit.notes(), patchSetId);
if (psa == null) {
throw new MergeValidationException(SET_BY_ADMIN);
}
if (!caller.getCapabilities().canAdministrateServer()) { if (!caller.getCapabilities().canAdministrateServer()) {
throw new MergeValidationException(SET_BY_ADMIN); throw new MergeValidationException(SET_BY_ADMIN);
} }

View File

@@ -150,9 +150,13 @@ public class PatchFile {
if (tw == null) { if (tw == null) {
return Text.EMPTY; return Text.EMPTY;
} }
if (tw.getFileMode(0).getObjectType() != Constants.OBJ_BLOB) { if (tw.getFileMode(0).getObjectType() == Constants.OBJ_BLOB) {
return new Text(repo.open(tw.getObjectId(0), Constants.OBJ_BLOB));
} else if (tw.getFileMode(0).getObjectType() == Constants.OBJ_COMMIT) {
String str = "Subproject commit " + ObjectId.toString(tw.getObjectId(0));
return new Text(str.getBytes());
} else {
return Text.EMPTY; return Text.EMPTY;
} }
return new Text(repo.open(tw.getObjectId(0), Constants.OBJ_BLOB));
} }
} }

View File

@@ -32,7 +32,6 @@ import com.google.gerrit.reviewdb.client.PatchSet;
import org.eclipse.jgit.diff.Edit; import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.patch.CombinedFileHeader; import org.eclipse.jgit.patch.CombinedFileHeader;
import org.eclipse.jgit.patch.FileHeader; import org.eclipse.jgit.patch.FileHeader;
import org.eclipse.jgit.util.IntList; import org.eclipse.jgit.util.IntList;
@@ -97,10 +96,7 @@ public class PatchListEntry {
header = compact(hdr); header = compact(hdr);
if (hdr instanceof CombinedFileHeader if (hdr instanceof CombinedFileHeader || hdr.getHunks().isEmpty()) {
|| hdr.getHunks().isEmpty() //
|| hdr.getOldMode() == FileMode.GITLINK
|| hdr.getNewMode() == FileMode.GITLINK) {
edits = Collections.emptyList(); edits = Collections.emptyList();
} else { } else {
edits = Collections.unmodifiableList(editList); edits = Collections.unmodifiableList(editList);

View File

@@ -312,14 +312,6 @@ public class PatchListLoader implements Callable<PatchList> {
private PatchListEntry newEntry(RevTree aTree, FileHeader fileHeader, private PatchListEntry newEntry(RevTree aTree, FileHeader fileHeader,
long size, long sizeDelta) { long size, long sizeDelta) {
final FileMode oldMode = fileHeader.getOldMode();
final FileMode newMode = fileHeader.getNewMode();
if (oldMode == FileMode.GITLINK || newMode == FileMode.GITLINK) {
return new PatchListEntry(fileHeader, Collections.<Edit> emptyList(),
size, sizeDelta);
}
if (aTree == null // want combined diff if (aTree == null // want combined diff
|| fileHeader.getPatchType() != PatchType.UNIFIED || fileHeader.getPatchType() != PatchType.UNIFIED
|| fileHeader.getHunks().isEmpty()) { || fileHeader.getHunks().isEmpty()) {

View File

@@ -179,9 +179,7 @@ class PatchScriptBuilder {
} }
boolean hugeFile = false; boolean hugeFile = false;
if (a.mode == FileMode.GITLINK || b.mode == FileMode.GITLINK) { if (a.src == b.src && a.size() <= context
// Do nothing
} else if (a.src == b.src && a.size() <= context
&& content.getEdits().isEmpty()) { && content.getEdits().isEmpty()) {
// Odd special case; the files are identical (100% rename or copy) // Odd special case; the files are identical (100% rename or copy)
// and the user has asked for context that is larger than the file. // and the user has asked for context that is larger than the file.
@@ -471,6 +469,10 @@ class PatchScriptBuilder {
} else if (mode.getObjectType() == Constants.OBJ_BLOB) { } else if (mode.getObjectType() == Constants.OBJ_BLOB) {
srcContent = Text.asByteArray(db.open(id, Constants.OBJ_BLOB)); srcContent = Text.asByteArray(db.open(id, Constants.OBJ_BLOB));
} else if (mode.getObjectType() == Constants.OBJ_COMMIT) {
String strContent = "Subproject commit " + ObjectId.toString(id);
srcContent = strContent.getBytes();
} else { } else {
srcContent = Text.NO_BYTES; srcContent = Text.NO_BYTES;
} }

View File

@@ -44,6 +44,7 @@ import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent; import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.GroupBackend; import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.ProjectOwnerGroupsProvider; import com.google.gerrit.server.config.ProjectOwnerGroupsProvider;
import com.google.gerrit.server.config.RepositoryConfig; import com.google.gerrit.server.config.RepositoryConfig;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated; import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
@@ -102,6 +103,7 @@ public class CreateProject implements RestModifyView<TopLevelResource, ProjectIn
private final PersonIdent serverIdent; private final PersonIdent serverIdent;
private final Provider<CurrentUser> currentUser; private final Provider<CurrentUser> currentUser;
private final Provider<PutConfig> putConfig; private final Provider<PutConfig> putConfig;
private final AllProjectsName allProjects;
private final String name; private final String name;
@Inject @Inject
@@ -120,6 +122,7 @@ public class CreateProject implements RestModifyView<TopLevelResource, ProjectIn
@GerritPersonIdent PersonIdent serverIdent, @GerritPersonIdent PersonIdent serverIdent,
Provider<CurrentUser> currentUser, Provider<CurrentUser> currentUser,
Provider<PutConfig> putConfig, Provider<PutConfig> putConfig,
AllProjectsName allProjects,
@Assisted String name) { @Assisted String name) {
this.projectsCollection = projectsCollection; this.projectsCollection = projectsCollection;
this.groupsCollection = groupsCollection; this.groupsCollection = groupsCollection;
@@ -137,6 +140,7 @@ public class CreateProject implements RestModifyView<TopLevelResource, ProjectIn
this.serverIdent = serverIdent; this.serverIdent = serverIdent;
this.currentUser = currentUser; this.currentUser = currentUser;
this.putConfig = putConfig; this.putConfig = putConfig;
this.allProjects = allProjects;
this.name = name; this.name = name;
} }
@@ -155,9 +159,9 @@ public class CreateProject implements RestModifyView<TopLevelResource, ProjectIn
CreateProjectArgs args = new CreateProjectArgs(); CreateProjectArgs args = new CreateProjectArgs();
args.setProjectName(ProjectUtil.stripGitSuffix(name)); args.setProjectName(ProjectUtil.stripGitSuffix(name));
if (!Strings.isNullOrEmpty(input.parent)) { String parentName = MoreObjects.firstNonNull(
args.newParent = projectsCollection.get().parse(input.parent).getControl(); Strings.emptyToNull(input.parent), allProjects.get());
} args.newParent = projectsCollection.get().parse(parentName).getControl();
args.createEmptyCommit = input.createEmptyCommit; args.createEmptyCommit = input.createEmptyCommit;
args.permissionsOnly = input.permissionsOnly; args.permissionsOnly = input.permissionsOnly;
args.projectDescription = Strings.emptyToNull(input.description); args.projectDescription = Strings.emptyToNull(input.description);

View File

@@ -14,6 +14,8 @@
package com.google.gerrit.server.project; package com.google.gerrit.server.project;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Strings; import com.google.common.base.Strings;
@@ -70,18 +72,18 @@ public class SetParent implements RestModifyView<ProjectResource, Input> {
throws AuthException, ResourceConflictException, throws AuthException, ResourceConflictException,
ResourceNotFoundException, UnprocessableEntityException, IOException { ResourceNotFoundException, UnprocessableEntityException, IOException {
ProjectControl ctl = rsrc.getControl(); ProjectControl ctl = rsrc.getControl();
validateParentUpdate(ctl, input.parent, checkIfAdmin); String parentName = MoreObjects.firstNonNull(
Strings.emptyToNull(input.parent), allProjects.get());
validateParentUpdate(ctl, parentName, checkIfAdmin);
try (MetaDataUpdate md = updateFactory.create(rsrc.getNameKey())) { try (MetaDataUpdate md = updateFactory.create(rsrc.getNameKey())) {
ProjectConfig config = ProjectConfig.read(md); ProjectConfig config = ProjectConfig.read(md);
Project project = config.getProject(); Project project = config.getProject();
project.setParentName(Strings.emptyToNull(input.parent)); project.setParentName(parentName);
String msg = Strings.emptyToNull(input.commitMessage); String msg = Strings.emptyToNull(input.commitMessage);
if (msg == null) { if (msg == null) {
msg = String.format( msg = String.format(
"Changed parent to %s.\n", "Changed parent to %s.\n", parentName);
MoreObjects.firstNonNull(project.getParentName(),
allProjects.get()));
} else if (!msg.endsWith("\n")) { } else if (!msg.endsWith("\n")) {
msg += "\n"; msg += "\n";
} }
@@ -90,8 +92,9 @@ public class SetParent implements RestModifyView<ProjectResource, Input> {
config.commit(md); config.commit(md);
cache.evict(ctl.getProject()); cache.evict(ctl.getProject());
Project.NameKey parentName = project.getParent(allProjects); Project.NameKey parent = project.getParent(allProjects);
return parentName != null ? parentName.get() : ""; checkNotNull(parent);
return parent.get();
} catch (RepositoryNotFoundException notFound) { } catch (RepositoryNotFoundException notFound) {
throw new ResourceNotFoundException(rsrc.getName()); throw new ResourceNotFoundException(rsrc.getName());
} catch (ConfigInvalidException e) { } catch (ConfigInvalidException e) {