Merge "Expose the AnonymousCowardName, GerritPersonIdent and NotesBranchUtil to plugins"
diff --git a/contrib/fake_ldap.pl b/contrib/fake_ldap.pl
new file mode 100644
index 0000000..5d423a78
--- /dev/null
+++ b/contrib/fake_ldap.pl
@@ -0,0 +1,333 @@
+#!/usr/bin/env perl
+
+# Fake LDAP server for Gerrit
+# Author: Olivier Croquette <ocroquette@free.fr>
+# Last change: 2012-11-12
+#
+# Abstract:
+# ====================================================================
+#
+# Gerrit currently supports several authentication schemes, but
+# unfortunately not the most basic one, e.g. local accounts with
+# local passwords.
+#
+# As a workaround, this script implements a minimal LDAP server
+# that can be used to authenticate against Gerrit. The information
+# required by Gerrit relative to users (user ID, password, display
+# name, email) is stored in a text file similar to /etc/passwd
+#
+#
+# Usage (see below for the setup)
+# ====================================================================
+#
+# To create a new file to store the user information:
+# fake-ldap edituser --datafile /path/datafile --username maxpower \
+# --displayname "Max Power" --email max.power@provider.com
+#
+# To modify an existing user (for instance the email):
+# fake-ldap edituser --datafile /path/datafile --username ocroquette \
+# --email max.power@provider2.com
+#
+# To set a new password for an existing user:
+# fake-ldap edituser --datafile /path/datafile --username ocroquette \
+# --password ""
+#
+# To start the server:
+# fake-ldap start --datafile /path/datafile
+#
+# The server reads the user data file on each new connection. It's not
+# scalable but it should not be a problem for the intended usage
+# (small teams, testing,...)
+#
+#
+# Setup
+# ===================================================================
+#
+# Install the dependencies
+#
+# Install the Perl module dependencies. On Debian and MacPorts,
+# all modules are available as packages, except Net::LDAP::Server.
+#
+# Debian: apt-get install libterm-readkey-perl
+#
+# Since Net::LDAP::Server consists only of one file, you can put it
+# along the script in Net/LDAP/Server.pm
+#
+# Create the data file with the first user (see above)
+#
+# Start as the script a server ("start" command, see above)
+#
+# Configure Gerrit with the following options:
+#
+# gerrit.canonicalWebUrl = ... (workaround for a known Gerrit bug)
+# auth.type = LDAP_BIND
+# ldap.server = ldap://localhost:10389
+# ldap.accountBase = ou=People,dc=nodomain
+# ldap.groupBase = ou=Group,dc=nodomain
+#
+# Start Gerrit
+#
+# Log on in the Web interface
+#
+# If you want the fake LDAP server to start at boot time, add it to
+# /etc/inittab, with a line like:
+#
+# ld1:6:respawn:su someuser /path/fake-ldap start --datafile /path/datafile
+#
+# ===================================================================
+
+use strict;
+
+# Global var containing the options passed on the command line:
+my %cmdLineOptions;
+
+# Global var containing the user data read from the data file:
+my %userData;
+
+my $defaultport = 10389;
+
+package MyServer;
+
+use Data::Dumper;
+use Net::LDAP::Server;
+use Net::LDAP::Constant qw(LDAP_SUCCESS LDAP_INVALID_CREDENTIALS LDAP_OPERATIONS_ERROR);
+use IO::Socket;
+use IO::Select;
+use Term::ReadKey;
+
+use Getopt::Long;
+
+use base 'Net::LDAP::Server';
+
+sub bind {
+ my $self = shift;
+ my ($reqData, $fullRequest) = @_;
+
+ print "bind called\n" if $cmdLineOptions{verbose} >= 1;
+ print Dumper(\@_) if $cmdLineOptions{verbose} >= 2;
+ my $sha1 = undef;
+ my $uid = undef;
+ eval{
+ $uid = $reqData->{name};
+ $sha1 = main::encryptpwd($uid, $reqData->{authentication}->{simple})
+ };
+ if ($@) {
+ warn $@;
+ return({
+ 'matchedDN' => '',
+ 'errorMessage' => $@,
+ 'resultCode' => LDAP_OPERATIONS_ERROR
+ });
+ }
+
+ print $sha1 . "\n" if $cmdLineOptions{verbose} >= 2;
+ print Dumper($userData{$uid}) . "\n" if $cmdLineOptions{verbose} >= 2;
+
+ if ( defined($sha1) && $sha1 && $userData{$uid} && ( $sha1 eq $userData{$uid}->{password} ) ) {
+ print "authentication of $uid succeeded\n" if $cmdLineOptions{verbose} >= 1;
+ return({
+ 'matchedDN' => "dn=$uid,ou=People,dc=nodomain",
+ 'errorMessage' => '',
+ 'resultCode' => LDAP_SUCCESS
+ });
+ }
+ else {
+ print "authentication of $uid failed\n" if $cmdLineOptions{verbose} >= 1;
+ return({
+ 'matchedDN' => '',
+ 'errorMessage' => '',
+ 'resultCode' => LDAP_INVALID_CREDENTIALS
+ });
+ }
+}
+
+sub search {
+ my $self = shift;
+ my ($reqData, $fullRequest) = @_;
+ print "search called\n" if $cmdLineOptions{verbose} >= 1;
+ print Dumper($reqData) if $cmdLineOptions{verbose} >= 2;
+ my @entries;
+ if ( $reqData->{baseObject} eq 'ou=People,dc=nodomain' ) {
+ my $uid = $reqData->{filter}->{equalityMatch}->{assertionValue};
+ push @entries, Net::LDAP::Entry->new ( "dn=$uid,ou=People,dc=nodomain",
+ , 'objectName'=>"dn=uid,ou=People,dc=nodomain", 'uid'=>$uid, 'mail'=>$userData{$uid}->{email}, 'displayName'=>$userData{$uid}->{displayName});
+ }
+ elsif ( $reqData->{baseObject} eq 'ou=Group,dc=nodomain' ) {
+ push @entries, Net::LDAP::Entry->new ( 'dn=Users,ou=Group,dc=nodomain',
+ , 'objectName'=>'dn=Users,ou=Group,dc=nodomain');
+ }
+
+ return {
+ 'matchedDN' => '',
+ 'errorMessage' => '',
+ 'resultCode' => LDAP_SUCCESS
+ }, @entries;
+}
+
+
+package main;
+
+use Digest::SHA1 qw(sha1 sha1_hex sha1_base64);
+
+sub exitWithError {
+ my $msg = shift;
+ print STDERR $msg . "\n";
+ exit(1);
+}
+
+sub encryptpwd {
+ my ($uid, $passwd) = @_;
+ # Use the user id to compute the hash, to avoid rainbox table attacks
+ return sha1_hex($uid.$passwd);
+}
+
+my $result = Getopt::Long::GetOptions (
+ "port=i" => \$cmdLineOptions{port},
+ "datafile=s" => \$cmdLineOptions{datafile},
+ "email=s" => \$cmdLineOptions{email},
+ "displayname=s" => \$cmdLineOptions{displayName},
+ "username=s" => \$cmdLineOptions{userName},
+ "password=s" => \$cmdLineOptions{password},
+ "verbose=i" => \$cmdLineOptions{verbose},
+);
+exitWithError("Failed to parse command line arguments") if ! $result;
+exitWithError("Please provide a valid path for the datafile") if ! $cmdLineOptions{datafile};
+
+my @commands = qw(start edituser);
+if ( @ARGV != 1 || ! grep {$_ eq $ARGV[0]} @commands ) {
+ exitWithError("Please provide a valid command among: " . join(",", @commands));
+}
+
+my $command = $ARGV[0];
+if ( $command eq "start") {
+ startServer();
+}
+elsif ( $command eq "edituser") {
+ editUser();
+}
+
+
+sub startServer() {
+
+ my $port = $cmdLineOptions{port} || $defaultport;
+
+ print "starting on port $port\n" if $cmdLineOptions{verbose} >= 1;
+
+ my $sock = IO::Socket::INET->new(
+ Listen => 5,
+ Proto => 'tcp',
+ Reuse => 1,
+ LocalAddr => "localhost", # Comment this line if Gerrit doesn't run on this host
+ LocalPort => $port
+ );
+
+ my $sel = IO::Select->new($sock);
+ my %Handlers;
+ while (my @ready = $sel->can_read) {
+ foreach my $fh (@ready) {
+ if ($fh == $sock) {
+ # Make sure the data is up to date on new every connection
+ readUserData();
+
+ # let's create a new socket
+ my $psock = $sock->accept;
+ $sel->add($psock);
+ $Handlers{*$psock} = MyServer->new($psock);
+ } else {
+ my $result = $Handlers{*$fh}->handle;
+ if ($result) {
+ # we have finished with the socket
+ $sel->remove($fh);
+ $fh->close;
+ delete $Handlers{*$fh};
+ }
+ }
+ }
+ }
+}
+
+sub readUserData {
+ %userData = ();
+ open (MYFILE, "<$cmdLineOptions{datafile}") || exitWithError("Could not open \"$cmdLineOptions{datafile}\" for reading");
+ while (<MYFILE>) {
+ chomp;
+ my @fields = split(/:/, $_);
+ $userData{$fields[0]} = { password=>$fields[1], displayName=>$fields[2], email=>$fields[3] };
+ }
+ close (MYFILE);
+}
+
+sub writeUserData {
+ open (MYFILE, ">$cmdLineOptions{datafile}") || exitWithError("Could not open \"$cmdLineOptions{datafile}\" for writing");
+ foreach my $userid (sort(keys(%userData))) {
+ my $userInfo = $userData{$userid};
+ print MYFILE join(":",
+ $userid,
+ $userInfo->{password},
+ $userInfo->{displayName},
+ $userInfo->{email}
+ ). "\n";
+ }
+ close (MYFILE);
+}
+
+sub readPassword {
+ Term::ReadKey::ReadMode('noecho');
+ my $password = Term::ReadKey::ReadLine(0);
+ Term::ReadKey::ReadMode('normal');
+ print "\n";
+ return $password;
+}
+
+sub readAndConfirmPassword {
+ print "Please enter the password: ";
+ my $pwd = readPassword();
+ print "Please re-enter the password: ";
+ my $pwdCheck = readPassword();
+ exitWithError("The passwords are different") if $pwd ne $pwdCheck;
+ return $pwd;
+}
+
+sub editUser {
+ exitWithError("Please provide a valid user name") if ! $cmdLineOptions{userName};
+ my $userName = $cmdLineOptions{userName};
+
+ readUserData() if -r $cmdLineOptions{datafile};
+
+ my $encryptedPassword = undef;
+ if ( ! defined($userData{$userName}) ) {
+ # New user
+
+ exitWithError("Please provide a valid display name") if ! $cmdLineOptions{displayName};
+ exitWithError("Please provide a valid email") if ! $cmdLineOptions{email};
+
+ $userData{$userName} = { };
+
+ if ( ! defined($cmdLineOptions{password}) ) {
+ # No password provided on the command line. Force reading from terminal.
+ $cmdLineOptions{password} = "";
+ }
+ }
+
+ if ( defined($cmdLineOptions{password}) && ! $cmdLineOptions{password} ) {
+ $cmdLineOptions{password} = readAndConfirmPassword();
+ exitWithError("Please provide a non empty password") if ! $cmdLineOptions{password};
+ }
+
+
+ if ( $cmdLineOptions{password} ) {
+ $encryptedPassword = encryptpwd($userName, $cmdLineOptions{password});
+ }
+
+
+ $userData{$userName}->{password} = $encryptedPassword if $encryptedPassword;
+ $userData{$userName}->{displayName} = $cmdLineOptions{displayName} if $cmdLineOptions{displayName};
+ $userData{$userName}->{email} = $cmdLineOptions{email} if $cmdLineOptions{email};
+ # print Data::Dumper::Dumper(\%userData);
+
+ print "New user data for $cmdLineOptions{userName}:\n";
+ foreach ( sort(keys(%{$userData{$userName}}))) {
+ printf " %-15s : %s\n", $_, $userData{$userName}->{$_}
+ }
+ writeUserData();
+}
\ No newline at end of file
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java
index 81d4fc9..67e9de6 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java
@@ -28,7 +28,7 @@
* has this capability can perform almost any other action, or can grant
* themselves the power to perform any other action on the site. Most of
* the other capabilities and permissions fall-back to the predicate
- * "OR user has capablity ADMINISTRATE_SERVER".
+ * "OR user has capability ADMINISTRATE_SERVER".
*/
public static final String ADMINISTRATE_SERVER = "administrateServer";
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.java
index e559d38..e30c366 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.java
@@ -14,6 +14,7 @@
package com.google.gerrit.client;
+import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
@@ -35,11 +36,14 @@
Label userEmail;
@UiField
Anchor logout;
+ @UiField
+ Anchor settings;
public CurrentUserPopupPanel(Account account, boolean canLogOut) {
super(/* auto hide */true, /* modal */false);
setWidget(binder.createAndBindUi(this));
setStyleName(Gerrit.RESOURCES.css().userInfoPopup());
+ settings.setHref(Gerrit.selfRedirect(PageLinks.SETTINGS));
if (account.getFullName() != null) {
userName.setText(account.getFullName());
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.ui.xml
index a50f11c..4dbfc23 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.ui.xml
@@ -18,7 +18,6 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:with field='constants' type='com.google.gerrit.client.GerritConstants'/>
- <ui:import field='com.google.gerrit.common.PageLinks.SETTINGS'/>
<ui:style>
.panel {
@@ -39,7 +38,7 @@
<g:FlowPanel styleName="{style.panel}">
<g:Label ui:field='userName' styleName="{style.userName}" />
<g:Label ui:field='userEmail' styleName="{style.email}" />
- <g:Anchor href='{SETTINGS}'>
+ <g:Anchor ui:field='settings'>
<ui:text from='{constants.menuSettings}' />
</g:Anchor>
<g:Anchor ui:field='logout' styleName="{style.logout}">
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
index d7db9ac..e72e127 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
@@ -434,8 +434,8 @@
}
c = dashboardId.indexOf(":");
if (0 <= c) {
- final String ref = URL.decode(dashboardId.substring(0, c));
- final String path = URL.decode(dashboardId.substring(c + 1));
+ final String ref = URL.decodeQueryString(dashboardId.substring(0, c));
+ final String path = URL.decodeQueryString(dashboardId.substring(c + 1));
DashboardList.get(new Project.NameKey(project), ref + ":" + path, cb);
return;
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardList.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardList.java
index f4da5fa..2fb4c17 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardList.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardList.java
@@ -50,11 +50,11 @@
private static String encodeDashboardId(String dashboardId) {
int c = dashboardId.indexOf(":");
if (0 <= c) {
- final String ref = URL.encode(dashboardId.substring(0, c));
- final String path = URL.encode(dashboardId.substring(c + 1));
+ final String ref = URL.encodeQueryString(dashboardId.substring(0, c));
+ final String path = URL.encodeQueryString(dashboardId.substring(c + 1));
return ref + ":" + path;
} else {
- return URL.encode(dashboardId);
+ return URL.encodeQueryString(dashboardId);
}
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java
index 546ac71..dad9b80 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java
@@ -289,6 +289,7 @@
ReceiveCommits rc = (ReceiveCommits) request.getAttribute(ATT_RC);
ReceivePack rp = rc.getReceivePack();
+ rp.getAdvertiseRefsHook().advertiseRefs(rp);
ProjectControl pc = (ProjectControl) request.getAttribute(ATT_CONTROL);
Project.NameKey projectName = pc.getProject().getNameKey();
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
index 2b00cc7..5667996 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
@@ -39,6 +39,7 @@
import com.google.inject.servlet.ServletModule;
import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Constants;
import java.io.IOException;
@@ -173,8 +174,9 @@
while (name.endsWith("/")) {
name = name.substring(0, name.length() - 1);
}
- if (name.endsWith(".git")) {
- name = name.substring(0, name.length() - 4);
+ if (name.endsWith(Constants.DOT_GIT_EXT)) {
+ name = name.substring(0, //
+ name.length() - Constants.DOT_GIT_EXT.length());
}
while (name.endsWith("/")) {
name = name.substring(0, name.length() - 1);
diff --git a/gerrit-package-plugins/pom.xml b/gerrit-package-plugins/pom.xml
index 5a4cdbb..9f11bb3 100644
--- a/gerrit-package-plugins/pom.xml
+++ b/gerrit-package-plugins/pom.xml
@@ -43,7 +43,7 @@
<dependency>
<groupId>com.googlesource.gerrit.plugins.replication</groupId>
<artifactId>replication</artifactId>
- <version>1.0</version>
+ <version>1.0-rc0</version>
<scope>provided</scope>
</dependency>
</dependencies>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/args4j/ProjectControlHandler.java b/gerrit-server/src/main/java/com/google/gerrit/server/args4j/ProjectControlHandler.java
index da033e7..836f246 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/args4j/ProjectControlHandler.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/args4j/ProjectControlHandler.java
@@ -20,6 +20,7 @@
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
+import org.eclipse.jgit.lib.Constants;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.OptionDef;
@@ -42,23 +43,12 @@
@Override
public final int parseArguments(final Parameters params)
throws CmdLineException {
- final String token = params.getParameter(0);
- String projectName = token;
+ String projectName = params.getParameter(0);
while (projectName.endsWith("/")) {
projectName = projectName.substring(0, projectName.length() - 1);
}
- if (projectName.endsWith(".git")) {
- // Be nice and drop the trailing ".git" suffix, which we never keep
- // in our database, but clients might mistakenly provide anyway.
- //
- projectName = projectName.substring(0, projectName.length() - 4);
- while (projectName.endsWith("/")) {
- projectName = projectName.substring(0, projectName.length() - 1);
- }
- }
-
while (projectName.startsWith("/")) {
// Be nice and drop the leading "/" if supplied by an absolute path.
// We don't have a file system hierarchy, just a flat namespace in
@@ -68,12 +58,25 @@
projectName = projectName.substring(1);
}
+ String nameWithoutSuffix = projectName;
+ if (nameWithoutSuffix.endsWith(Constants.DOT_GIT_EXT)) {
+ // Be nice and drop the trailing ".git" suffix, which we never keep
+ // in our database, but clients might mistakenly provide anyway.
+ //
+ nameWithoutSuffix = nameWithoutSuffix.substring(0, //
+ nameWithoutSuffix.length() - Constants.DOT_GIT_EXT.length());
+ while (nameWithoutSuffix.endsWith("/")) {
+ nameWithoutSuffix =
+ nameWithoutSuffix.substring(0, nameWithoutSuffix.length() - 1);
+ }
+ }
+
final ProjectControl control;
try {
- Project.NameKey nameKey = new Project.NameKey(projectName);
+ Project.NameKey nameKey = new Project.NameKey(nameWithoutSuffix);
control = projectControlFactory.validateFor(nameKey, ProjectControl.OWNER | ProjectControl.VISIBLE);
} catch (NoSuchProjectException e) {
- throw new CmdLineException(owner, "'" + token + "': not a Gerrit project");
+ throw new CmdLineException(owner, "'" + projectName + "': is not a Gerrit project");
}
setter.addValue(control);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 578fcc0..5ec33a3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -159,6 +159,7 @@
+ "To push into this reference you need 'Push' rights."),
DELETE("You need 'Push' rights with the 'Force Push'\n"
+ "flag set to delete references."),
+ DELETE_CHANGES("Cannot delete from 'refs/changes'"),
CODE_REVIEW("You need 'Push' rights to upload code review requests.\n"
+ "Verify that you are pushing to the right branch."),
CREATE("You are not allowed to perform this operation.\n"
@@ -947,7 +948,10 @@
private void parseDelete(final ReceiveCommand cmd) {
RefControl ctl = projectControl.controlForRef(cmd.getRefName());
- if (ctl.canDelete()) {
+ if (ctl.getRefName().startsWith("refs/changes/")) {
+ errors.put(Error.DELETE_CHANGES, ctl.getRefName());
+ reject(cmd, "cannot delete changes");
+ } else if (ctl.canDelete()) {
batch.addCommand(cmd);
} else {
if (GitRepositoryManager.REF_CONFIG.equals(ctl.getRefName())) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java
index 380b40b..3561c0c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java
@@ -81,7 +81,7 @@
final Change c, final String mc) {
super(ea, anonymousCowardName, mc);
change = c;
- changeData = change != null ? new ChangeData(change) : null;
+ changeData = new ChangeData(change);
emailOnlyAuthors = false;
}
@@ -208,7 +208,7 @@
/** Get a link to the change; null if the server doesn't know its own address. */
public String getChangeUrl() {
- if (change != null && getGerritUrl() != null) {
+ if (getGerritUrl() != null) {
final StringBuilder r = new StringBuilder();
r.append(getGerritUrl());
r.append(change.getChangeId());
@@ -356,10 +356,6 @@
/** Returns all watches that are relevant */
protected final Watchers getWatches(NotifyType type) throws OrmException {
Watchers matching = new Watchers();
- if (changeData == null) {
- return matching;
- }
-
Set<Account.Id> projectWatchers = new HashSet<Account.Id>();
for (AccountProjectWatch w : args.db.get().accountProjectWatches()
@@ -545,7 +541,6 @@
protected boolean isVisibleTo(final Account.Id to) throws OrmException {
return projectState == null
- || change == null
|| projectState.controlFor(args.identifiedUserFactory.create(to))
.controlFor(change).isVisible(args.db.get());
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java
index 3ff2c2a..20c2e15 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java
@@ -73,7 +73,6 @@
private boolean isOwnerOfProjectOrBranch(Account.Id user) {
return projectState != null
- && change != null
&& projectState.controlFor(args.identifiedUserFactory.create(user))
.controlForRef(change.getDest())
.isOwner();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
index d27c205..bb231a5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
@@ -278,7 +278,11 @@
try {
couldMerge = m.merge(b.getParents());
} catch (IOException e) {
- //
+ // It is not safe to continue further down in this method as throwing
+ // an exception most likely means that the merge tree was not created
+ // and m.getMergeResults() is empty. This would mean that all paths are
+ // unmerged and Gerrit UI would show all paths in the patch list.
+ return null;
}
if (couldMerge) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java
index 5049e9f..67a6d20 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java
@@ -229,7 +229,6 @@
private Injector newRootInjector(final PluginGuiceEnvironment env) {
List<Module> modules = Lists.newArrayListWithCapacity(4);
- modules.add(env.getSysModule());
if (apiType == ApiType.PLUGIN) {
modules.add(env.getSysModule());
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index 4e6f626..229b062 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -58,6 +58,7 @@
private Boolean owner;
private Boolean canForgeAuthor;
private Boolean canForgeCommitter;
+ private Boolean isVisible;
RefControl(ProjectControl projectControl, String ref,
PermissionCollection relevant) {
@@ -103,8 +104,12 @@
/** Can this user see this reference exists? */
public boolean isVisible() {
- return (getCurrentUser() instanceof InternalUser || canPerform(Permission.READ))
- && canRead();
+ if (isVisible == null) {
+ isVisible =
+ (getCurrentUser() instanceof InternalUser || canPerform(Permission.READ))
+ && canRead();
+ }
+ return isVisible;
}
/**
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/SubmoduleSectionParser.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/SubmoduleSectionParser.java
index df2e123..fbd8236 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/util/SubmoduleSectionParser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/SubmoduleSectionParser.java
@@ -103,8 +103,9 @@
fromIndex = urlExtractedPath.lastIndexOf('/', fromIndex - 1);
projectName = urlExtractedPath.substring(fromIndex + 1);
- if (projectName.endsWith(".git")) {
- projectName = projectName.substring(0, projectName.length() - 4);
+ if (projectName.endsWith(Constants.DOT_GIT_EXT)) {
+ projectName = projectName.substring(0, //
+ projectName.length() - Constants.DOT_GIT_EXT.length());
}
if (repoManager.list().contains(new Project.NameKey(projectName))) {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java
index 93d86e5..7294d4c 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java
@@ -27,6 +27,7 @@
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
import org.eclipse.jgit.lib.BlobBasedConfig;
+import org.eclipse.jgit.lib.Constants;
import org.junit.Before;
import org.junit.Test;
@@ -214,8 +215,9 @@
while (fromIndex > 0) {
fromIndex = urlExtractedPath.lastIndexOf('/', fromIndex - 1);
projectNameCandidate = urlExtractedPath.substring(fromIndex + 1);
- if (projectNameCandidate.endsWith(".git")) {
- projectNameCandidate = projectNameCandidate.substring(0, projectNameCandidate.length() - 4);
+ if (projectNameCandidate.endsWith(Constants.DOT_GIT_EXT)) {
+ projectNameCandidate = projectNameCandidate.substring(0, //
+ projectNameCandidate.length() - Constants.DOT_GIT_EXT.length());
}
if (projectNameCandidate.equals(reposToBeFound.get(id))) {
expect(repoManager.list()).andReturn(