summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClark Boylan <clark.boylan@gmail.com>2022-02-14 10:55:30 -0800
committerClark Boylan <clark.boylan@gmail.com>2022-02-15 09:21:16 -0800
commit77f5a066f0d5e30b4bb789bf40134a50f2070b59 (patch)
treefba42df5d9cbfeab79601a9b30263bdbaf593982
parentd9aa1bc8b5f943e3749c297f50998062f85c5380 (diff)
Add ${hash} as a substitution variable for gitweb file links
Gitweb file links interpolate ${commit} but this may be the ref rather than the commit hash when interpolating file links. This is problematic because some gitweb like systems (in this case gitea) rely on the hash rather than the ref path. We address this by adding a new ${hash} interpolation value that will always be the sha commitId value in the file links. We don't change the value of ${commit} as it appears gitiles may rely on the current implemenation and there may be other implementations out there relying on the current values for that variable. Bug: Issue 15589 Co-Authored-By: David Ostrovsky <david@ostrovsky.org> Release-Notes: Add SHA-1 hash variable to gitweb file links Change-Id: Ifabc2c27c62cd55a7b8d43cfa43f6dc1539423eb
-rw-r--r--Documentation/config-gerrit.txt5
-rw-r--r--Documentation/config-gitweb.txt17
-rw-r--r--java/com/google/gerrit/acceptance/ExtensionRegistry.java8
-rw-r--r--java/com/google/gerrit/extensions/webui/FileWebLink.java3
-rw-r--r--java/com/google/gerrit/server/WebLinks.java8
-rw-r--r--java/com/google/gerrit/server/config/GitwebConfig.java4
-rw-r--r--java/com/google/gerrit/server/restapi/change/GetDiff.java11
-rw-r--r--javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java42
m---------plugins/gitiles0
9 files changed, 88 insertions, 10 deletions
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 7090ff8e35..ab6b1840a8 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -2496,8 +2496,9 @@ at the contents of a file in a specific commit when `gitweb.type` is
set to `custom`.
+
Valid replacements are `${project}` for the project name in Gerrit,
-`${file}` for the file name and `${commit}` for the SHA-1 hash for
-the commit.
+`${file}` for the file name, `${hash}` for the SHA-1 hash for the commit,
+and `${commit}` for the change ref or SHA-1 of the commit if no base
+patch set.
[[gitweb.filehistory]]gitweb.filehistory::
+
diff --git a/Documentation/config-gitweb.txt b/Documentation/config-gitweb.txt
index 46c9ced2b4..00e33a35d3 100644
--- a/Documentation/config-gitweb.txt
+++ b/Documentation/config-gitweb.txt
@@ -268,7 +268,22 @@ Gerrit, such as cgit.
cgit can be used by specifying `gitweb.type` to be 'cgit'.
-It is also possible to define custom patterns.
+It is also possible to define custom patterns. Gitea can be used
+with custom patterns for example:
+
+----
+ git config -f $site_path/etc/gerrit.config gitweb.type custom
+ git config -f $site_path/etc/gerrit.config gitweb.urlEncode false
+ git config -f $site_path/etc/gerrit.config gitweb.linkname gitea
+ git config -f $site_path/etc/gerrit.config gitweb.url https://gitea.example.org/
+ git config -f $site_path/etc/gerrit.config gitweb.branch ${project}/src/branch/${branch}
+ git config -f $site_path/etc/gerrit.config gitweb.file ${project}/src/commit/${hash}/${file}
+ git config -f $site_path/etc/gerrit.config gitweb.filehistory ${project}/commits/branch/${branch}/${file}
+ git config -f $site_path/etc/gerrit.config gitweb.project ${project}
+ git config -f $site_path/etc/gerrit.config gitweb.revision ${project}/commit/${commit}
+ git config -f $site_path/etc/gerrit.config gitweb.roottree ${project}/src/commit/${commit}
+ git config -f $site_path/etc/gerrit.config gitweb.tag ${project}/src/tag/${tag}
+----
=== SEE ALSO
diff --git a/java/com/google/gerrit/acceptance/ExtensionRegistry.java b/java/com/google/gerrit/acceptance/ExtensionRegistry.java
index 35f8ce6da6..d72ee3f12d 100644
--- a/java/com/google/gerrit/acceptance/ExtensionRegistry.java
+++ b/java/com/google/gerrit/acceptance/ExtensionRegistry.java
@@ -33,6 +33,7 @@ import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.extensions.webui.FileHistoryWebLink;
+import com.google.gerrit.extensions.webui.FileWebLink;
import com.google.gerrit.extensions.webui.PatchSetWebLink;
import com.google.gerrit.server.ExceptionHook;
import com.google.gerrit.server.account.GroupBackend;
@@ -75,6 +76,7 @@ public class ExtensionRegistry {
private final DynamicSet<GitReferenceUpdatedListener> refUpdatedListeners;
private final DynamicSet<FileHistoryWebLink> fileHistoryWebLinks;
private final DynamicSet<PatchSetWebLink> patchSetWebLinks;
+ private final DynamicSet<FileWebLink> fileWebLinks;
private final DynamicSet<RevisionCreatedListener> revisionCreatedListeners;
private final DynamicSet<GroupBackend> groupBackends;
private final DynamicSet<AccountActivationValidationListener>
@@ -109,6 +111,7 @@ public class ExtensionRegistry {
DynamicSet<GitReferenceUpdatedListener> refUpdatedListeners,
DynamicSet<FileHistoryWebLink> fileHistoryWebLinks,
DynamicSet<PatchSetWebLink> patchSetWebLinks,
+ DynamicSet<FileWebLink> fileWebLinks,
DynamicSet<RevisionCreatedListener> revisionCreatedListeners,
DynamicSet<GroupBackend> groupBackends,
DynamicSet<AccountActivationValidationListener> accountActivationValidationListeners,
@@ -139,6 +142,7 @@ public class ExtensionRegistry {
this.refUpdatedListeners = refUpdatedListeners;
this.fileHistoryWebLinks = fileHistoryWebLinks;
this.patchSetWebLinks = patchSetWebLinks;
+ this.fileWebLinks = fileWebLinks;
this.revisionCreatedListeners = revisionCreatedListeners;
this.groupBackends = groupBackends;
this.accountActivationValidationListeners = accountActivationValidationListeners;
@@ -240,6 +244,10 @@ public class ExtensionRegistry {
return add(patchSetWebLinks, patchSetWebLink);
}
+ public Registration add(FileWebLink fileWebLink) {
+ return add(fileWebLinks, fileWebLink);
+ }
+
public Registration add(RevisionCreatedListener revisionCreatedListener) {
return add(revisionCreatedListeners, revisionCreatedListener);
}
diff --git a/java/com/google/gerrit/extensions/webui/FileWebLink.java b/java/com/google/gerrit/extensions/webui/FileWebLink.java
index c03d606a27..dc386b310d 100644
--- a/java/com/google/gerrit/extensions/webui/FileWebLink.java
+++ b/java/com/google/gerrit/extensions/webui/FileWebLink.java
@@ -32,8 +32,9 @@ public interface FileWebLink extends WebLink {
*
* @param projectName Name of the project
* @param revision Name of the revision (e.g. branch or commit ID)
+ * @param hash SHA-1 of the commit
* @param fileName Name of the file
* @return WebLinkInfo that links to project in external service, null if there should be no link.
*/
- WebLinkInfo getFileWebLink(String projectName, String revision, String fileName);
+ WebLinkInfo getFileWebLink(String projectName, String revision, String hash, String fileName);
}
diff --git a/java/com/google/gerrit/server/WebLinks.java b/java/com/google/gerrit/server/WebLinks.java
index e66e7f51e3..785cd1c0e9 100644
--- a/java/com/google/gerrit/server/WebLinks.java
+++ b/java/com/google/gerrit/server/WebLinks.java
@@ -113,14 +113,16 @@ public class WebLinks {
/**
* @param project Project name.
- * @param revision SHA1 of revision.
+ * @param revision Name of the revision (e.g. branch or commit ID)
+ * @param hash SHA1 of revision.
* @param file File name.
* @return Links for files.
*/
- public ImmutableList<WebLinkInfo> getFileLinks(String project, String revision, String file) {
+ public ImmutableList<WebLinkInfo> getFileLinks(
+ String project, String revision, String hash, String file) {
return Patch.isMagic(file)
? ImmutableList.of()
- : filterLinks(fileLinks, webLink -> webLink.getFileWebLink(project, revision, file));
+ : filterLinks(fileLinks, webLink -> webLink.getFileWebLink(project, revision, hash, file));
}
/**
diff --git a/java/com/google/gerrit/server/config/GitwebConfig.java b/java/com/google/gerrit/server/config/GitwebConfig.java
index 8214f031e0..40b5a8bbcc 100644
--- a/java/com/google/gerrit/server/config/GitwebConfig.java
+++ b/java/com/google/gerrit/server/config/GitwebConfig.java
@@ -315,11 +315,13 @@ public class GitwebConfig {
}
@Override
- public WebLinkInfo getFileWebLink(String projectName, String revision, String fileName) {
+ public WebLinkInfo getFileWebLink(
+ String projectName, String revision, String hash, String fileName) {
if (file != null) {
return link(
file.replace("project", encode(projectName))
.replace("commit", encode(revision))
+ .replace("hash", encode(revision))
.replace("file", encode(fileName))
.toString());
}
diff --git a/java/com/google/gerrit/server/restapi/change/GetDiff.java b/java/com/google/gerrit/server/restapi/change/GetDiff.java
index b8902b78ab..19256bb39e 100644
--- a/java/com/google/gerrit/server/restapi/change/GetDiff.java
+++ b/java/com/google/gerrit/server/restapi/change/GetDiff.java
@@ -183,6 +183,8 @@ public class GetDiff implements RestReadView<FileResource> {
private final DiffSide sideB;
private final String revA;
private final String revB;
+ private final String hashA;
+ private final String hashB;
private final FileResource resource;
@Nullable private final PatchSet basePatchSet;
@@ -201,6 +203,7 @@ public class GetDiff implements RestReadView<FileResource> {
this.sideB = sideB;
revA = basePatchSet != null ? basePatchSet.refName() : sideA.fileInfo().commitId;
+ hashA = sideA.fileInfo().commitId;
RevisionResource revision = resource.getRevision();
revB =
@@ -208,8 +211,9 @@ public class GetDiff implements RestReadView<FileResource> {
.getEdit()
.map(edit -> edit.getRefName())
.orElseGet(() -> revision.getPatchSet().refName());
+ hashB = sideB.fileInfo().commitId;
- logger.atFine().log("revA = %s, revB = %s", revA, revB);
+ logger.atFine().log("revA = %s, hashA = %s, revB = %s, hashB = %s", revA, hashA, revB, hashB);
}
@Override
@@ -228,15 +232,18 @@ public class GetDiff implements RestReadView<FileResource> {
@Override
public ImmutableList<WebLinkInfo> getFileWebLinks(DiffSide.Type type) {
String rev;
+ String hash;
DiffSide side;
if (type == DiffSide.Type.SIDE_A) {
rev = revA;
+ hash = hashA;
side = sideA;
} else {
rev = revB;
+ hash = hashB;
side = sideB;
}
- return webLinks.getFileLinks(projectName.get(), rev, side.fileName());
+ return webLinks.getFileLinks(projectName.get(), rev, hash, side.fileName());
}
}
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
index 0b18503895..021a7194a6 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
@@ -30,6 +30,8 @@ import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.ExtensionRegistry;
+import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.PushOneCommit.Result;
@@ -40,8 +42,11 @@ import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gerrit.extensions.common.ChangeType;
import com.google.gerrit.extensions.common.DiffInfo;
import com.google.gerrit.extensions.common.FileInfo;
+import com.google.gerrit.extensions.common.WebLinkInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
+import com.google.gerrit.extensions.webui.FileWebLink;
+import com.google.inject.Inject;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -75,6 +80,8 @@ public class RevisionDiffIT extends AbstractDaemonTest {
.collect(joining());
private static final String FILE_CONTENT2 = "1st line\n2nd line\n3rd line\n";
+ @Inject private ExtensionRegistry extensionRegistry;
+
private boolean intraline;
private boolean useNewDiffCacheListFiles;
private boolean useNewDiffCacheGetDiff;
@@ -142,6 +149,26 @@ public class RevisionDiffIT extends AbstractDaemonTest {
}
@Test
+ public void gitwebFileWebLinkIncludedInDiff() throws Exception {
+ try (Registration registration = newGitwebFileWebLink()) {
+ String fileName = "foo.txt";
+ String fileContent = "bar\n";
+ PushOneCommit.Result result = createChange("Add a file", fileName, fileContent);
+ DiffInfo info =
+ gApi.changes()
+ .id(result.getChangeId())
+ .revision(result.getCommit().name())
+ .file(fileName)
+ .diff();
+ assertThat(info.metaB.webLinks).hasSize(1);
+ assertThat(info.metaB.webLinks.get(0).url)
+ .isEqualTo(
+ String.format(
+ "http://gitweb/?p=%s;hb=%s;f=%s", project, result.getCommit().name(), fileName));
+ }
+ }
+
+ @Test
public void deletedFileIsIncludedInDiff() throws Exception {
gApi.changes().id(changeId).edit().deleteFile(FILE_NAME);
gApi.changes().id(changeId).edit().publish();
@@ -2875,6 +2902,21 @@ public class RevisionDiffIT extends AbstractDaemonTest {
assertThat(e).hasMessageThat().isEqualTo("edit not allowed as base");
}
+ private Registration newGitwebFileWebLink() {
+ FileWebLink fileWebLink =
+ new FileWebLink() {
+ @Override
+ public WebLinkInfo getFileWebLink(
+ String projectName, String revision, String hash, String fileName) {
+ return new WebLinkInfo(
+ "name",
+ "imageURL",
+ String.format("http://gitweb/?p=%s;hb=%s;f=%s", projectName, hash, fileName));
+ }
+ };
+ return extensionRegistry.newRegistration().add(fileWebLink);
+ }
+
private String updatedCommitMessage() {
return "An unchanged patchset\n\nChange-Id: " + changeId;
}
diff --git a/plugins/gitiles b/plugins/gitiles
-Subproject b99022c1775de502093c37950bc91a7d8fd0b4d
+Subproject 5e8809c34798022a81cabe1d2d682bb83245a3c