Merge branch 'master' into gwt-2.0
* master: Fix reading the $site_path/etc/ssh_host_key in serialized form Never compress a pid file under $site_path/logs Clean up the DWIMery for database.* configuration settings Completely remove GerritServer.properties Fix duplicate branches showing in the Branches tab Refactor GitRepositoryManager to be an interface Conflicts: tools/gwtui_dbg.launch tools/gwtui_mac.launch Change-Id: If50811015fa24804013338fa4261fc347c2a8812
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
/.project
|
/.project
|
||||||
/.settings/org.maven.ide.eclipse.prefs
|
/.settings/org.maven.ide.eclipse.prefs
|
||||||
/GerritServer.properties
|
|
||||||
/test_site
|
/test_site
|
||||||
|
@@ -531,7 +531,7 @@ records about user accounts and change reviews.
|
|||||||
|
|
||||||
----
|
----
|
||||||
[database]
|
[database]
|
||||||
type = postgres
|
type = POSTGRESQL
|
||||||
hostname = localhost
|
hostname = localhost
|
||||||
database = reviewdb
|
database = reviewdb
|
||||||
username = gerrit2
|
username = gerrit2
|
||||||
@@ -544,17 +544,21 @@ Type of database server to connect to. If set this value will be
|
|||||||
used to automatically create correct database.driver and database.url
|
used to automatically create correct database.driver and database.url
|
||||||
values to open the connection.
|
values to open the connection.
|
||||||
+
|
+
|
||||||
* `Postgres` or `PostgreSQL`
|
* `POSTGRESQL`
|
||||||
+
|
+
|
||||||
Connect to a PostgreSQL database server.
|
Connect to a PostgreSQL database server.
|
||||||
+
|
+
|
||||||
* `H2`
|
* `H2`
|
||||||
+
|
+
|
||||||
Connect to a local (or remote) H2 database.
|
Connect to a local embedded H2 database.
|
||||||
+
|
+
|
||||||
* `MySQL`
|
* `MYSQL`
|
||||||
+
|
+
|
||||||
Connect to a MySQL database server.
|
Connect to a MySQL database server.
|
||||||
|
+
|
||||||
|
* `JDBC`
|
||||||
|
+
|
||||||
|
Connect using a JDBC driver class name and URL.
|
||||||
|
|
||||||
+
|
+
|
||||||
If not specified, database.driver and database.url are used as-is,
|
If not specified, database.driver and database.url are used as-is,
|
||||||
@@ -571,10 +575,10 @@ of the server named by database.type.
|
|||||||
|
|
||||||
[[database.database]]database.database::
|
[[database.database]]database.database::
|
||||||
+
|
+
|
||||||
For PostgreSQL or MySQL, the name of the database on the server.
|
For POSTGRESQL or MYSQL, the name of the database on the server.
|
||||||
+
|
+
|
||||||
For H2, this is the path to the database, and if not absolute is
|
For H2, this is the path to the database, and if not absolute is
|
||||||
relative to `$site_path`.
|
relative to `'$site_path'`.
|
||||||
|
|
||||||
[[database.username]]database.username::
|
[[database.username]]database.username::
|
||||||
+
|
+
|
||||||
@@ -586,13 +590,15 @@ Password to authenticate to the database server with.
|
|||||||
|
|
||||||
[[database.driver]]database.driver::
|
[[database.driver]]database.driver::
|
||||||
+
|
+
|
||||||
Name of the JDBC driver class to connect to the database.
|
Name of the JDBC driver class to connect to the database with.
|
||||||
Setting this usually isn't necessary, set database.type instead.
|
Setting this usually isn't necessary as it can be derived from
|
||||||
|
database.type or database.url for any supported database.
|
||||||
|
|
||||||
[[database.url]]database.url::
|
[[database.url]]database.url::
|
||||||
+
|
+
|
||||||
JDBC style URL for the database. Setting this usually isn't
|
'jdbc:' URL for the database. Setting this variable usually
|
||||||
necessary, set database.type instead.
|
isn't necessary as it can be constructed from the all of the
|
||||||
|
above properties.
|
||||||
|
|
||||||
|
|
||||||
[[gerrit]]Section gerrit
|
[[gerrit]]Section gerrit
|
||||||
|
@@ -82,9 +82,9 @@ Duplicate the existing `pgm_daemon` launch configuration:
|
|||||||
* Modify the name to be unique.
|
* Modify the name to be unique.
|
||||||
|
|
||||||
* Switch to Arguments tab.
|
* Switch to Arguments tab.
|
||||||
* Edit the -d flag to match the path used during 'init'. The
|
* Edit the `-d` program argument flag to match the path used during
|
||||||
template launch configuration resolves to ../test_site since
|
'init'. The template launch configuration resolves to ../test_site
|
||||||
that is what the documentation recommends.
|
since that is what the documentation recommends.
|
||||||
|
|
||||||
* Switch to Common tab.
|
* Switch to Common tab.
|
||||||
* Change Save as to be Local file.
|
* Change Save as to be Local file.
|
||||||
@@ -93,12 +93,22 @@ Duplicate the existing `pgm_daemon` launch configuration:
|
|||||||
Running Hosted Mode
|
Running Hosted Mode
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* Copy
|
Duplicate the existing `gwtui_any` (or `gwtui_mac` if on Mac OS X)
|
||||||
`gerrit-war/src/main/webapp/WEB-INF/extra/GerritServer.properties_example`
|
launch configuration:
|
||||||
to
|
|
||||||
`gerrit-parent/GerritServer.properties`.
|
* Run -> Debug Configurations ...
|
||||||
* Edit to match your database parameters.
|
* Java Application -> `gwtui_any`
|
||||||
* Run the `gwtui_any` or `gwtui_mac` launch configuration.
|
* Right click, Duplicate
|
||||||
|
|
||||||
|
* Modify the name to be unique.
|
||||||
|
|
||||||
|
* Switch to Arguments tab.
|
||||||
|
* Edit the `-Dgerrit.site_path=` VM argument to match the path
|
||||||
|
used during 'init'. The template launch configuration resolves
|
||||||
|
to ../test_site since that is what the documentation recommends.
|
||||||
|
|
||||||
|
* Switch to Common tab.
|
||||||
|
* Change Save as to be Local file.
|
||||||
|
|
||||||
|
|
||||||
GERRIT
|
GERRIT
|
||||||
|
@@ -39,6 +39,11 @@ limitations under the License.
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jgit</groupId>
|
||||||
|
<artifactId>org.eclipse.jgit.junit</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.gwt</groupId>
|
<groupId>com.google.gwt</groupId>
|
||||||
<artifactId>gwt-servlet</artifactId>
|
<artifactId>gwt-servlet</artifactId>
|
||||||
|
@@ -34,7 +34,7 @@ import com.google.gerrit.httpd.GitWebConfig;
|
|||||||
import com.google.gerrit.reviewdb.Project;
|
import com.google.gerrit.reviewdb.Project;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
|
||||||
import com.google.gerrit.server.project.NoSuchProjectException;
|
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -77,12 +77,12 @@ class GitWebServlet extends HttpServlet {
|
|||||||
private final Set<String> deniedActions;
|
private final Set<String> deniedActions;
|
||||||
private final int bufferSize = 8192;
|
private final int bufferSize = 8192;
|
||||||
private final File gitwebCgi;
|
private final File gitwebCgi;
|
||||||
private final GitRepositoryManager repoManager;
|
private final LocalDiskRepositoryManager repoManager;
|
||||||
private final ProjectControl.Factory projectControl;
|
private final ProjectControl.Factory projectControl;
|
||||||
private final EnvList _env;
|
private final EnvList _env;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GitWebServlet(final GitRepositoryManager repoManager,
|
GitWebServlet(final LocalDiskRepositoryManager repoManager,
|
||||||
final ProjectControl.Factory projectControl,
|
final ProjectControl.Factory projectControl,
|
||||||
final SitePaths site, final GerritConfig gerritConfig,
|
final SitePaths site, final GerritConfig gerritConfig,
|
||||||
final GitWebConfig gitWebConfig) throws IOException {
|
final GitWebConfig gitWebConfig) throws IOException {
|
||||||
|
@@ -64,6 +64,7 @@ class ListBranches extends Handler<List<Branch>> {
|
|||||||
| ProjectControl.VISIBLE);
|
| ProjectControl.VISIBLE);
|
||||||
|
|
||||||
final List<Branch> branches = new ArrayList<Branch>();
|
final List<Branch> branches = new ArrayList<Branch>();
|
||||||
|
Branch headBranch = null;
|
||||||
final Repository db = repoManager.openRepository(projectName.get());
|
final Repository db = repoManager.openRepository(projectName.get());
|
||||||
try {
|
try {
|
||||||
final Map<String, Ref> all = db.getAllRefs();
|
final Map<String, Ref> all = db.getAllRefs();
|
||||||
@@ -84,14 +85,18 @@ class ListBranches extends Handler<List<Branch>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Ref ref : all.values()) {
|
for (final Ref ref : all.values()) {
|
||||||
if (Constants.HEAD.equals(ref.getOrigName())) {
|
if (Constants.HEAD.equals(ref.getOrigName())
|
||||||
final Branch b = createBranch(Constants.HEAD);
|
&& !ref.getOrigName().equals(ref.getName())) {
|
||||||
|
// HEAD is a symbolic reference to another branch, instead of
|
||||||
|
// showing the resolved value, show the name it references.
|
||||||
|
//
|
||||||
|
headBranch = createBranch(Constants.HEAD);
|
||||||
String target = ref.getName();
|
String target = ref.getName();
|
||||||
if (target.startsWith(Constants.R_HEADS)) {
|
if (target.startsWith(Constants.R_HEADS)) {
|
||||||
target = target.substring(Constants.R_HEADS.length());
|
target = target.substring(Constants.R_HEADS.length());
|
||||||
}
|
}
|
||||||
b.setRevision(new RevId(target));
|
headBranch.setRevision(new RevId(target));
|
||||||
branches.add(b);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ref.getName().startsWith(Constants.R_HEADS)) {
|
if (ref.getName().startsWith(Constants.R_HEADS)) {
|
||||||
@@ -111,6 +116,9 @@ class ListBranches extends Handler<List<Branch>> {
|
|||||||
return a.getName().compareTo(b.getName());
|
return a.getName().compareTo(b.getName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (headBranch != null) {
|
||||||
|
branches.add(0, headBranch);
|
||||||
|
}
|
||||||
return branches;
|
return branches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,239 @@
|
|||||||
|
// 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.httpd.rpc.project;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.eq;
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.EasyMock.expectLastCall;
|
||||||
|
import static org.easymock.classextension.EasyMock.createStrictMock;
|
||||||
|
import static org.easymock.classextension.EasyMock.replay;
|
||||||
|
import static org.easymock.classextension.EasyMock.verify;
|
||||||
|
import static org.eclipse.jgit.lib.Constants.HEAD;
|
||||||
|
import static org.eclipse.jgit.lib.Constants.R_HEADS;
|
||||||
|
|
||||||
|
import com.google.gerrit.reviewdb.Branch;
|
||||||
|
import com.google.gerrit.reviewdb.Project;
|
||||||
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
|
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||||
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
|
import com.google.gwtorm.client.KeyUtil;
|
||||||
|
import com.google.gwtorm.server.StandardKeyEncoder;
|
||||||
|
|
||||||
|
import org.easymock.IExpectationSetters;
|
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.lib.RefUpdate;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ListBranchesTest extends LocalDiskRepositoryTestCase {
|
||||||
|
static {
|
||||||
|
KeyUtil.setEncoderImpl(new StandardKeyEncoder());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObjectId idA;
|
||||||
|
private Project.NameKey name;
|
||||||
|
private Repository realDb;
|
||||||
|
private Repository mockDb;
|
||||||
|
private ProjectControl.Factory pcf;
|
||||||
|
private ProjectControl pc;
|
||||||
|
private GitRepositoryManager grm;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
idA = ObjectId.fromString("df84c2f4f7ce7e0b25cdeac84b8870bcff319885");
|
||||||
|
name = new Project.NameKey("test");
|
||||||
|
realDb = createBareRepository();
|
||||||
|
|
||||||
|
mockDb = createStrictMock(Repository.class);
|
||||||
|
pc = createStrictMock(ProjectControl.class);
|
||||||
|
pcf = createStrictMock(ProjectControl.Factory.class);
|
||||||
|
grm = createStrictMock(GitRepositoryManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IExpectationSetters<ProjectControl> validate()
|
||||||
|
throws NoSuchProjectException {
|
||||||
|
return expect(pcf.validateFor(eq(name), //
|
||||||
|
eq(ProjectControl.OWNER | ProjectControl.VISIBLE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doReplay() {
|
||||||
|
replay(mockDb, pc, pcf, grm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doVerify() {
|
||||||
|
verify(mockDb, pc, pcf, grm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void set(String branch, ObjectId id) throws IOException {
|
||||||
|
final RefUpdate u = realDb.updateRef(R_HEADS + branch);
|
||||||
|
u.setForceUpdate(true);
|
||||||
|
u.setNewObjectId(id);
|
||||||
|
switch (u.update()) {
|
||||||
|
case NEW:
|
||||||
|
case FAST_FORWARD:
|
||||||
|
case FORCED:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fail("unexpected update failure " + branch + " " + u.getResult());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testProjectNotVisible() throws Exception {
|
||||||
|
final NoSuchProjectException err = new NoSuchProjectException(name);
|
||||||
|
validate().andThrow(err);
|
||||||
|
doReplay();
|
||||||
|
try {
|
||||||
|
new ListBranches(pcf, grm, name).call();
|
||||||
|
fail("did not throw when expected not authorized");
|
||||||
|
} catch (NoSuchProjectException e2) {
|
||||||
|
assertSame(err, e2);
|
||||||
|
}
|
||||||
|
doVerify();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<Branch> permitted(boolean getFullBranch)
|
||||||
|
throws NoSuchProjectException, IOException {
|
||||||
|
validate().andReturn(pc);
|
||||||
|
expect(grm.openRepository(eq(name.get()))).andReturn(mockDb);
|
||||||
|
expect(mockDb.getAllRefs()).andDelegateTo(realDb);
|
||||||
|
if (getFullBranch) {
|
||||||
|
expect(mockDb.getFullBranch()).andDelegateTo(realDb);
|
||||||
|
}
|
||||||
|
mockDb.close();
|
||||||
|
expectLastCall();
|
||||||
|
|
||||||
|
doReplay();
|
||||||
|
final List<Branch> r = new ListBranches(pcf, grm, name).call();
|
||||||
|
doVerify();
|
||||||
|
assertNotNull(r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testEmptyProject() throws Exception {
|
||||||
|
List<Branch> r = permitted(true);
|
||||||
|
assertEquals(1, r.size());
|
||||||
|
|
||||||
|
Branch b = r.get(0);
|
||||||
|
assertNotNull(b);
|
||||||
|
|
||||||
|
assertNotNull(b.getNameKey());
|
||||||
|
assertSame(name, b.getNameKey().getParentKey());
|
||||||
|
assertEquals(HEAD, b.getNameKey().get());
|
||||||
|
|
||||||
|
assertEquals(HEAD, b.getName());
|
||||||
|
assertEquals(HEAD, b.getShortName());
|
||||||
|
|
||||||
|
assertNotNull(b.getRevision());
|
||||||
|
assertEquals("master", b.getRevision().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMasterBranch() throws Exception {
|
||||||
|
set("master", idA);
|
||||||
|
|
||||||
|
List<Branch> r = permitted(false);
|
||||||
|
assertEquals(2, r.size());
|
||||||
|
|
||||||
|
Branch b = r.get(0);
|
||||||
|
assertNotNull(b);
|
||||||
|
|
||||||
|
assertNotNull(b.getNameKey());
|
||||||
|
assertSame(name, b.getNameKey().getParentKey());
|
||||||
|
assertEquals(HEAD, b.getNameKey().get());
|
||||||
|
|
||||||
|
assertEquals(HEAD, b.getName());
|
||||||
|
assertEquals(HEAD, b.getShortName());
|
||||||
|
|
||||||
|
assertNotNull(b.getRevision());
|
||||||
|
assertEquals("master", b.getRevision().get());
|
||||||
|
|
||||||
|
b = r.get(1);
|
||||||
|
assertNotNull(b);
|
||||||
|
|
||||||
|
assertNotNull(b.getNameKey());
|
||||||
|
assertSame(name, b.getNameKey().getParentKey());
|
||||||
|
assertEquals(R_HEADS + "master", b.getNameKey().get());
|
||||||
|
|
||||||
|
assertEquals(R_HEADS + "master", b.getName());
|
||||||
|
assertEquals("master", b.getShortName());
|
||||||
|
|
||||||
|
assertNotNull(b.getRevision());
|
||||||
|
assertEquals(idA.name(), b.getRevision().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBranchNotHead() throws Exception {
|
||||||
|
set("foo", idA);
|
||||||
|
|
||||||
|
List<Branch> r = permitted(true);
|
||||||
|
assertEquals(2, r.size());
|
||||||
|
|
||||||
|
Branch b = r.get(0);
|
||||||
|
assertNotNull(b);
|
||||||
|
|
||||||
|
assertNotNull(b.getNameKey());
|
||||||
|
assertSame(name, b.getNameKey().getParentKey());
|
||||||
|
assertEquals(HEAD, b.getNameKey().get());
|
||||||
|
|
||||||
|
assertEquals(HEAD, b.getName());
|
||||||
|
assertEquals(HEAD, b.getShortName());
|
||||||
|
|
||||||
|
assertNotNull(b.getRevision());
|
||||||
|
assertEquals("master", b.getRevision().get());
|
||||||
|
|
||||||
|
b = r.get(1);
|
||||||
|
assertNotNull(b);
|
||||||
|
|
||||||
|
assertNotNull(b.getNameKey());
|
||||||
|
assertSame(name, b.getNameKey().getParentKey());
|
||||||
|
assertEquals(R_HEADS + "foo", b.getNameKey().get());
|
||||||
|
|
||||||
|
assertEquals(R_HEADS + "foo", b.getName());
|
||||||
|
assertEquals("foo", b.getShortName());
|
||||||
|
|
||||||
|
assertNotNull(b.getRevision());
|
||||||
|
assertEquals(idA.name(), b.getRevision().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSortByName() throws Exception {
|
||||||
|
Map<String, Ref> u = new LinkedHashMap<String, Ref>();
|
||||||
|
u.put("foo", new Ref(Ref.Storage.LOOSE, R_HEADS + "foo", idA));
|
||||||
|
u.put("bar", new Ref(Ref.Storage.LOOSE, R_HEADS + "bar", idA));
|
||||||
|
u.put(HEAD, new Ref(Ref.Storage.LOOSE, HEAD, R_HEADS + "master", null));
|
||||||
|
|
||||||
|
validate().andReturn(pc);
|
||||||
|
expect(grm.openRepository(eq(name.get()))).andReturn(mockDb);
|
||||||
|
expect(mockDb.getAllRefs()).andReturn(u);
|
||||||
|
mockDb.close();
|
||||||
|
expectLastCall();
|
||||||
|
|
||||||
|
doReplay();
|
||||||
|
final List<Branch> r = new ListBranches(pcf, grm, name).call();
|
||||||
|
doVerify();
|
||||||
|
assertNotNull(r);
|
||||||
|
|
||||||
|
assertEquals(3, r.size());
|
||||||
|
assertEquals(HEAD, r.get(0).getShortName());
|
||||||
|
assertEquals("bar", r.get(1).getShortName());
|
||||||
|
assertEquals("foo", r.get(2).getShortName());
|
||||||
|
}
|
||||||
|
}
|
@@ -38,11 +38,6 @@ limitations under the License.
|
|||||||
<artifactId>log4j</artifactId>
|
<artifactId>log4j</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-dbcp</groupId>
|
|
||||||
<artifactId>commons-dbcp</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.pgm;
|
package com.google.gerrit.pgm;
|
||||||
|
|
||||||
import static com.google.gerrit.pgm.util.DataSourceProvider.Context.MULTI_USER;
|
import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
|
||||||
|
|
||||||
import com.google.gerrit.httpd.HttpCanonicalWebUrlProvider;
|
import com.google.gerrit.httpd.HttpCanonicalWebUrlProvider;
|
||||||
import com.google.gerrit.httpd.WebModule;
|
import com.google.gerrit.httpd.WebModule;
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.pgm;
|
package com.google.gerrit.pgm;
|
||||||
|
|
||||||
import static com.google.gerrit.pgm.util.DataSourceProvider.Context.SINGLE_USER;
|
import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;
|
||||||
|
|
||||||
import com.google.gerrit.lifecycle.LifecycleManager;
|
import com.google.gerrit.lifecycle.LifecycleManager;
|
||||||
import com.google.gerrit.pgm.util.RuntimeShutdown;
|
import com.google.gerrit.pgm.util.RuntimeShutdown;
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.pgm;
|
package com.google.gerrit.pgm;
|
||||||
|
|
||||||
import static com.google.gerrit.pgm.util.DataSourceProvider.Context.SINGLE_USER;
|
import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;
|
||||||
import static com.google.inject.Stage.PRODUCTION;
|
import static com.google.inject.Stage.PRODUCTION;
|
||||||
|
|
||||||
import com.google.gerrit.common.PageLinks;
|
import com.google.gerrit.common.PageLinks;
|
||||||
@@ -30,6 +30,7 @@ import com.google.gerrit.pgm.util.IoUtil;
|
|||||||
import com.google.gerrit.pgm.util.SiteProgram;
|
import com.google.gerrit.pgm.util.SiteProgram;
|
||||||
import com.google.gerrit.server.config.SitePath;
|
import com.google.gerrit.server.config.SitePath;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
|
||||||
import com.google.gerrit.server.git.GitProjectImporter;
|
import com.google.gerrit.server.git.GitProjectImporter;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gerrit.server.schema.SchemaUpdater;
|
import com.google.gerrit.server.schema.SchemaUpdater;
|
||||||
@@ -176,13 +177,17 @@ public class Init extends SiteProgram {
|
|||||||
|
|
||||||
void importGit() throws OrmException, IOException {
|
void importGit() throws OrmException, IOException {
|
||||||
if (flags.importProjects) {
|
if (flags.importProjects) {
|
||||||
System.err.println("Scanning " + repositoryManager.getBasePath());
|
|
||||||
gitProjectImporter.run(new GitProjectImporter.Messages() {
|
gitProjectImporter.run(new GitProjectImporter.Messages() {
|
||||||
@Override
|
@Override
|
||||||
public void warning(String msg) {
|
public void info(String msg) {
|
||||||
System.err.println(msg);
|
System.err.println(msg);
|
||||||
System.err.flush();
|
System.err.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warning(String msg) {
|
||||||
|
info(msg);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +252,7 @@ public class Init extends SiteProgram {
|
|||||||
bind(ConsoleUI.class).toInstance(init.ui);
|
bind(ConsoleUI.class).toInstance(init.ui);
|
||||||
bind(InitFlags.class).toInstance(init.flags);
|
bind(InitFlags.class).toInstance(init.flags);
|
||||||
|
|
||||||
bind(GitRepositoryManager.class);
|
bind(GitRepositoryManager.class).to(LocalDiskRepositoryManager.class);
|
||||||
bind(GitProjectImporter.class);
|
bind(GitProjectImporter.class);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -16,11 +16,11 @@ package com.google.gerrit.pgm.init;
|
|||||||
|
|
||||||
import static com.google.gerrit.pgm.init.InitUtil.die;
|
import static com.google.gerrit.pgm.init.InitUtil.die;
|
||||||
import static com.google.gerrit.pgm.init.InitUtil.username;
|
import static com.google.gerrit.pgm.init.InitUtil.username;
|
||||||
import static com.google.gerrit.pgm.util.DataSourceProvider.Type.H2;
|
import static com.google.gerrit.server.schema.DataSourceProvider.Type.H2;
|
||||||
|
|
||||||
import com.google.gerrit.pgm.util.ConsoleUI;
|
import com.google.gerrit.pgm.util.ConsoleUI;
|
||||||
import com.google.gerrit.pgm.util.DataSourceProvider;
|
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.gerrit.server.schema.DataSourceProvider;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
@@ -82,7 +82,6 @@ class InitDatabase implements InitStep {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case POSTGRES:
|
|
||||||
case POSTGRESQL:
|
case POSTGRESQL:
|
||||||
case MYSQL: {
|
case MYSQL: {
|
||||||
userPassAuth = true;
|
userPassAuth = true;
|
||||||
|
@@ -19,8 +19,8 @@ import static com.google.gerrit.pgm.init.InitUtil.savePublic;
|
|||||||
import static com.google.gerrit.pgm.init.InitUtil.saveSecure;
|
import static com.google.gerrit.pgm.init.InitUtil.saveSecure;
|
||||||
|
|
||||||
import com.google.gerrit.pgm.util.ConsoleUI;
|
import com.google.gerrit.pgm.util.ConsoleUI;
|
||||||
import com.google.gerrit.pgm.util.DataSourceProvider;
|
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.gerrit.server.schema.DataSourceProvider;
|
||||||
import com.google.gerrit.server.util.SocketUtil;
|
import com.google.gerrit.server.util.SocketUtil;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
@@ -96,7 +96,8 @@ public class LogFileCompressor implements Runnable {
|
|||||||
|
|
||||||
private boolean isLive(final File entry) {
|
private boolean isLive(final File entry) {
|
||||||
final String name = entry.getName();
|
final String name = entry.getName();
|
||||||
return ErrorLogFile.LOG_NAME.equals(name);
|
return ErrorLogFile.LOG_NAME.equals(name) //
|
||||||
|
|| name.endsWith(".pid");
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCompressed(final File entry) {
|
private boolean isCompressed(final File entry) {
|
||||||
|
@@ -21,6 +21,7 @@ import com.google.gerrit.lifecycle.LifecycleModule;
|
|||||||
import com.google.gerrit.server.config.DatabaseModule;
|
import com.google.gerrit.server.config.DatabaseModule;
|
||||||
import com.google.gerrit.server.config.GerritServerConfigModule;
|
import com.google.gerrit.server.config.GerritServerConfigModule;
|
||||||
import com.google.gerrit.server.config.SitePath;
|
import com.google.gerrit.server.config.SitePath;
|
||||||
|
import com.google.gerrit.server.schema.DataSourceProvider;
|
||||||
import com.google.gwtorm.client.OrmException;
|
import com.google.gwtorm.client.OrmException;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.CreationException;
|
import com.google.inject.CreationException;
|
||||||
|
@@ -48,6 +48,11 @@ limitations under the License.
|
|||||||
<artifactId>ehcache-core</artifactId>
|
<artifactId>ehcache-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-dbcp</groupId>
|
||||||
|
<artifactId>commons-dbcp</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-net</groupId>
|
<groupId>commons-net</groupId>
|
||||||
<artifactId>commons-net</artifactId>
|
<artifactId>commons-net</artifactId>
|
||||||
|
@@ -37,6 +37,7 @@ import com.google.gerrit.server.account.Realm;
|
|||||||
import com.google.gerrit.server.auth.ldap.LdapModule;
|
import com.google.gerrit.server.auth.ldap.LdapModule;
|
||||||
import com.google.gerrit.server.cache.CachePool;
|
import com.google.gerrit.server.cache.CachePool;
|
||||||
import com.google.gerrit.server.git.ChangeMergeQueue;
|
import com.google.gerrit.server.git.ChangeMergeQueue;
|
||||||
|
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gerrit.server.git.MergeOp;
|
import com.google.gerrit.server.git.MergeOp;
|
||||||
import com.google.gerrit.server.git.MergeQueue;
|
import com.google.gerrit.server.git.MergeQueue;
|
||||||
@@ -111,7 +112,7 @@ public class GerritGlobalModule extends FactoryModule {
|
|||||||
factory(AccountInfoCacheFactory.Factory.class);
|
factory(AccountInfoCacheFactory.Factory.class);
|
||||||
factory(ProjectState.Factory.class);
|
factory(ProjectState.Factory.class);
|
||||||
|
|
||||||
bind(GitRepositoryManager.class);
|
bind(GitRepositoryManager.class).to(LocalDiskRepositoryManager.class);
|
||||||
bind(FileTypeRegistry.class).to(MimeUtilFileTypeRegistry.class);
|
bind(FileTypeRegistry.class).to(MimeUtilFileTypeRegistry.class);
|
||||||
bind(WorkQueue.class);
|
bind(WorkQueue.class);
|
||||||
|
|
||||||
@@ -141,7 +142,7 @@ public class GerritGlobalModule extends FactoryModule {
|
|||||||
install(new LifecycleModule() {
|
install(new LifecycleModule() {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
listener().to(GitRepositoryManager.Lifecycle.class);
|
listener().to(LocalDiskRepositoryManager.Lifecycle.class);
|
||||||
listener().to(CachePool.Lifecycle.class);
|
listener().to(CachePool.Lifecycle.class);
|
||||||
listener().to(WorkQueue.Lifecycle.class);
|
listener().to(WorkQueue.Lifecycle.class);
|
||||||
}
|
}
|
||||||
|
@@ -32,15 +32,16 @@ import java.util.Set;
|
|||||||
/** Imports all projects found within the repository manager. */
|
/** Imports all projects found within the repository manager. */
|
||||||
public class GitProjectImporter {
|
public class GitProjectImporter {
|
||||||
public interface Messages {
|
public interface Messages {
|
||||||
|
void info(String msg);
|
||||||
void warning(String msg);
|
void warning(String msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final GitRepositoryManager repositoryManager;
|
private final LocalDiskRepositoryManager repositoryManager;
|
||||||
private final SchemaFactory<ReviewDb> schema;
|
private final SchemaFactory<ReviewDb> schema;
|
||||||
private Messages messages;
|
private Messages messages;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GitProjectImporter(final GitRepositoryManager repositoryManager,
|
GitProjectImporter(final LocalDiskRepositoryManager repositoryManager,
|
||||||
final SchemaFactory<ReviewDb> schema) {
|
final SchemaFactory<ReviewDb> schema) {
|
||||||
this.repositoryManager = repositoryManager;
|
this.repositoryManager = repositoryManager;
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
@@ -48,6 +49,7 @@ public class GitProjectImporter {
|
|||||||
|
|
||||||
public void run(final Messages msg) throws OrmException, IOException {
|
public void run(final Messages msg) throws OrmException, IOException {
|
||||||
messages = msg;
|
messages = msg;
|
||||||
|
messages.info("Scanning " + repositoryManager.getBasePath());
|
||||||
final ReviewDb db = schema.open();
|
final ReviewDb db = schema.open();
|
||||||
try {
|
try {
|
||||||
final HashSet<String> have = new HashSet<String>();
|
final HashSet<String> have = new HashSet<String>();
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2008 The Android Open Source Project
|
// Copyright (C) 2009 The Android Open Source Project
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -14,75 +14,22 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.git;
|
package com.google.gerrit.server.git;
|
||||||
|
|
||||||
import com.google.gerrit.lifecycle.LifecycleListener;
|
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
import org.eclipse.jgit.lib.Config;
|
|
||||||
import org.eclipse.jgit.lib.Constants;
|
|
||||||
import org.eclipse.jgit.lib.LockFile;
|
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.lib.RepositoryCache;
|
|
||||||
import org.eclipse.jgit.lib.WindowCache;
|
|
||||||
import org.eclipse.jgit.lib.WindowCacheConfig;
|
|
||||||
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
|
|
||||||
import org.eclipse.jgit.util.IO;
|
|
||||||
import org.eclipse.jgit.util.RawParseUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/** Class managing Git repositories. */
|
|
||||||
@Singleton
|
|
||||||
public class GitRepositoryManager {
|
|
||||||
private static final Logger log =
|
|
||||||
LoggerFactory.getLogger(GitRepositoryManager.class);
|
|
||||||
|
|
||||||
private static final String UNNAMED =
|
|
||||||
"Unnamed repository; edit this file to name it for gitweb.";
|
|
||||||
|
|
||||||
public static class Lifecycle implements LifecycleListener {
|
|
||||||
private final Config cfg;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
Lifecycle(@GerritServerConfig final Config cfg) {
|
|
||||||
this.cfg = cfg;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() {
|
|
||||||
final WindowCacheConfig c = new WindowCacheConfig();
|
|
||||||
c.fromConfig(cfg);
|
|
||||||
WindowCache.reconfigure(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final File basePath;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
GitRepositoryManager(final SitePaths site,
|
|
||||||
@GerritServerConfig final Config cfg) {
|
|
||||||
basePath = site.resolve(cfg.getString("gerrit", null, "basePath"));
|
|
||||||
if (basePath == null) {
|
|
||||||
throw new IllegalStateException("gerrit.basePath must be configured");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return base directory under which all projects are stored. */
|
|
||||||
public File getBasePath() {
|
|
||||||
return basePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages Git repositories for the Gerrit server process.
|
||||||
|
* <p>
|
||||||
|
* Implementations of this interface should be a {@link Singleton} and
|
||||||
|
* registered in Guice so they are globally available within the server
|
||||||
|
* environment.
|
||||||
|
*/
|
||||||
|
public interface GitRepositoryManager {
|
||||||
/**
|
/**
|
||||||
* Get (or open) a repository by name.
|
* Get (or open) a repository by name.
|
||||||
*
|
*
|
||||||
@@ -92,22 +39,8 @@ public class GitRepositoryManager {
|
|||||||
* @throws RepositoryNotFoundException the name does not denote an existing
|
* @throws RepositoryNotFoundException the name does not denote an existing
|
||||||
* repository, or the name cannot be read as a repository.
|
* repository, or the name cannot be read as a repository.
|
||||||
*/
|
*/
|
||||||
public Repository openRepository(String name)
|
public abstract Repository openRepository(String name)
|
||||||
throws RepositoryNotFoundException {
|
throws RepositoryNotFoundException;
|
||||||
if (isUnreasonableName(name)) {
|
|
||||||
throw new RepositoryNotFoundException("Invalid name: " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
final FileKey loc = FileKey.lenient(new File(basePath, name));
|
|
||||||
return RepositoryCache.open(loc);
|
|
||||||
} catch (IOException e1) {
|
|
||||||
final RepositoryNotFoundException e2;
|
|
||||||
e2 = new RepositoryNotFoundException("Cannot open repository " + name);
|
|
||||||
e2.initCause(e1);
|
|
||||||
throw e2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create (and open) a repository by name.
|
* Create (and open) a repository by name.
|
||||||
@@ -118,25 +51,8 @@ public class GitRepositoryManager {
|
|||||||
* @throws RepositoryNotFoundException the name does not denote an existing
|
* @throws RepositoryNotFoundException the name does not denote an existing
|
||||||
* repository, or the name cannot be read as a repository.
|
* repository, or the name cannot be read as a repository.
|
||||||
*/
|
*/
|
||||||
public Repository createRepository(String name)
|
public abstract Repository createRepository(String name)
|
||||||
throws RepositoryNotFoundException {
|
throws RepositoryNotFoundException;
|
||||||
if (isUnreasonableName(name)) {
|
|
||||||
throw new RepositoryNotFoundException("Invalid name: " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!name.endsWith(".git")) {
|
|
||||||
name = name + ".git";
|
|
||||||
}
|
|
||||||
final FileKey loc = FileKey.exact(new File(basePath, name));
|
|
||||||
return RepositoryCache.open(loc, false);
|
|
||||||
} catch (IOException e1) {
|
|
||||||
final RepositoryNotFoundException e2;
|
|
||||||
e2 = new RepositoryNotFoundException("Cannot open repository " + name);
|
|
||||||
e2.initCause(e1);
|
|
||||||
throw e2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the {@code GIT_DIR/description} file for gitweb.
|
* Read the {@code GIT_DIR/description} file for gitweb.
|
||||||
@@ -150,29 +66,8 @@ public class GitRepositoryManager {
|
|||||||
* @throws IOException the description file exists, but is not readable by
|
* @throws IOException the description file exists, but is not readable by
|
||||||
* this process.
|
* this process.
|
||||||
*/
|
*/
|
||||||
public String getProjectDescription(final String name)
|
public abstract String getProjectDescription(final String name)
|
||||||
throws RepositoryNotFoundException, IOException {
|
throws RepositoryNotFoundException, IOException;
|
||||||
final Repository e = openRepository(name);
|
|
||||||
final File d = new File(e.getDirectory(), "description");
|
|
||||||
|
|
||||||
String description;
|
|
||||||
try {
|
|
||||||
description = RawParseUtils.decode(IO.readFully(d));
|
|
||||||
} catch (FileNotFoundException err) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (description != null) {
|
|
||||||
description = description.trim();
|
|
||||||
if (description.isEmpty()) {
|
|
||||||
description = null;
|
|
||||||
}
|
|
||||||
if (UNNAMED.equals(description)) {
|
|
||||||
description = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the {@code GIT_DIR/description} file for gitweb.
|
* Set the {@code GIT_DIR/description} file for gitweb.
|
||||||
@@ -183,48 +78,6 @@ public class GitRepositoryManager {
|
|||||||
* @param name the repository name, relative to the base directory.
|
* @param name the repository name, relative to the base directory.
|
||||||
* @param description new description text for the repository.
|
* @param description new description text for the repository.
|
||||||
*/
|
*/
|
||||||
public void setProjectDescription(final String name, final String description) {
|
public abstract void setProjectDescription(final String name,
|
||||||
// Update git's description file, in case gitweb is being used
|
final String description);
|
||||||
//
|
|
||||||
try {
|
|
||||||
final Repository e;
|
|
||||||
final LockFile f;
|
|
||||||
|
|
||||||
e = openRepository(name);
|
|
||||||
f = new LockFile(new File(e.getDirectory(), "description"));
|
|
||||||
if (f.lock()) {
|
|
||||||
String d = description;
|
|
||||||
if (d != null) {
|
|
||||||
d = d.trim();
|
|
||||||
if (d.length() > 0) {
|
|
||||||
d += "\n";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
d = "";
|
|
||||||
}
|
|
||||||
f.write(Constants.encode(d));
|
|
||||||
f.commit();
|
|
||||||
}
|
|
||||||
e.close();
|
|
||||||
} catch (RepositoryNotFoundException e) {
|
|
||||||
log.error("Cannot update description for " + name, e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Cannot update description for " + name, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isUnreasonableName(final String name) {
|
|
||||||
if (name.length() == 0) return true; // no empty paths
|
|
||||||
|
|
||||||
if (name.indexOf('\\') >= 0) return true; // no windows/dos stlye paths
|
|
||||||
if (name.charAt(0) == '/') return true; // no absolute paths
|
|
||||||
if (new File(name).isAbsolute()) return true; // no absolute paths
|
|
||||||
|
|
||||||
if (name.startsWith("../")) return true; // no "l../etc/passwd"
|
|
||||||
if (name.contains("/../")) return true; // no "foo/../etc/passwd"
|
|
||||||
if (name.contains("/./")) return true; // "foo/./foo" is insane to ask
|
|
||||||
if (name.contains("//")) return true; // windows UNC path can be "//..."
|
|
||||||
|
|
||||||
return false; // is a reasonable name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,191 @@
|
|||||||
|
// Copyright (C) 2008 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.server.git;
|
||||||
|
|
||||||
|
import com.google.gerrit.lifecycle.LifecycleListener;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.LockFile;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.lib.RepositoryCache;
|
||||||
|
import org.eclipse.jgit.lib.WindowCache;
|
||||||
|
import org.eclipse.jgit.lib.WindowCacheConfig;
|
||||||
|
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
|
||||||
|
import org.eclipse.jgit.util.IO;
|
||||||
|
import org.eclipse.jgit.util.RawParseUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/** Manages Git repositories stored on the local filesystem. */
|
||||||
|
@Singleton
|
||||||
|
public class LocalDiskRepositoryManager implements GitRepositoryManager {
|
||||||
|
private static final Logger log =
|
||||||
|
LoggerFactory.getLogger(LocalDiskRepositoryManager.class);
|
||||||
|
|
||||||
|
private static final String UNNAMED =
|
||||||
|
"Unnamed repository; edit this file to name it for gitweb.";
|
||||||
|
|
||||||
|
public static class Lifecycle implements LifecycleListener {
|
||||||
|
private final Config cfg;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Lifecycle(@GerritServerConfig final Config cfg) {
|
||||||
|
this.cfg = cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
final WindowCacheConfig c = new WindowCacheConfig();
|
||||||
|
c.fromConfig(cfg);
|
||||||
|
WindowCache.reconfigure(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final File basePath;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LocalDiskRepositoryManager(final SitePaths site,
|
||||||
|
@GerritServerConfig final Config cfg) {
|
||||||
|
basePath = site.resolve(cfg.getString("gerrit", null, "basePath"));
|
||||||
|
if (basePath == null) {
|
||||||
|
throw new IllegalStateException("gerrit.basePath must be configured");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return base directory under which all projects are stored. */
|
||||||
|
public File getBasePath() {
|
||||||
|
return basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Repository openRepository(String name)
|
||||||
|
throws RepositoryNotFoundException {
|
||||||
|
if (isUnreasonableName(name)) {
|
||||||
|
throw new RepositoryNotFoundException("Invalid name: " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final FileKey loc = FileKey.lenient(new File(basePath, name));
|
||||||
|
return RepositoryCache.open(loc);
|
||||||
|
} catch (IOException e1) {
|
||||||
|
final RepositoryNotFoundException e2;
|
||||||
|
e2 = new RepositoryNotFoundException("Cannot open repository " + name);
|
||||||
|
e2.initCause(e1);
|
||||||
|
throw e2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Repository createRepository(String name)
|
||||||
|
throws RepositoryNotFoundException {
|
||||||
|
if (isUnreasonableName(name)) {
|
||||||
|
throw new RepositoryNotFoundException("Invalid name: " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!name.endsWith(".git")) {
|
||||||
|
name = name + ".git";
|
||||||
|
}
|
||||||
|
final FileKey loc = FileKey.exact(new File(basePath, name));
|
||||||
|
return RepositoryCache.open(loc, false);
|
||||||
|
} catch (IOException e1) {
|
||||||
|
final RepositoryNotFoundException e2;
|
||||||
|
e2 = new RepositoryNotFoundException("Cannot open repository " + name);
|
||||||
|
e2.initCause(e1);
|
||||||
|
throw e2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProjectDescription(final String name)
|
||||||
|
throws RepositoryNotFoundException, IOException {
|
||||||
|
final Repository e = openRepository(name);
|
||||||
|
final File d = new File(e.getDirectory(), "description");
|
||||||
|
|
||||||
|
String description;
|
||||||
|
try {
|
||||||
|
description = RawParseUtils.decode(IO.readFully(d));
|
||||||
|
} catch (FileNotFoundException err) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description != null) {
|
||||||
|
description = description.trim();
|
||||||
|
if (description.isEmpty()) {
|
||||||
|
description = null;
|
||||||
|
}
|
||||||
|
if (UNNAMED.equals(description)) {
|
||||||
|
description = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProjectDescription(final String name, final String description) {
|
||||||
|
// Update git's description file, in case gitweb is being used
|
||||||
|
//
|
||||||
|
try {
|
||||||
|
final Repository e;
|
||||||
|
final LockFile f;
|
||||||
|
|
||||||
|
e = openRepository(name);
|
||||||
|
f = new LockFile(new File(e.getDirectory(), "description"));
|
||||||
|
if (f.lock()) {
|
||||||
|
String d = description;
|
||||||
|
if (d != null) {
|
||||||
|
d = d.trim();
|
||||||
|
if (d.length() > 0) {
|
||||||
|
d += "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d = "";
|
||||||
|
}
|
||||||
|
f.write(Constants.encode(d));
|
||||||
|
f.commit();
|
||||||
|
}
|
||||||
|
e.close();
|
||||||
|
} catch (RepositoryNotFoundException e) {
|
||||||
|
log.error("Cannot update description for " + name, e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Cannot update description for " + name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isUnreasonableName(final String name) {
|
||||||
|
if (name.length() == 0) return true; // no empty paths
|
||||||
|
|
||||||
|
if (name.indexOf('\\') >= 0) return true; // no windows/dos stlye paths
|
||||||
|
if (name.charAt(0) == '/') return true; // no absolute paths
|
||||||
|
if (new File(name).isAbsolute()) return true; // no absolute paths
|
||||||
|
|
||||||
|
if (name.startsWith("../")) return true; // no "l../etc/passwd"
|
||||||
|
if (name.contains("/../")) return true; // no "foo/../etc/passwd"
|
||||||
|
if (name.contains("/./")) return true; // "foo/./foo" is insane to ask
|
||||||
|
if (name.contains("//")) return true; // windows UNC path can be "//..."
|
||||||
|
|
||||||
|
return false; // is a reasonable name
|
||||||
|
}
|
||||||
|
}
|
@@ -12,10 +12,11 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package com.google.gerrit.pgm.util;
|
package com.google.gerrit.server.schema;
|
||||||
|
|
||||||
|
import static com.google.gerrit.server.config.ConfigUtil.getEnum;
|
||||||
|
|
||||||
import com.google.gerrit.lifecycle.LifecycleListener;
|
import com.google.gerrit.lifecycle.LifecycleListener;
|
||||||
import com.google.gerrit.server.config.ConfigUtil;
|
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gwtorm.jdbc.SimpleDataSource;
|
import com.google.gwtorm.jdbc.SimpleDataSource;
|
||||||
@@ -71,132 +72,87 @@ public final class DataSourceProvider implements Provider<DataSource>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static enum Type {
|
public static enum Type {
|
||||||
DEFAULT, JDBC, POSTGRES, POSTGRESQL, H2, MYSQL;
|
H2, POSTGRESQL, MYSQL, JDBC;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataSource open(final SitePaths site, final Config cfg,
|
private DataSource open(final SitePaths site, final Config cfg,
|
||||||
final Context context) {
|
final Context context) {
|
||||||
Type type = ConfigUtil.getEnum(cfg, "database", null, "type", Type.DEFAULT);
|
Type type = getEnum(cfg, "database", null, "type", Type.values(), null);
|
||||||
String driver = optional(cfg, "driver");
|
String driver = optional(cfg, "driver");
|
||||||
String url = optional(cfg, "url");
|
String url = optional(cfg, "url");
|
||||||
String username = optional(cfg, "username");
|
String username = optional(cfg, "username");
|
||||||
String password = optional(cfg, "password");
|
String password = optional(cfg, "password");
|
||||||
String hostname = optional(cfg, "hostname");
|
|
||||||
String port = optional(cfg, "port");
|
|
||||||
if (hostname == null) {
|
|
||||||
hostname = "localhost";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Type.DEFAULT == type && (driver == null || driver.isEmpty())) {
|
if (url == null || url.isEmpty()) {
|
||||||
if (url != null && url.isEmpty()) {
|
if (type == null) {
|
||||||
|
if (url != null && !url.isEmpty()) {
|
||||||
if (url.startsWith("jdbc:postgresql:")) {
|
type = Type.JDBC;
|
||||||
type = Type.POSTGRES;
|
} else {
|
||||||
} else if (url.startsWith("postgresql:")) {
|
|
||||||
url = "jdbc:" + url;
|
|
||||||
type = Type.POSTGRES;
|
|
||||||
} else if (url.startsWith("postgres:")) {
|
|
||||||
url = "jdbc:postgresql:" + url.substring(url.indexOf(':') + 1);
|
|
||||||
type = Type.POSTGRES;
|
|
||||||
|
|
||||||
} else if (url.startsWith("jdbc:h2:")) {
|
|
||||||
type = Type.H2;
|
|
||||||
} else if (url.startsWith("h2:")) {
|
|
||||||
url = "jdbc:" + url;
|
|
||||||
type = Type.H2;
|
|
||||||
|
|
||||||
} else if (url.startsWith("jdbc:mysql:")) {
|
|
||||||
type = Type.MYSQL;
|
|
||||||
} else if (url.startsWith("mysql:")) {
|
|
||||||
url = "jdbc:" + url;
|
|
||||||
type = Type.MYSQL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (url == null || url.isEmpty()) {
|
|
||||||
type = Type.H2;
|
type = Type.H2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case POSTGRES:
|
|
||||||
case POSTGRESQL: {
|
|
||||||
final String pfx = "jdbc:postgresql://";
|
|
||||||
driver = "org.postgresql.Driver";
|
|
||||||
if (url == null) {
|
|
||||||
final StringBuilder b = new StringBuilder();
|
|
||||||
b.append(pfx);
|
|
||||||
b.append(hostname);
|
|
||||||
if (port != null && !port.isEmpty()) {
|
|
||||||
b.append(":");
|
|
||||||
b.append(port);
|
|
||||||
}
|
|
||||||
b.append("/");
|
|
||||||
b.append(required(cfg, "database"));
|
|
||||||
url = b.toString();
|
|
||||||
}
|
|
||||||
if (url == null || !url.startsWith(pfx)) {
|
|
||||||
throw new IllegalArgumentException("database.url must be " + pfx
|
|
||||||
+ " and not " + url);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case H2: {
|
case H2: {
|
||||||
final String pfx = "jdbc:h2:";
|
|
||||||
driver = "org.h2.Driver";
|
|
||||||
if (url == null) {
|
|
||||||
String database = optional(cfg, "database");
|
String database = optional(cfg, "database");
|
||||||
if (database == null || database.isEmpty()) {
|
if (database == null || database.isEmpty()) {
|
||||||
database = "db/ReviewDB";
|
database = "db/ReviewDB";
|
||||||
}
|
}
|
||||||
|
|
||||||
File db = site.resolve(database);
|
File db = site.resolve(database);
|
||||||
try {
|
try {
|
||||||
db = db.getCanonicalFile();
|
db = db.getCanonicalFile();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
db = db.getAbsoluteFile();
|
db = db.getAbsoluteFile();
|
||||||
}
|
}
|
||||||
url = pfx + db.toURI().toString();
|
url = "jdbc:h2:" + db.toURI().toString();
|
||||||
}
|
break;
|
||||||
if (url == null || !url.startsWith(pfx)) {
|
|
||||||
throw new IllegalArgumentException("database.url must be " + pfx
|
|
||||||
+ " and not " + url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case POSTGRESQL: {
|
||||||
|
final StringBuilder b = new StringBuilder();
|
||||||
|
b.append("jdbc:postgresql://");
|
||||||
|
b.append(hostname(optional(cfg, "hostname")));
|
||||||
|
b.append(port(optional(cfg, "port")));
|
||||||
|
b.append("/");
|
||||||
|
b.append(required(cfg, "database"));
|
||||||
|
url = b.toString();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MYSQL: {
|
case MYSQL: {
|
||||||
final String pfx = "jdbc:mysql://";
|
|
||||||
driver = "com.mysql.jdbc.Driver";
|
|
||||||
if (url == null) {
|
|
||||||
final StringBuilder b = new StringBuilder();
|
final StringBuilder b = new StringBuilder();
|
||||||
b.append(pfx);
|
b.append("jdbc:mysql://");
|
||||||
b.append(hostname);
|
b.append(hostname(optional(cfg, "hostname")));
|
||||||
if (port != null && !port.isEmpty()) {
|
b.append(port(optional(cfg, "port")));
|
||||||
b.append(":");
|
|
||||||
b.append(port);
|
|
||||||
}
|
|
||||||
b.append("/");
|
b.append("/");
|
||||||
b.append(required(cfg, "database"));
|
b.append(required(cfg, "database"));
|
||||||
url = b.toString();
|
url = b.toString();
|
||||||
}
|
|
||||||
if (url == null || !url.startsWith(pfx)) {
|
|
||||||
throw new IllegalArgumentException("database.url must be " + pfx
|
|
||||||
+ " and not " + url);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DEFAULT:
|
|
||||||
case JDBC:
|
case JDBC:
|
||||||
default:
|
|
||||||
driver = required(cfg, "driver");
|
driver = required(cfg, "driver");
|
||||||
url = required(cfg, "url");
|
url = required(cfg, "url");
|
||||||
if (!url.startsWith("jdbc:")) {
|
|
||||||
throw new IllegalArgumentException("database.url must be jdbc: style");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(type + " not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (driver == null || driver.isEmpty()) {
|
||||||
|
if (url.startsWith("jdbc:h2:")) {
|
||||||
|
driver = "org.h2.Driver";
|
||||||
|
|
||||||
|
} else if (url.startsWith("jdbc:postgresql:")) {
|
||||||
|
driver = "org.postgresql.Driver";
|
||||||
|
|
||||||
|
} else if (url.startsWith("jdbc:mysql:")) {
|
||||||
|
driver = "com.mysql.jdbc.Driver";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("database.driver must be set");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean usePool;
|
boolean usePool;
|
||||||
@@ -252,6 +208,23 @@ public final class DataSourceProvider implements Provider<DataSource>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String hostname(String hostname) {
|
||||||
|
if (hostname == null || hostname.isEmpty()) {
|
||||||
|
hostname = "localhost";
|
||||||
|
|
||||||
|
} else if (hostname.contains(":") && !hostname.startsWith("[")) {
|
||||||
|
hostname = "[" + hostname + "]";
|
||||||
|
}
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String port(String port) {
|
||||||
|
if (port != null && !port.isEmpty()) {
|
||||||
|
return ":" + port;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
private static String optional(final Config config, final String name) {
|
private static String optional(final Config config, final String name) {
|
||||||
return config.getString("database", null, name);
|
return config.getString("database", null, name);
|
||||||
}
|
}
|
@@ -22,6 +22,7 @@ import com.google.inject.ProvisionException;
|
|||||||
import org.apache.sshd.common.KeyPairProvider;
|
import org.apache.sshd.common.KeyPairProvider;
|
||||||
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
|
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
|
||||||
import org.apache.sshd.common.util.SecurityUtils;
|
import org.apache.sshd.common.util.SecurityUtils;
|
||||||
|
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -37,33 +38,42 @@ class HostKeyProvider implements Provider<KeyPairProvider> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyPairProvider get() {
|
public KeyPairProvider get() {
|
||||||
final File anyKey = site.ssh_key;
|
final File objKey = site.ssh_key;
|
||||||
final File rsaKey = site.ssh_rsa;
|
final File rsaKey = site.ssh_rsa;
|
||||||
final File dsaKey = site.ssh_dsa;
|
final File dsaKey = site.ssh_dsa;
|
||||||
|
|
||||||
final List<String> keys = new ArrayList<String>(2);
|
final List<String> stdKeys = new ArrayList<String>(2);
|
||||||
if (rsaKey.exists()) {
|
if (rsaKey.exists()) {
|
||||||
keys.add(rsaKey.getAbsolutePath());
|
stdKeys.add(rsaKey.getAbsolutePath());
|
||||||
}
|
}
|
||||||
if (dsaKey.exists()) {
|
if (dsaKey.exists()) {
|
||||||
keys.add(dsaKey.getAbsolutePath());
|
stdKeys.add(dsaKey.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anyKey.exists() && !keys.isEmpty()) {
|
if (objKey.exists()) {
|
||||||
// If both formats of host key exist, we don't know which format
|
if (stdKeys.isEmpty()) {
|
||||||
|
SimpleGeneratorHostKeyProvider p = new SimpleGeneratorHostKeyProvider();
|
||||||
|
p.setPath(objKey.getAbsolutePath());
|
||||||
|
return p;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Both formats of host key exist, we don't know which format
|
||||||
// should be authoritative. Complain and abort.
|
// should be authoritative. Complain and abort.
|
||||||
//
|
//
|
||||||
keys.add(anyKey.getAbsolutePath());
|
stdKeys.add(objKey.getAbsolutePath());
|
||||||
throw new ProvisionException("Multiple host keys exist: " + keys);
|
throw new ProvisionException("Multiple host keys exist: " + stdKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keys.isEmpty()) {
|
} else {
|
||||||
|
if (stdKeys.isEmpty()) {
|
||||||
throw new ProvisionException("No SSH keys under " + site.etc_dir);
|
throw new ProvisionException("No SSH keys under " + site.etc_dir);
|
||||||
}
|
}
|
||||||
if (!SecurityUtils.isBouncyCastleRegistered()) {
|
if (!SecurityUtils.isBouncyCastleRegistered()) {
|
||||||
throw new ProvisionException("Bouncy Castle Crypto not installed;"
|
throw new ProvisionException("Bouncy Castle Crypto not installed;"
|
||||||
+ " needed to read server host keys: " + keys + "");
|
+ " needed to read server host keys: " + stdKeys + "");
|
||||||
|
}
|
||||||
|
return new FileKeyPairProvider(stdKeys
|
||||||
|
.toArray(new String[stdKeys.size()]));
|
||||||
}
|
}
|
||||||
return new FileKeyPairProvider(keys.toArray(new String[keys.size()]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,18 +15,10 @@
|
|||||||
package com.google.gerrit.httpd;
|
package com.google.gerrit.httpd;
|
||||||
|
|
||||||
import com.google.gerrit.lifecycle.LifecycleListener;
|
import com.google.gerrit.lifecycle.LifecycleListener;
|
||||||
import com.google.gwtorm.jdbc.SimpleDataSource;
|
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.ProvisionException;
|
import com.google.inject.ProvisionException;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
@@ -61,47 +53,8 @@ final class ReviewDbDataSourceProvider implements Provider<DataSource>,
|
|||||||
try {
|
try {
|
||||||
return (DataSource) new InitialContext().lookup(dsName);
|
return (DataSource) new InitialContext().lookup(dsName);
|
||||||
} catch (NamingException namingErr) {
|
} catch (NamingException namingErr) {
|
||||||
final Properties p = readGerritDataSource();
|
throw new ProvisionException("No DataSource " + dsName, namingErr);
|
||||||
if (p == null) {
|
|
||||||
throw new ProvisionException("Initialization error:\n"
|
|
||||||
+ " * No DataSource " + dsName + "\n"
|
|
||||||
+ " * No -DGerritServer=GerritServer.properties"
|
|
||||||
+ " on Java command line", namingErr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
return new SimpleDataSource(p);
|
|
||||||
} catch (SQLException se) {
|
|
||||||
throw new ProvisionException("Database unavailable", se);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Properties readGerritDataSource() throws ProvisionException {
|
|
||||||
final Properties srvprop = new Properties();
|
|
||||||
String name = System.getProperty("GerritServer");
|
|
||||||
if (name == null) {
|
|
||||||
name = "GerritServer.properties";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
final InputStream in = new FileInputStream(name);
|
|
||||||
try {
|
|
||||||
srvprop.load(in);
|
|
||||||
} finally {
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ProvisionException("Cannot read " + name, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Properties dbprop = new Properties();
|
|
||||||
for (final Map.Entry<Object, Object> e : srvprop.entrySet()) {
|
|
||||||
final String key = (String) e.getKey();
|
|
||||||
if (key.startsWith("database.")) {
|
|
||||||
dbprop.put(key.substring("database.".length()), e.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dbprop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeDataSource(final DataSource ds) {
|
private void closeDataSource(final DataSource ds) {
|
||||||
|
@@ -27,6 +27,7 @@ import com.google.gerrit.server.config.GerritServerConfigModule;
|
|||||||
import com.google.gerrit.server.config.MasterNodeStartup;
|
import com.google.gerrit.server.config.MasterNodeStartup;
|
||||||
import com.google.gerrit.server.config.SitePath;
|
import com.google.gerrit.server.config.SitePath;
|
||||||
import com.google.gerrit.server.config.SitePathFromSystemConfigProvider;
|
import com.google.gerrit.server.config.SitePathFromSystemConfigProvider;
|
||||||
|
import com.google.gerrit.server.schema.DataSourceProvider;
|
||||||
import com.google.gerrit.sshd.SshModule;
|
import com.google.gerrit.sshd.SshModule;
|
||||||
import com.google.gerrit.sshd.commands.MasterCommandModule;
|
import com.google.gerrit.sshd.commands.MasterCommandModule;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
@@ -57,6 +58,7 @@ public class WebAppInitializer extends GuiceServletContextListener {
|
|||||||
private static final Logger log =
|
private static final Logger log =
|
||||||
LoggerFactory.getLogger(WebAppInitializer.class);
|
LoggerFactory.getLogger(WebAppInitializer.class);
|
||||||
|
|
||||||
|
private File sitePath;
|
||||||
private Injector dbInjector;
|
private Injector dbInjector;
|
||||||
private Injector cfgInjector;
|
private Injector cfgInjector;
|
||||||
private Injector sysInjector;
|
private Injector sysInjector;
|
||||||
@@ -66,6 +68,11 @@ public class WebAppInitializer extends GuiceServletContextListener {
|
|||||||
|
|
||||||
private synchronized void init() {
|
private synchronized void init() {
|
||||||
if (manager == null) {
|
if (manager == null) {
|
||||||
|
final String path = System.getProperty("gerrit.site_path");
|
||||||
|
if (path != null) {
|
||||||
|
sitePath = new File(path);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dbInjector = createDbInjector();
|
dbInjector = createDbInjector();
|
||||||
} catch (CreationException ce) {
|
} catch (CreationException ce) {
|
||||||
@@ -115,6 +122,21 @@ public class WebAppInitializer extends GuiceServletContextListener {
|
|||||||
|
|
||||||
private Injector createDbInjector() {
|
private Injector createDbInjector() {
|
||||||
final List<Module> modules = new ArrayList<Module>();
|
final List<Module> modules = new ArrayList<Module>();
|
||||||
|
if (sitePath != null) {
|
||||||
|
modules.add(new LifecycleModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath);
|
||||||
|
bind(DataSourceProvider.Context.class).toInstance(
|
||||||
|
DataSourceProvider.Context.MULTI_USER);
|
||||||
|
bind(Key.get(DataSource.class, Names.named("ReviewDb"))).toProvider(
|
||||||
|
DataSourceProvider.class).in(SINGLETON);
|
||||||
|
listener().to(DataSourceProvider.class);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
modules.add(new GerritServerConfigModule());
|
||||||
|
|
||||||
|
} else {
|
||||||
modules.add(new LifecycleModule() {
|
modules.add(new LifecycleModule() {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
@@ -123,12 +145,18 @@ public class WebAppInitializer extends GuiceServletContextListener {
|
|||||||
listener().to(ReviewDbDataSourceProvider.class);
|
listener().to(ReviewDbDataSourceProvider.class);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
modules.add(new DatabaseModule());
|
modules.add(new DatabaseModule());
|
||||||
return Guice.createInjector(PRODUCTION, modules);
|
return Guice.createInjector(PRODUCTION, modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Injector createCfgInjector() {
|
private Injector createCfgInjector() {
|
||||||
final List<Module> modules = new ArrayList<Module>();
|
final List<Module> modules = new ArrayList<Module>();
|
||||||
|
if (sitePath == null) {
|
||||||
|
// If we didn't get the site path from the system property
|
||||||
|
// we need to get it from the database, as that's our old
|
||||||
|
// method of locating the site path on disk.
|
||||||
|
//
|
||||||
modules.add(new AbstractModule() {
|
modules.add(new AbstractModule() {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
@@ -137,6 +165,7 @@ public class WebAppInitializer extends GuiceServletContextListener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
modules.add(new GerritServerConfigModule());
|
modules.add(new GerritServerConfigModule());
|
||||||
|
}
|
||||||
modules.add(new AuthConfigModule());
|
modules.add(new AuthConfigModule());
|
||||||
return dbInjector.createChildInjector(modules);
|
return dbInjector.createChildInjector(modules);
|
||||||
}
|
}
|
||||||
|
@@ -1,32 +0,0 @@
|
|||||||
# Any properties starting with "database." will be fed to the JDBC driver,
|
|
||||||
# after removing the "database." prefix.
|
|
||||||
#
|
|
||||||
# The following "special" properties are removed from that set:
|
|
||||||
#
|
|
||||||
# database.driver : Class name of the driver to load.
|
|
||||||
# database.url : The connection URL
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
# H2
|
|
||||||
# (driver included)
|
|
||||||
#
|
|
||||||
# database.driver = org.h2.Driver
|
|
||||||
# database.url = jdbc:h2:file:ReviewDb
|
|
||||||
|
|
||||||
|
|
||||||
# PostgreSQL
|
|
||||||
# (driver included)
|
|
||||||
#
|
|
||||||
# database.driver = org.postgresql.Driver
|
|
||||||
# database.url = jdbc:postgresql:reviewdb
|
|
||||||
# database.user = gerrit2
|
|
||||||
# database.password = supersecretcode
|
|
||||||
|
|
||||||
|
|
||||||
# MySQL 5.0
|
|
||||||
# curl -O http://repo1.maven.org/maven2/mysql/mysql-connector-java/5.0.8/mysql-connector-java-5.0.8.jar
|
|
||||||
#
|
|
||||||
# database.classpath = mysql-connector-java-5.0.8.jar
|
|
||||||
# database.driver = com.mysql.jdbc.Driver
|
|
||||||
# database.url = jdbc:mysql://localhost/reviewdb?user=gerrit2&password=secretcode
|
|
@@ -31,5 +31,5 @@
|
|||||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-startupUrl / -war ${resource_loc:/gerrit-gwtui/target}/gwt-hosted-mode -server com.google.gerrit.gwtdebug.GerritDebugLauncher com.google.gerrit.GerritGwtUI"/>
|
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-startupUrl / -war ${resource_loc:/gerrit-gwtui/target}/gwt-hosted-mode -server com.google.gerrit.gwtdebug.GerritDebugLauncher com.google.gerrit.GerritGwtUI"/>
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="gerrit-gwtdbug"/>
|
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="gerrit-gwtdbug"/>
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.maven.ide.eclipse.launchconfig.sourcepathProvider"/>
|
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.maven.ide.eclipse.launchconfig.sourcepathProvider"/>
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256M -DGerritServer=${resource_loc:/gerrit-parent/GerritServer.properties}"/>
|
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256M -Dgerrit.site_path=${resource_loc:/gerrit-parent}/../test_site"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
||||||
|
Reference in New Issue
Block a user