Merge branch 'stable-2.14'
* stable-2.14: Document how to set default UI Note on branch-specific labels with custom rules.pl GWT UI: Allow to set blocking label range rules Extend LFS plugin servlet so that Git LFS 2.0 Lock API is handled PolyGerrit: Fix undefined url in gr-dropdown Change-Id: I01320e404daf1abd052c39321346e2eacff3dd09
This commit is contained in:
@@ -2102,6 +2102,20 @@ By default false.
|
|||||||
+
|
+
|
||||||
Path prefix for PolyGerrit's static resources if using a CDN.
|
Path prefix for PolyGerrit's static resources if using a CDN.
|
||||||
|
|
||||||
|
[[gerrit.ui]]gerrit.ui::
|
||||||
|
+
|
||||||
|
Default UI when the user does not request a different preference via argument
|
||||||
|
or cookie.
|
||||||
|
+
|
||||||
|
* `GWT` for the old-style Google Web Toolkit-based interface.
|
||||||
|
* `POLYGERRIT` for the new Polymer-based HTML5 Web interface.
|
||||||
|
+
|
||||||
|
A sanity check during startup is performed that the value of
|
||||||
|
gerrit.ui is an enabled UI.
|
||||||
|
+
|
||||||
|
Defaults to GWT (if GWT is enabled) or POLYGERRIT (if POLYGERRIT is
|
||||||
|
enabled and GWT is disabled)
|
||||||
|
|
||||||
[[gitweb]]
|
[[gitweb]]
|
||||||
=== Section gitweb
|
=== Section gitweb
|
||||||
|
|
||||||
|
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright (C) 2017 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.extensions.api.lfs;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
|
||||||
|
public final class LfsDefinitions {
|
||||||
|
public static final String CONTENTTYPE_VND_GIT_LFS_JSON =
|
||||||
|
"application/vnd.git-lfs+json; charset=utf-8";
|
||||||
|
|
||||||
|
public static final String LFS_OBJECTS_PATH = "objects/batch";
|
||||||
|
public static final String LFS_LOCKS_PATH_REGEX = "locks(?:/(.*)(?:/unlock))?";
|
||||||
|
public static final String LFS_VERIFICATION_PATH = "locks/verify";
|
||||||
|
public static final String LFS_UNIFIED_PATHS_REGEX =
|
||||||
|
Joiner.on('|').join(LFS_OBJECTS_PATH, LFS_LOCKS_PATH_REGEX, LFS_VERIFICATION_PATH);
|
||||||
|
public static final String LFS_URL_WO_AUTH_REGEX_TEAMPLATE = "(?:/p/|/)(.+)(?:/info/lfs/)(?:%s)$";
|
||||||
|
public static final String LFS_URL_WO_AUTH_REGEX =
|
||||||
|
String.format(LFS_URL_WO_AUTH_REGEX_TEAMPLATE, LFS_UNIFIED_PATHS_REGEX);
|
||||||
|
public static final String LFS_URL_REGEX_TEMPLATE = "^(?:/a)?" + LFS_URL_WO_AUTH_REGEX_TEAMPLATE;
|
||||||
|
public static final String LFS_URL_REGEX =
|
||||||
|
String.format(LFS_URL_REGEX_TEMPLATE, LFS_UNIFIED_PATHS_REGEX);
|
||||||
|
|
||||||
|
private LfsDefinitions() {}
|
||||||
|
}
|
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright (C) 2017 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.extensions.api.lfs;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class LfsDefinitionsTest {
|
||||||
|
private static final String[] URL_PREFIXES = new String[] {"/", "/a/", "/p/", "/a/p/"};
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noLfsEndPoint_noMatch() {
|
||||||
|
Pattern p = Pattern.compile(LfsDefinitions.LFS_URL_REGEX);
|
||||||
|
doesNotMatch(p, "/foo");
|
||||||
|
doesNotMatch(p, "/a/foo");
|
||||||
|
doesNotMatch(p, "/p/foo");
|
||||||
|
doesNotMatch(p, "/a/p/foo");
|
||||||
|
|
||||||
|
doesNotMatch(p, "/info/lfs/objects/batch");
|
||||||
|
doesNotMatch(p, "/info/lfs/objects/batch/foo");
|
||||||
|
doesNotMatch(p, "/info/lfs/locks");
|
||||||
|
doesNotMatch(p, "/info/lfs/locks/verify");
|
||||||
|
doesNotMatch(p, "/info/lfs/locks/unlock");
|
||||||
|
doesNotMatch(p, "/info/lfs/locks/lock_id/unlock");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void matchingLfsEndpoint_projectNameCaptured() {
|
||||||
|
Pattern p = Pattern.compile(LfsDefinitions.LFS_URL_REGEX);
|
||||||
|
testProjectGetsMatched(p, "foo/bar/info/lfs/objects/batch", "foo/bar");
|
||||||
|
testProjectGetsMatched(p, "foo/bar/info/lfs/locks", "foo/bar");
|
||||||
|
testProjectGetsMatched(p, "foo/bar/info/lfs/locks/verify", "foo/bar");
|
||||||
|
testProjectAndLockIdGetMatched(
|
||||||
|
p, "foo/bar/info/lfs/locks/lock_id/unlock", "foo/bar", "lock_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testProjectAndLockIdGetMatched(
|
||||||
|
Pattern p, String url, String expectedProject, String expectedLockId) {
|
||||||
|
for (String prefix : URL_PREFIXES) {
|
||||||
|
matches(p, prefix + url, expectedProject, expectedLockId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testProjectGetsMatched(Pattern p, String url, String expected) {
|
||||||
|
for (String prefix : URL_PREFIXES) {
|
||||||
|
matches(p, prefix + url, expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doesNotMatch(Pattern p, String input) {
|
||||||
|
Matcher m = p.matcher(input);
|
||||||
|
assertThat(m.matches()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void matches(Pattern p, String input, String expectedProjectName) {
|
||||||
|
Matcher m = p.matcher(input);
|
||||||
|
assertThat(m.matches()).isTrue();
|
||||||
|
assertThat(m.group(1)).isEqualTo(expectedProjectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void matches(Pattern p, String input, String expectedProjectName, String expectedLockId) {
|
||||||
|
Matcher m = p.matcher(input);
|
||||||
|
assertThat(m.matches()).isTrue();
|
||||||
|
assertThat(m.group(1)).isEqualTo(expectedProjectName);
|
||||||
|
assertThat(m.group(2)).isEqualTo(expectedLockId);
|
||||||
|
}
|
||||||
|
}
|
@@ -111,6 +111,12 @@ public class PermissionRuleEditor extends Composite
|
|||||||
min = minList;
|
min = minList;
|
||||||
max = maxList;
|
max = maxList;
|
||||||
|
|
||||||
|
action.setAcceptableValues(
|
||||||
|
Arrays.asList(
|
||||||
|
PermissionRule.Action.ALLOW,
|
||||||
|
PermissionRule.Action.DENY,
|
||||||
|
PermissionRule.Action.BLOCK));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
min = new RangeBox.Box();
|
min = new RangeBox.Box();
|
||||||
max = new RangeBox.Box();
|
max = new RangeBox.Box();
|
||||||
@@ -144,15 +150,13 @@ public class PermissionRuleEditor extends Composite
|
|||||||
}
|
}
|
||||||
force.setVisible(canForce);
|
force.setVisible(canForce);
|
||||||
force.setEnabled(!readOnly);
|
force.setEnabled(!readOnly);
|
||||||
|
action.getElement().setPropertyBoolean("disabled", readOnly);
|
||||||
|
|
||||||
if (validRange != null) {
|
if (validRange != null) {
|
||||||
min.setEnabled(!readOnly);
|
min.setEnabled(!readOnly);
|
||||||
max.setEnabled(!readOnly);
|
max.setEnabled(!readOnly);
|
||||||
action.getElement().getStyle().setDisplay(Display.NONE);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rangeEditor.getStyle().setDisplay(Display.NONE);
|
rangeEditor.getStyle().setDisplay(Display.NONE);
|
||||||
action.getElement().setPropertyBoolean("disabled", readOnly);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readOnly) {
|
if (readOnly) {
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.httpd;
|
package com.google.gerrit.httpd;
|
||||||
|
|
||||||
import static com.google.gerrit.httpd.plugins.LfsPluginServlet.LFS_REST;
|
import static com.google.gerrit.extensions.api.lfs.LfsDefinitions.LFS_URL_WO_AUTH_REGEX;
|
||||||
|
|
||||||
import com.google.gerrit.extensions.client.GitBasicAuthPolicy;
|
import com.google.gerrit.extensions.client.GitBasicAuthPolicy;
|
||||||
import com.google.gerrit.reviewdb.client.CoreDownloadSchemes;
|
import com.google.gerrit.reviewdb.client.CoreDownloadSchemes;
|
||||||
@@ -26,7 +26,7 @@ import javax.servlet.Filter;
|
|||||||
|
|
||||||
/** Configures Git access over HTTP with authentication. */
|
/** Configures Git access over HTTP with authentication. */
|
||||||
public class GitOverHttpModule extends ServletModule {
|
public class GitOverHttpModule extends ServletModule {
|
||||||
private static final String LFS_URL_REGEX = "^(?:(?!/a/))" + LFS_REST;
|
private static final String NOT_AUTHORIZED_LFS_URL_REGEX = "^(?:(?!/a/))" + LFS_URL_WO_AUTH_REGEX;
|
||||||
|
|
||||||
private final AuthConfig authConfig;
|
private final AuthConfig authConfig;
|
||||||
private final DownloadConfig downloadConfig;
|
private final DownloadConfig downloadConfig;
|
||||||
@@ -55,7 +55,7 @@ public class GitOverHttpModule extends ServletModule {
|
|||||||
serveRegex(git).with(GitOverHttpServlet.class);
|
serveRegex(git).with(GitOverHttpServlet.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
filterRegex(LFS_URL_REGEX).through(authFilter);
|
filterRegex(NOT_AUTHORIZED_LFS_URL_REGEX).through(authFilter);
|
||||||
filter("/a/*").through(authFilter);
|
filter("/a/*").through(authFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.httpd.plugins;
|
package com.google.gerrit.httpd.plugins;
|
||||||
|
|
||||||
|
import com.google.gerrit.extensions.api.lfs.LfsDefinitions;
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||||
import com.google.gerrit.httpd.resources.Resource;
|
import com.google.gerrit.httpd.resources.Resource;
|
||||||
import com.google.gerrit.httpd.resources.ResourceKey;
|
import com.google.gerrit.httpd.resources.ResourceKey;
|
||||||
@@ -35,7 +36,7 @@ public class HttpPluginModule extends ServletModule {
|
|||||||
serveRegex("^/(?:a/)?plugins/(.*)?$").with(HttpPluginServlet.class);
|
serveRegex("^/(?:a/)?plugins/(.*)?$").with(HttpPluginServlet.class);
|
||||||
|
|
||||||
bind(LfsPluginServlet.class);
|
bind(LfsPluginServlet.class);
|
||||||
serveRegex(LfsPluginServlet.URL_REGEX).with(LfsPluginServlet.class);
|
serveRegex(LfsDefinitions.LFS_URL_REGEX).with(LfsPluginServlet.class);
|
||||||
|
|
||||||
bind(StartPluginListener.class)
|
bind(StartPluginListener.class)
|
||||||
.annotatedWith(UniqueAnnotations.create())
|
.annotatedWith(UniqueAnnotations.create())
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.httpd.plugins;
|
package com.google.gerrit.httpd.plugins;
|
||||||
|
|
||||||
|
import static com.google.gerrit.extensions.api.lfs.LfsDefinitions.CONTENTTYPE_VND_GIT_LFS_JSON;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_NOT_IMPLEMENTED;
|
import static javax.servlet.http.HttpServletResponse.SC_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
@@ -52,12 +53,6 @@ public class LfsPluginServlet extends HttpServlet
|
|||||||
implements StartPluginListener, ReloadPluginListener {
|
implements StartPluginListener, ReloadPluginListener {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final Logger log = LoggerFactory.getLogger(LfsPluginServlet.class);
|
private static final Logger log = LoggerFactory.getLogger(LfsPluginServlet.class);
|
||||||
|
|
||||||
public static final String LFS_REST = "(?:/p/|/)(.+)(?:/info/lfs/objects/batch)$";
|
|
||||||
public static final String URL_REGEX = "^(?:/a)?" + LFS_REST;
|
|
||||||
|
|
||||||
private static final String CONTENTTYPE_VND_GIT_LFS_JSON =
|
|
||||||
"application/vnd.git-lfs+json; charset=utf-8";
|
|
||||||
private static final String MESSAGE_LFS_NOT_CONFIGURED =
|
private static final String MESSAGE_LFS_NOT_CONFIGURED =
|
||||||
"{\"message\":\"No LFS plugin is configured to handle LFS requests.\"}";
|
"{\"message\":\"No LFS plugin is configured to handle LFS requests.\"}";
|
||||||
|
|
||||||
|
@@ -1,56 +0,0 @@
|
|||||||
// Copyright (C) 2016 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.httpd.plugins;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class LfsPluginServletTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void noLfsEndPoint_noMatch() {
|
|
||||||
Pattern p = Pattern.compile(LfsPluginServlet.URL_REGEX);
|
|
||||||
doesNotMatch(p, "/foo");
|
|
||||||
doesNotMatch(p, "/a/foo");
|
|
||||||
doesNotMatch(p, "/p/foo");
|
|
||||||
doesNotMatch(p, "/a/p/foo");
|
|
||||||
|
|
||||||
doesNotMatch(p, "/info/lfs/objects/batch");
|
|
||||||
doesNotMatch(p, "/info/lfs/objects/batch/foo");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void matchingLfsEndpoint_projectNameCaptured() {
|
|
||||||
Pattern p = Pattern.compile(LfsPluginServlet.URL_REGEX);
|
|
||||||
matches(p, "/foo/bar/info/lfs/objects/batch", "foo/bar");
|
|
||||||
matches(p, "/a/foo/bar/info/lfs/objects/batch", "foo/bar");
|
|
||||||
matches(p, "/p/foo/bar/info/lfs/objects/batch", "foo/bar");
|
|
||||||
matches(p, "/a/p/foo/bar/info/lfs/objects/batch", "foo/bar");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doesNotMatch(Pattern p, String input) {
|
|
||||||
Matcher m = p.matcher(input);
|
|
||||||
assertThat(m.matches()).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void matches(Pattern p, String input, String expectedProjectName) {
|
|
||||||
Matcher m = p.matcher(input);
|
|
||||||
assertThat(m.matches()).isTrue();
|
|
||||||
assertThat(m.group(1)).isEqualTo(expectedProjectName);
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user