Merge branch 'stable-2.15'

* stable-2.15:
  BranchApi: Add missing throws declaration on NotImplemented#reflog
  FormatUtil: Fix Math#round() truncation error flagged by error-prone
  ReflogIT: Add test coverage for reflog permissions
  ChangeIT: Move reflog test to ReflogIT
  ChangeIT: Fix and expand reflog test
  BranchApi: Add method to get the branch's reflog
  GetReflog: Move ReflogEntryInfo to a separate class in extension API
  Fix http_archive rule in WORKSPACE
  ConfigInfoImpl: Return raw byte value for effective value
  TransferConfig: Move getEffectiveMaxObjectSizeLimit to ProjectState
  ProjectIT: Factor out a method to set the max object size limit
  Documentation: linux-quickstart - include Java 8 requirement
  Documentation: Include Java 8 requirement in installation notes
  Documentation: Remove 'install-quick' page in favour of 'linux-quickstart'

Change-Id: I895790a8b2f9e8439e91c15ba4ee9a5a14a4ee94
This commit is contained in:
David Pursehouse 2018-08-22 21:55:58 +09:00
commit 5b2f0d4b4e
18 changed files with 109 additions and 285 deletions

View File

@ -16,7 +16,8 @@ corporate installations. This is because there is no easy way to interact
with the database while Gerrit is offline, it's not easy to backup the data,
and it's not possible to set up H2 in a load balanced/hotswap configuration.
If this option interests you, you might want to consider link:install-quick.html[the quick guide].
If this option interests you, you might want to consider
link:linux-quickstart.html[the quick guide].
[[createdb_derby]]
=== Apache Derby

View File

@ -1,234 +0,0 @@
= Gerrit Code Review - Quick get started guide
****
This guide was made with the impatient in mind, ready to try out Gerrit on their
own server but not prepared to make the full installation procedure yet.
Explanation is sparse and you should not use a server installed this way in a
live setup, this is made with proof of concept activities in mind.
It is presumed you install it on a Unix based server such as any of the Linux
flavors or BSD.
It's also presumed that you have access to an OpenID enabled email address.
Examples of OpenID enable email providers are Gmail, Yahoo! Mail and Hotmail.
It's also possible to register a custom email address with OpenID, but that is
outside the scope of this quick installation guide. For testing purposes one of
the above providers should be fine. Please note that network access to the
OpenID provider you choose is necessary for both you and your Gerrit instance.
****
[[requirements]]
== Requirements
Most distributions come with Java today. Do you already have Java installed?
----
$ java -version
openjdk version "1.8.0_72"
OpenJDK Runtime Environment (build 1.8.0_72-b15)
OpenJDK 64-Bit Server VM (build 25.72-b15, mixed mode)
----
If Java isn't installed, get it:
* JRE, minimum version 1.8 http://www.oracle.com/technetwork/java/javase/downloads/index.html[Download]
[[user]]
== Create a user to host the Gerrit service
We will run the service as a non-privileged user on your system.
First create the user and then become the user:
----
$ sudo adduser gerrit
$ sudo su gerrit
----
If you don't have root privileges you could skip this step and run Gerrit
as your own user as well.
[[download]]
== Download Gerrit
It's time to download the archive that contains the Gerrit web and ssh service.
You can choose from different versions to download from here:
* https://www.gerritcodereview.com/download/index.html[A list of releases available]
This tutorial is based on version 2.2.2, and you can download that from this link
* https://www.gerritcodereview.com/download/gerrit-2.2.2.war[Link to the 2.2.2 war archive]
[[initialization]]
== Initialize the Site
It's time to run the initialization, and with the batch switch enabled, we don't have to answer any questions at all:
----
gerrit@host:~$ java -jar gerrit.war init --batch -d ~/gerrit_testsite
Generating SSH host key ... rsa(simple)... done
Initialized /home/gerrit/gerrit_testsite
Executing /home/gerrit/gerrit_testsite/bin/gerrit.sh start
Starting Gerrit Code Review: OK
gerrit@host:~$
----
When the init is complete, you can review your settings in the
file `'$site_path/etc/gerrit.config'`.
Note that initialization also starts the server. If any settings changes are
made, the server must be restarted before they will take effect.
----
gerrit@host:~$ ~/gerrit_testsite/bin/gerrit.sh restart
Stopping Gerrit Code Review: OK
Starting Gerrit Code Review: OK
gerrit@host:~$
----
The server can be also stopped and started by passing the `stop` and `start`
commands to gerrit.sh.
----
gerrit@host:~$ ~/gerrit_testsite/bin/gerrit.sh stop
Stopping Gerrit Code Review: OK
gerrit@host:~$
gerrit@host:~$ ~/gerrit_testsite/bin/gerrit.sh start
Starting Gerrit Code Review: OK
gerrit@host:~$
----
include::config-login-register.txt[]
== Project creation
Your base Gerrit server is now running and you have a user that's ready
to interact with it. You now have two options, either you create a new
test project to work with or you already have a git with history that
you would like to import into Gerrit and try out code review on.
=== New project from scratch
If you choose to create a new repository from scratch, it's easier for
you to create a project with an initial commit in it. That way first
time setup between client and server is easier.
This is done via the SSH port:
----
user@host:~$ ssh -p 29418 user@localhost gerrit create-project demo-project --empty-commit
user@host:~$
----
This will create a repository that you can clone to work with.
=== Already existing project
The other alternative is if you already have a git project that you
want to try out Gerrit on.
First you have to create the project. This is done via the SSH port:
----
user@host:~$ ssh -p 29418 user@localhost gerrit create-project demo-project
user@host:~$
----
You need to make sure that at least initially your account is granted
"Create Reference" privileges for the refs/heads/* reference.
This is done via the web interface in the Admin/Projects/Access page
that correspond to your project.
After that it's time to upload the previous history to the server:
----
user@host:~/my-project$ git push ssh://user@localhost:29418/demo-project *:*
Counting objects: 2011, done.
Writing objects: 100% (2011/2011), 456293 bytes, done.
Total 2011 (delta 0), reused 0 (delta 0)
To ssh://user@localhost:29418/demo-project
* [new branch] master -> master
user@host:~/my-project$
----
This will create a repository that you can clone to work with.
== My first change
Download a local clone of the repository and move into it
----
user@host:~$ git clone ssh://user@localhost:29418/demo-project
Cloning into demo-project...
remote: Counting objects: 2, done
remote: Finding sources: 100% (2/2)
remote: Total 2 (delta 0), reused 0 (delta 0)
user@host:~$ cd demo-project
user@host:~/demo-project$
----
Install the link:user-changeid.html[Change-Id commitmsg hook]
----
scp -p -P 29418 user@localhost:hooks/commit-msg $(git rev-parse --git-dir)/hooks/
----
Then make a change to the repository and upload it as a reviewable change
in Gerrit.
----
user@host:~/demo-project$ date > testfile.txt
user@host:~/demo-project$ git add testfile.txt
user@host:~/demo-project$ git commit -m "My pretty test commit"
[master ff643a5] My pretty test commit
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 testfile.txt
user@host:~/demo-project$
----
Usually when you push to a remote git, you push to the reference
`'/refs/heads/branch'`, but when working with Gerrit you have to push to a
virtual branch representing "code review before submission to branch".
This virtual name space is known as /refs/for/<branch>
----
user@host:~/demo-project$ git push origin HEAD:refs/for/master
Counting objects: 4, done.
Writing objects: 100% (3/3), 293 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: New Changes:
remote: http://localhost:8080/1
remote:
To ssh://user@localhost:29418/demo-project
* [new branch] HEAD -> refs/for/master
user@host:~/demo-project$
----
You should now be able to access your change by browsing to the http URL
suggested above, http://localhost:8080/1
== Quick Installation Complete
This covers the scope of getting Gerrit started and your first change uploaded.
It doesn't give any clue as to how the review workflow works, please read
link:http://source.android.com/source/life-of-a-patch[Default Workflow] to
learn more about the workflow of Gerrit.
To read more on the installation of Gerrit please see link:install.html[the detailed
installation page].
GERRIT
------
Part of link:index.html[Gerrit Code Review]
SEARCHBOX
---------

View File

@ -5,7 +5,9 @@
To run the Gerrit service, the following requirement must be met on the host:
* JRE, minimum version 1.8 http://www.oracle.com/technetwork/java/javase/downloads/index.html[Download]
* JRE, version 1.8 http://www.oracle.com/technetwork/java/javase/downloads/index.html[Download]
+
Gerrit is not yet compatible with Java 9 or newer at this time.
By default, Gerrit uses link:note-db.html[NoteDB] as the storage backend. (If
desired, you can _optionally_ use an external database such as MySQL or

View File

@ -16,9 +16,11 @@ link:install.html[Standalone Daemon Installation Guide].
Be sure you have:
<<<<<<< HEAD
. A Unix-based server, including any Linux flavor, MacOS, or Berkeley Software
Distribution (BSD).
. Java SE Runtime Environment 1.8 (or higher).
. Java SE Runtime Environment version 1.8. Gerrit is not compatible with Java
9 or newer yet.
== Download Gerrit

View File

@ -3435,7 +3435,7 @@ limit] of a project.
|===============================
|Field Name ||Description
|`value` |optional|
The effective value of the max object size limit as a formatted string. +
The effective value in bytes of the max object size limit. +
Not set if there is no limit for the object size.
|`configured_value`|optional|
The max object size limit that is configured on the project as a

View File

@ -16,7 +16,7 @@ http_archive(
name = "io_bazel_rules_closure",
sha256 = "4dd84dd2bdd6c9f56cb5a475d504ea31d199c34309e202e9379501d01c3067e5",
strip_prefix = "rules_closure-3103a773820b59b76345f94c231cb213e0d404e2",
url = "https://github.com/bazelbuild/rules_closure/archive/3103a773820b59b76345f94c231cb213e0d404e2.tar.gz",
urls = ["https://github.com/bazelbuild/rules_closure/archive/3103a773820b59b76345f94c231cb213e0d404e2.tar.gz"],
)
# File is specific to Polymer and copied from the Closure Github -- should be

View File

@ -126,7 +126,25 @@ public class FormatUtil {
if (size == 0) {
return Resources.C.notAvailable();
}
int p = Math.abs(Math.round(delta * 100 / size));
int p = Math.abs(saturatedCast(delta * 100 / size));
return p + "%";
}
/**
* Returns the {@code int} nearest in value to {@code value}.
*
* @param value any {@code long} value
* @return the same value cast to {@code int} if it is in the range of the {@code int} type,
* {@link Integer#MAX_VALUE} if it is too large, or {@link Integer#MIN_VALUE} if it is too
* small
*/
private static int saturatedCast(long value) {
if (value > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
if (value < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
return (int) value;
}
}

View File

@ -38,6 +38,8 @@ public interface AdminMessages extends Messages {
String globalMaxObjectSizeLimit(String globalMaxObjectSizeLimit);
String noMaxObjectSizeLimit();
String pluginProjectOptionsTitle(String pluginName);
String pluginProjectInheritedValue(String value);

View File

@ -5,8 +5,9 @@ project = Project {0}
deletedGroup = Deleted Group {0}
deletedReference = Reference {0} was deleted
deletedSection = Section {0} was deleted
effectiveMaxObjectSizeLimit = effective: {0}
effectiveMaxObjectSizeLimit = effective: {0} bytes
globalMaxObjectSizeLimit = The global max object size limit is set to {0}. The limit cannot be increased on project level.
noMaxObjectSizeLimit = No max object size limit is set.
pluginProjectOptionsTitle = {0} Plugin Options
pluginProjectOptionsTitle = {0} Plugin
pluginProjectInheritedValue = inherited: {0}

View File

@ -439,14 +439,15 @@ public class ProjectInfoScreen extends ProjectScreen {
setSubmitType(result.defaultSubmitType());
setState(result.state());
maxObjectSizeLimit.setText(result.maxObjectSizeLimit().configuredValue());
if (result.maxObjectSizeLimit().inheritedValue() != null) {
effectiveMaxObjectSizeLimit.setVisible(true);
if (result.maxObjectSizeLimit().value() != null) {
effectiveMaxObjectSizeLimit.setText(
AdminMessages.I.effectiveMaxObjectSizeLimit(result.maxObjectSizeLimit().value()));
effectiveMaxObjectSizeLimit.setTitle(
AdminMessages.I.globalMaxObjectSizeLimit(result.maxObjectSizeLimit().inheritedValue()));
if (result.maxObjectSizeLimit().inheritedValue() != null) {
effectiveMaxObjectSizeLimit.setTitle(
AdminMessages.I.globalMaxObjectSizeLimit(result.maxObjectSizeLimit().inheritedValue()));
}
} else {
effectiveMaxObjectSizeLimit.setVisible(false);
effectiveMaxObjectSizeLimit.setText(AdminMessages.I.noMaxObjectSizeLimit());
}
saveProject.setEnabled(false);

View File

@ -16,7 +16,6 @@ package com.google.gerrit.server.git;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.concurrent.TimeUnit;
@ -66,14 +65,4 @@ public class TransferConfig {
public String getFormattedMaxObjectSizeLimit() {
return maxObjectSizeLimitFormatted;
}
public long getEffectiveMaxObjectSizeLimit(ProjectState p) {
long global = getMaxObjectSizeLimit();
long local = p.getMaxObjectSizeLimit();
if (global > 0 && local > 0) {
return Math.min(global, local);
}
// zero means "no limit", in this case the max is more limiting
return Math.max(global, local);
}
}

View File

@ -224,7 +224,7 @@ public class AsyncReceiveCommits implements PreReceiveHook {
receivePack.setAllowNonFastForwards(true);
receivePack.setRefLogIdent(user.newRefLogIdent());
receivePack.setTimeout(transferConfig.getTimeout());
receivePack.setMaxObjectSizeLimit(transferConfig.getEffectiveMaxObjectSizeLimit(projectState));
receivePack.setMaxObjectSizeLimit(projectState.getEffectiveMaxObjectSizeLimit());
receivePack.setCheckReceivedObjects(projectState.getConfig().getCheckReceivedObjects());
receivePack.setRefFilter(new ReceiveRefFilter());
receivePack.setAllowPushOptions(true);

View File

@ -46,6 +46,7 @@ import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.BranchOrderSection;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@ -87,6 +88,7 @@ public class ProjectState {
private final ProjectConfig config;
private final Map<String, ProjectLevelConfig> configs;
private final Set<AccountGroup.UUID> localOwners;
private final long globalMaxObjectSizeLimit;
/** Last system time the configuration's revision was examined. */
private volatile long lastCheckGeneration;
@ -114,6 +116,7 @@ public class ProjectState {
GitRepositoryManager gitMgr,
List<CommentLinkInfo> commentLinks,
CapabilityCollection.Factory limitsFactory,
TransferConfig transferConfig,
@Assisted ProjectConfig config) {
this.sitePaths = sitePaths;
this.projectCache = projectCache;
@ -128,6 +131,7 @@ public class ProjectState {
isAllProjects
? limitsFactory.create(config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES))
: null;
this.globalMaxObjectSizeLimit = transferConfig.getMaxObjectSizeLimit();
if (isAllProjects && !Permission.canBeOnAllProjects(AccessSection.ALL, Permission.OWNER)) {
localOwners = Collections.emptySet();
@ -260,6 +264,15 @@ public class ProjectState {
}
}
public long getEffectiveMaxObjectSizeLimit() {
long local = getMaxObjectSizeLimit();
if (globalMaxObjectSizeLimit > 0 && local > 0) {
return Math.min(globalMaxObjectSizeLimit, local);
}
// zero means "no limit", in this case the max is more limiting
return Math.max(globalMaxObjectSizeLimit, local);
}
/** Get the sections that pertain only to this project. */
List<SectionMatcher> getLocalAccessSections() {
List<SectionMatcher> sm = localAccessSections;

View File

@ -110,11 +110,8 @@ public class ConfigInfoImpl extends ConfigInfo {
private MaxObjectSizeLimitInfo getMaxObjectSizeLimit(
ProjectState projectState, TransferConfig transferConfig, Project p) {
MaxObjectSizeLimitInfo info = new MaxObjectSizeLimitInfo();
info.value =
transferConfig.getEffectiveMaxObjectSizeLimit(projectState)
== transferConfig.getMaxObjectSizeLimit()
? transferConfig.getFormattedMaxObjectSizeLimit()
: p.getMaxObjectSizeLimit();
long value = projectState.getEffectiveMaxObjectSizeLimit();
info.value = value == 0 ? null : String.valueOf(value);
info.configuredValue = p.getMaxObjectSizeLimit();
info.inheritedValue = transferConfig.getFormattedMaxObjectSizeLimit();
return info;

View File

@ -422,16 +422,13 @@ public class ProjectIT extends AbstractDaemonTest {
@Test
public void maxObjectSizeCanBeSetAndCleared() throws Exception {
// Set a value
ConfigInput input = new ConfigInput();
input.maxObjectSizeLimit = "100k";
ConfigInfo info = setConfig(input);
assertThat(info.maxObjectSizeLimit.value).isEqualTo("100k");
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
// Clear the value
input.maxObjectSizeLimit = "0";
info = setConfig(input);
info = setMaxObjectSize("0");
assertThat(info.maxObjectSizeLimit.value).isNull();
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
@ -441,9 +438,8 @@ public class ProjectIT extends AbstractDaemonTest {
public void maxObjectSizeIsNotInheritedFromParentProject() throws Exception {
Project.NameKey child = createProject(name("child"), project);
ConfigInput input = new ConfigInput();
input.maxObjectSizeLimit = "100k";
ConfigInfo info = setConfig(input);
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
@ -457,7 +453,7 @@ public class ProjectIT extends AbstractDaemonTest {
@GerritConfig(name = "receive.maxObjectSizeLimit", value = "200k")
public void maxObjectSizeIsInheritedFromGlobalConfig() throws Exception {
ConfigInfo info = getConfig();
assertThat(info.maxObjectSizeLimit.value).isEqualTo("200k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.inheritedValue).isEqualTo("200k");
}
@ -465,10 +461,8 @@ public class ProjectIT extends AbstractDaemonTest {
@Test
@GerritConfig(name = "receive.maxObjectSizeLimit", value = "200k")
public void maxObjectSizeOverridesGlobalConfigWhenLower() throws Exception {
ConfigInput input = new ConfigInput();
input.maxObjectSizeLimit = "100k";
ConfigInfo info = setConfig(input);
assertThat(info.maxObjectSizeLimit.value).isEqualTo("100k");
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.inheritedValue).isEqualTo("200k");
}
@ -476,21 +470,17 @@ public class ProjectIT extends AbstractDaemonTest {
@Test
@GerritConfig(name = "receive.maxObjectSizeLimit", value = "200k")
public void maxObjectSizeDoesNotOverrideGlobalConfigWhenHigher() throws Exception {
ConfigInput input = new ConfigInput();
input.maxObjectSizeLimit = "300k";
ConfigInfo info = setConfig(input);
assertThat(info.maxObjectSizeLimit.value).isEqualTo("200k");
ConfigInfo info = setMaxObjectSize("300k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("300k");
assertThat(info.maxObjectSizeLimit.inheritedValue).isEqualTo("200k");
}
@Test
public void invalidMaxObjectSizeIsRejected() throws Exception {
ConfigInput input = new ConfigInput();
input.maxObjectSizeLimit = "100 foo";
exception.expect(ResourceConflictException.class);
exception.expectMessage("100 foo");
setConfig(input);
setMaxObjectSize("100 foo");
}
private ConfigInfo setConfig(Project.NameKey name, ConfigInput input) throws Exception {
@ -526,6 +516,12 @@ public class ProjectIT extends AbstractDaemonTest {
return input;
}
private ConfigInfo setMaxObjectSize(String value) throws Exception {
ConfigInput input = new ConfigInput();
input.maxObjectSizeLimit = value;
return setConfig(input);
}
private static class ProjectIndexedCounter implements ProjectIndexedListener {
private final AtomicLongMap<String> countsByProject = AtomicLongMap.create();

View File

@ -21,10 +21,15 @@ import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.groups.GroupApi;
import com.google.gerrit.extensions.api.projects.BranchApi;
import com.google.gerrit.extensions.api.projects.ReflogEntryInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.project.testing.Util;
import java.io.File;
import java.util.List;
import org.eclipse.jgit.lib.ReflogEntry;
@ -74,4 +79,32 @@ public class ReflogIT extends AbstractDaemonTest {
reflog = branchApi.reflog();
assertThat(reflog).hasSize(refLogLen + 1);
}
@Test
public void regularUserIsNotAllowedToGetReflog() throws Exception {
setApiUser(user);
exception.expect(AuthException.class);
gApi.projects().name(project.get()).branch("master").reflog();
}
@Test
public void ownerUserIsAllowedToGetReflog() throws Exception {
GroupApi groupApi = gApi.groups().create(name("get-reflog"));
groupApi.addMembers("user");
try (ProjectConfigUpdate u = updateProject(project)) {
Util.allow(
u.getConfig(), Permission.OWNER, new AccountGroup.UUID(groupApi.get().id), "refs/*");
u.save();
}
setApiUser(user);
gApi.projects().name(project.get()).branch("master").reflog();
}
@Test
public void adminUserIsAllowedToGetReflog() throws Exception {
setApiUser(admin);
gApi.projects().name(project.get()).branch("master").reflog();
}
}

View File

@ -56,6 +56,7 @@ import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.AllUsersNameProvider;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.index.SingleVersionModule.SingleVersionListener;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
@ -204,6 +205,7 @@ public class RefControlTest {
@Inject private ThreadLocalRequestContext requestContext;
@Inject private DefaultRefFilter.Factory refFilterFactory;
@Inject private IdentifiedUser.GenericFactory identifiedUserFactory;
@Inject private TransferConfig transferConfig;
@Before
public void setUp() throws Exception {
@ -971,6 +973,7 @@ public class RefControlTest {
repoManager,
commentLinks,
capabilityCollectionFactory,
transferConfig,
pc));
return repo;
}

View File

@ -90,7 +90,7 @@ One-time setup:
1. [Build Gerrit](https://gerrit-review.googlesource.com/Documentation/dev-bazel.html#_gerrit_development_war_file)
2. Set up a local test site. Docs
[here](https://gerrit-review.googlesource.com/Documentation/install-quick.html) and
[here](https://gerrit-review.googlesource.com/Documentation/linux-quickstart.html) and
[here](https://gerrit-review.googlesource.com/Documentation/dev-readme.html#init).
When your project is set up and works using the classic UI, run a test server