Age | Commit message (Collapse) | Author | Files | Lines |
|
* jk/merge-rename-ux:
pull: propagate --progress to merge
merge: enable progress reporting for rename detection
add inexact rename detection progress infrastructure
commit: stop setting rename limit
bump rename limit defaults (again)
merge: improve inexact rename limit warning
|
|
We might spend many seconds doing inexact rename detection
with no output. It's nice to let the user know that
something is actually happening.
This patch adds the infrastructure, but no callers actually
turn on progress reporting.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The warning is generated deep in the diffcore code, which
means that it will come first, followed possibly by a spew
of conflicts, making it hard to see.
Instead, let's have diffcore pass back the information about
how big the rename limit would needed to have been, and then
the caller can provide a more appropriate message (and at a
more appropriate time).
No refactoring of other non-merge callers is necessary,
because nobody else was even using the warn_on_rename_limit
feature.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The logic to quickly dismiss potential rename pairs was broken. It
would too eagerly dismiss possible renames when all of the difference
was due to pure new data (or deleted data).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
We would allow rename detection to do copy detection even when asked
purely for renames. That confuses users, but more importantly it can
terminally confuse the recursive merge rename logic.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
For the find_exact_renames() function, this allows us to pass the
diff_options structure pointer to the low-level routines. We will use
that to distinguish between the "rename" and "copy" cases.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Refactor the diff_queue_struct code, this macro help
to reset the structure.
Signed-off-by: Bo Yang <struggleyb.nku@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
After running one round of estimate_similarity(), filespecs on either
side will have populated their cnt_data fields, and we do not need
the blob text anymore. We used to retain the blob data to optimize
for smaller projects (not freeing the blob data here would mean that
the final output phase would not have to re-read it), but we are
efficient enough without such optimization for smaller projects anyway,
and freeing memory early will help larger projects.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Signed-off-by: Mike Ralphson <mike@abacus.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
In diffcore_rename, we assume that the blob contents in the filespec
aren't required anymore after estimate_similarity has been called and thus
we free it. But estimate_similarity might return early when the file sizes
differ too much. In that case, cnt_data is never set and the next call to
estimate_similarity will populate the filespec again, eventually rereading
the same blob over and over again.
To fix that, we first get the blob sizes and only when the blob contents
are actually required, and when cnt_data will be set, the full filespec is
populated, once.
Signed-off-by: Björn Steinbrink <B.Steinbrink@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When we refuse to do rename detection due to having too many files
created or deleted, let the user know the numbers. That way there is a
reasonable starting point for setting the diff.renamelimit option.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
In many cases, the warning ends up as clutter, because the
diff is being done "behind the scenes" from the user (e.g.,
when generating a commit diffstat), and whether we show
renames or not is not particularly interesting to the user.
However, in the case of a merge (which is what motivated the
warning in the first place), it is a useful hint as to why a
merge with renames might have failed.
This patch makes the warning optional based on the code
calling into diffcore. We default to not showing the
warning, but turn it on for merges.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
* 'jc/rename' (early part):
Optimize rename detection for a huge diff
|
|
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When there are N deleted paths and M created paths, we used to
allocate (N x M) "struct diff_score" that record how similar
each of the pair is, and picked the <src,dst> pair that gives
the best match first, and then went on to process worse matches.
This sorting is done so that when two new files in the postimage
that are similar to the same file deleted from the preimage, we
can process the more similar one first, and when processing the
second one, it can notice "Ah, the source I was planning to say
I am a copy of is already taken by somebody else" and continue
on to match itself with another file in the preimage with a
lessor match. This matters to a change introduced between
1.5.3.X series and 1.5.4-rc, that lets the code to favor unused
matches first and then falls back to using already used
matches.
This instead allocates and keeps only a handful rename source
candidates per new files in the postimage. I.e. it makes the
memory requirement from O(N x M) to O(M).
For each dst, we compute similarlity with all sources (i.e. the
number of similarity estimate computations is still O(N x M)),
but we keep handful best src candidates for each dst.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
On Thu, 29 Nov 2007, Jeff King wrote:
>
> I think it will get worse, because you are simultaneously calculating
> all of the similarity scores bit by bit rather than doing a loop. Though
> perhaps you mean at the end you will end up with a list of src/dst pairs
> sorted by score, and you can loop over that.
Well, after thinking about this a bit, I think there's a solution that may
work well with the current thing too: instead of looping just *once* over
the list of rename pairs, loop twice - and simply refuse to do copies on
the first loop.
This trivial patch does that, and turns Kumar's test-case into a perfect
rename list.
It's not pretty, it's not smart, but it seems to work. There's something
to be said for keeping it simple and stupid.
And it should not be nearly as expensive as it may _look_. Yes, the loop
is "(i = 0; i < num_create * num_src; i++)", but the important part is
that the whole array is sorted by rename score, and we have a
if (mx[i].score < minimum_score)
break;
in it, so uthe loop actually would tend to terminate rather quickly.
Anyway, Kumar, the thing to take away from this is:
- git really doesn't even *care* about the whole "rename detection"
internally, and any commits you have done with renames are totally
independent of the heuristics we then use to *show* the renames.
- the rename detection really is for just two reasons: (a) keep humans
happy, and keep the diffs small and (b) help automatic merging across
renames. So getting renames right is certainly good, but it's more of a
"politeness" issue than a "correctness" issue, although the merge
portion of it does matter a lot sometimes.
- the important thing here is that you can commit your changes and not
worry about them being somehow "corrupted" by lack of rename detection,
even if you commit them with a version of git that doesn't do rename
detection the way you expected it. The rename detection is an
"after-the-fact" thing, not something that actually gets saved in the
repository, which is why we can change the heuristics _after_ seeing
examples, and the examples magically correct themselves!
- try out the two patches I've posted, and see if they work for you. They
pass the test-suite, and the output for your example commit looks sane,
but hey, if you have other test-cases, try them out.
Here's Kumar's pretty diffstat with both my patches:
Makefile | 6 +++---
board/{cds => freescale}/common/cadmus.c | 0
board/{cds => freescale}/common/cadmus.h | 0
board/{cds => freescale}/common/eeprom.c | 0
board/{cds => freescale}/common/eeprom.h | 0
board/{cds => freescale}/common/ft_board.c | 0
board/{cds => freescale}/common/via.c | 0
board/{cds => freescale}/common/via.h | 0
board/{cds => freescale}/mpc8541cds/Makefile | 0
board/{cds => freescale}/mpc8541cds/config.mk | 0
board/{cds => freescale}/mpc8541cds/init.S | 0
board/{cds => freescale}/mpc8541cds/mpc8541cds.c | 0
board/{cds => freescale}/mpc8541cds/u-boot.lds | 4 ++--
board/{cds => freescale}/mpc8548cds/Makefile | 0
board/{cds => freescale}/mpc8548cds/config.mk | 0
board/{cds => freescale}/mpc8548cds/init.S | 0
board/{cds => freescale}/mpc8548cds/mpc8548cds.c | 0
board/{cds => freescale}/mpc8548cds/u-boot.lds | 4 ++--
board/{cds => freescale}/mpc8555cds/Makefile | 0
board/{cds => freescale}/mpc8555cds/config.mk | 0
board/{cds => freescale}/mpc8555cds/init.S | 0
board/{cds => freescale}/mpc8555cds/mpc8555cds.c | 0
board/{cds => freescale}/mpc8555cds/u-boot.lds | 4 ++--
23 files changed, 9 insertions(+), 9 deletions(-)
and here it is before:
Makefile | 6 +-
board/cds/mpc8548cds/Makefile | 60 -----
board/cds/mpc8555cds/Makefile | 60 -----
board/cds/mpc8555cds/init.S | 255 --------------------
board/cds/mpc8555cds/u-boot.lds | 150 ------------
board/{cds => freescale}/common/cadmus.c | 0
board/{cds => freescale}/common/cadmus.h | 0
board/{cds => freescale}/common/eeprom.c | 0
board/{cds => freescale}/common/eeprom.h | 0
board/{cds => freescale}/common/ft_board.c | 0
board/{cds => freescale}/common/via.c | 0
board/{cds => freescale}/common/via.h | 0
board/{cds => freescale}/mpc8541cds/Makefile | 0
board/{cds => freescale}/mpc8541cds/config.mk | 0
board/{cds => freescale}/mpc8541cds/init.S | 0
board/{cds => freescale}/mpc8541cds/mpc8541cds.c | 0
board/{cds => freescale}/mpc8541cds/u-boot.lds | 4 +-
.../mpc8541cds => freescale/mpc8548cds}/Makefile | 0
board/{cds => freescale}/mpc8548cds/config.mk | 0
board/{cds => freescale}/mpc8548cds/init.S | 0
board/{cds => freescale}/mpc8548cds/mpc8548cds.c | 0
board/{cds => freescale}/mpc8548cds/u-boot.lds | 4 +-
.../mpc8541cds => freescale/mpc8555cds}/Makefile | 0
board/{cds => freescale}/mpc8555cds/config.mk | 0
.../mpc8541cds => freescale/mpc8555cds}/init.S | 0
board/{cds => freescale}/mpc8555cds/mpc8555cds.c | 0
.../mpc8541cds => freescale/mpc8555cds}/u-boot.lds | 4 +-
27 files changed, 9 insertions(+), 534 deletions(-)
so it certainly makes the diffs prettier.
Linus
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Kumar Gala had a case in the u-boot archive with multiple renames of files
with identical contents, and git would turn those into multiple "copy"
operations of one of the sources, and just deleting the other sources.
This patch makes the git exact rename detection prefer to spread out the
renames over the multiple sources, rather than do multiple copies of one
source.
NOTE! The changes are a bit larger than required, because I also renamed
the variables named "one" and "two" to "target" and "source" respectively.
That makes the logic easier to follow, especially as the "one" was
illogically the target and not the soruce, for purely historical reasons
(this piece of code used to traverse over sources and targets in the wrong
order, and when we fixed that, we didn't fix the names back then. So I
fixed them now).
The important part of this change is just the trivial score calculations
for when files have identical contents:
/* Give higher scores to sources that haven't been used already */
score = !source->rename_used;
score += basename_same(source, target);
and when we have multiple choices we'll now pick the choice that gets the
best rename score, rather than only looking at whether the basename
matched.
It's worth noting a few gotchas:
- this scoring is currently only done for the "exact match" case.
In particular, in Kumar's example, even after this patch, the inexact
match case is still done as a copy+delete rather than as two renames:
delete mode 100644 board/cds/mpc8555cds/u-boot.lds
copy board/{cds => freescale}/mpc8541cds/u-boot.lds (97%)
rename board/{cds/mpc8541cds => freescale/mpc8555cds}/u-boot.lds (97%)
because apparently the "cds/mpc8541cds/u-boot.lds" copy looked
a bit more similar to both end results. That said, I *suspect* we just
have the exact same issue there - the similarity analysis just gave
identical (or at least very _close_ to identical) similarity points,
and we do not have any logic to prefer multiple renames over a
copy/delete there.
That is a separate patch.
- When you have identical contents and identical basenames, the actual
entry that is chosen is still picked fairly "at random" for the first
one (but the subsequent ones will prefer entries that haven't already
been used).
It's not actually really random, in that it actually depends on the
relative alphabetical order of the files (which in turn will have
impacted the order that the entries got hashed!), so it gives
consistent results that can be explained. But I wanted to point it out
as an issue for when anybody actually does cross-renames.
In Kumar's case the choice is the right one (and for a single normal
directory rename it should always be, since the relative alphabetical
sorting of the files will be identical), and we now get:
rename board/{cds => freescale}/mpc8541cds/init.S (100%)
rename board/{cds => freescale}/mpc8548cds/init.S (100%)
which is the "expected" answer. However, it might still be better to
change the pedantic "exact same basename" on/off choice into a more
graduated "how similar are the pathnames" scoring situation, in order
to be more likely to get the exact rename choice that people *expect*
to see, rather than other alternatives that may *technically* be
equally good, but are surprising to a human.
It's also unclear whether we should consider "basenames are equal" or
"have already used this as a source" to be more important. This gives them
equal weight, but I suspect we might want to just multiple the "basenames
are equal" weight by two, or something, to prefer equal basenames even if
that causes a copy/delete pair. I dunno.
Anyway, what I'm just saying in a really long-winded manner is that I
think this is right as-is, but it's not the complete solution, and it may
want some further tweaking in the future.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When we do the fuzzy rename detection, we don't care about the
destinations that we already handled with the exact rename detector.
And, in fact, the code already knew that - but the rename limiter, which
used to run *before* exact renames were detected, did not.
This fixes it so that the rename detection limiter now bases its
decisions on the *remaining* rename counts, rather than the original
ones.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
For historical reasons, the exact rename detection had populated the
filespecs for the entries it compared, and the rest of the similarity
analysis depended on that. I hadn't even bothered to debug why that was
the case when I re-did the rename detection, I just made the new one
have the same broken behaviour, with a note about this special case.
This fixes that fixme. The reason the exact rename detector needed to
fill in the file sizes of the files it checked was that the _inexact_
rename detector was broken, and started comparing file sizes before it
filled them in.
Fixing that allows the exact phase to do the sane thing of never even
caring (since all *it* cares about is really just the SHA1 itself, not
the size nor the contents).
It turns out that this also indirectly fixes a bug: trying to populate
all the filespecs will run out of virtual memory if there is tons and
tons of possible rename options. The fuzzy similarity analysis does the
right thing in this regard, and free's the blob info after it has
generated the hash tables, so the special case code caused more trouble
than just some extra illogical code.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Now that the exact rename detection is linear-time (with a very small
constant factor to boot), there is no longer any reason to limit it by
the number of files involved.
In some trivial testing, I created a repository with a directory that
had a hundred thousand files in it (all with different contents), and
then moved that directory to show the effects of renaming 100,000 files.
With the new code, that resulted in
[torvalds@woody big-rename]$ time ~/git/git show -C | wc -l
400006
real 0m2.071s
user 0m1.520s
sys 0m0.576s
ie the code can correctly detect the hundred thousand renames in about 2
seconds (the number "400006" comes from four lines for each rename:
diff --git a/really-big-dir/file-1-1-1-1-1 b/moved-big-dir/file-1-1-1-1-1
similarity index 100%
rename from really-big-dir/file-1-1-1-1-1
rename to moved-big-dir/file-1-1-1-1-1
and the extra six lines is from a one-liner commit message and all the
commit information and spacing).
Most of those two seconds weren't even really the rename detection, it's
really all the other stuff needed to get there.
With the old code, this wouldn't have been practically possible. Doing
a pairwise check of the ten billion possible pairs would have been
prohibitively expensive. In fact, even with the rename limiter in
place, the old code would waste a lot of time just on the diff_filespec
checks, and despite not even trying to find renames, it used to look
like:
[torvalds@woody big-rename]$ time git show -C | wc -l
1400006
real 0m12.337s
user 0m12.285s
sys 0m0.192s
ie we used to take 12 seconds for this load and not even do any rename
detection! (The number 1400006 comes from fourteen lines per file moved:
seven lines each for the delete and the create of a one-liner file, and
the same extra six lines of commit information).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
This implements a smarter rename detector for exact renames, which
rather than doing a pairwise comparison (time O(m*n)) will just hash the
files into a hash-table (size O(n+m)), and only do pairwise comparisons
to renames that have the same hash (time O(n+m) except for unrealistic
hash collissions, which we just cull aggressively).
Admittedly the exact rename case is not nearly as interesting as the
generic case, but it's an important case none-the-less. A similar general
approach should work for the generic case too, but even then you do need
to handle the exact renames/copies separately (to avoid the inevitable
added cost factor that comes from the _size_ of the file), so this is
worth doing.
In the expectation that we will indeed do the same hashing trick for the
general rename case, this code uses a generic hash-table implementation
that can be used for other things too. In fact, we might be able to
consolidate some of our existing hash tables with the new generic code
in hash.[ch].
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
The core rename detection had some rather stupid code to check if a
pathname was used by a later modification or rename, which basically
walked the whole pathname space for all renames for each rename, in
order to tell whether it was a pure rename (no remaining users) or
should be considered a copy (other users of the source file remaining).
That's really silly, since we can just keep a count of users around, and
replace all those complex and expensive loops with just testing that
simple counter (but this all depends on the previous commit that shared
the diff_filespec data structure by using a separate reference count).
Note that the reference count is not the same as the rename count: they
behave otherwise rather similarly, but the reference count is tied to
the allocation (and decremented at de-allocation, so that when it turns
zero we can get rid of the memory), while the rename count is tied to
the renames and is decremented when we find a rename (so that when it
turns zero we know that it was a rename, not a copy).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Rather than copy the filespecs when introducing new versions of them
(for rename or copy detection), use a refcount and increment the count
when reusing the diff_filespec.
This avoids unnecessary allocations, but the real reason behind this is
a future enhancement: we will want to track shared data across the
copy/rename detection. In order to efficiently notice when a filespec
is used by a rename, the rename machinery wants to keep track of a
rename usage count which is shared across all different users of the
filespec.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
This makes the exact content match a separate function of its own.
Partly to cut down a bit on the size of the diffcore_rename() function
(which is too complex as it is), and partly because there are smarter
ways to do this than an O(m*n) loop over it all, and that function
should be rewritten to take that into account.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
We find rename candidates by computing a fingerprint hash of
each file, and then comparing those fingerprints. There are
inherently O(n^2) comparisons, so it pays in CPU time to
hoist the (rather expensive) computation of the fingerprint
out of that loop (or to cache it once we have computed it once).
Previously, we didn't keep the filespec information around
because then we had the potential to consume a great deal of
memory. However, instead of keeping all of the filespec
data, we can instead just keep the fingerprint.
This patch implements and uses diff_free_filespec_data_large
to accomplish that goal. We also have to change
estimate_similarity not to needlessly repopulate the
filespec data when we already have the hash.
Practical tests showed 4.5x speedup for a 10% memory usage
increase.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
This adds more proper rename detection limits. Instead of just checking
the limit against the number of potential rename destinations, we verify
that the rename matrix (which is what really matters) doesn't grow
ridiculously large, and we also make sure that we don't overflow when
doing the matrix size calculation.
This also changes the default limits from unlimited, to a rename matrix
that is limited to 100 entries on a side. You can raise it with the config
entry, or by using the "-l<n>" command line flag, but at least the default
is now a sane number that avoids spending lots of time (and memory) in
situations that likely don't merit it.
The choice of default value is of course very debatable. Limiting the
rename matrix to a 100x100 size will mean that even if you have just one
obvious rename, but you also create (or delete) 10,000 files, the rename
matrix will be so big that we disable the heuristics. Sounds reasonable to
me, but let's see if people hit this (and, perhaps more importantly,
actually *care*) in real life.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
* jc/diffcore:
diffcore-delta.c: Ignore CR in CRLF for text files
diffcore-delta.c: update the comment on the algorithm.
diffcore_filespec: add is_binary
diffcore_count_changes: pass diffcore_filespec
|
|
We may want to use richer information on the data we are dealing
with in this function, so instead of passing a buffer address
and length, just pass the diffcore_filespec structure. Existing
callers always call this function with parameters taken from a
filespec anyway, so there is no functionality changes.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
This implements a suggestion from Johannes. It uses a separate field in
struct diff_score to keep the result of the file name comparison in the
rename detection logic. This reverts the value of the similarity index
to be a function of file contents, only, and basename comparison is only
used to decide between files with equal amounts of content changes.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
When there are several candidates for a rename source, and one of them
has an identical basename to the rename target, take that one.
Noticed by Govind Salinas, posted by Shawn O. Pearce, partial patch
by Linus Torvalds.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
We released the postimage candidate blobs after we are done to reduce
memory pressure. Do the same for preimage candidate blobs.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
Some systems have sizeof(off_t) == 8 while sizeof(size_t) == 4.
This implies that we are able to access and work on files whose
maximum length is around 2^63-1 bytes, but we can only malloc or
mmap somewhat less than 2^32-1 bytes of memory.
On such a system an implicit conversion of off_t to size_t can cause
the size_t to wrap, resulting in unexpected and exciting behavior.
Right now we are working around all gcc warnings generated by the
-Wshorten-64-to-32 option by passing the off_t through xsize_t().
In the future we should make xsize_t on such problematic platforms
detect the wrapping and die if such a file is accessed.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
When comparing file contents during the second loop through a rename
detection attempt we can skip the expensive byte-by-byte comparsion
if both source and destination files have valid SHA1 values. This
improves performance by avoiding either an expensive open/mmap to
read the working tree copy, or an expensive inflate of a blob object.
Unfortunately we still have to at least initialize the sizes of the
source and destination files even if the SHA1 values don't match.
Failing to initialize the sizes causes a number of test cases to fail
and start reporting different copy/rename behavior than was expected.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
The idea is that we are interested in renaming into only one path, so
we do not care about renames that happen elsewhere.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
Introduces global inline:
hashcmp(const unsigned char *sha1, const unsigned char *sha2)
Uses memcmp for comparison and returns the result based on the length of
the hash name (a future runtime decision).
Acked-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: David Rientjes <rientjes@google.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
The final output from diff used to compare pathnames between
preimage and postimage to tell if the filepair is a rename/copy.
By explicitly marking the filepair created by diffcore_rename(),
the output routine, resolve_rename_copy(), does not have to do
so anymore. This helps feeding a filepair that has different
pathnames in one and two elements to the diff machinery (most
notably, comparing two blobs).
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
When a broken pair is matched up by rename detector to be merged
back, we do not want to say it is "dissimilar" with the
similarity index. The output should just say they were changed,
taking the break score left by the earlier diffcore-break run if
any.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
The "score" calculation for diffcore-rename was totally broken.
It scaled "score" as
score = src_copied * MAX_SCORE / dst->size;
which means that you got a 100% similarity score even if src and dest were
different, if just every byte of dst was copied from src, even if source
was much larger than dst (eg we had copied 85% of the bytes, but _deleted_
the remaining 15%).
That's clearly bogus. We should do the score calculation relative not to
the destination size, but to the max size of the two.
This seems to fix it.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
To reduce wasted memory, wait until the hash fills up more
densely before we rehash. This reduces the working set size a
bit further.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
This changes diffcore-rename to reuse statistics information
gathered during similarity estimation, and updates the hashtable
implementation used to keep track of the statistics to be
denser. This seems to give better performance.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
The "similarity" logic was giving added material way too much
negative weight. What we wanted to see was how similar the
post-change image was compared to the pre-change image, so the
natural definition of similarity is how much common things are
there, relative to the post-change image's size.
This simplifies things a lot.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
This is to rework diffcore break/rename/copy detection code
so that it does not affected when deltifier code gets improved.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
Spotted by Nicolas Pitre.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
dietlibc versions of malloc, calloc and realloc all return NULL if
they're told to allocate 0 bytes, causes the x* wrappers to die().
There are several more places where these calls could end up asking
for 0 bytes, too...
Maybe simply not die()-ing in the x* wrappers if 0/NULL is returned
when the requested size is zero is a safer and easier way to go.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
When the user is interested in pure renames, there is no point
doing the similarity scores. This changes the score argument
parsing to special case -M100 (otherwise, it is a precision
scaled value 0 <= v < 1 and would mean 0.1, not 1.0 --- if you
do mean 0.1, you can say -M1), and optimizes the diffcore_rename
transformation to only look at pure renames in that case.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
A while ago, a rename-detection limit logic was implemented as a
response to this thread:
http://marc.theaimsgroup.com/?l=git&m=112413080630175
where gitweb was found to be using a lot of time and memory to
detect renames on huge commits. git-diff family takes -l<num>
flag, and if the number of paths that are rename destination
candidates (i.e. new paths with -M, or modified paths with -C)
are larger than that number, skips rename/copy detection even
when -M or -C is specified on the command line.
This commit makes the rename detection limit easier to use. You
can have:
[diff]
renamelimit = 30
in your .git/config file to specify the default rename detection
limit. You can override this from the command line; giving 0
means 'unlimited':
git diff -M -l0
We might want to change the default behaviour, when you do not
have the configuration, to limit it to say 20 paths or so. This
would also help the diffstat generation after a big 'git pull'.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
When many paths are modified, rename detection takes a lot of time.
The new option -l<num> can be used to disable rename detection when
more than <num> paths are possibly created as renames.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|
|
It is a bit embarrassing that it took this long for a fix since the
problem was first reported on Aug 13th.
Message-ID: <87y876gl1r.wl@mail2.atmark-techno.com>
From: Yasushi SHOJI <yashi@atmark-techno.com>
Newsgroups: gmane.comp.version-control.git
Subject: [patch] possible memory leak in diff.c::diff_free_filepair()
Date: Sat, 13 Aug 2005 19:58:56 +0900
This time I used valgrind to make sure that it does not overeagerly
discard memory that is still being used.
Signed-off-by: Junio C Hamano <junkio@cox.net>
|