/*
*
* Copyright (C) 2005 Junio C Hamano
*/
#include "cache.h"
#include "diff.h"
#include "diffcore.h"
#include "object-store.h"
#include "hashmap.h"
#include "progress.h"
#include "promisor-remote.h"
#include "strmap.h"
/* Table of rename/copy destinations */
static struct diff_rename_dst {
struct diff_filepair *p;
struct diff_filespec *filespec_to_free;
int is_rename; /* false -> just a create; true -> rename or copy */
} *rename_dst;
static int rename_dst_nr, rename_dst_alloc;
/* Mapping from break source pathname to break destination index */
static struct strintmap *break_idx = NULL;
static struct diff_rename_dst *locate_rename_dst(struct diff_filepair *p)
{
/* Lookup by p->ONE->path */
int idx = break_idx ? strintmap_get(break_idx, p->one->path) : -1;
return (idx == -1) ? NULL : &rename_dst[idx];
}
/*
* Returns 0 on success, -1 if we found a duplicate.
*/
static int add_rename_dst(struct diff_filepair *p)
{
ALLOC_GROW(rename_dst, rename_dst_nr + 1, rename_dst_alloc);
rename_dst[rename_dst_nr].p = p;
rename_dst[rename_dst_nr].filespec_to_free = NULL;
rename_dst[rename_dst_nr].is_rename = 0;
rename_dst_nr++;
return 0;
}
/* Table of rename/copy src files */
static struct diff_rename_src {
struct diff_filepair *p;
unsigned short score; /* to remember the break score */
} *rename_src;
static int rename_src_nr, rename_src_alloc;
static void register_rename_src(struct diff_filepair *p)
{
if (p->broken_pair) {
if (!break_idx) {
break_idx = xmalloc(sizeof(*break_idx));
strintmap_init(break_idx, -1);
}
strintmap_set(break_idx, p->one->path, rename_dst_nr);
}
ALLOC_GROW(rename_src, rename_src_nr + 1, rename_src_alloc);
rename_src[rename_src_nr].p = p;
rename_src[rename_src_nr].score = p->score;
rename_src_nr++;
}
static int basename_same(struct diff_filespec *src, struct diff_filespec *dst)
{
int src_len = strlen(src->path), dst_len = strlen(dst->path);
while (src_len && dst_len) {
char c1 = src->path[--src_len];
char c2 = dst->path[--dst_len];
if (c1 != c2)
return 0;
if (c1 == '/')
return 1;
}
return (!src_len || src->path[src_len - 1] == '/') &&
(!dst_len || dst->path[dst_len - 1] == '/');
}
struct diff_score {
int src; /* index in rename_src */
int dst; /* index in rename_dst */
unsigned short score;
short name_score;
};
struct prefetch_options {
struct repository *repo;
int skip_unmodified;
};
static void prefetch(void *prefetch_options)
{
struct prefetch_options *options = prefetch_options;
int i;
struct oid_array to_fetch = OID_ARRAY_INIT;
for (i = 0; i < rename_dst_nr; i++) {
if (rename_dst[i].p->renamed_pair)
/*
* The loop in diffcore_rename() will not need these
* blobs, so skip prefetching.
*/
continue; /* already found exact match */
diff_add_if_missing(options->repo, &to_fetch,
rename_dst[i].p->two);
}
for (i = 0; i < rename_src_nr; i++) {
if (options->skip_unmodified &&
diff_unmodified_pair(rename_src[i].p))
/*
* The loop in diffcore_rename() will not need these
* blobs, so skip prefetching.
*/
continue;
diff_add_if_missing(options->repo, &to_fetch,
rename_src[i].p-
|