summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Kossakowski <grek@google.com>2009-09-10 12:54:44 -0700
committerGrzegorz Kossakowski <grek@google.com>2009-09-10 14:32:09 -0700
commit8c9bfc4a89bdf71280d5f18926996c361e44071a (patch)
tree9cf0d24db8b9ce16139d07c0fd889e5082e523e8
parenta6992c36fc0d23bba01e6f07e2eb2f998b535079 (diff)
downloadgimd-8c9bfc4a89bdf71280d5f18926996c361e44071a.tar.gz
Added branch support for JGit-based implementation of Database trait.
Introduced JGitBranch class which holds complete information about branch: its name and repository where it's defined. Since now JGitDatabase can be constructed out of JGitBranch only. Also adapted all JGit-related test-cases to operate on specific branch instead of repository instance alone. Change-Id: I35a89c7d9dc12d2cb0d9efad98cfa9dde0f54d38 Signed-off-by: Grzegorz Kossakowski <grek@google.com>
-rw-r--r--src/main/scala/com/google/gimd/jgit/InvalidJGitBranchNameException.scala22
-rw-r--r--src/main/scala/com/google/gimd/jgit/JGitBranch.scala30
-rw-r--r--src/main/scala/com/google/gimd/jgit/JGitDatabase.scala38
-rw-r--r--src/main/scala/com/google/gimd/jgit/JGitDatabaseException.scala13
-rw-r--r--src/main/scala/com/google/gimd/jgit/JGitFile.scala6
-rw-r--r--src/main/scala/com/google/gimd/jgit/JGitMergeRetriesExceededException.scala4
-rw-r--r--src/main/scala/com/google/gimd/jgit/JGitSnapshot.scala6
-rw-r--r--src/test/scala/com/google/gimd/jgit/AbstractJGitTestCase.scala19
-rw-r--r--src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala16
-rw-r--r--src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala6
10 files changed, 107 insertions, 53 deletions
diff --git a/src/main/scala/com/google/gimd/jgit/InvalidJGitBranchNameException.scala b/src/main/scala/com/google/gimd/jgit/InvalidJGitBranchNameException.scala
new file mode 100644
index 0000000..e3c65f7
--- /dev/null
+++ b/src/main/scala/com/google/gimd/jgit/InvalidJGitBranchNameException.scala
@@ -0,0 +1,22 @@
+// 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.gimd.jgit
+
+import org.spearce.jgit.lib.Repository
+
+final class InvalidJGitBranchNameException(val repository: Repository, name: String)
+ extends JGitDatabaseException(JGitBranch(repository, ""), //not sure if creating artificial
+ //branch istance is a good idea
+ "'%1s' is invalid branch name".format(name))
diff --git a/src/main/scala/com/google/gimd/jgit/JGitBranch.scala b/src/main/scala/com/google/gimd/jgit/JGitBranch.scala
new file mode 100644
index 0000000..081463d
--- /dev/null
+++ b/src/main/scala/com/google/gimd/jgit/JGitBranch.scala
@@ -0,0 +1,30 @@
+// 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.gimd.jgit
+
+import org.spearce.jgit.lib.Repository
+
+/**
+ * <p>Class that stores information about branch which consists of name of branch and repository
+ * where that branch is stored.</p>
+ *
+ * @throws InvalidJGitBranchNameException if supplied <code>name</code> does not pass
+ * <code>Repository.isValidRefName</code> test.
+ */
+@throws(classOf[InvalidJGitBranchNameException])
+final case class JGitBranch(repository: Repository, name: String) {
+ if (!Repository.isValidRefName(name))
+ throw new InvalidJGitBranchNameException(repository, name)
+}
diff --git a/src/main/scala/com/google/gimd/jgit/JGitDatabase.scala b/src/main/scala/com/google/gimd/jgit/JGitDatabase.scala
index 0b02a6f..760ccb8 100644
--- a/src/main/scala/com/google/gimd/jgit/JGitDatabase.scala
+++ b/src/main/scala/com/google/gimd/jgit/JGitDatabase.scala
@@ -24,7 +24,7 @@ import org.spearce.jgit.lib.RefUpdate.Result
import org.spearce.jgit.dircache.{DirCache, DirCacheEditor, DirCacheEntry}
import org.spearce.jgit.revwalk.{RevCommit, RevTree, RevWalk}
-final class JGitDatabase(repository: Repository) extends Database {
+final class JGitDatabase(branch: JGitBranch) extends Database {
/**
* The maximal number of merge/transaction rebase retries.
@@ -42,12 +42,14 @@ final class JGitDatabase(repository: Repository) extends Database {
*/
private val MERGE_RETRIES = 10
+ private val repository = branch.repository
+
def latestSnapshot: JGitSnapshot = {
try {
- val id = repository.resolve(Constants.HEAD)
- new JGitSnapshot(repository, new RevWalk(repository).parseCommit(id))
+ val id = repository.resolve(branch.name)
+ new JGitSnapshot(branch, new RevWalk(repository).parseCommit(id))
} catch {
- case e: IOException => throw new JGitDatabaseException(repository, e)
+ case e: IOException => throw new JGitDatabaseException(branch, e)
}
}
@@ -56,37 +58,37 @@ final class JGitDatabase(repository: Repository) extends Database {
retry(MERGE_RETRIES) {
val snapshot = latestSnapshot
val dbModification = modification(snapshot)
- applyModification(dbModification, Constants.HEAD, snapshot.commit)
+ applyModification(dbModification, snapshot.commit)
}
} catch {
- case e: IOException => throw new JGitDatabaseException(repository, e)
+ case e: IOException => throw new JGitDatabaseException(branch, e)
}
if (!successful)
- throw new JGitMergeRetriesExceededException(repository, MERGE_RETRIES)
+ throw new JGitMergeRetriesExceededException(branch, MERGE_RETRIES)
}
- def applyModification(modification: DatabaseModification, branch: String, onto: RevCommit):
+ def applyModification(modification: DatabaseModification, onto: RevCommit):
Boolean = {
val treeId = writeMessages(modification, onto.getTree)
val commitId = createCommit(treeId, onto)
- val result = updateRef(branch, onto, commitId)
+ val result = updateRef(onto, commitId)
result match {
//there was no change to database since onto commit so changes were applied cleanly
case Result.FAST_FORWARD => true
//if there was a change since onto commit update gets rejected. Still it might be that change
//did not affected files we are trying to modify. Thus we are trying merging both changes.
- case Result.REJECTED => tryMerging(branch, commitId)
+ case Result.REJECTED => tryMerging(commitId)
//TODO: There should be a special treatment of LOCK_FAILURE case but it's low-priority task
//the idea is to not try merging if just JGit fails to obtain lock for given reference
case _ =>
- throw new JGitDatabaseException(repository,
+ throw new JGitDatabaseException(branch,
"RefUpdate returned unexpected result: %1s.".format(result))
}
}
- private def updateRef(name: String, oldCommit: ObjectId, newCommit: ObjectId): Result = {
- val refUpdate = repository.updateRef(name)
+ private def updateRef(oldCommit: ObjectId, newCommit: ObjectId): Result = {
+ val refUpdate = repository.updateRef(branch.name)
refUpdate.setExpectedOldObjectId(oldCommit)
refUpdate.setNewObjectId(newCommit)
refUpdate.update()
@@ -130,20 +132,20 @@ final class JGitDatabase(repository: Repository) extends Database {
dirCache.writeTree(objectWriter)
}
- private def merge(branch: String, commitToBeMerged: ObjectId): Boolean = {
- val baseCommit = repository.resolve(branch)
+ private def merge(commitToBeMerged: ObjectId): Boolean = {
+ val baseCommit = repository.resolve(branch.name)
val merger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(repository)
if (merger.merge(baseCommit, commitToBeMerged)) {
val treeId = merger.getResultTreeId
val mergeCommit = createCommit(treeId, baseCommit, commitToBeMerged)
- val result = updateRef(branch, baseCommit, mergeCommit)
+ val result = updateRef(baseCommit, mergeCommit)
Result.FAST_FORWARD == result
} else
false
}
- private def tryMerging(branch: String, commitToBeMerged: ObjectId) =
- retry(MERGE_RETRIES)(merge(branch, commitToBeMerged))
+ private def tryMerging(commitToBeMerged: ObjectId) =
+ retry(MERGE_RETRIES)(merge(commitToBeMerged))
private def retry(howManyTimes: Int)(what: => Boolean): Boolean =
if (howManyTimes > 0)
diff --git a/src/main/scala/com/google/gimd/jgit/JGitDatabaseException.scala b/src/main/scala/com/google/gimd/jgit/JGitDatabaseException.scala
index 1245df9..16429a3 100644
--- a/src/main/scala/com/google/gimd/jgit/JGitDatabaseException.scala
+++ b/src/main/scala/com/google/gimd/jgit/JGitDatabaseException.scala
@@ -14,14 +14,11 @@
package com.google.gimd.jgit
+case class JGitDatabaseException(val branch: JGitBranch,
+ val msg: String,
+ val cause: Throwable) extends GimdException(msg, cause) {
-import org.spearce.jgit.lib.Repository
+ def this(branch: JGitBranch, msg: String) = this(branch, msg, null)
-class JGitDatabaseException(val repository: Repository,
- val msg: String,
- val cause: Throwable) extends GimdException(msg, cause) {
-
- def this(repository: Repository, msg: String) = this(repository, msg, null)
-
- def this(repository: Repository, cause: Throwable) = this(repository, null, cause)
+ def this(branch: JGitBranch, cause: Throwable) = this(branch, null, cause)
}
diff --git a/src/main/scala/com/google/gimd/jgit/JGitFile.scala b/src/main/scala/com/google/gimd/jgit/JGitFile.scala
index dd110d5..4cdf3ca 100644
--- a/src/main/scala/com/google/gimd/jgit/JGitFile.scala
+++ b/src/main/scala/com/google/gimd/jgit/JGitFile.scala
@@ -20,15 +20,15 @@ import org.spearce.jgit.lib.{ObjectId, Repository}
import text.Parser
final class JGitFile[T](val path: String, val blobId: ObjectId, val fileType: FileType[T],
- val repository: Repository) extends File[T] {
+ val branch: JGitBranch) extends File[T] {
lazy val message = Parser.parse(new InputStreamReader(blobInputStream, "UTF-8"))
lazy val userObject = fileType.userType.toUserObject(message)
private lazy val blobInputStream = {
- val objectLoader = repository.openBlob(blobId)
+ val objectLoader = branch.repository.openBlob(blobId)
if (objectLoader == null)
- throw new JGitDatabaseException(repository, "Blob '" + blobId.name + "' does not exist.")
+ throw new JGitDatabaseException(branch, "Blob '" + blobId.name + "' does not exist.")
new ByteArrayInputStream(objectLoader.getCachedBytes)
}
diff --git a/src/main/scala/com/google/gimd/jgit/JGitMergeRetriesExceededException.scala b/src/main/scala/com/google/gimd/jgit/JGitMergeRetriesExceededException.scala
index b982850..ca2bb2a 100644
--- a/src/main/scala/com/google/gimd/jgit/JGitMergeRetriesExceededException.scala
+++ b/src/main/scala/com/google/gimd/jgit/JGitMergeRetriesExceededException.scala
@@ -21,6 +21,6 @@ import org.spearce.jgit.lib.Repository
*
* @see JGitDatabase
*/
-class JGitMergeRetriesExceededException(override val repository: Repository, val retries: Int)
- extends JGitDatabaseException(repository, ("Tried to rebase transaction %1s times and " +
+class JGitMergeRetriesExceededException(override val branch: JGitBranch, val retries: Int)
+ extends JGitDatabaseException(branch, ("Tried to rebase transaction %1s times and " +
"failed to merge changes successfuly. Aborting.").format(retries))
diff --git a/src/main/scala/com/google/gimd/jgit/JGitSnapshot.scala b/src/main/scala/com/google/gimd/jgit/JGitSnapshot.scala
index 2fd01ef..1f8f553 100644
--- a/src/main/scala/com/google/gimd/jgit/JGitSnapshot.scala
+++ b/src/main/scala/com/google/gimd/jgit/JGitSnapshot.scala
@@ -20,10 +20,10 @@ import org.spearce.jgit.revwalk.RevCommit
import org.spearce.jgit.treewalk.filter.{PathFilter, PathSuffixFilter, AndTreeFilter, TreeFilter}
import org.spearce.jgit.treewalk.TreeWalk
-final class JGitSnapshot(val repository: Repository, val commit: RevCommit) extends Snapshot {
+final class JGitSnapshot(val branch: JGitBranch, val commit: RevCommit) extends Snapshot {
def all[T](fileType: FileType[T]): Iterator[File[T]] = {
- val treeWalk = new TreeWalk(repository)
+ val treeWalk = new TreeWalk(branch.repository)
treeWalk.reset(commit.getTree)
treeWalk.setRecursive(true)
treeWalk.setFilter(treeFilter(fileType))
@@ -35,7 +35,7 @@ final class JGitSnapshot(val repository: Repository, val commit: RevCommit) exte
if (!hasNext)
throw new NoSuchElementException
val result =
- new JGitFile(treeWalk.getPathString, treeWalk.getObjectId(0), fileType, repository)
+ new JGitFile(treeWalk.getPathString, treeWalk.getObjectId(0), fileType, branch)
doesHasNext = treeWalk.next
result
}
diff --git a/src/test/scala/com/google/gimd/jgit/AbstractJGitTestCase.scala b/src/test/scala/com/google/gimd/jgit/AbstractJGitTestCase.scala
index ad8f110..33de36f 100644
--- a/src/test/scala/com/google/gimd/jgit/AbstractJGitTestCase.scala
+++ b/src/test/scala/com/google/gimd/jgit/AbstractJGitTestCase.scala
@@ -14,23 +14,26 @@
package com.google.gimd.jgit
-
import java.io.{ByteArrayInputStream, IOException, File}
import org.junit.{After, Before}
import org.spearce.jgit.lib._
+
abstract class AbstractJGitTestCase {
private val repositoryPath = "test-repository/.git"
- var repository: Repository = null
+ protected val masterRef = Constants.R_HEADS + Constants.MASTER
+
+ protected var masterBranch: JGitBranch = null
@Before protected def createRepository {
val file = new File(repositoryPath)
- repository = new Repository(file)
+ val repository = new Repository(file)
if (file.exists)
throw new IOException("Repository already exists: " + file)
file.mkdirs()
repository.create()
+ masterBranch = JGitBranch(repository, masterRef)
}
@After protected def removeRepository {
@@ -38,7 +41,7 @@ abstract class AbstractJGitTestCase {
}
protected def writeTextContent(text: String): ObjectId = {
- val ow = new ObjectWriter(repository)
+ val ow = new ObjectWriter(masterBranch.repository)
ow.writeBlob(text.getBytes("UTF-8"))
}
@@ -55,11 +58,11 @@ abstract class AbstractJGitTestCase {
builder.add(entry)
}
builder.finish()
- dc.writeTree(new ObjectWriter(repository))
+ dc.writeTree(new ObjectWriter(masterBranch.repository))
}
protected def createCommit(message: String, treeId: ObjectId): ObjectId = {
- val commit = new Commit(repository, Array())
+ val commit = new Commit(masterBranch.repository, Array())
val person = new PersonIdent("A U Thor", "author@example.com")
commit.setAuthor(person)
commit.setCommitter(person)
@@ -69,8 +72,8 @@ abstract class AbstractJGitTestCase {
commit.getCommitId
}
- protected def moveHEAD(commitId: ObjectId) {
- val refUpdate = repository.updateRef(Constants.HEAD)
+ protected def moveMaster(commitId: ObjectId) {
+ val refUpdate = masterBranch.repository.updateRef(masterRef)
refUpdate.setNewObjectId(commitId)
refUpdate.forceUpdate()
}
diff --git a/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala b/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala
index 14ad484..7fdfaf7 100644
--- a/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala
+++ b/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala
@@ -52,7 +52,7 @@ final class JGitDatabaseTestCase extends AbstractJGitTestCase {
)
commit(files)
- val db = new JGitDatabase(repository)
+ val db = new JGitDatabase(masterBranch)
val foundFiles = db.latestSnapshot.all(SimpleMessageFileType).toList
@@ -72,7 +72,7 @@ final class JGitDatabaseTestCase extends AbstractJGitTestCase {
)
commit(files)
- val db = new JGitDatabase(repository)
+ val db = new JGitDatabase(masterBranch)
val foundFiles = db.latestSnapshot.all(SimpleMessageFileType).toList
@@ -89,11 +89,11 @@ final class JGitDatabaseTestCase extends AbstractJGitTestCase {
entry.setObjectId(writeTextContent("text content"))
builder.add(entry)
builder.finish()
- val treeId = dc.writeTree(new org.spearce.jgit.lib.ObjectWriter(repository))
+ val treeId = dc.writeTree(new org.spearce.jgit.lib.ObjectWriter(masterBranch.repository))
val commitId = createCommit("Test commit", treeId)
- moveHEAD(commitId)
+ moveMaster(commitId)
- val db = new JGitDatabase(repository)
+ val db = new JGitDatabase(masterBranch)
val foundFiles = db.latestSnapshot.all(SimpleMessageFileType).toList
assertEquals(Nil, foundFiles)
@@ -112,7 +112,7 @@ final class JGitDatabaseTestCase extends AbstractJGitTestCase {
)
commit(files)
- val db = new JGitDatabase(repository)
+ val db = new JGitDatabase(masterBranch)
db.modify { snapshot =>
val sms = snapshot.query(SimpleMessageFileType, (sm: SimpleMessage) => sm.name == "second")
@@ -140,7 +140,7 @@ final class JGitDatabaseTestCase extends AbstractJGitTestCase {
)
commit(files)
- val db = new JGitDatabase(repository)
+ val db = new JGitDatabase(masterBranch)
db.modify { snapshot =>
val sms = snapshot.query(SimpleMessageFileType, (sm: SimpleMessage) => sm.name == "second")
@@ -158,7 +158,7 @@ final class JGitDatabaseTestCase extends AbstractJGitTestCase {
private def commit(files: List[(String, ObjectId)]) {
val treeId = addFiles(files)
val commitId = createCommit("Test", treeId)
- moveHEAD(commitId)
+ moveMaster(commitId)
}
}
diff --git a/src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala b/src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala
index ec1a7ee..2c1ca42 100644
--- a/src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala
+++ b/src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala
@@ -45,7 +45,7 @@ class JGitFileTestCase extends AbstractJGitTestCase {
val blobId = writeTextContent(expected.toString)
- val jGitFile = new JGitFile("test", blobId, SimpleMessageFileType, repository)
+ val jGitFile = new JGitFile("test", blobId, SimpleMessageFileType, masterBranch)
assertEquals(expected, jGitFile.message)
}
@@ -56,13 +56,13 @@ class JGitFileTestCase extends AbstractJGitTestCase {
val blobId = writeTextContent(message.toString)
- val jGitFile = new JGitFile("test", blobId, SimpleMessageFileType, repository)
+ val jGitFile = new JGitFile("test", blobId, SimpleMessageFileType, masterBranch)
assertEquals(expected, jGitFile.userObject)
}
@Test{val expected = classOf[JGitDatabaseException]}
def testMessageOfNonExistingObject {
- val jGitFile = new JGitFile("test", ObjectId.zeroId, SimpleMessageFileType, repository)
+ val jGitFile = new JGitFile("test", ObjectId.zeroId, SimpleMessageFileType, masterBranch)
jGitFile.message
}
}