Merge branch stable-2.10

* stable-2.10:
  Add full names for options on list groups REST API
  Add full names for options on list projects REST API
  Make `-S` an alias of `--start` in changes query REST API
  Mention deprecation of sortkey parameters in 2.9 release notes
  Set the version to 2.10-SNAPSHOT
  Run change hooks and ref-updated events after indexing is done.
  Fix Guice module auto-discover for plugin providers
  Fix broken formatting in changes REST documentation
  Restrict the input of plugin_archetype_deploy.sh
  Gracefully handle `buck audit` failure
  Revert "Make VisibleRefFilter.Filter reuse the refs passed from JGit."

Conflicts:
	VERSION
	gerrit-extension-api/pom.xml
	gerrit-plugin-api/pom.xml
	gerrit-plugin-archetype/pom.xml
	gerrit-plugin-gwt-archetype/pom.xml
	gerrit-plugin-gwtui/pom.xml
	gerrit-plugin-js-archetype/pom.xml
	gerrit-war/pom.xml

Change-Id: I01f5e9ffa67058d914485c53c8c7b64643da4c84
This commit is contained in:
Hugo Arès 2014-09-05 08:58:50 -04:00
commit e05b9b2858
19 changed files with 134 additions and 88 deletions

View File

@ -135,11 +135,10 @@ Query for open changes of watched projects:
If the `n` query parameter is supplied and additional changes exist If the `n` query parameter is supplied and additional changes exist
that match the query beyond the end, the last change object has a that match the query beyond the end, the last change object has a
`_more_changes: true` JSON field set. Callers can resume a query with `_more_changes: true` JSON field set.
the `N` query parameter, supplying the last change's `_sortkey` field
as the value. When going in the reverse direction with the `P` query The `S` or `start` query parameter can be supplied to skip a number
parameter a `_more_changes: true` is put in the first change object if of changes from the list.
there are results *before* the first change returned.
Clients are allowed to specify more than one query by setting the `q` Clients are allowed to specify more than one query by setting the `q`
parameter multiple times. In this case the result is an array of parameter multiple times. In this case the result is an array of
@ -3627,7 +3626,7 @@ In addition `ReviewerInfo` has the following fields:
|Field Name |Description |Field Name |Description
|`approvals` | |`approvals` |
The approvals of the reviewer as a map that maps the label names to the The approvals of the reviewer as a map that maps the label names to the
approval values ("`-2`", "`-1`", " `0`", "`+1`", "`+2`"). approval values ("`-2`", "`-1`", "`0`", "`+1`", "`+2`").
|========================== |==========================
[[reviewer-input]] [[reviewer-input]]

View File

@ -33,6 +33,9 @@ Important Notes
*WARNING:* Support for query via the SQL index is removed. The usage of *WARNING:* Support for query via the SQL index is removed. The usage of
a secondary index is now mandatory. a secondary index is now mandatory.
*WARNING:* The `sortkey` and `sortkey_prev` options on the query changes
REST endpoint are link:#sortkey-deprecation[deprecated].
*WARNING:* The new change screen only displays download commands if the *WARNING:* The new change screen only displays download commands if the
`download-commands` core plugin or any other plugin providing download `download-commands` core plugin or any other plugin providing download
commands is installed. The `download-commands` plugin provides the commands is installed. The `download-commands` plugin provides the
@ -299,6 +302,22 @@ REST API
~~~~~~~~ ~~~~~~~~
Changes
^^^^^^^
[[sortkey-deprecation]]
* Results returned by the
link:https://gerrit-documentation.storage.googleapis.com/Documentation/2.9/rest-api-changes.html#list-changes[
query changes] endpoint are now paginated using offsets instead of sortkeys.
+
The `sortkey` and `sortkey_prev` parameters on the endpoint are deprecated. The
results are now paginated using the `--limit` (`-n`) option to limit the number
of results, and the `-S` option to set the start point.
+
Queries with sortkeys are still supported against old index versions, to enable
online reindexing while clients have an older JS version.
Projects Projects
^^^^^^^^ ^^^^^^^^

View File

@ -133,13 +133,13 @@ public class Abandon implements RestModifyView<ChangeResource, AbandonInput>,
} catch (Exception e) { } catch (Exception e) {
log.error("Cannot email update for change " + change.getChangeId(), e); log.error("Cannot email update for change " + change.getChangeId(), e);
} }
indexFuture.checkedGet();
hooks.doChangeAbandonedHook(change, hooks.doChangeAbandonedHook(change,
caller.getAccount(), caller.getAccount(),
db.patchSets().get(change.currentPatchSetId()), db.patchSets().get(change.currentPatchSetId()),
Strings.emptyToNull(input.message), Strings.emptyToNull(input.message),
db); db);
ChangeInfo result = json.format(change); ChangeInfo result = json.format(change);
indexFuture.checkedGet();
return result; return result;
} }

View File

@ -200,12 +200,6 @@ public class ChangeInserter {
if(!messageIsForChange()) { if(!messageIsForChange()) {
commitMessageNotForChange(); commitMessageNotForChange();
} }
gitRefUpdated.fire(change.getProject(), patchSet.getRefName(),
ObjectId.zeroId(), commit);
if (runHooks) {
hooks.doPatchsetCreatedHook(change, patchSet, db);
}
if (sendMail) { if (sendMail) {
try { try {
@ -221,6 +215,14 @@ public class ChangeInserter {
} }
} }
f.checkedGet(); f.checkedGet();
gitRefUpdated.fire(change.getProject(), patchSet.getRefName(),
ObjectId.zeroId(), commit);
if (runHooks) {
hooks.doPatchsetCreatedHook(change, patchSet, db);
}
return change; return change;
} }

View File

@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.SetMultimap; import com.google.common.collect.SetMultimap;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.gerrit.common.ChangeHooks; import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
@ -318,14 +317,13 @@ public class PatchSetInserter {
} finally { } finally {
db.rollback(); db.rollback();
} }
CheckedFuture<?, IOException> f = mergeabilityChecker.newCheck() mergeabilityChecker.newCheck()
.addChange(updatedChange) .addChange(updatedChange)
.reindex() .reindex()
.runAsync(); .run();
if (runHooks) { if (runHooks) {
hooks.doPatchsetCreatedHook(updatedChange, patchSet, db); hooks.doPatchsetCreatedHook(updatedChange, patchSet, db);
} }
f.checkedGet();
return updatedChange; return updatedChange;
} }

View File

@ -173,22 +173,22 @@ public class PostReview implements RestModifyView<RevisionResource, ReviewInput>
} else { } else {
indexWrite = Futures.<Void, IOException> immediateCheckedFuture(null); indexWrite = Futures.<Void, IOException> immediateCheckedFuture(null);
} }
if (message != null) { if (message != null && input.notify.compareTo(NotifyHandling.NONE) > 0) {
if (input.notify.compareTo(NotifyHandling.NONE) > 0) { email.create(
email.create( input.notify,
input.notify, change,
change, revision.getPatchSet(),
revision.getPatchSet(), revision.getAccountId(),
revision.getAccountId(), message,
message, comments).sendAsync();
comments).sendAsync();
}
fireCommentAddedHook(revision);
} }
Output output = new Output(); Output output = new Output();
output.labels = input.labels; output.labels = input.labels;
indexWrite.checkedGet(); indexWrite.checkedGet();
if (message != null) {
fireCommentAddedHook(revision);
}
return output; return output;
} }

View File

@ -249,24 +249,23 @@ public class PostReviewers implements RestModifyView<ChangeResource, AddReviewer
ImmutableList.of(psa))); ImmutableList.of(psa)));
} }
accountLoaderFactory.create(true).fill(result.reviewers); accountLoaderFactory.create(true).fill(result.reviewers);
postAdd(rsrc.getChange(), added); emailReviewers(rsrc.getChange(), added);
indexFuture.checkedGet(); indexFuture.checkedGet();
if (!added.isEmpty()) {
PatchSet patchSet = dbProvider.get().patchSets().get(rsrc.getChange().currentPatchSetId());
for (PatchSetApproval psa : added) {
Account account = accountCache.get(psa.getAccountId()).getAccount();
hooks.doReviewerAddedHook(rsrc.getChange(), account, patchSet, dbProvider.get());
}
}
} }
private void postAdd(Change change, List<PatchSetApproval> added) private void emailReviewers(Change change, List<PatchSetApproval> added)
throws OrmException, EmailException { throws OrmException, EmailException {
if (added.isEmpty()) { if (added.isEmpty()) {
return; return;
} }
// Execute hook for added reviewers
//
PatchSet patchSet = dbProvider.get().patchSets().get(change.currentPatchSetId());
for (PatchSetApproval psa : added) {
Account account = accountCache.get(psa.getAccountId()).getAccount();
hooks.doReviewerAddedHook(change, account, patchSet, dbProvider.get());
}
// Email the reviewers // Email the reviewers
// //
// The user knows they added themselves, don't bother emailing them. // The user knows they added themselves, don't bother emailing them.

View File

@ -96,12 +96,13 @@ public class Publish implements RestModifyView<RevisionResource, Input>,
|| updatedChange.getStatus() == Change.Status.NEW) { || updatedChange.getStatus() == Change.Status.NEW) {
CheckedFuture<?, IOException> indexFuture = CheckedFuture<?, IOException> indexFuture =
indexer.indexAsync(updatedChange.getId()); indexer.indexAsync(updatedChange.getId());
hooks.doDraftPublishedHook(updatedChange, updatedPatchSet, dbProvider.get());
sender.send(rsrc.getNotes(), update, sender.send(rsrc.getNotes(), update,
rsrc.getChange().getStatus() == Change.Status.DRAFT, rsrc.getChange().getStatus() == Change.Status.DRAFT,
rsrc.getUser(), updatedChange, updatedPatchSet, rsrc.getUser(), updatedChange, updatedPatchSet,
rsrc.getControl().getLabelTypes()); rsrc.getControl().getLabelTypes());
indexFuture.checkedGet(); indexFuture.checkedGet();
hooks.doDraftPublishedHook(updatedChange, updatedPatchSet,
dbProvider.get());
} }
} catch (PatchSetInfoNotAvailableException e) { } catch (PatchSetInfoNotAvailableException e) {
throw new ResourceNotFoundException(e.getMessage()); throw new ResourceNotFoundException(e.getMessage());

View File

@ -15,7 +15,6 @@
package com.google.gerrit.server.change; package com.google.gerrit.server.change;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.gerrit.common.ChangeHooks; import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.DefaultInput; import com.google.gerrit.extensions.restapi.DefaultInput;
@ -123,11 +122,9 @@ public class PutTopic implements RestModifyView<ChangeResource, Input>,
db.rollback(); db.rollback();
} }
update.commit(); update.commit();
CheckedFuture<?, IOException> indexFuture = indexer.index(db, change);
indexer.indexAsync(change.getId());
hooks.doTopicChangedHook(change, currentUser.getAccount(), hooks.doTopicChangedHook(change, currentUser.getAccount(),
oldTopicName, db); oldTopicName, db);
indexFuture.checkedGet();
} }
return Strings.isNullOrEmpty(newTopicName) return Strings.isNullOrEmpty(newTopicName)
? Response.<String>none() ? Response.<String>none()

View File

@ -134,13 +134,13 @@ public class Restore implements RestModifyView<ChangeResource, RestoreInput>,
} catch (Exception e) { } catch (Exception e) {
log.error("Cannot email update for change " + change.getChangeId(), e); log.error("Cannot email update for change " + change.getChangeId(), e);
} }
f.checkedGet();
hooks.doChangeRestoredHook(change, hooks.doChangeRestoredHook(change,
caller.getAccount(), caller.getAccount(),
db.patchSets().get(change.currentPatchSetId()), db.patchSets().get(change.currentPatchSetId()),
Strings.emptyToNull(input.message), Strings.emptyToNull(input.message),
dbProvider.get()); dbProvider.get());
ChangeInfo result = json.format(change); ChangeInfo result = json.format(change);
f.checkedGet();
return result; return result;
} }

View File

@ -859,6 +859,7 @@ public class MergeOp {
db.commit(); db.commit();
sendMergedEmail(c, submitter); sendMergedEmail(c, submitter);
indexer.index(db, c);
if (submitter != null) { if (submitter != null) {
try { try {
hooks.doChangeMergedHook(c, hooks.doChangeMergedHook(c,
@ -1085,6 +1086,14 @@ public class MergeOp {
} }
})); }));
if (indexFuture != null) {
try {
indexFuture.checkedGet();
} catch (IOException e) {
log.error("Failed to index new change message", e);
}
}
if (submitter != null) { if (submitter != null) {
try { try {
hooks.doMergeFailedHook(c, hooks.doMergeFailedHook(c,
@ -1094,13 +1103,6 @@ public class MergeOp {
log.error("Cannot run hook for merge failed " + c.getId(), ex); log.error("Cannot run hook for merge failed " + c.getId(), ex);
} }
} }
if (indexFuture != null) {
try {
indexFuture.checkedGet();
} catch (IOException e) {
log.error("Failed to index new change message", e);
}
}
} }
private void abandonAllOpenChanges() throws NoSuchChangeException { private void abandonAllOpenChanges() throws NoSuchChangeException {

View File

@ -2100,13 +2100,6 @@ public class ReceiveCommits {
.addChange(change) .addChange(change)
.reindex() .reindex()
.runAsync(); .runAsync();
gitRefUpdated.fire(project.getNameKey(), newPatchSet.getRefName(),
ObjectId.zeroId(), newCommit);
hooks.doPatchsetCreatedHook(change, newPatchSet, db);
if (mergedIntoRef != null) {
hooks.doChangeMergedHook(
change, currentUser.getAccount(), newPatchSet, db);
}
workQueue.getDefaultQueue() workQueue.getDefaultQueue()
.submit(requestScopePropagator.wrap(new Runnable() { .submit(requestScopePropagator.wrap(new Runnable() {
@Override @Override
@ -2135,6 +2128,14 @@ public class ReceiveCommits {
})); }));
f.checkedGet(); f.checkedGet();
gitRefUpdated.fire(project.getNameKey(), newPatchSet.getRefName(),
ObjectId.zeroId(), newCommit);
hooks.doPatchsetCreatedHook(change, newPatchSet, db);
if (mergedIntoRef != null) {
hooks.doChangeMergedHook(
change, currentUser.getAccount(), newPatchSet, db);
}
if (magicBranch != null && magicBranch.isSubmit()) { if (magicBranch != null && magicBranch.isSubmit()) {
submit(changeCtl, newPatchSet); submit(changeCtl, newPatchSet);
} }

View File

@ -114,7 +114,7 @@ public class VisibleRefFilter extends AbstractAdvertiseRefsHook {
TagMatcher tags = tagCache.get(projectName).matcher( TagMatcher tags = tagCache.get(projectName).matcher(
tagCache, tagCache,
db, db,
filterTagsSeperately ? filter(refs).values() : result.values()); filterTagsSeperately ? filter(db.getAllRefs()).values() : result.values());
for (Ref tag : deferredTags) { for (Ref tag : deferredTags) {
if (tags.isReachable(tag)) { if (tags.isReachable(tag)) {
result.put(tag.getName(), tag); result.put(tag.getName(), tag);

View File

@ -90,10 +90,10 @@ public class ListGroups implements RestReadView<TopLevelResource> {
@Option(name = "--limit", aliases = {"-n"}, metaVar = "CNT", usage = "maximum number of groups to list") @Option(name = "--limit", aliases = {"-n"}, metaVar = "CNT", usage = "maximum number of groups to list")
private int limit; private int limit;
@Option(name = "-S", metaVar = "CNT", usage = "number of groups to skip") @Option(name = "--start", aliases = {"-S"}, metaVar = "CNT", usage = "number of groups to skip")
private int start; private int start;
@Option(name = "-m", metaVar = "MATCH", usage = "match group substring") @Option(name = "--match", aliases = {"-m"}, metaVar = "MATCH", usage = "match group substring")
private String matchSubstring; private String matchSubstring;
@Option(name = "-o", usage = "Output options per group") @Option(name = "-o", usage = "Output options per group")

View File

@ -70,9 +70,9 @@ public abstract class AbstractPreloadedPluginScanner implements
+ "Implementation-Version: " + pluginVersion + "\n" + "Implementation-Version: " + pluginVersion + "\n"
+ "Gerrit-ReloadMode: restart\n" + "Gerrit-ReloadMode: restart\n"
+ "Gerrit-ApiType: " + apiType + "\n"); + "Gerrit-ApiType: " + apiType + "\n");
appendIfNotNull(manifestString, "Gerrit-Module: ", sshModuleClass); appendIfNotNull(manifestString, "Gerrit-SshModule: ", sshModuleClass);
appendIfNotNull(manifestString, "Gerrit-HttpModule: ", httpModuleClass); appendIfNotNull(manifestString, "Gerrit-HttpModule: ", httpModuleClass);
appendIfNotNull(manifestString, "Gerrit-SshModule: ", sysModuleClass); appendIfNotNull(manifestString, "Gerrit-Module: ", sysModuleClass);
return new Manifest(new ByteArrayInputStream(manifestString.toString() return new Manifest(new ByteArrayInputStream(manifestString.toString()
.getBytes())); .getBytes()));
} }
@ -115,8 +115,14 @@ public abstract class AbstractPreloadedPluginScanner implements
Class.forName("com.google.inject.servlet.ServletModule"); Class.forName("com.google.inject.servlet.ServletModule");
Class<?> sshModuleBaseClass = Class<?> sshModuleBaseClass =
Class.forName("com.google.gerrit.sshd.CommandModule"); Class.forName("com.google.gerrit.sshd.CommandModule");
sshModuleClass = null;
httpModuleClass = null;
sysModuleClass = null;
for (Class<?> clazz : classes) { for (Class<?> clazz : classes) {
if (clazz.isLocalClass()) {
continue;
}
if (sshModuleBaseClass.isAssignableFrom(clazz)) { if (sshModuleBaseClass.isAssignableFrom(clazz)) {
sshModuleClass = sshModuleClass =

View File

@ -151,17 +151,17 @@ public class ListProjects implements RestReadView<TopLevelResource> {
this.limit = limit; this.limit = limit;
} }
@Option(name = "-S", metaVar = "CNT", usage = "number of projects to skip") @Option(name = "--start", aliases = {"-S"}, metaVar = "CNT", usage = "number of projects to skip")
public void setStart(int start) { public void setStart(int start) {
this.start = start; this.start = start;
} }
@Option(name = "-p", metaVar = "PREFIX", usage = "match project prefix") @Option(name = "--prefix", aliases = {"-p"}, metaVar = "PREFIX", usage = "match project prefix")
public void setMatchPrefix(String matchPrefix) { public void setMatchPrefix(String matchPrefix) {
this.matchPrefix = matchPrefix; this.matchPrefix = matchPrefix;
} }
@Option(name = "-m", metaVar = "MATCH", usage = "match project substring") @Option(name = "--match", aliases = {"-m"}, metaVar = "MATCH", usage = "match project substring")
public void setMatchSubstring(String matchSubstring) { public void setMatchSubstring(String matchSubstring) {
this.matchSubstring = matchSubstring; this.matchSubstring = matchSubstring;
} }

View File

@ -80,7 +80,7 @@ public class QueryChanges implements RestReadView<TopLevelResource> {
imp.setSortkeyBefore(key); imp.setSortkeyBefore(key);
} }
@Option(name = "-S", metaVar = "CNT", usage = "Number of changes to skip") @Option(name = "--start", aliases = {"-S"}, metaVar = "CNT", usage = "Number of changes to skip")
public void setStart(int start) { public void setStart(int start) {
imp.setStart(start); imp.setStart(start);
} }

View File

@ -35,7 +35,11 @@ def link_jars(libs, directory):
makedirs(directory) makedirs(directory)
while not path.isfile('.buckconfig'): while not path.isfile('.buckconfig'):
chdir('..') chdir('..')
cp = check_output(['buck', 'audit', 'classpath'] + libs) try:
cp = check_output(['buck', 'audit', 'classpath'] + libs)
except Exception as e:
print('call to buck audit failed: %s' % e, file=sys.stderr)
exit(1)
for j in cp.strip().splitlines(): for j in cp.strip().splitlines():
if j not in jars: if j not in jars:
jars.add(j) jars.add(j)

View File

@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
help() function help
{ {
cat <<'eof' cat <<'eof'
Usage: plugin_archetype_deploy [option] Usage: plugin_archetype_deploy [option]
@ -21,8 +21,9 @@ Usage: plugin_archetype_deploy [option]
Deploys Gerrit plugin Maven archetypes to Maven Central Deploys Gerrit plugin Maven archetypes to Maven Central
Valid options: Valid options:
--help show this message --help show this message.
--dry-run don't execute commands, just print them --dry-run don't execute commands, just print them.
eof eof
exit exit
} }
@ -62,22 +63,39 @@ function build_and_deploy
-Dfile=target/$module-$ver.jar -Dfile=target/$module-$ver.jar
} }
while [ $# -gt 0 ]; do function confirm
test "$1" == --dry-run && dryRun=true {
test "$1" == --help && help read -n1 -p "Are you sure you want to deploy? [N/y]: " ready
shift if [[ ! $ready == [Yy] ]]; then
done if [[ $ready == [Nn] || -z $ready ]]; then
echo; exit
else
echo; confirm
fi
fi
}
root=$(instroot) function run
cd "$root" {
ver=$(getver GERRIT_VERSION) test ${dryRun:-'false'} == 'false' && confirm
[[ $ver == *-SNAPSHOT ]] \ root=$(instroot)
&& url="https://oss.sonatype.org/content/repositories/snapshots" \ cd "$root"
|| url="https://oss.sonatype.org/service/local/staging/deploy/maven2" ver=$(getver GERRIT_VERSION)
[[ $ver == *-SNAPSHOT ]] \
&& url="https://oss.sonatype.org/content/repositories/snapshots" \
|| url="https://oss.sonatype.org/service/local/staging/deploy/maven2"
for d in gerrit-plugin-archetype \ for d in gerrit-plugin-archetype \
gerrit-plugin-js-archetype \ gerrit-plugin-js-archetype \
gerrit-plugin-gwt-archetype ; do gerrit-plugin-gwt-archetype ; do
(cd "$d"; build_and_deploy) (cd "$d"; build_and_deploy)
done done
}
if [ "$1" == "--dry-run" ]; then
dryRun=true && run
elif [ -z "$1" ]; then
run
else
help
fi