Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce2010-07-22 18:17:00 +0000
committerShawn O. Pearce2010-07-22 21:56:34 +0000
commitfa9b225e06f16ca7fd7ffca5689f4af0942a73e1 (patch)
treed85054426a826f9b1495186d41252d0130f33407
parentab062caa2255054cca413985bbaa3ad7c1c9c383 (diff)
parent12fe0f2d1eb18aab2964532e99d11d4311d558eb (diff)
downloadjgit-fa9b225e06f16ca7fd7ffca5689f4af0942a73e1.tar.gz
jgit-fa9b225e06f16ca7fd7ffca5689f4af0942a73e1.tar.xz
jgit-fa9b225e06f16ca7fd7ffca5689f4af0942a73e1.zip
Merge branch 'delta'
* delta: (103 commits) Discard the uncompressed delta as soon as its compressed Honor pack.windowlimit to cap memory usage during packing Honor pack.threads and perform delta search in parallel Cache small deltas during packing Implement delta generation during packing debug-show-packdelta: Dump a pack delta to the console Initial pack format delta generator Add debugging toString() method to ObjectToPack Make ObjectToPack clearReuseAsIs signal available to subclasses Correctly classify the compressing objects phase Refactor ObjectToPack's delta depth setting Configure core.bigFileThreshold into PackWriter Add doNotDelta flag to ObjectToPack Add more configuration options to PackWriter Save object path hash codes during packing Add path hash code to ObjectWalk Add getObjectSize to ObjectReader Allow TemporaryBuffer.Heap to allocate smaller than 8 KiB Define a constant for 127 in DeltaEncoder Cap delta copy instructions at 64k ... Conflicts: org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java Change-Id: I7c7a05e443a48d32c836173a409ee7d340c70796
-rw-r--r--org.eclipse.jgit.http.server/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java4
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java49
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java2
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java2
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java7
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java2
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java14
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/FileResolver.java4
-rw-r--r--org.eclipse.jgit.http.test/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AdvertiseErrorTest.java9
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java9
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java17
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java15
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/util/HttpTestCase.java6
-rw-r--r--org.eclipse.jgit.iplog/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java18
-rw-r--r--org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogMeta.java4
-rw-r--r--org.eclipse.jgit.junit/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java17
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java2
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java183
-rw-r--r--org.eclipse.jgit.pgm/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin1
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java21
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java8
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java4
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java4
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java76
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java18
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java4
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java9
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java26
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java2
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java3
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java3
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java2
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java2
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java127
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java2
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Iplog.java2
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Ipzilla.java2
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java6
-rw-r--r--org.eclipse.jgit.test/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0007_GitIndexTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java44
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java18
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/SimilarityIndexTest.java16
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java20
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java20
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java16
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java14
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReadTreeTest.java18
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java7
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SampleDataRepositoryTestCase.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WorkDirCheckout_ReadTreeTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java28
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java75
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java5
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/ConcurrentRepackTest.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConcurrentRepackTest.java)26
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackFileTest.java387
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackIndexTestCase.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexTestCase.java)5
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackIndexV1Test.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV1Test.java)3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackIndexV2Test.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV2Test.java)3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackReverseIndexTest.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackReverseIndexTest.java)5
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackWriterTest.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackWriterTest.java)23
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefDirectoryTest.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDirectoryTest.java)6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefUpdateTest.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefUpdateTest.java)31
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/ReflogReaderTest.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogReaderTest.java)7
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RepositorySetupWorkDirTest.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositorySetupWorkDirTest.java)86
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0003_Basic.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0003_Basic.java)106
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0004_PackReader.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java)15
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/UnpackedObjectTest.java534
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/WindowCacheGetTest.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheGetTest.java)19
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/WindowCacheReconfigureTest.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheReconfigureTest.java)4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/XInputStream.java (renamed from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/XInputStream.java)2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/pack/DeltaIndexTest.java228
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/pack/DeltaStreamTest.java273
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java34
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java7
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java16
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/PostOrderTreeWalkTest.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathSuffixFilterTestCase.java30
-rw-r--r--org.eclipse.jgit/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java100
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java68
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java49
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java22
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java52
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java56
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuildIterator.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java21
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/errors/LargeObjectException.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexChangedEvent.java)38
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/errors/NoWorkTreeException.java59
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/errors/StoredObjectRepresentationNotAvailableException.java61
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/ConfigChangedEvent.java57
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/ConfigChangedListener.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryAdapter.java)25
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/IndexChangedEvent.java57
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/IndexChangedListener.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryListener.java)26
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/ListenerHandle.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/RefsChangedEvent.java)40
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/ListenerList.java142
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/RefsChangedEvent.java57
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/RefsChangedListener.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryChangedEvent.java)31
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/RepositoryEvent.java95
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/events/RepositoryListener.java49
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/AlternateRepositoryDatabase.java142
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java616
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BlobBasedConfig.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/CachedObjectDatabase.java132
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Commit.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java15
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/DeltaOfsPackedObjectLoader.java82
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/DeltaPackedObjectLoader.java118
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/FileTreeEntry.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java24
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java339
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java395
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java151
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java185
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectStream.java220
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectWriter.java331
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java526
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java1040
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/PackedObjectLoader.java188
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java1025
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryBuilder.java74
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java135
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Tag.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java111
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Tree.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/UnpackedObjectLoader.java223
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/WholePackedObjectLoader.java110
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java35
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java23
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java37
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PendingGenerator.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevObject.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java96
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ByteArrayWindow.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/ByteArrayWindow.java)45
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ByteBufferWindow.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/ByteBufferWindow.java)38
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ByteWindow.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/ByteWindow.java)67
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/CachedObjectDirectory.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/CachedObjectDirectory.java)129
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/FileBasedConfig.java)4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileObjectDatabase.java271
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileRepository.java328
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileRepositoryBuilder.java90
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedDeltaObject.java230
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LargePackedWholeObject.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/DeltaRefPackedObjectLoader.java)94
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LocalObjectRepresentation.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/PackOutputStream.java)105
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LocalObjectToPack.java78
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LockFile.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/LockFile.java)4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ObjectDirectory.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDirectory.java)232
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ObjectDirectoryInserter.java182
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java920
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndex.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/PackIndex.java)5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexV1.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/PackIndexV1.java)5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexV2.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/PackIndexV2.java)5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexWriter.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/PackIndexWriter.java)4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexWriterV1.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/PackIndexWriterV1.java)2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexWriterV2.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/PackIndexWriterV2.java)2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackInputStream.java85
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackLock.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/PackLock.java)4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackReverseIndex.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/PackReverseIndex.java)5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/RefDirectory.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectory.java)56
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/RefDirectoryRename.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryRename.java)9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/RefDirectoryUpdate.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryUpdate.java)6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ReflogReader.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogReader.java)6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java413
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObjectCache.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/UnpackedObjectCache.java)2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCache.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/WindowCache.java)2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheConfig.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/WindowCacheConfig.java)4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCursor.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/WindowCursor.java)141
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/BinaryDelta.java (renamed from org.eclipse.jgit/src/org/eclipse/jgit/lib/BinaryDelta.java)149
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaCache.java134
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaEncoder.java294
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaIndex.java586
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaIndexScanner.java130
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaStream.java341
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaWindow.java511
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaWindowEntry.java80
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/ObjectReuseAsIs.java136
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/ObjectToPack.java320
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java93
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackOutputStream.java213
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java1442
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/StoredObjectRepresentation.java90
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/ThreadSafeDeltaCache.java86
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java43
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java92
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleWriter.java69
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchConnection.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java47
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java40
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PushProcess.java52
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java26
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteRefUpdate.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java45
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java55
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java146
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java42
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java78
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/EmptyTreeIterator.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java56
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/LongList.java14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java52
243 files changed, 14011 insertions, 5615 deletions
diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
index b9aeef5195..edaa1edd19 100644
--- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
@@ -17,6 +17,7 @@ Import-Package: javax.servlet;version="[2.5.0,3.0.0)",
org.eclipse.jgit.lib;version="[0.9.0,0.10.0)",
org.eclipse.jgit.nls;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.file;version="[0.9.0,0.10.0)",
org.eclipse.jgit.transport;version="[0.9.0,0.10.0)",
org.eclipse.jgit.util;version="[0.9.0,0.10.0)",
org.eclipse.jgit.util.io;version="[0.9.0,0.10.0)"
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java
index dff1e8252e..d217fe1c35 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java
@@ -53,8 +53,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.ObjectDatabase;
-import org.eclipse.jgit.lib.ObjectDirectory;
-import org.eclipse.jgit.lib.PackFile;
+import org.eclipse.jgit.storage.file.ObjectDirectory;
+import org.eclipse.jgit.storage.file.PackFile;
/** Sends the current list of pack files, sorted most recent first. */
class InfoPacksServlet extends HttpServlet {
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java
index f667ce95a7..647919e065 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java
@@ -74,30 +74,35 @@ class InfoRefsServlet extends HttpServlet {
final Repository db = getRepository(req);
final RevWalk walk = new RevWalk(db);
- final RevFlag ADVERTISED = walk.newFlag("ADVERTISED");
+ try {
+ final RevFlag ADVERTISED = walk.newFlag("ADVERTISED");
- final OutputStreamWriter out = new OutputStreamWriter(
- new SmartOutputStream(req, rsp), Constants.CHARSET);
- final RefAdvertiser adv = new RefAdvertiser() {
- @Override
- protected void writeOne(final CharSequence line) throws IOException {
- // Whoever decided that info/refs should use a different
- // delimiter than the native git:// protocol shouldn't
- // be allowed to design this sort of stuff. :-(
- out.append(line.toString().replace(' ', '\t'));
- }
+ final OutputStreamWriter out = new OutputStreamWriter(
+ new SmartOutputStream(req, rsp), Constants.CHARSET);
+ final RefAdvertiser adv = new RefAdvertiser() {
+ @Override
+ protected void writeOne(final CharSequence line)
+ throws IOException {
+ // Whoever decided that info/refs should use a different
+ // delimiter than the native git:// protocol shouldn't
+ // be allowed to design this sort of stuff. :-(
+ out.append(line.toString().replace(' ', '\t'));
+ }
- @Override
- protected void end() {
- // No end marker required for info/refs format.
- }
- };
- adv.init(walk, ADVERTISED);
- adv.setDerefTags(true);
+ @Override
+ protected void end() {
+ // No end marker required for info/refs format.
+ }
+ };
+ adv.init(walk, ADVERTISED);
+ adv.setDerefTags(true);
- Map<String, Ref> refs = db.getAllRefs();
- refs.remove(Constants.HEAD);
- adv.send(refs);
- out.close();
+ Map<String, Ref> refs = db.getAllRefs();
+ refs.remove(Constants.HEAD);
+ adv.send(refs);
+ out.close();
+ } finally {
+ walk.release();
+ }
}
}
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java
index 34edf82792..019ec90bc4 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java
@@ -56,8 +56,8 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.storage.file.ObjectDirectory;
/**
* Requires the target {@link Repository} to be available via local filesystem.
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java
index 5d774a8248..84865121c0 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java
@@ -60,8 +60,8 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.storage.file.ObjectDirectory;
/** Sends any object from {@code GIT_DIR/objects/??/0 38}, or any pack file. */
abstract class ObjectFileServlet extends HttpServlet {
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java
index 49fd535a71..4bc05c1886 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java
@@ -83,7 +83,12 @@ class ReceivePackServlet extends HttpServlet {
protected void advertise(HttpServletRequest req, Repository db,
PacketLineOutRefAdvertiser pck) throws IOException,
ServiceNotEnabledException, ServiceNotAuthorizedException {
- receivePackFactory.create(req, db).sendAdvertisedRefs(pck);
+ ReceivePack rp = receivePackFactory.create(req, db);
+ try {
+ rp.sendAdvertisedRefs(pck);
+ } finally {
+ rp.getRevWalk().release();
+ }
}
}
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java
index 5bf5546cf7..650059bd38 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java
@@ -80,6 +80,8 @@ class TextFileServlet extends HttpServlet {
private byte[] read(final HttpServletRequest req) throws IOException {
final File gitdir = getRepository(req).getDirectory();
+ if (gitdir == null)
+ throw new FileNotFoundException(fileName);
return IO.readFully(new File(gitdir, fileName));
}
}
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java
index 92d41a0caf..602d66a90c 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java
@@ -83,7 +83,12 @@ class UploadPackServlet extends HttpServlet {
protected void advertise(HttpServletRequest req, Repository db,
PacketLineOutRefAdvertiser pck) throws IOException,
ServiceNotEnabledException, ServiceNotAuthorizedException {
- uploadPackFactory.create(req, db).sendAdvertisedRefs(pck);
+ UploadPack up = uploadPackFactory.create(req, db);
+ try {
+ up.sendAdvertisedRefs(pck);
+ } finally {
+ up.getRevWalk().release();
+ }
}
}
@@ -107,7 +112,12 @@ class UploadPackServlet extends HttpServlet {
up.setBiDirectionalPipe(false);
rsp.setContentType(RSP_TYPE);
- final SmartOutputStream out = new SmartOutputStream(req, rsp);
+ final SmartOutputStream out = new SmartOutputStream(req, rsp) {
+ @Override
+ public void flush() throws IOException {
+ doFlush();
+ }
+ };
up.upload(getInputStream(req), out, null);
out.close();
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/FileResolver.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/FileResolver.java
index cc062dbe88..296725b678 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/FileResolver.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/FileResolver.java
@@ -138,8 +138,10 @@ public class FileResolver implements RepositoryResolver {
Repository db) throws IOException {
if (isExportAll())
return true;
- else
+ else if (db.getDirectory() != null)
return new File(db.getDirectory(), "git-daemon-export-ok").exists();
+ else
+ return false;
}
private static boolean isUnreasonableName(final String name) {
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index 370bd40353..21dd60817d 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -29,5 +29,6 @@ Import-Package: javax.servlet;version="[2.5.0,3.0.0)",
org.eclipse.jgit.junit;version="[0.9.0,0.10.0)",
org.eclipse.jgit.lib;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.file;version="[0.9.0,0.10.0)",
org.eclipse.jgit.transport;version="[0.9.0,0.10.0)",
org.eclipse.jgit.util;version="[0.9.0,0.10.0)"
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AdvertiseErrorTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AdvertiseErrorTest.java
index 47d7806a1e..db4aa802e2 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AdvertiseErrorTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AdvertiseErrorTest.java
@@ -62,23 +62,24 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.RepositoryConfig;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
public class AdvertiseErrorTest extends HttpTestCase {
- private Repository remoteRepository;
+ private FileRepository remoteRepository;
private URIish remoteURI;
protected void setUp() throws Exception {
super.setUp();
- final TestRepository src = createTestRepository();
+ final TestRepository<FileRepository> src = createTestRepository();
final String srcName = src.getRepository().getDirectory().getName();
ServletContextHandler app = server.addContext("/git");
@@ -114,7 +115,7 @@ public class AdvertiseErrorTest extends HttpTestCase {
remoteRepository = src.getRepository();
remoteURI = toURIish(app, srcName);
- RepositoryConfig cfg = remoteRepository.getConfig();
+ FileBasedConfig cfg = remoteRepository.getConfig();
cfg.setBoolean("http", null, "receivepack", true);
cfg.save();
}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java
index 224ea05c18..18f8dc928b 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java
@@ -64,9 +64,10 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.RepositoryConfig;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.transport.PreReceiveHook;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.ReceiveCommand;
@@ -76,14 +77,14 @@ import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
public class HookMessageTest extends HttpTestCase {
- private Repository remoteRepository;
+ private FileRepository remoteRepository;
private URIish remoteURI;
protected void setUp() throws Exception {
super.setUp();
- final TestRepository src = createTestRepository();
+ final TestRepository<FileRepository> src = createTestRepository();
final String srcName = src.getRepository().getDirectory().getName();
ServletContextHandler app = server.addContext("/git");
@@ -124,7 +125,7 @@ public class HookMessageTest extends HttpTestCase {
remoteRepository = src.getRepository();
remoteURI = toURIish(app, srcName);
- RepositoryConfig cfg = remoteRepository.getConfig();
+ FileBasedConfig cfg = remoteRepository.getConfig();
cfg.setBoolean("http", null, "receivepack", true);
cfg.save();
}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java
index 729466df3b..4cc141bb41 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java
@@ -66,12 +66,13 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.transport.FetchConnection;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
public class HttpClientTests extends HttpTestCase {
- private TestRepository remoteRepository;
+ private TestRepository<FileRepository> remoteRepository;
private URIish dumbAuthNoneURI;
@@ -95,7 +96,7 @@ public class HttpClientTests extends HttpTestCase {
server.setUp();
- final String srcName = nameOf(remoteRepository);
+ final String srcName = nameOf(remoteRepository.getRepository());
dumbAuthNoneURI = toURIish(dNone, srcName);
dumbAuthBasicURI = toURIish(dBasic, srcName);
@@ -119,10 +120,10 @@ public class HttpClientTests extends HttpTestCase {
public Repository open(HttpServletRequest req, String name)
throws RepositoryNotFoundException,
ServiceNotEnabledException {
- if (!name.equals(nameOf(remoteRepository)))
+ final FileRepository db = remoteRepository.getRepository();
+ if (!name.equals(nameOf(db)))
throw new RepositoryNotFoundException(name);
- final Repository db = remoteRepository.getRepository();
db.incrementOpen();
return db;
}
@@ -133,8 +134,8 @@ public class HttpClientTests extends HttpTestCase {
return ctx;
}
- private static String nameOf(final TestRepository db) {
- return db.getRepository().getDirectory().getName();
+ private static String nameOf(final FileRepository db) {
+ return db.getDirectory().getName();
}
public void testRepositoryNotFound_Dumb() throws Exception {
@@ -198,7 +199,7 @@ public class HttpClientTests extends HttpTestCase {
}
public void testListRemote_Dumb_NoHEAD() throws Exception {
- Repository src = remoteRepository.getRepository();
+ FileRepository src = remoteRepository.getRepository();
File headref = new File(src.getDirectory(), Constants.HEAD);
assertTrue("HEAD used to be present", headref.delete());
assertFalse("HEAD is gone", headref.exists());
@@ -306,7 +307,7 @@ public class HttpClientTests extends HttpTestCase {
}
public void testListRemote_Smart_UploadPackDisabled() throws Exception {
- Repository src = remoteRepository.getRepository();
+ FileRepository src = remoteRepository.getRepository();
src.getConfig().setBoolean("http", null, "uploadpack", false);
src.getConfig().save();
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
index f7b3bdb203..a7b51c6819 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
@@ -79,11 +79,12 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.RepositoryConfig;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.storage.file.FileRepository;
+import org.eclipse.jgit.storage.file.ReflogReader;
import org.eclipse.jgit.transport.FetchConnection;
import org.eclipse.jgit.transport.HttpTransport;
import org.eclipse.jgit.transport.RemoteRefUpdate;
@@ -94,7 +95,7 @@ import org.eclipse.jgit.transport.URIish;
public class SmartClientSmartServerTest extends HttpTestCase {
private static final String HDR_TRANSFER_ENCODING = "Transfer-Encoding";
- private Repository remoteRepository;
+ private FileRepository remoteRepository;
private URIish remoteURI;
@@ -107,7 +108,7 @@ public class SmartClientSmartServerTest extends HttpTestCase {
protected void setUp() throws Exception {
super.setUp();
- final TestRepository src = createTestRepository();
+ final TestRepository<FileRepository> src = createTestRepository();
final String srcName = src.getRepository().getDirectory().getName();
ServletContextHandler app = server.addContext("/git");
@@ -489,10 +490,10 @@ public class SmartClientSmartServerTest extends HttpTestCase {
}
public void testPush_ChunkedEncoding() throws Exception {
- final TestRepository src = createTestRepository();
+ final TestRepository<FileRepository> src = createTestRepository();
final RevBlob Q_bin = src.blob(new TestRng("Q").nextBytes(128 * 1024));
final RevCommit Q = src.commit().add("Q", Q_bin).create();
- final Repository db = src.getRepository();
+ final FileRepository db = src.getRepository();
final String dstName = Constants.R_HEADS + "new.branch";
Transport t;
@@ -547,7 +548,7 @@ public class SmartClientSmartServerTest extends HttpTestCase {
}
private void enableReceivePack() throws IOException {
- final RepositoryConfig cfg = remoteRepository.getConfig();
+ final FileBasedConfig cfg = remoteRepository.getConfig();
cfg.setBoolean("http", null, "receivepack", true);
cfg.save();
}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/util/HttpTestCase.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/util/HttpTestCase.java
index e259757615..313b6ad90b 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/util/HttpTestCase.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/util/HttpTestCase.java
@@ -61,6 +61,7 @@ import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.URIish;
@@ -82,8 +83,9 @@ public abstract class HttpTestCase extends LocalDiskRepositoryTestCase {
super.tearDown();
}
- protected TestRepository createTestRepository() throws Exception {
- return new TestRepository(createBareRepository());
+ protected TestRepository<FileRepository> createTestRepository()
+ throws IOException {
+ return new TestRepository<FileRepository>(createBareRepository());
}
protected URIish toURIish(String path) throws URISyntaxException {
diff --git a/org.eclipse.jgit.iplog/META-INF/MANIFEST.MF b/org.eclipse.jgit.iplog/META-INF/MANIFEST.MF
index 4ff6144004..31a19b5ca0 100644
--- a/org.eclipse.jgit.iplog/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.iplog/META-INF/MANIFEST.MF
@@ -15,6 +15,7 @@ Import-Package: org.eclipse.jgit.diff;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revplot;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk.filter;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.file;version="[0.9.0,0.10.0)",
org.eclipse.jgit.transport;version="[0.9.0,0.10.0)",
org.eclipse.jgit.treewalk;version="[0.9.0,0.10.0)",
org.eclipse.jgit.treewalk.filter;version="[0.9.0,0.10.0)",
diff --git a/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java b/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java
index f64c329847..433d4338df 100644
--- a/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java
+++ b/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java
@@ -78,15 +78,13 @@ import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.MyersDiff;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.iplog.Committer.ActiveRange;
import org.eclipse.jgit.lib.BlobBasedConfig;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.MutableObjectId;
-import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.WindowCursor;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
@@ -144,7 +142,7 @@ public class IpLogGenerator {
private NameConflictTreeWalk tw;
- private final WindowCursor curs = new WindowCursor();
+ private ObjectReader curs;
private final MutableObjectId idbuf = new MutableObjectId();
@@ -184,8 +182,9 @@ public class IpLogGenerator {
throws IOException, ConfigInvalidException {
try {
db = repo;
- rw = new RevWalk(db);
- tw = new NameConflictTreeWalk(db);
+ curs = db.newObjectReader();
+ rw = new RevWalk(curs);
+ tw = new NameConflictTreeWalk(curs);
RevCommit c = rw.parseCommit(startCommit);
@@ -194,7 +193,7 @@ public class IpLogGenerator {
scanProjectCommits(meta.getProjects().get(0), c);
commits.add(c);
} finally {
- WindowCursor.release(curs);
+ curs.release();
db = null;
rw = null;
tw = null;
@@ -417,10 +416,7 @@ public class IpLogGenerator {
private byte[] openBlob(int side) throws IOException {
tw.getObjectId(idbuf, side);
- ObjectLoader ldr = db.openObject(curs, idbuf);
- if (ldr == null)
- throw new MissingObjectException(idbuf.copy(), Constants.OBJ_BLOB);
- return ldr.getCachedBytes();
+ return curs.open(idbuf, Constants.OBJ_BLOB).getCachedBytes();
}
/**
diff --git a/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogMeta.java b/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogMeta.java
index 89695bdb8d..2799a4a30b 100644
--- a/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogMeta.java
+++ b/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogMeta.java
@@ -58,9 +58,9 @@ import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.FileBasedConfig;
-import org.eclipse.jgit.lib.LockFile;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.storage.file.LockFile;
/**
* Manages the {@code .eclipse_iplog} file in a project.
diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
index 051079b78e..7f4dcfddd6 100644
--- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
@@ -18,6 +18,8 @@ Import-Package: junit.framework;version="[3.8.2,4.0.0)",
org.eclipse.jgit.revplot;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk.filter;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.file;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.pack;version="[0.9.0,0.10.0)",
org.eclipse.jgit.transport;version="[0.9.0,0.10.0)",
org.eclipse.jgit.treewalk;version="[0.9.0,0.10.0)",
org.eclipse.jgit.treewalk.filter;version="[0.9.0,0.10.0)",
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
index 001deb262b..2b82d82d74 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
@@ -62,12 +62,13 @@ import junit.framework.TestCase;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.FileBasedConfig;
import org.eclipse.jgit.lib.PersonIdent;
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.storage.file.FileBasedConfig;
+import org.eclipse.jgit.storage.file.FileRepository;
+import org.eclipse.jgit.storage.file.WindowCache;
+import org.eclipse.jgit.storage.file.WindowCacheConfig;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.SystemReader;
@@ -259,7 +260,7 @@ public abstract class LocalDiskRepositoryTestCase extends TestCase {
* @throws IOException
* the repository could not be created in the temporary area
*/
- protected Repository createBareRepository() throws IOException {
+ protected FileRepository createBareRepository() throws IOException {
return createRepository(true /* bare */);
}
@@ -270,7 +271,7 @@ public abstract class LocalDiskRepositoryTestCase extends TestCase {
* @throws IOException
* the repository could not be created in the temporary area
*/
- protected Repository createWorkRepository() throws IOException {
+ protected FileRepository createWorkRepository() throws IOException {
return createRepository(false /* not bare */);
}
@@ -284,11 +285,11 @@ public abstract class LocalDiskRepositoryTestCase extends TestCase {
* @throws IOException
* the repository could not be created in the temporary area
*/
- private Repository createRepository(boolean bare) throws IOException {
+ private FileRepository createRepository(boolean bare) throws IOException {
String uniqueId = System.currentTimeMillis() + "_" + (testCount++);
String gitdirName = "test" + uniqueId + (bare ? "" : "/") + Constants.DOT_GIT;
File gitdir = new File(trash, gitdirName).getCanonicalFile();
- Repository db = new Repository(gitdir);
+ FileRepository db = new FileRepository(gitdir);
assertFalse(gitdir.exists());
db.create();
@@ -323,7 +324,7 @@ public abstract class LocalDiskRepositoryTestCase extends TestCase {
putPersonIdent(env, "AUTHOR", author);
putPersonIdent(env, "COMMITTER", committer);
- final File cwd = db.getWorkDir();
+ final File cwd = db.getWorkTree();
final Process p = Runtime.getRuntime().exec(argv, toEnvArray(env), cwd);
p.getOutputStream().close();
p.getErrorStream().close();
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
index c502fb6344..eb08417bc8 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
@@ -52,7 +52,7 @@ import java.util.TimeZone;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.FileBasedConfig;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
index 59504aa780..3c58271257 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
@@ -73,22 +73,16 @@ import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
-import org.eclipse.jgit.lib.LockFile;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectChecker;
-import org.eclipse.jgit.lib.ObjectDatabase;
-import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectWriter;
-import org.eclipse.jgit.lib.PackFile;
-import org.eclipse.jgit.lib.PackWriter;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefWriter;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.Tag;
-import org.eclipse.jgit.lib.PackIndex.MutableEntry;
import org.eclipse.jgit.revwalk.ObjectWalk;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -96,11 +90,22 @@ import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.file.FileRepository;
+import org.eclipse.jgit.storage.file.LockFile;
+import org.eclipse.jgit.storage.file.ObjectDirectory;
+import org.eclipse.jgit.storage.file.PackFile;
+import org.eclipse.jgit.storage.file.PackIndex.MutableEntry;
+import org.eclipse.jgit.storage.pack.PackWriter;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
-/** Wrapper to make creating test data easier. */
-public class TestRepository {
+/**
+ * Wrapper to make creating test data easier.
+ *
+ * @param <R>
+ * type of Repository the test data is stored on.
+ */
+public class TestRepository<R extends Repository> {
private static final PersonIdent author;
private static final PersonIdent committer;
@@ -119,11 +124,11 @@ public class TestRepository {
committer = new PersonIdent(cn, ce, now, tz);
}
- private final Repository db;
+ private final R db;
private final RevWalk pool;
- private final ObjectWriter writer;
+ private final ObjectInserter inserter;
private long now;
@@ -132,9 +137,9 @@ public class TestRepository {
*
* @param db
* the test repository to write into.
- * @throws Exception
+ * @throws IOException
*/
- public TestRepository(Repository db) throws Exception {
+ public TestRepository(R db) throws IOException {
this(db, new RevWalk(db));
}
@@ -145,17 +150,17 @@ public class TestRepository {
* the test repository to write into.
* @param rw
* the RevObject pool to use for object lookup.
- * @throws Exception
+ * @throws IOException
*/
- public TestRepository(Repository db, RevWalk rw) throws Exception {
+ public TestRepository(R db, RevWalk rw) throws IOException {
this.db = db;
this.pool = rw;
- this.writer = new ObjectWriter(db);
+ this.inserter = db.newObjectInserter();
this.now = 1236977987000L;
}
/** @return the repository this helper class operates against. */
- public Repository getRepository() {
+ public R getRepository() {
return db;
}
@@ -200,7 +205,14 @@ public class TestRepository {
* @throws Exception
*/
public RevBlob blob(final byte[] content) throws Exception {
- return pool.lookupBlob(writer.writeBlob(content));
+ ObjectId id;
+ try {
+ id = inserter.insert(Constants.OBJ_BLOB, content);
+ inserter.flush();
+ } finally {
+ inserter.release();
+ }
+ return pool.lookupBlob(id);
}
/**
@@ -236,7 +248,14 @@ public class TestRepository {
for (final DirCacheEntry e : entries)
b.add(e);
b.finish();
- return pool.lookupTree(dc.writeTree(writer));
+ ObjectId root;
+ try {
+ root = dc.writeTree(inserter);
+ inserter.flush();
+ } finally {
+ inserter.release();
+ }
+ return pool.lookupTree(root);
}
/**
@@ -253,7 +272,7 @@ public class TestRepository {
*/
public RevObject get(final RevTree tree, final String path)
throws AssertionFailedError, Exception {
- final TreeWalk tw = new TreeWalk(db);
+ final TreeWalk tw = new TreeWalk(pool.getObjectReader());
tw.setFilter(PathFilterGroup.createFromStrings(Collections
.singleton(path)));
tw.reset(tree);
@@ -346,7 +365,14 @@ public class TestRepository {
c.setAuthor(new PersonIdent(author, new Date(now)));
c.setCommitter(new PersonIdent(committer, new Date(now)));
c.setMessage("");
- return pool.lookupCommit(writer.writeCommit(c));
+ ObjectId id;
+ try {
+ id = inserter.insert(Constants.OBJ_COMMIT, inserter.format(c));
+ inserter.flush();
+ } finally {
+ inserter.release();
+ }
+ return pool.lookupCommit(id);
}
/** @return a new commit builder. */
@@ -377,7 +403,14 @@ public class TestRepository {
t.setTag(name);
t.setTagger(new PersonIdent(committer, new Date(now)));
t.setMessage("");
- return (RevTag) pool.lookupAny(writer.writeTag(t), Constants.OBJ_TAG);
+ ObjectId id;
+ try {
+ id = inserter.insert(Constants.OBJ_TAG, inserter.format(t));
+ inserter.flush();
+ } finally {
+ inserter.release();
+ }
+ return (RevTag) pool.lookupAny(id, Constants.OBJ_TAG);
}
/**
@@ -443,25 +476,27 @@ public class TestRepository {
* @throws Exception
*/
public void updateServerInfo() throws Exception {
- final ObjectDatabase odb = db.getObjectDatabase();
- if (odb instanceof ObjectDirectory) {
- RefWriter rw = new RefWriter(db.getAllRefs().values()) {
+ if (db instanceof FileRepository) {
+ final FileRepository fr = (FileRepository) db;
+ RefWriter rw = new RefWriter(fr.getAllRefs().values()) {
@Override
protected void writeFile(final String name, final byte[] bin)
throws IOException {
- TestRepository.this.writeFile(name, bin);
+ File path = new File(fr.getDirectory(), name);
+ TestRepository.this.writeFile(path, bin);
}
};
rw.writePackedRefs();
rw.writeInfoRefs();
final StringBuilder w = new StringBuilder();
- for (PackFile p : ((ObjectDirectory) odb).getPacks()) {
+ for (PackFile p : fr.getObjectDatabase().getPacks()) {
w.append("P ");
w.append(p.getPackFile().getName());
w.append('\n');
}
- writeFile("objects/info/packs", Constants.encodeASCII(w.toString()));
+ writeFile(new File(new File(fr.getObjectDatabase().getDirectory(),
+ "info"), "packs"), Constants.encodeASCII(w.toString()));
}
}
@@ -528,7 +563,7 @@ public class TestRepository {
if (o == null)
break;
- final byte[] bin = db.openObject(o).getCachedBytes();
+ final byte[] bin = db.open(o, o.getType()).getCachedBytes();
oc.checkCommit(bin);
assertHash(o, bin);
}
@@ -538,7 +573,7 @@ public class TestRepository {
if (o == null)
break;
- final byte[] bin = db.openObject(o).getCachedBytes();
+ final byte[] bin = db.open(o, o.getType()).getCachedBytes();
oc.check(o.getType(), bin);
assertHash(o, bin);
}
@@ -563,38 +598,46 @@ public class TestRepository {
* @throws Exception
*/
public void packAndPrune() throws Exception {
- final ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
- final PackWriter pw = new PackWriter(db, NullProgressMonitor.INSTANCE);
-
- Set<ObjectId> all = new HashSet<ObjectId>();
- for (Ref r : db.getAllRefs().values())
- all.add(r.getObjectId());
- pw.preparePack(all, Collections.<ObjectId> emptySet());
-
- final ObjectId name = pw.computeName();
- OutputStream out;
-
- final File pack = nameFor(odb, name, ".pack");
- out = new BufferedOutputStream(new FileOutputStream(pack));
- try {
- pw.writePack(out);
- } finally {
- out.close();
- }
- pack.setReadOnly();
+ if (db.getObjectDatabase() instanceof ObjectDirectory) {
+ ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
+ NullProgressMonitor m = NullProgressMonitor.INSTANCE;
+
+ final File pack, idx;
+ PackWriter pw = new PackWriter(db);
+ try {
+ Set<ObjectId> all = new HashSet<ObjectId>();
+ for (Ref r : db.getAllRefs().values())
+ all.add(r.getObjectId());
+ pw.preparePack(m, all, Collections.<ObjectId> emptySet());
+
+ final ObjectId name = pw.computeName();
+ OutputStream out;
+
+ pack = nameFor(odb, name, ".pack");
+ out = new BufferedOutputStream(new FileOutputStream(pack));
+ try {
+ pw.writePack(m, m, out);
+ } finally {
+ out.close();
+ }
+ pack.setReadOnly();
+
+ idx = nameFor(odb, name, ".idx");
+ out = new BufferedOutputStream(new FileOutputStream(idx));
+ try {
+ pw.writeIndex(out);
+ } finally {
+ out.close();
+ }
+ idx.setReadOnly();
+ } finally {
+ pw.release();
+ }
- final File idx = nameFor(odb, name, ".idx");
- out = new BufferedOutputStream(new FileOutputStream(idx));
- try {
- pw.writeIndex(out);
- } finally {
- out.close();
+ odb.openPack(pack, idx);
+ updateServerInfo();
+ prunePacked(odb);
}
- idx.setReadOnly();
-
- odb.openPack(pack, idx);
- updateServerInfo();
- prunePacked(odb);
}
private void prunePacked(ObjectDirectory odb) {
@@ -609,9 +652,8 @@ public class TestRepository {
return new File(packdir, "pack-" + name.name() + t);
}
- private void writeFile(final String name, final byte[] bin)
- throws IOException, ObjectWritingException {
- final File p = new File(db.getDirectory(), name);
+ private void writeFile(final File p, final byte[] bin) throws IOException,
+ ObjectWritingException {
final LockFile lck = new LockFile(p);
if (!lck.lock())
throw new ObjectWritingException("Can't write " + p);
@@ -711,7 +753,8 @@ public class TestRepository {
if (parents.isEmpty()) {
DirCacheBuilder b = tree.builder();
parseBody(p);
- b.addTree(new byte[0], DirCacheEntry.STAGE_0, db, p.getTree());
+ b.addTree(new byte[0], DirCacheEntry.STAGE_0, pool
+ .getObjectReader(), p.getTree());
b.finish();
}
parents.add(p);
@@ -769,13 +812,21 @@ public class TestRepository {
TestRepository.this.tick(tick);
final Commit c = new Commit(db);
- c.setTreeId(pool.lookupTree(tree.writeTree(writer)));
c.setParentIds(parents.toArray(new RevCommit[parents.size()]));
c.setAuthor(new PersonIdent(author, new Date(now)));
c.setCommitter(new PersonIdent(committer, new Date(now)));
c.setMessage(message);
- self = pool.lookupCommit(writer.writeCommit(c));
+ ObjectId commitId;
+ try {
+ c.setTreeId(tree.writeTree(inserter));
+ commitId = inserter.insert(Constants.OBJ_COMMIT, inserter
+ .format(c));
+ inserter.flush();
+ } finally {
+ inserter.release();
+ }
+ self = pool.lookupCommit(commitId);
if (branch != null)
branch.update(self);
diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
index 8628896780..d6eac232e1 100644
--- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
@@ -17,6 +17,8 @@ Import-Package: org.eclipse.jgit.api;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revplot;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk.filter;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.file;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.pack;version="[0.9.0,0.10.0)",
org.eclipse.jgit.transport;version="[0.9.0,0.10.0)",
org.eclipse.jgit.treewalk;version="[0.9.0,0.10.0)",
org.eclipse.jgit.treewalk.filter;version="[0.9.0,0.10.0)",
diff --git a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
index 0d4a140e62..075cadef79 100644
--- a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
+++ b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
@@ -30,6 +30,7 @@ org.eclipse.jgit.pgm.debug.RebuildCommitGraph
org.eclipse.jgit.pgm.debug.ShowCacheTree
org.eclipse.jgit.pgm.debug.ShowCommands
org.eclipse.jgit.pgm.debug.ShowDirCache
+org.eclipse.jgit.pgm.debug.ShowPackDelta
org.eclipse.jgit.pgm.debug.WriteDirCache
org.eclipse.jgit.pgm.eclipse.Iplog
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java
index b0f51ec58a..22302bba81 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java
@@ -61,10 +61,10 @@ import org.eclipse.jgit.lib.GitIndex;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefComparator;
import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.lib.Tree;
import org.eclipse.jgit.lib.WorkDirCheckout;
+import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
@@ -82,6 +82,8 @@ class Clone extends AbstractFetchCommand {
@Argument(index = 1, metaVar = "metaVar_directory")
private String localName;
+ private FileRepository dst;
+
@Override
protected final boolean requiresRepository() {
return false;
@@ -103,10 +105,11 @@ class Clone extends AbstractFetchCommand {
if (gitdir == null)
gitdir = new File(localName, Constants.DOT_GIT);
- db = new Repository(gitdir);
- db.create();
- db.getConfig().setBoolean("core", null, "bare", false);
- db.getConfig().save();
+ dst = new FileRepository(gitdir);
+ dst.create();
+ dst.getConfig().setBoolean("core", null, "bare", false);
+ dst.getConfig().save();
+ db = dst;
out.format(CLIText.get().initializedEmptyGitRepositoryIn, gitdir.getAbsolutePath());
out.println();
@@ -120,13 +123,13 @@ class Clone extends AbstractFetchCommand {
private void saveRemote(final URIish uri) throws URISyntaxException,
IOException {
- final RemoteConfig rc = new RemoteConfig(db.getConfig(), remoteName);
+ final RemoteConfig rc = new RemoteConfig(dst.getConfig(), remoteName);
rc.addURI(uri);
rc.addFetchRefSpec(new RefSpec().setForceUpdate(true)
.setSourceDestination(Constants.R_HEADS + "*",
Constants.R_REMOTES + remoteName + "/*"));
- rc.update(db.getConfig());
- db.getConfig().save();
+ rc.update(dst.getConfig());
+ dst.getConfig().save();
}
private FetchResult runFetch() throws NotSupportedException,
@@ -180,7 +183,7 @@ class Clone extends AbstractFetchCommand {
final Tree tree = commit.getTree();
final WorkDirCheckout co;
- co = new WorkDirCheckout(db, db.getWorkDir(), index, tree);
+ co = new WorkDirCheckout(db, db.getWorkTree(), index, tree);
co.checkout();
index.write();
}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java
index 3dfd8ff62d..ae11f67317 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java
@@ -125,10 +125,12 @@ class Glog extends RevWalkTextBuiltin {
}
private String repoName() {
- final File f = db.getDirectory();
- String n = f.getName();
+ final File gitDir = db.getDirectory();
+ if (gitDir == null)
+ return db.toString();
+ String n = gitDir.getName();
if (Constants.DOT_GIT.equals(n))
- n = f.getParentFile().getName();
+ n = gitDir.getParentFile().getName();
return n;
}
}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java
index 35fd2a5971..640c8ef348 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java
@@ -49,6 +49,7 @@ import java.io.File;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.CoreConfig;
import org.eclipse.jgit.lib.TextProgressMonitor;
class IndexPack extends TextBuiltin {
@@ -64,7 +65,8 @@ class IndexPack extends TextBuiltin {
@Override
protected void run() throws Exception {
if (indexVersion == -1)
- indexVersion = db.getConfig().getCore().getPackIndexVersion();
+ indexVersion = db.getConfig().get(CoreConfig.KEY)
+ .getPackIndexVersion();
final BufferedInputStream in;
final org.eclipse.jgit.transport.IndexPack ip;
in = new BufferedInputStream(System.in);
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java
index d8c7bdfb4a..c5a696a57f 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java
@@ -50,7 +50,7 @@ import java.text.MessageFormat;
import org.kohsuke.args4j.Option;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.storage.file.FileRepository;
@Command(common = true, usage = "usage_CreateAnEmptyGitRepository")
class Init extends TextBuiltin {
@@ -66,7 +66,7 @@ class Init extends TextBuiltin {
protected void run() throws Exception {
if (gitdir == null)
gitdir = new File(bare ? "." : Constants.DOT_GIT);
- db = new Repository(gitdir);
+ db = new FileRepository(gitdir);
db.create(bare);
out.println(MessageFormat.format(CLIText.get().initializedEmptyGitRepositoryIn, gitdir.getAbsolutePath()));
}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
index 306ac816d8..ab11062cc2 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
@@ -51,20 +51,15 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import org.eclipse.jgit.awtui.AwtAuthenticator;
import org.eclipse.jgit.awtui.AwtSshSessionFactory;
import org.eclipse.jgit.errors.TransportException;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryBuilder;
import org.eclipse.jgit.pgm.opt.CmdLineParser;
import org.eclipse.jgit.pgm.opt.SubcommandHandler;
import org.eclipse.jgit.util.CachedAuthenticator;
-import org.eclipse.jgit.util.SystemReader;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.ExampleMode;
@@ -168,51 +163,17 @@ public class Main {
final TextBuiltin cmd = subcommand;
if (cmd.requiresRepository()) {
- if (gitdir == null) {
- String gitDirEnv = SystemReader.getInstance().getenv(Constants.GIT_DIR_KEY);
- if (gitDirEnv != null)
- gitdir = new File(gitDirEnv);
- }
- if (gitdir == null)
- gitdir = findGitDir();
-
- File gitworktree;
- String gitWorkTreeEnv = SystemReader.getInstance().getenv(Constants.GIT_WORK_TREE_KEY);
- if (gitWorkTreeEnv != null)
- gitworktree = new File(gitWorkTreeEnv);
- else
- gitworktree = null;
-
- File indexfile;
- String indexFileEnv = SystemReader.getInstance().getenv(Constants.GIT_INDEX_KEY);
- if (indexFileEnv != null)
- indexfile = new File(indexFileEnv);
- else
- indexfile = null;
-
- File objectdir;
- String objectDirEnv = SystemReader.getInstance().getenv(Constants.GIT_OBJECT_DIRECTORY_KEY);
- if (objectDirEnv != null)
- objectdir = new File(objectDirEnv);
- else
- objectdir = null;
-
- File[] altobjectdirs;
- String altObjectDirEnv = SystemReader.getInstance().getenv(Constants.GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY);
- if (altObjectDirEnv != null) {
- String[] parserdAltObjectDirEnv = altObjectDirEnv.split(File.pathSeparator);
- altobjectdirs = new File[parserdAltObjectDirEnv.length];
- for (int i = 0; i < parserdAltObjectDirEnv.length; i++)
- altobjectdirs[i] = new File(parserdAltObjectDirEnv[i]);
- } else
- altobjectdirs = null;
-
- if (gitdir == null || !gitdir.isDirectory()) {
+ RepositoryBuilder rb = new RepositoryBuilder() //
+ .setGitDir(gitdir) //
+ .readEnvironment() //
+ .findGitDir();
+ if (rb.getGitDir() == null) {
writer.println(CLIText.get().cantFindGitDirectory);
writer.flush();
System.exit(1);
}
- cmd.init(new Repository(gitdir, gitworktree, objectdir, altobjectdirs, indexfile), gitdir);
+
+ cmd.init(rb.build(), null);
} else {
cmd.init(null, gitdir);
}
@@ -224,27 +185,6 @@ public class Main {
}
}
- private static File findGitDir() {
- Set<String> ceilingDirectories = new HashSet<String>();
- String ceilingDirectoriesVar = SystemReader.getInstance().getenv(
- Constants.GIT_CEILING_DIRECTORIES_KEY);
- if (ceilingDirectoriesVar != null) {
- ceilingDirectories.addAll(Arrays.asList(ceilingDirectoriesVar
- .split(File.pathSeparator)));
- }
- File current = new File("").getAbsoluteFile();
- while (current != null) {
- final File gitDir = new File(current, Constants.DOT_GIT);
- if (gitDir.isDirectory())
- return gitDir;
- current = current.getParentFile();
- if (current != null
- && ceilingDirectories.contains(current.getPath()))
- break;
- }
- return null;
- }
-
private static boolean installConsole() {
try {
install("org.eclipse.jgit.console.ConsoleAuthenticator");
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java
index 09a9f2b580..7a27617220 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java
@@ -47,9 +47,10 @@ package org.eclipse.jgit.pgm;
import java.io.File;
import java.text.MessageFormat;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.RepositoryCache.FileKey;
+import org.eclipse.jgit.util.FS;
import org.kohsuke.args4j.Argument;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.Repository;
@Command(common = false, usage = "usage_ServerSideBackendForJgitPush")
class ReceivePack extends TextBuiltin {
@@ -65,11 +66,14 @@ class ReceivePack extends TextBuiltin {
protected void run() throws Exception {
final org.eclipse.jgit.transport.ReceivePack rp;
- if (new File(dstGitdir, Constants.DOT_GIT).isDirectory())
- dstGitdir = new File(dstGitdir, Constants.DOT_GIT);
- db = new Repository(dstGitdir);
- if (!db.getObjectsDirectory().isDirectory())
- throw die(MessageFormat.format(CLIText.get().notAGitRepository, dstGitdir.getPath()));
+ try {
+ FileKey key = FileKey.lenient(dstGitdir, FS.DETECTED);
+ db = key.open(true /* must exist */);
+ } catch (RepositoryNotFoundException notFound) {
+ throw die(MessageFormat.format(CLIText.get().notAGitRepository,
+ dstGitdir.getPath()));
+ }
+
rp = new org.eclipse.jgit.transport.ReceivePack(db);
rp.receive(System.in, System.out, System.err);
}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java
index 1b8711dc9d..9f577ff05e 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java
@@ -67,9 +67,9 @@ class Rm extends TextBuiltin {
@Override
protected void run() throws Exception {
- root = db.getWorkDir();
+ root = db.getWorkTree();
- final DirCache dirc = DirCache.lock(db);
+ final DirCache dirc = db.lockDirCache();
final DirCacheBuilder edit = dirc.builder();
final TreeWalk walk = new TreeWalk(db);
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java
index 63d26eacae..c798950a2e 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java
@@ -49,13 +49,12 @@ package org.eclipse.jgit.pgm;
import java.text.MessageFormat;
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
-import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.PersonIdent;
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
@Command(common = true, usage = "usage_CreateATag")
class Tag extends TextBuiltin {
@@ -86,9 +85,7 @@ class Tag extends TextBuiltin {
, tagName.substring(Constants.R_TAGS.length())));
}
- final ObjectLoader ldr = db.openObject(object);
- if (ldr == null)
- throw new MissingObjectException(object, "any");
+ final ObjectLoader ldr = db.open(object);
org.eclipse.jgit.lib.Tag tag = new org.eclipse.jgit.lib.Tag(db);
tag.setObjId(object);
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java
index 52d2488f70..d4e2bcec76 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java
@@ -47,10 +47,11 @@ package org.eclipse.jgit.pgm;
import java.io.File;
import java.text.MessageFormat;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.RepositoryCache.FileKey;
+import org.eclipse.jgit.util.FS;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.Repository;
@Command(common = false, usage = "usage_ServerSideBackendForJgitFetch")
class UploadPack extends TextBuiltin {
@@ -67,16 +68,19 @@ class UploadPack extends TextBuiltin {
@Override
protected void run() throws Exception {
- final org.eclipse.jgit.transport.UploadPack rp;
+ final org.eclipse.jgit.transport.UploadPack up;
- if (new File(srcGitdir, Constants.DOT_GIT).isDirectory())
- srcGitdir = new File(srcGitdir, Constants.DOT_GIT);
- db = new Repository(srcGitdir);
- if (!db.getObjectsDirectory().isDirectory())
- throw die(MessageFormat.format(CLIText.get().notAGitRepository, srcGitdir.getPath()));
- rp = new org.eclipse.jgit.transport.UploadPack(db);
+ try {
+ FileKey key = FileKey.lenient(srcGitdir, FS.DETECTED);
+ db = key.open(true /* must exist */);
+ } catch (RepositoryNotFoundException notFound) {
+ throw die(MessageFormat.format(CLIText.get().notAGitRepository,
+ srcGitdir.getPath()));
+ }
+
+ up = new org.eclipse.jgit.transport.UploadPack(db);
if (0 <= timeout)
- rp.setTimeout(timeout);
- rp.upload(System.in, System.out, System.err);
+ up.setTimeout(timeout);
+ up.upload(System.in, System.out, System.err);
}
}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java
index d772ffe23f..709b45a17b 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java
@@ -54,7 +54,7 @@ import org.eclipse.jgit.pgm.TextBuiltin;
class MakeCacheTree extends TextBuiltin {
@Override
protected void run() throws Exception {
- final DirCache cache = DirCache.read(db);
+ final DirCache cache = db.readDirCache();
final DirCacheTree tree = cache.getCacheTree(true);
show(tree);
}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java
index 2a1079b313..0ca050880e 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java
@@ -46,7 +46,6 @@ package org.eclipse.jgit.pgm.debug;
import java.text.MessageFormat;
-import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.pgm.CLIText;
import org.eclipse.jgit.pgm.TextBuiltin;
@@ -56,7 +55,7 @@ class ReadDirCache extends TextBuiltin {
final int cnt = 100;
final long start = System.currentTimeMillis();
for (int i = 0; i < cnt; i++)
- DirCache.read(db);
+ db.readDirCache();
final long end = System.currentTimeMillis();
out.print(" ");
out.println(MessageFormat.format(CLIText.get().averageMSPerRead, (end - start) / cnt));
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
index 1681dbc96e..5b75c1b5c5 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
@@ -62,7 +62,6 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.ObjectWritingException;
import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.LockFile;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.ObjectWriter;
@@ -76,6 +75,7 @@ import org.eclipse.jgit.lib.Tree;
import org.eclipse.jgit.pgm.CLIText;
import org.eclipse.jgit.pgm.TextBuiltin;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.file.LockFile;
/**
* Recreates a repository from another one's commit graph.
@@ -297,6 +297,7 @@ class RebuildCommitGraph extends TextBuiltin {
name, id));
}
} finally {
+ rw.release();
br.close();
}
return refs;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java
index 09796edb30..c49aefbf2f 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java
@@ -54,7 +54,7 @@ import org.eclipse.jgit.pgm.TextBuiltin;
class ShowCacheTree extends TextBuiltin {
@Override
protected void run() throws Exception {
- final DirCache cache = DirCache.read(db);
+ final DirCache cache = db.readDirCache();
final DirCacheTree tree = cache.getCacheTree(false);
if (tree == null)
throw die(CLIText.get().noTREESectionInIndex);
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java
index 854596c97b..a94d37ff87 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java
@@ -59,7 +59,7 @@ class ShowDirCache extends TextBuiltin {
final SimpleDateFormat fmt;
fmt = new SimpleDateFormat("yyyyMMdd,HHmmss.SSS");
- final DirCache cache = DirCache.read(db);
+ final DirCache cache = db.readDirCache();
for (int i = 0; i < cache.getEntryCount(); i++) {
final DirCacheEntry ent = cache.getEntry(i);
final FileMode mode = FileMode.fromBits(ent.getRawMode());
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java
new file mode 100644
index 0000000000..1718ef30f2
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.pgm.debug;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.zip.InflaterInputStream;
+
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.pgm.TextBuiltin;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.pack.BinaryDelta;
+import org.eclipse.jgit.storage.pack.ObjectReuseAsIs;
+import org.eclipse.jgit.storage.pack.ObjectToPack;
+import org.eclipse.jgit.storage.pack.PackOutputStream;
+import org.eclipse.jgit.storage.pack.PackWriter;
+import org.eclipse.jgit.storage.pack.StoredObjectRepresentation;
+import org.eclipse.jgit.util.TemporaryBuffer;
+import org.kohsuke.args4j.Argument;
+
+class ShowPackDelta extends TextBuiltin {
+ @Argument(index = 0)
+ private ObjectId objectId;
+
+ @Override
+ protected void run() throws Exception {
+ ObjectReader reader = db.newObjectReader();
+ RevObject obj = new RevWalk(reader).parseAny(objectId);
+ byte[] delta = getDelta(reader, obj);
+
+ // We're crossing our fingers that this will be a delta. Double
+ // check the size field in the header, it should match.
+ //
+ long size = reader.getObjectSize(obj, obj.getType());
+ try {
+ if (BinaryDelta.getResultSize(delta) != size)
+ throw die("Object " + obj.name() + " is not a delta");
+ } catch (ArrayIndexOutOfBoundsException bad) {
+ throw die("Object " + obj.name() + " is not a delta");
+ }
+
+ out.println(BinaryDelta.format(delta));
+ }
+
+ private byte[] getDelta(ObjectReader reader, RevObject obj)
+ throws IOException, MissingObjectException,
+ StoredObjectRepresentationNotAvailableException {
+ ObjectReuseAsIs asis = (ObjectReuseAsIs) reader;
+ ObjectToPack target = asis.newObjectToPack(obj);
+
+ PackWriter pw = new PackWriter(reader) {
+ @Override
+ public void select(ObjectToPack otp, StoredObjectRepresentation next) {
+ otp.select(next);
+ }
+ };
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ asis.selectObjectRepresentation(pw, target);
+ asis.copyObjectAsIs(new PackOutputStream(NullProgressMonitor.INSTANCE,
+ buf, pw), target);
+
+ // At this point the object header has no delta information,
+ // because it was output as though it were a whole object.
+ // Skip over the header and inflate.
+ //
+ byte[] bufArray = buf.toByteArray();
+ int ptr = 0;
+ while ((bufArray[ptr] & 0x80) != 0)
+ ptr++;
+ ptr++;
+
+ TemporaryBuffer.Heap raw = new TemporaryBuffer.Heap(bufArray.length);
+ InflaterInputStream inf = new InflaterInputStream(
+ new ByteArrayInputStream(bufArray, ptr, bufArray.length));
+ raw.copy(inf);
+ inf.close();
+ return raw.toByteArray();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java
index cee5966a03..142dbeecc8 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java
@@ -51,7 +51,7 @@ import org.eclipse.jgit.pgm.TextBuiltin;
class WriteDirCache extends TextBuiltin {
@Override
protected void run() throws Exception {
- final DirCache cache = DirCache.read(db);
+ final DirCache cache = db.readDirCache();
if (!cache.lock())
throw die(CLIText.get().failedToLockIndex);
cache.read();
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Iplog.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Iplog.java
index e13bb1f136..a99e0abca2 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Iplog.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Iplog.java
@@ -51,7 +51,6 @@ import java.text.MessageFormat;
import org.eclipse.jgit.iplog.IpLogGenerator;
import org.eclipse.jgit.iplog.SimpleCookieManager;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.LockFile;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.pgm.CLIText;
import org.eclipse.jgit.pgm.Command;
@@ -59,6 +58,7 @@ import org.eclipse.jgit.pgm.TextBuiltin;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.file.LockFile;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Ipzilla.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Ipzilla.java
index 4f0e338e8d..b563f07910 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Ipzilla.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/eclipse/Ipzilla.java
@@ -91,7 +91,7 @@ class Ipzilla extends TextBuiltin {
}
if (output == null)
- output = new File(db.getWorkDir(), IpLogMeta.IPLOG_CONFIG_FILE);
+ output = new File(db.getWorkTree(), IpLogMeta.IPLOG_CONFIG_FILE);
IpLogMeta meta = new IpLogMeta();
meta.syncCQs(output, ipzilla, username, password);
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java
index 2043ac2090..01981600dd 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java
@@ -59,7 +59,7 @@ import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.WindowCursor;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.pgm.CLIText;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
@@ -121,9 +121,9 @@ public class AbstractTreeIteratorHandler extends
throw new CmdLineException(MessageFormat.format(CLIText.get().notATree, name));
final CanonicalTreeParser p = new CanonicalTreeParser();
- final WindowCursor curs = new WindowCursor();
+ final ObjectReader curs = clp.getRepository().newObjectReader();
try {
- p.reset(clp.getRepository(), clp.getRevWalk().parseTree(id), curs);
+ p.reset(curs, clp.getRevWalk().parseTree(id));
} catch (MissingObjectException e) {
throw new CmdLineException(MessageFormat.format(CLIText.get().notATree, name));
} catch (IncorrectObjectTypeException e) {
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index 3aaa8a45e8..d6128afc97 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -29,6 +29,8 @@ Import-Package: junit.framework;version="[3.8.2,4.0.0)",
org.eclipse.jgit.revplot;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk;version="[0.9.0,0.10.0)",
org.eclipse.jgit.revwalk.filter;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.file;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.pack;version="[0.9.0,0.10.0)",
org.eclipse.jgit.transport;version="[0.9.0,0.10.0)",
org.eclipse.jgit.treewalk;version="[0.9.0,0.10.0)",
org.eclipse.jgit.treewalk.filter;version="[0.9.0,0.10.0)",
diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0007_GitIndexTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0007_GitIndexTest.java
index dd3b51efc7..c5591b9bfd 100644
--- a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0007_GitIndexTest.java
+++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0007_GitIndexTest.java
@@ -116,7 +116,7 @@ public class T0007_GitIndexTest extends LocalDiskRepositoryTestCase {
protected void setUp() throws Exception {
super.setUp();
db = createWorkRepository();
- trash = db.getWorkDir();
+ trash = db.getWorkTree();
}
public void testCreateEmptyIndex() throws Exception {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
index ab011807cb..9e195b4974 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
@@ -78,7 +78,7 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddExistingSingleFile() throws IOException, NoFilepatternException {
- File file = new File(db.getWorkDir(), "a.txt");
+ File file = new File(db.getWorkTree(), "a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
@@ -98,8 +98,8 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddExistingSingleFileInSubDir() throws IOException, NoFilepatternException {
- new File(db.getWorkDir(), "sub").mkdir();
- File file = new File(db.getWorkDir(), "sub/a.txt");
+ new File(db.getWorkTree(), "sub").mkdir();
+ File file = new File(db.getWorkTree(), "sub/a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
@@ -119,7 +119,7 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddExistingSingleFileTwice() throws IOException, NoFilepatternException {
- File file = new File(db.getWorkDir(), "a.txt");
+ File file = new File(db.getWorkTree(), "a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
@@ -143,7 +143,7 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddExistingSingleFileTwiceWithCommit() throws Exception {
- File file = new File(db.getWorkDir(), "a.txt");
+ File file = new File(db.getWorkTree(), "a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
@@ -169,7 +169,7 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddRemovedFile() throws Exception {
- File file = new File(db.getWorkDir(), "a.txt");
+ File file = new File(db.getWorkTree(), "a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
@@ -191,7 +191,7 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddRemovedCommittedFile() throws Exception {
- File file = new File(db.getWorkDir(), "a.txt");
+ File file = new File(db.getWorkTree(), "a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
@@ -217,20 +217,20 @@ public class AddCommandTest extends RepositoryTestCase {
public void testAddWithConflicts() throws Exception {
// prepare conflict
- File file = new File(db.getWorkDir(), "a.txt");
+ File file = new File(db.getWorkTree(), "a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
writer.close();
- File file2 = new File(db.getWorkDir(), "b.txt");
+ File file2 = new File(db.getWorkTree(), "b.txt");
file2.createNewFile();
writer = new PrintWriter(file2);
writer.print("content b");
writer.close();
ObjectWriter ow = new ObjectWriter(db);
- DirCache dc = DirCache.lock(db);
+ DirCache dc = db.lockDirCache();
DirCacheBuilder builder = dc.builder();
addEntryToBuilder("b.txt", file2, ow, builder, 0);
@@ -264,13 +264,13 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddTwoFiles() throws Exception {
- File file = new File(db.getWorkDir(), "a.txt");
+ File file = new File(db.getWorkTree(), "a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
writer.close();
- File file2 = new File(db.getWorkDir(), "b.txt");
+ File file2 = new File(db.getWorkTree(), "b.txt");
file2.createNewFile();
writer = new PrintWriter(file2);
writer.print("content b");
@@ -287,14 +287,14 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddFolder() throws Exception {
- new File(db.getWorkDir(), "sub").mkdir();
- File file = new File(db.getWorkDir(), "sub/a.txt");
+ new File(db.getWorkTree(), "sub").mkdir();
+ File file = new File(db.getWorkTree(), "sub/a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
writer.close();
- File file2 = new File(db.getWorkDir(), "sub/b.txt");
+ File file2 = new File(db.getWorkTree(), "sub/b.txt");
file2.createNewFile();
writer = new PrintWriter(file2);
writer.print("content b");
@@ -311,20 +311,20 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddIgnoredFile() throws Exception {
- new File(db.getWorkDir(), "sub").mkdir();
- File file = new File(db.getWorkDir(), "sub/a.txt");
+ new File(db.getWorkTree(), "sub").mkdir();
+ File file = new File(db.getWorkTree(), "sub/a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
writer.close();
- File ignoreFile = new File(db.getWorkDir(), ".gitignore");
+ File ignoreFile = new File(db.getWorkTree(), ".gitignore");
ignoreFile.createNewFile();
writer = new PrintWriter(ignoreFile);
writer.print("sub/b.txt");
writer.close();
- File file2 = new File(db.getWorkDir(), "sub/b.txt");
+ File file2 = new File(db.getWorkTree(), "sub/b.txt");
file2.createNewFile();
writer = new PrintWriter(file2);
writer.print("content b");
@@ -339,14 +339,14 @@ public class AddCommandTest extends RepositoryTestCase {
}
public void testAddWholeRepo() throws Exception {
- new File(db.getWorkDir(), "sub").mkdir();
- File file = new File(db.getWorkDir(), "sub/a.txt");
+ new File(db.getWorkTree(), "sub").mkdir();
+ File file = new File(db.getWorkTree(), "sub/a.txt");
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
writer.print("content");
writer.close();
- File file2 = new File(db.getWorkDir(), "sub/b.txt");
+ File file2 = new File(db.getWorkTree(), "sub/b.txt");
file2.createNewFile();
writer = new PrintWriter(file2);
writer.print("content b");
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
index c965c67664..773d2f0556 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
@@ -100,20 +100,20 @@ public class MergeCommandTest extends RepositoryTestCase {
addNewFileToIndex("file1");
RevCommit first = git.commit().setMessage("initial commit").call();
- assertTrue(new File(db.getWorkDir(), "file1").exists());
+ assertTrue(new File(db.getWorkTree(), "file1").exists());
createBranch(first, "refs/heads/branch1");
addNewFileToIndex("file2");
RevCommit second = git.commit().setMessage("second commit").call();
- assertTrue(new File(db.getWorkDir(), "file2").exists());
+ assertTrue(new File(db.getWorkTree(), "file2").exists());
checkoutBranch("refs/heads/branch1");
- assertFalse(new File(db.getWorkDir(), "file2").exists());
+ assertFalse(new File(db.getWorkTree(), "file2").exists());
MergeResult result = git.merge().include(db.getRef(Constants.MASTER)).call();
- assertTrue(new File(db.getWorkDir(), "file1").exists());
- assertTrue(new File(db.getWorkDir(), "file2").exists());
+ assertTrue(new File(db.getWorkTree(), "file1").exists());
+ assertTrue(new File(db.getWorkTree(), "file2").exists());
assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus());
assertEquals(second, result.getNewHead());
}
@@ -132,8 +132,8 @@ public class MergeCommandTest extends RepositoryTestCase {
git.commit().setMessage("third commit").call();
checkoutBranch("refs/heads/branch1");
- assertFalse(new File(db.getWorkDir(), "file2").exists());
- assertFalse(new File(db.getWorkDir(), "file3").exists());
+ assertFalse(new File(db.getWorkTree(), "file2").exists());
+ assertFalse(new File(db.getWorkTree(), "file3").exists());
MergeCommand merge = git.merge();
merge.include(second.getId());
@@ -152,7 +152,7 @@ public class MergeCommandTest extends RepositoryTestCase {
}
private void checkoutBranch(String branchName) throws Exception {
- File workDir = db.getWorkDir();
+ File workDir = db.getWorkTree();
if (workDir != null) {
WorkDirCheckout workDirCheckout = new WorkDirCheckout(db,
workDir, db.mapCommit(Constants.HEAD).getTree(),
@@ -176,7 +176,7 @@ public class MergeCommandTest extends RepositoryTestCase {
File writeTrashFile = writeTrashFile(filename, filename);
GitIndex index = db.getIndex();
- Entry entry = index.add(db.getWorkDir(), writeTrashFile);
+ Entry entry = index.add(db.getWorkTree(), writeTrashFile);
entry.update(writeTrashFile);
index.write();
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/SimilarityIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/SimilarityIndexTest.java
index d6915eb872..7e42e53586 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/SimilarityIndexTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/SimilarityIndexTest.java
@@ -43,12 +43,15 @@
package org.eclipse.jgit.diff;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
import junit.framework.TestCase;
import org.eclipse.jgit.lib.Constants;
public class SimilarityIndexTest extends TestCase {
- public void testIndexing() {
+ public void testIndexingSmallObject() {
SimilarityIndex si = hash("" //
+ "A\n" //
+ "B\n" //
@@ -67,6 +70,17 @@ public class SimilarityIndexTest extends TestCase {
assertEquals(2, si.count(si.findIndex(key_D)));
}
+ public void testIndexingLargeObject() throws IOException {
+ byte[] in = ("" //
+ + "A\n" //
+ + "B\n" //
+ + "B\n" //
+ + "B\n").getBytes("UTF-8");
+ SimilarityIndex si = new SimilarityIndex();
+ si.hash(new ByteArrayInputStream(in), in.length);
+ assertEquals(2, si.size());
+ }
+
public void testCommonScore_SameFiles() {
String text = "" //
+ "A\n" //
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java
index f4692b168d..c3ac952a11 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java
@@ -54,7 +54,7 @@ public class DirCacheBasicTest extends RepositoryTestCase {
final File idx = new File(db.getDirectory(), "index");
assertFalse(idx.exists());
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
assertNotNull(dc);
assertEquals(0, dc.getEntryCount());
}
@@ -74,7 +74,7 @@ public class DirCacheBasicTest extends RepositoryTestCase {
assertFalse(idx.exists());
assertFalse(lck.exists());
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
assertNotNull(dc);
assertFalse(idx.exists());
assertTrue(lck.exists());
@@ -108,7 +108,7 @@ public class DirCacheBasicTest extends RepositoryTestCase {
assertFalse(idx.exists());
assertFalse(lck.exists());
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
assertEquals(0, lck.length());
dc.write();
assertEquals(12 + 20, lck.length());
@@ -124,7 +124,7 @@ public class DirCacheBasicTest extends RepositoryTestCase {
assertFalse(idx.exists());
assertFalse(lck.exists());
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
assertEquals(0, lck.length());
dc.write();
assertEquals(12 + 20, lck.length());
@@ -141,13 +141,13 @@ public class DirCacheBasicTest extends RepositoryTestCase {
assertFalse(idx.exists());
assertFalse(lck.exists());
{
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
dc.write();
assertTrue(dc.commit());
assertTrue(idx.exists());
}
{
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
assertEquals(0, dc.getEntryCount());
}
}
@@ -158,13 +158,13 @@ public class DirCacheBasicTest extends RepositoryTestCase {
assertFalse(idx.exists());
assertFalse(lck.exists());
{
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
dc.write();
assertTrue(dc.commit());
assertTrue(idx.exists());
}
{
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
assertEquals(0, dc.getEntryCount());
assertTrue(idx.exists());
assertTrue(lck.exists());
@@ -173,7 +173,7 @@ public class DirCacheBasicTest extends RepositoryTestCase {
}
public void testBuildThenClear() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a.b", "a/b", "a0b" };
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
@@ -195,7 +195,7 @@ public class DirCacheBasicTest extends RepositoryTestCase {
}
public void testDetectUnmergedPaths() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final DirCacheEntry[] ents = new DirCacheEntry[3];
ents[0] = new DirCacheEntry("a", 1);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java
index 03bb7f5e83..a09f8e86c4 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java
@@ -52,7 +52,7 @@ import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
public class DirCacheBuilderIteratorTest extends RepositoryTestCase {
public void testPathFilterGroup_DoesNotSkipTail() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final FileMode mode = FileMode.REGULAR_FILE;
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java
index e919e41f4d..81ffab9148 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java
@@ -52,7 +52,7 @@ import org.eclipse.jgit.lib.RepositoryTestCase;
public class DirCacheBuilderTest extends RepositoryTestCase {
public void testBuildEmpty() throws Exception {
{
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
final DirCacheBuilder b = dc.builder();
assertNotNull(b);
b.finish();
@@ -60,7 +60,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase {
assertTrue(dc.commit());
}
{
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
assertEquals(0, dc.getEntryCount());
}
}
@@ -86,7 +86,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase {
final int length = 1342;
final DirCacheEntry entOrig;
{
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
final DirCacheBuilder b = dc.builder();
assertNotNull(b);
@@ -113,7 +113,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase {
assertTrue(dc.commit());
}
{
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
assertEquals(1, dc.getEntryCount());
final DirCacheEntry entRead = dc.getEntry(0);
@@ -135,7 +135,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase {
final int length = 1342;
final DirCacheEntry entOrig;
{
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
final DirCacheBuilder b = dc.builder();
assertNotNull(b);
@@ -160,7 +160,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase {
assertFalse(new File(db.getDirectory(), "index.lock").exists());
}
{
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
assertEquals(1, dc.getEntryCount());
final DirCacheEntry entRead = dc.getEntry(0);
@@ -177,7 +177,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase {
public void testFindSingleFile() throws Exception {
final String path = "a-file-path";
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final DirCacheBuilder b = dc.builder();
assertNotNull(b);
@@ -202,7 +202,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase {
}
public void testAdd_InGitSortOrder() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a.b", "a/b", "a0b" };
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
@@ -226,7 +226,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase {
}
public void testAdd_ReverseGitSortOrder() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a.b", "a/b", "a0b" };
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
@@ -250,7 +250,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase {
}
public void testBuilderClear() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a.b", "a/b", "a0b" };
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java
index d5a632c48c..5533fe358a 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java
@@ -48,7 +48,7 @@ import org.eclipse.jgit.lib.RepositoryTestCase;
public class DirCacheFindTest extends RepositoryTestCase {
public void testEntriesWithin() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java
index efea117388..24e3c34ddf 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java
@@ -52,7 +52,7 @@ import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
public class DirCacheIteratorTest extends RepositoryTestCase {
public void testEmptyTree_NoTreeWalk() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
assertEquals(0, dc.getEntryCount());
final DirCacheIterator i = new DirCacheIterator(dc);
@@ -60,7 +60,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase {
}
public void testEmptyTree_WithTreeWalk() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
assertEquals(0, dc.getEntryCount());
final TreeWalk tw = new TreeWalk(db);
@@ -70,7 +70,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase {
}
public void testNoSubtree_NoTreeWalk() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a0b" };
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
@@ -95,7 +95,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase {
}
public void testNoSubtree_WithTreeWalk() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a0b" };
final FileMode[] modes = { FileMode.EXECUTABLE_FILE, FileMode.GITLINK };
@@ -128,7 +128,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase {
}
public void testSingleSubtree_NoRecursion() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
@@ -172,7 +172,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase {
}
public void testSingleSubtree_Recursive() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final FileMode mode = FileMode.REGULAR_FILE;
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
@@ -207,7 +207,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase {
}
public void testTwoLevelSubtree_Recursive() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final FileMode mode = FileMode.REGULAR_FILE;
final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
@@ -241,7 +241,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase {
}
public void testTwoLevelSubtree_FilterPath() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final FileMode mode = FileMode.REGULAR_FILE;
final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java
index 0926ab9899..a6d7e39eb5 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java
@@ -85,7 +85,7 @@ public class DirCacheLargePathTest extends RepositoryTestCase {
assertEquals(shortPath, shortEnt.getPathString());
{
- final DirCache dc1 = DirCache.lock(db);
+ final DirCache dc1 = db.lockDirCache();
{
final DirCacheBuilder b = dc1.builder();
b.add(longEnt);
@@ -97,7 +97,7 @@ public class DirCacheLargePathTest extends RepositoryTestCase {
assertSame(shortEnt, dc1.getEntry(1));
}
{
- final DirCache dc2 = DirCache.read(db);
+ final DirCache dc2 = db.readDirCache();
assertEquals(2, dc2.getEntryCount());
assertNotSame(longEnt, dc2.getEntry(0));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java
index 8345c5d83d..dfca2fb298 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java
@@ -51,12 +51,12 @@ import org.eclipse.jgit.lib.RepositoryTestCase;
public class DirCacheTreeTest extends RepositoryTestCase {
public void testEmptyCache_NoCacheTree() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
assertNull(dc.getCacheTree(false));
}
public void testEmptyCache_CreateEmptyCacheTree() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final DirCacheTree tree = dc.getCacheTree(true);
assertNotNull(tree);
assertSame(tree, dc.getCacheTree(false));
@@ -69,7 +69,7 @@ public class DirCacheTreeTest extends RepositoryTestCase {
}
public void testEmptyCache_Clear_NoCacheTree() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final DirCacheTree tree = dc.getCacheTree(true);
assertNotNull(tree);
dc.clear();
@@ -78,7 +78,7 @@ public class DirCacheTreeTest extends RepositoryTestCase {
}
public void testSingleSubtree() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
@@ -115,7 +115,7 @@ public class DirCacheTreeTest extends RepositoryTestCase {
}
public void testTwoLevelSubtree() throws Exception {
- final DirCache dc = DirCache.read(db);
+ final DirCache dc = db.readDirCache();
final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
@@ -172,7 +172,7 @@ public class DirCacheTreeTest extends RepositoryTestCase {
* @throws IOException
*/
public void testWriteReadTree() throws CorruptObjectException, IOException {
- final DirCache dc = DirCache.lock(db);
+ final DirCache dc = db.lockDirCache();
final String A = String.format("a%2000s", "a");
final String B = String.format("b%2000s", "b");
@@ -188,7 +188,7 @@ public class DirCacheTreeTest extends RepositoryTestCase {
b.add(ents[i]);
b.commit();
- DirCache read = DirCache.read(db);
+ DirCache read = db.readDirCache();
assertEquals(paths.length, read.getEntryCount());
assertEquals(1, read.getCacheTree(true).getChildCount());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReadTreeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReadTreeTest.java
index 02bfdc1df5..2fa45c8211 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReadTreeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReadTreeTest.java
@@ -45,11 +45,9 @@
*/
package org.eclipse.jgit.lib;
-import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -131,13 +129,15 @@ public abstract class ReadTreeTest extends RepositoryTestCase {
}
ObjectId genSha1(String data) {
- InputStream is = new ByteArrayInputStream(data.getBytes());
- ObjectWriter objectWriter = new ObjectWriter(db);
+ ObjectInserter w = db.newObjectInserter();
try {
- return objectWriter.writeObject(Constants.OBJ_BLOB, data
- .getBytes().length, is, true);
+ ObjectId id = w.insert(Constants.OBJ_BLOB, data.getBytes());
+ w.flush();
+ return id;
} catch (IOException e) {
fail(e.toString());
+ } finally {
+ w.release();
}
return null;
}
@@ -623,7 +623,7 @@ public abstract class ReadTreeTest extends RepositoryTestCase {
expectedValue = i.get(path);
assertNotNull("found unexpected file for path "
+ path + " in workdir", expectedValue);
- File file = new File(db.getWorkDir(), path);
+ File file = new File(db.getWorkTree(), path);
assertTrue(file.exists());
if (file.isFile()) {
FileInputStream is = new FileInputStream(file);
@@ -661,8 +661,8 @@ public abstract class ReadTreeTest extends RepositoryTestCase {
assertTrue("unexpected content for path " + path
+ " in index. Expected: <" + expectedValue + ">",
Arrays.equals(
- db.openBlob(theIndex.getMembers()[j].getObjectId())
- .getBytes(), i.get(path).getBytes()));
+ db.open(theIndex.getMembers()[j].getObjectId())
+ .getCachedBytes(), i.get(path).getBytes()));
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java
index 88bcf76710..d78892b89d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java
@@ -70,7 +70,7 @@ public class ReflogConfigTest extends RepositoryTestCase {
// set the logAllRefUpdates parameter to true and check it
db.getConfig().setBoolean("core", null, "logallrefupdates", true);
- assertTrue(db.getConfig().getCore().isLogAllRefUpdates());
+ assertTrue(db.getConfig().get(CoreConfig.KEY).isLogAllRefUpdates());
// do one commit and check that reflog size is increased to 1
addFileToTree(t, "i-am-another-file", "and this is other data in me\n");
@@ -83,7 +83,7 @@ public class ReflogConfigTest extends RepositoryTestCase {
// set the logAllRefUpdates parameter to false and check it
db.getConfig().setBoolean("core", null, "logallrefupdates", false);
- assertFalse(db.getConfig().getCore().isLogAllRefUpdates());
+ assertFalse(db.getConfig().get(CoreConfig.KEY).isLogAllRefUpdates());
// do one commit and check that reflog size is 2
addFileToTree(t, "i-am-anotheranother-file",
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java
index c5c6d998bb..e78f8512a2 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java
@@ -54,6 +54,7 @@ import java.io.InputStreamReader;
import java.io.Reader;
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
+import org.eclipse.jgit.storage.file.FileRepository;
/**
* Base class for most JGit unit tests.
@@ -83,7 +84,7 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase {
protected File writeTrashFile(final String name, final String data)
throws IOException {
- File path = new File(db.getWorkDir(), name);
+ File path = new File(db.getWorkTree(), name);
write(path, data);
return path;
}
@@ -102,7 +103,7 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase {
}
/** Test repository, initialized for this test case. */
- protected Repository db;
+ protected FileRepository db;
/** Working directory of {@link #db}. */
protected File trash;
@@ -111,6 +112,6 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase {
protected void setUp() throws Exception {
super.setUp();
db = createWorkRepository();
- trash = db.getWorkDir();
+ trash = db.getWorkTree();
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SampleDataRepositoryTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SampleDataRepositoryTestCase.java
index 10c005679b..7bc9bb22e7 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SampleDataRepositoryTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SampleDataRepositoryTestCase.java
@@ -65,7 +65,7 @@ public abstract class SampleDataRepositoryTestCase extends RepositoryTestCase {
"pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa",
"pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12"
};
- final File packDir = new File(db.getObjectsDirectory(), "pack");
+ final File packDir = new File(db.getObjectDatabase().getDirectory(), "pack");
for (String n : packs) {
copyFile(JGitTestUtil.getTestResourceFile(n + ".pack"), new File(packDir, n + ".pack"));
copyFile(JGitTestUtil.getTestResourceFile(n + ".idx"), new File(packDir, n + ".idx"));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WorkDirCheckout_ReadTreeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WorkDirCheckout_ReadTreeTest.java
index ecaac5846e..7b5c3cdc57 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WorkDirCheckout_ReadTreeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WorkDirCheckout_ReadTreeTest.java
@@ -52,12 +52,12 @@ import java.util.HashMap;
public class WorkDirCheckout_ReadTreeTest extends ReadTreeTest {
private WorkDirCheckout wdc;
public void prescanTwoTrees(Tree head, Tree merge) throws IllegalStateException, IOException {
- wdc = new WorkDirCheckout(db, db.getWorkDir(), head, db.getIndex(), merge);
+ wdc = new WorkDirCheckout(db, db.getWorkTree(), head, db.getIndex(), merge);
wdc.prescanTwoTrees();
}
public void checkout() throws IOException {
- wdc = new WorkDirCheckout(db, db.getWorkDir(), theHead, db.getIndex(), theMerge);
+ wdc = new WorkDirCheckout(db, db.getWorkTree(), theHead, db.getIndex(), theMerge);
wdc.checkout();
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java
index 42e653be37..1cd1261636 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java
@@ -44,7 +44,8 @@
package org.eclipse.jgit.merge;
-import java.io.ByteArrayInputStream;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
@@ -53,7 +54,7 @@ import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RepositoryTestCase;
import org.eclipse.jgit.treewalk.TreeWalk;
@@ -66,10 +67,10 @@ public class CherryPickTest extends RepositoryTestCase {
// Cherry-pick "T" onto "O". This shouldn't introduce "p-fail", which
// was created by "P", nor should it modify "a", which was done by "P".
//
- final DirCache treeB = DirCache.read(db);
- final DirCache treeO = DirCache.read(db);
- final DirCache treeP = DirCache.read(db);
- final DirCache treeT = DirCache.read(db);
+ final DirCache treeB = db.readDirCache();
+ final DirCache treeO = db.readDirCache();
+ final DirCache treeP = db.readDirCache();
+ final DirCache treeT = db.readDirCache();
{
final DirCacheBuilder b = treeB.builder();
final DirCacheBuilder o = treeO.builder();
@@ -93,7 +94,7 @@ public class CherryPickTest extends RepositoryTestCase {
t.finish();
}
- final ObjectWriter ow = new ObjectWriter(db);
+ final ObjectInserter ow = db.newObjectInserter();
final ObjectId B = commit(ow, treeB, new ObjectId[] {});
final ObjectId O = commit(ow, treeO, new ObjectId[] { B });
final ObjectId P = commit(ow, treeP, new ObjectId[] { B });
@@ -128,15 +129,17 @@ public class CherryPickTest extends RepositoryTestCase {
.getObjectId(0));
}
- private ObjectId commit(final ObjectWriter ow, final DirCache treeB,
+ private ObjectId commit(final ObjectInserter odi, final DirCache treeB,
final ObjectId[] parentIds) throws Exception {
final Commit c = new Commit(db);
- c.setTreeId(treeB.writeTree(ow));
+ c.setTreeId(treeB.writeTree(odi));
c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
c.setCommitter(c.getAuthor());
c.setParentIds(parentIds);
c.setMessage("Tree " + c.getTreeId().name());
- return ow.writeCommit(c);
+ ObjectId id = odi.insert(OBJ_COMMIT, odi.format(c));
+ odi.flush();
+ return id;
}
private DirCacheEntry makeEntry(final String path, final FileMode mode)
@@ -148,9 +151,8 @@ public class CherryPickTest extends RepositoryTestCase {
final String content) throws Exception {
final DirCacheEntry ent = new DirCacheEntry(path);
ent.setFileMode(mode);
- final byte[] contentBytes = Constants.encode(content);
- ent.setObjectId(new ObjectWriter(db).computeBlobSha1(
- contentBytes.length, new ByteArrayInputStream(contentBytes)));
+ ent.setObjectId(new ObjectInserter.Formatter().idFor(OBJ_BLOB,
+ Constants.encode(content)));
return ent;
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java
index 690b166cbc..8657c52b16 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java
@@ -44,7 +44,9 @@
package org.eclipse.jgit.merge;
-import java.io.ByteArrayInputStream;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
+
import java.io.IOException;
import org.eclipse.jgit.dircache.DirCache;
@@ -54,7 +56,7 @@ import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
import org.eclipse.jgit.treewalk.TreeWalk;
@@ -103,9 +105,9 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
}
public void testTrivialTwoWay_validSubtreeSort() throws Exception {
- final DirCache treeB = DirCache.read(db);
- final DirCache treeO = DirCache.read(db);
- final DirCache treeT = DirCache.read(db);
+ final DirCache treeB = db.readDirCache();
+ final DirCache treeO = db.readDirCache();
+ final DirCache treeT = db.readDirCache();
{
final DirCacheBuilder b = treeB.builder();
final DirCacheBuilder o = treeO.builder();
@@ -126,7 +128,7 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
t.finish();
}
- final ObjectWriter ow = new ObjectWriter(db);
+ final ObjectInserter ow = db.newObjectInserter();
final ObjectId b = commit(ow, treeB, new ObjectId[] {});
final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
@@ -155,9 +157,9 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
}
public void testTrivialTwoWay_concurrentSubtreeChange() throws Exception {
- final DirCache treeB = DirCache.read(db);
- final DirCache treeO = DirCache.read(db);
- final DirCache treeT = DirCache.read(db);
+ final DirCache treeB = db.readDirCache();
+ final DirCache treeO = db.readDirCache();
+ final DirCache treeT = db.readDirCache();
{
final DirCacheBuilder b = treeB.builder();
final DirCacheBuilder o = treeO.builder();
@@ -177,7 +179,7 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
t.finish();
}
- final ObjectWriter ow = new ObjectWriter(db);
+ final ObjectInserter ow = db.newObjectInserter();
final ObjectId b = commit(ow, treeB, new ObjectId[] {});
final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
@@ -202,9 +204,9 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
}
public void testTrivialTwoWay_conflictSubtreeChange() throws Exception {
- final DirCache treeB = DirCache.read(db);
- final DirCache treeO = DirCache.read(db);
- final DirCache treeT = DirCache.read(db);
+ final DirCache treeB = db.readDirCache();
+ final DirCache treeO = db.readDirCache();
+ final DirCache treeT = db.readDirCache();
{
final DirCacheBuilder b = treeB.builder();
final DirCacheBuilder o = treeO.builder();
@@ -224,7 +226,7 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
t.finish();
}
- final ObjectWriter ow = new ObjectWriter(db);
+ final ObjectInserter ow = db.newObjectInserter();
final ObjectId b = commit(ow, treeB, new ObjectId[] {});
final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
@@ -235,9 +237,9 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
}
public void testTrivialTwoWay_leftDFconflict1() throws Exception {
- final DirCache treeB = DirCache.read(db);
- final DirCache treeO = DirCache.read(db);
- final DirCache treeT = DirCache.read(db);
+ final DirCache treeB = db.readDirCache();
+ final DirCache treeO = db.readDirCache();
+ final DirCache treeT = db.readDirCache();
{
final DirCacheBuilder b = treeB.builder();
final DirCacheBuilder o = treeO.builder();
@@ -256,7 +258,7 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
t.finish();
}
- final ObjectWriter ow = new ObjectWriter(db);
+ final ObjectInserter ow = db.newObjectInserter();
final ObjectId b = commit(ow, treeB, new ObjectId[] {});
final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
@@ -267,9 +269,9 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
}
public void testTrivialTwoWay_rightDFconflict1() throws Exception {
- final DirCache treeB = DirCache.read(db);
- final DirCache treeO = DirCache.read(db);
- final DirCache treeT = DirCache.read(db);
+ final DirCache treeB = db.readDirCache();
+ final DirCache treeO = db.readDirCache();
+ final DirCache treeT = db.readDirCache();
{
final DirCacheBuilder b = treeB.builder();
final DirCacheBuilder o = treeO.builder();
@@ -288,7 +290,7 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
t.finish();
}
- final ObjectWriter ow = new ObjectWriter(db);
+ final ObjectInserter ow = db.newObjectInserter();
final ObjectId b = commit(ow, treeB, new ObjectId[] {});
final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
@@ -299,9 +301,9 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
}
public void testTrivialTwoWay_leftDFconflict2() throws Exception {
- final DirCache treeB = DirCache.read(db);
- final DirCache treeO = DirCache.read(db);
- final DirCache treeT = DirCache.read(db);
+ final DirCache treeB = db.readDirCache();
+ final DirCache treeO = db.readDirCache();
+ final DirCache treeT = db.readDirCache();
{
final DirCacheBuilder b = treeB.builder();
final DirCacheBuilder o = treeO.builder();
@@ -318,7 +320,7 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
t.finish();
}
- final ObjectWriter ow = new ObjectWriter(db);
+ final ObjectInserter ow = db.newObjectInserter();
final ObjectId b = commit(ow, treeB, new ObjectId[] {});
final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
@@ -329,9 +331,9 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
}
public void testTrivialTwoWay_rightDFconflict2() throws Exception {
- final DirCache treeB = DirCache.read(db);
- final DirCache treeO = DirCache.read(db);
- final DirCache treeT = DirCache.read(db);
+ final DirCache treeB = db.readDirCache();
+ final DirCache treeO = db.readDirCache();
+ final DirCache treeT = db.readDirCache();
{
final DirCacheBuilder b = treeB.builder();
final DirCacheBuilder o = treeO.builder();
@@ -348,7 +350,7 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
t.finish();
}
- final ObjectWriter ow = new ObjectWriter(db);
+ final ObjectInserter ow = db.newObjectInserter();
final ObjectId b = commit(ow, treeB, new ObjectId[] {});
final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
@@ -363,15 +365,17 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
.getObjectId(0));
}
- private ObjectId commit(final ObjectWriter ow, final DirCache treeB,
+ private ObjectId commit(final ObjectInserter odi, final DirCache treeB,
final ObjectId[] parentIds) throws Exception {
final Commit c = new Commit(db);
- c.setTreeId(treeB.writeTree(ow));
+ c.setTreeId(treeB.writeTree(odi));
c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
c.setCommitter(c.getAuthor());
c.setParentIds(parentIds);
c.setMessage("Tree " + c.getTreeId().name());
- return ow.writeCommit(c);
+ ObjectId id = odi.insert(OBJ_COMMIT, odi.format(c));
+ odi.flush();
+ return id;
}
private DirCacheEntry makeEntry(final String path, final FileMode mode)
@@ -383,9 +387,8 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
final String content) throws Exception {
final DirCacheEntry ent = new DirCacheEntry(path);
ent.setFileMode(mode);
- final byte[] contentBytes = Constants.encode(content);
- ent.setObjectId(new ObjectWriter(db).computeBlobSha1(
- contentBytes.length, new ByteArrayInputStream(contentBytes)));
+ ent.setObjectId(new ObjectInserter.Formatter().idFor(OBJ_BLOB,
+ Constants.encode(content)));
return ent;
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java
index 64052323f1..9473fe6318 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java
@@ -47,18 +47,19 @@ import java.util.Date;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryTestCase;
/** Support for tests of the {@link RevWalk} class. */
public abstract class RevWalkTestCase extends RepositoryTestCase {
- private TestRepository util;
+ private TestRepository<Repository> util;
protected RevWalk rw;
@Override
public void setUp() throws Exception {
super.setUp();
- util = new TestRepository(db, createRevWalk());
+ util = new TestRepository<Repository>(db, createRevWalk());
rw = util.getRevWalk();
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConcurrentRepackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/ConcurrentRepackTest.java
index 69430ed334..c8f2aad759 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConcurrentRepackTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/ConcurrentRepackTest.java
@@ -42,7 +42,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -53,8 +53,17 @@ import java.util.Arrays;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryTestCase;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.pack.PackWriter;
public class ConcurrentRepackTest extends RepositoryTestCase {
public void setUp() throws Exception {
@@ -125,10 +134,11 @@ public class ConcurrentRepackTest extends RepositoryTestCase {
// within the pack has been modified.
//
final RevObject o2 = writeBlob(eden, "o2");
- final PackWriter pw = new PackWriter(eden, NullProgressMonitor.INSTANCE);
+ final PackWriter pw = new PackWriter(eden);
pw.addObject(o2);
pw.addObject(o1);
write(out1, pw);
+ pw.release();
// Try the old name, then the new name. The old name should cause the
// pack to reload when it opens and the index and pack mismatch.
@@ -148,7 +158,7 @@ public class ConcurrentRepackTest extends RepositoryTestCase {
final File[] out1 = pack(eden, o1);
assertEquals(o1.name(), parse(o1).name());
- final ObjectLoader load1 = db.openBlob(o1);
+ final ObjectLoader load1 = db.open(o1, Constants.OBJ_BLOB);
assertNotNull(load1);
final RevObject o2 = writeBlob(eden, "o2");
@@ -163,7 +173,7 @@ public class ConcurrentRepackTest extends RepositoryTestCase {
// earlier still resolve the object, even though its underlying
// pack is gone, but the object still exists.
//
- final ObjectLoader load2 = db.openBlob(o1);
+ final ObjectLoader load2 = db.open(o1, Constants.OBJ_BLOB);
assertNotNull(load2);
assertNotSame(load1, load2);
@@ -189,7 +199,7 @@ public class ConcurrentRepackTest extends RepositoryTestCase {
private File[] pack(final Repository src, final RevObject... list)
throws IOException {
- final PackWriter pw = new PackWriter(src, NullProgressMonitor.INSTANCE);
+ final PackWriter pw = new PackWriter(src);
for (final RevObject o : list) {
pw.addObject(o);
}
@@ -199,17 +209,19 @@ public class ConcurrentRepackTest extends RepositoryTestCase {
final File idxFile = fullPackFileName(name, ".idx");
final File[] files = new File[] { packFile, idxFile };
write(files, pw);
+ pw.release();
return files;
}
private static void write(final File[] files, final PackWriter pw)
throws IOException {
final long begin = files[0].getParentFile().lastModified();
+ NullProgressMonitor m = NullProgressMonitor.INSTANCE;
OutputStream out;
out = new BufferedOutputStream(new FileOutputStream(files[0]));
try {
- pw.writePack(out);
+ pw.writePack(m, m, out);
} finally {
out.close();
}
@@ -245,7 +257,7 @@ public class ConcurrentRepackTest extends RepositoryTestCase {
}
private File fullPackFileName(final ObjectId name, final String suffix) {
- final File packdir = new File(db.getObjectsDirectory(), "pack");
+ final File packdir = new File(db.getObjectDatabase().getDirectory(), "pack");
return new File(packdir, "pack-" + name.name() + suffix);
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackFileTest.java
new file mode 100644
index 0000000000..1a40b8e79c
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackFileTest.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.zip.Deflater;
+
+import org.eclipse.jgit.errors.LargeObjectException;
+import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.junit.TestRng;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectStream;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.storage.pack.DeltaEncoder;
+import org.eclipse.jgit.transport.IndexPack;
+import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.NB;
+import org.eclipse.jgit.util.TemporaryBuffer;
+
+public class PackFileTest extends LocalDiskRepositoryTestCase {
+ private TestRng rng;
+
+ private FileRepository repo;
+
+ private TestRepository<FileRepository> tr;
+
+ private WindowCursor wc;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ rng = new TestRng(getName());
+ repo = createBareRepository();
+ tr = new TestRepository<FileRepository>(repo);
+ wc = (WindowCursor) repo.newObjectReader();
+ }
+
+ protected void tearDown() throws Exception {
+ if (wc != null)
+ wc.release();
+ super.tearDown();
+ }
+
+ public void testWhole_SmallObject() throws Exception {
+ final int type = Constants.OBJ_BLOB;
+ byte[] data = rng.nextBytes(300);
+ RevBlob id = tr.blob(data);
+ tr.branch("master").commit().add("A", id).create();
+ tr.packAndPrune();
+ assertTrue("has blob", wc.has(id));
+
+ ObjectLoader ol = wc.open(id);
+ assertNotNull("created loader", ol);
+ assertEquals(type, ol.getType());
+ assertEquals(data.length, ol.getSize());
+ assertFalse("is not large", ol.isLarge());
+ assertTrue("same content", Arrays.equals(data, ol.getCachedBytes()));
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(type, in.getType());
+ assertEquals(data.length, in.getSize());
+ byte[] data2 = new byte[data.length];
+ IO.readFully(in, data2, 0, data.length);
+ assertTrue("same content", Arrays.equals(data2, data));
+ assertEquals("stream at EOF", -1, in.read());
+ in.close();
+ }
+
+ public void testWhole_LargeObject() throws Exception {
+ final int type = Constants.OBJ_BLOB;
+ byte[] data = rng.nextBytes(ObjectLoader.STREAM_THRESHOLD + 5);
+ RevBlob id = tr.blob(data);
+ tr.branch("master").commit().add("A", id).create();
+ tr.packAndPrune();
+ assertTrue("has blob", wc.has(id));
+
+ ObjectLoader ol = wc.open(id);
+ assertNotNull("created loader", ol);
+ assertEquals(type, ol.getType());
+ assertEquals(data.length, ol.getSize());
+ assertTrue("is large", ol.isLarge());
+ try {
+ ol.getCachedBytes();
+ fail("Should have thrown LargeObjectException");
+ } catch (LargeObjectException tooBig) {
+ assertEquals(id.name(), tooBig.getMessage());
+ }
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(type, in.getType());
+ assertEquals(data.length, in.getSize());
+ byte[] data2 = new byte[data.length];
+ IO.readFully(in, data2, 0, data.length);
+ assertTrue("same content", Arrays.equals(data2, data));
+ assertEquals("stream at EOF", -1, in.read());
+ in.close();
+ }
+
+ public void testDelta_SmallObjectChain() throws Exception {
+ ObjectInserter.Formatter fmt = new ObjectInserter.Formatter();
+ byte[] data0 = new byte[512];
+ Arrays.fill(data0, (byte) 0xf3);
+ ObjectId id0 = fmt.idFor(Constants.OBJ_BLOB, data0);
+
+ TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64 * 1024);
+ packHeader(pack, 4);
+ objectHeader(pack, Constants.OBJ_BLOB, data0.length);
+ deflate(pack, data0);
+
+ byte[] data1 = clone(0x01, data0);
+ byte[] delta1 = delta(data0, data1);
+ ObjectId id1 = fmt.idFor(Constants.OBJ_BLOB, data1);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta1.length);
+ id0.copyRawTo(pack);
+ deflate(pack, delta1);
+
+ byte[] data2 = clone(0x02, data1);
+ byte[] delta2 = delta(data1, data2);
+ ObjectId id2 = fmt.idFor(Constants.OBJ_BLOB, data2);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta2.length);
+ id1.copyRawTo(pack);
+ deflate(pack, delta2);
+
+ byte[] data3 = clone(0x03, data2);
+ byte[] delta3 = delta(data2, data3);
+ ObjectId id3 = fmt.idFor(Constants.OBJ_BLOB, data3);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta3.length);
+ id2.copyRawTo(pack);
+ deflate(pack, delta3);
+
+ digest(pack);
+ final byte[] raw = pack.toByteArray();
+ IndexPack ip = IndexPack.create(repo, new ByteArrayInputStream(raw));
+ ip.setFixThin(true);
+ ip.index(NullProgressMonitor.INSTANCE);
+ ip.renameAndOpenPack();
+
+ assertTrue("has blob", wc.has(id3));
+
+ ObjectLoader ol = wc.open(id3);
+ assertNotNull("created loader", ol);
+ assertEquals(Constants.OBJ_BLOB, ol.getType());
+ assertEquals(data3.length, ol.getSize());
+ assertFalse("is large", ol.isLarge());
+ assertNotNull(ol.getCachedBytes());
+ assertTrue(Arrays.equals(data3, ol.getCachedBytes()));
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(Constants.OBJ_BLOB, in.getType());
+ assertEquals(data3.length, in.getSize());
+ byte[] act = new byte[data3.length];
+ IO.readFully(in, act, 0, data3.length);
+ assertTrue("same content", Arrays.equals(act, data3));
+ assertEquals("stream at EOF", -1, in.read());
+ in.close();
+ }
+
+ public void testDelta_LargeObjectChain() throws Exception {
+ ObjectInserter.Formatter fmt = new ObjectInserter.Formatter();
+ byte[] data0 = new byte[ObjectLoader.STREAM_THRESHOLD + 5];
+ Arrays.fill(data0, (byte) 0xf3);
+ ObjectId id0 = fmt.idFor(Constants.OBJ_BLOB, data0);
+
+ TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64 * 1024);
+ packHeader(pack, 4);
+ objectHeader(pack, Constants.OBJ_BLOB, data0.length);
+ deflate(pack, data0);
+
+ byte[] data1 = clone(0x01, data0);
+ byte[] delta1 = delta(data0, data1);
+ ObjectId id1 = fmt.idFor(Constants.OBJ_BLOB, data1);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta1.length);
+ id0.copyRawTo(pack);
+ deflate(pack, delta1);
+
+ byte[] data2 = clone(0x02, data1);
+ byte[] delta2 = delta(data1, data2);
+ ObjectId id2 = fmt.idFor(Constants.OBJ_BLOB, data2);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta2.length);
+ id1.copyRawTo(pack);
+ deflate(pack, delta2);
+
+ byte[] data3 = clone(0x03, data2);
+ byte[] delta3 = delta(data2, data3);
+ ObjectId id3 = fmt.idFor(Constants.OBJ_BLOB, data3);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta3.length);
+ id2.copyRawTo(pack);
+ deflate(pack, delta3);
+
+ digest(pack);
+ final byte[] raw = pack.toByteArray();
+ IndexPack ip = IndexPack.create(repo, new ByteArrayInputStream(raw));
+ ip.setFixThin(true);
+ ip.index(NullProgressMonitor.INSTANCE);
+ ip.renameAndOpenPack();
+
+ assertTrue("has blob", wc.has(id3));
+
+ ObjectLoader ol = wc.open(id3);
+ assertNotNull("created loader", ol);
+ assertEquals(Constants.OBJ_BLOB, ol.getType());
+ assertEquals(data3.length, ol.getSize());
+ assertTrue("is large", ol.isLarge());
+ try {
+ ol.getCachedBytes();
+ fail("Should have thrown LargeObjectException");
+ } catch (LargeObjectException tooBig) {
+ assertEquals(id3.name(), tooBig.getMessage());
+ }
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(Constants.OBJ_BLOB, in.getType());
+ assertEquals(data3.length, in.getSize());
+ byte[] act = new byte[data3.length];
+ IO.readFully(in, act, 0, data3.length);
+ assertTrue("same content", Arrays.equals(act, data3));
+ assertEquals("stream at EOF", -1, in.read());
+ in.close();
+ }
+
+ public void testDelta_LargeInstructionStream() throws Exception {
+ ObjectInserter.Formatter fmt = new ObjectInserter.Formatter();
+ byte[] data0 = new byte[32];
+ Arrays.fill(data0, (byte) 0xf3);
+ ObjectId id0 = fmt.idFor(Constants.OBJ_BLOB, data0);
+
+ byte[] data3 = rng.nextBytes(ObjectLoader.STREAM_THRESHOLD + 5);
+ ByteArrayOutputStream tmp = new ByteArrayOutputStream();
+ DeltaEncoder de = new DeltaEncoder(tmp, data0.length, data3.length);
+ de.insert(data3, 0, data3.length);
+ byte[] delta3 = tmp.toByteArray();
+ assertTrue(delta3.length > ObjectLoader.STREAM_THRESHOLD);
+
+ TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64 * 1024);
+ packHeader(pack, 2);
+ objectHeader(pack, Constants.OBJ_BLOB, data0.length);
+ deflate(pack, data0);
+
+ ObjectId id3 = fmt.idFor(Constants.OBJ_BLOB, data3);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta3.length);
+ id0.copyRawTo(pack);
+ deflate(pack, delta3);
+
+ digest(pack);
+ final byte[] raw = pack.toByteArray();
+ IndexPack ip = IndexPack.create(repo, new ByteArrayInputStream(raw));
+ ip.setFixThin(true);
+ ip.index(NullProgressMonitor.INSTANCE);
+ ip.renameAndOpenPack();
+
+ assertTrue("has blob", wc.has(id3));
+
+ ObjectLoader ol = wc.open(id3);
+ assertNotNull("created loader", ol);
+ assertEquals(Constants.OBJ_BLOB, ol.getType());
+ assertEquals(data3.length, ol.getSize());
+ assertTrue("is large", ol.isLarge());
+ try {
+ ol.getCachedBytes();
+ fail("Should have thrown LargeObjectException");
+ } catch (LargeObjectException tooBig) {
+ assertEquals(id3.name(), tooBig.getMessage());
+ }
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(Constants.OBJ_BLOB, in.getType());
+ assertEquals(data3.length, in.getSize());
+ byte[] act = new byte[data3.length];
+ IO.readFully(in, act, 0, data3.length);
+ assertTrue("same content", Arrays.equals(act, data3));
+ assertEquals("stream at EOF", -1, in.read());
+ in.close();
+ }
+
+ private byte[] clone(int first, byte[] base) {
+ byte[] r = new byte[base.length];
+ System.arraycopy(base, 1, r, 1, r.length - 1);
+ r[0] = (byte) first;
+ return r;
+ }
+
+ private byte[] delta(byte[] base, byte[] dest) throws IOException {
+ ByteArrayOutputStream tmp = new ByteArrayOutputStream();
+ DeltaEncoder de = new DeltaEncoder(tmp, base.length, dest.length);
+ de.insert(dest, 0, 1);
+ de.copy(1, base.length - 1);
+ return tmp.toByteArray();
+ }
+
+ private void packHeader(TemporaryBuffer.Heap pack, int cnt)
+ throws IOException {
+ final byte[] hdr = new byte[8];
+ NB.encodeInt32(hdr, 0, 2);
+ NB.encodeInt32(hdr, 4, cnt);
+ pack.write(Constants.PACK_SIGNATURE);
+ pack.write(hdr, 0, 8);
+ }
+
+ private void objectHeader(TemporaryBuffer.Heap pack, int type, int sz)
+ throws IOException {
+ byte[] buf = new byte[8];
+ int nextLength = sz >>> 4;
+ buf[0] = (byte) ((nextLength > 0 ? 0x80 : 0x00) | (type << 4) | (sz & 0x0F));
+ sz = nextLength;
+ int n = 1;
+ while (sz > 0) {
+ nextLength >>>= 7;
+ buf[n++] = (byte) ((nextLength > 0 ? 0x80 : 0x00) | (sz & 0x7F));
+ sz = nextLength;
+ }
+ pack.write(buf, 0, n);
+ }
+
+ private void deflate(TemporaryBuffer.Heap pack, final byte[] content)
+ throws IOException {
+ final Deflater deflater = new Deflater();
+ final byte[] buf = new byte[128];
+ deflater.setInput(content, 0, content.length);
+ deflater.finish();
+ do {
+ final int n = deflater.deflate(buf, 0, buf.length);
+ if (n > 0)
+ pack.write(buf, 0, n);
+ } while (!deflater.finished());
+ deflater.end();
+ }
+
+ private void digest(TemporaryBuffer.Heap buf) throws IOException {
+ MessageDigest md = Constants.newMessageDigest();
+ md.update(buf.toByteArray());
+ buf.write(md.digest());
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackIndexTestCase.java
index d1c5c5eccd..9884142e5c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackIndexTestCase.java
@@ -41,14 +41,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.File;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.PackIndex.MutableEntry;
+import org.eclipse.jgit.lib.RepositoryTestCase;
+import org.eclipse.jgit.storage.file.PackIndex.MutableEntry;
public abstract class PackIndexTestCase extends RepositoryTestCase {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV1Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackIndexV1Test.java
index f3082fb294..303eeff72d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV1Test.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackIndexV1Test.java
@@ -43,11 +43,12 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.File;
import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.util.JGitTestUtil;
public class PackIndexV1Test extends PackIndexTestCase {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV2Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackIndexV2Test.java
index c5669f9d24..2d3ec7b729 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV2Test.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackIndexV2Test.java
@@ -43,11 +43,12 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.File;
import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.util.JGitTestUtil;
public class PackIndexV2Test extends PackIndexTestCase {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackReverseIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackReverseIndexTest.java
index 19b705813f..07a40a425f 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackReverseIndexTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackReverseIndexTest.java
@@ -42,10 +42,11 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import org.eclipse.jgit.errors.CorruptObjectException;
-import org.eclipse.jgit.lib.PackIndex.MutableEntry;
+import org.eclipse.jgit.lib.RepositoryTestCase;
+import org.eclipse.jgit.storage.file.PackIndex.MutableEntry;
import org.eclipse.jgit.util.JGitTestUtil;
public class PackReverseIndexTest extends RepositoryTestCase {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackWriterTest.java
index 76b663a29b..9e663d7b4c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackWriterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackWriterTest.java
@@ -41,7 +41,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -59,9 +59,14 @@ import java.util.LinkedList;
import java.util.List;
import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.PackIndex.MutableEntry;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
+import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.file.PackIndex.MutableEntry;
+import org.eclipse.jgit.storage.pack.PackWriter;
import org.eclipse.jgit.transport.IndexPack;
import org.eclipse.jgit.util.JGitTestUtil;
@@ -91,7 +96,7 @@ public class PackWriterTest extends SampleDataRepositoryTestCase {
packBase = new File(trash, "tmp_pack");
packFile = new File(trash, "tmp_pack.pack");
indexFile = new File(trash, "tmp_pack.idx");
- writer = new PackWriter(db, new TextProgressMonitor());
+ writer = new PackWriter(db);
}
/**
@@ -238,7 +243,7 @@ public class PackWriterTest extends SampleDataRepositoryTestCase {
* @throws IOException
*/
public void testWritePack2DeltasCRC32Copy() throws IOException {
- final File packDir = new File(db.getObjectsDirectory(), "pack");
+ final File packDir = new File(db.getObjectDatabase().getDirectory(), "pack");
final File crc32Pack = new File(packDir,
"pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack");
final File crc32Idx = new File(packDir,
@@ -476,17 +481,21 @@ public class PackWriterTest extends SampleDataRepositoryTestCase {
final Collection<ObjectId> uninterestings, final boolean thin,
final boolean ignoreMissingUninteresting)
throws MissingObjectException, IOException {
+ NullProgressMonitor m = NullProgressMonitor.INSTANCE;
writer.setThin(thin);
writer.setIgnoreMissingUninteresting(ignoreMissingUninteresting);
- writer.preparePack(interestings, uninterestings);
- writer.writePack(os);
+ writer.preparePack(m, interestings, uninterestings);
+ writer.writePack(m, m, os);
+ writer.release();
verifyOpenPack(thin);
}
private void createVerifyOpenPack(final Iterator<RevObject> objectSource)
throws MissingObjectException, IOException {
+ NullProgressMonitor m = NullProgressMonitor.INSTANCE;
writer.preparePack(objectSource);
- writer.writePack(os);
+ writer.writePack(m, m, os);
+ writer.release();
verifyOpenPack(false);
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefDirectoryTest.java
index a2812901bc..6e98541603 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDirectoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefDirectoryTest.java
@@ -41,7 +41,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import static org.eclipse.jgit.lib.Constants.HEAD;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
@@ -55,6 +55,10 @@ import java.util.Map;
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefDatabase;
+import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTag;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefUpdateTest.java
index 8a9bb52633..875c2e96f5 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefUpdateTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefUpdateTest.java
@@ -43,7 +43,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.File;
import java.io.IOException;
@@ -51,9 +51,22 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefRename;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.file.FileRepository;
+import org.eclipse.jgit.storage.file.LockFile;
+import org.eclipse.jgit.storage.file.RefDirectory;
+import org.eclipse.jgit.storage.file.RefDirectoryUpdate;
+import org.eclipse.jgit.storage.file.ReflogReader;
public class RefUpdateTest extends SampleDataRepositoryTestCase {
@@ -103,14 +116,14 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
assertNotSame(newid, r.getObjectId());
assertSame(ObjectId.class, r.getObjectId().getClass());
assertEquals(newid.copy(), r.getObjectId());
- List<org.eclipse.jgit.lib.ReflogReader.Entry> reverseEntries1 = db.getReflogReader("refs/heads/abc").getReverseEntries();
- org.eclipse.jgit.lib.ReflogReader.Entry entry1 = reverseEntries1.get(0);
+ List<org.eclipse.jgit.storage.file.ReflogReader.Entry> reverseEntries1 = db.getReflogReader("refs/heads/abc").getReverseEntries();
+ org.eclipse.jgit.storage.file.ReflogReader.Entry entry1 = reverseEntries1.get(0);
assertEquals(1, reverseEntries1.size());
assertEquals(ObjectId.zeroId(), entry1.getOldId());
assertEquals(r.getObjectId(), entry1.getNewId());
assertEquals(new PersonIdent(db).toString(), entry1.getWho().toString());
assertEquals("", entry1.getComment());
- List<org.eclipse.jgit.lib.ReflogReader.Entry> reverseEntries2 = db.getReflogReader("HEAD").getReverseEntries();
+ List<org.eclipse.jgit.storage.file.ReflogReader.Entry> reverseEntries2 = db.getReflogReader("HEAD").getReverseEntries();
assertEquals(0, reverseEntries2.size());
}
@@ -326,7 +339,7 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
// the branch HEAD referred to is left untouched
assertEquals(pid, db.resolve("refs/heads/master"));
ReflogReader reflogReader = new ReflogReader(db, "HEAD");
- org.eclipse.jgit.lib.ReflogReader.Entry e = reflogReader.getReverseEntries().get(0);
+ org.eclipse.jgit.storage.file.ReflogReader.Entry e = reflogReader.getReverseEntries().get(0);
assertEquals(pid, e.getOldId());
assertEquals(ppid, e.getNewId());
assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
@@ -355,7 +368,7 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
// the branch HEAD referred to is left untouched
assertNull(db.resolve("refs/heads/unborn"));
ReflogReader reflogReader = new ReflogReader(db, "HEAD");
- org.eclipse.jgit.lib.ReflogReader.Entry e = reflogReader.getReverseEntries().get(0);
+ org.eclipse.jgit.storage.file.ReflogReader.Entry e = reflogReader.getReverseEntries().get(0);
assertEquals(ObjectId.zeroId(), e.getOldId());
assertEquals(ppid, e.getNewId());
assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
@@ -664,7 +677,7 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
// Create new Repository instance, to reread caches and make sure our
// assumptions are persistent.
- Repository ndb = new Repository(db.getDirectory());
+ Repository ndb = new FileRepository(db.getDirectory());
assertEquals(rb2, ndb.resolve("refs/heads/new/name"));
assertNull(ndb.resolve("refs/heads/b"));
}
@@ -677,9 +690,9 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
ObjectId oldHeadId = db.resolve(Constants.HEAD);
writeReflog(db, oldfromId, oldfromId, "Just a message",
fromName);
- List<org.eclipse.jgit.lib.ReflogReader.Entry> oldFromLog = db
+ List<org.eclipse.jgit.storage.file.ReflogReader.Entry> oldFromLog = db
.getReflogReader(fromName).getReverseEntries();
- List<org.eclipse.jgit.lib.ReflogReader.Entry> oldHeadLog = oldHeadId != null ? db
+ List<org.eclipse.jgit.storage.file.ReflogReader.Entry> oldHeadLog = oldHeadId != null ? db
.getReflogReader(Constants.HEAD).getReverseEntries() : null;
assertTrue("internal check, we have a log", new File(db.getDirectory(),
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogReaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/ReflogReaderTest.java
index 6144851fcd..1d268a4740 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogReaderTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/ReflogReaderTest.java
@@ -42,7 +42,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.File;
import java.io.FileNotFoundException;
@@ -51,7 +51,10 @@ import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
-import org.eclipse.jgit.lib.ReflogReader.Entry;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
+import org.eclipse.jgit.storage.file.ReflogReader.Entry;
public class ReflogReaderTest extends SampleDataRepositoryTestCase {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositorySetupWorkDirTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RepositorySetupWorkDirTest.java
index 6e5e0054b8..4f6d5b3bd6 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositorySetupWorkDirTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RepositorySetupWorkDirTest.java
@@ -42,12 +42,17 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.File;
import java.io.IOException;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
/**
* Tests for setting up the working directory when creating a Repository
@@ -57,12 +62,12 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
public void testIsBare_CreateRepositoryFromArbitraryGitDir()
throws Exception {
File gitDir = getFile("workdir");
- assertTrue(new Repository(gitDir).isBare());
+ assertTrue(new FileRepository(gitDir).isBare());
}
public void testNotBare_CreateRepositoryFromDotGitGitDir() throws Exception {
File gitDir = getFile("workdir", Constants.DOT_GIT);
- Repository repo = new Repository(gitDir);
+ Repository repo = new FileRepository(gitDir);
assertFalse(repo.isBare());
assertWorkdirPath(repo, "workdir");
assertGitdirPath(repo, "workdir", Constants.DOT_GIT);
@@ -71,14 +76,14 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
public void testWorkdirIsParentDir_CreateRepositoryFromDotGitGitDir()
throws Exception {
File gitDir = getFile("workdir", Constants.DOT_GIT);
- Repository repo = new Repository(gitDir);
- String workdir = repo.getWorkDir().getName();
+ Repository repo = new FileRepository(gitDir);
+ String workdir = repo.getWorkTree().getName();
assertEquals(workdir, "workdir");
}
public void testNotBare_CreateRepositoryFromWorkDirOnly() throws Exception {
File workdir = getFile("workdir", "repo");
- Repository repo = new Repository(null, workdir);
+ FileRepository repo = new FileRepositoryBuilder().setWorkTree(workdir).build();
assertFalse(repo.isBare());
assertWorkdirPath(repo, "workdir", "repo");
assertGitdirPath(repo, "workdir", "repo", Constants.DOT_GIT);
@@ -87,7 +92,7 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
public void testWorkdirIsDotGit_CreateRepositoryFromWorkDirOnly()
throws Exception {
File workdir = getFile("workdir", "repo");
- Repository repo = new Repository(null, workdir);
+ FileRepository repo = new FileRepositoryBuilder().setWorkTree(workdir).build();
assertGitdirPath(repo, "workdir", "repo", Constants.DOT_GIT);
}
@@ -96,7 +101,7 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
File gitDir = getFile("workdir", "repoWithConfig");
File workTree = getFile("workdir", "treeRoot");
setWorkTree(gitDir, workTree);
- Repository repo = new Repository(gitDir, null);
+ FileRepository repo = new FileRepositoryBuilder().setGitDir(gitDir).build();
assertFalse(repo.isBare());
assertWorkdirPath(repo, "workdir", "treeRoot");
assertGitdirPath(repo, "workdir", "repoWithConfig");
@@ -106,7 +111,7 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
throws Exception {
File gitDir = getFile("workdir", "repoWithConfig");
setBare(gitDir, true);
- Repository repo = new Repository(gitDir, null);
+ FileRepository repo = new FileRepositoryBuilder().setGitDir(gitDir).build();
assertTrue(repo.isBare());
}
@@ -114,7 +119,7 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
throws Exception {
File gitDir = getFile("workdir", "repoWithBareConfigTrue", "child");
setBare(gitDir, false);
- Repository repo = new Repository(gitDir, null);
+ FileRepository repo = new FileRepositoryBuilder().setGitDir(gitDir).build();
assertWorkdirPath(repo, "workdir", "repoWithBareConfigTrue");
}
@@ -122,27 +127,18 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
throws Exception {
File gitDir = getFile("workdir", "repoWithBareConfigFalse", "child");
setBare(gitDir, false);
- Repository repo = new Repository(gitDir, null);
+ FileRepository repo = new FileRepositoryBuilder().setGitDir(gitDir).build();
assertFalse(repo.isBare());
assertWorkdirPath(repo, "workdir", "repoWithBareConfigFalse");
assertGitdirPath(repo, "workdir", "repoWithBareConfigFalse", "child");
}
- public void testNotBare_MakeBareUnbareBySetWorkdir() throws Exception {
- File gitDir = getFile("gitDir");
- Repository repo = new Repository(gitDir);
- repo.setWorkDir(getFile("workingDir"));
- assertFalse(repo.isBare());
- assertWorkdirPath(repo, "workingDir");
- assertGitdirPath(repo, "gitDir");
- }
-
public void testExceptionThrown_BareRepoGetWorkDir() throws Exception {
File gitDir = getFile("workdir");
try {
- new Repository(gitDir).getWorkDir();
- fail("Expected IllegalStateException missing");
- } catch (IllegalStateException e) {
+ new FileRepository(gitDir).getWorkTree();
+ fail("Expected NoWorkTreeException missing");
+ } catch (NoWorkTreeException e) {
// expected
}
}
@@ -150,9 +146,9 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
public void testExceptionThrown_BareRepoGetIndex() throws Exception {
File gitDir = getFile("workdir");
try {
- new Repository(gitDir).getIndex();
- fail("Expected IllegalStateException missing");
- } catch (IllegalStateException e) {
+ new FileRepository(gitDir).getIndex();
+ fail("Expected NoWorkTreeException missing");
+ } catch (NoWorkTreeException e) {
// expected
}
}
@@ -160,9 +156,9 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
public void testExceptionThrown_BareRepoGetIndexFile() throws Exception {
File gitDir = getFile("workdir");
try {
- new Repository(gitDir).getIndexFile();
- fail("Expected Exception missing");
- } catch (IllegalStateException e) {
+ new FileRepository(gitDir).getIndexFile();
+ fail("Expected NoWorkTreeException missing");
+ } catch (NoWorkTreeException e) {
// expected
}
}
@@ -176,20 +172,28 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
return result;
}
- private void setBare(File gitDir, boolean bare) throws IOException {
- Repository repo = new Repository(gitDir, null);
- repo.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
+ private void setBare(File gitDir, boolean bare) throws IOException,
+ ConfigInvalidException {
+ FileBasedConfig cfg = configFor(gitDir);
+ cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
ConfigConstants.CONFIG_KEY_BARE, bare);
- repo.getConfig().save();
+ cfg.save();
+ }
+
+ private void setWorkTree(File gitDir, File workTree) throws IOException,
+ ConfigInvalidException {
+ String path = workTree.getAbsolutePath();
+ FileBasedConfig cfg = configFor(gitDir);
+ cfg.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_WORKTREE, path);
+ cfg.save();
}
- private void setWorkTree(File gitDir, File workTree) throws IOException {
- Repository repo = new Repository(gitDir, null);
- repo.getConfig()
- .setString(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_WORKTREE,
- workTree.getAbsolutePath());
- repo.getConfig().save();
+ private FileBasedConfig configFor(File gitDir) throws IOException,
+ ConfigInvalidException {
+ FileBasedConfig cfg = new FileBasedConfig(new File(gitDir, "config"));
+ cfg.load();
+ return cfg;
}
private void assertGitdirPath(Repository repo, String... expected)
@@ -202,7 +206,7 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
private void assertWorkdirPath(Repository repo, String... expected)
throws IOException {
File exp = getFile(expected).getCanonicalFile();
- File act = repo.getWorkDir().getCanonicalFile();
+ File act = repo.getWorkTree().getCanonicalFile();
assertEquals("Wrong working Directory", exp, act);
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0003_Basic.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0003_Basic.java
index ce8a79ef96..477b0dfb50 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0003_Basic.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0003_Basic.java
@@ -43,7 +43,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -53,7 +53,23 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
+import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileTreeEntry;
+import org.eclipse.jgit.lib.ObjectDatabase;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
+import org.eclipse.jgit.lib.Tag;
+import org.eclipse.jgit.lib.Tree;
+import org.eclipse.jgit.lib.TreeEntry;
+import org.eclipse.jgit.lib.WriteTree;
public class T0003_Basic extends SampleDataRepositoryTestCase {
public void test001_Initalize() {
@@ -80,11 +96,11 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
public void test000_openRepoBadArgs() throws IOException {
try {
- new Repository(null, null);
+ new FileRepositoryBuilder().build();
fail("Must pass either GIT_DIR or GIT_WORK_TREE");
} catch (IllegalArgumentException e) {
assertEquals(
- "Either GIT_DIR or GIT_WORK_TREE must be passed to Repository constructor",
+ JGitText.get().eitherGitDirOrWorkTreeRequired,
e.getMessage());
}
}
@@ -97,16 +113,16 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
*/
public void test000_openrepo_default_gitDirSet() throws IOException {
File repo1Parent = new File(trash.getParentFile(), "r1");
- Repository repo1initial = new Repository(new File(repo1Parent, Constants.DOT_GIT));
+ Repository repo1initial = new FileRepository(new File(repo1Parent, Constants.DOT_GIT));
repo1initial.create();
repo1initial.close();
File theDir = new File(repo1Parent, Constants.DOT_GIT);
- Repository r = new Repository(theDir, null);
+ FileRepository r = new FileRepositoryBuilder().setGitDir(theDir).build();
assertEqualsPath(theDir, r.getDirectory());
- assertEqualsPath(repo1Parent, r.getWorkDir());
+ assertEqualsPath(repo1Parent, r.getWorkTree());
assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
- assertEqualsPath(new File(theDir, "objects"), r.getObjectsDirectory());
+ assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase().getDirectory());
}
/**
@@ -117,16 +133,17 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
*/
public void test000_openrepo_default_gitDirAndWorkTreeSet() throws IOException {
File repo1Parent = new File(trash.getParentFile(), "r1");
- Repository repo1initial = new Repository(new File(repo1Parent, Constants.DOT_GIT));
+ Repository repo1initial = new FileRepository(new File(repo1Parent, Constants.DOT_GIT));
repo1initial.create();
repo1initial.close();
File theDir = new File(repo1Parent, Constants.DOT_GIT);
- Repository r = new Repository(theDir, repo1Parent.getParentFile());
+ FileRepository r = new FileRepositoryBuilder().setGitDir(theDir)
+ .setWorkTree(repo1Parent.getParentFile()).build();
assertEqualsPath(theDir, r.getDirectory());
- assertEqualsPath(repo1Parent.getParentFile(), r.getWorkDir());
+ assertEqualsPath(repo1Parent.getParentFile(), r.getWorkTree());
assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
- assertEqualsPath(new File(theDir, "objects"), r.getObjectsDirectory());
+ assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase().getDirectory());
}
/**
@@ -137,16 +154,16 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
*/
public void test000_openrepo_default_workDirSet() throws IOException {
File repo1Parent = new File(trash.getParentFile(), "r1");
- Repository repo1initial = new Repository(new File(repo1Parent, Constants.DOT_GIT));
+ Repository repo1initial = new FileRepository(new File(repo1Parent, Constants.DOT_GIT));
repo1initial.create();
repo1initial.close();
File theDir = new File(repo1Parent, Constants.DOT_GIT);
- Repository r = new Repository(null, repo1Parent);
+ FileRepository r = new FileRepositoryBuilder().setWorkTree(repo1Parent).build();
assertEqualsPath(theDir, r.getDirectory());
- assertEqualsPath(repo1Parent, r.getWorkDir());
+ assertEqualsPath(repo1Parent, r.getWorkTree());
assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
- assertEqualsPath(new File(theDir, "objects"), r.getObjectsDirectory());
+ assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase().getDirectory());
}
/**
@@ -159,7 +176,7 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
File repo1Parent = new File(trash.getParentFile(), "r1");
File workdir = new File(trash.getParentFile(), "rw");
workdir.mkdir();
- Repository repo1initial = new Repository(new File(repo1Parent, Constants.DOT_GIT));
+ FileRepository repo1initial = new FileRepository(new File(repo1Parent, Constants.DOT_GIT));
repo1initial.create();
repo1initial.getConfig().setString("core", null, "worktree",
workdir.getAbsolutePath());
@@ -167,11 +184,11 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
repo1initial.close();
File theDir = new File(repo1Parent, Constants.DOT_GIT);
- Repository r = new Repository(theDir, null);
+ FileRepository r = new FileRepositoryBuilder().setGitDir(theDir).build();
assertEqualsPath(theDir, r.getDirectory());
- assertEqualsPath(workdir, r.getWorkDir());
+ assertEqualsPath(workdir, r.getWorkTree());
assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
- assertEqualsPath(new File(theDir, "objects"), r.getObjectsDirectory());
+ assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase().getDirectory());
}
/**
@@ -184,7 +201,7 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
File repo1Parent = new File(trash.getParentFile(), "r1");
File workdir = new File(trash.getParentFile(), "rw");
workdir.mkdir();
- Repository repo1initial = new Repository(new File(repo1Parent, Constants.DOT_GIT));
+ FileRepository repo1initial = new FileRepository(new File(repo1Parent, Constants.DOT_GIT));
repo1initial.create();
repo1initial.getConfig()
.setString("core", null, "worktree", "../../rw");
@@ -192,11 +209,11 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
repo1initial.close();
File theDir = new File(repo1Parent, Constants.DOT_GIT);
- Repository r = new Repository(theDir, null);
+ FileRepository r = new FileRepositoryBuilder().setGitDir(theDir).build();
assertEqualsPath(theDir, r.getDirectory());
- assertEqualsPath(workdir, r.getWorkDir());
+ assertEqualsPath(workdir, r.getWorkTree());
assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
- assertEqualsPath(new File(theDir, "objects"), r.getObjectsDirectory());
+ assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase().getDirectory());
}
/**
@@ -210,18 +227,21 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
File repo1Parent = new File(trash.getParentFile(), "r1");
File indexFile = new File(trash, "idx");
File objDir = new File(trash, "../obj");
- File[] altObjDirs = new File[] { db.getObjectsDirectory() };
- Repository repo1initial = new Repository(new File(repo1Parent, Constants.DOT_GIT));
+ File altObjDir = db.getObjectDatabase().getDirectory();
+ Repository repo1initial = new FileRepository(new File(repo1Parent, Constants.DOT_GIT));
repo1initial.create();
repo1initial.close();
File theDir = new File(repo1Parent, Constants.DOT_GIT);
- Repository r = new Repository(theDir, null, objDir, altObjDirs,
- indexFile);
+ FileRepository r = new FileRepositoryBuilder() //
+ .setGitDir(theDir).setObjectDirectory(objDir) //
+ .addAlternateObjectDirectory(altObjDir) //
+ .setIndexFile(indexFile) //
+ .build();
assertEqualsPath(theDir, r.getDirectory());
- assertEqualsPath(theDir.getParentFile(), r.getWorkDir());
+ assertEqualsPath(theDir.getParentFile(), r.getWorkTree());
assertEqualsPath(indexFile, r.getIndexFile());
- assertEqualsPath(objDir, r.getObjectsDirectory());
+ assertEqualsPath(objDir, r.getObjectDatabase().getDirectory());
assertNotNull(r.mapCommit("6db9c2ebf75590eef973081736730a9ea169a0c4"));
// Must close or the default repo pack files created by this test gets
// locked via the alternate object directories on Windows.
@@ -283,7 +303,7 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
}
public void test005_ReadSimpleConfig() {
- final RepositoryConfig c = db.getConfig();
+ final Config c = db.getConfig();
assertNotNull(c);
assertEquals("0", c.getString("core", null, "repositoryformatversion"));
assertEquals("0", c.getString("CoRe", null, "REPOSITORYFoRmAtVeRsIoN"));
@@ -294,8 +314,8 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
public void test006_ReadUglyConfig() throws IOException,
ConfigInvalidException {
- final RepositoryConfig c = db.getConfig();
final File cfg = new File(db.getDirectory(), "config");
+ final FileBasedConfig c = new FileBasedConfig(cfg);
final FileWriter pw = new FileWriter(cfg);
final String configStr = " [core];comment\n\tfilemode = yes\n"
+ "[user]\n"
@@ -321,9 +341,9 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
}
public void test007_Open() throws IOException {
- final Repository db2 = new Repository(db.getDirectory());
+ final FileRepository db2 = new FileRepository(db.getDirectory());
assertEquals(db.getDirectory(), db2.getDirectory());
- assertEquals(db.getObjectsDirectory(), db2.getObjectsDirectory());
+ assertEquals(db.getObjectDatabase().getDirectory(), db2.getObjectDatabase().getDirectory());
assertNotSame(db.getConfig(), db2.getConfig());
}
@@ -337,7 +357,7 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
pw.close();
try {
- new Repository(db.getDirectory());
+ new FileRepository(db.getDirectory());
fail("incorrectly opened a bad repository");
} catch (IOException ioe) {
assertTrue(ioe.getMessage().indexOf("format") > 0);
@@ -345,11 +365,7 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
}
}
- public void test009_CreateCommitOldFormat() throws IOException,
- ConfigInvalidException {
- writeTrashFile(".git/config", "[core]\n" + "legacyHeaders=1\n");
- db.getConfig().load();
-
+ public void test009_CreateCommitOldFormat() throws IOException {
final Tree t = new Tree(db);
final FileTreeEntry f = t.addFile("i-am-a-file");
writeTrashFile(f.getName(), "and this is the data in me\n");
@@ -369,8 +385,10 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
assertEquals(cmtid, c.getCommitId());
// Verify the commit we just wrote is in the correct format.
- final XInputStream xis = new XInputStream(new FileInputStream(db
- .toFile(cmtid)));
+ ObjectDatabase odb = db.getObjectDatabase();
+ assertTrue("is ObjectDirectory", odb instanceof ObjectDirectory);
+ final XInputStream xis = new XInputStream(new FileInputStream(
+ ((ObjectDirectory) odb).fileFor(cmtid)));
try {
assertEquals(0x78, xis.readUInt8());
assertEquals(0x9c, xis.readUInt8());
@@ -724,10 +742,10 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
assertEquals("", Repository.stripWorkDir(relBase, relNonFile));
assertEquals("", Repository.stripWorkDir(absBase, absNonFile));
- assertEquals("", Repository.stripWorkDir(db.getWorkDir(), db.getWorkDir()));
+ assertEquals("", Repository.stripWorkDir(db.getWorkTree(), db.getWorkTree()));
- File file = new File(new File(db.getWorkDir(), "subdir"), "File.java");
- assertEquals("subdir/File.java", Repository.stripWorkDir(db.getWorkDir(), file));
+ File file = new File(new File(db.getWorkTree(), "subdir"), "File.java");
+ assertEquals("subdir/File.java", Repository.stripWorkDir(db.getWorkTree(), file));
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0004_PackReader.java
index 336bba22ce..472d6956e3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0004_PackReader.java
@@ -44,11 +44,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.File;
import java.io.IOException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
import org.eclipse.jgit.util.JGitTestUtil;
public class T0004_PackReader extends SampleDataRepositoryTestCase {
@@ -59,15 +63,14 @@ public class T0004_PackReader extends SampleDataRepositoryTestCase {
public void test003_lookupCompressedObject() throws IOException {
final PackFile pr;
final ObjectId id;
- final PackedObjectLoader or;
+ final ObjectLoader or;
id = ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327");
pr = new PackFile(TEST_IDX, TEST_PACK);
- or = pr.get(new WindowCursor(), id);
+ or = pr.get(new WindowCursor(null), id);
assertNotNull(or);
assertEquals(Constants.OBJ_TREE, or.getType());
assertEquals(35, or.getSize());
- assertEquals(7736, or.getObjectOffset());
pr.close();
}
@@ -76,11 +79,9 @@ public class T0004_PackReader extends SampleDataRepositoryTestCase {
final ObjectLoader or;
id = ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259");
- or = db.openObject(id);
+ or = db.open(id);
assertNotNull(or);
- assertTrue(or instanceof PackedObjectLoader);
assertEquals(Constants.OBJ_BLOB, or.getType());
assertEquals(18009, or.getSize());
- assertEquals(516, ((PackedObjectLoader) or).getObjectOffset());
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/UnpackedObjectTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/UnpackedObjectTest.java
new file mode 100644
index 0000000000..25dfe4c239
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/UnpackedObjectTest.java
@@ -0,0 +1,534 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.zip.DeflaterOutputStream;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.errors.LargeObjectException;
+import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
+import org.eclipse.jgit.junit.TestRng;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectStream;
+import org.eclipse.jgit.util.IO;
+
+public class UnpackedObjectTest extends LocalDiskRepositoryTestCase {
+ private TestRng rng;
+
+ private FileRepository repo;
+
+ private WindowCursor wc;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ rng = new TestRng(getName());
+ repo = createBareRepository();
+ wc = (WindowCursor) repo.newObjectReader();
+ }
+
+ protected void tearDown() throws Exception {
+ if (wc != null)
+ wc.release();
+ super.tearDown();
+ }
+
+ public void testStandardFormat_SmallObject() throws Exception {
+ final int type = Constants.OBJ_BLOB;
+ byte[] data = rng.nextBytes(300);
+ byte[] gz = compressStandardFormat(type, data);
+ ObjectId id = ObjectId.zeroId();
+
+ ObjectLoader ol = UnpackedObject.open(new ByteArrayInputStream(gz),
+ path(id), id, wc);
+ assertNotNull("created loader", ol);
+ assertEquals(type, ol.getType());
+ assertEquals(data.length, ol.getSize());
+ assertFalse("is not large", ol.isLarge());
+ assertTrue("same content", Arrays.equals(data, ol.getCachedBytes()));
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(type, in.getType());
+ assertEquals(data.length, in.getSize());
+ byte[] data2 = new byte[data.length];
+ IO.readFully(in, data2, 0, data.length);
+ assertTrue("same content", Arrays.equals(data2, data));
+ assertEquals("stream at EOF", -1, in.read());
+ in.close();
+ }
+
+ public void testStandardFormat_LargeObject() throws Exception {
+ final int type = Constants.OBJ_BLOB;
+ byte[] data = rng.nextBytes(ObjectLoader.STREAM_THRESHOLD + 5);
+ ObjectId id = new ObjectInserter.Formatter().idFor(type, data);
+ write(id, compressStandardFormat(type, data));
+
+ ObjectLoader ol;
+ {
+ FileInputStream fs = new FileInputStream(path(id));
+ try {
+ ol = UnpackedObject.open(fs, path(id), id, wc);
+ } finally {
+ fs.close();
+ }
+ }
+
+ assertNotNull("created loader", ol);
+ assertEquals(type, ol.getType());
+ assertEquals(data.length, ol.getSize());
+ assertTrue("is large", ol.isLarge());
+ try {
+ ol.getCachedBytes();
+ fail("Should have thrown LargeObjectException");
+ } catch (LargeObjectException tooBig) {
+ assertEquals(id.name(), tooBig.getMessage());
+ }
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(type, in.getType());
+ assertEquals(data.length, in.getSize());
+ byte[] data2 = new byte[data.length];
+ IO.readFully(in, data2, 0, data.length);
+ assertTrue("same content", Arrays.equals(data2, data));
+ assertEquals("stream at EOF", -1, in.read());
+ in.close();
+ }
+
+ public void testStandardFormat_NegativeSize() throws Exception {
+ ObjectId id = ObjectId.zeroId();
+ byte[] data = rng.nextBytes(300);
+
+ try {
+ byte[] gz = compressStandardFormat("blob", "-1", data);
+ UnpackedObject.open(new ByteArrayInputStream(gz), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectNegativeSize), coe
+ .getMessage());
+ }
+ }
+
+ public void testStandardFormat_InvalidType() throws Exception {
+ ObjectId id = ObjectId.zeroId();
+ byte[] data = rng.nextBytes(300);
+
+ try {
+ byte[] gz = compressStandardFormat("not.a.type", "1", data);
+ UnpackedObject.open(new ByteArrayInputStream(gz), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectInvalidType), coe
+ .getMessage());
+ }
+ }
+
+ public void testStandardFormat_NoHeader() throws Exception {
+ ObjectId id = ObjectId.zeroId();
+ byte[] data = {};
+
+ try {
+ byte[] gz = compressStandardFormat("", "", data);
+ UnpackedObject.open(new ByteArrayInputStream(gz), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectNoHeader), coe
+ .getMessage());
+ }
+ }
+
+ public void testStandardFormat_GarbageAfterSize() throws Exception {
+ ObjectId id = ObjectId.zeroId();
+ byte[] data = rng.nextBytes(300);
+
+ try {
+ byte[] gz = compressStandardFormat("blob", "1foo", data);
+ UnpackedObject.open(new ByteArrayInputStream(gz), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectGarbageAfterSize),
+ coe.getMessage());
+ }
+ }
+
+ public void testStandardFormat_SmallObject_CorruptZLibStream()
+ throws Exception {
+ ObjectId id = ObjectId.zeroId();
+ byte[] data = rng.nextBytes(300);
+
+ try {
+ byte[] gz = compressStandardFormat(Constants.OBJ_BLOB, data);
+ for (int i = 5; i < gz.length; i++)
+ gz[i] = 0;
+ UnpackedObject.open(new ByteArrayInputStream(gz), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectBadStream), coe
+ .getMessage());
+ }
+ }
+
+ public void testStandardFormat_SmallObject_TruncatedZLibStream()
+ throws Exception {
+ ObjectId id = ObjectId.zeroId();
+ byte[] data = rng.nextBytes(300);
+
+ try {
+ byte[] gz = compressStandardFormat(Constants.OBJ_BLOB, data);
+ byte[] tr = new byte[gz.length - 1];
+ System.arraycopy(gz, 0, tr, 0, tr.length);
+ UnpackedObject.open(new ByteArrayInputStream(tr), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectBadStream), coe
+ .getMessage());
+ }
+ }
+
+ public void testStandardFormat_SmallObject_TrailingGarbage()
+ throws Exception {
+ ObjectId id = ObjectId.zeroId();
+ byte[] data = rng.nextBytes(300);
+
+ try {
+ byte[] gz = compressStandardFormat(Constants.OBJ_BLOB, data);
+ byte[] tr = new byte[gz.length + 1];
+ System.arraycopy(gz, 0, tr, 0, gz.length);
+ UnpackedObject.open(new ByteArrayInputStream(tr), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectBadStream), coe
+ .getMessage());
+ }
+ }
+
+ public void testStandardFormat_LargeObject_CorruptZLibStream()
+ throws Exception {
+ final int type = Constants.OBJ_BLOB;
+ byte[] data = rng.nextBytes(ObjectLoader.STREAM_THRESHOLD + 5);
+ ObjectId id = new ObjectInserter.Formatter().idFor(type, data);
+ byte[] gz = compressStandardFormat(type, data);
+ gz[gz.length - 1] = 0;
+ gz[gz.length - 2] = 0;
+
+ write(id, gz);
+
+ ObjectLoader ol;
+ {
+ FileInputStream fs = new FileInputStream(path(id));
+ try {
+ ol = UnpackedObject.open(fs, path(id), id, wc);
+ } finally {
+ fs.close();
+ }
+ }
+
+ try {
+ byte[] tmp = new byte[data.length];
+ InputStream in = ol.openStream();
+ try {
+ IO.readFully(in, tmp, 0, tmp.length);
+ } finally {
+ in.close();
+ }
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectBadStream), coe
+ .getMessage());
+ }
+ }
+
+ public void testStandardFormat_LargeObject_TruncatedZLibStream()
+ throws Exception {
+ final int type = Constants.OBJ_BLOB;
+ byte[] data = rng.nextBytes(ObjectLoader.STREAM_THRESHOLD + 5);
+ ObjectId id = new ObjectInserter.Formatter().idFor(type, data);
+ byte[] gz = compressStandardFormat(type, data);
+ byte[] tr = new byte[gz.length - 1];
+ System.arraycopy(gz, 0, tr, 0, tr.length);
+
+ write(id, tr);
+
+ ObjectLoader ol;
+ {
+ FileInputStream fs = new FileInputStream(path(id));
+ try {
+ ol = UnpackedObject.open(fs, path(id), id, wc);
+ } finally {
+ fs.close();
+ }
+ }
+
+ byte[] tmp = new byte[data.length];
+ InputStream in = ol.openStream();
+ IO.readFully(in, tmp, 0, tmp.length);
+ try {
+ in.close();
+ fail("close did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectBadStream), coe
+ .getMessage());
+ }
+ }
+
+ public void testStandardFormat_LargeObject_TrailingGarbage()
+ throws Exception {
+ final int type = Constants.OBJ_BLOB;
+ byte[] data = rng.nextBytes(ObjectLoader.STREAM_THRESHOLD + 5);
+ ObjectId id = new ObjectInserter.Formatter().idFor(type, data);
+ byte[] gz = compressStandardFormat(type, data);
+ byte[] tr = new byte[gz.length + 1];
+ System.arraycopy(gz, 0, tr, 0, gz.length);
+
+ write(id, tr);
+
+ ObjectLoader ol;
+ {
+ FileInputStream fs = new FileInputStream(path(id));
+ try {
+ ol = UnpackedObject.open(fs, path(id), id, wc);
+ } finally {
+ fs.close();
+ }
+ }
+
+ byte[] tmp = new byte[data.length];
+ InputStream in = ol.openStream();
+ IO.readFully(in, tmp, 0, tmp.length);
+ try {
+ in.close();
+ fail("close did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectBadStream), coe
+ .getMessage());
+ }
+ }
+
+ public void testPackFormat_SmallObject() throws Exception {
+ final int type = Constants.OBJ_BLOB;
+ byte[] data = rng.nextBytes(300);
+ byte[] gz = compressPackFormat(type, data);
+ ObjectId id = ObjectId.zeroId();
+
+ ObjectLoader ol = UnpackedObject.open(new ByteArrayInputStream(gz),
+ path(id), id, wc);
+ assertNotNull("created loader", ol);
+ assertEquals(type, ol.getType());
+ assertEquals(data.length, ol.getSize());
+ assertFalse("is not large", ol.isLarge());
+ assertTrue("same content", Arrays.equals(data, ol.getCachedBytes()));
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(type, in.getType());
+ assertEquals(data.length, in.getSize());
+ byte[] data2 = new byte[data.length];
+ IO.readFully(in, data2, 0, data.length);
+ assertTrue("same content", Arrays.equals(data, ol.getCachedBytes()));
+ in.close();
+ }
+
+ public void testPackFormat_LargeObject() throws Exception {
+ final int type = Constants.OBJ_BLOB;
+ byte[] data = rng.nextBytes(ObjectLoader.STREAM_THRESHOLD + 5);
+ ObjectId id = new ObjectInserter.Formatter().idFor(type, data);
+ write(id, compressPackFormat(type, data));
+
+ ObjectLoader ol;
+ {
+ FileInputStream fs = new FileInputStream(path(id));
+ try {
+ ol = UnpackedObject.open(fs, path(id), id, wc);
+ } finally {
+ fs.close();
+ }
+ }
+
+ assertNotNull("created loader", ol);
+ assertEquals(type, ol.getType());
+ assertEquals(data.length, ol.getSize());
+ assertTrue("is large", ol.isLarge());
+ try {
+ ol.getCachedBytes();
+ fail("Should have thrown LargeObjectException");
+ } catch (LargeObjectException tooBig) {
+ assertEquals(id.name(), tooBig.getMessage());
+ }
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(type, in.getType());
+ assertEquals(data.length, in.getSize());
+ byte[] data2 = new byte[data.length];
+ IO.readFully(in, data2, 0, data.length);
+ assertTrue("same content", Arrays.equals(data2, data));
+ assertEquals("stream at EOF", -1, in.read());
+ in.close();
+ }
+
+ public void testPackFormat_DeltaNotAllowed() throws Exception {
+ ObjectId id = ObjectId.zeroId();
+ byte[] data = rng.nextBytes(300);
+
+ try {
+ byte[] gz = compressPackFormat(Constants.OBJ_OFS_DELTA, data);
+ UnpackedObject.open(new ByteArrayInputStream(gz), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectInvalidType), coe
+ .getMessage());
+ }
+
+ try {
+ byte[] gz = compressPackFormat(Constants.OBJ_REF_DELTA, data);
+ UnpackedObject.open(new ByteArrayInputStream(gz), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectInvalidType), coe
+ .getMessage());
+ }
+
+ try {
+ byte[] gz = compressPackFormat(Constants.OBJ_TYPE_5, data);
+ UnpackedObject.open(new ByteArrayInputStream(gz), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectInvalidType), coe
+ .getMessage());
+ }
+
+ try {
+ byte[] gz = compressPackFormat(Constants.OBJ_EXT, data);
+ UnpackedObject.open(new ByteArrayInputStream(gz), path(id), id, wc);
+ fail("Did not throw CorruptObjectException");
+ } catch (CorruptObjectException coe) {
+ assertEquals(MessageFormat.format(JGitText.get().objectIsCorrupt,
+ id.name(), JGitText.get().corruptObjectInvalidType), coe
+ .getMessage());
+ }
+ }
+
+ private byte[] compressStandardFormat(int type, byte[] data)
+ throws IOException {
+ String typeString = Constants.typeString(type);
+ String length = String.valueOf(data.length);
+ return compressStandardFormat(typeString, length, data);
+ }
+
+ private byte[] compressStandardFormat(String type, String length,
+ byte[] data) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ DeflaterOutputStream d = new DeflaterOutputStream(out);
+ d.write(Constants.encodeASCII(type));
+ d.write(' ');
+ d.write(Constants.encodeASCII(length));
+ d.write(0);
+ d.write(data);
+ d.finish();
+ return out.toByteArray();
+ }
+
+ private byte[] compressPackFormat(int type, byte[] data) throws IOException {
+ byte[] hdr = new byte[64];
+ int rawLength = data.length;
+ int nextLength = rawLength >>> 4;
+ hdr[0] = (byte) ((nextLength > 0 ? 0x80 : 0x00) | (type << 4) | (rawLength & 0x0F));
+ rawLength = nextLength;
+ int n = 1;
+ while (rawLength > 0) {
+ nextLength >>>= 7;
+ hdr[n++] = (byte) ((nextLength > 0 ? 0x80 : 0x00) | (rawLength & 0x7F));
+ rawLength = nextLength;
+ }
+
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(hdr, 0, n);
+
+ DeflaterOutputStream d = new DeflaterOutputStream(out);
+ d.write(data);
+ d.finish();
+ return out.toByteArray();
+ }
+
+ private File path(ObjectId id) {
+ return repo.getObjectDatabase().fileFor(id);
+ }
+
+ private void write(ObjectId id, byte[] data) throws IOException {
+ File path = path(id);
+ path.getParentFile().mkdirs();
+ FileOutputStream out = new FileOutputStream(path);
+ try {
+ out.write(data);
+ } finally {
+ out.close();
+ }
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheGetTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/WindowCacheGetTest.java
index 8ff022ddc4..d8c682999c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheGetTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/WindowCacheGetTest.java
@@ -41,7 +41,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.BufferedReader;
import java.io.FileInputStream;
@@ -51,6 +51,10 @@ import java.util.ArrayList;
import java.util.List;
import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
import org.eclipse.jgit.util.JGitTestUtil;
import org.eclipse.jgit.util.MutableInteger;
@@ -73,9 +77,9 @@ public class WindowCacheGetTest extends SampleDataRepositoryTestCase {
final TestObject o = new TestObject();
o.id = ObjectId.fromString(parts[0]);
o.setType(parts[1]);
- o.rawSize = Integer.parseInt(parts[2]);
+ // parts[2] is the inflate size
// parts[3] is the size-in-pack
- o.offset = Long.parseLong(parts[4]);
+ // parts[4] is the offset in the pack
toLoad.add(o);
}
} finally {
@@ -122,12 +126,9 @@ public class WindowCacheGetTest extends SampleDataRepositoryTestCase {
private void doCacheTests() throws IOException {
for (final TestObject o : toLoad) {
- final ObjectLoader or = db.openObject(o.id);
+ final ObjectLoader or = db.open(o.id, o.type);
assertNotNull(or);
- assertTrue(or instanceof PackedObjectLoader);
assertEquals(o.type, or.getType());
- assertEquals(o.rawSize, or.getRawSize());
- assertEquals(o.offset, ((PackedObjectLoader) or).getObjectOffset());
}
}
@@ -136,10 +137,6 @@ public class WindowCacheGetTest extends SampleDataRepositoryTestCase {
int type;
- int rawSize;
-
- long offset;
-
void setType(final String typeStr) throws CorruptObjectException {
final byte[] typeRaw = Constants.encode(typeStr + " ");
final MutableInteger ptr = new MutableInteger();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheReconfigureTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/WindowCacheReconfigureTest.java
index 9e093c85bd..e52b19d925 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheReconfigureTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/WindowCacheReconfigureTest.java
@@ -41,7 +41,9 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
+
+import org.eclipse.jgit.lib.RepositoryTestCase;
public class WindowCacheReconfigureTest extends RepositoryTestCase {
public void testConfigureCache_PackedGitLimit_0() {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/XInputStream.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/XInputStream.java
index eef32b9276..9978c8e13c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/XInputStream.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/XInputStream.java
@@ -41,7 +41,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.storage.file;
import java.io.BufferedInputStream;
import java.io.EOFException;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/pack/DeltaIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/pack/DeltaIndexTest.java
new file mode 100644
index 0000000000..868ef8825c
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/pack/DeltaIndexTest.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.pack;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jgit.junit.TestRng;
+import org.eclipse.jgit.lib.Constants;
+
+public class DeltaIndexTest extends TestCase {
+ private TestRng rng;
+
+ private ByteArrayOutputStream actDeltaBuf;
+
+ private ByteArrayOutputStream expDeltaBuf;
+
+ private DeltaEncoder expDeltaEnc;
+
+ private byte[] src;
+
+ private byte[] dst;
+
+ private ByteArrayOutputStream dstBuf;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ rng = new TestRng(getName());
+ actDeltaBuf = new ByteArrayOutputStream();
+ expDeltaBuf = new ByteArrayOutputStream();
+ expDeltaEnc = new DeltaEncoder(expDeltaBuf, 0, 0);
+ dstBuf = new ByteArrayOutputStream();
+ }
+
+ public void testInsertWholeObject_Length12() throws IOException {
+ src = rng.nextBytes(12);
+ insert(src);
+ doTest();
+ }
+
+ public void testCopyWholeObject_Length128() throws IOException {
+ src = rng.nextBytes(128);
+ copy(0, 128);
+ doTest();
+ }
+
+ public void testCopyWholeObject_Length123() throws IOException {
+ src = rng.nextBytes(123);
+ copy(0, 123);
+ doTest();
+ }
+
+ public void testCopyZeros_Length128() throws IOException {
+ src = new byte[2048];
+ copy(0, src.length);
+ doTest();
+
+ // The index should be smaller than expected due to the chain
+ // being truncated. Without truncation we would expect to have
+ // more than 3584 bytes used.
+ //
+ assertEquals(2636, new DeltaIndex(src).getIndexSize());
+ }
+
+ public void testShuffleSegments() throws IOException {
+ src = rng.nextBytes(128);
+ copy(64, 64);
+ copy(0, 64);
+ doTest();
+ }
+
+ public void testInsertHeadMiddle() throws IOException {
+ src = rng.nextBytes(1024);
+ insert("foo");
+ copy(0, 512);
+ insert("yet more fooery");
+ copy(0, 512);
+ doTest();
+ }
+
+ public void testInsertTail() throws IOException {
+ src = rng.nextBytes(1024);
+ copy(0, 512);
+ insert("bar");
+ doTest();
+ }
+
+ public void testIndexSize() {
+ src = rng.nextBytes(1024);
+ DeltaIndex di = new DeltaIndex(src);
+ assertEquals(1860, di.getIndexSize());
+ assertEquals("DeltaIndex[2 KiB]", di.toString());
+ }
+
+ public void testLimitObjectSize_Length12InsertFails() throws IOException {
+ src = rng.nextBytes(12);
+ dst = src;
+
+ DeltaIndex di = new DeltaIndex(src);
+ assertFalse(di.encode(actDeltaBuf, dst, src.length));
+ }
+
+ public void testLimitObjectSize_Length130InsertFails() throws IOException {
+ src = rng.nextBytes(130);
+ dst = rng.nextBytes(130);
+
+ DeltaIndex di = new DeltaIndex(src);
+ assertFalse(di.encode(actDeltaBuf, dst, src.length));
+ }
+
+ public void testLimitObjectSize_Length130CopyOk() throws IOException {
+ src = rng.nextBytes(130);
+ copy(0, 130);
+ dst = dstBuf.toByteArray();
+
+ DeltaIndex di = new DeltaIndex(src);
+ assertTrue(di.encode(actDeltaBuf, dst, dst.length));
+
+ byte[] actDelta = actDeltaBuf.toByteArray();
+ byte[] expDelta = expDeltaBuf.toByteArray();
+
+ assertEquals(BinaryDelta.format(expDelta, false), //
+ BinaryDelta.format(actDelta, false));
+ }
+
+ public void testLimitObjectSize_Length130CopyFails() throws IOException {
+ src = rng.nextBytes(130);
+ copy(0, 130);
+ dst = dstBuf.toByteArray();
+
+ // The header requires 4 bytes for these objects, so a target length
+ // of 5 is bigger than the copy instruction and should cause an abort.
+ //
+ DeltaIndex di = new DeltaIndex(src);
+ assertFalse(di.encode(actDeltaBuf, dst, 5));
+ assertEquals(4, actDeltaBuf.size());
+ }
+
+ public void testLimitObjectSize_InsertFrontFails() throws IOException {
+ src = rng.nextBytes(130);
+ insert("eight");
+ copy(0, 130);
+ dst = dstBuf.toByteArray();
+
+ // The header requires 4 bytes for these objects, so a target length
+ // of 5 is bigger than the copy instruction and should cause an abort.
+ //
+ DeltaIndex di = new DeltaIndex(src);
+ assertFalse(di.encode(actDeltaBuf, dst, 5));
+ assertEquals(4, actDeltaBuf.size());
+ }
+
+ private void copy(int offset, int len) throws IOException {
+ dstBuf.write(src, offset, len);
+ expDeltaEnc.copy(offset, len);
+ }
+
+ private void insert(String text) throws IOException {
+ insert(Constants.encode(text));
+ }
+
+ private void insert(byte[] text) throws IOException {
+ dstBuf.write(text);
+ expDeltaEnc.insert(text);
+ }
+
+ private void doTest() throws IOException {
+ dst = dstBuf.toByteArray();
+
+ DeltaIndex di = new DeltaIndex(src);
+ di.encode(actDeltaBuf, dst);
+
+ byte[] actDelta = actDeltaBuf.toByteArray();
+ byte[] expDelta = expDeltaBuf.toByteArray();
+
+ assertEquals(BinaryDelta.format(expDelta, false), //
+ BinaryDelta.format(actDelta, false));
+
+ assertTrue("delta is not empty", actDelta.length > 0);
+ assertEquals(src.length, BinaryDelta.getBaseSize(actDelta));
+ assertEquals(dst.length, BinaryDelta.getResultSize(actDelta));
+ assertTrue(Arrays.equals(dst, BinaryDelta.apply(src, actDelta)));
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/pack/DeltaStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/pack/DeltaStreamTest.java
new file mode 100644
index 0000000000..9b34ad5e09
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/pack/DeltaStreamTest.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.pack;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.junit.TestRng;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.util.IO;
+
+public class DeltaStreamTest extends TestCase {
+ private TestRng rng;
+
+ private ByteArrayOutputStream deltaBuf;
+
+ private DeltaEncoder deltaEnc;
+
+ private byte[] base;
+
+ private byte[] data;
+
+ private int dataPtr;
+
+ private byte[] delta;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ rng = new TestRng(getName());
+ deltaBuf = new ByteArrayOutputStream();
+ }
+
+ public void testCopy_SingleOp() throws IOException {
+ init((1 << 16) + 1, (1 << 8) + 1);
+ copy(0, data.length);
+ assertValidState();
+ }
+
+ public void testCopy_MaxSize() throws IOException {
+ int max = (0xff << 16) + (0xff << 8) + 0xff;
+ init(1 + max, max);
+ copy(1, max);
+ assertValidState();
+ }
+
+ public void testCopy_64k() throws IOException {
+ init(0x10000 + 2, 0x10000 + 1);
+ copy(1, 0x10000);
+ copy(0x10001, 1);
+ assertValidState();
+ }
+
+ public void testCopy_Gap() throws IOException {
+ init(256, 8);
+ copy(4, 4);
+ copy(128, 4);
+ assertValidState();
+ }
+
+ public void testCopy_OutOfOrder() throws IOException {
+ init((1 << 16) + 1, (1 << 16) + 1);
+ copy(1 << 8, 1 << 8);
+ copy(0, data.length - dataPtr);
+ assertValidState();
+ }
+
+ public void testInsert_SingleOp() throws IOException {
+ init((1 << 16) + 1, 2);
+ insert("hi");
+ assertValidState();
+ }
+
+ public void testInsertAndCopy() throws IOException {
+ init(8, 512);
+ insert(new byte[127]);
+ insert(new byte[127]);
+ insert(new byte[127]);
+ insert(new byte[125]);
+ copy(2, 6);
+ assertValidState();
+ }
+
+ public void testSkip() throws IOException {
+ init(32, 15);
+ copy(2, 2);
+ insert("ab");
+ insert("cd");
+ copy(4, 4);
+ copy(0, 2);
+ insert("efg");
+ assertValidState();
+
+ for (int p = 0; p < data.length; p++) {
+ byte[] act = new byte[data.length];
+ System.arraycopy(data, 0, act, 0, p);
+ DeltaStream in = open();
+ IO.skipFully(in, p);
+ assertEquals(data.length - p, in.read(act, p, data.length - p));
+ assertEquals(-1, in.read());
+ assertTrue("skipping " + p, Arrays.equals(data, act));
+ }
+
+ // Skip all the way to the end should still recognize EOF.
+ DeltaStream in = open();
+ IO.skipFully(in, data.length);
+ assertEquals(-1, in.read());
+ assertEquals(0, in.skip(1));
+
+ // Skip should not open the base as we move past it, but it
+ // will open when we need to start copying data from it.
+ final boolean[] opened = new boolean[1];
+ in = new DeltaStream(new ByteArrayInputStream(delta)) {
+ @Override
+ protected long getBaseSize() throws IOException {
+ return base.length;
+ }
+
+ @Override
+ protected InputStream openBase() throws IOException {
+ opened[0] = true;
+ return new ByteArrayInputStream(base);
+ }
+ };
+ IO.skipFully(in, 7);
+ assertFalse("not yet open", opened[0]);
+ assertEquals(data[7], in.read());
+ assertTrue("now open", opened[0]);
+ }
+
+ public void testIncorrectBaseSize() throws IOException {
+ init(4, 4);
+ copy(0, 4);
+ assertValidState();
+
+ DeltaStream in = new DeltaStream(new ByteArrayInputStream(delta)) {
+ @Override
+ protected long getBaseSize() throws IOException {
+ return 128;
+ }
+
+ @Override
+ protected InputStream openBase() throws IOException {
+ return new ByteArrayInputStream(base);
+ }
+ };
+ try {
+ in.read(new byte[4]);
+ fail("did not throw an exception");
+ } catch (CorruptObjectException e) {
+ assertEquals(JGitText.get().baseLengthIncorrect, e.getMessage());
+ }
+
+ in = new DeltaStream(new ByteArrayInputStream(delta)) {
+ @Override
+ protected long getBaseSize() throws IOException {
+ return 4;
+ }
+
+ @Override
+ protected InputStream openBase() throws IOException {
+ return new ByteArrayInputStream(new byte[0]);
+ }
+ };
+ try {
+ in.read(new byte[4]);
+ fail("did not throw an exception");
+ } catch (CorruptObjectException e) {
+ assertEquals(JGitText.get().baseLengthIncorrect, e.getMessage());
+ }
+ }
+
+ private void init(int baseSize, int dataSize) throws IOException {
+ base = rng.nextBytes(baseSize);
+ data = new byte[dataSize];
+ deltaEnc = new DeltaEncoder(deltaBuf, baseSize, dataSize);
+ }
+
+ private void copy(int offset, int len) throws IOException {
+ System.arraycopy(base, offset, data, dataPtr, len);
+ deltaEnc.copy(offset, len);
+ assertEquals(deltaBuf.size(), deltaEnc.getSize());
+ dataPtr += len;
+ }
+
+ private void insert(String text) throws IOException {
+ insert(Constants.encode(text));
+ }
+
+ private void insert(byte[] text) throws IOException {
+ System.arraycopy(text, 0, data, dataPtr, text.length);
+ deltaEnc.insert(text);
+ assertEquals(deltaBuf.size(), deltaEnc.getSize());
+ dataPtr += text.length;
+ }
+
+ private void assertValidState() throws IOException {
+ assertEquals("test filled example result", data.length, dataPtr);
+
+ delta = deltaBuf.toByteArray();
+ assertEquals(base.length, BinaryDelta.getBaseSize(delta));
+ assertEquals(data.length, BinaryDelta.getResultSize(delta));
+ assertTrue(Arrays.equals(data, BinaryDelta.apply(base, delta)));
+
+ byte[] act = new byte[data.length];
+ DeltaStream in = open();
+ assertEquals(data.length, in.getSize());
+ assertEquals(data.length, in.read(act));
+ assertEquals(-1, in.read());
+ assertTrue(Arrays.equals(data, act));
+ }
+
+ private DeltaStream open() throws IOException {
+ return new DeltaStream(new ByteArrayInputStream(delta)) {
+ @Override
+ protected long getBaseSize() throws IOException {
+ return base.length;
+ }
+
+ @Override
+ protected InputStream openBase() throws IOException {
+ return new ByteArrayInputStream(base);
+ }
+ };
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java
index 2d6aa28d5a..cc7056225b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java
@@ -148,12 +148,12 @@ public class BundleWriterTest extends SampleDataRepositoryTestCase {
throws FileNotFoundException, IOException {
final BundleWriter bw;
- bw = new BundleWriter(db, NullProgressMonitor.INSTANCE);
+ bw = new BundleWriter(db);
bw.include(name, ObjectId.fromString(anObjectToInclude));
if (assume != null)
bw.assume(assume);
final ByteArrayOutputStream out = new ByteArrayOutputStream();
- bw.writeBundle(out);
+ bw.writeBundle(NullProgressMonitor.INSTANCE, out);
return out.toByteArray();
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java
index e18f741ac4..110804f91a 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java
@@ -58,10 +58,10 @@ import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PackFile;
import org.eclipse.jgit.lib.RepositoryTestCase;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.storage.file.PackFile;
import org.eclipse.jgit.util.JGitTestUtil;
import org.eclipse.jgit.util.NB;
import org.eclipse.jgit.util.TemporaryBuffer;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java
index 40c719f699..b331f9cf54 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java
@@ -56,7 +56,6 @@ import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
-import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Ref;
@@ -64,6 +63,7 @@ import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.storage.file.ObjectDirectory;
import org.eclipse.jgit.util.NB;
import org.eclipse.jgit.util.TemporaryBuffer;
@@ -176,7 +176,7 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase {
// Verify the only storage of b is our packed delta above.
//
ObjectDirectory od = (ObjectDirectory) src.getObjectDatabase();
- assertTrue("has b", od.hasObject(b));
+ assertTrue("has b", src.hasObject(b));
assertFalse("b not loose", od.fileFor(b).exists());
// Now use b but in a different commit than what is hidden.
@@ -255,7 +255,7 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase {
}
public void testUsingHiddenDeltaBaseFails() throws Exception {
- final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
+ final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
packHeader(pack, 1);
pack.write((Constants.OBJ_REF_DELTA) << 4 | 4);
b.copyRawTo(pack);
@@ -292,18 +292,18 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase {
public void testUsingHiddenCommonBlobFails() throws Exception {
// Try to use the 'b' blob that is hidden.
//
- TestRepository s = new TestRepository(src);
+ TestRepository<Repository> s = new TestRepository<Repository>(src);
RevCommit N = s.commit().parent(B).add("q", s.blob("b")).create();
// But don't include it in the pack.
//
- final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
+ final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
packHeader(pack, 2);
- copy(pack, src.openObject(N));
- copy(pack,src.openObject(s.parseBody(N).getTree()));
+ copy(pack, src.open(N));
+ copy(pack,src.open(s.parseBody(N).getTree()));
digest(pack);
- final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(256);
+ final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
final PacketLineOut inPckLine = new PacketLineOut(inBuf);
inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
+ "refs/heads/s" + '\0'
@@ -333,19 +333,19 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase {
public void testUsingUnknownBlobFails() throws Exception {
// Try to use the 'n' blob that is not on the server.
//
- TestRepository s = new TestRepository(src);
+ TestRepository<Repository> s = new TestRepository<Repository>(src);
RevBlob n = s.blob("n");
RevCommit N = s.commit().parent(B).add("q", n).create();
// But don't include it in the pack.
//
- final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
+ final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
packHeader(pack, 2);
- copy(pack, src.openObject(N));
- copy(pack,src.openObject(s.parseBody(N).getTree()));
+ copy(pack, src.open(N));
+ copy(pack,src.open(s.parseBody(N).getTree()));
digest(pack);
- final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(256);
+ final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
final PacketLineOut inPckLine = new PacketLineOut(inBuf);
inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
+ "refs/heads/s" + '\0'
@@ -373,18 +373,18 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase {
}
public void testUsingUnknownTreeFails() throws Exception {
- TestRepository s = new TestRepository(src);
+ TestRepository<Repository> s = new TestRepository<Repository>(src);
RevCommit N = s.commit().parent(B).add("q", s.blob("a")).create();
RevTree t = s.parseBody(N).getTree();
// Don't include the tree in the pack.
//
- final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64);
+ final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
packHeader(pack, 1);
- copy(pack, src.openObject(N));
+ copy(pack, src.open(N));
digest(pack);
- final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(256);
+ final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
final PacketLineOut inPckLine = new PacketLineOut(inBuf);
inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' '
+ "refs/heads/s" + '\0'
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java
index e3518251fe..a6bdd8886f 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java
@@ -48,7 +48,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import org.eclipse.jgit.lib.RepositoryConfig;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
public class TransportTest extends SampleDataRepositoryTestCase {
@@ -59,7 +59,7 @@ public class TransportTest extends SampleDataRepositoryTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
- final RepositoryConfig config = db.getConfig();
+ final Config config = db.getConfig();
remoteConfig = new RemoteConfig(config, "test");
remoteConfig.addURI(new URIish("http://everyones.loves.git/u/2"));
transport = null;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java
index e96445a30a..12c11482ae 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java
@@ -51,7 +51,7 @@ import junit.framework.TestCase;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
-import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.ObjectReader;
public class AbstractTreeIteratorTest extends TestCase {
@@ -73,7 +73,7 @@ public class AbstractTreeIteratorTest extends TestCase {
}
@Override
- public AbstractTreeIterator createSubtreeIterator(Repository repo)
+ public AbstractTreeIterator createSubtreeIterator(ObjectReader reader)
throws IncorrectObjectTypeException, IOException {
return null;
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java
index 111264b1c9..1ea2dc6250 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java
@@ -44,6 +44,7 @@
package org.eclipse.jgit.treewalk;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.RepositoryTestCase;
public class EmptyTreeIteratorTest extends RepositoryTestCase {
@@ -55,7 +56,8 @@ public class EmptyTreeIteratorTest extends RepositoryTestCase {
public void testCreateSubtreeIterator() throws Exception {
final EmptyTreeIterator etp = new EmptyTreeIterator();
- final AbstractTreeIterator sub = etp.createSubtreeIterator(db);
+ final ObjectReader reader = db.newObjectReader();
+ final AbstractTreeIterator sub = etp.createSubtreeIterator(reader);
assertNotNull(sub);
assertTrue(sub.first());
assertTrue(sub.eof());
@@ -106,7 +108,8 @@ public class EmptyTreeIteratorTest extends RepositoryTestCase {
called[0] = true;
}
};
- parent.createSubtreeIterator(db).stopWalk();
+ final ObjectReader reader = db.newObjectReader();
+ parent.createSubtreeIterator(reader).stopWalk();
assertTrue(called[0]);
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
index eb08e495b9..f939c90d81 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
@@ -49,6 +49,7 @@ import java.security.MessageDigest;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.RepositoryTestCase;
import org.eclipse.jgit.util.RawParseUtils;
@@ -124,7 +125,8 @@ public class FileTreeIteratorTest extends RepositoryTestCase {
assertFalse(top.eof());
assertEquals(FileMode.TREE.getBits(), top.mode);
- final AbstractTreeIterator sub = top.createSubtreeIterator(db);
+ final ObjectReader reader = db.newObjectReader();
+ final AbstractTreeIterator sub = top.createSubtreeIterator(reader);
assertTrue(sub instanceof FileTreeIterator);
final FileTreeIterator subfti = (FileTreeIterator) sub;
assertTrue(sub.first());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java
index 35298b803f..675331baf4 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java
@@ -66,8 +66,8 @@ public class NameConflictTreeWalkTest extends RepositoryTestCase {
private static final FileMode EXECUTABLE_FILE = FileMode.EXECUTABLE_FILE;
public void testNoDF_NoGap() throws Exception {
- final DirCache tree0 = DirCache.read(db);
- final DirCache tree1 = DirCache.read(db);
+ final DirCache tree0 = db.readDirCache();
+ final DirCache tree1 = db.readDirCache();
{
final DirCacheBuilder b0 = tree0.builder();
final DirCacheBuilder b1 = tree1.builder();
@@ -97,8 +97,8 @@ public class NameConflictTreeWalkTest extends RepositoryTestCase {
}
public void testDF_NoGap() throws Exception {
- final DirCache tree0 = DirCache.read(db);
- final DirCache tree1 = DirCache.read(db);
+ final DirCache tree0 = db.readDirCache();
+ final DirCache tree1 = db.readDirCache();
{
final DirCacheBuilder b0 = tree0.builder();
final DirCacheBuilder b1 = tree1.builder();
@@ -128,8 +128,8 @@ public class NameConflictTreeWalkTest extends RepositoryTestCase {
}
public void testDF_GapByOne() throws Exception {
- final DirCache tree0 = DirCache.read(db);
- final DirCache tree1 = DirCache.read(db);
+ final DirCache tree0 = db.readDirCache();
+ final DirCache tree1 = db.readDirCache();
{
final DirCacheBuilder b0 = tree0.builder();
final DirCacheBuilder b1 = tree1.builder();
@@ -160,8 +160,8 @@ public class NameConflictTreeWalkTest extends RepositoryTestCase {
}
public void testDF_SkipsSeenSubtree() throws Exception {
- final DirCache tree0 = DirCache.read(db);
- final DirCache tree1 = DirCache.read(db);
+ final DirCache tree0 = db.readDirCache();
+ final DirCache tree1 = db.readDirCache();
{
final DirCacheBuilder b0 = tree0.builder();
final DirCacheBuilder b1 = tree1.builder();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/PostOrderTreeWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/PostOrderTreeWalkTest.java
index d136b8f297..274df5bec0 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/PostOrderTreeWalkTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/PostOrderTreeWalkTest.java
@@ -86,7 +86,7 @@ public class PostOrderTreeWalkTest extends RepositoryTestCase {
}
public void testNoPostOrder() throws Exception {
- final DirCache tree = DirCache.read(db);
+ final DirCache tree = db.readDirCache();
{
final DirCacheBuilder b = tree.builder();
@@ -115,7 +115,7 @@ public class PostOrderTreeWalkTest extends RepositoryTestCase {
}
public void testWithPostOrder_EnterSubtree() throws Exception {
- final DirCache tree = DirCache.read(db);
+ final DirCache tree = db.readDirCache();
{
final DirCacheBuilder b = tree.builder();
@@ -150,7 +150,7 @@ public class PostOrderTreeWalkTest extends RepositoryTestCase {
}
public void testWithPostOrder_NoEnterSubtree() throws Exception {
- final DirCache tree = DirCache.read(db);
+ final DirCache tree = db.readDirCache();
{
final DirCacheBuilder b = tree.builder();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathSuffixFilterTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathSuffixFilterTestCase.java
index 1aaefc415f..302eada999 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathSuffixFilterTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathSuffixFilterTestCase.java
@@ -43,6 +43,8 @@
package org.eclipse.jgit.treewalk.filter;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
@@ -52,17 +54,17 @@ import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.RepositoryTestCase;
import org.eclipse.jgit.treewalk.TreeWalk;
public class PathSuffixFilterTestCase extends RepositoryTestCase {
public void testNonRecursiveFiltering() throws IOException {
- final ObjectWriter ow = new ObjectWriter(db);
- final ObjectId aSth = ow.writeBlob("a.sth".getBytes());
- final ObjectId aTxt = ow.writeBlob("a.txt".getBytes());
- final DirCache dc = DirCache.read(db);
+ final ObjectInserter odi = db.newObjectInserter();
+ final ObjectId aSth = odi.insert(OBJ_BLOB, "a.sth".getBytes());
+ final ObjectId aTxt = odi.insert(OBJ_BLOB, "a.txt".getBytes());
+ final DirCache dc = db.readDirCache();
final DirCacheBuilder builder = dc.builder();
final DirCacheEntry aSthEntry = new DirCacheEntry("a.sth");
aSthEntry.setFileMode(FileMode.REGULAR_FILE);
@@ -73,7 +75,8 @@ public class PathSuffixFilterTestCase extends RepositoryTestCase {
builder.add(aSthEntry);
builder.add(aTxtEntry);
builder.finish();
- final ObjectId treeId = dc.writeTree(ow);
+ final ObjectId treeId = dc.writeTree(odi);
+ odi.flush();
final TreeWalk tw = new TreeWalk(db);
@@ -92,12 +95,12 @@ public class PathSuffixFilterTestCase extends RepositoryTestCase {
}
public void testRecursiveFiltering() throws IOException {
- final ObjectWriter ow = new ObjectWriter(db);
- final ObjectId aSth = ow.writeBlob("a.sth".getBytes());
- final ObjectId aTxt = ow.writeBlob("a.txt".getBytes());
- final ObjectId bSth = ow.writeBlob("b.sth".getBytes());
- final ObjectId bTxt = ow.writeBlob("b.txt".getBytes());
- final DirCache dc = DirCache.read(db);
+ final ObjectInserter odi = db.newObjectInserter();
+ final ObjectId aSth = odi.insert(OBJ_BLOB, "a.sth".getBytes());
+ final ObjectId aTxt = odi.insert(OBJ_BLOB, "a.txt".getBytes());
+ final ObjectId bSth = odi.insert(OBJ_BLOB, "b.sth".getBytes());
+ final ObjectId bTxt = odi.insert(OBJ_BLOB, "b.txt".getBytes());
+ final DirCache dc = db.readDirCache();
final DirCacheBuilder builder = dc.builder();
final DirCacheEntry aSthEntry = new DirCacheEntry("a.sth");
aSthEntry.setFileMode(FileMode.REGULAR_FILE);
@@ -116,7 +119,8 @@ public class PathSuffixFilterTestCase extends RepositoryTestCase {
builder.add(bSthEntry);
builder.add(bTxtEntry);
builder.finish();
- final ObjectId treeId = dc.writeTree(ow);
+ final ObjectId treeId = dc.writeTree(odi);
+ odi.flush();
final TreeWalk tw = new TreeWalk(db);
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 51d440e58e..a8f39d93bf 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -9,6 +9,7 @@ Export-Package: org.eclipse.jgit;version="0.9.0",
org.eclipse.jgit.api;version="0.9.0",
org.eclipse.jgit.diff;version="0.9.0",
org.eclipse.jgit.dircache;version="0.9.0",
+ org.eclipse.jgit.events;version="0.9.0",
org.eclipse.jgit.errors;version="0.9.0",
org.eclipse.jgit.fnmatch;version="0.9.0",
org.eclipse.jgit.ignore;version="0.9.0",
@@ -19,6 +20,8 @@ Export-Package: org.eclipse.jgit;version="0.9.0",
org.eclipse.jgit.revplot;version="0.9.0",
org.eclipse.jgit.revwalk;version="0.9.0",
org.eclipse.jgit.revwalk.filter;version="0.9.0",
+ org.eclipse.jgit.storage.file;version="0.9.0",
+ org.eclipse.jgit.storage.pack;version="0.9.0",
org.eclipse.jgit.transport;version="0.9.0",
org.eclipse.jgit.treewalk;version="0.9.0",
org.eclipse.jgit.treewalk.filter;version="0.9.0",
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
index ca1832e571..88c6c8e3a4 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
@@ -127,7 +127,7 @@ duplicateAdvertisementsOf=duplicate advertisements of {0}
duplicateRef=Duplicate ref: {0}
duplicateRemoteRefUpdateIsIllegal=Duplicate remote ref update is illegal. Affected remote name: {0}
duplicateStagesNotAllowed=Duplicate stages not allowed
-eitherGIT_DIRorGIT_WORK_TREEmustBePassed=Either GIT_DIR or GIT_WORK_TREE must be passed to Repository constructor
+eitherGitDirOrWorkTreeRequired=One of setGitDir or setWorkTree must be called.
emptyPathNotPermitted=Empty path not permitted.
encryptionError=Encryption error: {0}
endOfFileInEscape=End of file in escape
@@ -224,6 +224,7 @@ mergeStrategyAlreadyExistsAsDefault=Merge strategy "{0}" already exists as a def
mergeStrategyDoesNotSupportHeads=merge strategy {0} does not support {1} heads to be merged into HEAD
mergeUsingStrategyResultedInDescription=Merge using strategy {0} resulted in: {1}. {2}
missingAccesskey=Missing accesskey.
+missingDeltaBase=delta base
missingForwardImageInGITBinaryPatch=Missing forward-image in GIT binary patch
missingObject=Missing {0} {1}
missingPrerequisiteCommits=missing prerequisite commits:
@@ -304,6 +305,7 @@ renamesAlreadyFound=Renames have already been found.
renamesFindingByContent=Finding renames by content similarity
renamesFindingExact=Finding exact renames
repositoryAlreadyExists=Repository already exists: {0}
+repositoryConfigFileInvalid=Repository config file {0} invalid {1}
repositoryIsRequired=Repository is required.
repositoryNotFound=repository not found: {0}
repositoryState_applyMailbox=Apply mailbox
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
index 71e5e4a899..9df9887af4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
@@ -187,7 +187,7 @@ public class JGitText extends TranslationBundle {
/***/ public String duplicateRef;
/***/ public String duplicateRemoteRefUpdateIsIllegal;
/***/ public String duplicateStagesNotAllowed;
- /***/ public String eitherGIT_DIRorGIT_WORK_TREEmustBePassed;
+ /***/ public String eitherGitDirOrWorkTreeRequired;
/***/ public String emptyPathNotPermitted;
/***/ public String encryptionError;
/***/ public String endOfFileInEscape;
@@ -284,6 +284,7 @@ public class JGitText extends TranslationBundle {
/***/ public String mergeStrategyDoesNotSupportHeads;
/***/ public String mergeUsingStrategyResultedInDescription;
/***/ public String missingAccesskey;
+ /***/ public String missingDeltaBase;
/***/ public String missingForwardImageInGITBinaryPatch;
/***/ public String missingObject;
/***/ public String missingPrerequisiteCommits;
@@ -363,6 +364,7 @@ public class JGitText extends TranslationBundle {
/***/ public String renamesFindingByContent;
/***/ public String renamesFindingExact;
/***/ public String repositoryAlreadyExists;
+ /***/ public String repositoryConfigFileInvalid;
/***/ public String repositoryIsRequired;
/***/ public String repositoryNotFound;
/***/ public String repositoryState_applyMailbox;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
index 157b85f9c9..e41ab580bb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
@@ -127,7 +127,7 @@ public class AddCommand extends GitCommand<DirCache> {
addAll = true;
try {
- dc = DirCache.lock(repo);
+ dc = repo.lockDirCache();
ObjectWriter ow = new ObjectWriter(repo);
DirCacheIterator c;
@@ -147,7 +147,7 @@ public class AddCommand extends GitCommand<DirCache> {
while (tw.next()) {
String path = tw.getPathString();
- final File file = new File(repo.getWorkDir(), path);
+ final File file = new File(repo.getWorkTree(), path);
WorkingTreeIterator f = tw.getTree(1, WorkingTreeIterator.class);
if (tw.getTree(0, DirCacheIterator.class) == null &&
f != null && f.isEntryIgnored()) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
index eef952e7cd..17b7113470 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
@@ -54,13 +54,13 @@ import org.eclipse.jgit.errors.UnmergedPathException;
import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
+import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
@@ -139,54 +139,66 @@ public class CommitCommand extends GitCommand<RevCommit> {
parents.add(0, headId);
// lock the index
- DirCache index = DirCache.lock(repo);
+ DirCache index = repo.lockDirCache();
try {
- ObjectWriter repoWriter = new ObjectWriter(repo);
-
- // Write the index as tree to the object database. This may fail
- // for example when the index contains unmerged pathes
- // (unresolved conflicts)
- ObjectId indexTreeId = index.writeTree(repoWriter);
+ ObjectInserter odi = repo.newObjectInserter();
+ try {
+ // Write the index as tree to the object database. This may
+ // fail for example when the index contains unmerged paths
+ // (unresolved conflicts)
+ ObjectId indexTreeId = index.writeTree(odi);
- // Create a Commit object, populate it and write it
- Commit commit = new Commit(repo);
- commit.setCommitter(committer);
- commit.setAuthor(author);
- commit.setMessage(message);
+ // Create a Commit object, populate it and write it
+ Commit commit = new Commit(repo);
+ commit.setCommitter(committer);
+ commit.setAuthor(author);
+ commit.setMessage(message);
- commit.setParentIds(parents.toArray(new ObjectId[]{}));
- commit.setTreeId(indexTreeId);
- ObjectId commitId = repoWriter.writeCommit(commit);
+ commit.setParentIds(parents.toArray(new ObjectId[] {}));
+ commit.setTreeId(indexTreeId);
+ ObjectId commitId = odi.insert(Constants.OBJ_COMMIT, odi
+ .format(commit));
+ odi.flush();
- RevCommit revCommit = new RevWalk(repo).parseCommit(commitId);
- RefUpdate ru = repo.updateRef(Constants.HEAD);
- ru.setNewObjectId(commitId);
- ru.setRefLogMessage("commit : " + revCommit.getShortMessage(),
- false);
+ RevWalk revWalk = new RevWalk(repo);
+ try {
+ RevCommit revCommit = revWalk.parseCommit(commitId);
+ RefUpdate ru = repo.updateRef(Constants.HEAD);
+ ru.setNewObjectId(commitId);
+ ru.setRefLogMessage("commit : "
+ + revCommit.getShortMessage(), false);
- ru.setExpectedOldObjectId(headId);
- Result rc = ru.update();
- switch (rc) {
- case NEW:
- case FAST_FORWARD:
- setCallable(false);
- if (state == RepositoryState.MERGING_RESOLVED) {
- // Commit was successful. Now delete the files
- // used for merge commits
- new File(repo.getDirectory(), Constants.MERGE_HEAD)
- .delete();
- new File(repo.getDirectory(), Constants.MERGE_MSG)
- .delete();
+ ru.setExpectedOldObjectId(headId);
+ Result rc = ru.update();
+ switch (rc) {
+ case NEW:
+ case FAST_FORWARD: {
+ setCallable(false);
+ File meta = repo.getDirectory();
+ if (state == RepositoryState.MERGING_RESOLVED
+ && meta != null) {
+ // Commit was successful. Now delete the files
+ // used for merge commits
+ new File(meta, Constants.MERGE_HEAD).delete();
+ new File(meta, Constants.MERGE_MSG).delete();
+ }
+ return revCommit;
+ }
+ case REJECTED:
+ case LOCK_FAILURE:
+ throw new ConcurrentRefUpdateException(JGitText
+ .get().couldNotLockHEAD, ru.getRef(), rc);
+ default:
+ throw new JGitInternalException(MessageFormat
+ .format(JGitText.get().updatingRefFailed,
+ Constants.HEAD,
+ commitId.toString(), rc));
+ }
+ } finally {
+ revWalk.release();
}
- return revCommit;
- case REJECTED:
- case LOCK_FAILURE:
- throw new ConcurrentRefUpdateException(
- JGitText.get().couldNotLockHEAD, ru.getRef(), rc);
- default:
- throw new JGitInternalException(MessageFormat.format(
- JGitText.get().updatingRefFailed
- , Constants.HEAD, commitId.toString(), rc));
+ } finally {
+ odi.release();
}
} finally {
index.unlock();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
index 00a0309152..972aa618ad 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
@@ -119,37 +119,41 @@ public class MergeCommand extends GitCommand<MergeResult> {
// Check for FAST_FORWARD, ALREADY_UP_TO_DATE
RevWalk revWalk = new RevWalk(repo);
- RevCommit headCommit = revWalk.lookupCommit(head.getObjectId());
-
- Ref ref = commits.get(0);
-
- refLogMessage.append(ref.getName());
-
- // handle annotated tags
- ObjectId objectId = ref.getPeeledObjectId();
- if (objectId == null)
- objectId = ref.getObjectId();
-
- RevCommit srcCommit = revWalk.lookupCommit(objectId);
- if (revWalk.isMergedInto(srcCommit, headCommit)) {
- setCallable(false);
- return new MergeResult(headCommit,
- MergeStatus.ALREADY_UP_TO_DATE, mergeStrategy);
- } else if (revWalk.isMergedInto(headCommit, srcCommit)) {
- // FAST_FORWARD detected: skip doing a real merge but only
- // update HEAD
- refLogMessage.append(": " + MergeStatus.FAST_FORWARD);
- checkoutNewHead(revWalk, headCommit, srcCommit);
- updateHead(refLogMessage, srcCommit, head.getObjectId());
- setCallable(false);
- return new MergeResult(srcCommit, MergeStatus.FAST_FORWARD,
- mergeStrategy);
- } else {
- return new MergeResult(
- headCommit,
- MergeResult.MergeStatus.NOT_SUPPORTED,
- mergeStrategy,
- JGitText.get().onlyAlreadyUpToDateAndFastForwardMergesAreAvailable);
+ try {
+ RevCommit headCommit = revWalk.lookupCommit(head.getObjectId());
+
+ Ref ref = commits.get(0);
+
+ refLogMessage.append(ref.getName());
+
+ // handle annotated tags
+ ObjectId objectId = ref.getPeeledObjectId();
+ if (objectId == null)
+ objectId = ref.getObjectId();
+
+ RevCommit srcCommit = revWalk.lookupCommit(objectId);
+ if (revWalk.isMergedInto(srcCommit, headCommit)) {
+ setCallable(false);
+ return new MergeResult(headCommit,
+ MergeStatus.ALREADY_UP_TO_DATE, mergeStrategy);
+ } else if (revWalk.isMergedInto(headCommit, srcCommit)) {
+ // FAST_FORWARD detected: skip doing a real merge but only
+ // update HEAD
+ refLogMessage.append(": " + MergeStatus.FAST_FORWARD);
+ checkoutNewHead(revWalk, headCommit, srcCommit);
+ updateHead(refLogMessage, srcCommit, head.getObjectId());
+ setCallable(false);
+ return new MergeResult(srcCommit, MergeStatus.FAST_FORWARD,
+ mergeStrategy);
+ } else {
+ return new MergeResult(
+ headCommit,
+ MergeResult.MergeStatus.NOT_SUPPORTED,
+ mergeStrategy,
+ JGitText.get().onlyAlreadyUpToDateAndFastForwardMergesAreAvailable);
+ }
+ } finally {
+ revWalk.release();
}
} catch (IOException e) {
throw new JGitInternalException(
@@ -163,7 +167,7 @@ public class MergeCommand extends GitCommand<MergeResult> {
RevCommit newHeadCommit) throws IOException, CheckoutConflictException {
GitIndex index = repo.getIndex();
- File workDir = repo.getWorkDir();
+ File workDir = repo.getWorkTree();
if (workDir != null) {
WorkDirCheckout workDirCheckout = new WorkDirCheckout(repo,
workDir, headCommit.asCommit(revWalk).getTree(), index,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
index cdcc5e63e4..835cf6f865 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
@@ -50,20 +50,24 @@ import static org.eclipse.jgit.lib.FileMode.GITLINK;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.CoreConfig;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.patch.FileHeader;
import org.eclipse.jgit.patch.HunkHeader;
import org.eclipse.jgit.patch.FileHeader.PatchType;
+import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.QuotedString;
import org.eclipse.jgit.util.io.DisabledOutputStream;
@@ -83,6 +87,8 @@ public class DiffFormatter {
private RawText.Factory rawTextFactory = RawText.FACTORY;
+ private long bigFileThreshold = 50 * 1024 * 1024;
+
/**
* Create a new formatter with a default level of context.
*
@@ -110,6 +116,9 @@ public class DiffFormatter {
*/
public void setRepository(Repository repository) {
db = repository;
+
+ CoreConfig cfg = db.getConfig().get(CoreConfig.KEY);
+ bigFileThreshold = cfg.getStreamFileThreshold();
}
/**
@@ -158,6 +167,19 @@ public class DiffFormatter {
}
/**
+ * Set the maximum file size that should be considered for diff output.
+ * <p>
+ * Text files that are larger than this size will not have a difference
+ * generated during output.
+ *
+ * @param bigFileThreshold
+ * the limit, in bytes.
+ */
+ public void setBigFileThreshold(long bigFileThreshold) {
+ this.bigFileThreshold = bigFileThreshold;
+ }
+
+ /**
* Flush the underlying output stream of this formatter.
*
* @throws IOException
@@ -318,9 +340,32 @@ public class DiffFormatter {
if (db == null)
throw new IllegalStateException(JGitText.get().repositoryIsRequired);
+
if (id.isComplete()) {
- ObjectLoader ldr = db.openObject(id.toObjectId());
- return ldr.getCachedBytes();
+ ObjectLoader ldr = db.open(id.toObjectId());
+ if (!ldr.isLarge())
+ return ldr.getCachedBytes();
+
+ long sz = ldr.getSize();
+ if (sz < bigFileThreshold && sz < Integer.MAX_VALUE) {
+ byte[] buf;
+ try {
+ buf = new byte[(int) sz];
+ } catch (OutOfMemoryError noMemory) {
+ LargeObjectException e;
+
+ e = new LargeObjectException(id.toObjectId());
+ e.initCause(noMemory);
+ throw e;
+ }
+ InputStream in = ldr.openStream();
+ try {
+ IO.readFully(in, buf, 0, buf.length);
+ } finally {
+ in.close();
+ }
+ return buf;
+ }
}
return new byte[] {};
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
index cf5615a1cb..a3203e349f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
@@ -57,6 +57,7 @@ import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
@@ -294,14 +295,19 @@ public class RenameDetector {
return;
if (getRenameLimit() == 0 || cnt <= getRenameLimit()) {
- SimilarityRenameDetector d;
-
- d = new SimilarityRenameDetector(repo, deleted, added);
- d.setRenameScore(getRenameScore());
- d.compute(pm);
- deleted = d.getLeftOverSources();
- added = d.getLeftOverDestinations();
- entries.addAll(d.getMatches());
+ ObjectReader reader = repo.newObjectReader();
+ try {
+ SimilarityRenameDetector d;
+
+ d = new SimilarityRenameDetector(reader, deleted, added);
+ d.setRenameScore(getRenameScore());
+ d.compute(pm);
+ deleted = d.getLeftOverSources();
+ added = d.getLeftOverDestinations();
+ entries.addAll(d.getMatches());
+ } finally {
+ reader.release();
+ }
} else {
overRenameLimit = true;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java
index d5a31d6044..22b74f461c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java
@@ -43,9 +43,14 @@
package org.eclipse.jgit.diff;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.Arrays;
+import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectStream;
/**
* Index structure of lines/blocks in one file.
@@ -107,10 +112,20 @@ class SimilarityIndex {
fileSize = size;
}
- void hash(ObjectLoader obj) {
- byte[] raw = obj.getCachedBytes();
- setFileSize(raw.length);
- hash(raw, 0, raw.length);
+ void hash(ObjectLoader obj) throws MissingObjectException, IOException {
+ if (obj.isLarge()) {
+ ObjectStream in = obj.openStream();
+ try {
+ setFileSize(in.getSize());
+ hash(in, fileSize);
+ } finally {
+ in.close();
+ }
+ } else {
+ byte[] raw = obj.getCachedBytes();
+ setFileSize(raw.length);
+ hash(raw, 0, raw.length);
+ }
}
void hash(byte[] raw, int ptr, final int end) {
@@ -129,6 +144,35 @@ class SimilarityIndex {
}
}
+ void hash(InputStream in, long remaining) throws IOException {
+ byte[] buf = new byte[4096];
+ int ptr = 0;
+ int cnt = 0;
+
+ while (0 < remaining) {
+ int hash = 5381;
+
+ // Hash one line, or one block, whichever occurs first.
+ int n = 0;
+ do {
+ if (ptr == cnt) {
+ ptr = 0;
+ cnt = in.read(buf, 0, buf.length);
+ if (cnt <= 0)
+ throw new EOFException();
+ }
+
+ n++;
+ int c = buf[ptr++] & 0xff;
+ if (c == '\n')
+ break;
+ hash = (hash << 5) ^ c;
+ } while (n < 64 && n < remaining);
+ add(hash, n);
+ remaining -= n;
+ }
+ }
+
/**
* Sort the internal table so it can be used for efficient scoring.
* <p>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
index e2115f0acc..d05fc2a313 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
@@ -50,11 +50,12 @@ import java.util.List;
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.ProgressMonitor;
-import org.eclipse.jgit.lib.Repository;
class SimilarityRenameDetector {
/**
@@ -71,7 +72,7 @@ class SimilarityRenameDetector {
private static final int SCORE_SHIFT = 2 * BITS_PER_INDEX;
- private final Repository repo;
+ private ObjectReader reader;
/**
* All sources to consider for copies or renames.
@@ -111,9 +112,9 @@ class SimilarityRenameDetector {
private List<DiffEntry> out;
- SimilarityRenameDetector(Repository repo, List<DiffEntry> srcs,
+ SimilarityRenameDetector(ObjectReader reader, List<DiffEntry> srcs,
List<DiffEntry> dsts) {
- this.repo = repo;
+ this.reader = reader;
this.srcs = srcs;
this.dsts = dsts;
}
@@ -336,13 +337,13 @@ class SimilarityRenameDetector {
private SimilarityIndex hash(ObjectId objectId) throws IOException {
SimilarityIndex r = new SimilarityIndex();
- r.hash(repo.openObject(objectId));
+ r.hash(reader.open(objectId));
r.sort();
return r;
}
private long size(ObjectId objectId) throws IOException {
- return repo.openObject(objectId).getSize();
+ return reader.getObjectSize(objectId, Constants.OBJ_BLOB);
}
private static int score(long value) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
index 42fea48520..cc10fad2b4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
@@ -64,10 +64,9 @@ import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.UnmergedPathException;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.LockFile;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectWriter;
-import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.storage.file.LockFile;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.MutableInteger;
import org.eclipse.jgit.util.NB;
@@ -158,28 +157,6 @@ public class DirCache {
}
/**
- * Create a new in-core index representation and read an index from disk.
- * <p>
- * The new index will be read before it is returned to the caller. Read
- * failures are reported as exceptions and therefore prevent the method from
- * returning a partially populated index.
- *
- * @param db
- * repository the caller wants to read the default index of.
- * @return a cache representing the contents of the specified index file (if
- * it exists) or an empty cache if the file does not exist.
- * @throws IOException
- * the index file is present but could not be read.
- * @throws CorruptObjectException
- * the index file is using a format or extension that this
- * library does not support.
- */
- public static DirCache read(final Repository db)
- throws CorruptObjectException, IOException {
- return read(new File(db.getDirectory(), "index"));
- }
-
- /**
* Create a new in-core index representation, lock it, and read from disk.
* <p>
* The new index will be locked and then read before it is returned to the
@@ -220,29 +197,6 @@ public class DirCache {
return c;
}
- /**
- * Create a new in-core index representation, lock it, and read from disk.
- * <p>
- * The new index will be locked and then read before it is returned to the
- * caller. Read failures are reported as exceptions and therefore prevent
- * the method from returning a partially populated index.
- *
- * @param db
- * repository the caller wants to read the default index of.
- * @return a cache representing the contents of the specified index file (if
- * it exists) or an empty cache if the file does not exist.
- * @throws IOException
- * the index file is present but could not be read, or the lock
- * could not be obtained.
- * @throws CorruptObjectException
- * the index file is using a format or extension that this
- * library does not support.
- */
- public static DirCache lock(final Repository db)
- throws CorruptObjectException, IOException {
- return lock(new File(db.getDirectory(), "index"));
- }
-
/** Location of the current version of the index file. */
private final File liveFile;
@@ -768,7 +722,9 @@ public class DirCache {
* Write all index trees to the object store, returning the root tree.
*
* @param ow
- * the writer to use when serializing to the store.
+ * the writer to use when serializing to the store. The caller is
+ * responsible for flushing the inserter before trying to use the
+ * returned tree identity.
* @return identity for the root tree.
* @throws UnmergedPathException
* one or more paths contain higher-order stages (stage > 0),
@@ -779,7 +735,7 @@ public class DirCache {
* @throws IOException
* an unexpected error occurred writing to the object store.
*/
- public ObjectId writeTree(final ObjectWriter ow)
+ public ObjectId writeTree(final ObjectInserter ow)
throws UnmergedPathException, IOException {
return getCacheTree(true).writeTree(sortedEntries, 0, 0, ow);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuildIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuildIterator.java
index 181192d141..1eb95c4be0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuildIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuildIterator.java
@@ -50,7 +50,7 @@ import java.io.IOException;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
/**
@@ -106,7 +106,7 @@ public class DirCacheBuildIterator extends DirCacheIterator {
}
@Override
- public AbstractTreeIterator createSubtreeIterator(final Repository repo)
+ public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader)
throws IncorrectObjectTypeException, IOException {
if (currentSubtree == null)
throw new IncorrectObjectTypeException(getEntryObjectId(),
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java
index e6b6197819..5665002dc7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java
@@ -50,8 +50,7 @@ import java.util.Arrays;
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.WindowCursor;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
@@ -149,11 +148,12 @@ public class DirCacheBuilder extends BaseDirCacheEditor {
* as necessary.
* @param stage
* stage of the entries when adding them.
- * @param db
- * repository the tree(s) will be read from during recursive
+ * @param reader
+ * reader the tree(s) will be read from during recursive
* traversal. This must be the same repository that the resulting
* DirCache would be written out to (or used in) otherwise the
* caller is simply asking for deferred MissingObjectExceptions.
+ * Caller is responsible for releasing this reader when done.
* @param tree
* the tree to recursively add. This tree's contents will appear
* under <code>pathPrefix</code>. The ObjectId must be that of a
@@ -163,16 +163,11 @@ public class DirCacheBuilder extends BaseDirCacheEditor {
* a tree cannot be read to iterate through its entries.
*/
public void addTree(final byte[] pathPrefix, final int stage,
- final Repository db, final AnyObjectId tree) throws IOException {
- final TreeWalk tw = new TreeWalk(db);
+ final ObjectReader reader, final AnyObjectId tree) throws IOException {
+ final TreeWalk tw = new TreeWalk(reader);
tw.reset();
- final WindowCursor curs = new WindowCursor();
- try {
- tw.addTree(new CanonicalTreeParser(pathPrefix, db, tree
- .toObjectId(), curs));
- } finally {
- curs.release();
- }
+ tw.addTree(new CanonicalTreeParser(pathPrefix, reader, tree
+ .toObjectId()));
tw.setRecursive(true);
if (tw.next()) {
final DirCacheEntry newEntry = toEntry(stage, tw);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java
index 9c47187821..b4e2d2c2dd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java
@@ -50,7 +50,7 @@ import java.util.Arrays;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
-import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
@@ -125,7 +125,7 @@ public class DirCacheIterator extends AbstractTreeIterator {
}
@Override
- public AbstractTreeIterator createSubtreeIterator(final Repository repo)
+ public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader)
throws IncorrectObjectTypeException, IOException {
if (currentSubtree == null)
throw new IncorrectObjectTypeException(getEntryObjectId(),
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
index 144b1a6cfc..e04b797ab3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
@@ -57,7 +57,7 @@ import org.eclipse.jgit.errors.UnmergedPathException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.util.MutableInteger;
import org.eclipse.jgit.util.RawParseUtils;
@@ -311,7 +311,7 @@ public class DirCacheTree {
* an unexpected error occurred writing to the object store.
*/
ObjectId writeTree(final DirCacheEntry[] cache, int cIdx,
- final int pathOffset, final ObjectWriter ow)
+ final int pathOffset, final ObjectInserter ow)
throws UnmergedPathException, IOException {
if (id == null) {
final int endIdx = cIdx + entrySpan;
@@ -346,13 +346,13 @@ public class DirCacheTree {
entryIdx++;
}
- id = ow.writeCanonicalTree(out.toByteArray());
+ id = ow.insert(Constants.OBJ_TREE, out.toByteArray());
}
return id;
}
private int computeSize(final DirCacheEntry[] cache, int cIdx,
- final int pathOffset, final ObjectWriter ow)
+ final int pathOffset, final ObjectInserter ow)
throws UnmergedPathException, IOException {
final int endIdx = cIdx + entrySpan;
int childIdx = 0;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexChangedEvent.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/LargeObjectException.java
index c866db531e..d897c51de1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexChangedEvent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/LargeObjectException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@@ -41,27 +41,27 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.errors;
+
+import org.eclipse.jgit.lib.ObjectId;
+
+/** An object is too big to load into memory as a single byte array. */
+public class LargeObjectException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ /** Create a large object exception, where the object isn't known. */
+ public LargeObjectException() {
+ // Do nothing.
+ }
-/**
- * This class passes information about a changed Git index to a
- * {@link RepositoryListener}
- *
- * Currently only a reference to the repository is passed.
- */
-public class IndexChangedEvent extends RepositoryChangedEvent {
/**
- * Create an event describing index changes in a repository.
+ * Create a large object exception, naming the object that is too big.
*
- * @param repository
- * the repository whose index (DirCache) recently changed.
+ * @param id
+ * identity of the object that is too big to be loaded as a byte
+ * array in this JVM.
*/
- public IndexChangedEvent(final Repository repository) {
- super(repository);
- }
-
- @Override
- public String toString() {
- return "IndexChangedEvent[" + getRepository() + "]";
+ public LargeObjectException(ObjectId id) {
+ super(id.name());
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/NoWorkTreeException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/NoWorkTreeException.java
new file mode 100644
index 0000000000..f2980efe69
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/NoWorkTreeException.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.errors;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Indicates a {@link Repository} has no working directory, and is thus bare.
+ */
+public class NoWorkTreeException extends IllegalStateException {
+ private static final long serialVersionUID = 1L;
+
+ /** Creates an exception indicating there is no work tree for a repository. */
+ public NoWorkTreeException() {
+ super(JGitText.get().bareRepositoryNoWorkdirAndIndex);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/StoredObjectRepresentationNotAvailableException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/StoredObjectRepresentationNotAvailableException.java
new file mode 100644
index 0000000000..e9e3f4d65e
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/StoredObjectRepresentationNotAvailableException.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.errors;
+
+import org.eclipse.jgit.storage.pack.ObjectToPack;
+
+/** A previously selected representation is no longer available. */
+public class StoredObjectRepresentationNotAvailableException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Construct an error for an object.
+ *
+ * @param otp
+ * the object whose current representation is no longer present.
+ */
+ public StoredObjectRepresentationNotAvailableException(ObjectToPack otp) {
+ // Do nothing.
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/events/ConfigChangedEvent.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/ConfigChangedEvent.java
new file mode 100644
index 0000000000..79598eacb3
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/ConfigChangedEvent.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.events;
+
+/** Describes a change to one or more keys in the configuration. */
+public class ConfigChangedEvent extends RepositoryEvent<ConfigChangedListener> {
+ @Override
+ public Class<ConfigChangedListener> getListenerType() {
+ return ConfigChangedListener.class;
+ }
+
+ @Override
+ public void dispatch(ConfigChangedListener listener) {
+ listener.onConfigChanged(this);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryAdapter.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/ConfigChangedListener.java
index e43c33ad7d..322cf7f6d6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryAdapter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/ConfigChangedListener.java
@@ -41,20 +41,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
-
-/**
- * A default {@link RepositoryListener} that does nothing except invoke an
- * optional general method for any repository change.
- */
-public class RepositoryAdapter implements RepositoryListener {
-
- public void indexChanged(final IndexChangedEvent e) {
- // Empty
- }
-
- public void refsChanged(final RefsChangedEvent e) {
- // Empty
- }
+package org.eclipse.jgit.events;
+/** Receives {@link ConfigChangedEvent}s. */
+public interface ConfigChangedListener extends RepositoryListener {
+ /**
+ * Invoked when any change is made to the configuration.
+ *
+ * @param event
+ * information about the changes.
+ */
+ void onConfigChanged(ConfigChangedEvent event);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/events/IndexChangedEvent.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/IndexChangedEvent.java
new file mode 100644
index 0000000000..a54288ee9e
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/IndexChangedEvent.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.events;
+
+/** Describes a change to one or more paths in the index file. */
+public class IndexChangedEvent extends RepositoryEvent<IndexChangedListener> {
+ @Override
+ public Class<IndexChangedListener> getListenerType() {
+ return IndexChangedListener.class;
+ }
+
+ @Override
+ public void dispatch(IndexChangedListener listener) {
+ listener.onIndexChanged(this);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryListener.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/IndexChangedListener.java
index 0473093e20..d41ef74ee9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryListener.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/IndexChangedListener.java
@@ -41,29 +41,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.events;
-/**
- * A RepositoryListener gets notification about changes in refs or repository.
- * <p>
- * It currently does <em>not</em> get notification about which items are
- * changed.
- */
-public interface RepositoryListener {
+/** Receives {@link IndexChangedEvent}s. */
+public interface IndexChangedListener extends RepositoryListener {
/**
- * Invoked when a ref changes
+ * Invoked when any change is made to the index.
*
- * @param e
+ * @param event
* information about the changes.
*/
- void refsChanged(RefsChangedEvent e);
-
- /**
- * Invoked when the index changes
- *
- * @param e
- * information about the changes.
- */
- void indexChanged(IndexChangedEvent e);
-
+ void onIndexChanged(IndexChangedEvent event);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefsChangedEvent.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/ListenerHandle.java
index 705c6138e3..ef90b2205c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefsChangedEvent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/ListenerHandle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@@ -41,27 +41,31 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
+package org.eclipse.jgit.events;
-/**
- * This class passes information about a changed Git index to a
- * {@link RepositoryListener}
- *
- * Currently only a reference to the repository is passed.
- */
-public class RefsChangedEvent extends RepositoryChangedEvent {
- /**
- * Create an event describing reference changes in a repository.
- *
- * @param repository
- * the repository whose references recently changed.
- */
- public RefsChangedEvent(final Repository repository) {
- super(repository);
+/** Tracks a previously registered {@link RepositoryListener}. */
+public class ListenerHandle {
+ private final ListenerList parent;
+
+ final Class<? extends RepositoryListener> type;
+
+ final RepositoryListener listener;
+
+ ListenerHandle(ListenerList parent,
+ Class<? extends RepositoryListener> type,
+ RepositoryListener listener) {
+ this.parent = parent;
+ this.type = type;
+ this.listener = listener;
+ }
+
+ /** Remove the listener and stop receiving events. */
+ public void remove() {
+ parent.remove(this);
}
@Override
public String toString() {
- return "RefsChangedEvent[" + getRepository() + "]";
+ return type.getSimpleName() + "[" + listener + "]";
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/events/ListenerList.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/ListenerList.java
new file mode 100644
index 0000000000..6ac4b0f8ba
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/ListenerList.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.events;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/** Manages a thread-safe list of {@link RepositoryListener}s. */
+public class ListenerList {
+ private final ConcurrentMap<Class<? extends RepositoryListener>, CopyOnWriteArrayList<ListenerHandle>> lists = new ConcurrentHashMap<Class<? extends RepositoryListener>, CopyOnWriteArrayList<ListenerHandle>>();
+
+ /**
+ * Register an IndexChangedListener.
+ *
+ * @param listener
+ * the listener implementation.
+ * @return handle to later remove the listener.
+ */
+ public ListenerHandle addIndexChangedListener(IndexChangedListener listener) {
+ return addListener(IndexChangedListener.class, listener);
+ }
+
+ /**
+ * Register a RefsChangedListener.
+ *
+ * @param listener
+ * the listener implementation.
+ * @return handle to later remove the listener.
+ */
+ public ListenerHandle addRefsChangedListener(RefsChangedListener listener) {
+ return addListener(RefsChangedListener.class, listener);
+ }
+
+ /**
+ * Register a ConfigChangedListener.
+ *
+ * @param listener
+ * the listener implementation.
+ * @return handle to later remove the listener.
+ */
+ public ListenerHandle addConfigChangedListener(
+ ConfigChangedListener listener) {
+ return addListener(ConfigChangedListener.class, listener);
+ }
+
+ /**
+ * Add a listener to the list.
+ *
+ * @param <T>
+ * the type of listener being registered.
+ * @param type
+ * type of listener being registered.
+ * @param listener
+ * the listener instance.
+ * @return a handle to later remove the registration, if desired.
+ */
+ public <T extends RepositoryListener> ListenerHandle addListener(
+ Class<T> type, T listener) {
+ ListenerHandle handle = new ListenerHandle(this, type, listener);
+ add(handle);
+ return handle;
+ }
+
+ /**
+ * Dispatch an event to all interested listeners.
+ * <p>
+ * Listeners are selected by the type of listener the event delivers to.
+ *
+ * @param event
+ * the event to deliver.
+ */
+ @SuppressWarnings("unchecked")
+ public void dispatch(RepositoryEvent event) {
+ List<ListenerHandle> list = lists.get(event.getListenerType());
+ if (list != null) {
+ for (ListenerHandle handle : list)
+ event.dispatch(handle.listener);
+ }
+ }
+
+ private void add(ListenerHandle handle) {
+ List<ListenerHandle> list = lists.get(handle.type);
+ if (list == null) {
+ CopyOnWriteArrayList<ListenerHandle> newList;
+
+ newList = new CopyOnWriteArrayList<ListenerHandle>();
+ list = lists.putIfAbsent(handle.type, newList);
+ if (list == null)
+ list = newList;
+ }
+ list.add(handle);
+ }
+
+ void remove(ListenerHandle handle) {
+ List<ListenerHandle> list = lists.get(handle.type);
+ if (list != null)
+ list.remove(handle);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/events/RefsChangedEvent.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/RefsChangedEvent.java
new file mode 100644
index 0000000000..36af3f8b77
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/RefsChangedEvent.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.events;
+
+/** Describes a change to one or more references of a repository. */
+public class RefsChangedEvent extends RepositoryEvent<RefsChangedListener> {
+ @Override
+ public Class<RefsChangedListener> getListenerType() {
+ return RefsChangedListener.class;
+ }
+
+ @Override
+ public void dispatch(RefsChangedListener listener) {
+ listener.onRefsChanged(this);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryChangedEvent.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/RefsChangedListener.java
index 495049ce74..9c0f4ed588 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryChangedEvent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/RefsChangedListener.java
@@ -41,30 +41,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package org.eclipse.jgit.lib;
-
-/**
- * This class passes information about changed refs to a
- * {@link RepositoryListener}
- *
- * Currently only a reference to the repository is passed.
- */
-public class RepositoryChangedEvent {
- private final Repository repository;
-
- RepositoryChangedEvent(final Repository repository) {
- this.repository = repository;
- }
+package org.eclipse.jgit.events;
+/** Receives {@link RefsChangedEvent}s. */
+public interface RefsChangedListener extends RepositoryListener {
/**
- * @return the repository that was changed
+ * Invoked when any reference changes.
+ *
+ * @param event
+ * information about the changes.
*/
- public Repository getRepository() {
- return repository;
- }
-
- @Override
- public String toString() {
- return "RepositoryChangedEvent[" + repository + "]";
- }
+ void onRefsChanged(RefsChangedEvent event);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/events/RepositoryEvent.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/RepositoryEvent.java
new file mode 100644
index 0000000000..ba1c81d5d8
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/RepositoryEvent.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.events;
+
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Describes a modification made to a repository.
+ *
+ * @param <T>
+ * type of listener this event dispatches to.
+ */
+public abstract class RepositoryEvent<T extends RepositoryListener> {
+ private Repository repository;
+
+ /**
+ * Set the repository this event occurred on.
+ * <p>
+ * This method should only be invoked once on each event object, and is
+ * automatically set by {@link Repository#fireEvent(RepositoryEvent)}.
+ *
+ * @param r
+ * the repository.
+ */
+ public void setRepository(Repository r) {
+ if (repository == null)
+ repository = r;
+ }
+
+ /** @return the repository that was changed. */
+ public Repository getRepository() {
+ return repository;
+ }
+
+ /** @return type of listener this event dispatches to. */
+ public abstract Class<T> getListenerType();
+
+ /**
+ * Dispatch this event to the given listener.
+ *
+ * @param listener
+ * listener that wants this event.
+ */
+ public abstract void dispatch(T listener);
+
+ @Override
+ public String toString() {
+ String type = getClass().getSimpleName();
+ if (repository == null)
+ return type;
+ return type + "[" + repository + "]";
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/events/RepositoryListener.java b/org.eclipse.jgit/src/org/eclipse/jgit/events/RepositoryListener.java
new file mode 100644
index 0000000000..4f951e5f87
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/events/RepositoryListener.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.events;
+
+/** A listener can register for event delivery. */
+public interface RepositoryListener {
+ // Empty marker interface; see extensions for actual methods.
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AlternateRepositoryDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AlternateRepositoryDatabase.java
deleted file mode 100644
index 40f110684e..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AlternateRepositoryDatabase.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2010, Constantine Plotnikov <constantine.plotnikov@gmail.com>
- * Copyright (C) 2009, Google Inc.
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-import java.util.Collection;
-
-/**
- * An ObjectDatabase of another {@link Repository}.
- * <p>
- * This {@code ObjectDatabase} wraps around another {@code Repository}'s object
- * database, providing its contents to the caller, and closing the Repository
- * when this database is closed. The primary user of this class is
- * {@link ObjectDirectory}, when the {@code info/alternates} file points at the
- * {@code objects/} directory of another repository.
- */
-public final class AlternateRepositoryDatabase extends ObjectDatabase {
- private final Repository repository;
-
- private final ObjectDatabase odb;
-
- /**
- * @param alt
- * the alternate repository to wrap and export.
- */
- public AlternateRepositoryDatabase(final Repository alt) {
- repository = alt;
- odb = repository.getObjectDatabase();
- }
-
- /** @return the alternate repository objects are borrowed from. */
- public Repository getRepository() {
- return repository;
- }
-
- @Override
- public void closeSelf() {
- repository.close();
- }
-
- @Override
- public void create() throws IOException {
- repository.create();
- }
-
- @Override
- public boolean exists() {
- return odb.exists();
- }
-
- @Override
- protected boolean hasObject1(final AnyObjectId objectId) {
- return odb.hasObject1(objectId);
- }
-
- @Override
- protected boolean tryAgain1() {
- return odb.tryAgain1();
- }
-
- @Override
- protected boolean hasObject2(final String objectName) {
- return odb.hasObject2(objectName);
- }
-
- @Override
- protected ObjectLoader openObject1(final WindowCursor curs,
- final AnyObjectId objectId) throws IOException {
- return odb.openObject1(curs, objectId);
- }
-
- @Override
- protected ObjectLoader openObject2(final WindowCursor curs,
- final String objectName, final AnyObjectId objectId)
- throws IOException {
- return odb.openObject2(curs, objectName, objectId);
- }
-
- @Override
- void openObjectInAllPacks1(final Collection<PackedObjectLoader> out,
- final WindowCursor curs, final AnyObjectId objectId)
- throws IOException {
- odb.openObjectInAllPacks1(out, curs, objectId);
- }
-
- @Override
- protected ObjectDatabase[] loadAlternates() throws IOException {
- return odb.getAlternates();
- }
-
- @Override
- protected void closeAlternates(final ObjectDatabase[] alt) {
- // Do nothing; these belong to odb to close, not us.
- }
-
- @Override
- public ObjectDatabase newCachedDatabase() {
- return odb.newCachedDatabase();
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
index 7d08f3d4c9..ecaa82b75a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
@@ -113,7 +113,7 @@ public abstract class AnyObjectId implements Comparable {
* @return < 0 if this id comes before other; 0 if this id is equal to
* other; > 0 if this id comes after other.
*/
- public int compareTo(final ObjectId other) {
+ public int compareTo(final AnyObjectId other) {
if (this == other)
return 0;
@@ -139,7 +139,7 @@ public abstract class AnyObjectId implements Comparable {
}
public int compareTo(final Object other) {
- return compareTo(((ObjectId) other));
+ return compareTo(((AnyObjectId) other));
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
new file mode 100644
index 0000000000..92edb0325c
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
@@ -0,0 +1,616 @@
+package org.eclipse.jgit.lib;
+
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BARE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WORKTREE;
+import static org.eclipse.jgit.lib.Constants.DOT_GIT;
+import static org.eclipse.jgit.lib.Constants.GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY;
+import static org.eclipse.jgit.lib.Constants.GIT_CEILING_DIRECTORIES_KEY;
+import static org.eclipse.jgit.lib.Constants.GIT_DIR_KEY;
+import static org.eclipse.jgit.lib.Constants.GIT_INDEX_KEY;
+import static org.eclipse.jgit.lib.Constants.GIT_OBJECT_DIRECTORY_KEY;
+import static org.eclipse.jgit.lib.Constants.GIT_WORK_TREE_KEY;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.RepositoryCache.FileKey;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.storage.file.FileRepository;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.SystemReader;
+
+/**
+ * Base builder to customize repository construction.
+ * <p>
+ * Repository implementations may subclass this builder in order to add custom
+ * repository detection methods.
+ *
+ * @param <B>
+ * type of the repository builder.
+ * @param <R>
+ * type of the repository that is constructed.
+ * @see RepositoryBuilder
+ * @see FileRepositoryBuilder
+ */
+public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Repository> {
+ private FS fs;
+
+ private File gitDir;
+
+ private File objectDirectory;
+
+ private List<File> alternateObjectDirectories;
+
+ private File indexFile;
+
+ private File workTree;
+
+ /** Directories limiting the search for a Git repository. */
+ private List<File> ceilingDirectories;
+
+ /** True only if the caller wants to force bare behavior. */
+ private boolean bare;
+
+ /** Configuration file of target repository, lazily loaded if required. */
+ private Config config;
+
+ /**
+ * Set the file system abstraction needed by this repository.
+ *
+ * @param fs
+ * the abstraction.
+ * @return {@code this} (for chaining calls).
+ */
+ public B setFS(FS fs) {
+ this.fs = fs;
+ return self();
+ }
+
+ /** @return the file system abstraction, or null if not set. */
+ public FS getFS() {
+ return fs;
+ }
+
+ /**
+ * Set the Git directory storing the repository metadata.
+ * <p>
+ * The meta directory stores the objects, references, and meta files like
+ * {@code MERGE_HEAD}, or the index file. If {@code null} the path is
+ * assumed to be {@code workTree/.git}.
+ *
+ * @param gitDir
+ * {@code GIT_DIR}, the repository meta directory.
+ * @return {@code this} (for chaining calls).
+ */
+ public B setGitDir(File gitDir) {
+ this.gitDir = gitDir;
+ this.config = null;
+ return self();
+ }
+
+ /** @return the meta data directory; null if not set. */
+ public File getGitDir() {
+ return gitDir;
+ }
+
+ /**
+ * Set the directory storing the repository's objects.
+ *
+ * @param objectDirectory
+ * {@code GIT_OBJECT_DIRECTORY}, the directory where the
+ * repository's object files are stored.
+ * @return {@code this} (for chaining calls).
+ */
+ public B setObjectDirectory(File objectDirectory) {
+ this.objectDirectory = objectDirectory;
+ return self();
+ }
+
+ /** @return the object directory; null if not set. */
+ public File getObjectDirectory() {
+ return objectDirectory;
+ }
+
+ /**
+ * Add an alternate object directory to the search list.
+ * <p>
+ * This setting handles one alternate directory at a time, and is provided
+ * to support {@code GIT_ALTERNATE_OBJECT_DIRECTORIES}.
+ *
+ * @param other
+ * another objects directory to search after the standard one.
+ * @return {@code this} (for chaining calls).
+ */
+ public B addAlternateObjectDirectory(File other) {
+ if (other != null) {
+ if (alternateObjectDirectories == null)
+ alternateObjectDirectories = new LinkedList<File>();
+ alternateObjectDirectories.add(other);
+ }
+ return self();
+ }
+
+ /**
+ * Add alternate object directories to the search list.
+ * <p>
+ * This setting handles several alternate directories at once, and is
+ * provided to support {@code GIT_ALTERNATE_OBJECT_DIRECTORIES}.
+ *
+ * @param inList
+ * other object directories to search after the standard one. The
+ * collection's contents is copied to an internal list.
+ * @return {@code this} (for chaining calls).
+ */
+ public B addAlternateObjectDirectories(Collection<File> inList) {
+ if (inList != null) {
+ for (File path : inList)
+ addAlternateObjectDirectory(path);
+ }
+ return self();
+ }
+
+ /**
+ * Add alternate object directories to the search list.
+ * <p>
+ * This setting handles several alternate directories at once, and is
+ * provided to support {@code GIT_ALTERNATE_OBJECT_DIRECTORIES}.
+ *
+ * @param inList
+ * other object directories to search after the standard one. The
+ * array's contents is copied to an internal list.
+ * @return {@code this} (for chaining calls).
+ */
+ public B addAlternateObjectDirectories(File[] inList) {
+ if (inList != null) {
+ for (File path : inList)
+ addAlternateObjectDirectory(path);
+ }
+ return self();
+ }
+
+ /** @return ordered array of alternate directories; null if non were set. */
+ public File[] getAlternateObjectDirectories() {
+ final List<File> alts = alternateObjectDirectories;
+ if (alts == null)
+ return null;
+ return alts.toArray(new File[alts.size()]);
+ }
+
+ /**
+ * Force the repository to be treated as bare (have no working directory).
+ * <p>
+ * If bare the working directory aspects of the repository won't be
+ * configured, and will not be accessible.
+ *
+ * @return {@code this} (for chaining calls).
+ */
+ public B setBare() {
+ setIndexFile(null);
+ setWorkTree(null);
+ bare = true;
+ return self();
+ }
+
+ /** @return true if this repository was forced bare by {@link #setBare()}. */
+ public boolean isBare() {
+ return bare;
+ }
+
+ /**
+ * Set the top level directory of the working files.
+ *
+ * @param workTree
+ * {@code GIT_WORK_TREE}, the working directory of the checkout.
+ * @return {@code this} (for chaining calls).
+ */
+ public B setWorkTree(File workTree) {
+ this.workTree = workTree;
+ return self();
+ }
+
+ /** @return the work tree directory, or null if not set. */
+ public File getWorkTree() {
+ return workTree;
+ }
+
+ /**
+ * Set the local index file that is caching checked out file status.
+ * <p>
+ * The location of the index file tracking the status information for each
+ * checked out file in {@code workTree}. This may be null to assume the
+ * default {@code gitDiir/index}.
+ *
+ * @param indexFile
+ * {@code GIT_INDEX_FILE}, the index file location.
+ * @return {@code this} (for chaining calls).
+ */
+ public B setIndexFile(File indexFile) {
+ this.indexFile = indexFile;
+ return self();
+ }
+
+ /** @return the index file location, or null if not set. */
+ public File getIndexFile() {
+ return indexFile;
+ }
+
+ /**
+ * Read standard Git environment variables and configure from those.
+ * <p>
+ * This method tries to read the standard Git environment variables, such as
+ * {@code GIT_DIR} and {@code GIT_WORK_TREE} to configure this builder
+ * instance. If an environment variable is set, it overrides the value
+ * already set in this builder.
+ *
+ * @return {@code this} (for chaining calls).
+ */
+ public B readEnvironment() {
+ return readEnvironment(SystemReader.getInstance());
+ }
+
+ /**
+ * Read standard Git environment variables and configure from those.
+ * <p>
+ * This method tries to read the standard Git environment variables, such as
+ * {@code GIT_DIR} and {@code GIT_WORK_TREE} to configure this builder
+ * instance. If a property is already set in the builder, the environment
+ * variable is not used.
+ *
+ * @param sr
+ * the SystemReader abstraction to access the environment.
+ * @return {@code this} (for chaining calls).
+ */
+ public B readEnvironment(SystemReader sr) {
+ if (getGitDir() == null) {
+ String val = sr.getenv(GIT_DIR_KEY);
+ if (val != null)
+ setGitDir(new File(val));
+ }
+
+ if (getObjectDirectory() == null) {
+ String val = sr.getenv(GIT_OBJECT_DIRECTORY_KEY);
+ if (val != null)
+ setObjectDirectory(new File(val));
+ }
+
+ if (getAlternateObjectDirectories() == null) {
+ String val = sr.getenv(GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY);
+ if (val != null) {
+ for (String path : val.split(File.pathSeparator))
+ addAlternateObjectDirectory(new File(path));
+ }
+ }
+
+ if (getWorkTree() == null) {
+ String val = sr.getenv(GIT_WORK_TREE_KEY);
+ if (val != null)
+ setWorkTree(new File(val));
+ }
+
+ if (getIndexFile() == null) {
+ String val = sr.getenv(GIT_INDEX_KEY);
+ if (val != null)
+ setIndexFile(new File(val));
+ }
+
+ if (ceilingDirectories == null) {
+ String val = sr.getenv(GIT_CEILING_DIRECTORIES_KEY);
+ if (val != null) {
+ for (String path : val.split(File.pathSeparator))
+ addCeilingDirectory(new File(path));
+ }
+ }
+
+ return self();
+ }
+
+ /**
+ * Add a ceiling directory to the search limit list.
+ * <p>
+ * This setting handles one ceiling directory at a time, and is provided to
+ * support {@code GIT_CEILING_DIRECTORIES}.
+ *
+ * @param root
+ * a path to stop searching at; its parent will not be searched.
+ * @return {@code this} (for chaining calls).
+ */
+ public B addCeilingDirectory(File root) {
+ if (root != null) {
+ if (ceilingDirectories == null)
+ ceilingDirectories = new LinkedList<File>();
+ ceilingDirectories.add(root);
+ }
+ return self();
+ }
+
+ /**
+ * Add ceiling directories to the search list.
+ * <p>
+ * This setting handles several ceiling directories at once, and is provided
+ * to support {@code GIT_CEILING_DIRECTORIES}.
+ *
+ * @param inList
+ * directory paths to stop searching at. The collection's
+ * contents is copied to an internal list.
+ * @return {@code this} (for chaining calls).
+ */
+ public B addCeilingDirectories(Collection<File> inList) {
+ if (inList != null) {
+ for (File path : inList)
+ addCeilingDirectory(path);
+ }
+ return self();
+ }
+
+ /**
+ * Add ceiling directories to the search list.
+ * <p>
+ * This setting handles several ceiling directories at once, and is provided
+ * to support {@code GIT_CEILING_DIRECTORIES}.
+ *
+ * @param inList
+ * directory paths to stop searching at. The array's contents is
+ * copied to an internal list.
+ * @return {@code this} (for chaining calls).
+ */
+ public B addCeilingDirectories(File[] inList) {
+ if (inList != null) {
+ for (File path : inList)
+ addCeilingDirectory(path);
+ }
+ return self();
+ }
+
+ /**
+ * Configure {@code GIT_DIR} by searching up the file system.
+ * <p>
+ * Starts from the current working directory of the JVM and scans up through
+ * the directory tree until a Git repository is found. Success can be
+ * determined by checking for {@code getGitDir() != null}.
+ * <p>
+ * The search can be limited to specific spaces of the local filesystem by
+ * {@link #addCeilingDirectory(File)}, or inheriting the list through a
+ * prior call to {@link #readEnvironment()}.
+ *
+ * @return {@code this} (for chaining calls).
+ */
+ public B findGitDir() {
+ if (getGitDir() == null)
+ findGitDir(new File("").getAbsoluteFile());
+ return self();
+ }
+
+ /**
+ * Configure {@code GIT_DIR} by searching up the file system.
+ * <p>
+ * Starts from the supplied directory path and scans up through the parent
+ * directory tree until a Git repository is found. Success can be determined
+ * by checking for {@code getGitDir() != null}.
+ * <p>
+ * The search can be limited to specific spaces of the local filesystem by
+ * {@link #addCeilingDirectory(File)}, or inheriting the list through a
+ * prior call to {@link #readEnvironment()}.
+ *
+ * @param current
+ * directory to begin searching in.
+ * @return {@code this} (for chaining calls).
+ */
+ public B findGitDir(File current) {
+ if (getGitDir() == null) {
+ FS tryFS = safeFS();
+ while (current != null) {
+ File dir = new File(current, DOT_GIT);
+ if (FileKey.isGitRepository(dir, tryFS)) {
+ setGitDir(dir);
+ break;
+ }
+
+ current = current.getParentFile();
+ if (current != null && ceilingDirectories.contains(current))
+ break;
+ }
+ }
+ return self();
+ }
+
+ /**
+ * Guess and populate all parameters not already defined.
+ * <p>
+ * If an option was not set, the setup method will try to default the option
+ * based on other options. If insufficient information is available, an
+ * exception is thrown to the caller.
+ *
+ * @return {@code this}
+ * @throws IllegalArgumentException
+ * insufficient parameters were set, or some parameters are
+ * incompatible with one another.
+ * @throws IOException
+ * the repository could not be accessed to configure the rest of
+ * the builder's parameters.
+ */
+ public B setup() throws IllegalArgumentException, IOException {
+ requireGitDirOrWorkTree();
+ setupGitDir();
+ setupWorkTree();
+ setupInternals();
+ return self();
+ }
+
+ /**
+ * Create a repository matching the configuration in this builder.
+ * <p>
+ * If an option was not set, the build method will try to default the option
+ * based on other options. If insufficient information is available, an
+ * exception is thrown to the caller.
+ *
+ * @return a repository matching this configuration.
+ * @throws IllegalArgumentException
+ * insufficient parameters were set.
+ * @throws IOException
+ * the repository could not be accessed to configure the rest of
+ * the builder's parameters.
+ */
+ @SuppressWarnings("unchecked")
+ public R build() throws IOException {
+ return (R) new FileRepository(setup());
+ }
+
+ /** Require either {@code gitDir} or {@code workTree} to be set. */
+ protected void requireGitDirOrWorkTree() {
+ if (getGitDir() == null && getWorkTree() == null)
+ throw new IllegalArgumentException(
+ JGitText.get().eitherGitDirOrWorkTreeRequired);
+ }
+
+ /**
+ * Perform standard gitDir initialization.
+ *
+ * @throws IOException
+ * the repository could not be accessed
+ */
+ protected void setupGitDir() throws IOException {
+ // No gitDir? Try to assume its under the workTree.
+ //
+ if (getGitDir() == null && getWorkTree() != null)
+ setGitDir(new File(getWorkTree(), DOT_GIT));
+ }
+
+ /**
+ * Perform standard work-tree initialization.
+ * <p>
+ * This is a method typically invoked inside of {@link #setup()}, near the
+ * end after the repository has been identified and its configuration is
+ * available for inspection.
+ *
+ * @throws IOException
+ * the repository configuration could not be read.
+ */
+ protected void setupWorkTree() throws IOException {
+ if (getFS() == null)
+ setFS(FS.DETECTED);
+
+ // If we aren't bare, we should have a work tree.
+ //
+ if (!isBare() && getWorkTree() == null)
+ setWorkTree(guessWorkTreeOrFail());
+
+ if (!isBare()) {
+ // If after guessing we're still not bare, we must have
+ // a metadata directory to hold the repository. Assume
+ // its at the work tree.
+ //
+ if (getGitDir() == null)
+ setGitDir(getWorkTree().getParentFile());
+ if (getIndexFile() == null)
+ setIndexFile(new File(getGitDir(), "index"));
+ }
+ }
+
+ /**
+ * Configure the internal implementation details of the repository.
+ *
+ * @throws IOException
+ * the repository could not be accessed
+ */
+ protected void setupInternals() throws IOException {
+ if (getObjectDirectory() == null && getGitDir() != null)
+ setObjectDirectory(safeFS().resolve(getGitDir(), "objects"));
+ }
+
+ /**
+ * Get the cached repository configuration, loading if not yet available.
+ *
+ * @return the configuration of the repository.
+ * @throws IOException
+ * the configuration is not available, or is badly formed.
+ */
+ protected Config getConfig() throws IOException {
+ if (config == null)
+ config = loadConfig();
+ return config;
+ }
+
+ /**
+ * Parse and load the repository specific configuration.
+ * <p>
+ * The default implementation reads {@code gitDir/config}, or returns an
+ * empty configuration if gitDir was not set.
+ *
+ * @return the repository's configuration.
+ * @throws IOException
+ * the configuration is not available.
+ */
+ protected Config loadConfig() throws IOException {
+ if (getGitDir() != null) {
+ // We only want the repository's configuration file, and not
+ // the user file, as these parameters must be unique to this
+ // repository and not inherited from other files.
+ //
+ File path = safeFS().resolve(getGitDir(), "config");
+ FileBasedConfig cfg = new FileBasedConfig(path);
+ try {
+ cfg.load();
+ } catch (ConfigInvalidException err) {
+ throw new IllegalArgumentException(MessageFormat.format(
+ JGitText.get().repositoryConfigFileInvalid, path
+ .getAbsolutePath(), err.getMessage()));
+ }
+ return cfg;
+ } else {
+ return new Config();
+ }
+ }
+
+ private File guessWorkTreeOrFail() throws IOException {
+ final Config cfg = getConfig();
+
+ // If set, core.worktree wins.
+ //
+ String path = cfg.getString(CONFIG_CORE_SECTION, null,
+ CONFIG_KEY_WORKTREE);
+ if (path != null)
+ return safeFS().resolve(getGitDir(), path);
+
+ // If core.bare is set, honor its value. Assume workTree is
+ // the parent directory of the repository.
+ //
+ if (cfg.getString(CONFIG_CORE_SECTION, null, CONFIG_KEY_BARE) != null) {
+ if (cfg.getBoolean(CONFIG_CORE_SECTION, CONFIG_KEY_BARE, true)) {
+ setBare();
+ return null;
+ }
+ return getGitDir().getParentFile();
+ }
+
+ if (getGitDir().getName().equals(DOT_GIT)) {
+ // No value for the "bare" flag, but gitDir is named ".git",
+ // use the parent of the directory
+ //
+ return getGitDir().getParentFile();
+ }
+
+ // We have to assume we are bare.
+ //
+ setBare();
+ return null;
+ }
+
+ /** @return the configured FS, or {@link FS#DETECTED}. */
+ protected FS safeFS() {
+ return getFS() != null ? getFS() : FS.DETECTED;
+ }
+
+ /** @return {@code this} */
+ @SuppressWarnings("unchecked")
+ protected final B self() {
+ return (B) this;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BlobBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BlobBasedConfig.java
index b05942b02c..b56966ff42 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BlobBasedConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BlobBasedConfig.java
@@ -91,10 +91,8 @@ public class BlobBasedConfig extends Config {
public BlobBasedConfig(Config base, final Repository r,
final ObjectId objectId) throws IOException, ConfigInvalidException {
super(base);
- final ObjectLoader loader = r.openBlob(objectId);
- if (loader == null)
- throw new IOException(MessageFormat.format(JGitText.get().blobNotFound, objectId));
- fromText(RawParseUtils.decode(loader.getBytes()));
+ ObjectLoader loader = r.open(objectId, Constants.OBJ_BLOB);
+ fromText(RawParseUtils.decode(loader.getCachedBytes()));
}
/**
@@ -122,10 +120,7 @@ public class BlobBasedConfig extends Config {
if (tree == null)
throw new FileNotFoundException(MessageFormat.format(JGitText.get().entryNotFoundByPath, path));
final ObjectId blobId = tree.getObjectId(0);
- final ObjectLoader loader = tree.getRepository().openBlob(blobId);
- if (loader == null)
- throw new IOException(MessageFormat.format(JGitText.get().blobNotFoundForPath
- , blobId, path));
- fromText(RawParseUtils.decode(loader.getBytes()));
+ ObjectLoader loader = r.open(blobId,Constants.OBJ_BLOB);
+ fromText(RawParseUtils.decode(loader.getCachedBytes()));
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CachedObjectDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CachedObjectDatabase.java
deleted file mode 100644
index 3dcea1636f..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CachedObjectDatabase.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2010, Constantine Plotnikov <constantine.plotnikov@gmail.com>
- * Copyright (C) 2010, JetBrains s.r.o.
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-import java.util.Collection;
-
-/**
- * {@link ObjectDatabase} wrapper providing temporary lookup caching.
- * <p>
- * The base class for {@code ObjectDatabase}s that wrap other database instances
- * and optimize querying for objects by caching some database dependent
- * information. Instances of this class (or any of its subclasses) can be
- * returned from the method {@link ObjectDatabase#newCachedDatabase()}. This
- * class can be used in scenarios where the database does not change, or when
- * changes in the database while some operation is in progress is an acceptable
- * risk.
- * <p>
- * The default implementation delegates all requests to the wrapped database.
- * The instance might be indirectly invalidated if the wrapped instance is
- * closed. Closing the delegating instance does not implies closing the wrapped
- * instance. For alternative databases, cached instances are used as well.
- */
-public class CachedObjectDatabase extends ObjectDatabase {
- /**
- * The wrapped database instance
- */
- protected final ObjectDatabase wrapped;
-
- /**
- * Create the delegating database instance
- *
- * @param wrapped
- * the wrapped object database
- */
- public CachedObjectDatabase(ObjectDatabase wrapped) {
- this.wrapped = wrapped;
- }
-
- @Override
- protected boolean hasObject1(AnyObjectId objectId) {
- return wrapped.hasObject1(objectId);
- }
-
- @Override
- protected ObjectLoader openObject1(WindowCursor curs, AnyObjectId objectId)
- throws IOException {
- return wrapped.openObject1(curs, objectId);
- }
-
- @Override
- protected boolean hasObject2(String objectName) {
- return wrapped.hasObject2(objectName);
- }
-
- @Override
- protected ObjectDatabase[] loadAlternates() throws IOException {
- ObjectDatabase[] loaded = wrapped.getAlternates();
- ObjectDatabase[] result = new ObjectDatabase[loaded.length];
- for (int i = 0; i < loaded.length; i++) {
- result[i] = loaded[i].newCachedDatabase();
- }
- return result;
- }
-
- @Override
- protected ObjectLoader openObject2(WindowCursor curs, String objectName,
- AnyObjectId objectId) throws IOException {
- return wrapped.openObject2(curs, objectName, objectId);
- }
-
- @Override
- void openObjectInAllPacks1(Collection<PackedObjectLoader> out,
- WindowCursor curs, AnyObjectId objectId) throws IOException {
- wrapped.openObjectInAllPacks1(out, curs, objectId);
- }
-
- @Override
- protected boolean tryAgain1() {
- return wrapped.tryAgain1();
- }
-
- @Override
- public ObjectDatabase newCachedDatabase() {
- // Note that "this" is not returned since subclasses might actually do something,
- // on closeSelf() (for example closing database connections or open repositories).
- // The situation might become even more tricky if we will consider alternates.
- return wrapped.newCachedDatabase();
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Commit.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Commit.java
index 66dd89120c..eeffb08e95 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Commit.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Commit.java
@@ -339,7 +339,14 @@ public class Commit implements Treeish {
public void commit() throws IOException {
if (getCommitId() != null)
throw new IllegalStateException(MessageFormat.format(JGitText.get().commitAlreadyExists, getCommitId()));
- setCommitId(new ObjectWriter(objdb).writeCommit(this));
+ ObjectInserter odi = objdb.newObjectInserter();
+ try {
+ ObjectId id = odi.insert(Constants.OBJ_COMMIT, odi.format(this));
+ odi.flush();
+ setCommitId(id);
+ } finally {
+ odi.release();
+ }
}
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
index 9080ec1398..5ad7910be8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
@@ -47,6 +47,7 @@
package org.eclipse.jgit.lib;
import static java.util.zip.Deflater.DEFAULT_COMPRESSION;
+import static org.eclipse.jgit.lib.ObjectLoader.STREAM_THRESHOLD;
import org.eclipse.jgit.lib.Config.SectionParser;
@@ -67,14 +68,21 @@ public class CoreConfig {
private final boolean logAllRefUpdates;
+ private final int streamFileThreshold;
+
private CoreConfig(final Config rc) {
compression = rc.getInt("core", "compression", DEFAULT_COMPRESSION);
packIndexVersion = rc.getInt("pack", "indexversion", 2);
logAllRefUpdates = rc.getBoolean("core", "logallrefupdates", true);
+
+ long maxMem = Runtime.getRuntime().maxMemory();
+ long sft = rc.getLong("core", null, "streamfilethreshold", STREAM_THRESHOLD);
+ sft = Math.min(sft, maxMem / 4); // don't use more than 1/4 of the heap
+ sft = Math.min(sft, Integer.MAX_VALUE); // cannot exceed array length
+ streamFileThreshold = (int) sft;
}
/**
- * @see ObjectWriter
* @return The compression level to use when storing loose objects
*/
public int getCompression() {
@@ -95,4 +103,9 @@ public class CoreConfig {
public boolean isLogAllRefUpdates() {
return logAllRefUpdates;
}
+
+ /** @return the size threshold beyond which objects must be streamed. */
+ public int getStreamFileThreshold() {
+ return streamFileThreshold;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DeltaOfsPackedObjectLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DeltaOfsPackedObjectLoader.java
deleted file mode 100644
index d0e98a2a92..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DeltaOfsPackedObjectLoader.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2009, Google Inc.
- * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-
-import org.eclipse.jgit.JGitText;
-import org.eclipse.jgit.errors.CorruptObjectException;
-
-/** Reads a deltified object which uses an offset to find its base. */
-class DeltaOfsPackedObjectLoader extends DeltaPackedObjectLoader {
- private final long deltaBase;
-
- DeltaOfsPackedObjectLoader(final PackFile pr, final long objectOffset,
- final int headerSz, final int deltaSz, final long base) {
- super(pr, objectOffset, headerSz, deltaSz);
- deltaBase = base;
- }
-
- protected PackedObjectLoader getBaseLoader(final WindowCursor curs)
- throws IOException {
- return pack.resolveBase(curs, deltaBase);
- }
-
- @Override
- public int getRawType() {
- return Constants.OBJ_OFS_DELTA;
- }
-
- @Override
- public ObjectId getDeltaBase() throws IOException {
- final ObjectId id = pack.findObjectForOffset(deltaBase);
- if (id == null)
- throw new CorruptObjectException(
- JGitText.get().offsetWrittenDeltaBaseForObjectNotFoundInAPack);
- return id;
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DeltaPackedObjectLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DeltaPackedObjectLoader.java
deleted file mode 100644
index bbc1c62a8a..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DeltaPackedObjectLoader.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2008-2009, Google Inc.
- * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-import java.text.MessageFormat;
-import java.util.zip.DataFormatException;
-
-import org.eclipse.jgit.JGitText;
-import org.eclipse.jgit.errors.CorruptObjectException;
-
-/** Reader for a deltified object stored in a pack file. */
-abstract class DeltaPackedObjectLoader extends PackedObjectLoader {
- private static final int OBJ_COMMIT = Constants.OBJ_COMMIT;
-
- private final int deltaSize;
-
- DeltaPackedObjectLoader(final PackFile pr, final long objectOffset,
- final int headerSize, final int deltaSz) {
- super(pr, objectOffset, headerSize);
- objectType = -1;
- deltaSize = deltaSz;
- }
-
- @Override
- public void materialize(final WindowCursor curs) throws IOException {
- if (cachedBytes != null) {
- return;
- }
-
- if (objectType != OBJ_COMMIT) {
- UnpackedObjectCache.Entry cache = pack.readCache(objectOffset);
- if (cache != null) {
- curs.release();
- objectType = cache.type;
- objectSize = cache.data.length;
- cachedBytes = cache.data;
- return;
- }
- }
-
- try {
- final PackedObjectLoader baseLoader = getBaseLoader(curs);
- baseLoader.materialize(curs);
- cachedBytes = BinaryDelta.apply(baseLoader.getCachedBytes(), pack
- .decompress(objectOffset + headerSize, deltaSize, curs));
- curs.release();
- objectType = baseLoader.getType();
- objectSize = cachedBytes.length;
- if (objectType != OBJ_COMMIT)
- pack.saveCache(objectOffset, cachedBytes, objectType);
- } catch (DataFormatException dfe) {
- final CorruptObjectException coe;
- coe = new CorruptObjectException(MessageFormat.format(JGitText.get().objectAtHasBadZlibStream,
- objectOffset, pack.getPackFile()));
- coe.initCause(dfe);
- throw coe;
- }
- }
-
- @Override
- public long getRawSize() {
- return deltaSize;
- }
-
- /**
- * @param curs
- * temporary thread storage during data access.
- * @return the object loader for the base object
- * @throws IOException
- */
- protected abstract PackedObjectLoader getBaseLoader(WindowCursor curs)
- throws IOException;
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileTreeEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileTreeEntry.java
index ed1b51d8d5..7990956f6b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileTreeEntry.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileTreeEntry.java
@@ -100,7 +100,7 @@ public class FileTreeEntry extends TreeEntry {
* @throws IOException
*/
public ObjectLoader openReader() throws IOException {
- return getRepository().openBlob(getId());
+ return getRepository().open(getId(), Constants.OBJ_BLOB);
}
public void accept(final TreeVisitor tv, final int flags)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java
index df4906374f..bf293d190b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java
@@ -71,6 +71,7 @@ import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.NotSupportedException;
+import org.eclipse.jgit.events.IndexChangedEvent;
import org.eclipse.jgit.util.RawParseUtils;
/**
@@ -155,7 +156,7 @@ public class GitIndex {
public void rereadIfNecessary() throws IOException {
if (cacheFile.exists() && cacheFile.lastModified() != lastCacheTime) {
read();
- db.fireIndexChanged();
+ db.fireEvent(new IndexChangedEvent());
}
}
@@ -329,7 +330,7 @@ public class GitIndex {
changed = false;
statDirty = false;
lastCacheTime = cacheFile.lastModified();
- db.fireIndexChanged();
+ db.fireEvent(new IndexChangedEvent());
} finally {
if (!lock.delete())
throw new IOException(
@@ -374,7 +375,7 @@ public class GitIndex {
// to change this for testing.
if (filemode != null)
return filemode.booleanValue();
- RepositoryConfig config = db.getConfig();
+ Config config = db.getConfig();
filemode = Boolean.valueOf(config.getBoolean("core", null, "filemode", true));
return filemode.booleanValue();
}
@@ -459,7 +460,7 @@ public class GitIndex {
uid = -1;
gid = -1;
try {
- size = (int) db.openBlob(f.getId()).getSize();
+ size = (int) db.open(f.getId(), Constants.OBJ_BLOB).getSize();
} catch (IOException e) {
e.printStackTrace();
size = -1;
@@ -899,17 +900,16 @@ public class GitIndex {
* @throws IOException
*/
public void checkoutEntry(File wd, Entry e) throws IOException {
- ObjectLoader ol = db.openBlob(e.sha1);
- byte[] bytes = ol.getBytes();
+ ObjectLoader ol = db.open(e.sha1, Constants.OBJ_BLOB);
File file = new File(wd, e.getName());
file.delete();
file.getParentFile().mkdirs();
- FileChannel channel = new FileOutputStream(file).getChannel();
- ByteBuffer buffer = ByteBuffer.wrap(bytes);
- int j = channel.write(buffer);
- if (j != bytes.length)
- throw new IOException(MessageFormat.format(JGitText.get().couldNotWriteFile, file));
- channel.close();
+ FileOutputStream dst = new FileOutputStream(file);
+ try {
+ ol.copyTo(dst);
+ } finally {
+ dst.close();
+ }
if (config_filemode() && File_hasExecute()) {
if (FileMode.EXECUTABLE_FILE.equals(e.mode)) {
if (!File_canExecute(file))
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
index 030b94214d..db0f942b07 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
@@ -95,7 +95,7 @@ public class IndexDiff {
* @throws IOException
*/
public boolean diff() throws IOException {
- final File root = index.getRepository().getWorkDir();
+ final File root = index.getRepository().getWorkTree();
new IndexTreeWalker(index, tree, root, new AbstractIndexTreeVisitor() {
public void visitEntry(TreeEntry treeEntry, Entry indexEntry, File file) {
if (treeEntry == null) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java
index 7eac79fb78..15d118c0e9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java
@@ -44,31 +44,20 @@
package org.eclipse.jgit.lib;
import java.io.IOException;
-import java.util.Collection;
-import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
/**
* Abstraction of arbitrary object storage.
* <p>
* An object database stores one or more Git objects, indexed by their unique
- * {@link ObjectId}. Optionally an object database can reference one or more
- * alternates; other ObjectDatabase instances that are searched in addition to
- * the current database.
- * <p>
- * Databases are usually divided into two halves: a half that is considered to
- * be fast to search, and a half that is considered to be slow to search. When
- * alternates are present the fast half is fully searched (recursively through
- * all alternates) before the slow half is considered.
+ * {@link ObjectId}.
*/
public abstract class ObjectDatabase {
- /** Constant indicating no alternate databases exist. */
- protected static final ObjectDatabase[] NO_ALTERNATES = {};
-
- private final AtomicReference<ObjectDatabase[]> alternates;
-
/** Initialize a new database instance for access. */
protected ObjectDatabase() {
- alternates = new AtomicReference<ObjectDatabase[]>();
+ // Protected to force extension.
}
/**
@@ -92,292 +81,101 @@ public abstract class ObjectDatabase {
}
/**
- * Close any resources held by this database and its active alternates.
- */
- public final void close() {
- closeSelf();
- closeAlternates();
- }
-
- /**
- * Close any resources held by this database only; ignoring alternates.
+ * Create a new {@code ObjectInserter} to insert new objects.
* <p>
- * To fully close this database and its referenced alternates, the caller
- * should instead invoke {@link #close()}.
+ * The returned inserter is not itself thread-safe, but multiple concurrent
+ * inserter instances created from the same {@code ObjectDatabase} must be
+ * thread-safe.
+ *
+ * @return writer the caller can use to create objects in this database.
*/
- public void closeSelf() {
- // Assume no action is required.
- }
-
- /** Fully close all loaded alternates and clear the alternate list. */
- public final void closeAlternates() {
- ObjectDatabase[] alt = alternates.get();
- if (alt != null) {
- alternates.set(null);
- closeAlternates(alt);
- }
- }
+ public abstract ObjectInserter newInserter();
/**
- * Does the requested object exist in this database?
+ * Create a new {@code ObjectReader} to read existing objects.
* <p>
- * Alternates (if present) are searched automatically.
+ * The returned reader is not itself thread-safe, but multiple concurrent
+ * reader instances created from the same {@code ObjectDatabase} must be
+ * thread-safe.
*
- * @param objectId
- * identity of the object to test for existence of.
- * @return true if the specified object is stored in this database, or any
- * of the alternate databases.
+ * @return reader the caller can use to load objects from this database.
*/
- public final boolean hasObject(final AnyObjectId objectId) {
- return hasObjectImpl1(objectId) || hasObjectImpl2(objectId.name());
- }
-
- private final boolean hasObjectImpl1(final AnyObjectId objectId) {
- if (hasObject1(objectId)) {
- return true;
- }
- for (final ObjectDatabase alt : getAlternates()) {
- if (alt.hasObjectImpl1(objectId)) {
- return true;
- }
- }
- return tryAgain1() && hasObject1(objectId);
- }
-
- private final boolean hasObjectImpl2(final String objectId) {
- if (hasObject2(objectId)) {
- return true;
- }
- for (final ObjectDatabase alt : getAlternates()) {
- if (alt.hasObjectImpl2(objectId)) {
- return true;
- }
- }
- return false;
- }
+ public abstract ObjectReader newReader();
/**
- * Fast half of {@link #hasObject(AnyObjectId)}.
- *
- * @param objectId
- * identity of the object to test for existence of.
- * @return true if the specified object is stored in this database.
+ * Close any resources held by this database.
*/
- protected abstract boolean hasObject1(AnyObjectId objectId);
+ public abstract void close();
/**
- * Slow half of {@link #hasObject(AnyObjectId)}.
+ * Does the requested object exist in this database?
+ * <p>
+ * This is a one-shot call interface which may be faster than allocating a
+ * {@link #newReader()} to perform the lookup.
*
- * @param objectName
+ * @param objectId
* identity of the object to test for existence of.
* @return true if the specified object is stored in this database.
- */
- protected boolean hasObject2(String objectName) {
- // Assume the search took place during hasObject1.
- return false;
+ * @throws IOException
+ * the object store cannot be accessed.
+ */
+ public boolean has(final AnyObjectId objectId) throws IOException {
+ final ObjectReader or = newReader();
+ try {
+ return or.has(objectId);
+ } finally {
+ or.release();
+ }
}
/**
* Open an object from this database.
* <p>
- * Alternates (if present) are searched automatically.
+ * This is a one-shot call interface which may be faster than allocating a
+ * {@link #newReader()} to perform the lookup.
*
- * @param curs
- * temporary working space associated with the calling thread.
* @param objectId
* identity of the object to open.
- * @return a {@link ObjectLoader} for accessing the data of the named
- * object, or null if the object does not exist.
+ * @return a {@link ObjectLoader} for accessing the object.
+ * @throws MissingObjectException
+ * the object does not exist.
* @throws IOException
+ * the object store cannot be accessed.
*/
- public final ObjectLoader openObject(final WindowCursor curs,
- final AnyObjectId objectId) throws IOException {
- ObjectLoader ldr;
-
- ldr = openObjectImpl1(curs, objectId);
- if (ldr != null) {
- return ldr;
- }
-
- ldr = openObjectImpl2(curs, objectId.name(), objectId);
- if (ldr != null) {
- return ldr;
- }
- return null;
- }
-
- private ObjectLoader openObjectImpl1(final WindowCursor curs,
- final AnyObjectId objectId) throws IOException {
- ObjectLoader ldr;
-
- ldr = openObject1(curs, objectId);
- if (ldr != null) {
- return ldr;
- }
- for (final ObjectDatabase alt : getAlternates()) {
- ldr = alt.openObjectImpl1(curs, objectId);
- if (ldr != null) {
- return ldr;
- }
- }
- if (tryAgain1()) {
- ldr = openObject1(curs, objectId);
- if (ldr != null) {
- return ldr;
- }
- }
- return null;
- }
-
- private ObjectLoader openObjectImpl2(final WindowCursor curs,
- final String objectName, final AnyObjectId objectId)
+ public ObjectLoader open(final AnyObjectId objectId)
throws IOException {
- ObjectLoader ldr;
-
- ldr = openObject2(curs, objectName, objectId);
- if (ldr != null) {
- return ldr;
- }
- for (final ObjectDatabase alt : getAlternates()) {
- ldr = alt.openObjectImpl2(curs, objectName, objectId);
- if (ldr != null) {
- return ldr;
- }
- }
- return null;
+ return open(objectId, ObjectReader.OBJ_ANY);
}
/**
- * Fast half of {@link #openObject(WindowCursor, AnyObjectId)}.
- *
- * @param curs
- * temporary working space associated with the calling thread.
- * @param objectId
- * identity of the object to open.
- * @return a {@link ObjectLoader} for accessing the data of the named
- * object, or null if the object does not exist.
- * @throws IOException
- */
- protected abstract ObjectLoader openObject1(WindowCursor curs,
- AnyObjectId objectId) throws IOException;
-
- /**
- * Slow half of {@link #openObject(WindowCursor, AnyObjectId)}.
- *
- * @param curs
- * temporary working space associated with the calling thread.
- * @param objectName
- * name of the object to open.
- * @param objectId
- * identity of the object to open.
- * @return a {@link ObjectLoader} for accessing the data of the named
- * object, or null if the object does not exist.
- * @throws IOException
- */
- protected ObjectLoader openObject2(WindowCursor curs, String objectName,
- AnyObjectId objectId) throws IOException {
- // Assume the search took place during openObject1.
- return null;
- }
-
- /**
- * Open the object from all packs containing it.
+ * Open an object from this database.
* <p>
- * If any alternates are present, their packs are also considered.
- *
- * @param out
- * result collection of loaders for this object, filled with
- * loaders from all packs containing specified object
- * @param curs
- * temporary working space associated with the calling thread.
- * @param objectId
- * id of object to search for
- * @throws IOException
- */
- final void openObjectInAllPacks(final Collection<PackedObjectLoader> out,
- final WindowCursor curs, final AnyObjectId objectId)
- throws IOException {
- openObjectInAllPacks1(out, curs, objectId);
- for (final ObjectDatabase alt : getAlternates()) {
- alt.openObjectInAllPacks1(out, curs, objectId);
- }
- }
-
- /**
- * Open the object from all packs containing it.
+ * This is a one-shot call interface which may be faster than allocating a
+ * {@link #newReader()} to perform the lookup.
*
- * @param out
- * result collection of loaders for this object, filled with
- * loaders from all packs containing specified object
- * @param curs
- * temporary working space associated with the calling thread.
* @param objectId
- * id of object to search for
- * @throws IOException
- */
- void openObjectInAllPacks1(Collection<PackedObjectLoader> out,
- WindowCursor curs, AnyObjectId objectId) throws IOException {
- // Assume no pack support
- }
-
- /**
- * @return true if the fast-half search should be tried again.
- */
- protected boolean tryAgain1() {
- return false;
- }
-
- /**
- * Get the alternate databases known to this database.
- *
- * @return the alternate list. Never null, but may be an empty array.
- */
- public final ObjectDatabase[] getAlternates() {
- ObjectDatabase[] r = alternates.get();
- if (r == null) {
- synchronized (alternates) {
- r = alternates.get();
- if (r == null) {
- try {
- r = loadAlternates();
- } catch (IOException e) {
- r = NO_ALTERNATES;
- }
- alternates.set(r);
- }
- }
- }
- return r;
- }
-
- /**
- * Load the list of alternate databases into memory.
- * <p>
- * This method is invoked by {@link #getAlternates()} if the alternate list
- * has not yet been populated, or if {@link #closeAlternates()} has been
- * called on this instance and the alternate list is needed again.
- * <p>
- * If the alternate array is empty, implementors should consider using the
- * constant {@link #NO_ALTERNATES}.
- *
- * @return the alternate list for this database.
+ * identity of the object to open.
+ * @param typeHint
+ * hint about the type of object being requested;
+ * {@link ObjectReader#OBJ_ANY} if the object type is not known,
+ * or does not matter to the caller.
+ * @return a {@link ObjectLoader} for accessing the object.
+ * @throws MissingObjectException
+ * the object does not exist.
+ * @throws IncorrectObjectTypeException
+ * typeHint was not OBJ_ANY, and the object's actual type does
+ * not match typeHint.
* @throws IOException
- * the alternate list could not be accessed. The empty alternate
- * array {@link #NO_ALTERNATES} will be assumed by the caller.
- */
- protected ObjectDatabase[] loadAlternates() throws IOException {
- return NO_ALTERNATES;
- }
-
- /**
- * Close the list of alternates returned by {@link #loadAlternates()}.
- *
- * @param alt
- * the alternate list, from {@link #loadAlternates()}.
- */
- protected void closeAlternates(ObjectDatabase[] alt) {
- for (final ObjectDatabase d : alt) {
- d.close();
+ * the object store cannot be accessed.
+ */
+ public ObjectLoader open(AnyObjectId objectId, int typeHint)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException {
+ final ObjectReader or = newReader();
+ try {
+ return or.open(objectId, typeHint);
+ } finally {
+ or.release();
}
}
@@ -387,9 +185,8 @@ public abstract class ObjectDatabase {
* done after instance creation might fail to be noticed.
*
* @return new cached database instance
- * @see CachedObjectDatabase
*/
public ObjectDatabase newCachedDatabase() {
- return new CachedObjectDatabase(this);
+ return this;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java
new file mode 100644
index 0000000000..fd99d39e78
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2009, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.lib;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.errors.ObjectWritingException;
+
+/**
+ * Inserts objects into an existing {@code ObjectDatabase}.
+ * <p>
+ * An inserter is not thread-safe. Individual threads should each obtain their
+ * own unique inserter instance, or must arrange for locking at a higher level
+ * to ensure the inserter is in use by no more than one thread at a time.
+ * <p>
+ * Objects written by an inserter may not be immediately visible for reading
+ * after the insert method completes. Callers must invoke either
+ * {@link #release()} or {@link #flush()} prior to updating references or
+ * otherwise making the returned ObjectIds visible to other code.
+ */
+public abstract class ObjectInserter {
+ private static final byte[] htree = Constants.encodeASCII("tree");
+
+ private static final byte[] hparent = Constants.encodeASCII("parent");
+
+ private static final byte[] hauthor = Constants.encodeASCII("author");
+
+ private static final byte[] hcommitter = Constants.encodeASCII("committer");
+
+ private static final byte[] hencoding = Constants.encodeASCII("encoding");
+
+ /** An inserter that can be used for formatting and id generation only. */
+ public static class Formatter extends ObjectInserter {
+ @Override
+ public ObjectId insert(int objectType, long length, InputStream in)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ // Do nothing.
+ }
+
+ @Override
+ public void release() {
+ // Do nothing.
+ }
+ }
+
+ /** Digest to compute the name of an object. */
+ private final MessageDigest digest;
+
+ /** Temporary working buffer for streaming data through. */
+ private byte[] tempBuffer;
+
+ /** Create a new inserter for a database. */
+ protected ObjectInserter() {
+ digest = Constants.newMessageDigest();
+ }
+
+ /** @return a temporary byte array for use by the caller. */
+ protected byte[] buffer() {
+ if (tempBuffer == null)
+ tempBuffer = new byte[8192];
+ return tempBuffer;
+ }
+
+ /** @return digest to help compute an ObjectId */
+ protected MessageDigest digest() {
+ digest.reset();
+ return digest;
+ }
+
+ /**
+ * Compute the name of an object, without inserting it.
+ *
+ * @param type
+ * type code of the object to store.
+ * @param data
+ * complete content of the object.
+ * @return the name of the object.
+ */
+ public ObjectId idFor(int type, byte[] data) {
+ return idFor(type, data, 0, data.length);
+ }
+
+ /**
+ * Compute the name of an object, without inserting it.
+ *
+ * @param type
+ * type code of the object to store.
+ * @param data
+ * complete content of the object.
+ * @param off
+ * first position within {@code data}.
+ * @param len
+ * number of bytes to copy from {@code data}.
+ * @return the name of the object.
+ */
+ public ObjectId idFor(int type, byte[] data, int off, int len) {
+ MessageDigest md = digest();
+ md.update(Constants.encodedTypeString(type));
+ md.update((byte) ' ');
+ md.update(Constants.encodeASCII(len));
+ md.update((byte) 0);
+ md.update(data, off, len);
+ return ObjectId.fromRaw(md.digest());
+ }
+
+ /**
+ * Compute the name of an object, without inserting it.
+ *
+ * @param objectType
+ * type code of the object to store.
+ * @param length
+ * number of bytes to scan from {@code in}.
+ * @param in
+ * stream providing the object content. The caller is responsible
+ * for closing the stream.
+ * @return the name of the object.
+ * @throws IOException
+ * the source stream could not be read.
+ */
+ public ObjectId idFor(int objectType, long length, InputStream in)
+ throws IOException {
+ MessageDigest md = digest();
+ md.update(Constants.encodedTypeString(objectType));
+ md.update((byte) ' ');
+ md.update(Constants.encodeASCII(length));
+ md.update((byte) 0);
+ byte[] buf = buffer();
+ while (length > 0) {
+ int n = in.read(buf, 0, (int) Math.min(length, buf.length));
+ if (n < 0)
+ throw new EOFException("Unexpected end of input");
+ md.update(buf, 0, n);
+ length -= n;
+ }
+ return ObjectId.fromRaw(md.digest());
+ }
+
+ /**
+ * Insert a single object into the store, returning its unique name.
+ *
+ * @param type
+ * type code of the object to store.
+ * @param data
+ * complete content of the object.
+ * @return the name of the object.
+ * @throws IOException
+ * the object could not be stored.
+ */
+ public ObjectId insert(final int type, final byte[] data)
+ throws IOException {
+ return insert(type, data, 0, data.length);
+ }
+
+ /**
+ * Insert a single object into the store, returning its unique name.
+ *
+ * @param type
+ * type code of the object to store.
+ * @param data
+ * complete content of the object.
+ * @param off
+ * first position within {@code data}.
+ * @param len
+ * number of bytes to copy from {@code data}.
+ * @return the name of the object.
+ * @throws IOException
+ * the object could not be stored.
+ */
+ public ObjectId insert(int type, byte[] data, int off, int len)
+ throws IOException {
+ return insert(type, len, new ByteArrayInputStream(data, off, len));
+ }
+
+ /**
+ * Insert a single object into the store, returning its unique name.
+ *
+ * @param objectType
+ * type code of the object to store.
+ * @param length
+ * number of bytes to copy from {@code in}.
+ * @param in
+ * stream providing the object content. The caller is responsible
+ * for closing the stream.
+ * @return the name of the object.
+ * @throws IOException
+ * the object could not be stored, or the source stream could
+ * not be read.
+ */
+ public abstract ObjectId insert(int objectType, long length, InputStream in)
+ throws IOException;
+
+ /**
+ * Make all inserted objects visible.
+ * <p>
+ * The flush may take some period of time to make the objects available to
+ * other threads.
+ *
+ * @throws IOException
+ * the flush could not be completed; objects inserted thus far
+ * are in an indeterminate state.
+ */
+ public abstract void flush() throws IOException;
+
+ /**
+ * Release any resources used by this inserter.
+ * <p>
+ * An inserter that has been released can be used again, but may need to be
+ * released after the subsequent usage.
+ */
+ public abstract void release();
+
+ /**
+ * Format a Tree in canonical format.
+ *
+ * @param tree
+ * the tree object to format
+ * @return canonical encoding of the tree object.
+ * @throws IOException
+ * the tree cannot be loaded, or its not in a writable state.
+ */
+ public final byte[] format(Tree tree) throws IOException {
+ ByteArrayOutputStream o = new ByteArrayOutputStream();
+ for (TreeEntry e : tree.members()) {
+ ObjectId id = e.getId();
+ if (id == null)
+ throw new ObjectWritingException(MessageFormat.format(JGitText
+ .get().objectAtPathDoesNotHaveId, e.getFullName()));
+
+ e.getMode().copyTo(o);
+ o.write(' ');
+ o.write(e.getNameUTF8());
+ o.write(0);
+ id.copyRawTo(o);
+ }
+ return o.toByteArray();
+ }
+
+ /**
+ * Format a Commit in canonical format.
+ *
+ * @param commit
+ * the commit object to format
+ * @return canonical encoding of the commit object.
+ * @throws UnsupportedEncodingException
+ * the commit's chosen encoding isn't supported on this JVM.
+ */
+ public final byte[] format(Commit commit)
+ throws UnsupportedEncodingException {
+ String encoding = commit.getEncoding();
+ if (encoding == null)
+ encoding = Constants.CHARACTER_ENCODING;
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ OutputStreamWriter w = new OutputStreamWriter(os, encoding);
+ try {
+ os.write(htree);
+ os.write(' ');
+ commit.getTreeId().copyTo(os);
+ os.write('\n');
+
+ ObjectId[] ps = commit.getParentIds();
+ for (int i = 0; i < ps.length; ++i) {
+ os.write(hparent);
+ os.write(' ');
+ ps[i].copyTo(os);
+ os.write('\n');
+ }
+
+ os.write(hauthor);
+ os.write(' ');
+ w.write(commit.getAuthor().toExternalString());
+ w.flush();
+ os.write('\n');
+
+ os.write(hcommitter);
+ os.write(' ');
+ w.write(commit.getCommitter().toExternalString());
+ w.flush();
+ os.write('\n');
+
+ if (!encoding.equals(Constants.CHARACTER_ENCODING)) {
+ os.write(hencoding);
+ os.write(' ');
+ os.write(Constants.encodeASCII(encoding));
+ os.write('\n');
+ }
+
+ os.write('\n');
+ w.write(commit.getMessage());
+ w.flush();
+ } catch (IOException err) {
+ // This should never occur, the only way to get it above is
+ // for the ByteArrayOutputStream to throw, but it doesn't.
+ //
+ throw new RuntimeException(err);
+ }
+ return os.toByteArray();
+ }
+
+ /**
+ * Format a Tag in canonical format.
+ *
+ * @param tag
+ * the tag object to format
+ * @return canonical encoding of the tag object.
+ */
+ public final byte[] format(Tag tag) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ OutputStreamWriter w = new OutputStreamWriter(os, Constants.CHARSET);
+ try {
+ w.write("object ");
+ tag.getObjId().copyTo(w);
+ w.write('\n');
+
+ w.write("type ");
+ w.write(tag.getType());
+ w.write("\n");
+
+ w.write("tag ");
+ w.write(tag.getTag());
+ w.write("\n");
+
+ w.write("tagger ");
+ w.write(tag.getAuthor().toExternalString());
+ w.write('\n');
+
+ w.write('\n');
+ w.write(tag.getMessage());
+ w.close();
+ } catch (IOException err) {
+ // This should never occur, the only way to get it above is
+ // for the ByteArrayOutputStream to throw, but it doesn't.
+ //
+ throw new RuntimeException(err);
+ }
+ return os.toByteArray();
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java
index 4839a1c28b..e19bfc4fba 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java
@@ -47,6 +47,12 @@
package org.eclipse.jgit.lib;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.eclipse.jgit.errors.LargeObjectException;
+import org.eclipse.jgit.errors.MissingObjectException;
/**
* Base class for a set of loaders for different representations of Git objects.
@@ -54,6 +60,14 @@ package org.eclipse.jgit.lib;
*/
public abstract class ObjectLoader {
/**
+ * Default setting for the large object threshold.
+ * <p>
+ * Objects larger than this size must be accessed as a stream through the
+ * loader's {@link #openStream()} method.
+ */
+ public static final int STREAM_THRESHOLD = 1024 * 1024;
+
+ /**
* @return Git in pack object type, see {@link Constants}.
*/
public abstract int getType();
@@ -64,14 +78,32 @@ public abstract class ObjectLoader {
public abstract long getSize();
/**
+ * @return true if this object is too large to obtain as a byte array.
+ * Objects over a certain threshold should be accessed only by their
+ * {@link #openStream()} to prevent overflowing the JVM heap.
+ */
+ public boolean isLarge() {
+ try {
+ getCachedBytes();
+ return false;
+ } catch (LargeObjectException tooBig) {
+ return true;
+ }
+ }
+
+ /**
* Obtain a copy of the bytes of this object.
* <p>
* Unlike {@link #getCachedBytes()} this method returns an array that might
* be modified by the caller.
*
* @return the bytes of this object.
+ * @throws LargeObjectException
+ * if the object won't fit into a byte array, because
+ * {@link #isLarge()} returns true. Callers should use
+ * {@link #openStream()} instead to access the contents.
*/
- public final byte[] getBytes() {
+ public final byte[] getBytes() throws LargeObjectException {
final byte[] data = getCachedBytes();
final byte[] copy = new byte[data.length];
System.arraycopy(data, 0, copy, 0, data.length);
@@ -87,19 +119,120 @@ public abstract class ObjectLoader {
* Changes (if made) will affect the cache but not the repository itself.
*
* @return the cached bytes of this object. Do not modify it.
+ * @throws LargeObjectException
+ * if the object won't fit into a byte array, because
+ * {@link #isLarge()} returns true. Callers should use
+ * {@link #openStream()} instead to access the contents.
+ */
+ public abstract byte[] getCachedBytes() throws LargeObjectException;
+
+ /**
+ * Obtain an input stream to read this object's data.
+ *
+ * @return a stream of this object's data. Caller must close the stream when
+ * through with it. The returned stream is buffered with a
+ * reasonable buffer size.
+ * @throws MissingObjectException
+ * the object no longer exists.
+ * @throws IOException
+ * the object store cannot be accessed.
*/
- public abstract byte[] getCachedBytes();
+ public abstract ObjectStream openStream() throws MissingObjectException,
+ IOException;
/**
- * @return raw object type from object header, as stored in storage (pack,
- * loose file). This may be different from {@link #getType()} result
- * for packs (see {@link Constants}).
+ * Copy this object to the output stream.
+ * <p>
+ * For some object store implementations, this method may be more efficient
+ * than reading from {@link #openStream()} into a temporary byte array, then
+ * writing to the destination stream.
+ * <p>
+ * The default implementation of this method is to copy with a temporary
+ * byte array for large objects, or to pass through the cached byte array
+ * for small objects.
+ *
+ * @param out
+ * stream to receive the complete copy of this object's data.
+ * Caller is responsible for flushing or closing this stream
+ * after this method returns.
+ * @throws MissingObjectException
+ * the object no longer exists.
+ * @throws IOException
+ * the object store cannot be accessed, or the stream cannot be
+ * written to.
*/
- public abstract int getRawType();
+ public void copyTo(OutputStream out) throws MissingObjectException,
+ IOException {
+ if (isLarge()) {
+ ObjectStream in = openStream();
+ try {
+ byte[] tmp = new byte[1024];
+ long copied = 0;
+ for (;;) {
+ int n = in.read(tmp);
+ if (n < 0)
+ break;
+ out.write(tmp, 0, n);
+ copied += n;
+ }
+ if (copied != getSize())
+ throw new EOFException();
+ } finally {
+ in.close();
+ }
+ } else {
+ out.write(getCachedBytes());
+ }
+ }
/**
- * @return raw size of object from object header (pack, loose file).
- * Interpretation of this value depends on {@link #getRawType()}.
+ * Simple loader around the cached byte array.
+ * <p>
+ * ObjectReader implementations can use this stream type when the object's
+ * content is small enough to be accessed as a single byte array.
*/
- public abstract long getRawSize();
+ public static class SmallObject extends ObjectLoader {
+ private final int type;
+
+ private final byte[] data;
+
+ /**
+ * Construct a small object loader.
+ *
+ * @param type
+ * type of the object.
+ * @param data
+ * the object's data array. This array will be returned as-is
+ * for the {@link #getCachedBytes()} method.
+ */
+ public SmallObject(int type, byte[] data) {
+ this.type = type;
+ this.data = data;
+ }
+
+ @Override
+ public int getType() {
+ return type;
+ }
+
+ @Override
+ public long getSize() {
+ return getCachedBytes().length;
+ }
+
+ @Override
+ public boolean isLarge() {
+ return false;
+ }
+
+ @Override
+ public byte[] getCachedBytes() {
+ return data;
+ }
+
+ @Override
+ public ObjectStream openStream() {
+ return new ObjectStream.SmallStream(this);
+ }
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java
new file mode 100644
index 0000000000..ae70638672
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.lib;
+
+import java.io.IOException;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.storage.pack.ObjectReuseAsIs;
+
+/**
+ * Reads an {@link ObjectDatabase} for a single thread.
+ * <p>
+ * Readers that can support efficient reuse of pack encoded objects should also
+ * implement the companion interface {@link ObjectReuseAsIs}.
+ */
+public abstract class ObjectReader {
+ /** Type hint indicating the caller doesn't know the type. */
+ protected static final int OBJ_ANY = -1;
+
+ /**
+ * Construct a new reader from the same data.
+ * <p>
+ * Applications can use this method to build a new reader from the same data
+ * source, but for an different thread.
+ *
+ * @return a brand new reader, using the same data source.
+ */
+ public abstract ObjectReader newReader();
+
+ /**
+ * Does the requested object exist in this database?
+ *
+ * @param objectId
+ * identity of the object to test for existence of.
+ * @return true if the specified object is stored in this database.
+ * @throws IOException
+ * the object store cannot be accessed.
+ */
+ public boolean has(AnyObjectId objectId) throws IOException {
+ return has(objectId, OBJ_ANY);
+ }
+
+ /**
+ * Does the requested object exist in this database?
+ *
+ * @param objectId
+ * identity of the object to test for existence of.
+ * @param typeHint
+ * hint about the type of object being requested;
+ * {@link #OBJ_ANY} if the object type is not known, or does not
+ * matter to the caller.
+ * @return true if the specified object is stored in this database.
+ * @throws IncorrectObjectTypeException
+ * typeHint was not OBJ_ANY, and the object's actual type does
+ * not match typeHint.
+ * @throws IOException
+ * the object store cannot be accessed.
+ */
+ public boolean has(AnyObjectId objectId, int typeHint) throws IOException {
+ try {
+ open(objectId, typeHint);
+ return true;
+ } catch (MissingObjectException notFound) {
+ return false;
+ }
+ }
+
+ /**
+ * Open an object from this database.
+ *
+ * @param objectId
+ * identity of the object to open.
+ * @return a {@link ObjectLoader} for accessing the object.
+ * @throws MissingObjectException
+ * the object does not exist.
+ * @throws IOException
+ * the object store cannot be accessed.
+ */
+ public ObjectLoader open(AnyObjectId objectId)
+ throws MissingObjectException, IOException {
+ return open(objectId, OBJ_ANY);
+ }
+
+ /**
+ * Open an object from this database.
+ *
+ * @param objectId
+ * identity of the object to open.
+ * @param typeHint
+ * hint about the type of object being requested;
+ * {@link #OBJ_ANY} if the object type is not known, or does not
+ * matter to the caller.
+ * @return a {@link ObjectLoader} for accessing the object.
+ * @throws MissingObjectException
+ * the object does not exist.
+ * @throws IncorrectObjectTypeException
+ * typeHint was not OBJ_ANY, and the object's actual type does
+ * not match typeHint.
+ * @throws IOException
+ * the object store cannot be accessed.
+ */
+ public abstract ObjectLoader open(AnyObjectId objectId, int typeHint)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException;
+
+ /**
+ * Get only the size of an object.
+ * <p>
+ * The default implementation of this method opens an ObjectLoader.
+ * Databases are encouraged to override this if a faster access method is
+ * available to them.
+ *
+ * @param objectId
+ * identity of the object to open.
+ * @param typeHint
+ * hint about the type of object being requested;
+ * {@link #OBJ_ANY} if the object type is not known, or does not
+ * matter to the caller.
+ * @return size of object in bytes.
+ * @throws MissingObjectException
+ * the object does not exist.
+ * @throws IncorrectObjectTypeException
+ * typeHint was not OBJ_ANY, and the object's actual type does
+ * not match typeHint.
+ * @throws IOException
+ * the object store cannot be accessed.
+ */
+ public long getObjectSize(AnyObjectId objectId, int typeHint)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException {
+ return open(objectId, typeHint).getSize();
+ }
+
+ /**
+ * Release any resources used by this reader.
+ * <p>
+ * A reader that has been released can be used again, but may need to be
+ * released after the subsequent usage.
+ */
+ public void release() {
+ // Do nothing.
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectStream.java
new file mode 100644
index 0000000000..86d66439d0
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectStream.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.lib;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/** Stream of data coming from an object loaded by {@link ObjectLoader}. */
+public abstract class ObjectStream extends InputStream {
+ /** @return Git object type, see {@link Constants}. */
+ public abstract int getType();
+
+ /** @return total size of object in bytes */
+ public abstract long getSize();
+
+ /**
+ * Simple stream around the cached byte array created by a loader.
+ * <p>
+ * ObjectLoader implementations can use this stream type when the object's
+ * content is small enough to be accessed as a single byte array, but the
+ * application has still requested it in stream format.
+ */
+ public static class SmallStream extends ObjectStream {
+ private final int type;
+
+ private final byte[] data;
+
+ private int ptr;
+
+ private int mark;
+
+ /**
+ * Create the stream from an existing loader's cached bytes.
+ *
+ * @param loader
+ * the loader.
+ */
+ public SmallStream(ObjectLoader loader) {
+ this.type = loader.getType();
+ this.data = loader.getCachedBytes();
+ }
+
+ @Override
+ public int getType() {
+ return type;
+ }
+
+ @Override
+ public long getSize() {
+ return data.length;
+ }
+
+ @Override
+ public int available() {
+ return data.length - ptr;
+ }
+
+ @Override
+ public long skip(long n) {
+ int s = (int) Math.min(available(), Math.max(0, n));
+ ptr += s;
+ return s;
+ }
+
+ @Override
+ public int read() {
+ if (ptr == data.length)
+ return -1;
+ return data[ptr++] & 0xff;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) {
+ if (ptr == data.length)
+ return -1;
+ int n = Math.min(available(), len);
+ System.arraycopy(data, ptr, b, off, n);
+ ptr += n;
+ return n;
+ }
+
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ @Override
+ public void mark(int readlimit) {
+ mark = ptr;
+ }
+
+ @Override
+ public void reset() {
+ ptr = mark;
+ }
+ }
+
+ /**
+ * Simple filter stream around another stream.
+ * <p>
+ * ObjectLoader implementations can use this stream type when the object's
+ * content is available from a standard InputStream.
+ */
+ public static class Filter extends ObjectStream {
+ private final int type;
+
+ private final long size;
+
+ private final InputStream in;
+
+ /**
+ * Create a filter stream for an object.
+ *
+ * @param type
+ * the type of the object.
+ * @param size
+ * total size of the object, in bytes.
+ * @param in
+ * stream the object's raw data is available from. This
+ * stream should be buffered with some reasonable amount of
+ * buffering.
+ */
+ public Filter(int type, long size, InputStream in) {
+ this.type = type;
+ this.size = size;
+ this.in = in;
+ }
+
+ @Override
+ public int getType() {
+ return type;
+ }
+
+ @Override
+ public long getSize() {
+ return size;
+ }
+
+ @Override
+ public int available() throws IOException {
+ return in.available();
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ return in.skip(n);
+ }
+
+ @Override
+ public int read() throws IOException {
+ return in.read();
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return in.read(b, off, len);
+ }
+
+ @Override
+ public boolean markSupported() {
+ return in.markSupported();
+ }
+
+ @Override
+ public void mark(int readlimit) {
+ in.mark(readlimit);
+ }
+
+ @Override
+ public void reset() throws IOException {
+ in.reset();
+ }
+
+ @Override
+ public void close() throws IOException {
+ in.close();
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectWriter.java
index 20147ed6ce..ce91efb8e4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectWriter.java
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2009, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@@ -44,61 +45,49 @@
package org.eclipse.jgit.lib;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
+import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
+import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
+
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.security.MessageDigest;
-import java.text.MessageFormat;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-
-import org.eclipse.jgit.JGitText;
-import org.eclipse.jgit.errors.ObjectWritingException;
/**
* A class for writing loose objects.
+ *
+ * @deprecated Use {@link Repository#newObjectInserter()}.
*/
public class ObjectWriter {
- private static final byte[] htree = Constants.encodeASCII("tree");
-
- private static final byte[] hparent = Constants.encodeASCII("parent");
-
- private static final byte[] hauthor = Constants.encodeASCII("author");
-
- private static final byte[] hcommitter = Constants.encodeASCII("committer");
-
- private static final byte[] hencoding = Constants.encodeASCII("encoding");
-
- private final Repository r;
-
- private final byte[] buf;
-
- private final MessageDigest md;
+ private final ObjectInserter inserter;
/**
* Construct an Object writer for the specified repository
+ *
* @param d
*/
public ObjectWriter(final Repository d) {
- r = d;
- buf = new byte[8192];
- md = Constants.newMessageDigest();
+ inserter = d.newObjectInserter();
}
/**
* Write a blob with the specified data
*
- * @param b bytes of the blob
+ * @param b
+ * bytes of the blob
* @return SHA-1 of the blob
* @throws IOException
*/
public ObjectId writeBlob(final byte[] b) throws IOException {
- return writeBlob(b.length, new ByteArrayInputStream(b));
+ try {
+ ObjectId id = inserter.insert(OBJ_BLOB, b);
+ inserter.flush();
+ return id;
+ } finally {
+ inserter.release();
+ }
}
/**
@@ -130,174 +119,101 @@ public class ObjectWriter {
*/
public ObjectId writeBlob(final long len, final InputStream is)
throws IOException {
- return writeObject(Constants.OBJ_BLOB, len, is, true);
+ try {
+ ObjectId id = inserter.insert(OBJ_BLOB, len, is);
+ inserter.flush();
+ return id;
+ } finally {
+ inserter.release();
+ }
}
/**
* Write a Tree to the object database.
*
- * @param t
+ * @param tree
* Tree
* @return SHA-1 of the tree
* @throws IOException
*/
- public ObjectId writeTree(final Tree t) throws IOException {
- final ByteArrayOutputStream o = new ByteArrayOutputStream();
- final TreeEntry[] items = t.members();
- for (int k = 0; k < items.length; k++) {
- final TreeEntry e = items[k];
- final ObjectId id = e.getId();
-
- if (id == null)
- throw new ObjectWritingException(MessageFormat.format(
- JGitText.get().objectAtPathDoesNotHaveId, e.getFullName()));
-
- e.getMode().copyTo(o);
- o.write(' ');
- o.write(e.getNameUTF8());
- o.write(0);
- id.copyRawTo(o);
+ public ObjectId writeTree(Tree tree) throws IOException {
+ try {
+ ObjectId id = inserter.insert(OBJ_TREE, inserter.format(tree));
+ inserter.flush();
+ return id;
+ } finally {
+ inserter.release();
}
- return writeCanonicalTree(o.toByteArray());
}
/**
* Write a canonical tree to the object database.
*
- * @param b
+ * @param treeData
* the canonical encoding of the tree object.
* @return SHA-1 of the tree
* @throws IOException
*/
- public ObjectId writeCanonicalTree(final byte[] b) throws IOException {
- return writeTree(b.length, new ByteArrayInputStream(b));
- }
-
- private ObjectId writeTree(final long len, final InputStream is)
- throws IOException {
- return writeObject(Constants.OBJ_TREE, len, is, true);
+ public ObjectId writeCanonicalTree(byte[] treeData) throws IOException {
+ try {
+ ObjectId id = inserter.insert(OBJ_TREE, treeData);
+ inserter.flush();
+ return id;
+ } finally {
+ inserter.release();
+ }
}
/**
* Write a Commit to the object database
*
- * @param c
+ * @param commit
* Commit to store
* @return SHA-1 of the commit
* @throws IOException
*/
- public ObjectId writeCommit(final Commit c) throws IOException {
- final ByteArrayOutputStream os = new ByteArrayOutputStream();
- String encoding = c.getEncoding();
- if (encoding == null)
- encoding = Constants.CHARACTER_ENCODING;
- final OutputStreamWriter w = new OutputStreamWriter(os, encoding);
-
- os.write(htree);
- os.write(' ');
- c.getTreeId().copyTo(os);
- os.write('\n');
-
- ObjectId[] ps = c.getParentIds();
- for (int i=0; i<ps.length; ++i) {
- os.write(hparent);
- os.write(' ');
- ps[i].copyTo(os);
- os.write('\n');
- }
-
- os.write(hauthor);
- os.write(' ');
- w.write(c.getAuthor().toExternalString());
- w.flush();
- os.write('\n');
-
- os.write(hcommitter);
- os.write(' ');
- w.write(c.getCommitter().toExternalString());
- w.flush();
- os.write('\n');
-
- if (!encoding.equals(Constants.CHARACTER_ENCODING)) {
- os.write(hencoding);
- os.write(' ');
- os.write(Constants.encodeASCII(encoding));
- os.write('\n');
+ public ObjectId writeCommit(Commit commit) throws IOException {
+ try {
+ ObjectId id = inserter.insert(OBJ_COMMIT, inserter.format(commit));
+ inserter.flush();
+ return id;
+ } finally {
+ inserter.release();
}
-
- os.write('\n');
- w.write(c.getMessage());
- w.flush();
-
- return writeCommit(os.toByteArray());
- }
-
- private ObjectId writeTag(final byte[] b) throws IOException {
- return writeTag(b.length, new ByteArrayInputStream(b));
}
/**
* Write an annotated Tag to the object database
*
- * @param c
+ * @param tag
* Tag
* @return SHA-1 of the tag
* @throws IOException
*/
- public ObjectId writeTag(final Tag c) throws IOException {
- final ByteArrayOutputStream os = new ByteArrayOutputStream();
- final OutputStreamWriter w = new OutputStreamWriter(os,
- Constants.CHARSET);
-
- w.write("object ");
- c.getObjId().copyTo(w);
- w.write('\n');
-
- w.write("type ");
- w.write(c.getType());
- w.write("\n");
-
- w.write("tag ");
- w.write(c.getTag());
- w.write("\n");
-
- w.write("tagger ");
- w.write(c.getAuthor().toExternalString());
- w.write('\n');
-
- w.write('\n');
- w.write(c.getMessage());
- w.close();
-
- return writeTag(os.toByteArray());
- }
-
- private ObjectId writeCommit(final byte[] b) throws IOException {
- return writeCommit(b.length, new ByteArrayInputStream(b));
- }
-
- private ObjectId writeCommit(final long len, final InputStream is)
- throws IOException {
- return writeObject(Constants.OBJ_COMMIT, len, is, true);
- }
-
- private ObjectId writeTag(final long len, final InputStream is)
- throws IOException {
- return writeObject(Constants.OBJ_TAG, len, is, true);
+ public ObjectId writeTag(Tag tag) throws IOException {
+ try {
+ ObjectId id = inserter.insert(OBJ_TAG, inserter.format(tag));
+ inserter.flush();
+ return id;
+ } finally {
+ inserter.release();
+ }
}
/**
* Compute the SHA-1 of a blob without creating an object. This is for
* figuring out if we already have a blob or not.
*
- * @param len number of bytes to consume
- * @param is stream for read blob data from
+ * @param len
+ * number of bytes to consume
+ * @param is
+ * stream for read blob data from
* @return SHA-1 of a looked for blob
* @throws IOException
*/
- public ObjectId computeBlobSha1(final long len, final InputStream is)
+ public ObjectId computeBlobSha1(long len, InputStream is)
throws IOException {
- return writeObject(Constants.OBJ_BLOB, len, is, false);
+ return computeObjectSha1(OBJ_BLOB, len, is);
}
/**
@@ -313,119 +229,12 @@ public class ObjectWriter {
* @return SHA-1 of data combined with type information
* @throws IOException
*/
- public ObjectId computeObjectSha1(final int type, final long len, final InputStream is)
+ public ObjectId computeObjectSha1(int type, long len, InputStream is)
throws IOException {
- return writeObject(type, len, is, false);
- }
-
- ObjectId writeObject(final int type, long len, final InputStream is,
- boolean store) throws IOException {
- final File t;
- final DeflaterOutputStream deflateStream;
- final FileOutputStream fileStream;
- ObjectId id = null;
- Deflater def = null;
-
- if (store) {
- t = File.createTempFile("noz", null, r.getObjectsDirectory());
- fileStream = new FileOutputStream(t);
- } else {
- t = null;
- fileStream = null;
- }
-
- md.reset();
- if (store) {
- def = new Deflater(r.getConfig().getCore().getCompression());
- deflateStream = new DeflaterOutputStream(fileStream, def);
- } else
- deflateStream = null;
-
try {
- byte[] header;
- int n;
-
- header = Constants.encodedTypeString(type);
- md.update(header);
- if (deflateStream != null)
- deflateStream.write(header);
-
- md.update((byte) ' ');
- if (deflateStream != null)
- deflateStream.write((byte) ' ');
-
- header = Constants.encodeASCII(len);
- md.update(header);
- if (deflateStream != null)
- deflateStream.write(header);
-
- md.update((byte) 0);
- if (deflateStream != null)
- deflateStream.write((byte) 0);
-
- while (len > 0
- && (n = is.read(buf, 0, (int) Math.min(len, buf.length))) > 0) {
- md.update(buf, 0, n);
- if (deflateStream != null)
- deflateStream.write(buf, 0, n);
- len -= n;
- }
-
- if (len != 0)
- throw new IOException("Input did not match supplied length. "
- + len + " bytes are missing.");
-
- if (deflateStream != null ) {
- deflateStream.close();
- if (t != null)
- t.setReadOnly();
- }
-
- id = ObjectId.fromRaw(md.digest());
+ return inserter.idFor(type, len, is);
} finally {
- if (id == null && deflateStream != null) {
- try {
- deflateStream.close();
- } finally {
- t.delete();
- }
- }
- if (def != null) {
- def.end();
- }
+ inserter.release();
}
-
- if (t == null)
- return id;
-
- if (r.hasObject(id)) {
- // Object is already in the repository so remove
- // the temporary file.
- //
- t.delete();
- } else {
- final File o = r.toFile(id);
- if (!t.renameTo(o)) {
- // Maybe the directory doesn't exist yet as the object
- // directories are always lazily created. Note that we
- // try the rename first as the directory likely does exist.
- //
- o.getParentFile().mkdir();
- if (!t.renameTo(o)) {
- if (!r.hasObject(id)) {
- // The object failed to be renamed into its proper
- // location and it doesn't exist in the repository
- // either. We really don't know what went wrong, so
- // fail.
- //
- t.delete();
- throw new ObjectWritingException("Unable to"
- + " create new object: " + o);
- }
- }
- }
- }
-
- return id;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java
deleted file mode 100644
index 829832e6a5..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * Copyright (C) 2008-2009, Google Inc.
- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.EOFException;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel.MapMode;
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.zip.CRC32;
-import java.util.zip.CheckedOutputStream;
-import java.util.zip.DataFormatException;
-
-import org.eclipse.jgit.JGitText;
-import org.eclipse.jgit.errors.CorruptObjectException;
-import org.eclipse.jgit.errors.PackInvalidException;
-import org.eclipse.jgit.errors.PackMismatchException;
-import org.eclipse.jgit.util.NB;
-import org.eclipse.jgit.util.RawParseUtils;
-
-/**
- * A Git version 2 pack file representation. A pack file contains Git objects in
- * delta packed format yielding high compression of lots of object where some
- * objects are similar.
- */
-public class PackFile implements Iterable<PackIndex.MutableEntry> {
- /** Sorts PackFiles to be most recently created to least recently created. */
- public static Comparator<PackFile> SORT = new Comparator<PackFile>() {
- public int compare(final PackFile a, final PackFile b) {
- return b.packLastModified - a.packLastModified;
- }
- };
-
- private final File idxFile;
-
- private final File packFile;
-
- final int hash;
-
- private RandomAccessFile fd;
-
- /** Serializes reads performed against {@link #fd}. */
- private final Object readLock = new Object();
-
- long length;
-
- private int activeWindows;
-
- private int activeCopyRawData;
-
- private int packLastModified;
-
- private volatile boolean invalid;
-
- private byte[] packChecksum;
-
- private PackIndex loadedIdx;
-
- private PackReverseIndex reverseIdx;
-
- /**
- * Construct a reader for an existing, pre-indexed packfile.
- *
- * @param idxFile
- * path of the <code>.idx</code> file listing the contents.
- * @param packFile
- * path of the <code>.pack</code> file holding the data.
- */
- public PackFile(final File idxFile, final File packFile) {
- this.idxFile = idxFile;
- this.packFile = packFile;
- this.packLastModified = (int) (packFile.lastModified() >> 10);
-
- // Multiply by 31 here so we can more directly combine with another
- // value in WindowCache.hash(), without doing the multiply there.
- //
- hash = System.identityHashCode(this) * 31;
- length = Long.MAX_VALUE;
- }
-
- private synchronized PackIndex idx() throws IOException {
- if (loadedIdx == null) {
- if (invalid)
- throw new PackInvalidException(packFile);
-
- try {
- final PackIndex idx = PackIndex.open(idxFile);
-
- if (packChecksum == null)
- packChecksum = idx.packChecksum;
- else if (!Arrays.equals(packChecksum, idx.packChecksum))
- throw new PackMismatchException(JGitText.get().packChecksumMismatch);
-
- loadedIdx = idx;
- } catch (IOException e) {
- invalid = true;
- throw e;
- }
- }
- return loadedIdx;
- }
-
- final PackedObjectLoader resolveBase(final WindowCursor curs, final long ofs)
- throws IOException {
- return reader(curs, ofs);
- }
-
- /** @return the File object which locates this pack on disk. */
- public File getPackFile() {
- return packFile;
- }
-
- /**
- * Determine if an object is contained within the pack file.
- * <p>
- * For performance reasons only the index file is searched; the main pack
- * content is ignored entirely.
- * </p>
- *
- * @param id
- * the object to look for. Must not be null.
- * @return true if the object is in this pack; false otherwise.
- * @throws IOException
- * the index file cannot be loaded into memory.
- */
- public boolean hasObject(final AnyObjectId id) throws IOException {
- return idx().hasObject(id);
- }
-
- /**
- * Get an object from this pack.
- *
- * @param curs
- * temporary working space associated with the calling thread.
- * @param id
- * the object to obtain from the pack. Must not be null.
- * @return the object loader for the requested object if it is contained in
- * this pack; null if the object was not found.
- * @throws IOException
- * the pack file or the index could not be read.
- */
- public PackedObjectLoader get(final WindowCursor curs, final AnyObjectId id)
- throws IOException {
- final long offset = idx().findOffset(id);
- return 0 < offset ? reader(curs, offset) : null;
- }
-
- /**
- * Close the resources utilized by this repository
- */
- public void close() {
- UnpackedObjectCache.purge(this);
- WindowCache.purge(this);
- synchronized (this) {
- loadedIdx = null;
- reverseIdx = null;
- }
- }
-
- /**
- * Provide iterator over entries in associated pack index, that should also
- * exist in this pack file. Objects returned by such iterator are mutable
- * during iteration.
- * <p>
- * Iterator returns objects in SHA-1 lexicographical order.
- * </p>
- *
- * @return iterator over entries of associated pack index
- *
- * @see PackIndex#iterator()
- */
- public Iterator<PackIndex.MutableEntry> iterator() {
- try {
- return idx().iterator();
- } catch (IOException e) {
- return Collections.<PackIndex.MutableEntry> emptyList().iterator();
- }
- }
-
- /**
- * Obtain the total number of objects available in this pack. This method
- * relies on pack index, giving number of effectively available objects.
- *
- * @return number of objects in index of this pack, likewise in this pack
- * @throws IOException
- * the index file cannot be loaded into memory.
- */
- long getObjectCount() throws IOException {
- return idx().getObjectCount();
- }
-
- /**
- * Search for object id with the specified start offset in associated pack
- * (reverse) index.
- *
- * @param offset
- * start offset of object to find
- * @return object id for this offset, or null if no object was found
- * @throws IOException
- * the index file cannot be loaded into memory.
- */
- ObjectId findObjectForOffset(final long offset) throws IOException {
- return getReverseIdx().findObject(offset);
- }
-
- final UnpackedObjectCache.Entry readCache(final long position) {
- return UnpackedObjectCache.get(this, position);
- }
-
- final void saveCache(final long position, final byte[] data, final int type) {
- UnpackedObjectCache.store(this, position, data, type);
- }
-
- final byte[] decompress(final long position, final int totalSize,
- final WindowCursor curs) throws DataFormatException, IOException {
- final byte[] dstbuf = new byte[totalSize];
- if (curs.inflate(this, position, dstbuf, 0) != totalSize)
- throw new EOFException(MessageFormat.format(JGitText.get().shortCompressedStreamAt, position));
- return dstbuf;
- }
-
- final void copyRawData(final PackedObjectLoader loader,
- final OutputStream out, final byte buf[], final WindowCursor curs)
- throws IOException {
- final long objectOffset = loader.objectOffset;
- final long dataOffset = objectOffset + loader.headerSize;
- final long sz = findEndOffset(objectOffset) - dataOffset;
- final PackIndex idx = idx();
-
- if (idx.hasCRC32Support()) {
- final CRC32 crc = new CRC32();
- int headerCnt = loader.headerSize;
- while (headerCnt > 0) {
- final int toRead = Math.min(headerCnt, buf.length);
- readFully(objectOffset, buf, 0, toRead, curs);
- crc.update(buf, 0, toRead);
- headerCnt -= toRead;
- }
- final CheckedOutputStream crcOut = new CheckedOutputStream(out, crc);
- copyToStream(dataOffset, buf, sz, crcOut, curs);
- final long computed = crc.getValue();
-
- final ObjectId id = findObjectForOffset(objectOffset);
- final long expected = idx.findCRC32(id);
- if (computed != expected)
- throw new CorruptObjectException(MessageFormat.format(
- JGitText.get().objectAtHasBadZlibStream, objectOffset, getPackFile()));
- } else {
- try {
- curs.inflateVerify(this, dataOffset);
- } catch (DataFormatException dfe) {
- final CorruptObjectException coe;
- coe = new CorruptObjectException(MessageFormat.format(
- JGitText.get().objectAtHasBadZlibStream, objectOffset, getPackFile()));
- coe.initCause(dfe);
- throw coe;
- }
- copyToStream(dataOffset, buf, sz, out, curs);
- }
- }
-
- boolean supportsFastCopyRawData() throws IOException {
- return idx().hasCRC32Support();
- }
-
- boolean invalid() {
- return invalid;
- }
-
- private void readFully(final long position, final byte[] dstbuf,
- int dstoff, final int cnt, final WindowCursor curs)
- throws IOException {
- if (curs.copy(this, position, dstbuf, dstoff, cnt) != cnt)
- throw new EOFException();
- }
-
- private void copyToStream(long position, final byte[] buf, long cnt,
- final OutputStream out, final WindowCursor curs)
- throws IOException, EOFException {
- while (cnt > 0) {
- final int toRead = (int) Math.min(cnt, buf.length);
- readFully(position, buf, 0, toRead, curs);
- position += toRead;
- cnt -= toRead;
- out.write(buf, 0, toRead);
- }
- }
-
- synchronized void beginCopyRawData() throws IOException {
- if (++activeCopyRawData == 1 && activeWindows == 0)
- doOpen();
- }
-
- synchronized void endCopyRawData() {
- if (--activeCopyRawData == 0 && activeWindows == 0)
- doClose();
- }
-
- synchronized boolean beginWindowCache() throws IOException {
- if (++activeWindows == 1) {
- if (activeCopyRawData == 0)
- doOpen();
- return true;
- }
- return false;
- }
-
- synchronized boolean endWindowCache() {
- final boolean r = --activeWindows == 0;
- if (r && activeCopyRawData == 0)
- doClose();
- return r;
- }
-
- private void doOpen() throws IOException {
- try {
- if (invalid)
- throw new PackInvalidException(packFile);
- synchronized (readLock) {
- fd = new RandomAccessFile(packFile, "r");
- length = fd.length();
- onOpenPack();
- }
- } catch (IOException ioe) {
- openFail();
- throw ioe;
- } catch (RuntimeException re) {
- openFail();
- throw re;
- } catch (Error re) {
- openFail();
- throw re;
- }
- }
-
- private void openFail() {
- activeWindows = 0;
- activeCopyRawData = 0;
- invalid = true;
- doClose();
- }
-
- private void doClose() {
- synchronized (readLock) {
- if (fd != null) {
- try {
- fd.close();
- } catch (IOException err) {
- // Ignore a close event. We had it open only for reading.
- // There should not be errors related to network buffers
- // not flushed, etc.
- }
- fd = null;
- }
- }
- }
-
- ByteArrayWindow read(final long pos, int size) throws IOException {
- synchronized (readLock) {
- if (length < pos + size)
- size = (int) (length - pos);
- final byte[] buf = new byte[size];
- fd.seek(pos);
- fd.readFully(buf, 0, size);
- return new ByteArrayWindow(this, pos, buf);
- }
- }
-
- ByteWindow mmap(final long pos, int size) throws IOException {
- synchronized (readLock) {
- if (length < pos + size)
- size = (int) (length - pos);
-
- MappedByteBuffer map;
- try {
- map = fd.getChannel().map(MapMode.READ_ONLY, pos, size);
- } catch (IOException ioe1) {
- // The most likely reason this failed is the JVM has run out
- // of virtual memory. We need to discard quickly, and try to
- // force the GC to finalize and release any existing mappings.
- //
- System.gc();
- System.runFinalization();
- map = fd.getChannel().map(MapMode.READ_ONLY, pos, size);
- }
-
- if (map.hasArray())
- return new ByteArrayWindow(this, pos, map.array());
- return new ByteBufferWindow(this, pos, map);
- }
- }
-
- private void onOpenPack() throws IOException {
- final PackIndex idx = idx();
- final byte[] buf = new byte[20];
-
- fd.seek(0);
- fd.readFully(buf, 0, 12);
- if (RawParseUtils.match(buf, 0, Constants.PACK_SIGNATURE) != 4)
- throw new IOException(JGitText.get().notAPACKFile);
- final long vers = NB.decodeUInt32(buf, 4);
- final long packCnt = NB.decodeUInt32(buf, 8);
- if (vers != 2 && vers != 3)
- throw new IOException(MessageFormat.format(JGitText.get().unsupportedPackVersion, vers));
-
- if (packCnt != idx.getObjectCount())
- throw new PackMismatchException(MessageFormat.format(
- JGitText.get().packObjectCountMismatch, packCnt, idx.getObjectCount(), getPackFile()));
-
- fd.seek(length - 20);
- fd.read(buf, 0, 20);
- if (!Arrays.equals(buf, packChecksum))
- throw new PackMismatchException(MessageFormat.format(
- JGitText.get().packObjectCountMismatch
- , ObjectId.fromRaw(buf).name()
- , ObjectId.fromRaw(idx.packChecksum).name()
- , getPackFile()));
- }
-
- private PackedObjectLoader reader(final WindowCursor curs,
- final long objOffset) throws IOException {
- int p = 0;
- final byte[] ib = curs.tempId;
- readFully(objOffset, ib, 0, 20, curs);
- int c = ib[p++] & 0xff;
- final int typeCode = (c >> 4) & 7;
- long dataSize = c & 15;
- int shift = 4;
- while ((c & 0x80) != 0) {
- c = ib[p++] & 0xff;
- dataSize += (c & 0x7f) << shift;
- shift += 7;
- }
-
- switch (typeCode) {
- case Constants.OBJ_COMMIT:
- case Constants.OBJ_TREE:
- case Constants.OBJ_BLOB:
- case Constants.OBJ_TAG:
- return new WholePackedObjectLoader(this, objOffset, p, typeCode,
- (int) dataSize);
-
- case Constants.OBJ_OFS_DELTA: {
- c = ib[p++] & 0xff;
- long ofs = c & 127;
- while ((c & 128) != 0) {
- ofs += 1;
- c = ib[p++] & 0xff;
- ofs <<= 7;
- ofs += (c & 127);
- }
- return new DeltaOfsPackedObjectLoader(this, objOffset, p,
- (int) dataSize, objOffset - ofs);
- }
- case Constants.OBJ_REF_DELTA: {
- readFully(objOffset + p, ib, 0, 20, curs);
- return new DeltaRefPackedObjectLoader(this, objOffset, p + 20,
- (int) dataSize, ObjectId.fromRaw(ib));
- }
- default:
- throw new IOException(MessageFormat.format(JGitText.get().unknownObjectType, typeCode));
- }
- }
-
- private long findEndOffset(final long startOffset)
- throws IOException, CorruptObjectException {
- final long maxOffset = length - 20;
- return getReverseIdx().findNextOffset(startOffset, maxOffset);
- }
-
- private synchronized PackReverseIndex getReverseIdx() throws IOException {
- if (reverseIdx == null)
- reverseIdx = new PackReverseIndex(idx());
- return reverseIdx;
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java
deleted file mode 100644
index 48f41a5586..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java
+++ /dev/null
@@ -1,1040 +0,0 @@
-/*
- * Copyright (C) 2008-2010, Google Inc.
- * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.security.MessageDigest;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.zip.Deflater;
-
-import org.eclipse.jgit.JGitText;
-import org.eclipse.jgit.errors.IncorrectObjectTypeException;
-import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.revwalk.ObjectWalk;
-import org.eclipse.jgit.revwalk.RevFlag;
-import org.eclipse.jgit.revwalk.RevObject;
-import org.eclipse.jgit.revwalk.RevSort;
-import org.eclipse.jgit.transport.PackedObjectInfo;
-import org.eclipse.jgit.util.NB;
-
-/**
- * <p>
- * PackWriter class is responsible for generating pack files from specified set
- * of objects from repository. This implementation produce pack files in format
- * version 2.
- * </p>
- * <p>
- * Source of objects may be specified in two ways:
- * <ul>
- * <li>(usually) by providing sets of interesting and uninteresting objects in
- * repository - all interesting objects and their ancestors except uninteresting
- * objects and their ancestors will be included in pack, or</li>
- * <li>by providing iterator of {@link RevObject} specifying exact list and
- * order of objects in pack</li>
- * </ul>
- * Typical usage consists of creating instance intended for some pack,
- * configuring options, preparing the list of objects by calling
- * {@link #preparePack(Iterator)} or
- * {@link #preparePack(Collection, Collection)}, and finally
- * producing the stream with {@link #writePack(OutputStream)}.
- * </p>
- * <p>
- * Class provide set of configurable options and {@link ProgressMonitor}
- * support, as operations may take a long time for big repositories. Deltas
- * searching algorithm is <b>NOT IMPLEMENTED</b> yet - this implementation
- * relies only on deltas and objects reuse.
- * </p>
- * <p>
- * This class is not thread safe, it is intended to be used in one thread, with
- * one instance per created pack. Subsequent calls to writePack result in
- * undefined behavior.
- * </p>
- */
-public class PackWriter {
- /**
- * Title of {@link ProgressMonitor} task used during counting objects to
- * pack.
- *
- * @see #preparePack(Collection, Collection)
- */
- public static final String COUNTING_OBJECTS_PROGRESS = JGitText.get().countingObjects;
-
- /**
- * Title of {@link ProgressMonitor} task used during searching for objects
- * reuse or delta reuse.
- *
- * @see #writePack(OutputStream)
- */
- public static final String SEARCHING_REUSE_PROGRESS = JGitText.get().compressingObjects;
-
- /**
- * Title of {@link ProgressMonitor} task used during writing out pack
- * (objects)
- *
- * @see #writePack(OutputStream)
- */
- public static final String WRITING_OBJECTS_PROGRESS = JGitText.get().writingObjects;
-
- /**
- * Default value of deltas reuse option.
- *
- * @see #setReuseDeltas(boolean)
- */
- public static final boolean DEFAULT_REUSE_DELTAS = true;
-
- /**
- * Default value of objects reuse option.
- *
- * @see #setReuseObjects(boolean)
- */
- public static final boolean DEFAULT_REUSE_OBJECTS = true;
-
- /**
- * Default value of delta base as offset option.
- *
- * @see #setDeltaBaseAsOffset(boolean)
- */
- public static final boolean DEFAULT_DELTA_BASE_AS_OFFSET = false;
-
- /**
- * Default value of maximum delta chain depth.
- *
- * @see #setMaxDeltaDepth(int)
- */
- public static final int DEFAULT_MAX_DELTA_DEPTH = 50;
-
- private static final int PACK_VERSION_GENERATED = 2;
-
- @SuppressWarnings("unchecked")
- private final List<ObjectToPack> objectsLists[] = new List[Constants.OBJ_TAG + 1];
- {
- objectsLists[0] = Collections.<ObjectToPack> emptyList();
- objectsLists[Constants.OBJ_COMMIT] = new ArrayList<ObjectToPack>();
- objectsLists[Constants.OBJ_TREE] = new ArrayList<ObjectToPack>();
- objectsLists[Constants.OBJ_BLOB] = new ArrayList<ObjectToPack>();
- objectsLists[Constants.OBJ_TAG] = new ArrayList<ObjectToPack>();
- }
-
- private final ObjectIdSubclassMap<ObjectToPack> objectsMap = new ObjectIdSubclassMap<ObjectToPack>();
-
- // edge objects for thin packs
- private final ObjectIdSubclassMap<ObjectId> edgeObjects = new ObjectIdSubclassMap<ObjectId>();
-
- private final Repository db;
-
- private PackOutputStream out;
-
- private final Deflater deflater;
-
- private ProgressMonitor initMonitor;
-
- private ProgressMonitor writeMonitor;
-
- private final byte[] buf = new byte[16384]; // 16 KB
-
- private final WindowCursor windowCursor = new WindowCursor();
-
- private List<ObjectToPack> sortedByName;
-
- private byte packcsum[];
-
- private boolean reuseDeltas = DEFAULT_REUSE_DELTAS;
-
- private boolean reuseObjects = DEFAULT_REUSE_OBJECTS;
-
- private boolean deltaBaseAsOffset = DEFAULT_DELTA_BASE_AS_OFFSET;
-
- private int maxDeltaDepth = DEFAULT_MAX_DELTA_DEPTH;
-
- private int outputVersion;
-
- private boolean thin;
-
- private boolean ignoreMissingUninteresting = true;
-
- /**
- * Create writer for specified repository.
- * <p>
- * Objects for packing are specified in {@link #preparePack(Iterator)} or
- * {@link #preparePack(Collection, Collection)}.
- *
- * @param repo
- * repository where objects are stored.
- * @param monitor
- * operations progress monitor, used within
- * {@link #preparePack(Iterator)},
- * {@link #preparePack(Collection, Collection)}
- * , or {@link #writePack(OutputStream)}.
- */
- public PackWriter(final Repository repo, final ProgressMonitor monitor) {
- this(repo, monitor, monitor);
- }
-
- /**
- * Create writer for specified repository.
- * <p>
- * Objects for packing are specified in {@link #preparePack(Iterator)} or
- * {@link #preparePack(Collection, Collection)}.
- *
- * @param repo
- * repository where objects are stored.
- * @param imonitor
- * operations progress monitor, used within
- * {@link #preparePack(Iterator)},
- * {@link #preparePack(Collection, Collection)}
- * @param wmonitor
- * operations progress monitor, used within
- * {@link #writePack(OutputStream)}.
- */
- public PackWriter(final Repository repo, final ProgressMonitor imonitor,
- final ProgressMonitor wmonitor) {
- this.db = repo;
- initMonitor = imonitor == null ? NullProgressMonitor.INSTANCE : imonitor;
- writeMonitor = wmonitor == null ? NullProgressMonitor.INSTANCE : wmonitor;
- this.deflater = new Deflater(db.getConfig().getCore().getCompression());
- outputVersion = repo.getConfig().getCore().getPackIndexVersion();
- }
-
- /**
- * Check whether object is configured to reuse deltas existing in
- * repository.
- * <p>
- * Default setting: {@value #DEFAULT_REUSE_DELTAS}
- * </p>
- *
- * @return true if object is configured to reuse deltas; false otherwise.
- */
- public boolean isReuseDeltas() {
- return reuseDeltas;
- }
-
- /**
- * Set reuse deltas configuration option for this writer. When enabled,
- * writer will search for delta representation of object in repository and
- * use it if possible. Normally, only deltas with base to another object
- * existing in set of objects to pack will be used. Exception is however
- * thin-pack (see
- * {@link #preparePack(Collection, Collection)} and
- * {@link #preparePack(Iterator)}) where base object must exist on other
- * side machine.
- * <p>
- * When raw delta data is directly copied from a pack file, checksum is
- * computed to verify data.
- * </p>
- * <p>
- * Default setting: {@value #DEFAULT_REUSE_DELTAS}
- * </p>
- *
- * @param reuseDeltas
- * boolean indicating whether or not try to reuse deltas.
- */
- public void setReuseDeltas(boolean reuseDeltas) {
- this.reuseDeltas = reuseDeltas;
- }
-
- /**
- * Checks whether object is configured to reuse existing objects
- * representation in repository.
- * <p>
- * Default setting: {@value #DEFAULT_REUSE_OBJECTS}
- * </p>
- *
- * @return true if writer is configured to reuse objects representation from
- * pack; false otherwise.
- */
- public boolean isReuseObjects() {
- return reuseObjects;
- }
-
- /**
- * Set reuse objects configuration option for this writer. If enabled,
- * writer searches for representation in a pack file. If possible,
- * compressed data is directly copied from such a pack file. Data checksum
- * is verified.
- * <p>
- * Default setting: {@value #DEFAULT_REUSE_OBJECTS}
- * </p>
- *
- * @param reuseObjects
- * boolean indicating whether or not writer should reuse existing
- * objects representation.
- */
- public void setReuseObjects(boolean reuseObjects) {
- this.reuseObjects = reuseObjects;
- }
-
- /**
- * Check whether writer can store delta base as an offset (new style
- * reducing pack size) or should store it as an object id (legacy style,
- * compatible with old readers).
- * <p>
- * Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
- * </p>
- *
- * @return true if delta base is stored as an offset; false if it is stored
- * as an object id.
- */
- public boolean isDeltaBaseAsOffset() {
- return deltaBaseAsOffset;
- }
-
- /**
- * Set writer delta base format. Delta base can be written as an offset in a
- * pack file (new approach reducing file size) or as an object id (legacy
- * approach, compatible with old readers).
- * <p>
- * Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
- * </p>
- *
- * @param deltaBaseAsOffset
- * boolean indicating whether delta base can be stored as an
- * offset.
- */
- public void setDeltaBaseAsOffset(boolean deltaBaseAsOffset) {
- this.deltaBaseAsOffset = deltaBaseAsOffset;
- }
-
- /**
- * Get maximum depth of delta chain set up for this writer. Generated chains
- * are not longer than this value.
- * <p>
- * Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
- * </p>
- *
- * @return maximum delta chain depth.
- */
- public int getMaxDeltaDepth() {
- return maxDeltaDepth;
- }
-
- /**
- * Set up maximum depth of delta chain for this writer. Generated chains are
- * not longer than this value. Too low value causes low compression level,
- * while too big makes unpacking (reading) longer.
- * <p>
- * Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
- * </p>
- *
- * @param maxDeltaDepth
- * maximum delta chain depth.
- */
- public void setMaxDeltaDepth(int maxDeltaDepth) {
- this.maxDeltaDepth = maxDeltaDepth;
- }
-
- /** @return true if this writer is producing a thin pack. */
- public boolean isThin() {
- return thin;
- }
-
- /**
- * @param packthin
- * a boolean indicating whether writer may pack objects with
- * delta base object not within set of objects to pack, but
- * belonging to party repository (uninteresting/boundary) as
- * determined by set; this kind of pack is used only for
- * transport; true - to produce thin pack, false - otherwise.
- */
- public void setThin(final boolean packthin) {
- thin = packthin;
- }
-
- /**
- * @return true to ignore objects that are uninteresting and also not found
- * on local disk; false to throw a {@link MissingObjectException}
- * out of {@link #preparePack(Collection, Collection)} if an
- * uninteresting object is not in the source repository. By default,
- * true, permitting gracefully ignoring of uninteresting objects.
- */
- public boolean isIgnoreMissingUninteresting() {
- return ignoreMissingUninteresting;
- }
-
- /**
- * @param ignore
- * true if writer should ignore non existing uninteresting
- * objects during construction set of objects to pack; false
- * otherwise - non existing uninteresting objects may cause
- * {@link MissingObjectException}
- */
- public void setIgnoreMissingUninteresting(final boolean ignore) {
- ignoreMissingUninteresting = ignore;
- }
-
- /**
- * Set the pack index file format version this instance will create.
- *
- * @param version
- * the version to write. The special version 0 designates the
- * oldest (most compatible) format available for the objects.
- * @see PackIndexWriter
- */
- public void setIndexVersion(final int version) {
- outputVersion = version;
- }
-
- /**
- * Returns objects number in a pack file that was created by this writer.
- *
- * @return number of objects in pack.
- */
- public int getObjectsNumber() {
- return objectsMap.size();
- }
-
- /**
- * Prepare the list of objects to be written to the pack stream.
- * <p>
- * Iterator <b>exactly</b> determines which objects are included in a pack
- * and order they appear in pack (except that objects order by type is not
- * needed at input). This order should conform general rules of ordering
- * objects in git - by recency and path (type and delta-base first is
- * internally secured) and responsibility for guaranteeing this order is on
- * a caller side. Iterator must return each id of object to write exactly
- * once.
- * </p>
- * <p>
- * When iterator returns object that has {@link RevFlag#UNINTERESTING} flag,
- * this object won't be included in an output pack. Instead, it is recorded
- * as edge-object (known to remote repository) for thin-pack. In such a case
- * writer may pack objects with delta base object not within set of objects
- * to pack, but belonging to party repository - those marked with
- * {@link RevFlag#UNINTERESTING} flag. This type of pack is used only for
- * transport.
- * </p>
- *
- * @param objectsSource
- * iterator of object to store in a pack; order of objects within
- * each type is important, ordering by type is not needed;
- * allowed types for objects are {@link Constants#OBJ_COMMIT},
- * {@link Constants#OBJ_TREE}, {@link Constants#OBJ_BLOB} and
- * {@link Constants#OBJ_TAG}; objects returned by iterator may
- * be later reused by caller as object id and type are internally
- * copied in each iteration; if object returned by iterator has
- * {@link RevFlag#UNINTERESTING} flag set, it won't be included
- * in a pack, but is considered as edge-object for thin-pack.
- * @throws IOException
- * when some I/O problem occur during reading objects.
- */
- public void preparePack(final Iterator<RevObject> objectsSource)
- throws IOException {
- while (objectsSource.hasNext()) {
- addObject(objectsSource.next());
- }
- }
-
- /**
- * Prepare the list of objects to be written to the pack stream.
- * <p>
- * Basing on these 2 sets, another set of objects to put in a pack file is
- * created: this set consists of all objects reachable (ancestors) from
- * interesting objects, except uninteresting objects and their ancestors.
- * This method uses class {@link ObjectWalk} extensively to find out that
- * appropriate set of output objects and their optimal order in output pack.
- * Order is consistent with general git in-pack rules: sort by object type,
- * recency, path and delta-base first.
- * </p>
- *
- * @param interestingObjects
- * collection of objects to be marked as interesting (start
- * points of graph traversal).
- * @param uninterestingObjects
- * collection of objects to be marked as uninteresting (end
- * points of graph traversal).
- * @throws IOException
- * when some I/O problem occur during reading objects.
- */
- public void preparePack(
- final Collection<? extends ObjectId> interestingObjects,
- final Collection<? extends ObjectId> uninterestingObjects)
- throws IOException {
- ObjectWalk walker = setUpWalker(interestingObjects,
- uninterestingObjects);
- findObjectsToPack(walker);
- }
-
- /**
- * Determine if the pack file will contain the requested object.
- *
- * @param id
- * the object to test the existence of.
- * @return true if the object will appear in the output pack file.
- */
- public boolean willInclude(final AnyObjectId id) {
- return objectsMap.get(id) != null;
- }
-
- /**
- * Computes SHA-1 of lexicographically sorted objects ids written in this
- * pack, as used to name a pack file in repository.
- *
- * @return ObjectId representing SHA-1 name of a pack that was created.
- */
- public ObjectId computeName() {
- final MessageDigest md = Constants.newMessageDigest();
- for (ObjectToPack otp : sortByName()) {
- otp.copyRawTo(buf, 0);
- md.update(buf, 0, Constants.OBJECT_ID_LENGTH);
- }
- return ObjectId.fromRaw(md.digest());
- }
-
- /**
- * Create an index file to match the pack file just written.
- * <p>
- * This method can only be invoked after {@link #preparePack(Iterator)} or
- * {@link #preparePack(Collection, Collection)} has been
- * invoked and completed successfully. Writing a corresponding index is an
- * optional feature that not all pack users may require.
- *
- * @param indexStream
- * output for the index data. Caller is responsible for closing
- * this stream.
- * @throws IOException
- * the index data could not be written to the supplied stream.
- */
- public void writeIndex(final OutputStream indexStream) throws IOException {
- final List<ObjectToPack> list = sortByName();
- final PackIndexWriter iw;
- if (outputVersion <= 0)
- iw = PackIndexWriter.createOldestPossible(indexStream, list);
- else
- iw = PackIndexWriter.createVersion(indexStream, outputVersion);
- iw.write(list, packcsum);
- }
-
- private List<ObjectToPack> sortByName() {
- if (sortedByName == null) {
- sortedByName = new ArrayList<ObjectToPack>(objectsMap.size());
- for (List<ObjectToPack> list : objectsLists) {
- for (ObjectToPack otp : list)
- sortedByName.add(otp);
- }
- Collections.sort(sortedByName);
- }
- return sortedByName;
- }
-
- /**
- * Write the prepared pack to the supplied stream.
- * <p>
- * At first, this method collects and sorts objects to pack, then deltas
- * search is performed if set up accordingly, finally pack stream is
- * written. {@link ProgressMonitor} tasks {@value #SEARCHING_REUSE_PROGRESS}
- * (only if reuseDeltas or reuseObjects is enabled) and
- * {@value #WRITING_OBJECTS_PROGRESS} are updated during packing.
- * </p>
- * <p>
- * All reused objects data checksum (Adler32/CRC32) is computed and
- * validated against existing checksum.
- * </p>
- *
- * @param packStream
- * output stream of pack data. The stream should be buffered by
- * the caller. The caller is responsible for closing the stream.
- * @throws IOException
- * an error occurred reading a local object's data to include in
- * the pack, or writing compressed object data to the output
- * stream.
- */
- public void writePack(OutputStream packStream) throws IOException {
- if (reuseDeltas || reuseObjects)
- searchForReuse();
-
- out = new PackOutputStream(packStream);
-
- writeMonitor.beginTask(WRITING_OBJECTS_PROGRESS, getObjectsNumber());
- writeHeader();
- writeObjects();
- writeChecksum();
-
- windowCursor.release();
- writeMonitor.endTask();
- }
-
- private void searchForReuse() throws IOException {
- initMonitor.beginTask(SEARCHING_REUSE_PROGRESS, getObjectsNumber());
- final Collection<PackedObjectLoader> reuseLoaders = new ArrayList<PackedObjectLoader>();
- for (List<ObjectToPack> list : objectsLists) {
- for (ObjectToPack otp : list) {
- if (initMonitor.isCancelled())
- throw new IOException(
- JGitText.get().packingCancelledDuringObjectsWriting);
- reuseLoaders.clear();
- searchForReuse(reuseLoaders, otp);
- initMonitor.update(1);
- }
- }
-
- initMonitor.endTask();
- }
-
- private void searchForReuse(
- final Collection<PackedObjectLoader> reuseLoaders,
- final ObjectToPack otp) throws IOException {
- db.openObjectInAllPacks(otp, reuseLoaders, windowCursor);
- if (reuseDeltas) {
- selectDeltaReuseForObject(otp, reuseLoaders);
- }
- // delta reuse is preferred over object reuse
- if (reuseObjects && !otp.isCopyable()) {
- selectObjectReuseForObject(otp, reuseLoaders);
- }
- }
-
- private void selectDeltaReuseForObject(final ObjectToPack otp,
- final Collection<PackedObjectLoader> loaders) throws IOException {
- PackedObjectLoader bestLoader = null;
- ObjectId bestBase = null;
-
- for (PackedObjectLoader loader : loaders) {
- ObjectId idBase = loader.getDeltaBase();
- if (idBase == null)
- continue;
- ObjectToPack otpBase = objectsMap.get(idBase);
-
- // only if base is in set of objects to write or thin-pack's edge
- if ((otpBase != null || (thin && edgeObjects.get(idBase) != null))
- // select smallest possible delta if > 1 available
- && isBetterDeltaReuseLoader(bestLoader, loader)) {
- bestLoader = loader;
- bestBase = (otpBase != null ? otpBase : idBase);
- }
- }
-
- if (bestLoader != null) {
- otp.setCopyFromPack(bestLoader);
- otp.setDeltaBase(bestBase);
- }
- }
-
- private static boolean isBetterDeltaReuseLoader(
- PackedObjectLoader currentLoader, PackedObjectLoader loader)
- throws IOException {
- if (currentLoader == null)
- return true;
- if (loader.getRawSize() < currentLoader.getRawSize())
- return true;
- return (loader.getRawSize() == currentLoader.getRawSize()
- && loader.supportsFastCopyRawData() && !currentLoader
- .supportsFastCopyRawData());
- }
-
- private void selectObjectReuseForObject(final ObjectToPack otp,
- final Collection<PackedObjectLoader> loaders) {
- for (final PackedObjectLoader loader : loaders) {
- if (loader instanceof WholePackedObjectLoader) {
- otp.setCopyFromPack(loader);
- return;
- }
- }
- }
-
- private void writeHeader() throws IOException {
- System.arraycopy(Constants.PACK_SIGNATURE, 0, buf, 0, 4);
- NB.encodeInt32(buf, 4, PACK_VERSION_GENERATED);
- NB.encodeInt32(buf, 8, getObjectsNumber());
- out.write(buf, 0, 12);
- }
-
- private void writeObjects() throws IOException {
- for (List<ObjectToPack> list : objectsLists) {
- for (ObjectToPack otp : list) {
- if (writeMonitor.isCancelled())
- throw new IOException(
- JGitText.get().packingCancelledDuringObjectsWriting);
- if (!otp.isWritten())
- writeObject(otp);
- }
- }
- }
-
- private void writeObject(final ObjectToPack otp) throws IOException {
- otp.markWantWrite();
- if (otp.isDeltaRepresentation()) {
- ObjectToPack deltaBase = otp.getDeltaBase();
- assert deltaBase != null || thin;
- if (deltaBase != null && !deltaBase.isWritten()) {
- if (deltaBase.wantWrite()) {
- otp.clearDeltaBase(); // cycle detected
- otp.clearSourcePack();
- } else {
- writeObject(deltaBase);
- }
- }
- }
-
- assert !otp.isWritten();
-
- out.resetCRC32();
- otp.setOffset(out.length());
-
- final PackedObjectLoader reuse = open(otp);
- if (reuse != null) {
- try {
- if (otp.isDeltaRepresentation())
- writeDeltaObjectHeader(otp, reuse);
- else
- writeObjectHeader(otp.getType(), reuse.getSize());
- reuse.copyRawData(out, buf, windowCursor);
- } finally {
- reuse.endCopyRawData();
- }
- } else if (otp.isDeltaRepresentation()) {
- throw new IOException(JGitText.get().creatingDeltasIsNotImplemented);
- } else {
- writeWholeObjectDeflate(otp);
- }
- otp.setCRC(out.getCRC32());
-
- writeMonitor.update(1);
- }
-
- private PackedObjectLoader open(final ObjectToPack otp) throws IOException {
- while (otp.isCopyable()) {
- try {
- PackedObjectLoader reuse = otp.getCopyLoader(windowCursor);
- reuse.beginCopyRawData();
- return reuse;
- } catch (IOException err) {
- // The pack we found the object in originally is gone, or
- // it has been overwritten with a different layout.
- //
- otp.clearDeltaBase();
- otp.clearSourcePack();
- searchForReuse(new ArrayList<PackedObjectLoader>(), otp);
- continue;
- }
- }
- return null;
- }
-
- private void writeWholeObjectDeflate(final ObjectToPack otp)
- throws IOException {
- final ObjectLoader loader = db.openObject(windowCursor, otp);
- final byte[] data = loader.getCachedBytes();
- writeObjectHeader(otp.getType(), data.length);
- deflater.reset();
- deflater.setInput(data, 0, data.length);
- deflater.finish();
- do {
- final int n = deflater.deflate(buf, 0, buf.length);
- if (n > 0)
- out.write(buf, 0, n);
- } while (!deflater.finished());
- }
-
- private void writeDeltaObjectHeader(final ObjectToPack otp,
- final PackedObjectLoader reuse) throws IOException {
- if (deltaBaseAsOffset && otp.getDeltaBase() != null) {
- writeObjectHeader(Constants.OBJ_OFS_DELTA, reuse.getRawSize());
-
- final ObjectToPack deltaBase = otp.getDeltaBase();
- long offsetDiff = otp.getOffset() - deltaBase.getOffset();
- int pos = buf.length - 1;
- buf[pos] = (byte) (offsetDiff & 0x7F);
- while ((offsetDiff >>= 7) > 0) {
- buf[--pos] = (byte) (0x80 | (--offsetDiff & 0x7F));
- }
-
- out.write(buf, pos, buf.length - pos);
- } else {
- writeObjectHeader(Constants.OBJ_REF_DELTA, reuse.getRawSize());
- otp.getDeltaBaseId().copyRawTo(buf, 0);
- out.write(buf, 0, Constants.OBJECT_ID_LENGTH);
- }
- }
-
- private void writeObjectHeader(final int objectType, long dataLength)
- throws IOException {
- long nextLength = dataLength >>> 4;
- int size = 0;
- buf[size++] = (byte) ((nextLength > 0 ? 0x80 : 0x00)
- | (objectType << 4) | (dataLength & 0x0F));
- dataLength = nextLength;
- while (dataLength > 0) {
- nextLength >>>= 7;
- buf[size++] = (byte) ((nextLength > 0 ? 0x80 : 0x00) | (dataLength & 0x7F));
- dataLength = nextLength;
- }
- out.write(buf, 0, size);
- }
-
- private void writeChecksum() throws IOException {
- packcsum = out.getDigest();
- out.write(packcsum);
- }
-
- private ObjectWalk setUpWalker(
- final Collection<? extends ObjectId> interestingObjects,
- final Collection<? extends ObjectId> uninterestingObjects)
- throws MissingObjectException, IOException,
- IncorrectObjectTypeException {
- final ObjectWalk walker = new ObjectWalk(db);
- walker.setRetainBody(false);
- walker.sort(RevSort.TOPO);
- walker.sort(RevSort.COMMIT_TIME_DESC, true);
- if (thin)
- walker.sort(RevSort.BOUNDARY, true);
-
- for (ObjectId id : interestingObjects) {
- RevObject o = walker.parseAny(id);
- walker.markStart(o);
- }
- if (uninterestingObjects != null) {
- for (ObjectId id : uninterestingObjects) {
- final RevObject o;
- try {
- o = walker.parseAny(id);
- } catch (MissingObjectException x) {
- if (ignoreMissingUninteresting)
- continue;
- throw x;
- }
- walker.markUninteresting(o);
- }
- }
- return walker;
- }
-
- private void findObjectsToPack(final ObjectWalk walker)
- throws MissingObjectException, IncorrectObjectTypeException,
- IOException {
- initMonitor.beginTask(COUNTING_OBJECTS_PROGRESS,
- ProgressMonitor.UNKNOWN);
- RevObject o;
-
- while ((o = walker.next()) != null) {
- addObject(o);
- initMonitor.update(1);
- }
- while ((o = walker.nextObject()) != null) {
- addObject(o);
- initMonitor.update(1);
- }
- initMonitor.endTask();
- }
-
- /**
- * Include one object to the output file.
- * <p>
- * Objects are written in the order they are added. If the same object is
- * added twice, it may be written twice, creating a larger than necessary
- * file.
- *
- * @param object
- * the object to add.
- * @throws IncorrectObjectTypeException
- * the object is an unsupported type.
- */
- public void addObject(final RevObject object)
- throws IncorrectObjectTypeException {
- if (object.has(RevFlag.UNINTERESTING)) {
- edgeObjects.add(object);
- thin = true;
- return;
- }
-
- final ObjectToPack otp = new ObjectToPack(object, object.getType());
- try {
- objectsLists[object.getType()].add(otp);
- } catch (ArrayIndexOutOfBoundsException x) {
- throw new IncorrectObjectTypeException(object,
- JGitText.get().incorrectObjectType_COMMITnorTREEnorBLOBnorTAG);
- } catch (UnsupportedOperationException x) {
- // index pointing to "dummy" empty list
- throw new IncorrectObjectTypeException(object,
- JGitText.get().incorrectObjectType_COMMITnorTREEnorBLOBnorTAG);
- }
- objectsMap.add(otp);
- }
-
- /**
- * Class holding information about object that is going to be packed by
- * {@link PackWriter}. Information include object representation in a
- * pack-file and object status.
- *
- */
- static class ObjectToPack extends PackedObjectInfo {
- /** Other object being packed that this will delta against. */
- private ObjectId deltaBase;
-
- /** Pack to reuse compressed data from, otherwise null. */
- private PackFile copyFromPack;
-
- /** Offset of the object's header in {@link #copyFromPack}. */
- private long copyOffset;
-
- /**
- * Bit field, from bit 0 to bit 31:
- * <ul>
- * <li>1 bit: wantWrite</li>
- * <li>3 bits: type</li>
- * <li>28 bits: deltaDepth</li>
- * </ul>
- */
- private int flags;
-
- /**
- * Construct object for specified object id. <br/> By default object is
- * marked as not written and non-delta packed (as a whole object).
- *
- * @param src
- * object id of object for packing
- * @param type
- * real type code of the object, not its in-pack type.
- */
- ObjectToPack(AnyObjectId src, final int type) {
- super(src);
- flags |= type << 1;
- }
-
- /**
- * @return delta base object id if object is going to be packed in delta
- * representation; null otherwise - if going to be packed as a
- * whole object.
- */
- ObjectId getDeltaBaseId() {
- return deltaBase;
- }
-
- /**
- * @return delta base object to pack if object is going to be packed in
- * delta representation and delta is specified as object to
- * pack; null otherwise - if going to be packed as a whole
- * object or delta base is specified only as id.
- */
- ObjectToPack getDeltaBase() {
- if (deltaBase instanceof ObjectToPack)
- return (ObjectToPack) deltaBase;
- return null;
- }
-
- /**
- * Set delta base for the object. Delta base set by this method is used
- * by {@link PackWriter} to write object - determines its representation
- * in a created pack.
- *
- * @param deltaBase
- * delta base object or null if object should be packed as a
- * whole object.
- *
- */
- void setDeltaBase(ObjectId deltaBase) {
- this.deltaBase = deltaBase;
- }
-
- void clearDeltaBase() {
- this.deltaBase = null;
- }
-
- /**
- * @return true if object is going to be written as delta; false
- * otherwise.
- */
- boolean isDeltaRepresentation() {
- return deltaBase != null;
- }
-
- /**
- * Check if object is already written in a pack. This information is
- * used to achieve delta-base precedence in a pack file.
- *
- * @return true if object is already written; false otherwise.
- */
- boolean isWritten() {
- return getOffset() != 0;
- }
-
- boolean isCopyable() {
- return copyFromPack != null;
- }
-
- PackedObjectLoader getCopyLoader(WindowCursor curs) throws IOException {
- return copyFromPack.resolveBase(curs, copyOffset);
- }
-
- void setCopyFromPack(PackedObjectLoader loader) {
- this.copyFromPack = loader.pack;
- this.copyOffset = loader.objectOffset;
- }
-
- void clearSourcePack() {
- copyFromPack = null;
- }
-
- int getType() {
- return (flags>>1) & 0x7;
- }
-
- int getDeltaDepth() {
- return flags >>> 4;
- }
-
- void updateDeltaDepth() {
- final int d;
- if (deltaBase instanceof ObjectToPack)
- d = ((ObjectToPack) deltaBase).getDeltaDepth() + 1;
- else if (deltaBase != null)
- d = 1;
- else
- d = 0;
- flags = (d << 4) | flags & 0x15;
- }
-
- boolean wantWrite() {
- return (flags & 1) == 1;
- }
-
- void markWantWrite() {
- flags |= 1;
- }
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackedObjectLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackedObjectLoader.java
deleted file mode 100644
index 026b008f1a..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackedObjectLoader.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2009, Google Inc.
- * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Base class for a set of object loader classes for packed objects.
- */
-abstract class PackedObjectLoader extends ObjectLoader {
- protected final PackFile pack;
-
- /** Position of the first byte of the object's header. */
- protected final long objectOffset;
-
- /** Bytes used to express the object header, including delta reference. */
- protected final int headerSize;
-
- protected int objectType;
-
- protected int objectSize;
-
- protected byte[] cachedBytes;
-
- PackedObjectLoader(final PackFile pr, final long objectOffset,
- final int headerSize) {
- pack = pr;
- this.objectOffset = objectOffset;
- this.headerSize = headerSize;
- }
-
- /**
- * Force this object to be loaded into memory and pinned in this loader.
- * <p>
- * Once materialized, subsequent get operations for the following methods
- * will always succeed without raising an exception, as all information is
- * pinned in memory by this loader instance.
- * <ul>
- * <li>{@link #getType()}</li>
- * <li>{@link #getSize()}</li>
- * <li>{@link #getBytes()}, {@link #getCachedBytes}</li>
- * <li>{@link #getRawSize()}</li>
- * <li>{@link #getRawType()}</li>
- * </ul>
- *
- * @param curs
- * temporary thread storage during data access.
- * @throws IOException
- * the object cannot be read.
- */
- public abstract void materialize(WindowCursor curs) throws IOException;
-
- public final int getType() {
- return objectType;
- }
-
- public final long getSize() {
- return objectSize;
- }
-
- @Override
- public final byte[] getCachedBytes() {
- return cachedBytes;
- }
-
- /**
- * @return offset of object header within pack file
- */
- public final long getObjectOffset() {
- return objectOffset;
- }
-
- /**
- * Peg the pack file open to support data copying.
- * <p>
- * Applications trying to copy raw pack data should ensure the pack stays
- * open and available throughout the entire copy. To do that use:
- *
- * <pre>
- * loader.beginCopyRawData();
- * try {
- * loader.copyRawData(out, tmpbuf, curs);
- * } finally {
- * loader.endCopyRawData();
- * }
- * </pre>
- *
- * @throws IOException
- * this loader contains stale information and cannot be used.
- * The most likely cause is the underlying pack file has been
- * deleted, and the object has moved to another pack file.
- */
- public void beginCopyRawData() throws IOException {
- pack.beginCopyRawData();
- }
-
- /**
- * Copy raw object representation from storage to provided output stream.
- * <p>
- * Copied data doesn't include object header. User must provide temporary
- * buffer used during copying by underlying I/O layer.
- * </p>
- *
- * @param out
- * output stream when data is copied. No buffering is guaranteed.
- * @param buf
- * temporary buffer used during copying. Recommended size is at
- * least few kB.
- * @param curs
- * temporary thread storage during data access.
- * @throws IOException
- * when the object cannot be read.
- * @see #beginCopyRawData()
- */
- public void copyRawData(OutputStream out, byte buf[], WindowCursor curs)
- throws IOException {
- pack.copyRawData(this, out, buf, curs);
- }
-
- /** Release resources after {@link #beginCopyRawData()}. */
- public void endCopyRawData() {
- pack.endCopyRawData();
- }
-
- /**
- * @return true if this loader is capable of fast raw-data copying basing on
- * compressed data checksum; false if raw-data copying needs
- * uncompressing and compressing data
- * @throws IOException
- * the index file format cannot be determined.
- */
- public boolean supportsFastCopyRawData() throws IOException {
- return pack.supportsFastCopyRawData();
- }
-
- /**
- * @return id of delta base object for this object representation. null if
- * object is not stored as delta.
- * @throws IOException
- * when delta base cannot read.
- */
- public abstract ObjectId getDeltaBase() throws IOException;
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
index 522f8477b1..0406684ea7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
@@ -77,7 +77,7 @@ public class PersonIdent {
* @param repo
*/
public PersonIdent(final Repository repo) {
- final RepositoryConfig config = repo.getConfig();
+ final UserConfig config = repo.getConfig().get(UserConfig.KEY);
name = config.getCommitterName();
emailAddress = config.getCommitterEmail();
when = SystemReader.getInstance().getCurrentTime();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java
index e04a587ac2..e6f8933389 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java
@@ -440,7 +440,12 @@ public abstract class RefUpdate {
* an unexpected IO error occurred while writing changes.
*/
public Result update() throws IOException {
- return update(new RevWalk(getRepository()));
+ RevWalk rw = new RevWalk(getRepository());
+ try {
+ return update(rw);
+ } finally {
+ rw.release();
+ }
}
/**
@@ -485,7 +490,12 @@ public abstract class RefUpdate {
* @throws IOException
*/
public Result delete() throws IOException {
- return delete(new RevWalk(getRepository()));
+ RevWalk rw = new RevWalk(getRepository());
+ try {
+ return delete(rw);
+ } finally {
+ rw.release();
+ }
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
index f2738245d4..4acb3ecd89 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
@@ -51,6 +51,7 @@ import java.io.StringWriter;
import java.util.Collection;
import java.util.Map;
+import org.eclipse.jgit.storage.file.RefDirectory;
import org.eclipse.jgit.util.RefList;
import org.eclipse.jgit.util.RefMap;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
index 62e1578350..6dfbc9d2da 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -49,9 +49,6 @@ package org.eclipse.jgit.lib;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -59,279 +56,103 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.dircache.DirCache;
-import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.errors.RevisionSyntaxException;
+import org.eclipse.jgit.events.ListenerList;
+import org.eclipse.jgit.events.RepositoryEvent;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.file.ReflogReader;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
-import org.eclipse.jgit.util.SystemReader;
/**
- * Represents a Git repository. A repository holds all objects and refs used for
- * managing source code (could by any type of file, but source code is what
- * SCM's are typically used for).
- *
- * In Git terms all data is stored in GIT_DIR, typically a directory called
- * .git. A work tree is maintained unless the repository is a bare repository.
- * Typically the .git directory is located at the root of the work dir.
- *
- * <ul>
- * <li>GIT_DIR
- * <ul>
- * <li>objects/ - objects</li>
- * <li>refs/ - tags and heads</li>
- * <li>config - configuration</li>
- * <li>info/ - more configurations</li>
- * </ul>
- * </li>
- * </ul>
+ * Represents a Git repository.
* <p>
- * This class is thread-safe.
+ * A repository holds all objects and refs used for managing source code (could
+ * be any type of file, but source code is what SCM's are typically used for).
* <p>
- * This implementation only handles a subtly undocumented subset of git features.
- *
+ * This class is thread-safe.
*/
-public class Repository {
+public abstract class Repository {
+ private static final ListenerList globalListeners = new ListenerList();
+
+ /** @return the global listener list observing all events in this JVM. */
+ public static ListenerList getGlobalListenerList() {
+ return globalListeners;
+ }
+
private final AtomicInteger useCnt = new AtomicInteger(1);
+ /** Metadata directory holding the repository's critical files. */
private final File gitDir;
+ /** File abstraction used to resolve paths. */
private final FS fs;
- private final FileBasedConfig userConfig;
-
- private final RepositoryConfig config;
-
- private final RefDatabase refs;
-
- private final ObjectDirectory objectDatabase;
-
private GitIndex index;
- private final List<RepositoryListener> listeners = new Vector<RepositoryListener>(); // thread safe
- static private final List<RepositoryListener> allListeners = new Vector<RepositoryListener>(); // thread safe
+ private final ListenerList myListeners = new ListenerList();
- private File workDir;
+ /** If not bare, the top level directory of the working files. */
+ private final File workTree;
- private File indexFile;
+ /** If not bare, the index file caching the working file states. */
+ private final File indexFile;
/**
- * Construct a representation of a Git repository.
- *
- * The work tree, object directory, alternate object directories and index
- * file locations are deduced from the given git directory and the default
- * rules.
+ * Initialize a new repository instance.
*
- * @param d
- * GIT_DIR (the location of the repository metadata).
- * @throws IOException
- * the repository appears to already exist but cannot be
- * accessed.
+ * @param options
+ * options to configure the repository.
*/
- public Repository(final File d) throws IOException {
- this(d, null, null, null, null); // go figure it out
+ protected Repository(final BaseRepositoryBuilder options) {
+ gitDir = options.getGitDir();
+ fs = options.getFS();
+ workTree = options.getWorkTree();
+ indexFile = options.getIndexFile();
}
- /**
- * Construct a representation of a Git repository.
- *
- * The work tree, object directory, alternate object directories and index
- * file locations are deduced from the given git directory and the default
- * rules.
- *
- * @param d
- * GIT_DIR (the location of the repository metadata). May be
- * null work workTree is set
- * @param workTree
- * GIT_WORK_TREE (the root of the checkout). May be null for
- * default value.
- * @throws IOException
- * the repository appears to already exist but cannot be
- * accessed.
- */
- public Repository(final File d, final File workTree) throws IOException {
- this(d, workTree, null, null, null); // go figure it out
+ /** @return listeners observing only events on this repository. */
+ public ListenerList getListenerList() {
+ return myListeners;
}
/**
- * Construct a representation of a Git repository using the given parameters
- * possibly overriding default conventions.
- *
- * @param d
- * GIT_DIR (the location of the repository metadata). May be null
- * for default value in which case it depends on GIT_WORK_TREE.
- * @param workTree
- * GIT_WORK_TREE (the root of the checkout). May be null for
- * default value if GIT_DIR is provided.
- * @param objectDir
- * GIT_OBJECT_DIRECTORY (where objects and are stored). May be
- * null for default value. Relative names ares resolved against
- * GIT_WORK_TREE.
- * @param alternateObjectDir
- * GIT_ALTERNATE_OBJECT_DIRECTORIES (where more objects are read
- * from). May be null for default value. Relative names ares
- * resolved against GIT_WORK_TREE.
- * @param indexFile
- * GIT_INDEX_FILE (the location of the index file). May be null
- * for default value. Relative names ares resolved against
- * GIT_WORK_TREE.
- * @throws IOException
- * the repository appears to already exist but cannot be
- * accessed.
- */
- public Repository(final File d, final File workTree, final File objectDir,
- final File[] alternateObjectDir, final File indexFile) throws IOException {
- this(d, workTree, objectDir, alternateObjectDir, indexFile, FS.DETECTED);
- }
-
- /**
- * Construct a representation of a Git repository using the given parameters
- * possibly overriding default conventions.
+ * Fire an event to all registered listeners.
+ * <p>
+ * The source repository of the event is automatically set to this
+ * repository, before the event is delivered to any listeners.
*
- * @param d
- * GIT_DIR (the location of the repository metadata). May be null
- * for default value in which case it depends on GIT_WORK_TREE.
- * @param workTree
- * GIT_WORK_TREE (the root of the checkout). May be null for
- * default value if GIT_DIR is provided.
- * @param objectDir
- * GIT_OBJECT_DIRECTORY (where objects and are stored). May be
- * null for default value. Relative names ares resolved against
- * GIT_WORK_TREE.
- * @param alternateObjectDir
- * GIT_ALTERNATE_OBJECT_DIRECTORIES (where more objects are read
- * from). May be null for default value. Relative names ares
- * resolved against GIT_WORK_TREE.
- * @param indexFile
- * GIT_INDEX_FILE (the location of the index file). May be null
- * for default value. Relative names ares resolved against
- * GIT_WORK_TREE.
- * @param fs
- * the file system abstraction which will be necessary to
- * perform certain file system operations.
- * @throws IOException
- * the repository appears to already exist but cannot be
- * accessed.
+ * @param event
+ * the event to deliver.
*/
- public Repository(final File d, final File workTree, final File objectDir,
- final File[] alternateObjectDir, final File indexFile, FS fs)
- throws IOException {
-
- if (workTree != null) {
- workDir = workTree;
- if (d == null)
- gitDir = new File(workTree, Constants.DOT_GIT);
- else
- gitDir = d;
- } else {
- if (d != null)
- gitDir = d;
- else
- throw new IllegalArgumentException(
- JGitText.get().eitherGIT_DIRorGIT_WORK_TREEmustBePassed);
- }
-
- this.fs = fs;
-
- userConfig = SystemReader.getInstance().openUserConfig(fs);
- config = new RepositoryConfig(userConfig, fs.resolve(gitDir, "config"));
-
- loadUserConfig();
- loadConfig();
-
- if (workDir == null) {
- // if the working directory was not provided explicitly,
- // we need to decide if this is a "bare" repository or not
- // first, we check the working tree configuration
- String workTreeConfig = getConfig().getString(
- ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_WORKTREE);
- if (workTreeConfig != null) {
- // the working tree configuration wins
- workDir = fs.resolve(d, workTreeConfig);
- } else if (getConfig().getString(
- ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_BARE) != null) {
- // we have asserted that a value for the "bare" flag was set
- if (!getConfig().getBoolean(ConfigConstants.CONFIG_CORE_SECTION,
- ConfigConstants.CONFIG_KEY_BARE, true))
- // the "bare" flag is false -> use the parent of the
- // meta data directory
- workDir = gitDir.getParentFile();
- else
- // the "bare" flag is true
- workDir = null;
- } else if (Constants.DOT_GIT.equals(gitDir.getName())) {
- // no value for the "bare" flag, but the meta data directory
- // is named ".git" -> use the parent of the meta data directory
- workDir = gitDir.getParentFile();
- } else {
- workDir = null;
- }
- }
-
- refs = new RefDirectory(this);
- if (objectDir != null)
- objectDatabase = new ObjectDirectory(fs.resolve(objectDir, ""),
- alternateObjectDir, fs);
- else
- objectDatabase = new ObjectDirectory(fs.resolve(gitDir, "objects"),
- alternateObjectDir, fs);
-
- if (indexFile != null)
- this.indexFile = indexFile;
- else
- this.indexFile = new File(gitDir, "index");
-
- if (objectDatabase.exists()) {
- final String repositoryFormatVersion = getConfig().getString(
- ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION);
- if (!"0".equals(repositoryFormatVersion)) {
- throw new IOException(MessageFormat.format(
- JGitText.get().unknownRepositoryFormat2,
- repositoryFormatVersion));
- }
- }
+ public void fireEvent(RepositoryEvent<?> event) {
+ event.setRepository(this);
+ myListeners.dispatch(event);
+ globalListeners.dispatch(event);
}
- private void loadUserConfig() throws IOException {
- try {
- userConfig.load();
- } catch (ConfigInvalidException e1) {
- IOException e2 = new IOException(MessageFormat.format(JGitText
- .get().userConfigFileInvalid, userConfig.getFile()
- .getAbsolutePath(), e1));
- e2.initCause(e1);
- throw e2;
- }
- }
-
- private void loadConfig() throws IOException {
- try {
- config.load();
- } catch (ConfigInvalidException e1) {
- IOException e2 = new IOException(JGitText.get().unknownRepositoryFormat);
- e2.initCause(e1);
- throw e2;
- }
- }
-
-
/**
- * Create a new Git repository initializing the necessary files and
- * directories. Repository with working tree is created using this method.
+ * Create a new Git repository.
+ * <p>
+ * Repository with working tree is created using this method. This method is
+ * the same as {@code create(false)}.
*
* @throws IOException
* @see #create(boolean)
*/
- public synchronized void create() throws IOException {
+ public void create() throws IOException {
create(false);
}
@@ -340,44 +161,14 @@ public class Repository {
* directories.
*
* @param bare
- * if true, a bare repository is created.
- *
+ * if true, a bare repository (a repository without a working
+ * directory) is created.
* @throws IOException
* in case of IO problem
*/
- public void create(boolean bare) throws IOException {
- final RepositoryConfig cfg = getConfig();
- if (cfg.getFile().exists()) {
- throw new IllegalStateException(MessageFormat.format(
- JGitText.get().repositoryAlreadyExists, gitDir));
- }
- gitDir.mkdirs();
- refs.create();
- objectDatabase.create();
-
- new File(gitDir, "branches").mkdir();
-
- RefUpdate head = updateRef(Constants.HEAD);
- head.disableRefLog();
- head.link(Constants.R_HEADS + Constants.MASTER);
-
- cfg.setInt(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION, 0);
- cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_FILEMODE, true);
- if (bare)
- cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_BARE, true);
- cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, !bare);
- cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_AUTOCRLF, false);
- cfg.save();
- }
+ public abstract void create(boolean bare) throws IOException;
- /**
- * @return GIT_DIR
- */
+ /** @return local metadata directory; null if repository isn't local. */
public File getDirectory() {
return gitDir;
}
@@ -385,42 +176,30 @@ public class Repository {
/**
* @return the directory containing the objects owned by this repository.
*/
- public File getObjectsDirectory() {
- return objectDatabase.getDirectory();
- }
+ public abstract File getObjectsDirectory();
/**
* @return the object database which stores this repository's data.
*/
- public ObjectDatabase getObjectDatabase() {
- return objectDatabase;
+ public abstract ObjectDatabase getObjectDatabase();
+
+ /** @return a new inserter to create objects in {@link #getObjectDatabase()} */
+ public ObjectInserter newObjectInserter() {
+ return getObjectDatabase().newInserter();
}
- /** @return the reference database which stores the reference namespace. */
- public RefDatabase getRefDatabase() {
- return refs;
+ /** @return a new inserter to create objects in {@link #getObjectDatabase()} */
+ public ObjectReader newObjectReader() {
+ return getObjectDatabase().newReader();
}
+ /** @return the reference database which stores the reference namespace. */
+ public abstract RefDatabase getRefDatabase();
+
/**
* @return the configuration of this repository
*/
- public RepositoryConfig getConfig() {
- if (userConfig.isOutdated()) {
- try {
- loadUserConfig();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- if (config.isOutdated()) {
- try {
- loadConfig();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- return config;
- }
+ public abstract Config getConfig();
/**
* @return the used file system abstraction
@@ -430,116 +209,63 @@ public class Repository {
}
/**
- * Construct a filename where the loose object having a specified SHA-1
- * should be stored. If the object is stored in a shared repository the path
- * to the alternative repo will be returned. If the object is not yet store
- * a usable path in this repo will be returned. It is assumed that callers
- * will look for objects in a pack first.
- *
- * @param objectId
- * @return suggested file name
- */
- public File toFile(final AnyObjectId objectId) {
- return objectDatabase.fileFor(objectId);
- }
-
- /**
* @param objectId
* @return true if the specified object is stored in this repo or any of the
* known shared repositories.
*/
- public boolean hasObject(final AnyObjectId objectId) {
- return objectDatabase.hasObject(objectId);
- }
-
- /**
- * @param id
- * SHA-1 of an object.
- *
- * @return a {@link ObjectLoader} for accessing the data of the named
- * object, or null if the object does not exist.
- * @throws IOException
- */
- public ObjectLoader openObject(final AnyObjectId id)
- throws IOException {
- final WindowCursor wc = new WindowCursor();
+ public boolean hasObject(AnyObjectId objectId) {
try {
- return openObject(wc, id);
- } finally {
- wc.release();
+ return getObjectDatabase().has(objectId);
+ } catch (IOException e) {
+ // Legacy API, assume error means "no"
+ return false;
}
}
/**
- * @param curs
- * temporary working space associated with the calling thread.
- * @param id
- * SHA-1 of an object.
- *
- * @return a {@link ObjectLoader} for accessing the data of the named
- * object, or null if the object does not exist.
- * @throws IOException
- */
- public ObjectLoader openObject(final WindowCursor curs, final AnyObjectId id)
- throws IOException {
- return objectDatabase.openObject(curs, id);
- }
-
- /**
- * Open object in all packs containing specified object.
+ * Open an object from this repository.
+ * <p>
+ * This is a one-shot call interface which may be faster than allocating a
+ * {@link #newObjectReader()} to perform the lookup.
*
* @param objectId
- * id of object to search for
- * @param curs
- * temporary working space associated with the calling thread.
- * @return collection of loaders for this object, from all packs containing
- * this object
+ * identity of the object to open.
+ * @return a {@link ObjectLoader} for accessing the object.
+ * @throws MissingObjectException
+ * the object does not exist.
* @throws IOException
+ * the object store cannot be accessed.
*/
- public Collection<PackedObjectLoader> openObjectInAllPacks(
- final AnyObjectId objectId, final WindowCursor curs)
- throws IOException {
- Collection<PackedObjectLoader> result = new LinkedList<PackedObjectLoader>();
- openObjectInAllPacks(objectId, result, curs);
- return result;
+ public ObjectLoader open(final AnyObjectId objectId)
+ throws MissingObjectException, IOException {
+ return getObjectDatabase().open(objectId);
}
/**
- * Open object in all packs containing specified object.
+ * Open an object from this repository.
+ * <p>
+ * This is a one-shot call interface which may be faster than allocating a
+ * {@link #newObjectReader()} to perform the lookup.
*
* @param objectId
- * id of object to search for
- * @param resultLoaders
- * result collection of loaders for this object, filled with
- * loaders from all packs containing specified object
- * @param curs
- * temporary working space associated with the calling thread.
- * @throws IOException
- */
- void openObjectInAllPacks(final AnyObjectId objectId,
- final Collection<PackedObjectLoader> resultLoaders,
- final WindowCursor curs) throws IOException {
- objectDatabase.openObjectInAllPacks(resultLoaders, curs, objectId);
- }
-
- /**
- * @param id
- * SHA'1 of a blob
- * @return an {@link ObjectLoader} for accessing the data of a named blob
+ * identity of the object to open.
+ * @param typeHint
+ * hint about the type of object being requested;
+ * {@link ObjectReader#OBJ_ANY} if the object type is not known,
+ * or does not matter to the caller.
+ * @return a {@link ObjectLoader} for accessing the object.
+ * @throws MissingObjectException
+ * the object does not exist.
+ * @throws IncorrectObjectTypeException
+ * typeHint was not OBJ_ANY, and the object's actual type does
+ * not match typeHint.
* @throws IOException
+ * the object store cannot be accessed.
*/
- public ObjectLoader openBlob(final ObjectId id) throws IOException {
- return openObject(id);
- }
-
- /**
- * @param id
- * SHA'1 of a tree
- * @return an {@link ObjectLoader} for accessing the data of a named tree
- * @throws IOException
- */
- public ObjectLoader openTree(final ObjectId id) throws IOException {
- return openObject(id);
+ public ObjectLoader open(AnyObjectId objectId, int typeHint)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException {
+ return getObjectDatabase().open(objectId, typeHint);
}
/**
@@ -572,23 +298,26 @@ public class Repository {
* @deprecated Use {@link org.eclipse.jgit.revwalk.RevWalk#parseCommit(AnyObjectId)},
* or {@link org.eclipse.jgit.revwalk.RevWalk#parseTag(AnyObjectId)}.
* To read a tree, use {@link org.eclipse.jgit.treewalk.TreeWalk#addTree(AnyObjectId)}.
- * To read a blob, open it with {@link #openObject(AnyObjectId)}.
+ * To read a blob, open it with {@link #open(AnyObjectId)}.
*/
@Deprecated
public Object mapObject(final ObjectId id, final String refName) throws IOException {
- final ObjectLoader or = openObject(id);
- if (or == null)
+ final ObjectLoader or;
+ try {
+ or = open(id);
+ } catch (MissingObjectException notFound) {
return null;
- final byte[] raw = or.getBytes();
+ }
+ final byte[] raw = or.getCachedBytes();
switch (or.getType()) {
case Constants.OBJ_TREE:
- return makeTree(id, raw);
+ return new Tree(this, id, raw);
case Constants.OBJ_COMMIT:
- return makeCommit(id, raw);
+ return new Commit(this, id, raw);
case Constants.OBJ_TAG:
- return makeTag(id, refName, raw);
+ return new Tag(this, id, refName, raw);
case Constants.OBJ_BLOB:
return raw;
@@ -608,18 +337,13 @@ public class Repository {
*/
@Deprecated
public Commit mapCommit(final ObjectId id) throws IOException {
- final ObjectLoader or = openObject(id);
- if (or == null)
+ final ObjectLoader or;
+ try {
+ or = open(id, Constants.OBJ_COMMIT);
+ } catch (MissingObjectException notFound) {
return null;
- final byte[] raw = or.getBytes();
- if (Constants.OBJ_COMMIT == or.getType())
- return new Commit(this, id, raw);
- throw new IncorrectObjectTypeException(id, Constants.TYPE_COMMIT);
- }
-
- private Commit makeCommit(final ObjectId id, final byte[] raw) {
- Commit ret = new Commit(this, id, raw);
- return ret;
+ }
+ return new Commit(this, id, or.getCachedBytes());
}
/**
@@ -650,10 +374,13 @@ public class Repository {
*/
@Deprecated
public Tree mapTree(final ObjectId id) throws IOException {
- final ObjectLoader or = openObject(id);
- if (or == null)
+ final ObjectLoader or;
+ try {
+ or = open(id);
+ } catch (MissingObjectException notFound) {
return null;
- final byte[] raw = or.getBytes();
+ }
+ final byte[] raw = or.getCachedBytes();
switch (or.getType()) {
case Constants.OBJ_TREE:
return new Tree(this, id, raw);
@@ -666,16 +393,6 @@ public class Repository {
}
}
- private Tree makeTree(final ObjectId id, final byte[] raw) throws IOException {
- Tree ret = new Tree(this, id, raw);
- return ret;
- }
-
- private Tag makeTag(final ObjectId id, final String refName, final byte[] raw) {
- Tag ret = new Tag(this, id, refName, raw);
- return ret;
- }
-
/**
* Access a tag by symbolic name.
*
@@ -701,12 +418,14 @@ public class Repository {
*/
@Deprecated
public Tag mapTag(final String refName, final ObjectId id) throws IOException {
- final ObjectLoader or = openObject(id);
- if (or == null)
+ final ObjectLoader or;
+ try {
+ or = open(id);
+ } catch (MissingObjectException notFound) {
return null;
- final byte[] raw = or.getBytes();
- if (Constants.OBJ_TAG == or.getType())
- return new Tag(this, id, refName, raw);
+ }
+ if (or.getType() == Constants.OBJ_TAG)
+ return new Tag(this, id, refName, or.getCachedBytes());
return new Tag(this, id, refName, null);
}
@@ -741,7 +460,7 @@ public class Repository {
* to the base ref, as the symbolic ref could not be read.
*/
public RefUpdate updateRef(final String ref, final boolean detach) throws IOException {
- return refs.newUpdate(ref, detach);
+ return getRefDatabase().newUpdate(ref, detach);
}
/**
@@ -757,7 +476,7 @@ public class Repository {
*
*/
public RefRename renameRef(final String fromRef, final String toRef) throws IOException {
- return refs.newRename(fromRef, toRef);
+ return getRefDatabase().newRename(fromRef, toRef);
}
/**
@@ -765,36 +484,45 @@ public class Repository {
*
* Currently supported is combinations of these.
* <ul>
- * <li>SHA-1 - a SHA-1</li>
- * <li>refs/... - a ref name</li>
- * <li>ref^n - nth parent reference</li>
- * <li>ref~n - distance via parent reference</li>
- * <li>ref@{n} - nth version of ref</li>
- * <li>ref^{tree} - tree references by ref</li>
- * <li>ref^{commit} - commit references by ref</li>
+ * <li>SHA-1 - a SHA-1</li>
+ * <li>refs/... - a ref name</li>
+ * <li>ref^n - nth parent reference</li>
+ * <li>ref~n - distance via parent reference</li>
+ * <li>ref@{n} - nth version of ref</li>
+ * <li>ref^{tree} - tree references by ref</li>
+ * <li>ref^{commit} - commit references by ref</li>
* </ul>
*
- * Not supported is
+ * Not supported is:
* <ul>
* <li>timestamps in reflogs, ref@{full or relative timestamp}</li>
* <li>abbreviated SHA-1's</li>
* </ul>
*
- * @param revstr A git object references expression
+ * @param revstr
+ * A git object references expression
* @return an ObjectId or null if revstr can't be resolved to any ObjectId
- * @throws IOException on serious errors
+ * @throws IOException
+ * on serious errors
*/
public ObjectId resolve(final String revstr) throws IOException {
+ RevWalk rw = new RevWalk(this);
+ try {
+ return resolve(rw, revstr);
+ } finally {
+ rw.release();
+ }
+ }
+
+ private ObjectId resolve(final RevWalk rw, final String revstr) throws IOException {
char[] rev = revstr.toCharArray();
- Object ref = null;
- ObjectId refId = null;
+ RevObject ref = null;
for (int i = 0; i < rev.length; ++i) {
switch (rev[i]) {
case '^':
- if (refId == null) {
- String refstr = new String(rev,0,i);
- refId = resolveSimple(refstr);
- if (refId == null)
+ if (ref == null) {
+ ref = parseSimple(rw, new String(rev, 0, i));
+ if (ref == null)
return null;
}
if (i + 1 < rev.length) {
@@ -810,19 +538,12 @@ public class Repository {
case '8':
case '9':
int j;
- ref = mapObject(refId, null);
- while (ref instanceof Tag) {
- Tag tag = (Tag)ref;
- refId = tag.getObjId();
- ref = mapObject(refId, null);
- }
- if (!(ref instanceof Commit))
- throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT);
- for (j=i+1; j<rev.length; ++j) {
+ ref = rw.parseCommit(ref);
+ for (j = i + 1; j < rev.length; ++j) {
if (!Character.isDigit(rev[j]))
break;
}
- String parentnum = new String(rev, i+1, j-i-1);
+ String parentnum = new String(rev, i + 1, j - i - 1);
int pnum;
try {
pnum = Integer.parseInt(parentnum);
@@ -832,123 +553,83 @@ public class Repository {
revstr);
}
if (pnum != 0) {
- final ObjectId parents[] = ((Commit) ref)
- .getParentIds();
- if (pnum > parents.length)
- refId = null;
+ RevCommit commit = (RevCommit) ref;
+ if (pnum > commit.getParentCount())
+ ref = null;
else
- refId = parents[pnum - 1];
+ ref = commit.getParent(pnum - 1);
}
i = j - 1;
break;
case '{':
int k;
String item = null;
- for (k=i+2; k<rev.length; ++k) {
+ for (k = i + 2; k < rev.length; ++k) {
if (rev[k] == '}') {
- item = new String(rev, i+2, k-i-2);
+ item = new String(rev, i + 2, k - i - 2);
break;
}
}
i = k;
if (item != null)
if (item.equals("tree")) {
- ref = mapObject(refId, null);
- while (ref instanceof Tag) {
- Tag t = (Tag)ref;
- refId = t.getObjId();
- ref = mapObject(refId, null);
- }
- if (ref instanceof Treeish)
- refId = ((Treeish)ref).getTreeId();
- else
- throw new IncorrectObjectTypeException(refId, Constants.TYPE_TREE);
- }
- else if (item.equals("commit")) {
- ref = mapObject(refId, null);
- while (ref instanceof Tag) {
- Tag t = (Tag)ref;
- refId = t.getObjId();
- ref = mapObject(refId, null);
- }
- if (!(ref instanceof Commit))
- throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT);
- }
- else if (item.equals("blob")) {
- ref = mapObject(refId, null);
- while (ref instanceof Tag) {
- Tag t = (Tag)ref;
- refId = t.getObjId();
- ref = mapObject(refId, null);
- }
- if (!(ref instanceof byte[]))
- throw new IncorrectObjectTypeException(refId, Constants.TYPE_BLOB);
- }
- else if (item.equals("")) {
- ref = mapObject(refId, null);
- while (ref instanceof Tag) {
- Tag t = (Tag)ref;
- refId = t.getObjId();
- ref = mapObject(refId, null);
- }
- }
- else
+ ref = rw.parseTree(ref);
+ } else if (item.equals("commit")) {
+ ref = rw.parseCommit(ref);
+ } else if (item.equals("blob")) {
+ ref = rw.peel(ref);
+ if (!(ref instanceof RevBlob))
+ throw new IncorrectObjectTypeException(ref,
+ Constants.TYPE_BLOB);
+ } else if (item.equals("")) {
+ ref = rw.peel(ref);
+ } else
throw new RevisionSyntaxException(revstr);
else
throw new RevisionSyntaxException(revstr);
break;
default:
- ref = mapObject(refId, null);
- if (ref instanceof Commit) {
- final ObjectId parents[] = ((Commit) ref)
- .getParentIds();
- if (parents.length == 0)
- refId = null;
+ ref = rw.parseAny(ref);
+ if (ref instanceof RevCommit) {
+ RevCommit commit = ((RevCommit) ref);
+ if (commit.getParentCount() == 0)
+ ref = null;
else
- refId = parents[0];
+ ref = commit.getParent(0);
} else
- throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT);
+ throw new IncorrectObjectTypeException(ref,
+ Constants.TYPE_COMMIT);
}
} else {
- ref = mapObject(refId, null);
- while (ref instanceof Tag) {
- Tag tag = (Tag)ref;
- refId = tag.getObjId();
- ref = mapObject(refId, null);
- }
- if (ref instanceof Commit) {
- final ObjectId parents[] = ((Commit) ref)
- .getParentIds();
- if (parents.length == 0)
- refId = null;
+ ref = rw.peel(ref);
+ if (ref instanceof RevCommit) {
+ RevCommit commit = ((RevCommit) ref);
+ if (commit.getParentCount() == 0)
+ ref = null;
else
- refId = parents[0];
+ ref = commit.getParent(0);
} else
- throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT);
+ throw new IncorrectObjectTypeException(ref,
+ Constants.TYPE_COMMIT);
}
break;
case '~':
if (ref == null) {
- String refstr = new String(rev,0,i);
- refId = resolveSimple(refstr);
- if (refId == null)
+ ref = parseSimple(rw, new String(rev, 0, i));
+ if (ref == null)
return null;
- ref = mapObject(refId, null);
}
- while (ref instanceof Tag) {
- Tag tag = (Tag)ref;
- refId = tag.getObjId();
- ref = mapObject(refId, null);
- }
- if (!(ref instanceof Commit))
- throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT);
+ ref = rw.peel(ref);
+ if (!(ref instanceof RevCommit))
+ throw new IncorrectObjectTypeException(ref,
+ Constants.TYPE_COMMIT);
int l;
for (l = i + 1; l < rev.length; ++l) {
if (!Character.isDigit(rev[l]))
break;
}
- String distnum = new String(rev, i+1, l-i-1);
+ String distnum = new String(rev, i + 1, l - i - 1);
int dist;
try {
dist = Integer.parseInt(distnum);
@@ -957,13 +638,14 @@ public class Repository {
JGitText.get().invalidAncestryLength, revstr);
}
while (dist > 0) {
- final ObjectId[] parents = ((Commit) ref).getParentIds();
- if (parents.length == 0) {
- refId = null;
+ RevCommit commit = (RevCommit) ref;
+ if (commit.getParentCount() == 0) {
+ ref = null;
break;
}
- refId = parents[0];
- ref = mapCommit(refId);
+ commit = commit.getParent(0);
+ rw.parseHeaders(commit);
+ ref = commit;
--dist;
}
i = l - 1;
@@ -971,30 +653,35 @@ public class Repository {
case '@':
int m;
String time = null;
- for (m=i+2; m<rev.length; ++m) {
+ for (m = i + 2; m < rev.length; ++m) {
if (rev[m] == '}') {
- time = new String(rev, i+2, m-i-2);
+ time = new String(rev, i + 2, m - i - 2);
break;
}
}
if (time != null)
- throw new RevisionSyntaxException(JGitText.get().reflogsNotYetSupportedByRevisionParser, revstr);
+ throw new RevisionSyntaxException(
+ JGitText.get().reflogsNotYetSupportedByRevisionParser,
+ revstr);
i = m - 1;
break;
default:
- if (refId != null)
+ if (ref != null)
throw new RevisionSyntaxException(revstr);
}
}
- if (refId == null)
- refId = resolveSimple(revstr);
- return refId;
+ return ref != null ? ref.copy() : resolveSimple(revstr);
+ }
+
+ private RevObject parseSimple(RevWalk rw, String revstr) throws IOException {
+ ObjectId id = resolveSimple(revstr);
+ return id != null ? rw.parseAny(id) : null;
}
private ObjectId resolveSimple(final String revstr) throws IOException {
if (ObjectId.isId(revstr))
return ObjectId.fromString(revstr);
- final Ref r = refs.getRef(revstr);
+ final Ref r = getRefDatabase().getRef(revstr);
return r != null ? r.getObjectId() : null;
}
@@ -1003,17 +690,24 @@ public class Repository {
useCnt.incrementAndGet();
}
- /**
- * Close all resources used by this repository
- */
+ /** Decrement the use count, and maybe close resources. */
public void close() {
if (useCnt.decrementAndGet() == 0) {
- objectDatabase.close();
- refs.close();
+ doClose();
}
}
/**
+ * Invoked when the use count drops to zero during {@link #close()}.
+ * <p>
+ * The default implementation closes the object and ref databases.
+ */
+ protected void doClose() {
+ getObjectDatabase().close();
+ getRefDatabase().close();
+ }
+
+ /**
* Add a single existing pack to the list of available pack files.
*
* @param pack
@@ -1024,12 +718,16 @@ public class Repository {
* index file could not be opened, read, or is not recognized as
* a Git pack file index.
*/
- public void openPack(final File pack, final File idx) throws IOException {
- objectDatabase.openPack(pack, idx);
- }
+ public abstract void openPack(File pack, File idx) throws IOException;
public String toString() {
- return "Repository[" + getDirectory() + "]";
+ String desc;
+ if (getDirectory() != null)
+ desc = getDirectory().getPath();
+ else
+ desc = getClass().getSimpleName() + "-"
+ + System.identityHashCode(this);
+ return "Repository[" + desc + "]";
}
/**
@@ -1078,6 +776,20 @@ public class Repository {
}
/**
+ * Objects known to exist but not expressed by {@link #getAllRefs()}.
+ * <p>
+ * When a repository borrows objects from another repository, it can
+ * advertise that it safely has that other repository's references, without
+ * exposing any other details about the other repository. This may help
+ * a client trying to push changes avoid pushing more than it needs to.
+ *
+ * @return unmodifiable collection of other known objects.
+ */
+ public Set<ObjectId> getAdditionalHaves() {
+ return Collections.emptySet();
+ }
+
+ /**
* Get a ref by name.
*
* @param name
@@ -1088,7 +800,7 @@ public class Repository {
* @throws IOException
*/
public Ref getRef(final String name) throws IOException {
- return refs.getRef(name);
+ return getRefDatabase().getRef(name);
}
/**
@@ -1096,7 +808,7 @@ public class Repository {
*/
public Map<String, Ref> getAllRefs() {
try {
- return refs.getRefs(RefDatabase.ALL);
+ return getRefDatabase().getRefs(RefDatabase.ALL);
} catch (IOException e) {
return new HashMap<String, Ref>();
}
@@ -1109,7 +821,7 @@ public class Repository {
*/
public Map<String, Ref> getTags() {
try {
- return refs.getRefs(Constants.R_TAGS);
+ return getRefDatabase().getRefs(Constants.R_TAGS);
} catch (IOException e) {
return new HashMap<String, Ref>();
}
@@ -1130,7 +842,7 @@ public class Repository {
*/
public Ref peel(final Ref ref) {
try {
- return refs.peel(ref);
+ return getRefDatabase().peel(ref);
} catch (IOException e) {
// Historical accident; if the reference cannot be peeled due
// to some sort of repository access problem we claim that the
@@ -1170,13 +882,13 @@ public class Repository {
* {@link Repository}
* @throws IOException
* if the index can not be read
- * @throws IllegalStateException
- * if this is bare (see {@link #isBare()})
+ * @throws NoWorkTreeException
+ * if this is bare, which implies it has no working directory.
+ * See {@link #isBare()}.
*/
- public GitIndex getIndex() throws IOException, IllegalStateException {
+ public GitIndex getIndex() throws IOException, NoWorkTreeException {
if (isBare())
- throw new IllegalStateException(
- JGitText.get().bareRepositoryNoWorkdirAndIndex);
+ throw new NoWorkTreeException();
if (index == null) {
index = new GitIndex(this);
index.read();
@@ -1188,16 +900,63 @@ public class Repository {
/**
* @return the index file location
- * @throws IllegalStateException
- * if this is bare (see {@link #isBare()})
+ * @throws NoWorkTreeException
+ * if this is bare, which implies it has no working directory.
+ * See {@link #isBare()}.
*/
- public File getIndexFile() throws IllegalStateException {
+ public File getIndexFile() throws NoWorkTreeException {
if (isBare())
- throw new IllegalStateException(
- JGitText.get().bareRepositoryNoWorkdirAndIndex);
+ throw new NoWorkTreeException();
return indexFile;
}
+ /**
+ * Create a new in-core index representation and read an index from disk.
+ * <p>
+ * The new index will be read before it is returned to the caller. Read
+ * failures are reported as exceptions and therefore prevent the method from
+ * returning a partially populated index.
+ *
+ * @return a cache representing the contents of the specified index file (if
+ * it exists) or an empty cache if the file does not exist.
+ * @throws NoWorkTreeException
+ * if this is bare, which implies it has no working directory.
+ * See {@link #isBare()}.
+ * @throws IOException
+ * the index file is present but could not be read.
+ * @throws CorruptObjectException
+ * the index file is using a format or extension that this
+ * library does not support.
+ */
+ public DirCache readDirCache() throws NoWorkTreeException,
+ CorruptObjectException, IOException {
+ return DirCache.read(getIndexFile());
+ }
+
+ /**
+ * Create a new in-core index representation, lock it, and read from disk.
+ * <p>
+ * The new index will be locked and then read before it is returned to the
+ * caller. Read failures are reported as exceptions and therefore prevent
+ * the method from returning a partially populated index.
+ *
+ * @return a cache representing the contents of the specified index file (if
+ * it exists) or an empty cache if the file does not exist.
+ * @throws NoWorkTreeException
+ * if this is bare, which implies it has no working directory.
+ * See {@link #isBare()}.
+ * @throws IOException
+ * the index file is present but could not be read, or the lock
+ * could not be obtained.
+ * @throws CorruptObjectException
+ * the index file is using a format or extension that this
+ * library does not support.
+ */
+ public DirCache lockDirCache() throws NoWorkTreeException,
+ CorruptObjectException, IOException {
+ return DirCache.lock(getIndexFile());
+ }
+
static byte[] gitInternalSlash(byte[] bytes) {
if (File.separatorChar == '/')
return bytes;
@@ -1211,10 +970,13 @@ public class Repository {
* @return an important state
*/
public RepositoryState getRepositoryState() {
+ if (isBare() || getDirectory() == null)
+ return RepositoryState.BARE;
+
// Pre Git-1.6 logic
- if (new File(getWorkDir(), ".dotest").exists())
+ if (new File(getWorkTree(), ".dotest").exists())
return RepositoryState.REBASING;
- if (new File(gitDir,".dotest-merge").exists())
+ if (new File(getDirectory(), ".dotest-merge").exists())
return RepositoryState.REBASING_INTERACTIVE;
// From 1.6 onwards
@@ -1231,10 +993,10 @@ public class Repository {
return RepositoryState.REBASING_MERGE;
// Both versions
- if (new File(gitDir, "MERGE_HEAD").exists()) {
+ if (new File(getDirectory(), "MERGE_HEAD").exists()) {
// we are merging - now check whether we have unmerged paths
try {
- if (!DirCache.read(this).hasUnmergedPaths()) {
+ if (!readDirCache().hasUnmergedPaths()) {
// no unmerged paths -> return the MERGING_RESOLVED state
return RepositoryState.MERGING_RESOLVED;
}
@@ -1247,7 +1009,7 @@ public class Repository {
return RepositoryState.MERGING;
}
- if (new File(gitDir,"BISECT_LOG").exists())
+ if (new File(getDirectory(), "BISECT_LOG").exists())
return RepositoryState.BISECTING;
return RepositoryState.SAFE;
@@ -1334,96 +1096,23 @@ public class Repository {
}
/**
- * @return the "bare"-ness of this Repository
+ * @return true if this is bare, which implies it has no working directory.
*/
public boolean isBare() {
- return workDir == null;
+ return workTree == null;
}
/**
- * @return the workdir file, i.e. where the files are checked out
- * @throws IllegalStateException
- * if the repository is "bare"
+ * @return the root directory of the working tree, where files are checked
+ * out for viewing and editing.
+ * @throws NoWorkTreeException
+ * if this is bare, which implies it has no working directory.
+ * See {@link #isBare()}.
*/
- public File getWorkDir() throws IllegalStateException {
+ public File getWorkTree() throws NoWorkTreeException {
if (isBare())
- throw new IllegalStateException(
- JGitText.get().bareRepositoryNoWorkdirAndIndex);
- return workDir;
- }
-
- /**
- * Override default workdir
- *
- * @param workTree
- * the work tree directory
- */
- public void setWorkDir(File workTree) {
- this.workDir = workTree;
- }
-
- /**
- * Register a {@link RepositoryListener} which will be notified
- * when ref changes are detected.
- *
- * @param l
- */
- public void addRepositoryChangedListener(final RepositoryListener l) {
- listeners.add(l);
- }
-
- /**
- * Remove a registered {@link RepositoryListener}
- * @param l
- */
- public void removeRepositoryChangedListener(final RepositoryListener l) {
- listeners.remove(l);
- }
-
- /**
- * Register a global {@link RepositoryListener} which will be notified
- * when a ref changes in any repository are detected.
- *
- * @param l
- */
- public static void addAnyRepositoryChangedListener(final RepositoryListener l) {
- allListeners.add(l);
- }
-
- /**
- * Remove a globally registered {@link RepositoryListener}
- * @param l
- */
- public static void removeAnyRepositoryChangedListener(final RepositoryListener l) {
- allListeners.remove(l);
- }
-
- void fireRefsChanged() {
- final RefsChangedEvent event = new RefsChangedEvent(this);
- List<RepositoryListener> all;
- synchronized (listeners) {
- all = new ArrayList<RepositoryListener>(listeners);
- }
- synchronized (allListeners) {
- all.addAll(allListeners);
- }
- for (final RepositoryListener l : all) {
- l.refsChanged(event);
- }
- }
-
- void fireIndexChanged() {
- final IndexChangedEvent event = new IndexChangedEvent(this);
- List<RepositoryListener> all;
- synchronized (listeners) {
- all = new ArrayList<RepositoryListener>(listeners);
- }
- synchronized (allListeners) {
- all.addAll(allListeners);
- }
- for (final RepositoryListener l : all) {
- l.indexChanged(event);
- }
+ throw new NoWorkTreeException();
+ return workTree;
}
/**
@@ -1431,11 +1120,7 @@ public class Repository {
*
* @throws IOException
*/
- public void scanForRepoChanges() throws IOException {
- getAllRefs(); // This will look for changes to refs
- if (!isBare())
- getIndex(); // This will detect changes in the index
- }
+ public abstract void scanForRepoChanges() throws IOException;
/**
* @param refName
@@ -1458,12 +1143,8 @@ public class Repository {
* named ref does not exist.
* @throws IOException the ref could not be accessed.
*/
- public ReflogReader getReflogReader(String refName) throws IOException {
- Ref ref = getRef(refName);
- if (ref != null)
- return new ReflogReader(this, ref.getName());
- return null;
- }
+ public abstract ReflogReader getReflogReader(String refName)
+ throws IOException;
/**
* Return the information stored in the file $GIT_DIR/MERGE_MSG. In this
@@ -1473,9 +1154,15 @@ public class Repository {
* @return a String containing the content of the MERGE_MSG file or
* {@code null} if this file doesn't exist
* @throws IOException
+ * @throws NoWorkTreeException
+ * if this is bare, which implies it has no working directory.
+ * See {@link #isBare()}.
*/
- public String readMergeCommitMsg() throws IOException {
- File mergeMsgFile = new File(gitDir, Constants.MERGE_MSG);
+ public String readMergeCommitMsg() throws IOException, NoWorkTreeException {
+ if (isBare() || getDirectory() == null)
+ throw new NoWorkTreeException();
+
+ File mergeMsgFile = new File(getDirectory(), Constants.MERGE_MSG);
try {
return new String(IO.readFully(mergeMsgFile));
} catch (FileNotFoundException e) {
@@ -1494,9 +1181,15 @@ public class Repository {
* file or {@code null} if this file doesn't exist. Also if the file
* exists but is empty {@code null} will be returned
* @throws IOException
+ * @throws NoWorkTreeException
+ * if this is bare, which implies it has no working directory.
+ * See {@link #isBare()}.
*/
- public List<ObjectId> readMergeHeads() throws IOException {
- File mergeHeadFile = new File(gitDir, Constants.MERGE_HEAD);
+ public List<ObjectId> readMergeHeads() throws IOException, NoWorkTreeException {
+ if (isBare() || getDirectory() == null)
+ throw new NoWorkTreeException();
+
+ File mergeHeadFile = new File(getDirectory(), Constants.MERGE_HEAD);
byte[] raw;
try {
raw = IO.readFully(mergeHeadFile);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryBuilder.java
new file mode 100644
index 0000000000..f9185e8f26
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryBuilder.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.lib;
+
+import java.io.File;
+
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+
+/**
+ * Base class to support constructing a {@link Repository}.
+ * <p>
+ * Applications must set one of {@link #setGitDir(File)} or
+ * {@link #setWorkTree(File)}, or use {@link #readEnvironment()} or
+ * {@link #findGitDir()} in order to configure the minimum property set
+ * necessary to open a repository.
+ * <p>
+ * Single repository applications trying to be compatible with other Git
+ * implementations are encouraged to use a model such as:
+ *
+ * <pre>
+ * new RepositoryBuilder() //
+ * .setGitDir(gitDirArgument) // --git-dir if supplied, no-op if null
+ * .readEnviroment() // scan environment GIT_* variables
+ * .findGitDir() // scan up the file system tree
+ * .build()
+ * </pre>
+ *
+ * @see FileRepositoryBuilder
+ */
+public class RepositoryBuilder extends
+ BaseRepositoryBuilder<RepositoryBuilder, Repository> {
+ // Empty implementation, everything is inherited.
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
index 0b0260a4cc..dc5eae5173 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
@@ -52,6 +52,7 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
@@ -120,7 +121,10 @@ public class RepositoryCache {
* repository to register.
*/
public static void register(final Repository db) {
- cache.registerRepository(FileKey.exact(db.getDirectory(), db.getFS()), db);
+ if (db.getDirectory() != null) {
+ FileKey key = FileKey.exact(db.getDirectory(), db.getFS());
+ cache.registerRepository(key, db);
+ }
}
/**
@@ -133,7 +137,10 @@ public class RepositoryCache {
* repository to unregister.
*/
public static void close(final Repository db) {
- cache.unregisterRepository(FileKey.exact(db.getDirectory(), db.getFS()));
+ if (db.getDirectory() != null) {
+ FileKey key = FileKey.exact(db.getDirectory(), db.getFS());
+ cache.unregisterRepository(key);
+ }
}
/** Unregister all repositories from the cache. */
@@ -313,7 +320,7 @@ public class RepositoryCache {
public Repository open(final boolean mustExist) throws IOException {
if (mustExist && !isGitRepository(path, fs))
throw new RepositoryNotFoundException(path);
- return new Repository(path);
+ return new FileRepository(path);
}
@Override
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java
deleted file mode 100644
index 805975a8d1..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryConfig.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
- * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
- * Copyright (C) 2008-2009, Google Inc.
- * Copyright (C) 2009, JetBrains s.r.o.
- * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
- * Copyright (C) 2008, Thad Hughes <thadh@thad.corp.google.com>
- * Copyright (C) 2009, Yann Simon <yann.simon.fr@gmail.com>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.File;
-
-/**
- * An object representing the Git config file.
- *
- * This can be either the repository specific file or the user global
- * file depending on how it is instantiated.
- */
-public class RepositoryConfig extends FileBasedConfig {
- /** Section name for a branch configuration. */
- public static final String BRANCH_SECTION = "branch";
-
- /**
- * Create a Git configuration file reader/writer/cache for a specific file.
- *
- * @param base
- * configuration that provides default values if this file does
- * not set/override a particular key. Often this is the user's
- * global configuration file, or the system level configuration.
- * @param cfgLocation
- * path of the file to load (or save).
- */
- public RepositoryConfig(final Config base, final File cfgLocation) {
- super(base, cfgLocation);
- }
-
- /**
- * @return Core configuration values
- */
- public CoreConfig getCore() {
- return get(CoreConfig.KEY);
- }
-
- /**
- * @return transfer, fetch and receive configuration values
- */
- public TransferConfig getTransfer() {
- return get(TransferConfig.KEY);
- }
-
- /** @return standard user configuration data */
- public UserConfig getUserConfig() {
- return get(UserConfig.KEY);
- }
-
- /**
- * @return the author name as defined in the git variables
- * and configurations. If no name could be found, try
- * to use the system user name instead.
- */
- public String getAuthorName() {
- return getUserConfig().getAuthorName();
- }
-
- /**
- * @return the committer name as defined in the git variables
- * and configurations. If no name could be found, try
- * to use the system user name instead.
- */
- public String getCommitterName() {
- return getUserConfig().getCommitterName();
- }
-
- /**
- * @return the author email as defined in git variables and
- * configurations. If no email could be found, try to
- * propose one default with the user name and the
- * host name.
- */
- public String getAuthorEmail() {
- return getUserConfig().getAuthorEmail();
- }
-
- /**
- * @return the committer email as defined in git variables and
- * configurations. If no email could be found, try to
- * propose one default with the user name and the
- * host name.
- */
- public String getCommitterEmail() {
- return getUserConfig().getCommitterEmail();
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java
index 2cf5225793..0a59906e94 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java
@@ -55,6 +55,14 @@ import org.eclipse.jgit.JGitText;
* on the state are the only supported means of deciding what to do.
*/
public enum RepositoryState {
+ /** Has no work tree and cannot be used for normal editing. */
+ BARE {
+ public boolean canCheckout() { return false; }
+ public boolean canResetHead() { return false; }
+ public boolean canCommit() { return false; }
+ public String getDescription() { return "Bare"; }
+ },
+
/**
* A safe state for working normally
* */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tag.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tag.java
index 5b3531eb1f..25a06c9c6c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tag.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tag.java
@@ -203,9 +203,14 @@ public class Tag {
final RefUpdate ru;
if (tagger!=null || message!=null || type!=null) {
- ObjectId tagid = new ObjectWriter(objdb).writeTag(this);
- setTagId(tagid);
- id = tagid;
+ ObjectInserter odi = objdb.newObjectInserter();
+ try {
+ id = odi.insert(Constants.OBJ_TAG, odi.format(this));
+ odi.flush();
+ setTagId(id);
+ } finally {
+ odi.release();
+ }
} else {
id = objId;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java
new file mode 100644
index 0000000000..9708bb2f92
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.lib;
+
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Wrapper around the general {@link ProgressMonitor} to make it thread safe.
+ */
+public class ThreadSafeProgressMonitor implements ProgressMonitor {
+ private final ProgressMonitor pm;
+
+ private final ReentrantLock lock;
+
+ /**
+ * Wrap a ProgressMonitor to be thread safe.
+ *
+ * @param pm
+ * the underlying monitor to receive events.
+ */
+ public ThreadSafeProgressMonitor(ProgressMonitor pm) {
+ this.pm = pm;
+ this.lock = new ReentrantLock();
+ }
+
+ public void start(int totalTasks) {
+ lock.lock();
+ try {
+ pm.start(totalTasks);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void beginTask(String title, int totalWork) {
+ lock.lock();
+ try {
+ pm.beginTask(title, totalWork);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void update(int completed) {
+ lock.lock();
+ try {
+ pm.update(completed);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean isCancelled() {
+ lock.lock();
+ try {
+ return pm.isCancelled();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void endTask() {
+ lock.lock();
+ try {
+ pm.endTask();
+ } finally {
+ lock.unlock();
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tree.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tree.java
index 0872c96250..d68b9f6380 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tree.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tree.java
@@ -537,10 +537,8 @@ public class Tree extends TreeEntry implements Treeish {
private void ensureLoaded() throws IOException, MissingObjectException {
if (!isLoaded()) {
- final ObjectLoader or = db.openTree(getId());
- if (or == null)
- throw new MissingObjectException(getId(), Constants.TYPE_TREE);
- readTree(or.getBytes());
+ ObjectLoader ldr = db.open(getId(), Constants.OBJ_TREE);
+ readTree(ldr.getCachedBytes());
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/UnpackedObjectLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/UnpackedObjectLoader.java
deleted file mode 100644
index cd2eb38ef1..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/UnpackedObjectLoader.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.zip.DataFormatException;
-import java.util.zip.Inflater;
-
-import org.eclipse.jgit.JGitText;
-import org.eclipse.jgit.errors.CorruptObjectException;
-import org.eclipse.jgit.util.IO;
-import org.eclipse.jgit.util.MutableInteger;
-import org.eclipse.jgit.util.RawParseUtils;
-
-/**
- * Loose object loader. This class loads an object not stored in a pack.
- */
-public class UnpackedObjectLoader extends ObjectLoader {
- private final int objectType;
-
- private final int objectSize;
-
- private final byte[] bytes;
-
- /**
- * Construct an ObjectLoader to read from the file.
- *
- * @param path
- * location of the loose object to read.
- * @param id
- * expected identity of the object being loaded, if known.
- * @throws FileNotFoundException
- * the loose object file does not exist.
- * @throws IOException
- * the loose object file exists, but is corrupt.
- */
- public UnpackedObjectLoader(final File path, final AnyObjectId id)
- throws IOException {
- this(IO.readFully(path), id);
- }
-
- /**
- * Construct an ObjectLoader from a loose object's compressed form.
- *
- * @param compressed
- * entire content of the loose object file.
- * @throws CorruptObjectException
- * The compressed data supplied does not match the format for a
- * valid loose object.
- */
- public UnpackedObjectLoader(final byte[] compressed)
- throws CorruptObjectException {
- this(compressed, null);
- }
-
- private UnpackedObjectLoader(final byte[] compressed, final AnyObjectId id)
- throws CorruptObjectException {
- // Try to determine if this is a legacy format loose object or
- // a new style loose object. The legacy format was completely
- // compressed with zlib so the first byte must be 0x78 (15-bit
- // window size, deflated) and the first 16 bit word must be
- // evenly divisible by 31. Otherwise its a new style loose
- // object.
- //
- final Inflater inflater = InflaterCache.get();
- try {
- final int fb = compressed[0] & 0xff;
- if (fb == 0x78 && (((fb << 8) | compressed[1] & 0xff) % 31) == 0) {
- inflater.setInput(compressed);
- final byte[] hdr = new byte[64];
- int avail = 0;
- while (!inflater.finished() && avail < hdr.length)
- try {
- int uncompressed = inflater.inflate(hdr, avail,
- hdr.length - avail);
- if (uncompressed == 0) {
- throw new CorruptObjectException(id,
- JGitText.get().corruptObjectBadStreamCorruptHeader);
- }
- avail += uncompressed;
- } catch (DataFormatException dfe) {
- final CorruptObjectException coe;
- coe = new CorruptObjectException(id, JGitText.get().corruptObjectBadStream);
- coe.initCause(dfe);
- throw coe;
- }
- if (avail < 5)
- throw new CorruptObjectException(id, JGitText.get().corruptObjectNoHeader);
-
- final MutableInteger p = new MutableInteger();
- objectType = Constants.decodeTypeString(id, hdr, (byte) ' ', p);
- objectSize = RawParseUtils.parseBase10(hdr, p.value, p);
- if (objectSize < 0)
- throw new CorruptObjectException(id, JGitText.get().corruptObjectNegativeSize);
- if (hdr[p.value++] != 0)
- throw new CorruptObjectException(id, JGitText.get().corruptObjectGarbageAfterSize);
- bytes = new byte[objectSize];
- if (p.value < avail)
- System.arraycopy(hdr, p.value, bytes, 0, avail - p.value);
- decompress(id, inflater, avail - p.value);
- } else {
- int p = 0;
- int c = compressed[p++] & 0xff;
- final int typeCode = (c >> 4) & 7;
- int size = c & 15;
- int shift = 4;
- while ((c & 0x80) != 0) {
- c = compressed[p++] & 0xff;
- size += (c & 0x7f) << shift;
- shift += 7;
- }
-
- switch (typeCode) {
- case Constants.OBJ_COMMIT:
- case Constants.OBJ_TREE:
- case Constants.OBJ_BLOB:
- case Constants.OBJ_TAG:
- objectType = typeCode;
- break;
- default:
- throw new CorruptObjectException(id, JGitText.get().corruptObjectInvalidType);
- }
-
- objectSize = size;
- bytes = new byte[objectSize];
- inflater.setInput(compressed, p, compressed.length - p);
- decompress(id, inflater, 0);
- }
- } finally {
- InflaterCache.release(inflater);
- }
- }
-
- private void decompress(final AnyObjectId id, final Inflater inf, int p)
- throws CorruptObjectException {
- try {
- while (!inf.finished()) {
- int uncompressed = inf.inflate(bytes, p, objectSize - p);
- p += uncompressed;
- if (uncompressed == 0 && !inf.finished()) {
- throw new CorruptObjectException(id,
- JGitText.get().corruptObjectBadStreamCorruptHeader);
- }
- }
- } catch (DataFormatException dfe) {
- final CorruptObjectException coe;
- coe = new CorruptObjectException(id, JGitText.get().corruptObjectBadStream);
- coe.initCause(dfe);
- throw coe;
- }
- if (p != objectSize)
- throw new CorruptObjectException(id, JGitText.get().corruptObjectIncorrectLength);
- }
-
- @Override
- public int getType() {
- return objectType;
- }
-
- @Override
- public long getSize() {
- return objectSize;
- }
-
- @Override
- public byte[] getCachedBytes() {
- return bytes;
- }
-
- @Override
- public int getRawType() {
- return objectType;
- }
-
- @Override
- public long getRawSize() {
- return objectSize;
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/WholePackedObjectLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/WholePackedObjectLoader.java
deleted file mode 100644
index fcfa57339e..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/WholePackedObjectLoader.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2008-2009, Google Inc.
- * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
- * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-import java.text.MessageFormat;
-import java.util.zip.DataFormatException;
-
-import org.eclipse.jgit.JGitText;
-import org.eclipse.jgit.errors.CorruptObjectException;
-
-/** Reader for a non-delta (just deflated) object in a pack file. */
-class WholePackedObjectLoader extends PackedObjectLoader {
- private static final int OBJ_COMMIT = Constants.OBJ_COMMIT;
-
- WholePackedObjectLoader(final PackFile pr, final long objectOffset,
- final int headerSize, final int type, final int size) {
- super(pr, objectOffset, headerSize);
- objectType = type;
- objectSize = size;
- }
-
- @Override
- public void materialize(final WindowCursor curs) throws IOException {
- if (cachedBytes != null) {
- return;
- }
-
- if (objectType != OBJ_COMMIT) {
- UnpackedObjectCache.Entry cache = pack.readCache(objectOffset);
- if (cache != null) {
- curs.release();
- cachedBytes = cache.data;
- return;
- }
- }
-
- try {
- cachedBytes = pack.decompress(objectOffset + headerSize,
- objectSize, curs);
- curs.release();
- if (objectType != OBJ_COMMIT)
- pack.saveCache(objectOffset, cachedBytes, objectType);
- } catch (DataFormatException dfe) {
- final CorruptObjectException coe;
- coe = new CorruptObjectException(MessageFormat.format(JGitText.get().objectAtHasBadZlibStream,
- objectOffset, pack.getPackFile()));
- coe.initCause(dfe);
- throw coe;
- }
- }
-
- @Override
- public int getRawType() {
- return objectType;
- }
-
- @Override
- public long getRawSize() {
- return objectSize;
- }
-
- @Override
- public ObjectId getDeltaBase() {
- return null;
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java
index 38af20fb8f..68d60c0077 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java
@@ -51,9 +51,9 @@ import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.WindowCursor;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTree;
@@ -70,10 +70,13 @@ public abstract class Merger {
/** The repository this merger operates on. */
protected final Repository db;
+ /** Reader to support {@link #walk} and other object loading. */
+ protected final ObjectReader reader;
+
/** A RevWalk for computing merge bases, or listing incoming commits. */
protected final RevWalk walk;
- private ObjectWriter writer;
+ private ObjectInserter inserter;
/** The original objects supplied in the merge; this can be any tree-ish. */
protected RevObject[] sourceObjects;
@@ -92,7 +95,8 @@ public abstract class Merger {
*/
protected Merger(final Repository local) {
db = local;
- walk = new RevWalk(db);
+ reader = db.newObjectReader();
+ walk = new RevWalk(reader);
}
/**
@@ -105,10 +109,10 @@ public abstract class Merger {
/**
* @return an object writer to create objects in {@link #getRepository()}.
*/
- public ObjectWriter getObjectWriter() {
- if (writer == null)
- writer = new ObjectWriter(getRepository());
- return writer;
+ public ObjectInserter getObjectInserter() {
+ if (inserter == null)
+ inserter = getRepository().newObjectInserter();
+ return inserter;
}
/**
@@ -148,7 +152,13 @@ public abstract class Merger {
for (int i = 0; i < sourceObjects.length; i++)
sourceTrees[i] = walk.parseTree(sourceObjects[i]);
- return mergeImpl();
+ try {
+ return mergeImpl();
+ } finally {
+ if (inserter != null)
+ inserter.release();
+ reader.release();
+ }
}
/**
@@ -202,12 +212,7 @@ public abstract class Merger {
*/
protected AbstractTreeIterator openTree(final AnyObjectId treeId)
throws IncorrectObjectTypeException, IOException {
- final WindowCursor curs = new WindowCursor();
- try {
- return new CanonicalTreeParser(null, db, treeId, curs);
- } finally {
- curs.release();
- }
+ return new CanonicalTreeParser(null, reader, treeId);
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java
index 6cd244599e..29342a7308 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java
@@ -51,6 +51,7 @@ import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.errors.UnmergedPathException;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.NameConflictTreeWalk;
@@ -99,7 +100,7 @@ public class StrategySimpleTwoWayInCore extends ThreeWayMergeStrategy {
InCoreMerger(final Repository local) {
super(local);
- tw = new NameConflictTreeWalk(db);
+ tw = new NameConflictTreeWalk(reader);
cache = DirCache.newInCore();
}
@@ -152,7 +153,9 @@ public class StrategySimpleTwoWayInCore extends ThreeWayMergeStrategy {
if (hasConflict)
return false;
try {
- resultTree = cache.writeTree(getObjectWriter());
+ ObjectInserter odi = getObjectInserter();
+ resultTree = cache.writeTree(odi);
+ odi.flush();
return true;
} catch (UnmergedPathException upe) {
resultTree = null;
@@ -168,7 +171,7 @@ public class StrategySimpleTwoWayInCore extends ThreeWayMergeStrategy {
final AbstractTreeIterator i = getTree(tree);
if (i != null) {
if (FileMode.TREE.equals(tw.getRawMode(tree))) {
- builder.addTree(tw.getRawPath(), stage, db, tw
+ builder.addTree(tw.getRawPath(), stage, reader, tw
.getObjectId(tree));
} else {
final DirCacheEntry e;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java
index 6b4ed80e15..476592f5d9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java
@@ -53,12 +53,13 @@ import java.util.Set;
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
-import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.Tag;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevSort;
+import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
/** Specialized RevWalk for visualization of a commit graph. */
@@ -115,8 +116,8 @@ public class PlotWalk extends RevWalk {
class PlotRefComparator implements Comparator<Ref> {
public int compare(Ref o1, Ref o2) {
try {
- Object obj1 = getRepository().mapObject(o1.getObjectId(), o1.getName());
- Object obj2 = getRepository().mapObject(o2.getObjectId(), o2.getName());
+ RevObject obj1 = parseAny(o1.getObjectId());
+ RevObject obj2 = parseAny(o2.getObjectId());
long t1 = timeof(obj1);
long t2 = timeof(obj2);
if (t1 > t2)
@@ -129,11 +130,15 @@ public class PlotWalk extends RevWalk {
return 0;
}
}
- long timeof(Object o) {
- if (o instanceof Commit)
- return ((Commit)o).getCommitter().getWhen().getTime();
- if (o instanceof Tag)
- return ((Tag)o).getTagger().getWhen().getTime();
+
+ long timeof(RevObject o) {
+ if (o instanceof RevCommit)
+ return ((RevCommit) o).getCommitTime();
+ if (o instanceof RevTag) {
+ RevTag tag = (RevTag) o;
+ PersonIdent who = tag.getTaggerIdent();
+ return who != null ? who.getWhen().getTime() : 0;
+ }
return 0;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java
index edb883714b..76510ce387 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/