Skip to content

Commit

Permalink
Merge branch 'lt/rename' into HEAD
Browse files Browse the repository at this point in the history
* lt/rename:
  Do the fuzzy rename detection limits with the exact renames removed
  Fix ugly magic special case in exact rename detection
  Do exact rename detection regardless of rename limits
  Do linear-time/space rename logic for exact renames
  copy vs rename detection: avoid unnecessary O(n*m) loops
  Ref-count the filespecs used by diffcore
  Split out "exact content match" phase of rename detection
  Add 'diffcore.h' to LIB_H
  • Loading branch information
gitster committed Oct 31, 2007
2 parents 6beb669 + 42899ac commit 7e9a464
Show file tree
Hide file tree
Showing 6 changed files with 395 additions and 166 deletions.
5 changes: 2 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ LIB_H = \
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
mailmap.h remote.h transport.h
mailmap.h remote.h transport.h diffcore.h hash.h

DIFF_OBJS = \
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
Expand All @@ -299,7 +299,7 @@ DIFF_OBJS = \
LIB_OBJS = \
blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \
date.o diff-delta.o entry.o exec_cmd.o ident.o \
interpolate.o \
interpolate.o hash.o \
lockfile.o \
patch-ids.o \
object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \
Expand Down Expand Up @@ -916,7 +916,6 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)

$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
$(DIFF_OBJS): diffcore.h

$(LIB_FILE): $(LIB_OBJS)
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
Expand Down
55 changes: 28 additions & 27 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1440,9 +1440,18 @@ struct diff_filespec *alloc_filespec(const char *path)
memset(spec, 0, sizeof(*spec));
spec->path = (char *)(spec + 1);
memcpy(spec->path, path, namelen+1);
spec->count = 1;
return spec;
}

void free_filespec(struct diff_filespec *spec)
{
if (!--spec->count) {
diff_free_filespec_data(spec);
free(spec);
}
}

void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
unsigned short mode)
{
Expand Down Expand Up @@ -2435,10 +2444,8 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue,

void diff_free_filepair(struct diff_filepair *p)
{
diff_free_filespec_data(p->one);
diff_free_filespec_data(p->two);
free(p->one);
free(p->two);
free_filespec(p->one);
free_filespec(p->two);
free(p);
}

Expand Down Expand Up @@ -2590,9 +2597,9 @@ void diff_debug_filepair(const struct diff_filepair *p, int i)
{
diff_debug_filespec(p->one, i, "one");
diff_debug_filespec(p->two, i, "two");
fprintf(stderr, "score %d, status %c stays %d broken %d\n",
fprintf(stderr, "score %d, status %c rename_used %d broken %d\n",
p->score, p->status ? p->status : '?',
p->source_stays, p->broken_pair);
p->one->rename_used, p->broken_pair);
}

void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
Expand All @@ -2610,8 +2617,8 @@ void diff_debug_queue(const char *msg, struct diff_queue_struct *q)

static void diff_resolve_rename_copy(void)
{
int i, j;
struct diff_filepair *p, *pp;
int i;
struct diff_filepair *p;
struct diff_queue_struct *q = &diff_queued_diff;

diff_debug_queue("resolve-rename-copy", q);
Expand All @@ -2633,27 +2640,21 @@ static void diff_resolve_rename_copy(void)
* either in-place edit or rename/copy edit.
*/
else if (DIFF_PAIR_RENAME(p)) {
if (p->source_stays) {
p->status = DIFF_STATUS_COPIED;
continue;
}
/* See if there is some other filepair that
* copies from the same source as us. If so
* we are a copy. Otherwise we are either a
* copy if the path stays, or a rename if it
* does not, but we already handled "stays" case.
/*
* A rename might have re-connected a broken
* pair up, causing the pathnames to be the
* same again. If so, that's not a rename at
* all, just a modification..
*
* Otherwise, see if this source was used for
* multiple renames, in which case we decrement
* the count, and call it a copy.
*/
for (j = i + 1; j < q->nr; j++) {
pp = q->queue[j];
if (strcmp(pp->one->path, p->one->path))
continue; /* not us */
if (!DIFF_PAIR_RENAME(pp))
continue; /* not a rename/copy */
/* pp is a rename/copy from the same source */
if (!strcmp(p->one->path, p->two->path))
p->status = DIFF_STATUS_MODIFIED;
else if (--p->one->rename_used > 0)
p->status = DIFF_STATUS_COPIED;
break;
}
if (!p->status)
else
p->status = DIFF_STATUS_RENAMED;
}
else if (hashcmp(p->one->sha1, p->two->sha1) ||
Expand Down

0 comments on commit 7e9a464

Please sign in to comment.