Merge branch 'stable-3.1'
* stable-3.1: Update git submodules Update git submodules OperatingSystemMXBeanFactory: Add a default constructor Remove unnecessary @SuppressWarnings("restriction") Set version to 2.16.19-SNAPSHOT Set version to 2.16.18 Update git submodules Update git submodules Update git submodules Update git submodules Add mirror for downloading Bazel rules. Update git submodules Upgrade JGit to v5.6.1.202002131546-r-19-ga79c5b1f1 Upgrade gwtjsonrpc to 1.12 CommitValidators: Use ImmutableList.Builder instead of ImmutableList.of Update git submodules Update git submodules Update git submodules Always verify PolyGerrit if bazel related files are changed Always run all tests, if bazel-related files are changed Fix implementation plan link in Contributing page Add test that verifies 'visibleto' predicate for group Make cache disk stat metric computation optional ReceiveCommits: Log "update failed" at severe level Revert "Insert Change-Id at start of trailers" Revert "commit-msg: Remove obsolete comments" Remove obsolete UpgradeFrom2_0_x init step Update git submodules Update git submodules Add coverageRangeChanged to notify all related listeners Improve documentation of change refs Notify all coverage listeners when coverage data is available Remove duplicate test method removeAnonymousRead ChangeQueryBuilder: Use ChangeIsVisibleToPredicate.Factory ChangeQueryProcessor: Use ChangeIsVisibleToPredicate.Factory Make the build pipeline fail if cannot post Checks feedback Switch to using no-AOP guice distribution Bazel: Use canonical_id for artifacts cached by http_file Fix for Memory leak in gr-plugin-endpoints Documentation: Clarify how to log e2e http details Make legacy version of the commit-msg hook available Don't inject CurrentUser to ChangeIsVisibleToPredicate HttpLogoutServlet: Test redirections with canonicalWebUrl set commit-msg: Remove obsolete comments Upgrade testcontainers to 1.14.0 Bump asm to version 7.2 Upgrade guice to 4.2.3 PostReview: Avoid multiple notifications for existing reviewers ChangeApi: Remove deprecated getEdit method ChangeApi: Remove useless @Deprecated annotation in NotImplemented Plugin API: Remove deprecated draft workflow methods ErrorProne: Enable ObjectToString check at ERROR severity Project: Add implementation of toString Allow HTTP {listen,canonicalWeb}Url in tests Account: Add implementation of toString LegacyChangeNoteWrite: Remove unused newIdent method Update git submodules PolyGerrit: Document commit-container extension endpoint e2e-tests: Make all current scenario names unique e2e-tests: Make http request name unique e2e-tests: Fix CloneUsingBothProtocols wait times e2e-tests: Create/delete ReplayRecordsFromFeeder project e2e-tests: Unhardcode ReplayRecordsFromFeeder data e2e-tests: Stabilize the ReplayRecordsFromFeeder scenario Remove obsolete FindBugs configuration Elasticsearch: Remove support for EOL 6.x versions REST: Allow to create annotated tag with only CREATE_TAG Upgrade recommended version of buildifier to 2.2.1 Bump Bazel version to 3.0.0 CreateRefControl: Pass CurrentUser to Reachable Change-Id: I0d30560b4ee78393ef6f25166999529c88341273
This commit is contained in:
@@ -1 +1 @@
|
||||
2.2.0
|
||||
3.0.0
|
||||
|
@@ -1,143 +0,0 @@
|
||||
#FindBugs User Preferences
|
||||
#Fri Mar 20 17:07:10 JST 2015
|
||||
cloud_id=edu.umd.cs.findbugs.cloud.doNothingCloud
|
||||
detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true
|
||||
detectorAtomicityProblem=AtomicityProblem|true
|
||||
detectorBadAppletConstructor=BadAppletConstructor|false
|
||||
detectorBadResultSetAccess=BadResultSetAccess|true
|
||||
detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true
|
||||
detectorBadUseOfReturnValue=BadUseOfReturnValue|true
|
||||
detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true
|
||||
detectorBooleanReturnNull=BooleanReturnNull|true
|
||||
detectorCallToUnsupportedMethod=CallToUnsupportedMethod|false
|
||||
detectorCheckExpectedWarnings=CheckExpectedWarnings|false
|
||||
detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true
|
||||
detectorCheckRelaxingNullnessAnnotation=CheckRelaxingNullnessAnnotation|true
|
||||
detectorCheckTypeQualifiers=CheckTypeQualifiers|true
|
||||
detectorCloneIdiom=CloneIdiom|true
|
||||
detectorComparatorIdiom=ComparatorIdiom|true
|
||||
detectorConfusedInheritance=ConfusedInheritance|true
|
||||
detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true
|
||||
detectorCovariantArrayAssignment=CovariantArrayAssignment|false
|
||||
detectorCrossSiteScripting=CrossSiteScripting|true
|
||||
detectorDefaultEncodingDetector=DefaultEncodingDetector|true
|
||||
detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true
|
||||
detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true
|
||||
detectorDontIgnoreResultOfPutIfAbsent=DontIgnoreResultOfPutIfAbsent|true
|
||||
detectorDontUseEnum=DontUseEnum|true
|
||||
detectorDroppedException=DroppedException|true
|
||||
detectorDumbMethodInvocations=DumbMethodInvocations|true
|
||||
detectorDumbMethods=DumbMethods|true
|
||||
detectorDuplicateBranches=DuplicateBranches|true
|
||||
detectorEmptyZipFileEntry=EmptyZipFileEntry|false
|
||||
detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true
|
||||
detectorExplicitSerialization=ExplicitSerialization|true
|
||||
detectorFinalizerNullsFields=FinalizerNullsFields|true
|
||||
detectorFindBadCast2=FindBadCast2|true
|
||||
detectorFindBadForLoop=FindBadForLoop|true
|
||||
detectorFindCircularDependencies=FindCircularDependencies|false
|
||||
detectorFindComparatorProblems=FindComparatorProblems|true
|
||||
detectorFindDeadLocalStores=FindDeadLocalStores|true
|
||||
detectorFindDoubleCheck=FindDoubleCheck|true
|
||||
detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true
|
||||
detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true
|
||||
detectorFindFinalizeInvocations=FindFinalizeInvocations|true
|
||||
detectorFindFloatEquality=FindFloatEquality|true
|
||||
detectorFindHEmismatch=FindHEmismatch|true
|
||||
detectorFindInconsistentSync2=FindInconsistentSync2|true
|
||||
detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true
|
||||
detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true
|
||||
detectorFindMaskedFields=FindMaskedFields|true
|
||||
detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true
|
||||
detectorFindNakedNotify=FindNakedNotify|true
|
||||
detectorFindNonShortCircuit=FindNonShortCircuit|true
|
||||
detectorFindNullDeref=FindNullDeref|true
|
||||
detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true
|
||||
detectorFindOpenStream=FindOpenStream|true
|
||||
detectorFindPuzzlers=FindPuzzlers|true
|
||||
detectorFindRefComparison=FindRefComparison|true
|
||||
detectorFindReturnRef=FindReturnRef|true
|
||||
detectorFindRoughConstants=FindRoughConstants|true
|
||||
detectorFindRunInvocations=FindRunInvocations|true
|
||||
detectorFindSelfComparison=FindSelfComparison|true
|
||||
detectorFindSelfComparison2=FindSelfComparison2|true
|
||||
detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true
|
||||
detectorFindSpinLoop=FindSpinLoop|true
|
||||
detectorFindSqlInjection=FindSqlInjection|true
|
||||
detectorFindTwoLockWait=FindTwoLockWait|true
|
||||
detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true
|
||||
detectorFindUnconditionalWait=FindUnconditionalWait|true
|
||||
detectorFindUninitializedGet=FindUninitializedGet|true
|
||||
detectorFindUnrelatedTypesInGenericContainer=FindUnrelatedTypesInGenericContainer|true
|
||||
detectorFindUnreleasedLock=FindUnreleasedLock|true
|
||||
detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true
|
||||
detectorFindUnsyncGet=FindUnsyncGet|true
|
||||
detectorFindUseOfNonSerializableValue=FindUseOfNonSerializableValue|true
|
||||
detectorFindUselessControlFlow=FindUselessControlFlow|true
|
||||
detectorFindUselessObjects=FindUselessObjects|true
|
||||
detectorFormatStringChecker=FormatStringChecker|true
|
||||
detectorHugeSharedStringConstants=HugeSharedStringConstants|true
|
||||
detectorIDivResultCastToDouble=IDivResultCastToDouble|true
|
||||
detectorIncompatMask=IncompatMask|true
|
||||
detectorInconsistentAnnotations=InconsistentAnnotations|true
|
||||
detectorInefficientIndexOf=InefficientIndexOf|true
|
||||
detectorInefficientInitializationInsideLoop=InefficientInitializationInsideLoop|false
|
||||
detectorInefficientMemberAccess=InefficientMemberAccess|false
|
||||
detectorInefficientToArray=InefficientToArray|true
|
||||
detectorInfiniteLoop=InfiniteLoop|true
|
||||
detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true
|
||||
detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true
|
||||
detectorInitializationChain=InitializationChain|true
|
||||
detectorInitializeNonnullFieldsInConstructor=InitializeNonnullFieldsInConstructor|true
|
||||
detectorInstantiateStaticClass=InstantiateStaticClass|true
|
||||
detectorIntCast2LongAsInstant=IntCast2LongAsInstant|true
|
||||
detectorInvalidJUnitTest=InvalidJUnitTest|true
|
||||
detectorIteratorIdioms=IteratorIdioms|true
|
||||
detectorLazyInit=LazyInit|true
|
||||
detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true
|
||||
detectorLostLoggerDueToWeakReference=LostLoggerDueToWeakReference|true
|
||||
detectorMethodReturnCheck=MethodReturnCheck|true
|
||||
detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true
|
||||
detectorMutableEnum=MutableEnum|true
|
||||
detectorMutableLock=MutableLock|true
|
||||
detectorMutableStaticFields=MutableStaticFields|true
|
||||
detectorNaming=Naming|true
|
||||
detectorNoteUnconditionalParamDerefs=NoteUnconditionalParamDerefs|true
|
||||
detectorNumberConstructor=NumberConstructor|true
|
||||
detectorOptionalReturnNull=OptionalReturnNull|true
|
||||
detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true
|
||||
detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true
|
||||
detectorPublicSemaphores=PublicSemaphores|false
|
||||
detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true
|
||||
detectorReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass=ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass|true
|
||||
detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true
|
||||
detectorRedundantConditions=RedundantConditions|true
|
||||
detectorRedundantInterfaces=RedundantInterfaces|true
|
||||
detectorRepeatedConditionals=RepeatedConditionals|true
|
||||
detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true
|
||||
detectorSerializableIdiom=SerializableIdiom|true
|
||||
detectorStartInConstructor=StartInConstructor|true
|
||||
detectorStaticCalendarDetector=StaticCalendarDetector|true
|
||||
detectorStringConcatenation=StringConcatenation|true
|
||||
detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true
|
||||
detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true
|
||||
detectorSwitchFallthrough=SwitchFallthrough|true
|
||||
detectorSynchronizationOnSharedBuiltinConstant=SynchronizationOnSharedBuiltinConstant|true
|
||||
detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true
|
||||
detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true
|
||||
detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true
|
||||
detectorURLProblems=URLProblems|true
|
||||
detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true
|
||||
detectorUnnecessaryMath=UnnecessaryMath|true
|
||||
detectorUnreadFields=UnreadFields|true
|
||||
detectorUselessSubclassMethod=UselessSubclassMethod|false
|
||||
detectorVarArgsProblems=VarArgsProblems|true
|
||||
detectorVolatileUsage=VolatileUsage|true
|
||||
detectorWaitInLoop=WaitInLoop|true
|
||||
detectorWrongMapIterator=WrongMapIterator|true
|
||||
detectorXMLFactoryBypass=XMLFactoryBypass|true
|
||||
detector_threshold=2
|
||||
effort=default
|
||||
filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,EXPERIMENTAL,MALICIOUS_CODE,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false|12
|
||||
filter_settings_neg=NOISE,I18N|
|
||||
run_at_full_build=false
|
@@ -706,6 +706,13 @@ If not absolute, the path is resolved relative to `$site_path`.
|
||||
+
|
||||
Default is unset, no disk cache.
|
||||
|
||||
[[cache.enableDiskStatMetrics]]cache.enableDiskStatMetrics::
|
||||
+
|
||||
Whether to enable the computation of disk statistics of persistent caches.
|
||||
This computation is expensive and requires a long time on larger installations.
|
||||
+
|
||||
By default, false.
|
||||
|
||||
[[cache.h2CacheSize]]cache.h2CacheSize::
|
||||
+
|
||||
The size of the in-memory cache for each opened H2 cache database, in bytes.
|
||||
|
@@ -189,7 +189,9 @@ sbt "gatling:lastReport"
|
||||
|
||||
The `src/test/resources/logback.xml` file
|
||||
link:http://logback.qos.ch/manual/configuration.html[configures,role=external,window=_blank]
|
||||
Gatling's logging level.
|
||||
Gatling's logging level. To quickly
|
||||
enable link:https://gatling.io/docs/current/general/debugging#logback[detailed logging] of `http`
|
||||
requests and responses, the `root level` can be set to `trace` in that file.
|
||||
|
||||
=== How to run using Docker
|
||||
|
||||
|
@@ -114,12 +114,15 @@ explains the link:error-messages.html[error messages].
|
||||
|
||||
[[change-ref]]
|
||||
When a commit is pushed for review, Gerrit stores it in a staging area
|
||||
which is a branch in the special `refs/changes/` namespace. A change
|
||||
ref has the format `refs/changes/XX/YYYY/ZZ` where `YYYY` is the
|
||||
numeric change number, `ZZ` is the patch set number and `XX` is the
|
||||
last two digits of the numeric change number, e.g.
|
||||
`refs/changes/20/884120/1`. Understanding the format of this ref is not
|
||||
required for working with Gerrit.
|
||||
which is a branch in the special `refs/changes/` namespace. Understanding
|
||||
the format of this ref is not required for working with Gerrit, but it
|
||||
is explained below.
|
||||
|
||||
A change ref has the format `refs/changes/X/Y/Z` where `X` is the last
|
||||
two digits of the change number, `Y` is the entire change number, and `Z`
|
||||
is the patch set. For example, if the change number is
|
||||
link:https://gerrit-review.googlesource.com/c/gerrit/+/263270[263270],
|
||||
the ref would be `refs/changes/70/263270/2` for the second patch set.
|
||||
|
||||
[[fetch-change]]
|
||||
Using the change ref git clients can fetch the corresponding commit,
|
||||
|
@@ -922,18 +922,6 @@ EXHIBIT A -Mozilla Public License.
|
||||
----
|
||||
|
||||
|
||||
[[PublicDomain]]
|
||||
PublicDomain
|
||||
|
||||
* guice:aopalliance
|
||||
|
||||
[[PublicDomain_license]]
|
||||
----
|
||||
This software has been placed in the public domain by its author(s).
|
||||
|
||||
----
|
||||
|
||||
|
||||
[[antlr]]
|
||||
antlr
|
||||
|
||||
|
@@ -156,6 +156,22 @@ link:rest-api-changes.html#change-info[ChangeInfo]
|
||||
The submit action, including the title and label, an instance of
|
||||
link:rest-api-changes.html#action-info[ActionInfo]
|
||||
|
||||
=== commit-container
|
||||
The `commit-container` extension point adds content at the end of the commit
|
||||
message to the change view.
|
||||
|
||||
In addition to default parameters, the following are available:
|
||||
|
||||
* `change`
|
||||
+
|
||||
current change displayed, an instance of
|
||||
link:rest-api-changes.html#change-info[ChangeInfo]
|
||||
|
||||
* `revision`
|
||||
+
|
||||
current revision displayed, an instance of
|
||||
link:rest-api-changes.html#revision-info[RevisionInfo]
|
||||
|
||||
== Dynamic Plugin endpoints
|
||||
|
||||
The following endpoints are available to plugins.
|
||||
|
8
Jenkinsfile
vendored
8
Jenkinsfile
vendored
@@ -90,16 +90,18 @@ def collectBuildModes() {
|
||||
def changedFiles = queryChangedFiles(Globals.gerritUrl)
|
||||
def polygerritFiles = changedFiles.findAll { it.startsWith("polygerrit-ui") ||
|
||||
it.startsWith("lib/js") }
|
||||
def bazelFiles = changedFiles.findAll { it == "WORKSPACE" || it.endsWith("BUILD") ||
|
||||
it.endsWith(".bzl") }
|
||||
|
||||
if(polygerritFiles.size() > 0) {
|
||||
if(changedFiles.size() == polygerritFiles.size()) {
|
||||
if(changedFiles.size() == polygerritFiles.size() && bazelFiles.isEmpty()) {
|
||||
println "Only PolyGerrit UI changes detected, skipping other test modes..."
|
||||
Builds.modes = ["polygerrit"]
|
||||
} else {
|
||||
println "PolyGerrit UI changes detected, adding 'polygerrit' validation..."
|
||||
Builds.modes += "polygerrit"
|
||||
}
|
||||
} else if(changedFiles.contains("WORKSPACE")) {
|
||||
} else if(!bazelFiles.isEmpty()) {
|
||||
println "WORKSPACE file changes detected, adding 'polygerrit' validation..."
|
||||
Builds.modes += "polygerrit"
|
||||
}
|
||||
@@ -110,10 +112,10 @@ def prepareBuildsForMode(buildName, mode="notedb", retryTimes = 1) {
|
||||
stage("${buildName}/${mode}") {
|
||||
def slaveBuild = null
|
||||
for (int i = 1; i <= retryTimes; i++) {
|
||||
try {
|
||||
postCheck(new GerritCheck(
|
||||
(buildName == "Gerrit-codestyle") ? "codestyle" : mode,
|
||||
new Build(currentBuild.getAbsoluteUrl(), null)))
|
||||
try {
|
||||
slaveBuild = build job: "${buildName}", parameters: [
|
||||
string(name: 'REFSPEC', value: "refs/changes/${env.BRANCH_NAME}"),
|
||||
string(name: 'BRANCH', value: env.GERRIT_PATCHSET_REVISION),
|
||||
|
34
WORKSPACE
34
WORKSPACE
@@ -52,7 +52,10 @@ http_archive(
|
||||
name = "io_bazel_rules_closure",
|
||||
sha256 = "b9c2bc6ba377aa497eb7c31681d34404febf9d4e3c9c7d98ce0d78238a0af20f",
|
||||
strip_prefix = "rules_closure-0.31",
|
||||
urls = ["https://github.com/davido/rules_closure/archive/V0.31.tar.gz"],
|
||||
urls = [
|
||||
"https://github.com/davido/rules_closure/archive/V0.31.tar.gz",
|
||||
"https://gerrit-ci.gerritforge.com/lib/V0.31.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -153,10 +156,20 @@ maven_jar(
|
||||
|
||||
GUICE_VERS = "4.2.3"
|
||||
|
||||
maven_jar(
|
||||
name = "guice-library",
|
||||
artifact = "com.google.inject:guice:" + GUICE_VERS,
|
||||
sha1 = "2ea992d6d7bdcac7a43111a95d182a4c42eb5ff7",
|
||||
GUICE_LIBRARY_SHA256 = "5168f5e7383f978c1b4154ac777b78edd8ac214bb9f9afdb92921c8d156483d3"
|
||||
|
||||
http_file(
|
||||
name = "guice-library-no-aop",
|
||||
canonical_id = "guice-library-no-aop-" + GUICE_VERS + ".jar-" + GUICE_LIBRARY_SHA256,
|
||||
downloaded_file_path = "guice-library-no-aop.jar",
|
||||
sha256 = GUICE_LIBRARY_SHA256,
|
||||
urls = [
|
||||
"https://repo1.maven.org/maven2/com/google/inject/guice/" +
|
||||
GUICE_VERS +
|
||||
"/guice-" +
|
||||
GUICE_VERS +
|
||||
"-no_aop.jar",
|
||||
],
|
||||
)
|
||||
|
||||
maven_jar(
|
||||
@@ -171,12 +184,6 @@ maven_jar(
|
||||
sha1 = "8d6e7e35eac4fb5e7df19c55b3bc23fa51b10a11",
|
||||
)
|
||||
|
||||
maven_jar(
|
||||
name = "aopalliance",
|
||||
artifact = "aopalliance:aopalliance:1.0",
|
||||
sha1 = "0235ba8b489512805ac13a8f9ea77a1ca5ebe3e8",
|
||||
)
|
||||
|
||||
maven_jar(
|
||||
name = "javax_inject",
|
||||
artifact = "javax.inject:javax.inject:1",
|
||||
@@ -257,14 +264,17 @@ maven_jar(
|
||||
sha1 = "6000774d7f8412ced005a704188ced78beeed2bb",
|
||||
)
|
||||
|
||||
CAFFEINE_GUAVA_SHA256 = "3a66ee3ec70971dee0bae6e56bda7b8742bc4bedd7489161bfbbaaf7137d89e1"
|
||||
|
||||
# TODO(davido): Rename guava.jar to caffeine-guava.jar on fetch to prevent potential
|
||||
# naming collision between caffeine guava adapater and guava library itself.
|
||||
# Remove this renaming procedure, once this upstream issue is fixed:
|
||||
# https://github.com/ben-manes/caffeine/issues/364.
|
||||
http_file(
|
||||
name = "caffeine-guava-renamed",
|
||||
canonical_id = "caffeine-guava-" + CAFFEINE_VERS + ".jar-" + CAFFEINE_GUAVA_SHA256,
|
||||
downloaded_file_path = "caffeine-guava-" + CAFFEINE_VERS + ".jar",
|
||||
sha256 = "3a66ee3ec70971dee0bae6e56bda7b8742bc4bedd7489161bfbbaaf7137d89e1",
|
||||
sha256 = CAFFEINE_GUAVA_SHA256,
|
||||
urls = [
|
||||
"https://repo1.maven.org/maven2/com/github/ben-manes/caffeine/guava/" +
|
||||
CAFFEINE_VERS +
|
||||
|
@@ -1,26 +1,10 @@
|
||||
[
|
||||
{
|
||||
"url": "ssh://admin@localhost:29418/loadtest-repo",
|
||||
"url": "ssh://admin@HOSTNAME:SSH_PORT/_PROJECT",
|
||||
"cmd": "clone"
|
||||
},
|
||||
{
|
||||
"url": "ssh://admin@localhost:29418/loadtest-repo",
|
||||
"cmd": "pull"
|
||||
},
|
||||
{
|
||||
"url": "ssh://admin@localhost:29418/loadtest-repo",
|
||||
"cmd": "push"
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:8080/loadtest-repo",
|
||||
"url": "http://HOSTNAME:HTTP_PORT/_PROJECT",
|
||||
"cmd": "clone"
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:8080/loadtest-repo",
|
||||
"cmd": "pull"
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:8080/loadtest-repo",
|
||||
"cmd": "push"
|
||||
}
|
||||
]
|
||||
|
@@ -28,7 +28,7 @@ class CloneUsingBothProtocols extends GitSimulation {
|
||||
replaceKeyWith("_project", default, in)
|
||||
}
|
||||
|
||||
private val test: ScenarioBuilder = scenario(name)
|
||||
private val test: ScenarioBuilder = scenario(unique)
|
||||
.feed(data)
|
||||
.exec(gitRequest)
|
||||
|
||||
@@ -40,11 +40,11 @@ class CloneUsingBothProtocols extends GitSimulation {
|
||||
atOnceUsers(1)
|
||||
),
|
||||
test.inject(
|
||||
nothingFor(1 second),
|
||||
nothingFor(2 seconds),
|
||||
constantUsersPerSec(1) during (2 seconds)
|
||||
),
|
||||
deleteProject.test.inject(
|
||||
nothingFor(3 second),
|
||||
nothingFor(6 seconds),
|
||||
atOnceUsers(1)
|
||||
),
|
||||
).protocols(gitProtocol, httpProtocol)
|
||||
|
@@ -26,7 +26,7 @@ class CreateProject extends ProjectSimulation {
|
||||
this.default = default
|
||||
}
|
||||
|
||||
val test: ScenarioBuilder = scenario(name)
|
||||
val test: ScenarioBuilder = scenario(unique)
|
||||
.feed(data)
|
||||
.exec(httpRequest)
|
||||
|
||||
|
@@ -26,7 +26,7 @@ class DeleteProject extends ProjectSimulation {
|
||||
this.default = default
|
||||
}
|
||||
|
||||
val test: ScenarioBuilder = scenario(name)
|
||||
val test: ScenarioBuilder = scenario(unique)
|
||||
.feed(data)
|
||||
.exec(httpRequest)
|
||||
|
||||
|
@@ -27,8 +27,9 @@ class GerritSimulation extends Simulation {
|
||||
private val path: String = pack.replaceAllLiterally(".", "/")
|
||||
protected val name: String = this.getClass.getSimpleName
|
||||
protected val resource: String = s"data/$path/$name.json"
|
||||
protected val unique: String = name + "-" + this.hashCode()
|
||||
|
||||
protected val httpRequest: HttpRequestBuilder = http(name).post("${url}")
|
||||
protected val httpRequest: HttpRequestBuilder = http(unique).post("${url}")
|
||||
protected val httpProtocol: HttpProtocolBuilder = http.basicAuth(
|
||||
conf.httpConfiguration.userName,
|
||||
conf.httpConfiguration.password)
|
||||
|
@@ -21,21 +21,37 @@ import io.gatling.core.structure.ScenarioBuilder
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class ReplayRecordsFromFeeder extends GitSimulation {
|
||||
private val data: FileBasedFeederBuilder[Any]#F = jsonFile(resource).circular
|
||||
private val data: FileBasedFeederBuilder[Any]#F#F = jsonFile(resource).convert(url).circular
|
||||
private val default: String = name
|
||||
|
||||
private val test: ScenarioBuilder = scenario(name)
|
||||
.repeat(10000) {
|
||||
override def replaceOverride(in: String): String = {
|
||||
replaceKeyWith("_project", default, in)
|
||||
}
|
||||
|
||||
private val test: ScenarioBuilder = scenario(unique)
|
||||
.repeat(10) {
|
||||
feed(data)
|
||||
.exec(gitRequest)
|
||||
}
|
||||
|
||||
private val createProject = new CreateProject(default)
|
||||
private val deleteProject = new DeleteProject(default)
|
||||
|
||||
setUp(
|
||||
createProject.test.inject(
|
||||
atOnceUsers(1)
|
||||
),
|
||||
test.inject(
|
||||
nothingFor(4 seconds),
|
||||
atOnceUsers(10),
|
||||
rampUsers(10) during (5 seconds),
|
||||
constantUsersPerSec(20) during (15 seconds),
|
||||
constantUsersPerSec(20) during (15 seconds) randomized
|
||||
)).protocols(gitProtocol)
|
||||
.maxDuration(60 seconds)
|
||||
),
|
||||
deleteProject.test.inject(
|
||||
nothingFor(59 seconds),
|
||||
atOnceUsers(1)
|
||||
),
|
||||
).protocols(gitProtocol, httpProtocol)
|
||||
.maxDuration(61 seconds)
|
||||
}
|
||||
|
@@ -20,9 +20,13 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static com.google.common.truth.TruthJUnit.assume;
|
||||
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
|
||||
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
|
||||
import static com.google.gerrit.entities.Patch.COMMIT_MSG;
|
||||
import static com.google.gerrit.entities.Patch.MERGE_LIST;
|
||||
import static com.google.gerrit.extensions.api.changes.SubmittedTogetherOption.NON_VISIBLE_CHANGES;
|
||||
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
|
||||
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
|
||||
import static com.google.gerrit.server.project.ProjectCache.illegalState;
|
||||
import static com.google.gerrit.server.project.testing.TestLabels.label;
|
||||
import static com.google.gerrit.server.project.testing.TestLabels.value;
|
||||
@@ -42,6 +46,7 @@ import com.google.common.primitives.Chars;
|
||||
import com.google.gerrit.acceptance.AcceptanceTestRequestScope.Context;
|
||||
import com.google.gerrit.acceptance.PushOneCommit.Result;
|
||||
import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
|
||||
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
|
||||
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
|
||||
import com.google.gerrit.common.Nullable;
|
||||
import com.google.gerrit.common.data.AccessSection;
|
||||
@@ -299,6 +304,7 @@ public abstract class AbstractDaemonTest {
|
||||
@Inject private ProjectIndexCollection projectIndexes;
|
||||
@Inject private RequestScopeOperations requestScopeOperations;
|
||||
@Inject private SitePaths sitePaths;
|
||||
@Inject private ProjectOperations projectOperations;
|
||||
|
||||
private ProjectResetter resetter;
|
||||
private List<Repository> toClose;
|
||||
@@ -414,6 +420,9 @@ public abstract class AbstractDaemonTest {
|
||||
baseConfig.setString("sshd", null, "listenAddress", "off");
|
||||
}
|
||||
|
||||
baseConfig.unset("gerrit", null, "canonicalWebUrl");
|
||||
baseConfig.unset("httpd", null, "listenUrl");
|
||||
|
||||
baseConfig.setInt("index", null, "batchThreads", -1);
|
||||
|
||||
baseConfig.setInt("receive", null, "changeUpdateThreads", 4);
|
||||
@@ -987,6 +996,16 @@ public abstract class AbstractDaemonTest {
|
||||
}
|
||||
}
|
||||
|
||||
protected void blockAnonymousRead() throws Exception {
|
||||
String allRefs = RefNames.REFS + "*";
|
||||
projectOperations
|
||||
.project(project)
|
||||
.forUpdate()
|
||||
.add(block(Permission.READ).ref(allRefs).group(ANONYMOUS_USERS))
|
||||
.add(allow(Permission.READ).ref(allRefs).group(REGISTERED_USERS))
|
||||
.update();
|
||||
}
|
||||
|
||||
protected PushOneCommit.Result pushTo(String ref) throws Exception {
|
||||
PushOneCommit push = pushFactory.create(admin.newIdent(), testRepo);
|
||||
return push.to(ref);
|
||||
|
@@ -468,9 +468,13 @@ public class GerritServer implements AutoCloseable {
|
||||
private static void mergeTestConfig(Config cfg) {
|
||||
String forceEphemeralPort = String.format("%s:0", getLocalHost().getHostName());
|
||||
String url = "http://" + forceEphemeralPort + "/";
|
||||
cfg.setString("gerrit", null, "canonicalWebUrl", url);
|
||||
cfg.setString("httpd", null, "listenUrl", url);
|
||||
|
||||
if (cfg.getString("gerrit", null, "canonicalWebUrl") == null) {
|
||||
cfg.setString("gerrit", null, "canonicalWebUrl", url);
|
||||
}
|
||||
if (cfg.getString("httpd", null, "listenUrl") == null) {
|
||||
cfg.setString("httpd", null, "listenUrl", url);
|
||||
}
|
||||
if (cfg.getString("sshd", null, "listenAddress") == null) {
|
||||
cfg.setString("sshd", null, "listenAddress", forceEphemeralPort);
|
||||
}
|
||||
|
@@ -18,9 +18,6 @@ import com.google.common.base.Joiner;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public enum ElasticVersion {
|
||||
V6_2("6.2.*"),
|
||||
V6_3("6.3.*"),
|
||||
V6_4("6.4.*"),
|
||||
V6_5("6.5.*"),
|
||||
V6_6("6.6.*"),
|
||||
V6_7("6.7.*"),
|
||||
|
@@ -269,4 +269,9 @@ public abstract class Account {
|
||||
|
||||
public abstract Account build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/** Projects match a source code repository managed by Gerrit */
|
||||
public final class Project {
|
||||
@@ -247,4 +248,9 @@ public final class Project {
|
||||
public void setConfigRefState(String state) {
|
||||
configRefState = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Optional.of(getName()).orElse("<null>");
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,6 @@ import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeMessageInfo;
|
||||
import com.google.gerrit.extensions.common.CommentInfo;
|
||||
import com.google.gerrit.extensions.common.CommitMessageInput;
|
||||
import com.google.gerrit.extensions.common.EditInfo;
|
||||
import com.google.gerrit.extensions.common.MergePatchSetInput;
|
||||
import com.google.gerrit.extensions.common.PureRevertInfo;
|
||||
import com.google.gerrit.extensions.common.RevertSubmissionInfo;
|
||||
@@ -187,12 +186,6 @@ public interface ChangeApi {
|
||||
EnumSet<ListChangesOption> listOptions, EnumSet<SubmittedTogetherOption> submitOptions)
|
||||
throws RestApiException;
|
||||
|
||||
/** Publishes a draft change. */
|
||||
@Deprecated
|
||||
default void publish() {
|
||||
throw new UnsupportedOperationException("draft workflow is discontinued");
|
||||
}
|
||||
|
||||
/** Rebase the current revision of a change using default options. */
|
||||
default void rebase() throws RestApiException {
|
||||
rebase(new RebaseInput());
|
||||
@@ -272,17 +265,6 @@ public interface ChangeApi {
|
||||
return get(EnumSet.noneOf(ListChangesOption.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve change edit when exists.
|
||||
*
|
||||
* @deprecated Replaced by {@link ChangeApi#edit()} in combination with {@link
|
||||
* ChangeEditApi#get()}.
|
||||
*/
|
||||
@Deprecated
|
||||
default EditInfo getEdit() throws RestApiException {
|
||||
return edit().get().orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to an API regarding the change edit of this change.
|
||||
*
|
||||
|
@@ -38,11 +38,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface RevisionApi {
|
||||
@Deprecated
|
||||
default void delete() {
|
||||
throw new UnsupportedOperationException("draft workflow is discontinued");
|
||||
}
|
||||
|
||||
String description() throws RestApiException;
|
||||
|
||||
void description(String description) throws RestApiException;
|
||||
@@ -62,11 +57,6 @@ public interface RevisionApi {
|
||||
|
||||
BinaryResult submitPreview(String format) throws RestApiException;
|
||||
|
||||
@Deprecated
|
||||
default void publish() {
|
||||
throw new UnsupportedOperationException("draft workflow is discontinued");
|
||||
}
|
||||
|
||||
ChangeApi cherryPick(CherryPickInput in) throws RestApiException;
|
||||
|
||||
ChangeInfo cherryPickAsInfo(CherryPickInput in) throws RestApiException;
|
||||
|
@@ -20,10 +20,11 @@ import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
class OperatingSystemMXBeanFactory {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private OperatingSystemMXBeanFactory() {}
|
||||
|
||||
static OperatingSystemMXBeanInterface create() {
|
||||
OperatingSystemMXBean sys = ManagementFactory.getOperatingSystemMXBean();
|
||||
if (sys instanceof UnixOperatingSystemMXBean) {
|
||||
|
@@ -16,7 +16,6 @@ package com.google.gerrit.metrics.proc;
|
||||
|
||||
import com.sun.management.UnixOperatingSystemMXBean;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
class OperatingSystemMXBeanUnixNative implements OperatingSystemMXBeanInterface {
|
||||
private final UnixOperatingSystemMXBean sys;
|
||||
|
||||
|
@@ -76,6 +76,7 @@ import com.google.gerrit.server.project.ProjectCacheImpl;
|
||||
import com.google.gerrit.server.project.ProjectState;
|
||||
import com.google.gerrit.server.project.SubmitRuleEvaluator;
|
||||
import com.google.gerrit.server.query.change.ChangeData;
|
||||
import com.google.gerrit.server.query.change.ChangeIsVisibleToPredicate;
|
||||
import com.google.gerrit.server.restapi.group.GroupModule;
|
||||
import com.google.gerrit.server.rules.DefaultSubmitRule;
|
||||
import com.google.gerrit.server.rules.IgnoreSelfApprovalRule;
|
||||
@@ -167,6 +168,7 @@ public class BatchProgramModule extends FactoryModule {
|
||||
install(PureRevertCache.module());
|
||||
factory(CapabilityCollection.Factory.class);
|
||||
factory(ChangeData.AssistedFactory.class);
|
||||
factory(ChangeIsVisibleToPredicate.Factory.class);
|
||||
factory(ProjectState.Factory.class);
|
||||
|
||||
// Submit rules
|
||||
|
@@ -25,10 +25,12 @@ import com.google.gerrit.metrics.CallbackMetric1;
|
||||
import com.google.gerrit.metrics.Description;
|
||||
import com.google.gerrit.metrics.Field;
|
||||
import com.google.gerrit.metrics.MetricMaker;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.logging.Metadata;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.Set;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
|
||||
@Singleton
|
||||
public class CacheMetrics {
|
||||
@@ -36,7 +38,8 @@ public class CacheMetrics {
|
||||
Field.ofString("cache_name", Metadata.Builder::cacheName).build();
|
||||
|
||||
@Inject
|
||||
public CacheMetrics(MetricMaker metrics, DynamicMap<Cache<?, ?>> cacheMap) {
|
||||
public CacheMetrics(
|
||||
MetricMaker metrics, DynamicMap<Cache<?, ?>> cacheMap, @GerritServerConfig Config config) {
|
||||
CallbackMetric1<String, Long> memEnt =
|
||||
metrics.newCallbackMetric(
|
||||
"caches/memory_cached",
|
||||
@@ -81,7 +84,8 @@ public class CacheMetrics {
|
||||
memEnt.set(name, c.size());
|
||||
memHit.set(name, cstats.hitRate() * 100);
|
||||
memEvict.set(name, cstats.evictionCount());
|
||||
if (c instanceof PersistentCache) {
|
||||
if (c instanceof PersistentCache
|
||||
&& config.getBoolean("cache", "enableDiskStatMetrics", false)) {
|
||||
PersistentCache.DiskStats d = ((PersistentCache) c).diskStats();
|
||||
perDiskEnt.set(name, d.size());
|
||||
perDiskHit.set(name, hitRatio(d));
|
||||
|
@@ -173,6 +173,7 @@ import com.google.gerrit.server.project.ProjectNameLockManager;
|
||||
import com.google.gerrit.server.project.ProjectState;
|
||||
import com.google.gerrit.server.project.SubmitRuleEvaluator;
|
||||
import com.google.gerrit.server.query.change.ChangeData;
|
||||
import com.google.gerrit.server.query.change.ChangeIsVisibleToPredicate;
|
||||
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
|
||||
import com.google.gerrit.server.query.change.ConflictsCacheImpl;
|
||||
import com.google.gerrit.server.quota.QuotaEnforcer;
|
||||
@@ -263,6 +264,7 @@ public class GerritGlobalModule extends FactoryModule {
|
||||
factory(CapabilityCollection.Factory.class);
|
||||
factory(ChangeData.AssistedFactory.class);
|
||||
factory(ChangeJson.AssistedFactory.class);
|
||||
factory(ChangeIsVisibleToPredicate.Factory.class);
|
||||
factory(LabelsJson.Factory.class);
|
||||
factory(MergeUtil.Factory.class);
|
||||
factory(PatchScriptFactory.Factory.class);
|
||||
|
@@ -141,23 +141,25 @@ public class CommitValidators {
|
||||
PermissionBackend.ForRef perm = forProject.ref(branch.branch());
|
||||
ProjectState projectState =
|
||||
projectCache.get(branch.project()).orElseThrow(illegalState(branch.project()));
|
||||
return new CommitValidators(
|
||||
ImmutableList.of(
|
||||
new UploadMergesPermissionValidator(perm),
|
||||
new ProjectStateValidationListener(projectState),
|
||||
new AmendedGerritMergeCommitValidationListener(perm, gerritIdent),
|
||||
new AuthorUploaderValidator(user, perm, urlFormatter.get()),
|
||||
new FileCountValidator(repoManager, config),
|
||||
new CommitterUploaderValidator(user, perm, urlFormatter.get()),
|
||||
new SignedOffByValidator(user, perm, projectState),
|
||||
ImmutableList.Builder<CommitValidationListener> validators = ImmutableList.builder();
|
||||
validators
|
||||
.add(new UploadMergesPermissionValidator(perm))
|
||||
.add(new ProjectStateValidationListener(projectState))
|
||||
.add(new AmendedGerritMergeCommitValidationListener(perm, gerritIdent))
|
||||
.add(new AuthorUploaderValidator(user, perm, urlFormatter.get()))
|
||||
.add(new FileCountValidator(repoManager, config))
|
||||
.add(new CommitterUploaderValidator(user, perm, urlFormatter.get()))
|
||||
.add(new SignedOffByValidator(user, perm, projectState))
|
||||
.add(
|
||||
new ChangeIdValidator(
|
||||
projectState, user, urlFormatter.get(), config, sshInfo, change),
|
||||
new ConfigValidator(projectConfigFactory, branch, user, rw, allUsers, allProjects),
|
||||
new BannedCommitsValidator(rejectCommits),
|
||||
new PluginCommitValidationListener(pluginValidators, skipValidation),
|
||||
new ExternalIdUpdateListener(allUsers, externalIdsConsistencyChecker),
|
||||
new AccountCommitValidator(repoManager, allUsers, accountValidator),
|
||||
new GroupCommitValidator(allUsers)));
|
||||
projectState, user, urlFormatter.get(), config, sshInfo, change))
|
||||
.add(new ConfigValidator(projectConfigFactory, branch, user, rw, allUsers, allProjects))
|
||||
.add(new BannedCommitsValidator(rejectCommits))
|
||||
.add(new PluginCommitValidationListener(pluginValidators, skipValidation))
|
||||
.add(new ExternalIdUpdateListener(allUsers, externalIdsConsistencyChecker))
|
||||
.add(new AccountCommitValidator(repoManager, allUsers, accountValidator))
|
||||
.add(new GroupCommitValidator(allUsers));
|
||||
return new CommitValidators(validators.build());
|
||||
}
|
||||
|
||||
public CommitValidators forGerritCommits(
|
||||
@@ -170,21 +172,23 @@ public class CommitValidators {
|
||||
PermissionBackend.ForRef perm = forProject.ref(branch.branch());
|
||||
ProjectState projectState =
|
||||
projectCache.get(branch.project()).orElseThrow(illegalState(branch.project()));
|
||||
return new CommitValidators(
|
||||
ImmutableList.of(
|
||||
new UploadMergesPermissionValidator(perm),
|
||||
new ProjectStateValidationListener(projectState),
|
||||
new AmendedGerritMergeCommitValidationListener(perm, gerritIdent),
|
||||
new AuthorUploaderValidator(user, perm, urlFormatter.get()),
|
||||
new FileCountValidator(repoManager, config),
|
||||
new SignedOffByValidator(user, perm, projectState),
|
||||
ImmutableList.Builder<CommitValidationListener> validators = ImmutableList.builder();
|
||||
validators
|
||||
.add(new UploadMergesPermissionValidator(perm))
|
||||
.add(new ProjectStateValidationListener(projectState))
|
||||
.add(new AmendedGerritMergeCommitValidationListener(perm, gerritIdent))
|
||||
.add(new AuthorUploaderValidator(user, perm, urlFormatter.get()))
|
||||
.add(new FileCountValidator(repoManager, config))
|
||||
.add(new SignedOffByValidator(user, perm, projectState))
|
||||
.add(
|
||||
new ChangeIdValidator(
|
||||
projectState, user, urlFormatter.get(), config, sshInfo, change),
|
||||
new ConfigValidator(projectConfigFactory, branch, user, rw, allUsers, allProjects),
|
||||
new PluginCommitValidationListener(pluginValidators),
|
||||
new ExternalIdUpdateListener(allUsers, externalIdsConsistencyChecker),
|
||||
new AccountCommitValidator(repoManager, allUsers, accountValidator),
|
||||
new GroupCommitValidator(allUsers)));
|
||||
projectState, user, urlFormatter.get(), config, sshInfo, change))
|
||||
.add(new ConfigValidator(projectConfigFactory, branch, user, rw, allUsers, allProjects))
|
||||
.add(new PluginCommitValidationListener(pluginValidators))
|
||||
.add(new ExternalIdUpdateListener(allUsers, externalIdsConsistencyChecker))
|
||||
.add(new AccountCommitValidator(repoManager, allUsers, accountValidator))
|
||||
.add(new GroupCommitValidator(allUsers));
|
||||
return new CommitValidators(validators.build());
|
||||
}
|
||||
|
||||
public CommitValidators forMergedCommits(
|
||||
@@ -205,12 +209,13 @@ public class CommitValidators {
|
||||
PermissionBackend.ForRef perm = forProject.ref(branch.branch());
|
||||
ProjectState projectState =
|
||||
projectCache.get(branch.project()).orElseThrow(illegalState(branch.project()));
|
||||
return new CommitValidators(
|
||||
ImmutableList.of(
|
||||
new UploadMergesPermissionValidator(perm),
|
||||
new ProjectStateValidationListener(projectState),
|
||||
new AuthorUploaderValidator(user, perm, urlFormatter.get()),
|
||||
new CommitterUploaderValidator(user, perm, urlFormatter.get())));
|
||||
ImmutableList.Builder<CommitValidationListener> validators = ImmutableList.builder();
|
||||
validators
|
||||
.add(new UploadMergesPermissionValidator(perm))
|
||||
.add(new ProjectStateValidationListener(projectState))
|
||||
.add(new AuthorUploaderValidator(user, perm, urlFormatter.get()))
|
||||
.add(new CommitterUploaderValidator(user, perm, urlFormatter.get()));
|
||||
return new CommitValidators(validators.build());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -366,7 +366,7 @@ public abstract class ChangeEmail extends NotificationEmail {
|
||||
}
|
||||
}
|
||||
|
||||
/** Users who have non-zero approval codes on the change. */
|
||||
/** Users who were added as reviewers to this change. */
|
||||
protected void ccExistingReviewers() {
|
||||
if (!NotifyHandling.ALL.equals(notify.handling())
|
||||
&& !NotifyHandling.OWNER_REVIEWERS.equals(notify.handling())) {
|
||||
|
@@ -29,6 +29,7 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
@@ -76,7 +77,7 @@ public class CreateRefControl {
|
||||
PermissionBackend.ForRef perm = permissionBackend.user(user.get()).ref(branch);
|
||||
if (object instanceof RevCommit) {
|
||||
perm.check(RefPermission.CREATE);
|
||||
checkCreateCommit(repo, (RevCommit) object, ps.getNameKey(), perm);
|
||||
checkCreateCommit(user, repo, (RevCommit) object, ps.getNameKey(), perm);
|
||||
} else if (object instanceof RevTag) {
|
||||
RevTag tag = (RevTag) object;
|
||||
try (RevWalk rw = new RevWalk(repo)) {
|
||||
@@ -96,7 +97,7 @@ public class CreateRefControl {
|
||||
|
||||
RevObject target = tag.getObject();
|
||||
if (target instanceof RevCommit) {
|
||||
checkCreateCommit(repo, (RevCommit) target, ps.getNameKey(), perm);
|
||||
checkCreateCommit(user, repo, (RevCommit) target, ps.getNameKey(), perm);
|
||||
} else {
|
||||
checkCreateRef(user, repo, branch, target);
|
||||
}
|
||||
@@ -117,7 +118,11 @@ public class CreateRefControl {
|
||||
* new commit to the repository.
|
||||
*/
|
||||
private void checkCreateCommit(
|
||||
Repository repo, RevCommit commit, Project.NameKey project, PermissionBackend.ForRef forRef)
|
||||
Provider<? extends CurrentUser> user,
|
||||
Repository repo,
|
||||
RevCommit commit,
|
||||
Project.NameKey project,
|
||||
PermissionBackend.ForRef forRef)
|
||||
throws AuthException, PermissionBackendException, IOException {
|
||||
try {
|
||||
// If the user has update (push) permission, they can create the ref regardless
|
||||
@@ -131,7 +136,8 @@ public class CreateRefControl {
|
||||
project,
|
||||
repo,
|
||||
commit,
|
||||
repo.getRefDatabase().getRefsByPrefix(Constants.R_HEADS, Constants.R_TAGS))) {
|
||||
repo.getRefDatabase().getRefsByPrefix(Constants.R_HEADS, Constants.R_TAGS),
|
||||
Optional.of(user.get()))) {
|
||||
// If the user has no push permissions, check whether the object is
|
||||
// merged into a branch or tag readable by this user. If so, they are
|
||||
// not effectively "pushing" more objects, so they can create the ref
|
||||
|
@@ -16,6 +16,7 @@ package com.google.gerrit.server.project;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.gerrit.entities.Project;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.change.IncludedInResolver;
|
||||
import com.google.gerrit.server.logging.Metadata;
|
||||
import com.google.gerrit.server.logging.TraceContext;
|
||||
@@ -28,6 +29,7 @@ import com.google.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
@@ -55,10 +57,20 @@ public class Reachable {
|
||||
*/
|
||||
public boolean fromRefs(
|
||||
Project.NameKey project, Repository repo, RevCommit commit, List<Ref> refs) {
|
||||
return fromRefs(project, repo, commit, refs, Optional.empty());
|
||||
}
|
||||
|
||||
boolean fromRefs(
|
||||
Project.NameKey project,
|
||||
Repository repo,
|
||||
RevCommit commit,
|
||||
List<Ref> refs,
|
||||
Optional<CurrentUser> optionalUserProvider) {
|
||||
try (RevWalk rw = new RevWalk(repo)) {
|
||||
Collection<Ref> filtered =
|
||||
permissionBackend
|
||||
.currentUser()
|
||||
optionalUserProvider
|
||||
.map(permissionBackend::user)
|
||||
.orElse(permissionBackend.currentUser())
|
||||
.project(project)
|
||||
.filter(refs, repo, RefFilterOptions.defaults());
|
||||
|
||||
|
@@ -30,12 +30,17 @@ import com.google.gerrit.server.project.ProjectCache;
|
||||
import com.google.gerrit.server.project.ProjectState;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import java.util.Optional;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
|
||||
public class ChangeIsVisibleToPredicate extends IsVisibleToPredicate<ChangeData> {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
public interface Factory {
|
||||
ChangeIsVisibleToPredicate forUser(CurrentUser user);
|
||||
}
|
||||
|
||||
protected final ChangeNotes.Factory notesFactory;
|
||||
protected final CurrentUser user;
|
||||
protected final PermissionBackend permissionBackend;
|
||||
@@ -45,10 +50,10 @@ public class ChangeIsVisibleToPredicate extends IsVisibleToPredicate<ChangeData>
|
||||
@Inject
|
||||
public ChangeIsVisibleToPredicate(
|
||||
ChangeNotes.Factory notesFactory,
|
||||
CurrentUser user,
|
||||
PermissionBackend permissionBackend,
|
||||
ProjectCache projectCache,
|
||||
Provider<AnonymousUser> anonymousUserProvider) {
|
||||
Provider<AnonymousUser> anonymousUserProvider,
|
||||
@Assisted CurrentUser user) {
|
||||
super(ChangeQueryBuilder.FIELD_VISIBLETO, IndexUtils.describe(user));
|
||||
this.notesFactory = notesFactory;
|
||||
this.user = user;
|
||||
|
@@ -49,7 +49,6 @@ import com.google.gerrit.index.query.QueryBuilder;
|
||||
import com.google.gerrit.index.query.QueryParseException;
|
||||
import com.google.gerrit.index.query.QueryRequiresAuthException;
|
||||
import com.google.gerrit.mail.Address;
|
||||
import com.google.gerrit.server.AnonymousUser;
|
||||
import com.google.gerrit.server.CommentsUtil;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
@@ -75,7 +74,6 @@ import com.google.gerrit.server.index.change.ChangeField;
|
||||
import com.google.gerrit.server.index.change.ChangeIndex;
|
||||
import com.google.gerrit.server.index.change.ChangeIndexCollection;
|
||||
import com.google.gerrit.server.index.change.ChangeIndexRewriter;
|
||||
import com.google.gerrit.server.notedb.ChangeNotes;
|
||||
import com.google.gerrit.server.notedb.ReviewerStateInternal;
|
||||
import com.google.gerrit.server.patch.PatchListCache;
|
||||
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||
@@ -217,7 +215,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
final ChangeData.Factory changeDataFactory;
|
||||
final ChangeIndex index;
|
||||
final ChangeIndexRewriter rewriter;
|
||||
final ChangeNotes.Factory notesFactory;
|
||||
final CommentsUtil commentsUtil;
|
||||
final ConflictsCache conflictsCache;
|
||||
final DynamicMap<ChangeHasOperandFactory> hasOperands;
|
||||
@@ -233,7 +230,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
final StarredChangesUtil starredChangesUtil;
|
||||
final SubmitDryRun submitDryRun;
|
||||
final GroupMembers groupMembers;
|
||||
final Provider<AnonymousUser> anonymousUserProvider;
|
||||
final ChangeIsVisibleToPredicate.Factory changeIsVisbleToPredicateFactory;
|
||||
final OperatorAliasConfig operatorAliasConfig;
|
||||
final boolean indexMergeable;
|
||||
final HasOperandAliasConfig hasOperandAliasConfig;
|
||||
@@ -250,7 +247,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
IdentifiedUser.GenericFactory userFactory,
|
||||
Provider<CurrentUser> self,
|
||||
PermissionBackend permissionBackend,
|
||||
ChangeNotes.Factory notesFactory,
|
||||
ChangeData.Factory changeDataFactory,
|
||||
CommentsUtil commentsUtil,
|
||||
AccountResolver accountResolver,
|
||||
@@ -268,10 +264,10 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
StarredChangesUtil starredChangesUtil,
|
||||
AccountCache accountCache,
|
||||
GroupMembers groupMembers,
|
||||
Provider<AnonymousUser> anonymousUserProvider,
|
||||
OperatorAliasConfig operatorAliasConfig,
|
||||
@GerritServerConfig Config gerritConfig,
|
||||
HasOperandAliasConfig hasOperandAliasConfig) {
|
||||
HasOperandAliasConfig hasOperandAliasConfig,
|
||||
ChangeIsVisibleToPredicate.Factory changeIsVisbleToPredicateFactory) {
|
||||
this(
|
||||
queryProvider,
|
||||
rewriter,
|
||||
@@ -280,7 +276,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
userFactory,
|
||||
self,
|
||||
permissionBackend,
|
||||
notesFactory,
|
||||
changeDataFactory,
|
||||
commentsUtil,
|
||||
accountResolver,
|
||||
@@ -298,10 +293,10 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
starredChangesUtil,
|
||||
accountCache,
|
||||
groupMembers,
|
||||
anonymousUserProvider,
|
||||
operatorAliasConfig,
|
||||
MergeabilityComputationBehavior.fromConfig(gerritConfig).includeInIndex(),
|
||||
hasOperandAliasConfig);
|
||||
hasOperandAliasConfig,
|
||||
changeIsVisbleToPredicateFactory);
|
||||
}
|
||||
|
||||
private Arguments(
|
||||
@@ -312,7 +307,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
IdentifiedUser.GenericFactory userFactory,
|
||||
Provider<CurrentUser> self,
|
||||
PermissionBackend permissionBackend,
|
||||
ChangeNotes.Factory notesFactory,
|
||||
ChangeData.Factory changeDataFactory,
|
||||
CommentsUtil commentsUtil,
|
||||
AccountResolver accountResolver,
|
||||
@@ -330,17 +324,16 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
StarredChangesUtil starredChangesUtil,
|
||||
AccountCache accountCache,
|
||||
GroupMembers groupMembers,
|
||||
Provider<AnonymousUser> anonymousUserProvider,
|
||||
OperatorAliasConfig operatorAliasConfig,
|
||||
boolean indexMergeable,
|
||||
HasOperandAliasConfig hasOperandAliasConfig) {
|
||||
HasOperandAliasConfig hasOperandAliasConfig,
|
||||
ChangeIsVisibleToPredicate.Factory changeIsVisbleToPredicateFactory) {
|
||||
this.queryProvider = queryProvider;
|
||||
this.rewriter = rewriter;
|
||||
this.opFactories = opFactories;
|
||||
this.userFactory = userFactory;
|
||||
this.self = self;
|
||||
this.permissionBackend = permissionBackend;
|
||||
this.notesFactory = notesFactory;
|
||||
this.changeDataFactory = changeDataFactory;
|
||||
this.commentsUtil = commentsUtil;
|
||||
this.accountResolver = accountResolver;
|
||||
@@ -359,7 +352,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
this.accountCache = accountCache;
|
||||
this.hasOperands = hasOperands;
|
||||
this.groupMembers = groupMembers;
|
||||
this.anonymousUserProvider = anonymousUserProvider;
|
||||
this.changeIsVisbleToPredicateFactory = changeIsVisbleToPredicateFactory;
|
||||
this.operatorAliasConfig = operatorAliasConfig;
|
||||
this.indexMergeable = indexMergeable;
|
||||
this.hasOperandAliasConfig = hasOperandAliasConfig;
|
||||
@@ -374,7 +367,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
userFactory,
|
||||
Providers.of(otherUser),
|
||||
permissionBackend,
|
||||
notesFactory,
|
||||
changeDataFactory,
|
||||
commentsUtil,
|
||||
accountResolver,
|
||||
@@ -392,10 +384,10 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
starredChangesUtil,
|
||||
accountCache,
|
||||
groupMembers,
|
||||
anonymousUserProvider,
|
||||
operatorAliasConfig,
|
||||
indexMergeable,
|
||||
hasOperandAliasConfig);
|
||||
hasOperandAliasConfig,
|
||||
changeIsVisbleToPredicateFactory);
|
||||
}
|
||||
|
||||
Arguments asUser(Account.Id otherId) {
|
||||
@@ -1018,12 +1010,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
||||
}
|
||||
|
||||
public Predicate<ChangeData> visibleto(CurrentUser user) {
|
||||
return new ChangeIsVisibleToPredicate(
|
||||
args.notesFactory,
|
||||
user,
|
||||
args.permissionBackend,
|
||||
args.projectCache,
|
||||
args.anonymousUserProvider);
|
||||
return args.changeIsVisbleToPredicateFactory.forUser(user);
|
||||
}
|
||||
|
||||
public Predicate<ChangeData> isVisible() throws QueryParseException {
|
||||
|
@@ -28,7 +28,6 @@ import com.google.gerrit.index.query.IndexPredicate;
|
||||
import com.google.gerrit.index.query.Predicate;
|
||||
import com.google.gerrit.index.query.QueryProcessor;
|
||||
import com.google.gerrit.metrics.MetricMaker;
|
||||
import com.google.gerrit.server.AnonymousUser;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.DynamicOptions;
|
||||
import com.google.gerrit.server.DynamicOptions.DynamicBean;
|
||||
@@ -40,9 +39,6 @@ import com.google.gerrit.server.index.change.ChangeIndexCollection;
|
||||
import com.google.gerrit.server.index.change.ChangeIndexRewriter;
|
||||
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
|
||||
import com.google.gerrit.server.index.change.IndexedChangeQuery;
|
||||
import com.google.gerrit.server.notedb.ChangeNotes;
|
||||
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||
import com.google.gerrit.server.project.ProjectCache;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.util.HashMap;
|
||||
@@ -58,11 +54,8 @@ import java.util.Set;
|
||||
public class ChangeQueryProcessor extends QueryProcessor<ChangeData>
|
||||
implements DynamicOptions.BeanReceiver, DynamicOptions.BeanProvider {
|
||||
private final Provider<CurrentUser> userProvider;
|
||||
private final ChangeNotes.Factory notesFactory;
|
||||
private final ImmutableListMultimap<String, ChangeAttributeFactory> attributeFactoriesByPlugin;
|
||||
private final PermissionBackend permissionBackend;
|
||||
private final ProjectCache projectCache;
|
||||
private final Provider<AnonymousUser> anonymousUserProvider;
|
||||
private final ChangeIsVisibleToPredicate.Factory changeIsVisibleToPredicateFactory;
|
||||
private final Map<String, DynamicBean> dynamicBeans = new HashMap<>();
|
||||
|
||||
static {
|
||||
@@ -80,11 +73,8 @@ public class ChangeQueryProcessor extends QueryProcessor<ChangeData>
|
||||
IndexConfig indexConfig,
|
||||
ChangeIndexCollection indexes,
|
||||
ChangeIndexRewriter rewriter,
|
||||
ChangeNotes.Factory notesFactory,
|
||||
DynamicSet<ChangeAttributeFactory> attributeFactories,
|
||||
PermissionBackend permissionBackend,
|
||||
ProjectCache projectCache,
|
||||
Provider<AnonymousUser> anonymousUserProvider) {
|
||||
ChangeIsVisibleToPredicate.Factory changeIsVisibleToPredicateFactory) {
|
||||
super(
|
||||
metricMaker,
|
||||
ChangeSchemaDefinitions.INSTANCE,
|
||||
@@ -94,10 +84,7 @@ public class ChangeQueryProcessor extends QueryProcessor<ChangeData>
|
||||
FIELD_LIMIT,
|
||||
() -> limitsFactory.create(userProvider.get()).getQueryLimit());
|
||||
this.userProvider = userProvider;
|
||||
this.notesFactory = notesFactory;
|
||||
this.permissionBackend = permissionBackend;
|
||||
this.projectCache = projectCache;
|
||||
this.anonymousUserProvider = anonymousUserProvider;
|
||||
this.changeIsVisibleToPredicateFactory = changeIsVisibleToPredicateFactory;
|
||||
|
||||
ImmutableListMultimap.Builder<String, ChangeAttributeFactory> factoriesBuilder =
|
||||
ImmutableListMultimap.builder();
|
||||
@@ -144,14 +131,7 @@ public class ChangeQueryProcessor extends QueryProcessor<ChangeData>
|
||||
@Override
|
||||
protected Predicate<ChangeData> enforceVisibility(Predicate<ChangeData> pred) {
|
||||
return new AndChangeSource(
|
||||
pred,
|
||||
new ChangeIsVisibleToPredicate(
|
||||
notesFactory,
|
||||
userProvider.get(),
|
||||
permissionBackend,
|
||||
projectCache,
|
||||
anonymousUserProvider),
|
||||
start);
|
||||
pred, changeIsVisibleToPredicateFactory.forUser(userProvider.get()), start);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -91,6 +91,7 @@ import com.google.gerrit.server.PublishCommentUtil;
|
||||
import com.google.gerrit.server.ReviewerSet;
|
||||
import com.google.gerrit.server.account.AccountResolver;
|
||||
import com.google.gerrit.server.change.AddReviewersEmail;
|
||||
import com.google.gerrit.server.change.AddReviewersOp.Result;
|
||||
import com.google.gerrit.server.change.ChangeResource;
|
||||
import com.google.gerrit.server.change.EmailReviewComments;
|
||||
import com.google.gerrit.server.change.NotifyResolver;
|
||||
@@ -426,10 +427,15 @@ public class PostReview implements RestModifyView<RevisionResource, ReviewInput>
|
||||
List<Address> toByEmail = new ArrayList<>();
|
||||
List<Address> ccByEmail = new ArrayList<>();
|
||||
for (ReviewerAddition addition : reviewerAdditions) {
|
||||
if (addition.state() == ReviewerState.REVIEWER) {
|
||||
Result reviewAdditionResult = addition.op.getResult();
|
||||
if (addition.state() == ReviewerState.REVIEWER
|
||||
&& (!reviewAdditionResult.addedReviewers().isEmpty()
|
||||
|| !reviewAdditionResult.addedReviewersByEmail().isEmpty())) {
|
||||
to.addAll(addition.reviewers);
|
||||
toByEmail.addAll(addition.reviewersByEmail);
|
||||
} else if (addition.state() == ReviewerState.CC) {
|
||||
} else if (addition.state() == ReviewerState.CC
|
||||
&& (!reviewAdditionResult.addedCCs().isEmpty()
|
||||
|| !reviewAdditionResult.addedCCsByEmail().isEmpty())) {
|
||||
cc.addAll(addition.reviewers);
|
||||
ccByEmail.addAll(addition.reviewersByEmail);
|
||||
}
|
||||
|
@@ -108,8 +108,11 @@ public class CreateTag implements RestCollectionCreateView<ProjectResource, TagR
|
||||
boolean isSigned = isAnnotated && input.message.contains("-----BEGIN PGP SIGNATURE-----\n");
|
||||
if (isSigned) {
|
||||
throw new MethodNotAllowedException("Cannot create signed tag \"" + ref + "\"");
|
||||
} else if (isAnnotated && !check(perm, RefPermission.CREATE_TAG)) {
|
||||
} else if (isAnnotated) {
|
||||
if (!check(perm, RefPermission.CREATE_TAG)) {
|
||||
throw new AuthException("Cannot create annotated tag \"" + ref + "\"");
|
||||
}
|
||||
|
||||
} else {
|
||||
perm.check(RefPermission.CREATE);
|
||||
}
|
||||
|
@@ -89,20 +89,20 @@ public class LocalMergeSuperSetComputation implements MergeSuperSetComputation {
|
||||
private final Map<QueryKey, ImmutableList<ChangeData>> queryCache;
|
||||
private final Map<BranchNameKey, Optional<RevCommit>> heads;
|
||||
private final ProjectCache projectCache;
|
||||
private final ChangeIsVisibleToPredicate changeIsVisibleToPredicate;
|
||||
private final ChangeIsVisibleToPredicate.Factory changeIsVisibleToPredicateFactory;
|
||||
|
||||
@Inject
|
||||
LocalMergeSuperSetComputation(
|
||||
PermissionBackend permissionBackend,
|
||||
Provider<InternalChangeQuery> queryProvider,
|
||||
ProjectCache projectCache,
|
||||
ChangeIsVisibleToPredicate changeIsVisibleToPredicate) {
|
||||
ChangeIsVisibleToPredicate.Factory changeIsVisibleToPredicateFactory) {
|
||||
this.projectCache = projectCache;
|
||||
this.permissionBackend = permissionBackend;
|
||||
this.queryProvider = queryProvider;
|
||||
this.queryCache = new HashMap<>();
|
||||
this.heads = new HashMap<>();
|
||||
this.changeIsVisibleToPredicate = changeIsVisibleToPredicate;
|
||||
this.changeIsVisibleToPredicateFactory = changeIsVisibleToPredicateFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,7 +150,8 @@ public class LocalMergeSuperSetComputation implements MergeSuperSetComputation {
|
||||
walkChangesByHashes(visibleCommits, Collections.emptySet(), or, b);
|
||||
Set<String> nonVisibleHashes = walkChangesByHashes(nonVisibleCommits, visibleHashes, or, b);
|
||||
|
||||
ChangeSet partialSet = byCommitsOnBranchNotMerged(or, b, visibleHashes, nonVisibleHashes);
|
||||
ChangeSet partialSet =
|
||||
byCommitsOnBranchNotMerged(or, b, visibleHashes, nonVisibleHashes, user);
|
||||
Iterables.addAll(visibleChanges, partialSet.changes());
|
||||
Iterables.addAll(nonVisibleChanges, partialSet.nonVisibleChanges());
|
||||
}
|
||||
@@ -207,13 +208,19 @@ public class LocalMergeSuperSetComputation implements MergeSuperSetComputation {
|
||||
}
|
||||
|
||||
private ChangeSet byCommitsOnBranchNotMerged(
|
||||
OpenRepo or, BranchNameKey branch, Set<String> visibleHashes, Set<String> nonVisibleHashes)
|
||||
OpenRepo or,
|
||||
BranchNameKey branch,
|
||||
Set<String> visibleHashes,
|
||||
Set<String> nonVisibleHashes,
|
||||
CurrentUser user)
|
||||
throws IOException {
|
||||
List<ChangeData> potentiallyVisibleChanges =
|
||||
byCommitsOnBranchNotMerged(or, branch, visibleHashes);
|
||||
List<ChangeData> invisibleChanges =
|
||||
new ArrayList<>(byCommitsOnBranchNotMerged(or, branch, nonVisibleHashes));
|
||||
List<ChangeData> visibleChanges = new ArrayList<>(potentiallyVisibleChanges.size());
|
||||
ChangeIsVisibleToPredicate changeIsVisibleToPredicate =
|
||||
changeIsVisibleToPredicateFactory.forUser(user);
|
||||
for (ChangeData cd : potentiallyVisibleChanges) {
|
||||
if (changeIsVisibleToPredicate.match(cd)) {
|
||||
visibleChanges.add(cd);
|
||||
|
@@ -90,6 +90,7 @@ import com.google.gerrit.extensions.api.accounts.DeletedDraftCommentInfo;
|
||||
import com.google.gerrit.extensions.api.accounts.EmailInput;
|
||||
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
|
||||
import com.google.gerrit.extensions.api.changes.DraftInput;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.api.changes.StarsInput;
|
||||
import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo;
|
||||
import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo.ConsistencyProblemInfo;
|
||||
@@ -883,6 +884,99 @@ public class AccountIT extends AbstractDaemonTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addExistingReviewersUsingPostReview() throws Exception {
|
||||
PushOneCommit.Result r = createChange();
|
||||
|
||||
// First reviewer added to the change
|
||||
ReviewInput input = new ReviewInput();
|
||||
input.reviewers = new ArrayList<>(1);
|
||||
AddReviewerInput addReviewerInput = new AddReviewerInput();
|
||||
addReviewerInput.reviewer = user.email();
|
||||
input.reviewers.add(addReviewerInput);
|
||||
gApi.changes().id(r.getChangeId()).current().review(input);
|
||||
List<Message> messages = sender.getMessages();
|
||||
assertThat(messages).hasSize(1);
|
||||
Message message = messages.get(0);
|
||||
assertThat(message.rcpt()).containsExactly(user.getNameEmail());
|
||||
assertMailReplyTo(message, admin.email());
|
||||
|
||||
sender.clear();
|
||||
|
||||
// Second reviewer and existing reviewer added to the change
|
||||
ReviewInput input2 = new ReviewInput();
|
||||
input2.reviewers = new ArrayList<>(2);
|
||||
AddReviewerInput addReviewerInput2 = new AddReviewerInput();
|
||||
addReviewerInput2.reviewer = user.email();
|
||||
input2.reviewers.add(addReviewerInput2);
|
||||
AddReviewerInput addReviewerInput3 = new AddReviewerInput();
|
||||
|
||||
TestAccount user2 = accountCreator.user2();
|
||||
addReviewerInput3.reviewer = user2.email();
|
||||
input2.reviewers.add(addReviewerInput3);
|
||||
|
||||
gApi.changes().id(r.getChangeId()).current().review(input2);
|
||||
List<Message> messages2 = sender.getMessages();
|
||||
assertThat(messages2).hasSize(1);
|
||||
Message message2 = messages2.get(0);
|
||||
assertThat(message2.rcpt()).containsExactly(user.getNameEmail(), user2.getNameEmail());
|
||||
assertMailReplyTo(message, admin.email());
|
||||
|
||||
sender.clear();
|
||||
|
||||
// Existing reviewers re-added to the change: no notifications
|
||||
ReviewInput input3 = new ReviewInput();
|
||||
input3.reviewers = new ArrayList<>(2);
|
||||
AddReviewerInput addReviewerInput4 = new AddReviewerInput();
|
||||
addReviewerInput4.reviewer = user.email();
|
||||
input3.reviewers.add(addReviewerInput4);
|
||||
AddReviewerInput addReviewerInput5 = new AddReviewerInput();
|
||||
|
||||
addReviewerInput5.reviewer = user2.email();
|
||||
input3.reviewers.add(addReviewerInput5);
|
||||
|
||||
gApi.changes().id(r.getChangeId()).current().review(input3);
|
||||
List<Message> messages3 = sender.getMessages();
|
||||
assertThat(messages3).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addExistingReviewersUsingAddReviewer() throws Exception {
|
||||
PushOneCommit.Result r = createChange();
|
||||
|
||||
// First reviewer added to the change
|
||||
AddReviewerInput addReviewerInput = new AddReviewerInput();
|
||||
addReviewerInput.reviewer = user.email();
|
||||
gApi.changes().id(r.getChangeId()).addReviewer(addReviewerInput);
|
||||
List<Message> messages = sender.getMessages();
|
||||
assertThat(messages).hasSize(1);
|
||||
Message message = messages.get(0);
|
||||
assertThat(message.rcpt()).containsExactly(user.getNameEmail());
|
||||
assertMailReplyTo(message, admin.email());
|
||||
|
||||
sender.clear();
|
||||
|
||||
// Second reviewer added to the change
|
||||
TestAccount user2 = accountCreator.user2();
|
||||
AddReviewerInput addReviewerInput2 = new AddReviewerInput();
|
||||
addReviewerInput2.reviewer = user2.email();
|
||||
gApi.changes().id(r.getChangeId()).addReviewer(addReviewerInput2);
|
||||
List<Message> messages2 = sender.getMessages();
|
||||
assertThat(messages2).hasSize(1);
|
||||
Message message2 = messages2.get(0);
|
||||
assertThat(message2.rcpt()).containsExactly(user.getNameEmail(), user2.getNameEmail());
|
||||
assertMailReplyTo(message2, admin.email());
|
||||
|
||||
sender.clear();
|
||||
|
||||
// Exiting reviewer re-added to the change: no notifications
|
||||
AddReviewerInput addReviewerInput3 = new AddReviewerInput();
|
||||
addReviewerInput3.reviewer = user2.email();
|
||||
gApi.changes().id(r.getChangeId()).addReviewer(addReviewerInput3);
|
||||
List<Message> messages3 = sender.getMessages();
|
||||
assertThat(messages3).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void suggestAccounts() throws Exception {
|
||||
AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
|
||||
|
@@ -22,7 +22,6 @@ import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import com.google.gerrit.acceptance.PushOneCommit;
|
||||
import com.google.gerrit.acceptance.TestAccount;
|
||||
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
|
||||
@@ -53,13 +52,18 @@ import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.transport.RefSpec;
|
||||
import org.eclipse.jgit.transport.RemoteRefUpdate;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@NoHttpd
|
||||
public class SubmitOnPushIT extends AbstractDaemonTest {
|
||||
public abstract class AbstractSubmitOnPush extends AbstractDaemonTest {
|
||||
@Inject private ApprovalsUtil approvalsUtil;
|
||||
@Inject private ProjectOperations projectOperations;
|
||||
|
||||
@Before
|
||||
public void blockAnonymous() throws Exception {
|
||||
blockAnonymousRead();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitOnPush() throws Exception {
|
||||
projectOperations
|
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2020 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.acceptance.git;
|
||||
|
||||
import com.google.gerrit.acceptance.GitUtil;
|
||||
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.junit.Before;
|
||||
|
||||
public class HttpSubmitOnPushIT extends AbstractSubmitOnPush {
|
||||
|
||||
@Before
|
||||
public void cloneProjectOverHttp() throws Exception {
|
||||
CredentialsProvider.setDefault(
|
||||
new UsernamePasswordCredentialsProvider(admin.username(), admin.httpPassword()));
|
||||
testRepo = GitUtil.cloneProject(project, admin.getHttpUrl(server) + "/a/" + project.get());
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
// Copyright (C) 2020 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.acceptance.git;
|
||||
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import org.junit.Before;
|
||||
|
||||
@NoHttpd
|
||||
public class SshSubmitOnPushIT extends AbstractSubmitOnPush {
|
||||
|
||||
@Before
|
||||
public void cloneProjectOverSsh() throws Exception {
|
||||
testRepo = cloneProject(project, admin);
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2020 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.acceptance.rest.project;
|
||||
|
||||
import com.google.gerrit.acceptance.GitUtil;
|
||||
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.junit.Before;
|
||||
|
||||
public abstract class AbstractHttpPushTag extends AbstractPushTag {
|
||||
|
||||
@Before
|
||||
public void cloneProjectOverHttp() throws Exception {
|
||||
// clone with user to avoid inherited tag permissions of admin user
|
||||
CredentialsProvider.setDefault(
|
||||
new UsernamePasswordCredentialsProvider(user.username(), user.httpPassword()));
|
||||
testRepo = GitUtil.cloneProject(project, user.getHttpUrl(server) + "/" + project.get());
|
||||
}
|
||||
}
|
@@ -28,7 +28,6 @@ import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.GitUtil;
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
|
||||
import com.google.gerrit.common.data.Permission;
|
||||
import com.google.gerrit.entities.RefNames;
|
||||
@@ -41,7 +40,6 @@ import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@NoHttpd
|
||||
public abstract class AbstractPushTag extends AbstractDaemonTest {
|
||||
enum TagType {
|
||||
LIGHTWEIGHT(Permission.CREATE),
|
||||
@@ -61,11 +59,9 @@ public abstract class AbstractPushTag extends AbstractDaemonTest {
|
||||
|
||||
@Before
|
||||
public void setUpTestEnvironment() throws Exception {
|
||||
// clone with user to avoid inherited tag permissions of admin user
|
||||
testRepo = cloneProject(project, user);
|
||||
|
||||
initialHead = projectOperations.project(project).getHead("master");
|
||||
tagType = getTagType();
|
||||
blockAnonymousRead();
|
||||
}
|
||||
|
||||
protected abstract TagType getTagType();
|
||||
|
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2020 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.acceptance.rest.project;
|
||||
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import com.google.gerrit.acceptance.UseSsh;
|
||||
import org.junit.Before;
|
||||
|
||||
@NoHttpd
|
||||
@UseSsh
|
||||
public abstract class AbstractSshPushTag extends AbstractPushTag {
|
||||
@Before
|
||||
public void cloneProjectOverSsh() throws Exception {
|
||||
// clone with user to avoid inherited tag permissions of admin user
|
||||
testRepo = cloneProject(project, user);
|
||||
}
|
||||
}
|
@@ -57,7 +57,9 @@ java_library(
|
||||
name = "push_tag_util",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"AbstractHttpPushTag.java",
|
||||
"AbstractPushTag.java",
|
||||
"AbstractSshPushTag.java",
|
||||
],
|
||||
deps = [
|
||||
"//java/com/google/gerrit/acceptance:lib",
|
||||
|
@@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2020 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.acceptance.rest.project;
|
||||
|
||||
public class HttpPushAnnotatedTagIT extends AbstractHttpPushTag {
|
||||
|
||||
@Override
|
||||
protected TagType getTagType() {
|
||||
return TagType.ANNOTATED;
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2017 The Android Open Source Project
|
||||
// Copyright (C) 2020 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package com.google.gerrit.acceptance.rest.project;
|
||||
|
||||
public class PushLightweightTagIT extends AbstractPushTag {
|
||||
public class HttpPushLightweightTagIT extends AbstractHttpPushTag {
|
||||
|
||||
@Override
|
||||
protected TagType getTagType() {
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2017 The Android Open Source Project
|
||||
// Copyright (C) 2020 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package com.google.gerrit.acceptance.rest.project;
|
||||
|
||||
public class PushAnnotatedTagIT extends AbstractPushTag {
|
||||
public class SshPushAnnotatedTagIT extends AbstractSshPushTag {
|
||||
|
||||
@Override
|
||||
protected TagType getTagType() {
|
@@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2020 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.acceptance.rest.project;
|
||||
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import com.google.gerrit.acceptance.UseSsh;
|
||||
|
||||
@NoHttpd
|
||||
@UseSsh
|
||||
public class SshPushLightweightTagIT extends AbstractSshPushTag {
|
||||
|
||||
@Override
|
||||
protected TagType getTagType() {
|
||||
return TagType.LIGHTWEIGHT;
|
||||
}
|
||||
}
|
@@ -38,10 +38,13 @@ import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.server.project.ProjectConfig;
|
||||
import com.google.inject.Inject;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@NoHttpd
|
||||
@@ -66,6 +69,16 @@ public class TagsIT extends AbstractDaemonTest {
|
||||
@Inject private ProjectOperations projectOperations;
|
||||
@Inject private RequestScopeOperations requestScopeOperations;
|
||||
|
||||
@Before
|
||||
public void setupPermissions() throws Exception {
|
||||
try (ProjectConfigUpdate u = updateProject(allProjects)) {
|
||||
ProjectConfig cfg = u.getConfig();
|
||||
removeAllBranchPermissions(
|
||||
cfg, Permission.CREATE, Permission.CREATE_TAG, Permission.CREATE_SIGNED_TAG);
|
||||
u.save();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listTagsOfNonExistingProject() throws Exception {
|
||||
assertThrows(
|
||||
@@ -455,4 +468,10 @@ public class TagsIT extends AbstractDaemonTest {
|
||||
.add(allow(Permission.CREATE_SIGNED_TAG).ref(R_TAGS + "*").group(adminGroupUuid()))
|
||||
.update();
|
||||
}
|
||||
|
||||
private static void removeAllBranchPermissions(ProjectConfig cfg, String... permissions) {
|
||||
cfg.getAccessSections().stream()
|
||||
.filter(s -> s.getName().startsWith("refs/tags/"))
|
||||
.forEach(s -> Arrays.stream(permissions).forEach(s::removePermission));
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,7 @@
|
||||
load("//javatests/com/google/gerrit/acceptance:tests.bzl", "acceptance_tests")
|
||||
|
||||
acceptance_tests(
|
||||
srcs = glob(["*IT.java"]),
|
||||
group = "server_httpd",
|
||||
labels = ["server"],
|
||||
)
|
@@ -0,0 +1,112 @@
|
||||
// Copyright (C) 2020 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.acceptance.server.httpd;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.gerrit.acceptance.StandaloneSiteTest;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.testing.ConfigSuite;
|
||||
import com.google.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HttpLogoutServletIT extends StandaloneSiteTest {
|
||||
private static final String LOCALHOST = InetAddress.getLoopbackAddress().getHostName();
|
||||
|
||||
@ConfigSuite.Config
|
||||
public static Config secondConfig() throws IOException {
|
||||
Config cfg = new Config();
|
||||
cfg.setString("auth", null, "logouturl", "/test-logout");
|
||||
cfg.setString("gerrit", null, "canonicalWebUrl", "https://" + LOCALHOST + ":8443/");
|
||||
cfg.setString("httpd", null, "listenUrl", "proxy-https://" + LOCALHOST + ":" + getFreePort());
|
||||
return cfg;
|
||||
}
|
||||
|
||||
@Inject @GerritServerConfig private Config gerritConfig;
|
||||
|
||||
private HttpClient httpClient;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
httpClient = HttpClientBuilder.create().disableRedirectHandling().build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHonourCanonicalWebUrlProxyWhenRedirectAfterLogout() throws Exception {
|
||||
try (ServerContext ctx = startServer()) {
|
||||
ctx.getInjector().injectMembers(this);
|
||||
|
||||
URIish listenUrl = new URIish(gerritConfig.getString("httpd", null, "listenUrl"));
|
||||
URIish canonicalWebUrl =
|
||||
new URIish(gerritConfig.getString("gerrit", null, "canonicalWebUrl"));
|
||||
|
||||
String logoutPath =
|
||||
Optional.ofNullable(baseConfig.getString("auth", null, "logouturl")).orElse("/");
|
||||
|
||||
HttpGet getLogout = new HttpGet("/logout");
|
||||
getLogout.addHeader("X-Forwarded-Host", canonicalWebUrl.getHost());
|
||||
getLogout.addHeader("X-Forwarded-Port", "" + canonicalWebUrl.getPort());
|
||||
getLogout.addHeader("X-Forwarded-Proto", canonicalWebUrl.getScheme());
|
||||
|
||||
HttpResponse logoutResponse =
|
||||
httpClient.execute(new HttpHost(listenUrl.getHost(), listenUrl.getPort()), getLogout);
|
||||
|
||||
assertThat(logoutResponse.getStatusLine().getStatusCode())
|
||||
.isEqualTo(HttpStatus.SC_MOVED_TEMPORARILY);
|
||||
assertThat(getLocationHeaderURIish(logoutResponse))
|
||||
.containsExactly(canonicalWebUrl.setPath(logoutPath));
|
||||
}
|
||||
}
|
||||
|
||||
private List<URIish> getLocationHeaderURIish(HttpResponse logoutResponse) {
|
||||
return Arrays.stream(logoutResponse.getHeaders("Location"))
|
||||
.map(h -> h.getValue())
|
||||
.map(HttpLogoutServletIT::unsafeNewURIish)
|
||||
.filter(u -> u.isPresent())
|
||||
.map(u -> u.get())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Optional<URIish> unsafeNewURIish(String uri) {
|
||||
try {
|
||||
return Optional.of(new URIish(uri));
|
||||
} catch (URISyntaxException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static int getFreePort() throws IOException {
|
||||
try (ServerSocket s = new ServerSocket(0)) {
|
||||
return s.getLocalPort();
|
||||
}
|
||||
}
|
||||
}
|
@@ -38,12 +38,6 @@ public class ElasticContainer extends ElasticsearchContainer {
|
||||
|
||||
private static String getImageName(ElasticVersion version) {
|
||||
switch (version) {
|
||||
case V6_2:
|
||||
return "blacktop/elasticsearch:6.2.4";
|
||||
case V6_3:
|
||||
return "blacktop/elasticsearch:6.3.2";
|
||||
case V6_4:
|
||||
return "blacktop/elasticsearch:6.4.3";
|
||||
case V6_5:
|
||||
return "blacktop/elasticsearch:6.5.4";
|
||||
case V6_6:
|
||||
|
@@ -22,15 +22,6 @@ import org.junit.Test;
|
||||
public class ElasticVersionTest {
|
||||
@Test
|
||||
public void supportedVersion() throws Exception {
|
||||
assertThat(ElasticVersion.forVersion("6.2.0")).isEqualTo(ElasticVersion.V6_2);
|
||||
assertThat(ElasticVersion.forVersion("6.2.4")).isEqualTo(ElasticVersion.V6_2);
|
||||
|
||||
assertThat(ElasticVersion.forVersion("6.3.0")).isEqualTo(ElasticVersion.V6_3);
|
||||
assertThat(ElasticVersion.forVersion("6.3.2")).isEqualTo(ElasticVersion.V6_3);
|
||||
|
||||
assertThat(ElasticVersion.forVersion("6.4.0")).isEqualTo(ElasticVersion.V6_4);
|
||||
assertThat(ElasticVersion.forVersion("6.4.1")).isEqualTo(ElasticVersion.V6_4);
|
||||
|
||||
assertThat(ElasticVersion.forVersion("6.5.0")).isEqualTo(ElasticVersion.V6_5);
|
||||
assertThat(ElasticVersion.forVersion("6.5.1")).isEqualTo(ElasticVersion.V6_5);
|
||||
|
||||
@@ -79,9 +70,6 @@ public class ElasticVersionTest {
|
||||
|
||||
@Test
|
||||
public void atLeastMinorVersion() throws Exception {
|
||||
assertThat(ElasticVersion.V6_2.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V6_3.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V6_4.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V6_5.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V6_6.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V6_7.isAtLeastMinorVersion(ElasticVersion.V6_7)).isTrue();
|
||||
@@ -97,9 +85,6 @@ public class ElasticVersionTest {
|
||||
|
||||
@Test
|
||||
public void version6OrLater() throws Exception {
|
||||
assertThat(ElasticVersion.V6_2.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V6_3.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V6_4.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V6_5.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V6_6.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V6_7.isV6OrLater()).isTrue();
|
||||
@@ -115,9 +100,6 @@ public class ElasticVersionTest {
|
||||
|
||||
@Test
|
||||
public void version7OrLater() throws Exception {
|
||||
assertThat(ElasticVersion.V6_2.isV7OrLater()).isFalse();
|
||||
assertThat(ElasticVersion.V6_3.isV7OrLater()).isFalse();
|
||||
assertThat(ElasticVersion.V6_4.isV7OrLater()).isFalse();
|
||||
assertThat(ElasticVersion.V6_5.isV7OrLater()).isFalse();
|
||||
assertThat(ElasticVersion.V6_6.isV7OrLater()).isFalse();
|
||||
assertThat(ElasticVersion.V6_7.isV7OrLater()).isFalse();
|
||||
|
@@ -44,7 +44,6 @@ public class FakeQueryBuilder extends ChangeQueryBuilder {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
indexes,
|
||||
null,
|
||||
null,
|
||||
@@ -53,8 +52,8 @@ public class FakeQueryBuilder extends ChangeQueryBuilder {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new Config(),
|
||||
null,
|
||||
null));
|
||||
}
|
||||
|
||||
|
@@ -1 +0,0 @@
|
||||
This software has been placed in the public domain by its author(s).
|
@@ -1,4 +1,9 @@
|
||||
load("@rules_java//java:defs.bzl", "java_library")
|
||||
load("@rules_java//java:defs.bzl", "java_import", "java_library")
|
||||
|
||||
java_import(
|
||||
name = "guice-library-no-aop",
|
||||
jars = ["@guice-library-no-aop//file"],
|
||||
)
|
||||
|
||||
java_library(
|
||||
name = "guice",
|
||||
@@ -14,8 +19,7 @@ java_library(
|
||||
name = "guice-library",
|
||||
data = ["//lib:LICENSE-Apache2.0"],
|
||||
visibility = ["//visibility:public"],
|
||||
exports = ["@guice-library//jar"],
|
||||
runtime_deps = ["aopalliance"],
|
||||
exports = [":guice-library-no-aop"],
|
||||
)
|
||||
|
||||
java_library(
|
||||
@@ -34,12 +38,6 @@ java_library(
|
||||
runtime_deps = [":guice"],
|
||||
)
|
||||
|
||||
java_library(
|
||||
name = "aopalliance",
|
||||
data = ["//lib:LICENSE-PublicDomain"],
|
||||
exports = ["@aopalliance//jar"],
|
||||
)
|
||||
|
||||
java_library(
|
||||
name = "javax_inject",
|
||||
data = ["//lib:LICENSE-Apache2.0"],
|
||||
|
@@ -111,7 +111,7 @@ EOF
|
||||
}
|
||||
|
||||
# Change-Id goes after existing trailers.
|
||||
function test_at_start {
|
||||
function test_at_end {
|
||||
cat << EOF > input
|
||||
bla bla
|
||||
|
||||
@@ -119,16 +119,16 @@ Bug: #123
|
||||
EOF
|
||||
|
||||
${hook} input || fail "failed hook execution"
|
||||
result=$(git interpret-trailers --parse input | head -1 | grep ^Change-Id)
|
||||
result=$(tail -1 input | grep ^Change-Id)
|
||||
if [[ -z "${result}" ]] ; then
|
||||
echo "after: "
|
||||
cat input
|
||||
|
||||
fail "did not find Change-Id at start"
|
||||
fail "did not find Change-Id at end"
|
||||
fi
|
||||
}
|
||||
|
||||
function test_dash_at_start {
|
||||
function test_dash_at_end {
|
||||
if [[ ! -x /bin/dash ]] ; then
|
||||
echo "/bin/dash not installed; skipping dash test."
|
||||
return
|
||||
@@ -142,12 +142,12 @@ EOF
|
||||
|
||||
/bin/dash ${hook} input || fail "failed hook execution"
|
||||
|
||||
result=$(git interpret-trailers --parse input | head -1 | grep ^Change-Id)
|
||||
result=$(tail -1 input | grep ^Change-Id)
|
||||
if [[ -z "${result}" ]] ; then
|
||||
echo "after: "
|
||||
cat input
|
||||
|
||||
fail "did not find Change-Id at start"
|
||||
fail "did not find Change-Id at end"
|
||||
fi
|
||||
}
|
||||
|
||||
|
@@ -5,4 +5,6 @@
|
||||
|
||||
755 hooks/commit-msg
|
||||
|
||||
755 hooks/commit-msg-legacy
|
||||
|
||||
755 scripts/reposize.sh
|
||||
|
@@ -50,7 +50,7 @@ fi
|
||||
|
||||
# Avoid the --in-place option which only appeared in Git 2.8
|
||||
# Avoid the --if-exists option which only appeared in Git 2.15
|
||||
if ! git -c trailer.ifexists=doNothing interpret-trailers --where start \
|
||||
if ! git -c trailer.ifexists=doNothing interpret-trailers \
|
||||
--trailer "Change-Id: I${random}" < "$1" > "${dest}" ; then
|
||||
echo "cannot insert change-id line in $1"
|
||||
exit 1
|
||||
|
193
resources/com/google/gerrit/server/tools/root/hooks/commit-msg-legacy
Executable file
193
resources/com/google/gerrit/server/tools/root/hooks/commit-msg-legacy
Executable file
@@ -0,0 +1,193 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Part of Gerrit Code Review (https://www.gerritcodereview.com/)
|
||||
#
|
||||
# Copyright (C) 2009 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.
|
||||
#
|
||||
|
||||
unset GREP_OPTIONS
|
||||
|
||||
CHANGE_ID_AFTER="Bug|Depends-On|Issue|Test|Feature|Fixes|Fixed"
|
||||
MSG="$1"
|
||||
|
||||
# Check for, and add if missing, a unique Change-Id
|
||||
#
|
||||
add_ChangeId() {
|
||||
clean_message=`sed -e '
|
||||
/^diff --git .*/{
|
||||
s///
|
||||
q
|
||||
}
|
||||
/^Signed-off-by:/d
|
||||
/^#/d
|
||||
' "$MSG" | git stripspace`
|
||||
if test -z "$clean_message"
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
# Do not add Change-Id to temp commits
|
||||
if echo "$clean_message" | head -1 | grep -q '^\(fixup\|squash\)!'
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
if test "false" = "`git config --bool --get gerrit.createChangeId`"
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
# Does Change-Id: already exist? if so, exit (no change).
|
||||
if grep -i '^Change-Id:' "$MSG" >/dev/null
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
id=`_gen_ChangeId`
|
||||
T="$MSG.tmp.$$"
|
||||
AWK=awk
|
||||
if [ -x /usr/xpg4/bin/awk ]; then
|
||||
# Solaris AWK is just too broken
|
||||
AWK=/usr/xpg4/bin/awk
|
||||
fi
|
||||
|
||||
# Get core.commentChar from git config or use default symbol
|
||||
commentChar=`git config --get core.commentChar`
|
||||
commentChar=${commentChar:-#}
|
||||
|
||||
# How this works:
|
||||
# - parse the commit message as (textLine+ blankLine*)*
|
||||
# - assume textLine+ to be a footer until proven otherwise
|
||||
# - exception: the first block is not footer (as it is the title)
|
||||
# - read textLine+ into a variable
|
||||
# - then count blankLines
|
||||
# - once the next textLine appears, print textLine+ blankLine* as these
|
||||
# aren't footer
|
||||
# - 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
|
||||
footerComment = 0
|
||||
blankLines = 0
|
||||
}
|
||||
|
||||
# Skip lines starting with commentChar without any spaces before it.
|
||||
/^'"$commentChar"'/ { next }
|
||||
|
||||
# Skip the line starting with the diff command and everything after it,
|
||||
# up to the end of the file, assuming it is only patch data.
|
||||
# If more than one line before the diff was empty, strip all but one.
|
||||
/^diff --git / {
|
||||
blankLines = 0
|
||||
while (getline) { }
|
||||
next
|
||||
}
|
||||
|
||||
# Count blank lines outside footer comments
|
||||
/^$/ && (footerComment == 0) {
|
||||
blankLines++
|
||||
next
|
||||
}
|
||||
|
||||
# Catch footer comment
|
||||
/^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) {
|
||||
footerComment = 1
|
||||
}
|
||||
|
||||
/]$/ && (footerComment == 1) {
|
||||
footerComment = 2
|
||||
}
|
||||
|
||||
# We have a non-blank line after blank lines. Handle this.
|
||||
(blankLines > 0) {
|
||||
print lines
|
||||
for (i = 0; i < blankLines; i++) {
|
||||
print ""
|
||||
}
|
||||
|
||||
lines = ""
|
||||
blankLines = 0
|
||||
isFooter = 1
|
||||
footerComment = 0
|
||||
}
|
||||
|
||||
# Detect that the current block is not the footer
|
||||
(footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) {
|
||||
isFooter = 0
|
||||
}
|
||||
|
||||
{
|
||||
# We need this information about the current last comment line
|
||||
if (footerComment == 2) {
|
||||
footerComment = 0
|
||||
}
|
||||
if (lines != "") {
|
||||
lines = lines "\n";
|
||||
}
|
||||
lines = lines $0
|
||||
}
|
||||
|
||||
# Footer handling:
|
||||
# If the last block is considered a footer, splice in the Change-Id at the
|
||||
# right place.
|
||||
# Look for the right place to inject Change-Id by considering
|
||||
# CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first,
|
||||
# then Change-Id, then everything else (eg. Signed-off-by:).
|
||||
#
|
||||
# Otherwise just print the last block, a new line and the Change-Id as a
|
||||
# block of its own.
|
||||
END {
|
||||
unprinted = 1
|
||||
if (isFooter == 0) {
|
||||
print lines "\n"
|
||||
lines = ""
|
||||
}
|
||||
changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):"
|
||||
numlines = split(lines, footer, "\n")
|
||||
for (line = 1; line <= numlines; line++) {
|
||||
if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) {
|
||||
unprinted = 0
|
||||
print "Change-Id: I'"$id"'"
|
||||
}
|
||||
print footer[line]
|
||||
}
|
||||
if (unprinted) {
|
||||
print "Change-Id: I'"$id"'"
|
||||
}
|
||||
}' "$MSG" > "$T" && mv "$T" "$MSG" || rm -f "$T"
|
||||
}
|
||||
_gen_ChangeIdInput() {
|
||||
echo "tree `git write-tree`"
|
||||
if parent=`git rev-parse "HEAD^0" 2>/dev/null`
|
||||
then
|
||||
echo "parent $parent"
|
||||
fi
|
||||
echo "author `git var GIT_AUTHOR_IDENT`"
|
||||
echo "committer `git var GIT_COMMITTER_IDENT`"
|
||||
echo
|
||||
printf '%s' "$clean_message"
|
||||
}
|
||||
_gen_ChangeId() {
|
||||
_gen_ChangeIdInput |
|
||||
git hash-object -t commit --stdin
|
||||
}
|
||||
|
||||
|
||||
add_ChangeId
|
@@ -70,6 +70,7 @@ java_package_configuration(
|
||||
"-Xep:NullableConstructor:ERROR",
|
||||
"-Xep:NullablePrimitive:ERROR",
|
||||
"-Xep:NullableVoid:ERROR",
|
||||
"-Xep:ObjectToString:ERROR",
|
||||
"-Xep:OperatorPrecedence:ERROR",
|
||||
"-Xep:OverridesGuiceInjectableMethod:ERROR",
|
||||
"-Xep:PreconditionsInvalidPlaceholder:ERROR",
|
||||
|
@@ -120,18 +120,18 @@ def declare_nongoogle_deps():
|
||||
sha1 = "dc13ae4faca6df981fc7aeb5a522d9db446d5d50",
|
||||
)
|
||||
|
||||
TESTCONTAINERS_VERSION = "1.13.0"
|
||||
TESTCONTAINERS_VERSION = "1.14.0"
|
||||
|
||||
maven_jar(
|
||||
name = "testcontainers",
|
||||
artifact = "org.testcontainers:testcontainers:" + TESTCONTAINERS_VERSION,
|
||||
sha1 = "c92d1094d2b227e881f66bf09872c46d91ce9ac5",
|
||||
sha1 = "c0d6aea93f4f7ff4b0d559e31308340eaa398798",
|
||||
)
|
||||
|
||||
maven_jar(
|
||||
name = "testcontainers-elasticsearch",
|
||||
artifact = "org.testcontainers:elasticsearch:" + TESTCONTAINERS_VERSION,
|
||||
sha1 = "09353bd960b3f0d26ba7652ae57bb4ac46d043a2",
|
||||
sha1 = "6df7bc7cb5e99c6d9528ea28dd16dbb042b1beec",
|
||||
)
|
||||
|
||||
maven_jar(
|
||||
|
Reference in New Issue
Block a user