Merge branch 'stable-2.15'

* stable-2.15:
  ChangeIT: Temporarily disable tests related to group matching
  Align SSH create-project with REST API
  SubmoduleOp: Fix formatting of submodule update commit message
  Fix Postgresql JDBC driver leaking memory
  Document that the build works with Python 2 or 3
  merge_jars.py: Fix for python 3 compatibility
  project.py: decode byte output from check_result
  license and doc: Add support for python3
  Bazel: Make build tool chain python 3 compatible
  ExternalIds NoteDb migration: Avoid intermediate migration state
  Make PrivateStateChanged and WorkInProgressStateChanged singletons
  BatchProgramModule: Bind GitReferenceUpdated.DISABLED
  BatchProgramModule: Don't bind event classes to null
  Document that Python 2 is required by the build
  Make event firing classes singleton
  Fix ConcurrentModificationException when posting reviews
  Revert partially "Trim multi-line arguments for task name and ssh_log"
  BaseCommand: Fix formatting of task description with arguments
  Add analytics to the list of plugins
  config-plugins: Consistently use "/+doc/" for documentation links
  config-plugins: Fix link to ref-protection plugin documentation
  config-plugins: Add readonly plugin to plugin list
  Add documentation for SshCreateCommandInterceptor
  Allow plugins to intercept ssh command creation
  GWT/Poly: Default to "Create initial commit" during project creation
  Revert "Reduce chance of deadlock in account cache"
  commit-msg: Adapt to awk behavior change on Cygwin/MSYS
  Expand docs on how to include external dependencies in core plugins
  Document how to bundle custom plugins in release.war
  Group members can't be added as reviewers if a matched username exists
  Set version to 2.13.11
  StreamEventsApiListener: Prevent NPE when account is null
  Set version to 2.11.11
  Replace links to code.google.com/p/gerrit
  Update issue tracker URL in documentation
  Update issue tracker URL in POM files
  Bump jsch to 0.54
  Update jsch to 0.1.53
  Bump Jsch to 1.52

Change-Id: Icec3dcfe53146da7d66d4d690afdd9e77ee10380
This commit is contained in:
David Pursehouse
2018-03-12 08:52:08 +09:00
43 changed files with 378 additions and 34 deletions

View File

@@ -60,7 +60,14 @@ This command is intended to be used in scripts.
--owner::
-o::
Name of the group(s) which will initially own this repository.
Identifier of the group(s) which will initially own this repository.
This can be:
* the UUID of the group
* the legacy numeric ID of the group
* the name of the group if it is unique
The specified group(s) must already be defined within Gerrit.
Several groups can be specified on the command line.
+

View File

@@ -119,7 +119,7 @@ This plugin allows users to configure different review strategies.
link:https://gerrit-review.googlesource.com/#/admin/projects/plugins/review-strategy[
Project] |
link:https://gerrit.googlesource.com/plugins/review-strategy/+/master/src/main/resources/Documentation/about.md[
link:https://gerrit.googlesource.com/plugins/review-strategy/+doc/master/src/main/resources/Documentation/about.md[
Documentation]
[[singleusergroup]]
@@ -161,6 +161,18 @@ Project] |
link:https://gerrit.googlesource.com/plugins/admin-console/+doc/master/src/main/resources/Documentation/about.md[
Documentation]
[[analytics]]
=== analytics
Plugin to extract commit and review data from Gerrit projects and
expose aggregated metrics over REST and SSH API.
Metrics are extracted in JSON format with one record per line, ready to be
archived and processed with popular BigData transformation tools such
Apache Spark or published and visualized in dashboards.
link:https://gerrit-review.googlesource.com/#/admin/projects/plugins/analytics[Project] |
link:https://gerrit.googlesource.com/plugins/analytics/+doc/master/README.md[Documentation]
[[avatars-external]]
=== avatars-external
@@ -473,7 +485,7 @@ This plugin provides a Prolog predicate `add_owner_approval/3` that
appends `label('Owner-Approval', need(_))` to a provided list.
link:https://gerrit-review.googlesource.com/#/admin/projects/plugins/owners[Project] |
link:https://gerrit.googlesource.com/plugins/owners/+/refs/heads/master/README.md[Documentation]
link:https://gerrit.googlesource.com/plugins/owners/+doc/master/README.md[Documentation]
[[project-download-commands]]
=== project-download-commands
@@ -507,6 +519,19 @@ Documentation]
link:https://gerrit.googlesource.com/plugins/quota/+doc/master/src/main/resources/Documentation/config.md[
Configuration]
[[readonly]]
=== readonly
A plugin that makes the Gerrit server read-only by rejecting git pushes,
blocking HTTP PUT/POST/DELETE requests, and disabling SSH commands.
link:https://gerrit-review.googlesource.com/#/admin/projects/plugins/readonly[
Project] |
link:https://gerrit.googlesource.com/plugins/readonly/+doc/master/src/main/resources/Documentation/about.md[
Documentation] |
link:https://gerrit.googlesource.com/plugins/readonly/+doc/master/src/main/resources/Documentation/config.md[
Configuration]
[[ref-protection]]
=== ref-protection
@@ -517,7 +542,7 @@ Backups of deleted or non-fast-forward updated refs are created under the
link:https://gerrit-review.googlesource.com/#/admin/projects/plugins/ref-protection[
Project] |
link:https://gerrit.googlesource.com/plugins/ref-protection/+/refs/heads/stable-2.11/src/main/resources/Documentation/about.md[
link:https://gerrit.googlesource.com/plugins/ref-protection/+doc/master/src/main/resources/Documentation/about.md[
Documentation]
[[reparent]]

View File

@@ -7,6 +7,7 @@ To build Gerrit from source, you need:
* A Linux or macOS system (Windows is not supported at this time)
* A JDK for Java 8
* Python 2 or 3
* Node.js
* link:https://www.bazel.io/versions/master/docs/install.html[Bazel]

View File

@@ -2716,6 +2716,26 @@ public class MyPlugin implements MailFilter {
}
----
[[ssh-command-interception]]
== SSH Command Interception
Gerrit provides an extension point that allows a plugin to intercept
creation of SSH commands and override the functionality with its own
implementation.
[source, java]
----
import com.google.gerrit.sshd.SshCreateCommandInterceptor;
class MyCommandInterceptor implements SshCreateCommandInterceptor {
@Override
public String intercept(String in) {
return pluginName + " mycommand";
}
}
----
== SEE ALSO
* link:js-api.html[JavaScript API]

View File

@@ -229,12 +229,16 @@ opts.add_option('--no-searchbox', action="store_false", dest='searchbox',
options, _ = opts.parse_args()
try:
try:
out_file = open(options.out, 'w', errors='ignore')
src_file = open(options.src, 'r', errors='ignore')
except TypeError:
out_file = open(options.out, 'w')
src_file = open(options.src, 'r')
last_line = ''
ignore_next_line = False
last_title = ''
for line in src_file.xreadlines():
for line in src_file:
if PAT_GERRIT.match(last_line):
# Case of "GERRIT\n------" at the footer
out_file.write(GERRIT_UPLINK)

View File

@@ -130,6 +130,7 @@ public class CreateProjectScreen extends Screen {
addGrid(fp);
emptyCommit = new CheckBox(AdminConstants.I.checkBoxEmptyCommit());
emptyCommit.setValue(true);
permissionsOnly = new CheckBox(AdminConstants.I.checkBoxPermissionsOnly());
fp.add(emptyCommit);
fp.add(permissionsOnly);

View File

@@ -1161,6 +1161,14 @@ public abstract class AbstractDaemonTest {
return createGroup(name, "Administrators");
}
protected String createGroupWithRealName(String name) throws Exception {
GroupInput in = new GroupInput();
in.name = name;
in.ownerId = "Administrators";
gApi.groups().create(in);
return name;
}
protected String createGroup(String name, String owner) throws Exception {
name = name(name);
GroupInput in = new GroupInput();

View File

@@ -29,7 +29,6 @@ import com.google.gerrit.pgm.util.ThreadLimiter;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.index.DummyIndexModule;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
import com.google.gerrit.server.notedb.rebuild.NoteDbMigrator;
@@ -189,7 +188,6 @@ public class MigrateToNoteDb extends SiteProgram {
@Override
public void configure() {
install(dbInjector.getInstance(BatchProgramModule.class));
bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED);
install(new DummyIndexModule());
factory(ChangeResource.Factory.class);
}

View File

@@ -32,7 +32,6 @@ import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.pgm.util.ThreadLimiter;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.index.IndexModule;
import com.google.gerrit.server.index.IndexModule.IndexType;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
@@ -166,7 +165,6 @@ public class Reindex extends SiteProgram {
@Override
protected void configure() {
factory(ChangeResource.Factory.class);
bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED);
}
});

View File

@@ -51,6 +51,9 @@ import com.google.gerrit.server.config.DisableReverseDnsLookupProvider;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.GitReceivePackGroups;
import com.google.gerrit.server.config.GitUploadPackGroups;
import com.google.gerrit.server.extensions.events.EventUtil;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.extensions.events.RevisionCreated;
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.git.SearchingChangeCacheImpl;
import com.google.gerrit.server.git.TagCache;
@@ -169,6 +172,9 @@ public class BatchProgramModule extends FactoryModule {
factory(SubmitRuleEvaluator.Factory.class);
bind(ChangeJson.Factory.class).toProvider(Providers.<ChangeJson.Factory>of(null));
bind(EventUtil.class).toProvider(Providers.<EventUtil>of(null));
bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED);
bind(RevisionCreated.class).toInstance(RevisionCreated.DISABLED);
bind(AccountVisibility.class).toProvider(AccountVisibilityProvider.class).in(SINGLETON);
}
}

View File

@@ -14,12 +14,18 @@
package com.google.gerrit.server.args4j;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupBackends;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.InternalGroupDescription;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.Optional;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.OptionDef;
@@ -29,20 +35,50 @@ import org.kohsuke.args4j.spi.Setter;
public class AccountGroupUUIDHandler extends OptionHandler<AccountGroup.UUID> {
private final GroupBackend groupBackend;
private final GroupControl.Factory groupControlFactory;
private final GroupCache groupCache;
@Inject
public AccountGroupUUIDHandler(
final GroupBackend groupBackend,
final GroupControl.Factory groupControlFactory,
@Assisted final CmdLineParser parser,
@Assisted final OptionDef option,
@Assisted final Setter<AccountGroup.UUID> setter) {
@Assisted final Setter<AccountGroup.UUID> setter,
GroupCache groupCache) {
super(parser, option, setter);
this.groupBackend = groupBackend;
this.groupControlFactory = groupControlFactory;
this.groupCache = groupCache;
}
@Override
public final int parseArguments(Parameters params) throws CmdLineException {
final String n = params.getParameter(0);
AccountGroup.UUID uuid = new AccountGroup.UUID(n);
if (groupBackend.handles(uuid)) {
GroupDescription.Basic d = groupBackend.get(uuid);
if (d != null) {
setter.addValue(uuid);
return 1;
}
}
// Might be a numeric AccountGroup.Id. -> Internal group.
if (n.matches("^[1-9][0-9]*$")) {
try {
AccountGroup.Id groupId = AccountGroup.Id.parse(n);
Optional<InternalGroup> groupInternal = groupCache.get(groupId);
if (groupInternal.isPresent()) {
uuid = new InternalGroupDescription(groupInternal.get()).getGroupUUID();
setter.addValue(uuid);
return 1;
}
} catch (IllegalArgumentException e) {
// Ignored
}
}
GroupReference group = GroupBackends.findExactSuggestion(groupBackend, n);
if (group == null) {
throw new CmdLineException(owner, "Group \"" + n + "\" does not exist");

View File

@@ -19,7 +19,9 @@ import com.google.gerrit.extensions.events.AgreementSignupListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.account.AccountState;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class AgreementSignup {
private final DynamicSet<AgreementSignupListener> listeners;
private final EventUtil util;

View File

@@ -23,10 +23,12 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.account.AccountState;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class AssigneeChanged {
private static final Logger log = LoggerFactory.getLogger(AssigneeChanged.class);

View File

@@ -29,11 +29,13 @@ import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class ChangeAbandoned {
private static final Logger log = LoggerFactory.getLogger(ChangeAbandoned.class);

View File

@@ -29,11 +29,13 @@ import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class ChangeMerged {
private static final Logger log = LoggerFactory.getLogger(ChangeMerged.class);

View File

@@ -29,11 +29,13 @@ import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class ChangeRestored {
private static final Logger log = LoggerFactory.getLogger(ChangeRestored.class);

View File

@@ -21,10 +21,12 @@ import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class ChangeReverted {
private static final Logger log = LoggerFactory.getLogger(ChangeReverted.class);

View File

@@ -30,12 +30,14 @@ import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class CommentAdded {
private static final Logger log = LoggerFactory.getLogger(CommentAdded.class);

View File

@@ -35,6 +35,7 @@ import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.EnumSet;
@@ -43,6 +44,7 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class EventUtil {
private static final Logger log = LoggerFactory.getLogger(EventUtil.class);
@@ -65,7 +67,7 @@ public class EventUtil {
private final ChangeData.Factory changeDataFactory;
private final Provider<ReviewDb> db;
private final ChangeJson changeJson;
private final ChangeJson.Factory changeJsonFactory;
@Inject
EventUtil(
@@ -74,11 +76,11 @@ public class EventUtil {
Provider<ReviewDb> db) {
this.changeDataFactory = changeDataFactory;
this.db = db;
this.changeJson = changeJsonFactory.create(CHANGE_OPTIONS);
this.changeJsonFactory = changeJsonFactory;
}
public ChangeInfo changeInfo(Change change) throws OrmException {
return changeJson.format(change);
return changeJsonFactory.create(CHANGE_OPTIONS).format(change);
}
public RevisionInfo revisionInfo(Project project, PatchSet ps)
@@ -91,7 +93,7 @@ public class EventUtil {
throws OrmException, PatchListNotAvailableException, GpgException, IOException,
PermissionBackendException {
ChangeData cd = changeDataFactory.create(db.get(), project, ps.getId().getParentKey());
return changeJson.getRevisionInfo(cd, ps);
return changeJsonFactory.create(CHANGE_OPTIONS).getRevisionInfo(cd, ps);
}
public AccountInfo accountInfo(AccountState accountState) {

View File

@@ -21,11 +21,13 @@ import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.account.AccountState;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.transport.ReceiveCommand;
@Singleton
public class GitReferenceUpdated {
public static final GitReferenceUpdated DISABLED =
new GitReferenceUpdated() {

View File

@@ -24,12 +24,14 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.account.AccountState;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class HashtagsEdited {
private static final Logger log = LoggerFactory.getLogger(HashtagsEdited.class);

View File

@@ -17,7 +17,9 @@ package com.google.gerrit.server.extensions.events;
import com.google.gerrit.extensions.events.PluginEventListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class PluginEvent {
private final DynamicSet<PluginEventListener> listeners;

View File

@@ -23,10 +23,12 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.account.AccountState;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class PrivateStateChanged {
private static final Logger log = LoggerFactory.getLogger(PrivateStateChanged.class);

View File

@@ -30,12 +30,14 @@ import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class ReviewerAdded {
private static final Logger log = LoggerFactory.getLogger(ReviewerAdded.class);

View File

@@ -30,12 +30,14 @@ import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class ReviewerDeleted {
private static final Logger log = LoggerFactory.getLogger(ReviewerDeleted.class);

View File

@@ -29,14 +29,27 @@ import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class RevisionCreated {
private static final Logger log = LoggerFactory.getLogger(RevisionCreated.class);
public static final RevisionCreated DISABLED =
new RevisionCreated() {
@Override
public void fire(
Change change,
PatchSet patchSet,
AccountState uploader,
Timestamp when,
NotifyHandling notify) {}
};
private final DynamicSet<RevisionCreatedListener> listeners;
private final EventUtil util;
@@ -46,6 +59,11 @@ public class RevisionCreated {
this.util = util;
}
private RevisionCreated() {
this.listeners = null;
this.util = null;
}
public void fire(
Change change,
PatchSet patchSet,

View File

@@ -23,10 +23,12 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.account.AccountState;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class TopicEdited {
private static final Logger log = LoggerFactory.getLogger(TopicEdited.class);

View File

@@ -30,12 +30,14 @@ import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class VoteDeleted {
private static final Logger log = LoggerFactory.getLogger(VoteDeleted.class);

View File

@@ -23,10 +23,12 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.account.AccountState;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class WorkInProgressStateChanged {
private static final Logger log = LoggerFactory.getLogger(WorkInProgressStateChanged.class);

View File

@@ -415,8 +415,13 @@ public class SubmoduleOp {
PersonIdent author = null;
DirCache dc = readTree(or.rw, currentCommit);
DirCacheEditor ed = dc.editor();
int count = 0;
for (SubmoduleSubscription s : targets.get(subscriber)) {
if (count > 0) {
msgbuf.append("\n\n");
}
RevCommit newCommit = updateSubmodule(dc, ed, msgbuf, s);
count++;
if (newCommit != null) {
if (author == null) {
author = newCommit.getAuthorIdent();

View File

@@ -395,12 +395,11 @@ public abstract class BaseCommand implements Command {
}
protected String getTaskDescription() {
StringBuilder m = new StringBuilder(commandName);
String[] ta = getTrimmedArguments();
if (ta != null) {
m.append(Joiner.on(" ").join(ta));
return commandName + " " + Joiner.on(" ").join(ta);
}
return m.toString();
return commandName;
}
private String getTaskName() {

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.sshd;
import com.google.common.util.concurrent.Atomics;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.WorkQueue;
@@ -57,6 +58,7 @@ class CommandFactoryProvider implements Provider<CommandFactory>, LifecycleListe
private final ScheduledExecutorService startExecutor;
private final ExecutorService destroyExecutor;
private final SchemaFactory<ReviewDb> schemaFactory;
private final DynamicItem<SshCreateCommandInterceptor> createCommandInterceptor;
@Inject
CommandFactoryProvider(
@@ -65,11 +67,13 @@ class CommandFactoryProvider implements Provider<CommandFactory>, LifecycleListe
WorkQueue workQueue,
SshLog l,
SshScope s,
SchemaFactory<ReviewDb> sf) {
SchemaFactory<ReviewDb> sf,
DynamicItem<SshCreateCommandInterceptor> i) {
dispatcher = d;
log = l;
sshScope = s;
schemaFactory = sf;
createCommandInterceptor = i;
int threads = cfg.getInt("sshd", "commandStartThreads", 2);
startExecutor = workQueue.createQueue(threads, "SshCommandStart");
@@ -94,7 +98,12 @@ class CommandFactoryProvider implements Provider<CommandFactory>, LifecycleListe
return new CommandFactory() {
@Override
public Command createCommand(String requestCommand) {
return new Trampoline(requestCommand);
String c = requestCommand;
SshCreateCommandInterceptor interceptor = createCommandInterceptor.get();
if (interceptor != null) {
c = interceptor.intercept(c);
}
return new Trampoline(c);
}
};
}

View File

@@ -0,0 +1,26 @@
// Copyright (C) 2018 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.sshd;
public interface SshCreateCommandInterceptor {
/**
* Intrcept SSH command creation
*
* @param in command name passed in to command instance creation machinery
* @return intercepted command name
*/
String intercept(String in);
}

View File

@@ -14,7 +14,6 @@
package com.google.gerrit.sshd;
import com.google.common.base.Joiner;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
import com.google.gerrit.common.TimeUtil;
@@ -283,9 +282,9 @@ class SshLog implements LifecycleListener {
return "Command was already destroyed";
}
StringBuilder commandName = new StringBuilder(dcmd.getCommandName());
String[] trimmedArgs = dcmd.getTrimmedArguments();
if (trimmedArgs != null) {
commandName.append(Joiner.on(".").join(trimmedArgs));
String[] args = dcmd.getArguments();
for (int i = 1; i < args.length; i++) {
commandName.append(".").append(args[i]);
}
return commandName.toString();
}

View File

@@ -19,6 +19,7 @@ import static com.google.inject.Scopes.SINGLETON;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.DynamicOptions;
@@ -100,6 +101,7 @@ public class SshModule extends LifecycleModule {
.to(SshPluginStarterCallback.class);
DynamicMap.mapOf(binder(), DynamicOptions.DynamicBean.class);
DynamicItem.itemOf(binder(), SshCreateCommandInterceptor.class);
listener().toInstance(registerInParentInjectors());
listener().to(SshLog.class);

View File

@@ -85,6 +85,7 @@ import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
import com.google.gerrit.extensions.api.changes.ReviewResult;
import com.google.gerrit.extensions.api.changes.RevisionApi;
import com.google.gerrit.extensions.api.changes.StarsInput;
import com.google.gerrit.extensions.api.groups.GroupApi;
import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.client.ChangeKind;
@@ -167,6 +168,7 @@ import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.PushResult;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@NoHttpd
@@ -1504,6 +1506,100 @@ public class ChangeIT extends AbstractDaemonTest {
assertThat(sender.getMessages()).hasSize(1);
}
@Ignore
@Test
public void addReviewerThatIsNotPerfectMatch() throws Exception {
TestTimeUtil.resetWithClockStep(1, SECONDS);
PushOneCommit.Result r = createChange();
ChangeResource rsrc = parseResource(r);
String oldETag = rsrc.getETag();
Timestamp oldTs = rsrc.getChange().getLastUpdatedOn();
//create a group named "ab" with one user: testUser
TestAccount testUser = accountCreator.create("abcd", "abcd@test.com", "abcd");
String testGroup = createGroupWithRealName("ab");
GroupApi groupApi = gApi.groups().id(testGroup);
groupApi.description("test group");
groupApi.addMembers(user.fullName);
AddReviewerInput in = new AddReviewerInput();
in.reviewer = "abc";
gApi.changes().id(r.getChangeId()).addReviewer(in.reviewer);
List<Message> messages = sender.getMessages();
assertThat(messages).hasSize(1);
Message m = messages.get(0);
assertThat(m.rcpt()).containsExactly(testUser.emailAddress);
assertThat(m.body()).contains("Hello " + testUser.fullName + ",\n");
assertThat(m.body()).contains("I'd like you to do a code review.");
assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
assertMailReplyTo(m, testUser.email);
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
// When NoteDb is enabled adding a reviewer records that user as reviewer
// in NoteDb. When NoteDb is disabled adding a reviewer results in a dummy 0
// approval on the change which is treated as CC when the ChangeInfo is
// created.
Collection<AccountInfo> reviewers = c.reviewers.get(REVIEWER);
assertThat(reviewers).isNotNull();
assertThat(reviewers).hasSize(1);
assertThat(reviewers.iterator().next()._accountId).isEqualTo(testUser.getId().get());
// Ensure ETag and lastUpdatedOn are updated.
rsrc = parseResource(r);
assertThat(rsrc.getETag()).isNotEqualTo(oldETag);
assertThat(rsrc.getChange().getLastUpdatedOn()).isNotEqualTo(oldTs);
}
@Ignore
@Test
public void addGroupAsReviewersWhenANotPerfectMatchedUserExists() throws Exception {
TestTimeUtil.resetWithClockStep(1, SECONDS);
PushOneCommit.Result r = createChange();
ChangeResource rsrc = parseResource(r);
String oldETag = rsrc.getETag();
Timestamp oldTs = rsrc.getChange().getLastUpdatedOn();
//create a group named "us" with one user: testUser
TestAccount testUser = accountCreator.create("testUser", "testUser@test.com", "testUser");
String testGroup =
createGroupWithRealName(user.fullName.substring(0, user.fullName.length() / 2));
GroupApi groupApi = gApi.groups().id(testGroup);
groupApi.description("test group");
groupApi.addMembers(testUser.fullName);
//ensure that user "user" is not in the group
groupApi.removeMembers(user.fullName);
AddReviewerInput in = new AddReviewerInput();
in.reviewer = testGroup;
gApi.changes().id(r.getChangeId()).addReviewer(in.reviewer);
List<Message> messages = sender.getMessages();
assertThat(messages).hasSize(1);
Message m = messages.get(0);
assertThat(m.rcpt()).containsExactly(testUser.emailAddress);
assertThat(m.body()).contains("Hello " + testUser.fullName + ",\n");
assertThat(m.body()).contains("I'd like you to do a code review.");
assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
assertMailReplyTo(m, testUser.email);
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
// When NoteDb is enabled adding a reviewer records that user as reviewer
// in NoteDb. When NoteDb is disabled adding a reviewer results in a dummy 0
// approval on the change which is treated as CC when the ChangeInfo is
// created.
Collection<AccountInfo> reviewers = c.reviewers.get(REVIEWER);
assertThat(reviewers).isNotNull();
assertThat(reviewers).hasSize(1);
assertThat(reviewers.iterator().next()._accountId).isEqualTo(testUser.getId().get());
// Ensure ETag and lastUpdatedOn are updated.
rsrc = parseResource(r);
assertThat(rsrc.getETag()).isNotEqualTo(oldETag);
assertThat(rsrc.getChange().getLastUpdatedOn()).isNotEqualTo(oldTs);
}
@Test
public void addReviewerWithNoteDbWhenDummyApprovalInReviewDbExists() throws Exception {
assume().that(notesMigration.readChanges()).isTrue();

View File

@@ -313,6 +313,52 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
expectToHaveSubmoduleState(superRepo, "master", "sub2", sub2, "master");
expectToHaveSubmoduleState(superRepo, "master", "sub3", sub3, "master");
String sub1HEAD =
sub1.git()
.fetch()
.setRemote("origin")
.call()
.getAdvertisedRef("refs/heads/master")
.getObjectId()
.name();
String sub2HEAD =
sub2.git()
.fetch()
.setRemote("origin")
.call()
.getAdvertisedRef("refs/heads/master")
.getObjectId()
.name();
String sub3HEAD =
sub3.git()
.fetch()
.setRemote("origin")
.call()
.getAdvertisedRef("refs/heads/master")
.getObjectId()
.name();
if (getSubmitType() == SubmitType.MERGE_IF_NECESSARY) {
expectToHaveCommitMessage(
superRepo,
"master",
"Update git submodules\n\n"
+ "* Update "
+ name("sub3")
+ " from branch 'master'\n to "
+ sub3HEAD
+ "\n\n* Update "
+ name("sub2")
+ " from branch 'master'\n to "
+ sub2HEAD
+ "\n\n* Update "
+ name("sub1")
+ " from branch 'master'\n to "
+ sub1HEAD);
}
superRepo
.git()
.fetch()

View File

@@ -31,7 +31,7 @@
value: () => {
// Set default values for dropdowns.
return {
create_empty_commit: false,
create_empty_commit: true,
permissions_only: false,
};
},

View File

@@ -49,7 +49,7 @@ limitations under the License.
});
test('default values are populated', () => {
assert.isFalse(element.$.initalCommit.bindValue);
assert.isTrue(element.$.initalCommit.bindValue);
assert.isFalse(element.$.parentRepo.bindValue);
});

View File

@@ -78,6 +78,9 @@ add_ChangeId() {
# - in END, the last textLine+ block is available for footer parsing
$AWK '
BEGIN {
if (match(ENVIRON["OS"], "Windows")) {
RS="\r?\n" # Required on recent Cygwin
}
# while we start with the assumption that textLine+
# is a footer, the first block is not.
isFooter = 0

View File

@@ -113,7 +113,12 @@ for n in sorted(graph.keys()):
print()
print("[[%s_license]]" % safename)
print("----")
with open(n[2:].replace(":", "/")) as fd:
filename = n[2:].replace(":", "/")
try:
with open(filename, errors='ignore') as fd:
copyfileobj(fd, stdout)
except TypeError:
with open(filename) as fd:
copyfileobj(fd, stdout)
print()
print("----")

View File

@@ -68,7 +68,7 @@ def retrieve_ext_location():
return check_output(_build_bazel_cmd('info', 'output_base')).strip()
def gen_bazel_path():
bazel = check_output(['which', 'bazel']).strip()
bazel = check_output(['which', 'bazel']).strip().decode('UTF-8')
with open(path.join(ROOT, ".bazel_path"), 'w') as fd:
fd.write("bazel=%s\n" % bazel)
fd.write("PATH=%s\n" % environ["PATH"])

View File

@@ -39,14 +39,12 @@ try:
continue
elif n.startswith(SERVICES):
# Concatenate all provider configuration files.
myfile = inzip.open(n, 'r')
myfile = io.TextIOWrapper(myfile, encoding='iso-8859-1', newline='')
services[n] += myfile.read()
services[n] += inzip.read(n).decode("UTF-8")
continue
outzip.writestr(info, inzip.read(n))
seen.add(n)
for n, v in services.items():
for n, v in list(services.items()):
outzip.writestr(n, v)
except Exception as err:
exit('Failed to merge jars: %s' % err)