Get branches directly from Git rather than database

We really don't use the Branch entity in Gerrit.  The Branch.Id
secondary key is completely unused, so I'm dropping it from the
schema to reduce the code complexity.  Unfortunately the record
in the database is used to determine if a change can e uploaded
to the branch, or not, so we are forced to keep it around as a
boolean flag for now.

The admin panel for a project now lists the branches directly
from the Git repository, as the database table will hopefully
disappear in the near-ish future, especially as we start to
move to a Git backed datastore.

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-08-08 13:47:17 -07:00
parent 25da99c5c0
commit 51f5f94b10
11 changed files with 108 additions and 81 deletions

View File

@@ -52,19 +52,17 @@ for a project named `project`.
,'new/project');
INSERT INTO branches
(branch_id
,branch_name
(branch_name
,project_name)
VALUES
(nextval('branch_id')
,'refs/heads/master'
('refs/heads/master'
,'new/project');
====
[NOTE]
On MySQL use `nextval_project_id()` and `nextval_branch_id()` to
obtain the next value in the sequences. These are contained in the
`sql/mysql_nextval.sql` script, available from `java -jar gerrit.war --cat sql/mysql_nextval.sql`.
On MySQL use `nextval_project_id()` to obtain the next value in the
sequences. This is contained in the `sql/mysql_nextval.sql` script,
available from `java -jar gerrit.war --cat sql/mysql_nextval.sql`.
Change Submit Action (submit_type)
----------------------------------

View File

@@ -15,7 +15,6 @@
package com.google.gerrit.client.reviewdb;
import com.google.gwtorm.client.Column;
import com.google.gwtorm.client.IntKey;
import com.google.gwtorm.client.StringKey;
/** Registered line of development within a {@link Project}. */
@@ -61,7 +60,7 @@ public final class Branch {
final String n = get();
// Git style branches will tend to start with "refs/heads/".
//
//
if (n.startsWith(R_HEADS)) {
return n.substring(R_HEADS.length());
}
@@ -70,47 +69,14 @@ public final class Branch {
}
}
/** Synthetic key to link to within the database */
public static class Id extends IntKey<com.google.gwtorm.client.Key<?>> {
private static final long serialVersionUID = 1L;
@Column
protected int id;
protected Id() {
}
public Id(final int id) {
this.id = id;
}
@Override
public int get() {
return id;
}
@Override
protected void set(int newValue) {
id = newValue;
}
}
@Column(name = Column.NONE)
protected NameKey name;
@Column
protected Id branchId;
protected Branch() {
}
public Branch(final Branch.NameKey newName, final Branch.Id newId) {
public Branch(final Branch.NameKey newName) {
name = newName;
branchId = newId;
}
public Branch.Id getId() {
return branchId;
}
public Branch.NameKey getNameKey() {

View File

@@ -19,15 +19,11 @@ import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.PrimaryKey;
import com.google.gwtorm.client.Query;
import com.google.gwtorm.client.ResultSet;
import com.google.gwtorm.client.SecondaryKey;
public interface BranchAccess extends Access<Branch, Branch.NameKey> {
@PrimaryKey("name")
Branch get(Branch.NameKey name) throws OrmException;
@SecondaryKey("branchId")
Branch get(Branch.Id id) throws OrmException;
@Query("WHERE name.projectName = ? ORDER BY name.branchName")
ResultSet<Branch> byProject(Project.NameKey key) throws OrmException;
}

View File

@@ -127,10 +127,6 @@ public interface ReviewDb extends Schema {
@Sequence
int nextProjectId() throws OrmException;
/** Next unique id for a {@link Branch}. */
@Sequence
int nextBranchId() throws OrmException;
/** Next unique id for a {@link Change}. */
@Sequence
int nextChangeId() throws OrmException;

View File

@@ -0,0 +1,80 @@
// 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.server.rpc.project;
import com.google.gerrit.client.reviewdb.Branch;
import com.google.gerrit.client.reviewdb.Project;
import com.google.gerrit.server.GerritServer;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.rpc.Handler;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.spearce.jgit.errors.RepositoryNotFoundException;
import org.spearce.jgit.lib.Constants;
import org.spearce.jgit.lib.Ref;
import org.spearce.jgit.lib.Repository;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class ListBranches extends Handler<List<Branch>> {
interface Factory {
ListBranches create(@Assisted("name") Project.NameKey name);
}
private final ProjectControl.Factory projectControlFactory;
private final GerritServer gerritServer;
private final Project.NameKey projectName;
@Inject
ListBranches(final ProjectControl.Factory projectControlFactory,
final GerritServer gerritServer,
@Assisted("name") final Project.NameKey name) {
this.projectControlFactory = projectControlFactory;
this.gerritServer = gerritServer;
this.projectName = name;
}
@Override
public List<Branch> call() throws NoSuchProjectException,
RepositoryNotFoundException {
final List<Branch> branches = new ArrayList<Branch>();
final ProjectControl c = projectControlFactory.validateFor(projectName);
final Repository db = gerritServer.openRepository(projectName.get());
try {
for (final Ref ref : db.getAllRefs().values()) {
final String name = ref.getOrigName();
if (name.startsWith(Constants.R_HEADS)) {
final Branch b = new Branch(new Branch.NameKey(projectName, name));
branches.add(b);
}
}
} finally {
db.close();
}
Collections.sort(branches, new Comparator<Branch>() {
@Override
public int compare(final Branch a, final Branch b) {
return a.getName().compareTo(b.getName());
}
});
return branches;
}
}

View File

@@ -74,6 +74,7 @@ class ProjectAdminServiceImpl extends BaseServiceImplementation implements
private final ReplicationQueue replication;
private final Provider<IdentifiedUser> identifiedUser;
private final ListBranches.Factory listBranchesFactory;
private final ProjectDetailFactory.Factory projectDetailFactory;
@Inject
@@ -82,6 +83,7 @@ class ProjectAdminServiceImpl extends BaseServiceImplementation implements
final Provider<IdentifiedUser> currentUser,
@WildProjectName final Project.NameKey wp,
final ProjectControl.Factory projectControlFactory,
final ListBranches.Factory listBranchesFactory,
final ProjectDetailFactory.Factory projectDetailFactory) {
super(schema, currentUser);
this.server = gs;
@@ -90,6 +92,8 @@ class ProjectAdminServiceImpl extends BaseServiceImplementation implements
this.wildProject = wp;
this.identifiedUser = currentUser;
this.projectControlFactory = projectControlFactory;
this.listBranchesFactory = listBranchesFactory;
this.projectDetailFactory = projectDetailFactory;
}
@@ -293,20 +297,7 @@ class ProjectAdminServiceImpl extends BaseServiceImplementation implements
public void listBranches(final Project.NameKey projectName,
final AsyncCallback<List<Branch>> callback) {
run(callback, new Action<List<Branch>>() {
public List<Branch> run(ReviewDb db) throws OrmException, Failure {
final ProjectControl c;
try {
c = projectControlFactory.controlFor(projectName);
} catch (NoSuchProjectException e) {
throw new Failure(new NoSuchEntityException());
}
if (!c.isOwner()) {
throw new Failure(new NoSuchEntityException());
}
return db.branches().byProject(c.getProject().getNameKey()).toList();
}
});
listBranchesFactory.create(projectName).to(callback);
}
public void deleteBranch(final Project.NameKey projectName,
@@ -481,8 +472,7 @@ class ProjectAdminServiceImpl extends BaseServiceImplementation implements
repo.close();
}
final Branch.Id id = new Branch.Id(db.nextBranchId());
final Branch newBranch = new Branch(name, id);
final Branch newBranch = new Branch(name);
db.branches().insert(Collections.singleton(newBranch));
return db.branches().byProject(pce.getProject().getNameKey()).toList();
}

View File

@@ -28,6 +28,7 @@ public class ProjectModule extends RpcServletModule {
install(new FactoryModule() {
@Override
protected void configure() {
factory(ListBranches.Factory.class);
factory(ProjectDetailFactory.Factory.class);
}
});

View File

@@ -1080,8 +1080,7 @@ final class Receive extends AbstractGitCommand {
try {
final Branch.NameKey nameKey =
new Branch.NameKey(proj.getNameKey(), c.getRefName());
final Branch.Id idKey = new Branch.Id(db.nextBranchId());
final Branch b = new Branch(nameKey, idKey);
final Branch b = new Branch(nameKey);
db.branches().insert(Collections.singleton(b));
} catch (OrmException e) {
final String msg = "database failure creating " + c.getRefName();

View File

@@ -2,18 +2,6 @@
--
delimiter //
CREATE FUNCTION nextval_branch_id ()
RETURNS BIGINT
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
BEGIN
INSERT INTO branch_id (s) VALUES (NULL);
DELETE FROM branch_id WHERE s = LAST_INSERT_ID();
RETURN LAST_INSERT_ID();
END;
//
CREATE FUNCTION nextval_project_id ()
RETURNS BIGINT
LANGUAGE SQL

View File

@@ -76,6 +76,13 @@ CREATE UNIQUE INDEX accounts_ssh_user_name_key
ON accounts (ssh_user_name);
-- branch (no id)
--
ALTER TABLE branches DROP COLUMN branch_id;
DROP TABLE branch_id;
DROP FUNCTION nextval_branch_id;
UPDATE project_rights SET min_value=1
WHERE category_id='OWN' AND min_value=0 AND max_value=1;

View File

@@ -102,6 +102,12 @@ CREATE UNIQUE INDEX accounts_ssh_user_name_key
ON accounts (ssh_user_name);
-- branch (no id)
--
ALTER TABLE branches DROP COLUMN branch_id;
DROP SEQUENCE branch_id;
UPDATE project_rights SET min_value=1
WHERE category_id='OWN' AND min_value=0 AND max_value=1;