]> source.dussan.org Git - jgit.git/log
jgit.git
14 years agoFix tag sorting in PlotWalk 92/1192/1
Shawn O. Pearce [Wed, 28 Jul 2010 18:44:00 +0000 (11:44 -0700)]
Fix tag sorting in PlotWalk

By deferring tag sorting until the commit is produced by the walker
we can avoid an infinite loop that was triggered by trying to sort
tags while allocating a commit.  This also avoids needing to look
at commits which aren't going to be produced in the result.

Bug: 321103
Change-Id: I25acc739db2ec0221a50b72c2d2aa618a9a75f37
Reviewed-by: Mathias Kinzler <mathias.kinzler@sap.com>
Reviewed-by: Christian Halstrick <christian.halstrick@sap.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoTeach NameConflictTreeWalk to report DF conflicts 69/1169/3
Christian Halstrick [Thu, 22 Jul 2010 13:57:14 +0000 (15:57 +0200)]
Teach NameConflictTreeWalk to report DF conflicts

Add a method isDirectoryFileConflict() to NameConflictTreeWalk which
tells whether the current path is part of a directory/file conflict.

Change-Id: Iffcc7090aaec743dd6f3fd1a333cac96c587ae5d
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoStack Overflow in EGit History View 83/1183/1
Mathias Kinzler [Wed, 28 Jul 2010 09:46:05 +0000 (11:46 +0200)]
Stack Overflow in EGit History View

This is caused by a recursion in PlotWalk.getTags().
As a hotfix, the sort was simply removed. The sort
must be re-implemented so that parseAny() is not called
again (currently, this happens in the PlotRefComparator).

Change-Id: I060d26fda8a75ac803acaf89cfb7d3b4317328f3
Signed-off-by: Mathias Kinzler <mathias.kinzler@sap.com>
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
14 years agoBreak dissimilar file pairs during diff 70/1170/7
Jeff Schumacher [Thu, 22 Jul 2010 19:55:28 +0000 (12:55 -0700)]
Break dissimilar file pairs during diff

File pairs that are very dissimilar during a diff were not being
broken apart into their constituent ADD/DELETE pairs. The leads to
sub-optimal rename detection. Take, for example, this situation:

A file exists at src/a.txt containing "foo". A user renames src/a.txt
to src/b.txt, then adds a new src/a.txt containing "bar".

Even though the old a.txt and the new b.txt are identical, the
rename detection algorithm would not detect it as a rename since
it was already paired in a MODIFY. I added code to split all
MODIFYs below a certain score into their constituent ADD/DELETE
pairs. This allows situations like the one I described above to be
more correctly handled.

Change-Id: I22c04b70581f206bbc68c4cd1ee87a1f663b418e
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAdd methods which write MERGE_HEAD and MERGE_MSG 62/1162/3
Christian Halstrick [Wed, 21 Jul 2010 15:14:54 +0000 (17:14 +0200)]
Add methods which write MERGE_HEAD and MERGE_MSG

Add methods to the Repository class which write into MERGE_HEAD
and MERGE_MSG files. Since we have the read methods in the same
class this seems to be the right place.

Change-Id: I5dd65306ceb06e008fcc71b37ca3a649632ba462
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoFix concurrent read / write issue in LockFile on Windows 72/1172/5
Jens Baumgart [Mon, 26 Jul 2010 08:18:47 +0000 (10:18 +0200)]
Fix concurrent read / write issue in LockFile on Windows

LockFile.commit fails if another thread concurrently reads
the base file. The problem is fixed by retrying the rename
operation if it fails.

Change-Id: I6bb76ea7f2e6e90e3ddc45f9dd4d69bd1b6fa1eb
Bug: 308506
Signed-off-by: Jens Baumgart <jens.baumgart@sap.com>
14 years agoFix Javadoc warnings 74/1174/2
Robin Stocker [Sat, 24 Jul 2010 09:34:58 +0000 (11:34 +0200)]
Fix Javadoc warnings

There were some broken links, incorrect uses of @value, an invalid
tag and an outdated comment.

Change-Id: I22886bcc869a4b62bd606ebed40669f7b4723664
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoMake forPath(ObjectReader) variant in TreeWalk 80/1180/1
Shawn O. Pearce [Tue, 27 Jul 2010 15:36:24 +0000 (08:36 -0700)]
Make forPath(ObjectReader) variant in TreeWalk

This simplifies the logic for those who already have an ObjectReader
on hand want to reuse it to lookup a single path.

Change-Id: Ief17d6b2a0674ddb34bbc9f43121b756eae960fb
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoMake StoredConfig an abstraction above FileBasedConfig 78/1178/1
Shawn O. Pearce [Mon, 26 Jul 2010 23:50:11 +0000 (16:50 -0700)]
Make StoredConfig an abstraction above FileBasedConfig

This exposes a load and save method, allowing a Repository to denote
that it has a persistent configuration of some kind which can be
accessed by the application, without needing to know exact details
of how its stored .

Change-Id: I7c414bc0f975b80f083084ea875eca25c75a07b2
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoMerge branch 'delta' 71/1171/1
Shawn O. Pearce [Thu, 22 Jul 2010 18:17:00 +0000 (11:17 -0700)]
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

14 years agoAllow client of Add command to set a WorkingTreeIterator 66/1166/2
Stefan Lay [Thu, 22 Jul 2010 12:57:00 +0000 (14:57 +0200)]
Allow client of Add command to set a WorkingTreeIterator

This is e.g. useful when a client of the AddCommand has
additional rules to ignore files. In Eclipse a resource can
be set to derived or be excluded by preferences.

Change-Id: I6c47e54a1ce26315faf5ed0723298ad2c2db197c
Signed-off-by: Stefan Lay <stefan.lay@sap.com>
14 years agoAllow for filepattern "." in AddCommand 65/1165/1
Stefan Lay [Thu, 22 Jul 2010 12:27:35 +0000 (14:27 +0200)]
Allow for filepattern "." in AddCommand

Enable adding on repository root level.

Change-Id: I415b10dc74cc9435578424d9f106c972fd703055
Signed-off-by: Stefan Lay <stefan.lay@sap.com>
14 years agoDo not add ignored files in Add command 63/1163/1
Stefan Lay [Thu, 22 Jul 2010 09:26:04 +0000 (11:26 +0200)]
Do not add ignored files in Add command

Signed-off-by: Stefan Lay <stefan.lay@sap.com>
14 years agoMove ignore node handling into WorkingTreeIterator 56/1156/5
Shawn O. Pearce [Wed, 21 Jul 2010 08:51:15 +0000 (10:51 +0200)]
Move ignore node handling into WorkingTreeIterator

The working tree iterator has perfect knowledge of the path structure
as well as immediate information about whether or not an ignore file
even exists at this level.  We can exploit that to simplify the
logic and running time for testing ignored file status by pushing
all of the checks down into the iterator itself.

Change-Id: I22ff534853e8c5672cc5c2d9444aeb14e294070e
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
CC: Charley Wang <chwang@redhat.com>
CC: Chris Aniszczyk <caniszczyk@gmail.com>
CC: Stefan Lay <stefan.lay@sap.com>
CC: Matthias Sohn <matthias.sohn@sap.com>
14 years agoMerge "Fix concurrent read / write issue in GitIndex on Windows"
Shawn Pearce [Wed, 21 Jul 2010 17:08:01 +0000 (13:08 -0400)]
Merge "Fix concurrent read / write issue in GitIndex on Windows"

14 years agoFix concurrent read / write issue in GitIndex on Windows 52/1152/4
Jens Baumgart [Wed, 21 Jul 2010 07:35:15 +0000 (09:35 +0200)]
Fix concurrent read / write issue in GitIndex on Windows

GitIndex.write fails if another thread concurrently reads
the index file. The problem is fixed by retrying the rename
operation if it fails.

Bug: 311051
Change-Id: Ib243d2a90adae312712d02521de4834d06804944
Signed-off-by: Jens Baumgart <jens.baumgart@sap.com>
14 years agoCheck for racy git in WorkingTreeIterator 43/1143/2
Christian Halstrick [Fri, 16 Jul 2010 07:59:13 +0000 (09:59 +0200)]
Check for racy git in WorkingTreeIterator

The WorkingTreeIterator has a method to check whether
the current file differs from the corresponding index
entry. This commit improves this check to also handle
racy git situations.

See http://git.kernel.org/?p=git/git.git;a=blob;f=Documentation/technical/racy-git.txt;hb=HEAD

Change-Id: I3ad0897211dcbb2eac9eebcb19d095a5052fb06b
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
14 years agoSmudge racily clean index entries by truncating length (like git.git) 42/1142/2
Christian Halstrick [Thu, 15 Jul 2010 11:36:11 +0000 (13:36 +0200)]
Smudge racily clean index entries by truncating length (like git.git)

To mark an entry racily clean we set its length to 0 (like native git
does). Entries which are not racily clean and have zero length can be
distinguished from racily clean entries by checking P_OBJECTID
against the SHA1 of empty content. When length is 0 and P_OBJECTID is
different from SHA1 of empty content we know the entry is marked
racily clean.

See http://dev.eclipse.org/mhonarc/lists/jgit-dev/msg00488.html

Change-Id: I689552931441ab51964b430b303160c9126b66af
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
14 years agoUse proper constants for .gitignore and .git directory 55/1155/1
Shawn O. Pearce [Tue, 20 Jul 2010 16:11:39 +0000 (09:11 -0700)]
Use proper constants for .gitignore and .git directory

We have a constant for .gitignore, so use it.  While we are in
the same method, correct the reference of ".git" to be the actual
GIT_DIR given.  This might not be within the work tree if the
GIT_DIR and GIT_WORK_TREE environment variables were used.

Change-Id: I38e1cec13405109b9c347858b38dd9fb2f1f2560
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
CC: Charley Wang <chwang@redhat.com>
CC: Chris Aniszczyk <caniszczyk@gmail.com>
CC: Stefan Lay <stefan.lay@sap.com>
CC: Matthias Sohn <matthias.sohn@sap.com>
14 years agoRemove gitIgnoreTimestamp from abstract iterator API 54/1154/1
Shawn O. Pearce [Tue, 20 Jul 2010 15:58:14 +0000 (08:58 -0700)]
Remove gitIgnoreTimestamp from abstract iterator API

This never should have been exposed on the top of the
AbstractTreeIterator type hierarchy.  There is no concept of a
timestamp in a canonical tree read from the object database, and
the time in the DirCache isn't what we want here either.

Actually all that we need is to find the files whose names are
".gitignore" and are below the root directory.  We can accomplish
that with a suffix filter, and process them immediately.

Change-Id: Ib09cbf81a9e038452ce491385c65498312e2916b
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
CC: Charley Wang <chwang@redhat.com>
CC: Chris Aniszczyk <caniszczyk@gmail.com>
CC: Stefan Lay <stefan.lay@sap.com>
CC: Matthias Sohn <matthias.sohn@sap.com>
14 years agoFix NPE in RenameDetector 51/1151/1
Shawn O. Pearce [Tue, 20 Jul 2010 14:52:35 +0000 (07:52 -0700)]
Fix NPE in RenameDetector

If we have two adds of the same object but no deletes the detector
threw an NPE because the entry that came back from the deleted map
was null (no matching objects).  In this case we need to put the
adds all back onto the list of left over additions since they did
not match a delete.

Change-Id: Ie68fbe7426b4dc0cb571a08911c7adbffff755d5
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
CC: Jeffrey Schumacher" <jeffschu@google.com>
14 years agoIndexPack: Fix spurious pack file corruption errors 50/1150/1
Shawn O. Pearce [Tue, 20 Jul 2010 14:40:48 +0000 (07:40 -0700)]
IndexPack: Fix spurious pack file corruption errors

We didn't correctly handle the zlib trailer for an object.  If the
trailer bytes were outside of the current buffer window but we had
fully inflated the object itself, we broke out of the loop (as we had
our target size) but inflate wasn't finished (as it did not yet get
the trailer) so we failed the test and threw a corruption exception.

Use an infinite loop and only break out when the inflater is done.

Change-Id: I7c9bbbeb577a990d9bc56a50ebd485935460f6c8
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoFully implement Logger interface 89/689/2
Jonathan Gossage [Fri, 16 Jul 2010 23:53:23 +0000 (01:53 +0200)]
Fully implement Logger interface

On April 27, 2010 the Logger interface was upgraded with a number of new methods
to make it consistent with the implementations it was meant to support.

This patch makes RecordingLogger consistent with the Logger interface and allows to
also use Jetty 7.1.5 released with Helios which can be installed from the p2 repository
at http://download.eclipse.org/jetty/7.1.5.v20100705/repository

Change-Id: I5645436bbe7492f82d4069e4d9cbebede0bf764e
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
14 years agoDiscard the uncompressed delta as soon as its compressed 41/1141/1
Shawn O. Pearce [Fri, 16 Jul 2010 17:41:09 +0000 (10:41 -0700)]
Discard the uncompressed delta as soon as its compressed

The DeltaCache will most likely need to copy the compressed delta
into a new buffer in order to compact away the wasted space at the
end caused by over allocation.  Since we don't need the uncompressed
format anymore, null out our only reference to it so the GC can
reclaim this memory if it needs to perform a collection in order
to satisfy the cache's allocation attempt.

Change-Id: I50403cfd2e3001b093f93a503cccf7adab43cc9d
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoMerge branch 'js/rename' 40/1140/1
Shawn O. Pearce [Fri, 16 Jul 2010 17:22:15 +0000 (10:22 -0700)]
Merge branch 'js/rename'

* js/rename:
  Implemented file path based tie breaking to exact rename detection
  Added more test cases for RenameDetector
  Added very small optimization to exact rename detection
  Fixed Misleading Javadoc
  Added file path similarity to scoring metric in rename detection
  Fixed potential div by zero bug
  Added file size based rename detection optimization
  Create FileHeader from DiffEntry
  log: Implement --follow
  Cache the diff configuration section
  log: Add whitespace ignore options
  Format submodule links during differences
  Redo DiffFormatter API to be easier to use
  log, diff: Add rename detection support
  Implement similarity based rename detection
  Added a preliminary version of rename detection
  Refactored code out of FileHeader to facilitate rename detection

14 years agoFix infinite loop in IndexPack 49/1049/4
Shawn O. Pearce [Sat, 3 Jul 2010 01:21:55 +0000 (18:21 -0700)]
Fix infinite loop in IndexPack

A programming error using the Inflater API led to an infinite
loop within IndexPack, caused by the Inflater returning 0 from
the inflate() method, but it didn't want more input.  This happens
when it has reached the end of the stream, or has reached a spot
asking for an external dictionary.  Such a case is a failure for us,
and we should abort out.

Thanks to Alex for pointing out that we had 3 implementations of
the inflate rountine, which should be consolidated into one and
use a switch to determine where to load data from.

Bug: 317416
Change-Id: I34120482375b687ea36ed9154002d77047e94b1f
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoImplemented file path based tie breaking to exact rename detection 30/1130/2
Jeff Schumacher [Tue, 13 Jul 2010 19:21:12 +0000 (12:21 -0700)]
Implemented file path based tie breaking to exact rename detection

During the exact rename detection phase in RenameDetector, ties were
resolved on a first-found basis. I added support for file path based
tie breaking during that phase. Basically, there are four situations
that have to be handled:

One add matching one delete:
In this simple case, we pair them as a rename.

One add matching many deletes:
Find the delete whos path matches the add the closest, and
pair them as a rename.

Many adds matching one delete:
Similar to the above case, we find the add that matches the
delete the closest, and pair them as a rename. The other adds
are marked as copies of the delete.

Many adds matching many deletes:
Build a scoring matrix similar to the one used for content-
based matching, scoring instead by file path. Some of the
utility functions in SimilarityRenameDetector are used in
this case, as we use the same encoding scheme. Once the
matrix is built, scan it for the best matches, marking them
as renames. The rest are marked as copies.

I don't particularly like the idea of using utility functions right
out of SimilarityRenameDetector, but it works for the moment. A later
commit will likely refactor this into a common utility class, as well
as bringing exact rename detection out of RenameDetector and into a
separate class, much like SimilarityRenameDetector.

Change-Id: I1fb08390aebdcbf20d049aecf402a36506e55611

14 years agoAdded dirty-detection to WorkingTreeIterator 59/1059/7
Christian Halstrick [Fri, 16 Jul 2010 08:03:49 +0000 (10:03 +0200)]
Added dirty-detection to WorkingTreeIterator

Added possibility to compare the current entry of a WorkingTreeIterator
to a given DirCacheEntry. This is done to detect whether an entry
in the index is dirty or not. 'Dirty' means that the file in the working tree
is different from what's in the index. Merge algorithms will make use of
this to detect conflicts.

Change-Id: I3ff847f4bf392553dcbd6ee236c6ca32a13eedeb
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
14 years agoMerge "Remove an unused File reference in test code"
Shawn Pearce [Thu, 15 Jul 2010 23:01:25 +0000 (19:01 -0400)]
Merge "Remove an unused File reference in test code"

14 years agoRemove an unused File reference in test code 37/1137/1
Robin Rosenberg [Thu, 15 Jul 2010 22:35:47 +0000 (00:35 +0200)]
Remove an unused File reference in test code

Change-Id: Ib0d6c36811df719a53c66e9fa7460b89b2faf98b
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
14 years agoMerge "Handle the tilde notation (~user) of git url"
Shawn Pearce [Thu, 15 Jul 2010 21:29:21 +0000 (17:29 -0400)]
Merge "Handle the tilde notation (~user) of git url"

14 years agoHandle the tilde notation (~user) of git url 34/1134/1
Robin Rosenberg [Wed, 14 Jul 2010 23:16:09 +0000 (01:16 +0200)]
Handle the tilde notation (~user) of git url

When the path is prefixed with ~ the URI parser thought about this
as /~. Strip the / if the next character is the tilde.

Bug: 307017
Change-Id: I58203e5617956b46d83e8987d1f8042beddffac3
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
14 years agoGit Porcelain API: Add Command 36/1036/7
Stefan Lay [Thu, 8 Jul 2010 08:32:57 +0000 (10:32 +0200)]
Git Porcelain API: Add Command

The new Add command adds files to the Git Index.
It  uses the DirCache to access the git index. It
works also in case of an existing conflict.

Fileglobs (e.g. *.c) are not yet supported.

The new Add command does add ignored files because
there is no gitignore support in jgit yet.

Bug: 318440
Change-Id: If16fdd4443e46b27361c2a18ed8f51668af5d9ff
Signed-off-by: Stefan Lay <stefan.lay@sap.com>
14 years agoMerge changes I104cd62f,I1d0238b4
Shawn Pearce [Wed, 14 Jul 2010 00:36:25 +0000 (20:36 -0400)]
Merge changes I104cd62f,I1d0238b4

* changes:
  Internationalize RepositoryState descriptions
  Say that commit is allowed during bisect

14 years agoFix ReadTreeTest 25/1125/3
Christian Halstrick [Tue, 13 Jul 2010 12:28:42 +0000 (12:28 +0000)]
Fix ReadTreeTest

After refactoring ReadTreeTest the tests failed for filesystems
with coarse modification time granularity. This is fixed by
explicitly telling the repo to reread the index after we build
a new index.

Additionally the test testDirectoryFileSimple was simplified
by using buildTree() instead of misusing GitIndex to construct
trees.

Change-Id: I20d2f097491e4cc8c657a696beabc7026b485017
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
14 years agoAdd compatibility with gitignore specifications 83/683/20
Charley Wang [Mon, 12 Jul 2010 22:34:15 +0000 (00:34 +0200)]
Add compatibility with gitignore specifications

This patch adds ignore compatibility to jgit. It encompasses
exclude files as well as .gitignore. Uses TreeWalk and
FileTreeIterator to find nodes and parses .gitignore
files when required. The patch includes a simple cache that
can be used to save results and avoid excessive gitignore
parsing.

CQ: 4302
Bug: 303925
Change-Id: Iebd7e5bb534accca4bf00d25bbc1f561d7cad11b
Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
Signed-off-by: Stefan Lay <stefan.lay@sap.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
14 years agoAdded more test cases for RenameDetector 23/1123/3
Jeff Schumacher [Mon, 12 Jul 2010 19:31:18 +0000 (12:31 -0700)]
Added more test cases for RenameDetector

I added test cases to cover the majority of the code. It's not 100%
coverage yet, but the remaining bits are small.

Change-Id: Ib534c8e94b13358b8b22cf54e2ff84132bae6d14

14 years agoAdded very small optimization to exact rename detection 22/1122/2
Jeff Schumacher [Mon, 12 Jul 2010 18:48:56 +0000 (11:48 -0700)]
Added very small optimization to exact rename detection

Optimized a small loop in findExactRenames. The loop would go through
all the items in a list of DiffEntries even after it already found
what it was looking for. I made it break out of the loop as soon as
a good match was found.

Change-Id: I28741e0c49ce52d8008930a87cd1db7037700a61

14 years agoFixed Misleading Javadoc 21/1121/2
Jeff Schumacher [Mon, 12 Jul 2010 17:37:10 +0000 (10:37 -0700)]
Fixed Misleading Javadoc

The javadoc for the setRenameLimit method in RenameDetector said
that you could only have limits in the range (0,100), implying
that 0 and 100 were illegal inputs. The code, however, allowed 0 and
100. I changed the javadoc to say that the range [0,100] was legal.
I also documented the IllegalArgumentException that is thrown if the
limit is outside that range.

Change-Id: I916838f254859f6f0e1516bb55b8e7dc87e57dc2

14 years agoAdded file path similarity to scoring metric in rename detection 93/1093/3
Jeff Schumacher [Fri, 9 Jul 2010 22:11:54 +0000 (15:11 -0700)]
Added file path similarity to scoring metric in rename detection

The scoring method was not taking into account the similarity of
the file paths and file names. I changed the metric so that it is 99%
based on content (which used to be 100% of the old metric), and 1%
based on path similarity. Of that 1%, half (.5% of the total final
score) is based on the actual file names (e.g. "foo.java"), and half
on the directory (e.g. "src/com/foo/bar/").

Change-Id: I94f0c23bf6413c491b10d5625f6ad7d2ecfb4def

14 years agoFixed potential div by zero bug 92/1092/2
Jeff Schumacher [Fri, 9 Jul 2010 19:53:57 +0000 (12:53 -0700)]
Fixed potential div by zero bug

The scoring logic in SimilarityIndex was dividing by the max file
size. If both files are empty, this would cause a div by zero
error. This case cannot currently happen, since two empty files
would have the same SHA1, and would therefore be caught in the
earlier SHA1 based detection pass. Still, if this logic eventually
gets separated from that pass, a div by zero error would occur.

I changed the logic to instead consider two empty files to have a
similarity score of 100.

Change-Id: Ic08e18a066b8fef25bb5e7c62418106a8cee762a

14 years agoAdded file size based rename detection optimization 91/1091/2
Jeff Schumacher [Fri, 9 Jul 2010 18:18:50 +0000 (11:18 -0700)]
Added file size based rename detection optimization

Prior to this change, files that were very different in size (enough
so that they could not have enough in common to be detected as
renames) were still having their scores calculated. I added an
optimization to skip such files. For example, if the rename detection
threshold is 60%, the larger file is 200kb, and the smaller file is
50kb, the pair cannot be counted as a rename since they cannot
possibly share 60% of their content in common. (200*.6=120, 120>50)

Change-Id: Icd8315412d5de6292839778e7cea7fe6f061b0fc

14 years agoInternationalize RepositoryState descriptions 96/1096/2
Robin Rosenberg [Sat, 10 Jul 2010 00:51:23 +0000 (02:51 +0200)]
Internationalize RepositoryState descriptions

Change-Id: I104cd62f3e89acf010b1d40a2b08e7f68f63bb85
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
14 years agoHonor pack.windowlimit to cap memory usage during packing 16/1116/1
Shawn O. Pearce [Sat, 10 Jul 2010 01:32:33 +0000 (18:32 -0700)]
Honor pack.windowlimit to cap memory usage during packing

The pack.windowlimit configuration parameter places an upper bound
on the number of bytes used by the DeltaWindow class as it scans
through the object list.  If memory usage would exceed the limit
the window is temporarily decreased in size to keep memory used
within that bound.

Change-Id: I09521b8f335475d8aee6125826da8ba2e545060d
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoHonor pack.threads and perform delta search in parallel 15/1115/1
Shawn O. Pearce [Sat, 10 Jul 2010 01:15:50 +0000 (18:15 -0700)]
Honor pack.threads and perform delta search in parallel

If we have multiple CPUs available, packing usually goes faster
when each CPU is assigned a slice of the available search space.
The number of threads to use is guessed from the runtime if it
wasn't set by the caller, or wasn't set in the configuration.

Change-Id: If554fd8973db77632a52a0f45377dd6ec13fc220
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoCache small deltas during packing 14/1114/1
Shawn O. Pearce [Sat, 10 Jul 2010 00:19:32 +0000 (17:19 -0700)]
Cache small deltas during packing

PackWriter now caches small deltas, or deltas that are very tiny
compared to their source inputs, so that the writing phase goes
faster by reusing those cached deltas.

The cached data is stored compressed, which usually translates to
a bigger footprint due to deltas being very hard to compress, but
saves time during writing by avoiding the deflate step.  They are
held under SoftReferences so that the JVM GC can clear out deltas
if memory gets very tight.  We would rather continue working and
spend a bit more CPU time during writing than crash due to OOME.

To avoid OutOfMemoryErrors during the caching phase we also trap
OOME and just abort out of the caching.

Because deflateBound() always produces something larger than what
we need to actually store the deflated data, we copy it over into
a new buffer if the actual length doesn't match the buffer length.
When packing jgit.git this saves over 111 KiB in the cache, and is
thus a worthwhile hit on CPU time.

To further save memory we store the inflated size of the delta
(which we need for the object header) in the same field as the
pathHash, as the pathHash is no longer necessary by this phase
of the packing algorithm.

Change-Id: I0da0c600d845e8ec962289751f24e65b5afa56d7
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoImplement delta generation during packing 13/1113/1
Shawn O. Pearce [Fri, 9 Jul 2010 22:16:15 +0000 (15:16 -0700)]
Implement delta generation during packing

PackWriter now produces new deltas if there is not a suitable delta
available for reuse from an existing pack file.  This permits JGit to
send less data on the wire by sending a delta relative to an object
the other side already has, instead of sending the whole object.

The delta searching algorithm is similar in style to what C Git
uses, but apparently has some differences (see below for more on).
Briefly, objects that should be considered for delta compression are
pushed onto a list.  This list is then sorted by a rough similarity
score, which is derived from the path name the object was discovered
at in the repository during object counting.  The list is then
walked in order.

At each position in the list, up to $WINDOW objects prior to it
are attempted as delta bases.  Each object in the window is tried,
and the shortest delta instruction sequence selects the base object.
Some rough rules are used to prevent pathological behavior during
this matching phase, like skipping pairings of objects that are
not similar enough in size.

PackWriter intentionally excludes commits and annotated tags from
this new delta search phase.  In the JGit repository only 28 out
of 2600+ commits can be delta compressed by C Git.  As the commit
count tends to be a fair percentage of the total number of objects
in the repository, and they generally do not delta compress well,
skipping over them can improve performance with little increase in
the output pack size.

Because this implementation was rebuilt from scratch based on my own
memory of how the packing algorithm has evolved over the years in
C Git, PackWriter, DeltaWindow, and DeltaEncoder don't use exactly
the same rules everywhere, and that leads JGit to produce different
(but logically equivalent) pack files.

  Repository | Pack Size (bytes)                | Packing Time
             | JGit     - CGit     = Difference | JGit / CGit
  -----------+----------------------------------+-----------------
   git       | 25094348 - 24322890 = +771458    | 59.434s / 59.133s
   jgit      |  5669515 -  5709046 = - 39531    |  6.654s /  6.806s
   linux-2.6 |     389M -     386M = +3M        |  20m02s / 18m01s

For the above tests pack.threads was set to 1, window size=10,
delta depth=50, and delta and object reuse was disabled for both
implementations.  Both implementations were reading from an already
fully packed repository on local disk.  The running time reported
is after 1 warm-up run of the tested implementation.

PackWriter is writing 771 KiB more data on git.git, 3M more on
linux-2.6, but is actually 39.5 KiB smaller on jgit.git.  Being
larger by less than 0.7% on linux-2.6 isn't bad, nor is taking an
extra 2 minutes to pack.  On the running time side, JGit is at a
major disadvantage because linux-2.6 doesn't fit into the default
WindowCache of 20M, while C Git is able to mmap the entire pack and
have it available instantly in physical memory (assuming hot cache).

CGit also has a feature where it caches deltas that were created
during the compression phase, and uses those cached deltas during
the writing phase.  PackWriter does not implement this (yet),
and therefore must create every delta twice.  This could easily
account for the increased running time we are seeing.

Change-Id: I6292edc66c2e95fbe45b519b65fdb3918068889c
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agodebug-show-packdelta: Dump a pack delta to the console 12/1112/1
Shawn O. Pearce [Fri, 9 Jul 2010 18:59:55 +0000 (11:59 -0700)]
debug-show-packdelta:  Dump a pack delta to the console

This is a horribly crude application, it doesn't even verify that
the object its dumping is delta encoded.  Its method of getting the
delta is pretty abusive to the public PackWriter API, because right
now we don't want to expose the real internal low-level methods
actually required to do this.

Change-Id: I437a17ceb98708b5603a2061126eb251e82f4ed4
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoInitial pack format delta generator 11/1111/1
Shawn O. Pearce [Wed, 7 Jul 2010 15:33:56 +0000 (08:33 -0700)]
Initial pack format delta generator

DeltaIndex is a simple pack style delta generator.  The function works
by creating a compact index of a source buffer's blocks, and then
walking a sliding window along a desired result buffer, searching for
the window in the index.  When a match is found, the window is
stretched to the longest possible length that is common with the
source buffer, and a copy instruction is created.

Rabin's polynomial hash function is used to compute the hash for a
block, permitting efficient sliding of the window in single byte
increments.  The update function to slide one byte originated from
David Mazieres' work in LBFS, and our implementation of the update
step was certainly inspired by the initial work Geert Bosch proposed
for C Git in http://marc.info/?l=git&m=114565424620771&w=2.

To ensure the encoder runs in linear time with respect to the size of
the two input buffers (source and result), the maximum number of
blocks that can share the same position in the index's hashtable is
capped at a constant number.  This prevents bad inputs from causing
the encoder to run in quadratic time, but comes with a penalty of
creating a longer delta due to fewer considered copy positions.

Strange hackery is used to cap the amount of memory used by the index
to be no more than 12 bytes for every 16 bytes of source buffer, no
matter what the JVM per-object overhead is.  This permits an index to
always be no larger than 1.75x the source buffer length, which is an
important feature to support large windows of candidates to match
against while packing.  Here the strange hackery is nothing more than
a manually managed chained hashtable, where pointers are array indexes
into storage arrays rather than object references.

Computation of the hash function for a single fixed sized block is
done through an unrolled loop, where the first 4 iterations have been
manually reduced down to eliminate unnecessary instructions.  The
pattern is derived from ObjectId.equals(byte[], int, byte[], int),
where we have unrolled the loop required to compare two 20 byte
arrays.  Hours of testing with the Sun 1.6 JRE concluded that the
non-obvious "foo[idx + 1]" style of reference is faster than
"foo[idx++]", and so that is what we use here during hashing.

Change-Id: If9fb2a1524361bc701405920560d8ae752221768
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAdd debugging toString() method to ObjectToPack 10/1110/1
Shawn O. Pearce [Fri, 9 Jul 2010 15:53:06 +0000 (08:53 -0700)]
Add debugging toString() method to ObjectToPack

Its useful to know what the flags are or what the base that was
selected is.  Dump these out as part of the object's toString.

Change-Id: I8810067fb8337b08b4fcafd5f9ea3e1e31ca6726
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoMake ObjectToPack clearReuseAsIs signal available to subclasses 09/1109/1
Shawn O. Pearce [Fri, 9 Jul 2010 15:51:47 +0000 (08:51 -0700)]
Make ObjectToPack clearReuseAsIs signal available to subclasses

A subclass may want to use this method to release handles that are
caching reuse information.  Make it protected so they can override
it and update themselves.

Change-Id: I2277a56ad28560d2d2d97961cbc74bc7405a70d4
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoCorrectly classify the compressing objects phase 08/1108/1
Shawn O. Pearce [Fri, 9 Jul 2010 15:04:06 +0000 (08:04 -0700)]
Correctly classify the compressing objects phase

Searching for reuse candidates should be fast compared to actually
doing delta compression.  So pull the progress monitor out of this
phase and rename it back to identify the compressing objects state.

Change-Id: I5eb80919f21c1251e0e3420ff7774126f1f79b27
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoRefactor ObjectToPack's delta depth setting 07/1107/1
Shawn O. Pearce [Fri, 9 Jul 2010 14:59:30 +0000 (07:59 -0700)]
Refactor ObjectToPack's delta depth setting

Long ago when PackWriter is first written we thought that the delta
depth could be updated automatically.  But its never used.  Instead
make this a simple standard setter so the caller can more directly
set the delta depth of this object.  This permits us to configure a
depth that takes into account more than just the depth of another
object in this same pack.

Change-Id: I1d71b74f2edd7029b8743a2c13b591098ce8cc8f
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoConfigure core.bigFileThreshold into PackWriter 06/1106/1
Shawn O. Pearce [Fri, 9 Jul 2010 14:57:47 +0000 (07:57 -0700)]
Configure core.bigFileThreshold into PackWriter

C Git's fast-import uses this to determine the maximum file size
that it tries to delta compress, anything equal to or above this
setting is stored with as a whole object with simple deflate.

Define the configuration so we can use it later.

Change-Id: Iea46e787d019a1b6c51135cc73d7688a02e207f5
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAdd doNotDelta flag to ObjectToPack 05/1105/1
Shawn O. Pearce [Fri, 9 Jul 2010 00:19:20 +0000 (17:19 -0700)]
Add doNotDelta flag to ObjectToPack

This flag will later control whether or not PackWriter search for a
delta base for this object.  Edge objects will never get searched,
as the writer won't be outputting them, so they should always have
this flag set on.  Sometime in the future this flag should also be
set for file blobs on file paths that have the "-delta" gitattribute
set in the repository's attributes file.

Change-Id: I6e518e1a6996c8ce00b523727f1b605e400e82c6
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAdd more configuration options to PackWriter 04/1104/1
Shawn O. Pearce [Sat, 10 Jul 2010 02:00:46 +0000 (19:00 -0700)]
Add more configuration options to PackWriter

We now at least import other pack settings like pack.window, which
means we can later use these to control how we search for deltas.

The compression level was fixed to use pack.compression rather than
the loose object core.compression setting.

Change-Id: I72ff6d481c936153ceb6a9e485fa731faf075a9a
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoSay that commit is allowed during bisect 95/1095/1
Robin Rosenberg [Sat, 10 Jul 2010 00:32:46 +0000 (02:32 +0200)]
Say that commit is allowed during bisect

C Git allows this and it is quite handy.

Change-Id: I1d0238b43fca931ad2079649fb7b431e2815c351
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
14 years agoSave object path hash codes during packing 03/1103/1
Shawn O. Pearce [Fri, 9 Jul 2010 00:14:45 +0000 (17:14 -0700)]
Save object path hash codes during packing

We need to remember these so we can later cluster objects that
have similar file paths near each other as we search for deltas
between them.

Change-Id: I52cb1e4ca15c9c267a2dbf51dd0d795f885f4cf8
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAdd path hash code to ObjectWalk 02/1102/1
Shawn O. Pearce [Fri, 9 Jul 2010 00:11:38 +0000 (17:11 -0700)]
Add path hash code to ObjectWalk

PackWriter wants to categorize objects that are similar in path name,
so blobs that are probably from the same file (or same sort of file)
can be delta compressed against each other.  Avoid converting into
a string by performing the hashing directly against the path buffer
in the tree iterator.

We only hash the last 16 bytes of the path, and we try avoid any
spaces, as we want the suffix of a file such as ".java" to be more
important than the directory it is in, like "src".

Change-Id: I31770ee711526306769a6f534afb19f937e0ba85
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAdd getObjectSize to ObjectReader 01/1101/1
Shawn O. Pearce [Fri, 9 Jul 2010 00:08:55 +0000 (17:08 -0700)]
Add getObjectSize to ObjectReader

This is an informational function used by PackWriter to help it
better organize objects for delta compression.  Storage systems
can implement it to provide up more detailed size information,
or they can simply rely on the default behavior that uses the
ObjectLoader obtained from open.

For local file storage, we can obtain this information faster
through specialized routines that parse a pack object header.

Change-Id: I13a09b4effb71ea5151b51547f7d091564531e58
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAllow TemporaryBuffer.Heap to allocate smaller than 8 KiB 00/1100/1
Shawn O. Pearce [Fri, 9 Jul 2010 17:10:12 +0000 (10:10 -0700)]
Allow TemporaryBuffer.Heap to allocate smaller than 8 KiB

If the heap limit was set to something smaller than 8 KiB, we were
still allocating the full 8 KiB block size, and accepting up to
the amount we allocated by.  Instead actually put a hard cap on
the limit.

Change-Id: Id1da26fde2102e76510b1da4ede8493928a981cc
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoMerge "Allow ReadTreeTest to test arbitrary Checkouts"
Christian Halstrick [Fri, 9 Jul 2010 13:42:12 +0000 (09:42 -0400)]
Merge "Allow ReadTreeTest to test arbitrary Checkouts"

14 years agoAdd support for updateNeeded flag in DirCacheEntry 78/1078/2
Matthias Sohn [Wed, 7 Jul 2010 23:51:17 +0000 (01:51 +0200)]
Add support for updateNeeded flag in DirCacheEntry

Change-Id: If06ff41d9ccd422afbc79ecbc3cfdf8bb2508dcd
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
14 years agoCreate FileHeader from DiffEntry 85/1085/5
Jeff Schumacher [Thu, 8 Jul 2010 16:59:36 +0000 (09:59 -0700)]
Create FileHeader from DiffEntry

Added support for converting DiffEntrys to FileHeaders. FileHeaders
are DiffEntrys with a buffer containing the diff output as well as
a list of HunkHeaders. The HunkHeaders contain EditLists. The
createFileHeader(DiffEntry) method in DiffFormatter performs a Myers
Diff on the files refered to by the DiffEntry, then puts the returned
EditList into a single HunkHeader, which is then put into the
FileHeader to be returned. It also generates the appropriate diff
header an puts it into the FileHeader's buffer. The rest of the diff
output, which would normally be parsed to generate the HunkHeaders,
is not generated. In fact, the purpose of this method is to avoid
the costly diff output generation and parsing normally required to
create a FileHeader.

Change-Id: I7d8b18c0f6c85e3d02ad58995d3d231e69af5887

14 years agoAllow ReadTreeTest to test arbitrary Checkouts 56/1056/3
Christian Halstrick [Thu, 1 Jul 2010 16:02:00 +0000 (18:02 +0200)]
Allow ReadTreeTest to test arbitrary Checkouts

ReadTreeTest was hardcoded to test WorkDirCheckout. Since we want
alternative checkout implementations (especially DirCacheCheckout)
this class has been refactored so that the tests can be reused
to test other implementations

The following changes have been done:
- abstract methods for checkout and prescanTwoTrees have been
  introduced. Parameters are only the two trees. As index we
  will implicitly use the current index of the repo.
- whenever tests needed a manipulated index before checkout
  and prescanTwoTrees it was ensured that the correct index was
  persisted (before we could use not-persisted instantiations of GitIndex
  passed as parameters to checkout, prescanTwoTrees
- abstract methods for getting updated, conflicting, removed entries
  resulting from the last checkout, prescanTwoTrees have been introduced
- an implementation for all these abstract methods using WorkDirCheckout
  has been added
- method to assert a certain state of the index and the working tree has
  been added

Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Change-Id:  Icf177cf8043487169a32ddd72b6f8f9246a433f7

14 years agoFix javadoc typos in JGit API 81/1081/1
Stefan Lay [Thu, 8 Jul 2010 08:42:29 +0000 (10:42 +0200)]
Fix javadoc typos in JGit API

There were some small errors which made it
difficult to read the JavaDoc.

Change-Id: Ib3b34353465162adebaca3514d596d0edf5aea51
Signed-off-by: Stefan Lay <stefan.lay@sap.com>
14 years agoDefine a constant for 127 in DeltaEncoder 99/1099/1
Shawn O. Pearce [Wed, 7 Jul 2010 15:52:46 +0000 (08:52 -0700)]
Define a constant for 127 in DeltaEncoder

The special value 127 here means how many bytes we can put into
a single insert command.  Rather than use the magical value 127,
lets name it to better document the code.

Change-Id: I5a326f4380f6ac87987fa833e9477700e984a88e
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoCap delta copy instructions at 64k 98/1098/1
Shawn O. Pearce [Wed, 7 Jul 2010 15:51:04 +0000 (08:51 -0700)]
Cap delta copy instructions at 64k

Although all modern delta decoders can process copy instructions
with a count as large as 0xffffff (~15.9 MiB), pack version 2 streams
are only supposed to use delta copy instructions up to 64 KiB.

Rewrite our copy instruction encode loop to use the lower 64 KiB
limit, even though modern decoders would support longer copies.

To improve encoding performance we now try to encode up to four full
copy commands in our buffer before we flush it to the stream, but
we don't try to implement full buffering here.  We are just trying
to amortize the virtual method call to the destination stream when
we have to do a large copy.

Change-Id: I9410a16e6912faa83180a9788dc05f11e33fabae
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoDeprecate all of the older Tree related code 77/1077/3
Shawn O. Pearce [Wed, 7 Jul 2010 16:15:02 +0000 (09:15 -0700)]
Deprecate all of the older Tree related code

We want to get rid of these APIs, because they don't perform as well
as DirCache/TreeWalk, or don't offer nearly as many features.

Bug: 319145
Change-Id: I2b28f9cddc36482e1ad42d53e86e9d6461ba3bfc
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoFix DeltaEncoder header for objects 128 bytes long 97/1097/1
Shawn O. Pearce [Wed, 7 Jul 2010 15:34:57 +0000 (08:34 -0700)]
Fix DeltaEncoder header for objects 128 bytes long

The encode loop had the wrong condition, objects that are 128 bytes
in size need to have their length encoded as two bytes, not one.

Change-Id: I3bef85f2b774871ba6104042b341749eb8e7595c
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoamend commit: Support large delta packed objects as streams 73/1073/2
Shawn O. Pearce [Wed, 7 Jul 2010 02:38:39 +0000 (19:38 -0700)]
amend commit: Support large delta packed objects as streams

Rename the ByteWindow's inflate() method to setInput.  We have
completely refactored the purpose of this method to be feeding part
(or all) of the window as input to the Inflater, and the actual
inflate activity happens in the caller.

Change-Id: Ie93a5bae0e9e637b5e822d56993ce6b562c6ad15
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoamend commit: Support large loose objects as streams 72/1072/2
Shawn O. Pearce [Wed, 7 Jul 2010 00:29:27 +0000 (17:29 -0700)]
amend commit: Support large loose objects as streams

We need to validate the stream state after the InflaterInputStream
thinks the stream is done.  Git expects a higher level of service from
the Inflater than the InflaterInputStream usually gives, we need to
ensure the embedded CRC is valid, and that there isn't trailing
garbage at the end of the file.

Change-Id: I1c9642a82dbd76b69e607dceccf8b85dc869a3c1
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoFix comparison of nanoseconds 67/1067/1
Stefan Lay [Tue, 6 Jul 2010 15:57:17 +0000 (17:57 +0200)]
Fix comparison of nanoseconds

NB.decodeInt32(info, base + 4) already returns nanoseconds.
Therefore it must not be divided by 1000000.

Change-Id: Ie8f5c4a03f984d98935dccedc2b1ba4457094899
Signed-off-by: Stefan Lay <stefan.lay@sap.com>
14 years agolog: Implement --follow 55/1055/1
Shawn O. Pearce [Sun, 4 Jul 2010 01:13:10 +0000 (18:13 -0700)]
log: Implement --follow

The FollowFilter can be installed on a RevWalk to cause the path
to be updated through rename detection when the affected file is
found to be added to the project.

The filter works reasonably well, for example we can follow the
history of the fsck command in git-core:

  $ jgit log --name-status --follow builtin/fsck.c | grep ^R
  R100 builtin-fsck.c builtin/fsck.c
  R099 fsck.c builtin-fsck.c
  R099 fsck-objects.c fsck.c
  R099 fsck-cache.c fsck-objects.c

Change-Id: I4017bcfd150126aa342fdd423a688493ca660a1f
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoCache the diff configuration section 54/1054/1
Shawn O. Pearce [Sun, 4 Jul 2010 01:16:20 +0000 (18:16 -0700)]
Cache the diff configuration section

This way we don't have to reparse for the rename limit every time
we create a new rename detector for a repository.

Change-Id: I669d031690b85ef4da5e39189be7173fb773fc56
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agolog: Add whitespace ignore options 53/1053/1
Shawn O. Pearce [Sun, 4 Jul 2010 00:32:47 +0000 (17:32 -0700)]
log: Add whitespace ignore options

Similar to what we did with diff, implement whitespace ignore options
for log too.  This requires us to define some means of creating any
RawText object type at will inside of DiffFormatter, so we define a
new factory interface to construct RawText instances on demand.

Unfortunately we have to copy the entire block of common options.
args4j only processes the options/arguments on the one command class
and Java doesn't support multiple inheritance.

Change-Id: Ia16cd3a11b850fffae9fbe7b721d7e43f1d0e8a5
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoFormat submodule links during differences 52/1052/1
Shawn O. Pearce [Sat, 3 Jul 2010 23:59:06 +0000 (16:59 -0700)]
Format submodule links during differences

Instead of crashing, output a submodule link with the simple
"Subproject commit $fullid\n" syntax used by C Git.

Change-Id: Iae8646941683fb19b73fb038217d2e3bf5f77fa9
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoRedo DiffFormatter API to be easier to use 51/1051/1
Shawn O. Pearce [Sat, 3 Jul 2010 23:58:37 +0000 (16:58 -0700)]
Redo DiffFormatter API to be easier to use

Passing around the OutputStream and the Repository is crazy.  Instead
put the stream in the constructor, since this formatter exists only to
output to the stream, and put the repository as a member variable that
can be optionally set.

Change-Id: I2bad012fee7f40dc1346700ebd19f1e048982878
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agolog, diff: Add rename detection support 50/1050/1
Shawn O. Pearce [Sat, 3 Jul 2010 22:49:07 +0000 (15:49 -0700)]
log, diff: Add rename detection support

Implement rename detection in the command line diff and log commands.
Also support --name-status, -p and -U flags, as these can be quite
useful to view more detail.

All of the Git patch file formatting code is now moved over to the
DiffFormatter class.  This permits us to reuse it in any context,
including inside of IDEs.

Change-Id: I687ccba34e18105a07e0a439d2181c323209d96c
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoImplement similarity based rename detection 48/1048/2
Shawn O. Pearce [Sat, 3 Jul 2010 00:29:09 +0000 (17:29 -0700)]
Implement similarity based rename detection

Content similarity based rename detection is performed only after
a linear time detection is performed using exact content match on
the ObjectIds.  Any names which were paired up during that exact
match phase are excluded from the inexact similarity based rename,
which reduces the space that must be considered.

During rename detection two entries cannot be marked as a rename
if they are different types of files.  This prevents a symlink from
being renamed to a regular file, even if their blob content appears
to be similar, or is identical.

Efficiently comparing two files is performed by building up two
hash indexes and hashing lines or short blocks from each file,
counting the number of bytes that each line or block represents.

Instead of using a standard java.util.HashMap, we use a custom
open hashing scheme similiar to what we use in ObjecIdSubclassMap.
This permits us to have a very light-weight hash, with very little
memory overhead per cell stored.

As we only need two ints per record in the map (line/block key and
number of bytes), we collapse them into a single long inside of
a long array, making very efficient use of available memory when
we create the index table.  We only need object headers for the
index structure itself, and the index table, but not per-cell.
This offers a massive space savings over using java.util.HashMap.

The score calculation is done by approximating how many bytes are
the same between the two inputs (which for a delta would be how much
is copied from the base into the result).  The score is derived by
dividing the approximate number of bytes in common into the length
of the larger of the two input files.

Right now the SimilarityIndex table should average about 1/2 full,
which means we waste about 50% of our memory on empty entries
after we are done indexing a file and sort the table's contents.
If memory becomes an issue we could discard the table and copy all
records over to a new array that is properly sized.

Building the index requires O(M + N log N) time, where M is the
size of the input file in bytes, and N is the number of unique
lines/blocks in the file.  The N log N time constraint comes
from the sort of the index table that is necessary to perform
linear time matching against another SimilarityIndex created for
a different file.

To actually perform the rename detection, a SxD matrix is created,
placing the sources (aka deletions) along one dimension and the
destinations (aka additions) along the other.  A simple O(S x D)
loop examines every cell in this matrix.

A SimilarityIndex is built along the row and reused for each
column compare along that row, avoiding the costly index rebuild
at the row level.  A future improvement would be to load a smaller
square matrix into SimilarityIndexes and process everything in that
sub-matrix before discarding the column dimension and moving down
to the next sub-matrix block along that same grid of rows.

An optional ProgressMonitor is permitted to be passed in, allowing
applications to see the progress of the detector as it works through
the matrix cells.  This provides some indication of current status
for very long running renames.

The default line/block hash function used by the SimilarityIndex
may not be optimal, and may produce too many collisions.  It is
borrowed from RawText's hash, which is used to quickly skip out of
a longer equality test if two lines have different hash functions.
We may need to refine this hash in the future, in order to minimize
the number of collisions we get on common source files.

Based on a handful of test commits in JGit (especially my own
recent rename repository refactoring series), this rename detector
produces output that is very close to C Git.  The content similarity
scores are sometimes off by 1%, which is most probably caused by
our SimilarityIndex type using a different hash function than C
Git uses when it computes the delta size between any two objects
in the rename matrix.

Bug: 318504
Change-Id: I11dff969e8a2e4cf252636d857d2113053bdd9dc
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoImprove description of isBare and NoWorkTreeException 47/1047/3
Shawn O. Pearce [Sat, 3 Jul 2010 00:12:30 +0000 (17:12 -0700)]
Improve description of isBare and NoWorkTreeException

Alex pointed out that my description of a bare repository might be
confusing for some readers.  Reword the description of the error,
and make it consistent throughout the Repository class's API.

Change-Id: I87929ddd3005f578a7022f363270952d1f7f8664
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoamend commit: Refactor repository construction to builder class 46/1046/3
Shawn O. Pearce [Sat, 3 Jul 2010 00:01:40 +0000 (17:01 -0700)]
amend commit: Refactor repository construction to builder class

During code review, Alex raised a few comments about commit
532421d98925 ("Refactor repository construction to builder class").
Due to the size of the related series we aren't going to go back
and rebase in something this minor, so resolve them as a follow-up
commit instead.

Change-Id: Ied52f7a8f7252743353c58d20bfc3ec498933e00
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoRemove pointless size test in PackFile decompress 45/1045/2
Shawn O. Pearce [Fri, 2 Jul 2010 23:56:31 +0000 (16:56 -0700)]
Remove pointless size test in PackFile decompress

Now that any large objects are forced through a streaming loader
when its bigger than getStreamFileThreshold(), and that threshold
is pegged at Integer.MAX_VALUE as its largest size, we will never
be able to reach this code path where we threw OutOfMemoryError.

Robin pointed out that we probably should include a message here,
but the code is effectively unreachable, so there isn't any value
in adding a message at this point.

So remove it.

Change-Id: Ie611d005622e38a75537f1350246df0ab89dd500
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAvoid unbounded getCachedBytes during parseAny 44/1044/2
Shawn O. Pearce [Fri, 2 Jul 2010 22:05:32 +0000 (15:05 -0700)]
Avoid unbounded getCachedBytes during parseAny

Since we don't know the type of object we are parsing, we don't
know if its a massive blob, or some small commit or annotated tag.
Avoid pulling the cached bytes until we have checked the type and
decided if we actually need them to continue parsing right now.

This way large blobs which won't fit in memory and would throw
a LargeObjectException don't abort parsing.

Change-Id: Ifb70df5d1c59f616aa20ee88898cb69524541636
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoMake type and size lazy for large delta objects 42/1042/2
Shawn O. Pearce [Fri, 2 Jul 2010 20:12:06 +0000 (13:12 -0700)]
Make type and size lazy for large delta objects

Callers don't necessarily need the getSize() result from a large
delta.  They instead should be always using openStream() or copyTo()
for blobs going to local files, or they should be checking the
result of the constant-time isLarge() method to determine the type
of access they can use on the ObjectLoader.  Avoid inflating the
delta instruction stream twice by delaying the decoding of the size
until after we have created the DeltaStream and decoded the header.

Likewise with the type, callers don't necessarily always need it
to be present in an ObjectLoader.  Delay looking at it as late as
we can, thereby avoiding an ugly O(N^2) loop looking up the type
for every single object in the entire delta chain.

Change-Id: I6487b75b52a5d201d811a8baed2fb4fcd6431320
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoClean up LICENSE file 40/1040/3
Shawn O. Pearce [Fri, 2 Jul 2010 21:52:49 +0000 (14:52 -0700)]
Clean up LICENSE file

We used our LICENSE file to describe both the license of the package,
and also the header template that should appear at the start of
all Java files we create.  This creates a confusing situation for
readers who just want to consume the package, because our file
header template starts off in the middle of a sentence.

Move our template header to a separate file, and reformat the text
of the license to be something more readable by a person reviewing
the project's terms of use.

Change-Id: If318e64c06683ea14e0240914c2d057c9199ce98
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoUse core.streamFileThreshold to set our streaming limit 41/1041/1
Shawn O. Pearce [Fri, 2 Jul 2010 19:41:39 +0000 (12:41 -0700)]
Use core.streamFileThreshold to set our streaming limit

We default this to 1 MiB for now, but we allow users to modify
it through the Repository's configuration file to be a different
value.  A new repository listener is used to identify when the
setting has been updated and trigger a reconfiguration of any
active ObjectReaders.

To prevent a horrible explosion we cap core.streamFileThreshold
at no more than 1/4 of the maximum JVM heap size.  We do this
because we need at least 2 byte arrays equal in size to the
stream threshold for the worst case delta inflation scenario,
and our host application probably also needs some amount of the
heap for their working set size.

Change-Id: I103b3a541dc970bbf1a6d92917a12c5a1ee34d6c
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoSupport large delta packed objects as streams 35/1035/1
Shawn O. Pearce [Fri, 2 Jul 2010 09:19:12 +0000 (02:19 -0700)]
Support large delta packed objects as streams

Very large delta instruction streams, or deltas which use very large
base objects, are now streamed through as large objects rather than
being inflated into a byte array.

This isn't the most efficient way to access delta encoded content, as
we may need to rewind and reprocess the base object when there was a
block moved within the file, but it will at least prevent the JVM from
having its heap explode.

When streaming a delta we have an inflater open for each level in the
delta chain, to inflate the instruction set of the delta, as well as
an inflater for the base level object.  The base object is buffered,
as is the top level delta requested by the application, but we do not
buffer the intermediate delta streams.  This keeps memory usage lower,
so its closer to 1024 bytes per level in the chain, without having an
adverse impact on raw throughput as the top-level buffer gets pushed
down to the lowest stream that has the next region.

Delta instructions transparently collapse here, if the top level does
not copy a region from its base, the base won't materialize that part
from its own base, etc.  This allows us to avoid copying around a lot
of segments which have been deleted from the final version.

Change-Id: I724d45245cebb4bad2deeae7b896fc55b2dd49b3
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoSupport large whole packed objects as streams 34/1034/1
Shawn O. Pearce [Fri, 2 Jul 2010 02:34:21 +0000 (19:34 -0700)]
Support large whole packed objects as streams

Similar to the loose object support, whole packed objects can
now be streamed back to the caller.  The streaming is less
efficient as we copy the data from the cached window array
into the InflaterInputStream's internal buffer, then inflate
it there before returning to the application.

Like with unpacked objects, there is plenty of room for some
optimization, especially for the copyTo method, where we don't
necessarily need so much buffering to exist.

Change-Id: Ie23be81289e37e24b91d17b0891e47b9da988008
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoReplace PackedObjectLoader with ObjectLoader.SmallObject 33/1033/1
Shawn O. Pearce [Fri, 2 Jul 2010 01:27:51 +0000 (18:27 -0700)]
Replace PackedObjectLoader with ObjectLoader.SmallObject

The class is identical, but ObjectLoader.SmallObject is part of our
public API for storage implementations to build on top of.

Change-Id: I381a3953b14870b6d3d74a9c295769ace78869dc
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoSupport large loose objects as streams 32/1032/1
Shawn O. Pearce [Fri, 2 Jul 2010 01:26:17 +0000 (18:26 -0700)]
Support large loose objects as streams

Big loose objects can now be streamed if they are over the large
object size threshold.  This prevents the JVM heap from exploding
with a very large byte array to hold the slurped file, and then
again with its uncompressed copy.

We may have slightly slowed down the simple case for small
loose objects, as the loader no longer slurps the entire thing
and decompresses in memory.  To try and keep good performance
for the very common small objects that are below 8 KiB in size,
buffers are set to 8 KiB, causing the reader to slurp most of the
file anyway.  However the data has to be copied at least once,
from the BufferedInputStream into the InflaterInputStream.

New unit tests are supplied to get nearly 100% code coverage on the
unpacked code paths, for both standard and pack style loose objects.
We tested a fair chunk of the code elsewhere, but these new tests
are better isolated to the specific branches in the code path.

Change-Id: I87b764ab1b84225e9b5619a2a55fd8eaa640e1fe
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAdded a preliminary version of rename detection 29/1029/5
Jeff Schumacher [Thu, 1 Jul 2010 22:30:46 +0000 (15:30 -0700)]
Added a preliminary version of rename detection

JGit does not currently do rename detection during diffs. I added
a class that, given a TreeWalk to iterate over, can output a list
of DiffEntry's for that TreeWalk, taking into account renames. This
class only detects renames by SHA1's. More complex rename detection,
along the lines of what C Git does will be added later.

Change-Id: I93606ce15da70df6660651ec322ea50718dd7c04

14 years agoPermit AnyObjectTo to compareTo AnyObjectId 26/1026/1
Shawn O. Pearce [Thu, 1 Jul 2010 02:07:36 +0000 (19:07 -0700)]
Permit AnyObjectTo to compareTo AnyObjectId

Assume that the argument of compareTo won't be mutated while we
are doing the compare, and support the wider AnyObjectId type so
MutableObjectId is suitable on either side of the compareTo call.

Change-Id: I2a63a496c0a7b04f0e5f27d588689c6d5e149d98
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoUse copyTo during checkout of files to working tree 25/1025/1
Shawn O. Pearce [Thu, 1 Jul 2010 01:56:20 +0000 (18:56 -0700)]
Use copyTo during checkout of files to working tree

This way we can stream a large file through memory, rather than
loading the entire thing into a single contiguous byte array.

Change-Id: I3ada2856af2bf518f072edec242667a486fb0df1
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoStream whole deflated objects in PackWriter 24/1024/1
Shawn O. Pearce [Thu, 1 Jul 2010 01:50:50 +0000 (18:50 -0700)]
Stream whole deflated objects in PackWriter

Instead of loading the entire object as a byte array and passing
that into the deflater, let the ObjectLoader copy the object onto
the DeflaterOutputStream.  This has the nice side effect of using
some sort of stride hack in the Sun implementation that may improve
compression performance.

Change-Id: I3f3d681b06af0da93ab96c75468e00e183ff32fe
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoLazily allocate Deflater in PackWriter 23/1023/1
Shawn O. Pearce [Thu, 1 Jul 2010 01:40:54 +0000 (18:40 -0700)]
Lazily allocate Deflater in PackWriter

Only allocate the Deflater if we can't reuse everything, but also
make sure we release it when we release the PackWriter's resources.

Change-Id: I16a32b94647af0778658eda87acbafc9a25b314a
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoAdd openStream to ObjectLoader for big blobs 22/1022/1
Shawn O. Pearce [Thu, 1 Jul 2010 01:36:10 +0000 (18:36 -0700)]
Add openStream to ObjectLoader for big blobs

Blobs that are too large to read as a single byte array should be
accessed through an InputStream based interface instead, allowing
the application to walk through the data stream incrementally.

Define the basic interface to support streaming contents, but don't
implement it yet for the file based backend.

Change-Id: If9e4442e9ef4ed52c3e0f1af9398199a73145516
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoRefactored code out of FileHeader to facilitate rename detection 15/1015/3
Jeff Schumacher [Wed, 30 Jun 2010 23:21:49 +0000 (16:21 -0700)]
Refactored code out of FileHeader to facilitate rename detection

Refactored a superclass out of FileHeader called DiffEntry that holds
the more general data from FileHeader that is useful in rename
detection (old/new Ids, modes, names, as well as changeType and
score). FileHeader is now a DiffEntry that adds Hunks, parsing
abilities, etc.

Change-Id: I8398728cd218f8c6e98f7a4a7f2f342391d865e4

14 years agoFix missing flush in StreamCopyThread
Dmitry Neverov [Wed, 30 Jun 2010 17:46:53 +0000 (10:46 -0700)]
Fix missing flush in StreamCopyThread

It is possible that StreamCopyThread will not flush everything
from it's src to it's dst.  In most cases StreamCopyThread works
like this:

  in loop:
    n = src.read(buf);
    dst.write(buf, 0, n);

and when we want to flush, we interrupt() StreamCopyThread and it
flushes everything it wrote to dst.

The problem is that our interrupt() could interrupt reading. In this
case we will flush everything we wrote to dst, but not everything
we wrote to src.

Change-Id: Ifaf4d8be87535c7364dd59b217dfc631460018ff
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
14 years agoMove DirCache factory methods to Repository 14/1014/1
Shawn O. Pearce [Wed, 30 Jun 2010 17:39:00 +0000 (10:39 -0700)]
Move DirCache factory methods to Repository

Instead of creating the DirCache from a static factory method, use
an instance method on Repository, permitting the implementation to
override the method with a completely different type of DirCache
reading and writing.  This would better support a repository in the
cloud strategy, or even just an in-memory unit test environment.

Change-Id: I6399894b12d6480c4b3ac84d10775dfd1b8d13e7
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>