Make gitweb url links customizable, add support for cgit

The gitweb.type variable can now be one of the following: "gitweb",
"cgit" or "custom", with suitable defaults for other variables
selected based on the preferred URL format for that gitweb type.

If gitweb.type = custom is used, then URL patterns must be defined
in the gerrit.config file:

  [gitweb]
    project = ${project}/summary
    revision = ${project}/commit/${commit}
    branch = ${project}/log/?h=${branch}

In a custom configuration, all 3 variables must be defined or gitweb
integration will be disabled.

Bug: issue 366
Bug: issue 371
Change-Id: Ic681af1300b9c7cbae1f0f0ce31a5272378feac6
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shane Mc Cormack
2009-12-28 04:49:39 +00:00
committed by Shawn O. Pearce
parent 5f95a93f0f
commit 27868a42d9
11 changed files with 220 additions and 51 deletions

View File

@@ -650,6 +650,36 @@ gerrit.basePath and the repositories it contains.
Gerrit appends any necessary query arguments onto the end of this URL.
For example, "?p=$project.git;h=$commit".
[[gitweb.type]]gitweb.type::
+
Optional type of affiliated gitweb service. This allows using
alternatives to gitweb, such as cgit.
+
Valid values are `gitweb`, `cgit` or `custom`.
[[gitweb.type]]gitweb.revision::
+
Optional pattern to use for constructing the gitweb URL when pointing
at a specific commit when `custom` is used above.
+
Valid replacements are `$\{project\}` for the project name in Gerrit
and `$\{commit\}` for the SHA1 hash for the commit.
[[gitweb.type]]gitweb.project::
+
Optional pattern to use for constructing the gitweb URL when pointing
at a specific project when `custom` is used above.
+
Valid replacements are `$\{project\}` for the project name in Gerrit.
[[gitweb.type]]gitweb.branch::
+
Optional pattern to use for constructing the gitweb URL when pointing
at a specific branch when `custom` is used above.
+
Valid replacements are `$\{project\}` for the project name in Gerrit
and `$\{branch\}` for the name of the branch.
[[http]]Section http
~~~~~~~~~~~~~~~~~~~~

View File

@@ -35,10 +35,20 @@ If your repository set is large and you are expecting a lot
of users, you may want to look at the caching forks used by
high-traffic sites like kernel.org or repo.or.cz.
Alternatives to gitweb
----------------------
There are other alternatives to gitweb that can also be used with
Gerrit, such as cgit.
cgit can be used by specifying `gitweb.type` to be 'cgit'.
It is also possible to define custom patterns.
See Also
--------
* link:config-gerrit.html#gitweb[Section gitweb]
* link:http://hjemli.net/git/cgit/[cgit]
GERRIT
------

View File

@@ -0,0 +1,122 @@
// 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.
package com.google.gerrit.common.data;
/** Class to store information about different gitweb types. */
public class GitWebType {
/**
* Get a GitWebType based on the given name.
*
* @param name Name to look for.
* @return GitWebType from the given name, else null if not found.
*/
public static GitWebType fromName(final String name) {
final GitWebType type;
if (name == null || name.isEmpty() || name.equalsIgnoreCase("gitweb")) {
type = new GitWebType();
type.setProject("?p=${project}.git;a=summary");
type.setRevision("?p=${project}.git;a=commit;h=${commit}");
type.setBranch("?p=${project}.git;a=shortlog;h=${branch}");
} else if (name.equalsIgnoreCase("cgit")) {
type = new GitWebType();
type.setProject("${project}/summary");
type.setRevision("${project}/commit/?id=${commit}");
type.setBranch("${project}/log/?h=${branch}");
} else if (name.equalsIgnoreCase("custom")) {
type = new GitWebType();
} else {
type = null;
}
return type;
}
/** String for revision view url. */
private String revision;
/** ParamertizedString for project view url. */
private String project;
/** ParamertizedString for branch view url. */
private String branch;
/** Private default constructor for gson. */
protected GitWebType() {
}
/**
* Get the String for branch view.
*
* @return The String for branch view
*/
public String getBranch() {
return branch;
}
/**
* Get the String for project view.
*
* @return The String for project view
*/
public String getProject() {
return project;
}
/**
* Get the String for revision view.
*
* @return The String for revision view
*/
public String getRevision() {
return revision;
}
/**
* Set the pattern for branch view.
*
* @param pattern The pattern for branch view
*/
public void setBranch(final String pattern) {
if (pattern != null && !pattern.isEmpty()) {
branch = pattern;
}
}
/**
* Set the pattern for project view.
*
* @param pattern The pattern for project view
*/
public void setProject(final String pattern) {
if (pattern != null && !pattern.isEmpty()) {
project = pattern;
}
}
/**
* Set the pattern for revision view.
*
* @param pattern The pattern for revision view
*/
public void setRevision(final String pattern) {
if (pattern != null && !pattern.isEmpty()) {
revision = pattern;
}
}
}

View File

@@ -18,67 +18,46 @@ import com.google.gerrit.reviewdb.Branch;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.Project;
import com.google.gwt.http.client.URL;
import java.util.HashMap;
import java.util.Map;
/** Link to an external gitweb server. */
public class GitwebLink {
protected String baseUrl;
protected GitWebType type;
protected GitwebLink() {
}
public GitwebLink(final String base) {
baseUrl = base + "?";
public GitwebLink(final String base, final GitWebType gitWebType) {
baseUrl = base;
type = gitWebType;
}
public String toRevision(final Project.NameKey project, final PatchSet ps) {
final StringBuilder r = new StringBuilder();
p(r, project);
a(r, "commit");
h(r, ps);
return baseUrl + r;
ParamertizedString pattern = new ParamertizedString(type.getRevision());
final Map<String, String> p = new HashMap<String, String>();
p.put("project", URL.encodeComponent(project.get()));
p.put("commit", URL.encodeComponent(ps.getRevision().get()));
return baseUrl + pattern.replace(p);
}
public String toProject(final Project.NameKey project) {
final StringBuilder r = new StringBuilder();
p(r, project);
a(r, "summary");
return baseUrl + r;
ParamertizedString pattern = new ParamertizedString(type.getProject());
final Map<String, String> p = new HashMap<String, String>();
p.put("project", URL.encodeComponent(project.get()));
return baseUrl + pattern.replace(p);
}
public String toBranch(final Branch.NameKey branch) {
final StringBuilder r = new StringBuilder();
p(r, branch.getParentKey());
h(r, branch);
a(r, "shortlog");
return baseUrl + r;
}
ParamertizedString pattern = new ParamertizedString(type.getBranch());
private static void p(final StringBuilder r, final Project.NameKey project) {
String n = project.get();
if (!n.endsWith(".git")) {
n += ".git";
}
var(r, "p", n);
}
private static void h(final StringBuilder r, final PatchSet ps) {
var(r, "h", ps.getRevision().get());
}
private static void h(final StringBuilder r, final Branch.NameKey branch) {
var(r, "h", branch.get());
}
private static void a(final StringBuilder r, final String where) {
var(r, "a", where);
}
private static void var(final StringBuilder r, final String n, final String v) {
if (r.length() > 0) {
r.append(";");
}
r.append(n);
r.append("=");
r.append(URL.encodeComponent(v));
final Map<String, String> p = new HashMap<String, String>();
p.put("project", URL.encodeComponent(branch.getParentKey().get()));
p.put("branch", URL.encodeComponent(branch.get()));
return baseUrl + pattern.replace(p);
}
}

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server;
package com.google.gerrit.common.data;
import java.util.ArrayList;
import java.util.Collections;
@@ -32,6 +32,10 @@ public class ParamertizedString {
private final List<Format> patternOps;
private final List<Parameter> parameters;
protected ParamertizedString() {
this(new Constant(""));
}
private ParamertizedString(final Constant c) {
pattern = c.text;
rawPattern = c.text;

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server;
package com.google.gerrit.common.data;
import junit.framework.TestCase;

View File

@@ -98,7 +98,8 @@ class GerritConfigProvider implements Provider<GerritConfig> {
config.setEditableAccountFields(fields);
if (gitWebConfig.getUrl() != null) {
config.setGitwebLink(new GitwebLink(gitWebConfig.getUrl()));
config.setGitwebLink(new GitwebLink(gitWebConfig.getUrl(), gitWebConfig
.getGitWebType()));
}
if (sshInfo != null && !sshInfo.getHostKeys().isEmpty()) {

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.httpd;
import com.google.gerrit.common.data.GitWebType;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
@@ -31,6 +32,7 @@ public class GitWebConfig {
private final File gitweb_cgi;
private final File gitweb_css;
private final File git_logo_png;
private GitWebType type;
@Inject
GitWebConfig(final SitePaths sitePaths,
@@ -38,8 +40,24 @@ public class GitWebConfig {
final String cfgUrl = cfg.getString("gitweb", null, "url");
final String cfgCgi = cfg.getString("gitweb", null, "cgi");
type = GitWebType.fromName(cfg.getString("gitweb", null, "type"));
type.setBranch(cfg.getString("gitweb", null, "branch"));
type.setProject(cfg.getString("gitweb", null, "project"));
type.setRevision(cfg.getString("gitweb", null, "revision"));
if (type.getBranch() == null) {
log.warn("No Pattern specified for gitweb.branch, disabling.");
type = null;
} else if (type.getProject() == null) {
log.warn("No Pattern specified for gitweb.project, disabling.");
type = null;
} else if (type.getRevision() == null) {
log.warn("No Pattern specified for gitweb.revision, disabling.");
type = null;
}
if ((cfgUrl != null && cfgUrl.isEmpty())
|| (cfgCgi != null && cfgCgi.isEmpty())) {
|| (cfgCgi != null && cfgCgi.isEmpty()) || type == null) {
// Either setting was explicitly set to the empty string disabling
// gitweb for this server. Disable the configuration.
//
@@ -103,6 +121,11 @@ public class GitWebConfig {
git_logo_png = logo;
}
/** @return GitWebType for gitweb viewer. */
public GitWebType getGitWebType() {
return type;
}
/**
* @return URL of the entry point into gitweb. This URL may be relative to our
* context if gitweb is hosted by ourselves; or absolute if its hosted

View File

@@ -14,7 +14,7 @@
package com.google.gerrit.server.auth.ldap;
import com.google.gerrit.server.ParamertizedString;
import com.google.gerrit.common.data.ParamertizedString;
import java.util.ArrayList;
import java.util.Collections;

View File

@@ -19,7 +19,7 @@ import com.google.gerrit.reviewdb.AccountExternalId;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.AuthType;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.ParamertizedString;
import com.google.gerrit.common.data.ParamertizedString;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.AuthRequest;

View File

@@ -16,7 +16,7 @@ package com.google.gerrit.server.mail;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.ParamertizedString;
import com.google.gerrit.common.data.ParamertizedString;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;