Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
0462fba5
Commit
0462fba5
authored
Apr 30, 2013
by
Edward Thomson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
renames!
parent
bec65a5e
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1485 additions
and
9 deletions
+1485
-9
include/git2/index.h
+53
-0
include/git2/merge.h
+13
-0
src/diff.h
+12
-0
src/diff_tform.c
+8
-8
src/index.c
+218
-0
src/index.h
+1
-0
src/merge.c
+484
-1
tests-clar/index/names.c
+83
-0
tests-clar/merge/merge_helpers.c
+85
-0
tests-clar/merge/trees/renames.c
+253
-0
tests-clar/merge/trees/treediff.c
+275
-0
No files found.
include/git2/index.h
View file @
0462fba5
...
...
@@ -84,6 +84,12 @@ typedef struct git_index_entry {
char
*
path
;
}
git_index_entry
;
typedef
struct
git_index_name_entry
{
char
*
ancestor
;
char
*
ours
;
char
*
theirs
;
}
git_index_name_entry
;
/** Representation of a resolve undo entry in the index. */
typedef
struct
git_index_reuc_entry
{
unsigned
int
mode
[
3
];
...
...
@@ -478,6 +484,53 @@ GIT_EXTERN(int) git_index_has_conflicts(const git_index *index);
/**@}*/
/** @name Conflict Name entry functions
*
* These functions work on rename conflict entries.
*/
/**@{*/
/**
* Get the count of filename conflict entries currently in the index.
*
* @param index an existing index object
* @return integer of count of current filename conflict entries
*/
GIT_EXTERN
(
unsigned
int
)
git_index_name_entrycount
(
git_index
*
index
);
/**
* Get a filename conflict entry from the index.
*
* The returned entry is read-only and should not be modified
* or freed by the caller.
*
* @param index an existing index object
* @param n the position of the entry
* @return a pointer to the filename conflict entry; NULL if out of bounds
*/
GIT_EXTERN
(
const
git_index_name_entry
*
)
git_index_name_get_byindex
(
git_index
*
index
,
size_t
n
);
/**
* Record the filenames involved in a rename conflict.
*
* @param index an existing index object
* @param ancestor the path of the file as it existed in the ancestor
* @param ours the path of the file as it existed in our tree
* @param theirs the path of the file as it existed in their tree
*/
GIT_EXTERN
(
int
)
git_index_name_add
(
git_index
*
index
,
const
char
*
ancestor
,
const
char
*
ours
,
const
char
*
theirs
);
/**
* Remove all filename conflict entries.
*
* @param index an existing index object
* @return 0 or an error code
*/
GIT_EXTERN
(
void
)
git_index_name_clear
(
git_index
*
index
);
/**@}*/
/** @name Resolve Undo (REUC) index entry manipulation.
*
* These functions work on the Resolve Undo index extension and contains
...
...
include/git2/merge.h
View file @
0462fba5
...
...
@@ -27,6 +27,8 @@ GIT_BEGIN_DECL
* passed in via the `flags` value in the `git_diff_tree_many_options`.
*/
typedef
enum
{
/** Detect renames */
GIT_MERGE_TREE_FIND_RENAMES
=
(
1
<<
0
),
}
git_merge_tree_flags
;
/**
...
...
@@ -44,6 +46,17 @@ typedef struct {
unsigned
int
version
;
git_merge_tree_flags
flags
;
/** Similarity to consider a file renamed (default 50) */
unsigned
int
rename_threshold
;
/** Maximum similarity sources to examine (overrides the
* `merge.renameLimit` config) (default 200)
*/
unsigned
int
target_limit
;
/** Pluggable similarity metric; pass NULL to use internal metric */
git_diff_similarity_metric
*
metric
;
/** Flags for automerging content. */
git_merge_automerge_flags
automerge_flags
;
}
git_merge_tree_opts
;
...
...
src/diff.h
View file @
0462fba5
...
...
@@ -74,5 +74,17 @@ extern int git_diff__from_iterators(
git_iterator
*
new_iter
,
const
git_diff_options
*
opts
);
int
git_diff_find_similar__hashsig_for_file
(
void
**
out
,
const
git_diff_file
*
f
,
const
char
*
path
,
void
*
p
);
int
git_diff_find_similar__hashsig_for_buf
(
void
**
out
,
const
git_diff_file
*
f
,
const
char
*
buf
,
size_t
len
,
void
*
p
);
void
git_diff_find_similar__hashsig_free
(
void
*
sig
,
void
*
payload
);
int
git_diff_find_similar__calc_similarity
(
int
*
score
,
void
*
siga
,
void
*
sigb
,
void
*
payload
);
#endif
src/diff_tform.c
View file @
0462fba5
...
...
@@ -170,7 +170,7 @@ int git_diff_merge(
return
error
;
}
static
int
find_similar__hashsig_for_file
(
int
git_diff_
find_similar__hashsig_for_file
(
void
**
out
,
const
git_diff_file
*
f
,
const
char
*
path
,
void
*
p
)
{
git_hashsig_option_t
opt
=
(
git_hashsig_option_t
)
p
;
...
...
@@ -187,7 +187,7 @@ static int find_similar__hashsig_for_file(
return
error
;
}
static
int
find_similar__hashsig_for_buf
(
int
git_diff_
find_similar__hashsig_for_buf
(
void
**
out
,
const
git_diff_file
*
f
,
const
char
*
buf
,
size_t
len
,
void
*
p
)
{
git_hashsig_option_t
opt
=
(
git_hashsig_option_t
)
p
;
...
...
@@ -204,13 +204,13 @@ static int find_similar__hashsig_for_buf(
return
error
;
}
static
void
find_similar__hashsig_free
(
void
*
sig
,
void
*
payload
)
void
git_diff_
find_similar__hashsig_free
(
void
*
sig
,
void
*
payload
)
{
GIT_UNUSED
(
payload
);
git_hashsig_free
(
sig
);
}
static
int
find_similar__calc_similarity
(
int
git_diff_
find_similar__calc_similarity
(
int
*
score
,
void
*
siga
,
void
*
sigb
,
void
*
payload
)
{
GIT_UNUSED
(
payload
);
...
...
@@ -291,10 +291,10 @@ static int normalize_find_opts(
opts
->
metric
=
git__malloc
(
sizeof
(
git_diff_similarity_metric
));
GITERR_CHECK_ALLOC
(
opts
->
metric
);
opts
->
metric
->
file_signature
=
find_similar__hashsig_for_file
;
opts
->
metric
->
buffer_signature
=
find_similar__hashsig_for_buf
;
opts
->
metric
->
free_signature
=
find_similar__hashsig_free
;
opts
->
metric
->
similarity
=
find_similar__calc_similarity
;
opts
->
metric
->
file_signature
=
git_diff_
find_similar__hashsig_for_file
;
opts
->
metric
->
buffer_signature
=
git_diff_
find_similar__hashsig_for_buf
;
opts
->
metric
->
free_signature
=
git_diff_
find_similar__hashsig_free
;
opts
->
metric
->
similarity
=
git_diff_
find_similar__calc_similarity
;
if
(
opts
->
flags
&
GIT_DIFF_FIND_IGNORE_WHITESPACE
)
opts
->
metric
->
payload
=
(
void
*
)
GIT_HASHSIG_IGNORE_WHITESPACE
;
...
...
src/index.c
View file @
0462fba5
...
...
@@ -35,6 +35,7 @@ static const unsigned int INDEX_VERSION_NUMBER_EXT = 3;
static
const
unsigned
int
INDEX_HEADER_SIG
=
0x44495243
;
static
const
char
INDEX_EXT_TREECACHE_SIG
[]
=
{
'T'
,
'R'
,
'E'
,
'E'
};
static
const
char
INDEX_EXT_UNMERGED_SIG
[]
=
{
'R'
,
'E'
,
'U'
,
'C'
};
static
const
char
INDEX_EXT_CONFLICT_NAME_SIG
[]
=
{
'N'
,
'A'
,
'M'
,
'E'
};
#define INDEX_OWNER(idx) ((git_repository *)(GIT_REFCOUNT_OWNER(idx)))
...
...
@@ -187,6 +188,46 @@ static int index_icmp(const void *a, const void *b)
return
diff
;
}
static
int
conflict_name_cmp
(
const
void
*
a
,
const
void
*
b
)
{
const
git_index_name_entry
*
name_a
=
a
;
const
git_index_name_entry
*
name_b
=
b
;
if
(
name_a
->
ancestor
&&
!
name_b
->
ancestor
)
return
1
;
if
(
!
name_a
->
ancestor
&&
name_b
->
ancestor
)
return
-
1
;
if
(
name_a
->
ancestor
)
return
strcmp
(
name_a
->
ancestor
,
name_b
->
ancestor
);
if
(
!
name_a
->
ours
||
!
name_b
->
ours
)
return
0
;
return
strcmp
(
name_a
->
ours
,
name_b
->
ours
);
}
static
int
conflict_name_icmp
(
const
void
*
a
,
const
void
*
b
)
{
const
git_index_name_entry
*
name_a
=
a
;
const
git_index_name_entry
*
name_b
=
b
;
if
(
name_a
->
ancestor
&&
!
name_b
->
ancestor
)
return
1
;
if
(
!
name_a
->
ancestor
&&
name_b
->
ancestor
)
return
-
1
;
if
(
name_a
->
ancestor
)
return
strcasecmp
(
name_a
->
ancestor
,
name_b
->
ancestor
);
if
(
!
name_a
->
ours
||
!
name_b
->
ours
)
return
0
;
return
strcasecmp
(
name_a
->
ours
,
name_b
->
ours
);
}
static
int
reuc_srch
(
const
void
*
key
,
const
void
*
array_member
)
{
const
git_index_reuc_entry
*
reuc
=
array_member
;
...
...
@@ -278,6 +319,7 @@ int git_index_open(git_index **index_out, const char *index_path)
}
if
(
git_vector_init
(
&
index
->
entries
,
32
,
index_cmp
)
<
0
||
git_vector_init
(
&
index
->
names
,
32
,
conflict_name_cmp
)
<
0
||
git_vector_init
(
&
index
->
reuc
,
32
,
reuc_cmp
)
<
0
)
return
-
1
;
...
...
@@ -331,6 +373,8 @@ void git_index_clear(git_index *index)
git_index_reuc_clear
(
index
);
git_index_name_clear
(
index
);
git_futils_filestamp_set
(
&
index
->
stamp
,
NULL
);
git_tree_cache_free
(
index
->
tree
);
...
...
@@ -1042,6 +1086,72 @@ int git_index_has_conflicts(const git_index *index)
return
0
;
}
unsigned
int
git_index_name_entrycount
(
git_index
*
index
)
{
assert
(
index
);
return
(
unsigned
int
)
index
->
names
.
length
;
}
const
git_index_name_entry
*
git_index_name_get_byindex
(
git_index
*
index
,
size_t
n
)
{
assert
(
index
);
git_vector_sort
(
&
index
->
names
);
return
git_vector_get
(
&
index
->
names
,
n
);
}
int
git_index_name_add
(
git_index
*
index
,
const
char
*
ancestor
,
const
char
*
ours
,
const
char
*
theirs
)
{
git_index_name_entry
*
conflict_name
;
assert
((
ancestor
&&
ours
)
||
(
ancestor
&&
theirs
)
||
(
ours
&&
theirs
));
conflict_name
=
git__calloc
(
1
,
sizeof
(
git_index_name_entry
));
GITERR_CHECK_ALLOC
(
conflict_name
);
if
(
ancestor
)
{
conflict_name
->
ancestor
=
git__strdup
(
ancestor
);
GITERR_CHECK_ALLOC
(
conflict_name
->
ancestor
);
}
if
(
ours
)
{
conflict_name
->
ours
=
git__strdup
(
ours
);
GITERR_CHECK_ALLOC
(
conflict_name
->
ours
);
}
if
(
theirs
)
{
conflict_name
->
theirs
=
git__strdup
(
theirs
);
GITERR_CHECK_ALLOC
(
conflict_name
->
theirs
);
}
return
git_vector_insert
(
&
index
->
names
,
conflict_name
);
}
void
git_index_name_clear
(
git_index
*
index
)
{
size_t
i
;
git_index_name_entry
*
conflict_name
;
assert
(
index
);
git_vector_foreach
(
&
index
->
names
,
i
,
conflict_name
)
{
if
(
conflict_name
->
ancestor
)
git__free
(
conflict_name
->
ancestor
);
if
(
conflict_name
->
ours
)
git__free
(
conflict_name
->
ours
);
if
(
conflict_name
->
theirs
)
git__free
(
conflict_name
->
theirs
);
git__free
(
conflict_name
);
}
git_vector_clear
(
&
index
->
names
);
}
unsigned
int
git_index_reuc_entrycount
(
git_index
*
index
)
{
assert
(
index
);
...
...
@@ -1228,6 +1338,52 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
return
0
;
}
static
int
read_conflict_names
(
git_index
*
index
,
const
char
*
buffer
,
size_t
size
)
{
size_t
len
;
/* This gets called multiple times, the vector might already be initialized */
if
(
index
->
names
.
_alloc_size
==
0
&&
git_vector_init
(
&
index
->
names
,
16
,
conflict_name_cmp
)
<
0
)
return
-
1
;
#define read_conflict_name(ptr) \
len = strlen(buffer) + 1; \
if (size < len) \
return index_error_invalid("reading conflict name entries"); \
\
if (len == 1) \
ptr = NULL; \
else { \
ptr = git__malloc(len); \
GITERR_CHECK_ALLOC(ptr); \
memcpy(ptr, buffer, len); \
} \
\
buffer += len; \
size -= len;
while
(
size
)
{
git_index_name_entry
*
conflict_name
=
git__calloc
(
1
,
sizeof
(
git_index_name_entry
));
GITERR_CHECK_ALLOC
(
conflict_name
);
read_conflict_name
(
conflict_name
->
ancestor
);
read_conflict_name
(
conflict_name
->
ours
);
read_conflict_name
(
conflict_name
->
theirs
);
if
(
git_vector_insert
(
&
index
->
names
,
conflict_name
)
<
0
)
return
-
1
;
}
#undef read_conflict_name
/* entries are guaranteed to be sorted on-disk */
index
->
names
.
sorted
=
1
;
return
0
;
}
static
size_t
read_entry
(
git_index_entry
*
dest
,
const
void
*
buffer
,
size_t
buffer_size
)
{
size_t
path_length
,
entry_size
;
...
...
@@ -1332,6 +1488,9 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer
}
else
if
(
memcmp
(
dest
.
signature
,
INDEX_EXT_UNMERGED_SIG
,
4
)
==
0
)
{
if
(
read_reuc
(
index
,
buffer
+
8
,
dest
.
extension_size
)
<
0
)
return
0
;
}
else
if
(
memcmp
(
dest
.
signature
,
INDEX_EXT_CONFLICT_NAME_SIG
,
4
)
==
0
)
{
if
(
read_conflict_names
(
index
,
buffer
+
8
,
dest
.
extension_size
)
<
0
)
return
0
;
}
/* else, unsupported extension. We cannot parse this, but we can skip
* it by returning `total_size */
...
...
@@ -1545,6 +1704,61 @@ static int write_extension(git_filebuf *file, struct index_extension *header, gi
return
error
;
}
static
int
create_name_extension_data
(
git_buf
*
name_buf
,
git_index_name_entry
*
conflict_name
)
{
int
error
=
0
;
if
(
conflict_name
->
ancestor
==
NULL
)
error
=
git_buf_put
(
name_buf
,
"
\0
"
,
1
);
else
error
=
git_buf_put
(
name_buf
,
conflict_name
->
ancestor
,
strlen
(
conflict_name
->
ancestor
)
+
1
);
if
(
error
!=
0
)
goto
on_error
;
if
(
conflict_name
->
ours
==
NULL
)
error
=
git_buf_put
(
name_buf
,
"
\0
"
,
1
);
else
error
=
git_buf_put
(
name_buf
,
conflict_name
->
ours
,
strlen
(
conflict_name
->
ours
)
+
1
);
if
(
error
!=
0
)
goto
on_error
;
if
(
conflict_name
->
theirs
==
NULL
)
error
=
git_buf_put
(
name_buf
,
"
\0
"
,
1
);
else
error
=
git_buf_put
(
name_buf
,
conflict_name
->
theirs
,
strlen
(
conflict_name
->
theirs
)
+
1
);
on_error
:
return
error
;
}
static
int
write_name_extension
(
git_index
*
index
,
git_filebuf
*
file
)
{
git_buf
name_buf
=
GIT_BUF_INIT
;
git_vector
*
out
=
&
index
->
names
;
git_index_name_entry
*
conflict_name
;
struct
index_extension
extension
;
size_t
i
;
int
error
=
0
;
git_vector_foreach
(
out
,
i
,
conflict_name
)
{
if
((
error
=
create_name_extension_data
(
&
name_buf
,
conflict_name
))
<
0
)
goto
done
;
}
memset
(
&
extension
,
0x0
,
sizeof
(
struct
index_extension
));
memcpy
(
&
extension
.
signature
,
INDEX_EXT_CONFLICT_NAME_SIG
,
4
);
extension
.
extension_size
=
(
uint32_t
)
name_buf
.
size
;
error
=
write_extension
(
file
,
&
extension
,
&
name_buf
);
git_buf_free
(
&
name_buf
);
done
:
return
error
;
}
static
int
create_reuc_extension_data
(
git_buf
*
reuc_buf
,
git_index_reuc_entry
*
reuc
)
{
int
i
;
...
...
@@ -1615,6 +1829,10 @@ static int write_index(git_index *index, git_filebuf *file)
/* TODO: write tree cache extension */
/* write the rename conflict extension */
if
(
index
->
names
.
length
>
0
&&
write_name_extension
(
index
,
file
)
<
0
)
return
-
1
;
/* write the reuc extension */
if
(
index
->
reuc
.
length
>
0
&&
write_reuc_extension
(
index
,
file
)
<
0
)
return
-
1
;
...
...
src/index.h
View file @
0462fba5
...
...
@@ -33,6 +33,7 @@ struct git_index {
git_tree_cache
*
tree
;
git_vector
names
;
git_vector
reuc
;
git_vector_cmp
entries_cmp_path
;
...
...
src/merge.c
View file @
0462fba5
...
...
@@ -23,6 +23,7 @@
#include "merge_file.h"
#include "blob.h"
#include "hashsig.h"
#include "oid.h"
#include "git2/types.h"
#include "git2/repository.h"
...
...
@@ -640,6 +641,440 @@ done:
return
error
;
}
/* Rename detection and coalescing */
struct
merge_diff_similarity
{
unsigned
char
similarity
;
size_t
other_idx
;
};
static
int
index_entry_similarity_exact
(
git_repository
*
repo
,
git_index_entry
*
a
,
size_t
a_idx
,
git_index_entry
*
b
,
size_t
b_idx
,
void
**
cache
,
const
git_merge_tree_opts
*
opts
)
{
GIT_UNUSED
(
repo
);
GIT_UNUSED
(
a_idx
);
GIT_UNUSED
(
b_idx
);
GIT_UNUSED
(
cache
);
GIT_UNUSED
(
opts
);
if
(
git_oid__cmp
(
&
a
->
oid
,
&
b
->
oid
)
==
0
)
return
100
;
return
0
;
}
static
int
index_entry_similarity_calc
(
void
**
out
,
git_repository
*
repo
,
git_index_entry
*
entry
,
const
git_merge_tree_opts
*
opts
)
{
git_blob
*
blob
;
git_diff_file
diff_file
=
{{{
0
}}};
int
error
;
*
out
=
NULL
;
if
((
error
=
git_blob_lookup
(
&
blob
,
repo
,
&
entry
->
oid
))
<
0
)
return
error
;
git_oid_cpy
(
&
diff_file
.
oid
,
&
entry
->
oid
);
diff_file
.
path
=
entry
->
path
;
diff_file
.
size
=
entry
->
file_size
;
diff_file
.
mode
=
entry
->
mode
;
diff_file
.
flags
=
0
;
error
=
opts
->
metric
->
buffer_signature
(
out
,
&
diff_file
,
git_blob_rawcontent
(
blob
),
git_blob_rawsize
(
blob
),
opts
->
metric
->
payload
);
git_blob_free
(
blob
);
return
error
;
}
static
int
index_entry_similarity_inexact
(
git_repository
*
repo
,
git_index_entry
*
a
,
size_t
a_idx
,
git_index_entry
*
b
,
size_t
b_idx
,
void
**
cache
,
const
git_merge_tree_opts
*
opts
)
{
int
score
=
0
;
int
error
=
0
;
if
(
GIT_MODE_TYPE
(
a
->
mode
)
!=
GIT_MODE_TYPE
(
b
->
mode
))
return
0
;
/* update signature cache if needed */
if
(
!
cache
[
a_idx
]
&&
(
error
=
index_entry_similarity_calc
(
&
cache
[
a_idx
],
repo
,
a
,
opts
))
<
0
)
return
error
;
if
(
!
cache
[
b_idx
]
&&
(
error
=
index_entry_similarity_calc
(
&
cache
[
b_idx
],
repo
,
b
,
opts
))
<
0
)
return
error
;
/* some metrics may not wish to process this file (too big / too small) */
if
(
!
cache
[
a_idx
]
||
!
cache
[
b_idx
])
return
0
;
/* compare signatures */
if
(
opts
->
metric
->
similarity
(
&
score
,
cache
[
a_idx
],
cache
[
b_idx
],
opts
->
metric
->
payload
)
<
0
)
return
-
1
;
/* clip score */
if
(
score
<
0
)
score
=
0
;
else
if
(
score
>
100
)
score
=
100
;
return
score
;
}
static
int
merge_diff_mark_similarity
(
git_repository
*
repo
,
git_merge_diff_list
*
diff_list
,
struct
merge_diff_similarity
*
similarity_ours
,
struct
merge_diff_similarity
*
similarity_theirs
,
int
(
*
similarity_fn
)(
git_repository
*
,
git_index_entry
*
,
size_t
,
git_index_entry
*
,
size_t
,
void
**
,
const
git_merge_tree_opts
*
),
void
**
cache
,
const
git_merge_tree_opts
*
opts
)
{
size_t
i
,
j
;
git_merge_diff
*
conflict_src
,
*
conflict_tgt
;
int
similarity
;
git_vector_foreach
(
&
diff_list
->
conflicts
,
i
,
conflict_src
)
{
/* Items can be the source of a rename iff they have an item in the
* ancestor slot and lack an item in the ours or theirs slot. */
if
(
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict_src
->
ancestor_entry
)
||
(
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict_src
->
our_entry
)
&&
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict_src
->
their_entry
)))
continue
;
git_vector_foreach
(
&
diff_list
->
conflicts
,
j
,
conflict_tgt
)
{
size_t
our_idx
=
diff_list
->
conflicts
.
length
+
j
;
size_t
their_idx
=
(
diff_list
->
conflicts
.
length
*
2
)
+
j
;
if
(
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict_tgt
->
ancestor_entry
))
continue
;
if
(
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict_tgt
->
our_entry
)
&&
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict_src
->
our_entry
))
{
similarity
=
similarity_fn
(
repo
,
&
conflict_src
->
ancestor_entry
,
i
,
&
conflict_tgt
->
our_entry
,
our_idx
,
cache
,
opts
);
if
(
similarity
==
GIT_EBUFS
)
continue
;
else
if
(
similarity
<
0
)
return
similarity
;
if
(
similarity
>
similarity_ours
[
i
].
similarity
&&
similarity
>
similarity_ours
[
j
].
similarity
)
{
/* Clear previous best similarity */
if
(
similarity_ours
[
i
].
similarity
>
0
)
similarity_ours
[
similarity_ours
[
i
].
other_idx
].
similarity
=
0
;
if
(
similarity_ours
[
j
].
similarity
>
0
)
similarity_ours
[
similarity_ours
[
j
].
other_idx
].
similarity
=
0
;
similarity_ours
[
i
].
similarity
=
similarity
;
similarity_ours
[
i
].
other_idx
=
j
;
similarity_ours
[
j
].
similarity
=
similarity
;
similarity_ours
[
j
].
other_idx
=
i
;
}
}
if
(
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict_tgt
->
their_entry
)
&&
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict_src
->
their_entry
))
{
similarity
=
similarity_fn
(
repo
,
&
conflict_src
->
ancestor_entry
,
i
,
&
conflict_tgt
->
their_entry
,
their_idx
,
cache
,
opts
);
if
(
similarity
>
similarity_theirs
[
i
].
similarity
&&
similarity
>
similarity_theirs
[
j
].
similarity
)
{
/* Clear previous best similarity */
if
(
similarity_theirs
[
i
].
similarity
>
0
)
similarity_theirs
[
similarity_theirs
[
i
].
other_idx
].
similarity
=
0
;
if
(
similarity_theirs
[
j
].
similarity
>
0
)
similarity_theirs
[
similarity_theirs
[
j
].
other_idx
].
similarity
=
0
;
similarity_theirs
[
i
].
similarity
=
similarity
;
similarity_theirs
[
i
].
other_idx
=
j
;
similarity_theirs
[
j
].
similarity
=
similarity
;
similarity_theirs
[
j
].
other_idx
=
i
;
}
}
}
}
return
0
;
}
/*
* Rename conflicts:
*
* Ancestor Ours Theirs
*
* 0a A A A No rename
* b A A* A No rename (ours was rewritten)
* c A A A* No rename (theirs rewritten)
* 1a A A B[A] Rename or rename/edit
* b A B[A] A (automergeable)
* 2 A B[A] B[A] Both renamed (automergeable)
* 3a A B[A] Rename/delete
* b A B[A] (same)
* 4a A B[A] B Rename/add [B~ours B~theirs]
* b A B B[A] (same)
* 5 A B[A] C[A] Both renamed ("1 -> 2")
* 6 A C[A] Both renamed ("2 -> 1")
* B C[B] [C~ours C~theirs] (automergeable)
*/
static
void
merge_diff_mark_rename_conflict
(
git_merge_diff_list
*
diff_list
,
struct
merge_diff_similarity
*
similarity_ours
,
bool
ours_renamed
,
size_t
ours_source_idx
,
struct
merge_diff_similarity
*
similarity_theirs
,
bool
theirs_renamed
,
size_t
theirs_source_idx
,
git_merge_diff
*
target
,
const
git_merge_tree_opts
*
opts
)
{
git_merge_diff
*
ours_source
=
NULL
,
*
theirs_source
=
NULL
;
if
(
ours_renamed
)
ours_source
=
diff_list
->
conflicts
.
contents
[
ours_source_idx
];
if
(
theirs_renamed
)
theirs_source
=
diff_list
->
conflicts
.
contents
[
theirs_source_idx
];
/* Detect 2->1 conflicts */
if
(
ours_renamed
&&
theirs_renamed
)
{
/* Both renamed to the same target name. */
if
(
ours_source_idx
==
theirs_source_idx
)
ours_source
->
type
=
GIT_MERGE_DIFF_BOTH_RENAMED
;
else
{
ours_source
->
type
=
GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1
;
theirs_source
->
type
=
GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1
;
}
}
else
if
(
ours_renamed
)
{
/* If our source was also renamed in theirs, this is a 1->2 */
if
(
similarity_theirs
[
ours_source_idx
].
similarity
>=
opts
->
rename_threshold
)
ours_source
->
type
=
GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2
;
else
if
(
GIT_MERGE_INDEX_ENTRY_EXISTS
(
target
->
their_entry
))
{
ours_source
->
type
=
GIT_MERGE_DIFF_RENAMED_ADDED
;
target
->
type
=
GIT_MERGE_DIFF_RENAMED_ADDED
;
}
else
if
(
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
ours_source
->
their_entry
))
ours_source
->
type
=
GIT_MERGE_DIFF_RENAMED_DELETED
;
else
if
(
ours_source
->
type
==
GIT_MERGE_DIFF_MODIFIED_DELETED
)
ours_source
->
type
=
GIT_MERGE_DIFF_RENAMED_MODIFIED
;
}
else
if
(
theirs_renamed
)
{
/* If their source was also renamed in ours, this is a 1->2 */
if
(
similarity_ours
[
theirs_source_idx
].
similarity
>=
opts
->
rename_threshold
)
theirs_source
->
type
=
GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2
;
else
if
(
GIT_MERGE_INDEX_ENTRY_EXISTS
(
target
->
our_entry
))
{
theirs_source
->
type
=
GIT_MERGE_DIFF_RENAMED_ADDED
;
target
->
type
=
GIT_MERGE_DIFF_RENAMED_ADDED
;
}
else
if
(
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
theirs_source
->
our_entry
))
theirs_source
->
type
=
GIT_MERGE_DIFF_RENAMED_DELETED
;
else
if
(
theirs_source
->
type
==
GIT_MERGE_DIFF_MODIFIED_DELETED
)
theirs_source
->
type
=
GIT_MERGE_DIFF_RENAMED_MODIFIED
;
}
}
GIT_INLINE
(
void
)
merge_diff_coalesce_rename
(
git_index_entry
*
source_entry
,
git_delta_t
*
source_status
,
git_index_entry
*
target_entry
,
git_delta_t
*
target_status
)
{
/* Coalesce the rename target into the rename source. */
memcpy
(
source_entry
,
target_entry
,
sizeof
(
git_index_entry
));
*
source_status
=
GIT_DELTA_RENAMED
;
memset
(
target_entry
,
0x0
,
sizeof
(
git_index_entry
));
*
target_status
=
GIT_DELTA_UNMODIFIED
;
}
static
void
merge_diff_list_coalesce_renames
(
git_merge_diff_list
*
diff_list
,
struct
merge_diff_similarity
*
similarity_ours
,
struct
merge_diff_similarity
*
similarity_theirs
,
const
git_merge_tree_opts
*
opts
)
{
size_t
i
;
bool
ours_renamed
=
0
,
theirs_renamed
=
0
;
size_t
ours_source_idx
=
0
,
theirs_source_idx
=
0
;
git_merge_diff
*
ours_source
,
*
theirs_source
,
*
target
;
for
(
i
=
0
;
i
<
diff_list
->
conflicts
.
length
;
i
++
)
{
target
=
diff_list
->
conflicts
.
contents
[
i
];
ours_renamed
=
0
;
theirs_renamed
=
0
;
if
(
GIT_MERGE_INDEX_ENTRY_EXISTS
(
target
->
our_entry
)
&&
similarity_ours
[
i
].
similarity
>=
opts
->
rename_threshold
)
{
ours_source_idx
=
similarity_ours
[
i
].
other_idx
;
ours_source
=
diff_list
->
conflicts
.
contents
[
ours_source_idx
];
merge_diff_coalesce_rename
(
&
ours_source
->
our_entry
,
&
ours_source
->
our_status
,
&
target
->
our_entry
,
&
target
->
our_status
);
similarity_ours
[
ours_source_idx
].
similarity
=
0
;
similarity_ours
[
i
].
similarity
=
0
;
ours_renamed
=
1
;
}
/* insufficient to determine direction */
if
(
GIT_MERGE_INDEX_ENTRY_EXISTS
(
target
->
their_entry
)
&&
similarity_theirs
[
i
].
similarity
>=
opts
->
rename_threshold
)
{
theirs_source_idx
=
similarity_theirs
[
i
].
other_idx
;
theirs_source
=
diff_list
->
conflicts
.
contents
[
theirs_source_idx
];
merge_diff_coalesce_rename
(
&
theirs_source
->
their_entry
,
&
theirs_source
->
their_status
,
&
target
->
their_entry
,
&
target
->
their_status
);
similarity_theirs
[
theirs_source_idx
].
similarity
=
0
;
similarity_theirs
[
i
].
similarity
=
0
;
theirs_renamed
=
1
;
}
merge_diff_mark_rename_conflict
(
diff_list
,
similarity_ours
,
ours_renamed
,
ours_source_idx
,
similarity_theirs
,
theirs_renamed
,
theirs_source_idx
,
target
,
opts
);
}
}
static
int
merge_diff_empty
(
const
git_vector
*
conflicts
,
size_t
idx
)
{
git_merge_diff
*
conflict
=
conflicts
->
contents
[
idx
];
return
(
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict
->
ancestor_entry
)
&&
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict
->
our_entry
)
&&
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict
->
their_entry
));
}
static
void
merge_diff_list_count_candidates
(
git_merge_diff_list
*
diff_list
,
size_t
*
src_count
,
size_t
*
tgt_count
)
{
git_merge_diff
*
entry
;
size_t
i
;
*
src_count
=
0
;
*
tgt_count
=
0
;
git_vector_foreach
(
&
diff_list
->
conflicts
,
i
,
entry
)
{
if
(
GIT_MERGE_INDEX_ENTRY_EXISTS
(
entry
->
ancestor_entry
)
&&
(
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
entry
->
our_entry
)
||
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
entry
->
their_entry
)))
src_count
++
;
else
if
(
!
GIT_MERGE_INDEX_ENTRY_EXISTS
(
entry
->
ancestor_entry
))
tgt_count
++
;
}
}
int
git_merge_diff_list__find_renames
(
git_repository
*
repo
,
git_merge_diff_list
*
diff_list
,
const
git_merge_tree_opts
*
opts
)
{
struct
merge_diff_similarity
*
similarity_ours
,
*
similarity_theirs
;
void
**
cache
=
NULL
;
size_t
cache_size
=
0
;
size_t
src_count
,
tgt_count
,
i
;
int
error
=
0
;
assert
(
diff_list
&&
opts
);
if
((
opts
->
flags
&
GIT_MERGE_TREE_FIND_RENAMES
)
==
0
)
return
0
;
similarity_ours
=
git__calloc
(
diff_list
->
conflicts
.
length
,
sizeof
(
struct
merge_diff_similarity
));
GITERR_CHECK_ALLOC
(
similarity_ours
);
similarity_theirs
=
git__calloc
(
diff_list
->
conflicts
.
length
,
sizeof
(
struct
merge_diff_similarity
));
GITERR_CHECK_ALLOC
(
similarity_theirs
);
/* Calculate similarity between items that were deleted from the ancestor
* and added in the other branch.
*/
if
((
error
=
merge_diff_mark_similarity
(
repo
,
diff_list
,
similarity_ours
,
similarity_theirs
,
index_entry_similarity_exact
,
NULL
,
opts
))
<
0
)
goto
done
;
if
(
diff_list
->
conflicts
.
length
<=
opts
->
target_limit
)
{
cache_size
=
diff_list
->
conflicts
.
length
*
3
;
cache
=
git__calloc
(
cache_size
,
sizeof
(
void
*
));
GITERR_CHECK_ALLOC
(
cache
);
merge_diff_list_count_candidates
(
diff_list
,
&
src_count
,
&
tgt_count
);
if
(
src_count
>
opts
->
target_limit
||
tgt_count
>
opts
->
target_limit
)
{
/* TODO: report! */
}
else
{
if
((
error
=
merge_diff_mark_similarity
(
repo
,
diff_list
,
similarity_ours
,
similarity_theirs
,
index_entry_similarity_inexact
,
cache
,
opts
))
<
0
)
goto
done
;
}
}
/* For entries that are appropriately similar, merge the new name's entry
* into the old name.
*/
merge_diff_list_coalesce_renames
(
diff_list
,
similarity_ours
,
similarity_theirs
,
opts
);
/* And remove any entries that were merged and are now empty. */
git_vector_remove_matching
(
&
diff_list
->
conflicts
,
merge_diff_empty
);
done
:
if
(
cache
!=
NULL
)
{
for
(
i
=
0
;
i
<
cache_size
;
++
i
)
{
if
(
cache
[
i
]
!=
NULL
)
opts
->
metric
->
free_signature
(
cache
[
i
],
opts
->
metric
->
payload
);
}
git__free
(
cache
);
}
git__free
(
similarity_ours
);
git__free
(
similarity_theirs
);
return
error
;
}
/* Directory/file conflict handling */
GIT_INLINE
(
const
char
*
)
merge_diff_path
(
...
...
@@ -951,6 +1386,43 @@ static int merge_tree_normalize_opts(
else
{
git_merge_tree_opts
init
=
GIT_MERGE_TREE_OPTS_INIT
;
memcpy
(
opts
,
&
init
,
sizeof
(
init
));
opts
->
flags
=
GIT_MERGE_TREE_FIND_RENAMES
;
opts
->
rename_threshold
=
GIT_MERGE_TREE_RENAME_THRESHOLD
;
}
if
(
!
opts
->
target_limit
)
{
int32_t
limit
=
0
;
opts
->
target_limit
=
GIT_MERGE_TREE_TARGET_LIMIT
;
if
(
git_config_get_int32
(
&
limit
,
cfg
,
"merge.renameLimit"
)
<
0
)
{
giterr_clear
();
if
(
git_config_get_int32
(
&
limit
,
cfg
,
"diff.renameLimit"
)
<
0
)
giterr_clear
();
}
if
(
limit
>
0
)
opts
->
target_limit
=
limit
;
}
/* assign the internal metric with whitespace flag as payload */
if
(
!
opts
->
metric
)
{
opts
->
metric
=
git__malloc
(
sizeof
(
git_diff_similarity_metric
));
GITERR_CHECK_ALLOC
(
opts
->
metric
);
opts
->
metric
->
file_signature
=
git_diff_find_similar__hashsig_for_file
;
opts
->
metric
->
buffer_signature
=
git_diff_find_similar__hashsig_for_buf
;
opts
->
metric
->
free_signature
=
git_diff_find_similar__hashsig_free
;
opts
->
metric
->
similarity
=
git_diff_find_similar__calc_similarity
;
if
(
opts
->
flags
&
GIT_DIFF_FIND_IGNORE_WHITESPACE
)
opts
->
metric
->
payload
=
(
void
*
)
GIT_HASHSIG_IGNORE_WHITESPACE
;
else
if
(
opts
->
flags
&
GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE
)
opts
->
metric
->
payload
=
(
void
*
)
GIT_HASHSIG_NORMAL
;
else
opts
->
metric
->
payload
=
(
void
*
)
GIT_HASHSIG_SMART_WHITESPACE
;
}
return
0
;
...
...
@@ -1035,6 +1507,12 @@ int index_from_diff_list(git_index **out, git_merge_diff_list *diff_list)
their_path
=
GIT_MERGE_INDEX_ENTRY_EXISTS
(
conflict
->
their_entry
)
?
conflict
->
their_entry
.
path
:
NULL
;
if
((
our_path
&&
strcmp
(
ancestor_path
,
our_path
)
!=
0
)
||
(
their_path
&&
strcmp
(
ancestor_path
,
their_path
)
!=
0
))
{
if
((
error
=
git_index_name_add
(
index
,
ancestor_path
,
our_path
,
their_path
))
<
0
)
goto
on_error
;
}
}
/* Add each entry in the resolved conflict to the REUC independently, since
...
...
@@ -1099,7 +1577,8 @@ int git_merge_trees(
diff_list
=
git_merge_diff_list__alloc
(
repo
);
GITERR_CHECK_ALLOC
(
diff_list
);
if
((
error
=
git_merge_diff_list__find_differences
(
diff_list
,
ancestor_tree
,
our_tree
,
their_tree
))
<
0
)
if
((
error
=
git_merge_diff_list__find_differences
(
diff_list
,
ancestor_tree
,
our_tree
,
their_tree
))
<
0
||
(
error
=
git_merge_diff_list__find_renames
(
repo
,
diff_list
,
&
opts
))
<
0
)
goto
done
;
memcpy
(
&
changes
,
&
diff_list
->
conflicts
,
sizeof
(
git_vector
));
...
...
@@ -1115,6 +1594,9 @@ int git_merge_trees(
git_vector_insert
(
&
diff_list
->
conflicts
,
conflict
);
}
if
(
!
given_opts
||
!
given_opts
->
metric
)
git__free
(
opts
.
metric
);
error
=
index_from_diff_list
(
out
,
diff_list
);
done
:
...
...
@@ -1134,3 +1616,4 @@ void git_merge_diff_list__free(git_merge_diff_list *diff_list)
git_pool_clear
(
&
diff_list
->
pool
);
git__free
(
diff_list
);
}
tests-clar/index/names.c
0 → 100644
View file @
0462fba5
#include "clar_libgit2.h"
#include "index.h"
#include "git2/repository.h"
#include "../reset/reset_helpers.h"
static
git_repository
*
repo
;
static
git_index
*
repo_index
;
#define TEST_REPO_PATH "mergedrepo"
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
// Fixture setup and teardown
void
test_index_names__initialize
(
void
)
{
repo
=
cl_git_sandbox_init
(
"mergedrepo"
);
git_repository_index
(
&
repo_index
,
repo
);
}
void
test_index_names__cleanup
(
void
)
{
git_index_free
(
repo_index
);
repo_index
=
NULL
;
cl_git_sandbox_cleanup
();
}
void
test_index_names__add
(
void
)
{
const
git_index_name_entry
*
conflict_name
;
cl_git_pass
(
git_index_name_add
(
repo_index
,
"ancestor"
,
"ours"
,
"theirs"
));
cl_git_pass
(
git_index_name_add
(
repo_index
,
"ancestor2"
,
"ours2"
,
NULL
));
cl_git_pass
(
git_index_name_add
(
repo_index
,
"ancestor3"
,
NULL
,
"theirs3"
));
cl_assert
(
git_index_name_entrycount
(
repo_index
)
==
3
);
conflict_name
=
git_index_name_get_byindex
(
repo_index
,
0
);
cl_assert
(
strcmp
(
conflict_name
->
ancestor
,
"ancestor"
)
==
0
);
cl_assert
(
strcmp
(
conflict_name
->
ours
,
"ours"
)
==
0
);
cl_assert
(
strcmp
(
conflict_name
->
theirs
,
"theirs"
)
==
0
);
conflict_name
=
git_index_name_get_byindex
(
repo_index
,
1
);
cl_assert
(
strcmp
(
conflict_name
->
ancestor
,
"ancestor2"
)
==
0
);
cl_assert
(
strcmp
(
conflict_name
->
ours
,
"ours2"
)
==
0
);
cl_assert
(
conflict_name
->
theirs
==
NULL
);
conflict_name
=
git_index_name_get_byindex
(
repo_index
,
2
);
cl_assert
(
strcmp
(
conflict_name
->
ancestor
,
"ancestor3"
)
==
0
);
cl_assert
(
conflict_name
->
ours
==
NULL
);
cl_assert
(
strcmp
(
conflict_name
->
theirs
,
"theirs3"
)
==
0
);
}
void
test_index_names__roundtrip
(
void
)
{
const
git_index_name_entry
*
conflict_name
;
cl_git_pass
(
git_index_name_add
(
repo_index
,
"ancestor"
,
"ours"
,
"theirs"
));
cl_git_pass
(
git_index_name_add
(
repo_index
,
"ancestor2"
,
"ours2"
,
NULL
));
cl_git_pass
(
git_index_name_add
(
repo_index
,
"ancestor3"
,
NULL
,
"theirs3"
));
cl_git_pass
(
git_index_write
(
repo_index
));
git_index_clear
(
repo_index
);
cl_assert
(
git_index_name_entrycount
(
repo_index
)
==
0
);
cl_git_pass
(
git_index_read
(
repo_index
));
cl_assert
(
git_index_name_entrycount
(
repo_index
)
==
3
);
conflict_name
=
git_index_name_get_byindex
(
repo_index
,
0
);
cl_assert
(
strcmp
(
conflict_name
->
ancestor
,
"ancestor"
)
==
0
);
cl_assert
(
strcmp
(
conflict_name
->
ours
,
"ours"
)
==
0
);
cl_assert
(
strcmp
(
conflict_name
->
theirs
,
"theirs"
)
==
0
);
conflict_name
=
git_index_name_get_byindex
(
repo_index
,
1
);
cl_assert
(
strcmp
(
conflict_name
->
ancestor
,
"ancestor2"
)
==
0
);
cl_assert
(
strcmp
(
conflict_name
->
ours
,
"ours2"
)
==
0
);
cl_assert
(
conflict_name
->
theirs
==
NULL
);
conflict_name
=
git_index_name_get_byindex
(
repo_index
,
2
);
cl_assert
(
strcmp
(
conflict_name
->
ancestor
,
"ancestor3"
)
==
0
);
cl_assert
(
conflict_name
->
ours
==
NULL
);
cl_assert
(
strcmp
(
conflict_name
->
theirs
,
"theirs3"
)
==
0
);
}
tests-clar/merge/merge_helpers.c
View file @
0462fba5
...
...
@@ -51,6 +51,58 @@ int merge_trees_from_branches(
return
0
;
}
static
void
dump_index_entries
(
git_vector
*
index_entries
)
{
size_t
i
;
const
git_index_entry
*
index_entry
;
printf
(
"
\n
INDEX [%d]:
\n
"
,
(
int
)
index_entries
->
length
);
for
(
i
=
0
;
i
<
index_entries
->
length
;
i
++
)
{
index_entry
=
index_entries
->
contents
[
i
];
printf
(
"%o "
,
index_entry
->
mode
);
printf
(
"%s "
,
git_oid_allocfmt
(
&
index_entry
->
oid
));
printf
(
"%d "
,
git_index_entry_stage
(
index_entry
));
printf
(
"%s "
,
index_entry
->
path
);
printf
(
"
\n
"
);
}
printf
(
"
\n
"
);
}
static
void
dump_names
(
git_index
*
index
)
{
size_t
i
;
const
git_index_name_entry
*
conflict_name
;
for
(
i
=
0
;
i
<
git_index_name_entrycount
(
index
);
i
++
)
{
conflict_name
=
git_index_name_get_byindex
(
index
,
i
);
printf
(
"%s %s %s
\n
"
,
conflict_name
->
ancestor
,
conflict_name
->
ours
,
conflict_name
->
theirs
);
}
printf
(
"
\n
"
);
}
static
void
dump_reuc
(
git_index
*
index
)
{
size_t
i
;
const
git_index_reuc_entry
*
reuc
;
printf
(
"
\n
REUC:
\n
"
);
for
(
i
=
0
;
i
<
git_index_reuc_entrycount
(
index
);
i
++
)
{
reuc
=
git_index_reuc_get_byindex
(
index
,
i
);
printf
(
"%s "
,
reuc
->
path
);
printf
(
"%o "
,
reuc
->
mode
[
0
]);
printf
(
"%s
\n
"
,
git_oid_allocfmt
(
&
reuc
->
oid
[
0
]));
printf
(
" %o "
,
reuc
->
mode
[
1
]);
printf
(
" %s
\n
"
,
git_oid_allocfmt
(
&
reuc
->
oid
[
1
]));
printf
(
" %o "
,
reuc
->
mode
[
2
]);
printf
(
" %s "
,
git_oid_allocfmt
(
&
reuc
->
oid
[
2
]));
printf
(
"
\n
"
);
}
printf
(
"
\n
"
);
}
static
int
index_entry_eq_merge_index_entry
(
const
struct
merge_index_entry
*
expected
,
const
git_index_entry
*
actual
)
{
git_oid
expected_oid
;
...
...
@@ -84,6 +136,16 @@ static int name_entry_eq(const char *expected, const char *actual)
return
(
strcmp
(
expected
,
actual
)
==
0
)
?
1
:
0
;
}
static
int
name_entry_eq_merge_name_entry
(
const
struct
merge_name_entry
*
expected
,
const
git_index_name_entry
*
actual
)
{
if
(
name_entry_eq
(
expected
->
ancestor_path
,
actual
->
ancestor
)
==
0
||
name_entry_eq
(
expected
->
our_path
,
actual
->
ours
)
==
0
||
name_entry_eq
(
expected
->
their_path
,
actual
->
theirs
)
==
0
)
return
0
;
return
1
;
}
static
int
index_conflict_data_eq_merge_diff
(
const
struct
merge_index_conflict_data
*
expected
,
git_merge_diff
*
actual
)
{
if
(
!
index_entry_eq_merge_index_entry
((
const
struct
merge_index_entry
*
)
&
expected
->
ancestor
,
&
actual
->
ancestor_entry
)
||
...
...
@@ -139,6 +201,29 @@ int merge_test_index(git_index *index, const struct merge_index_entry expected[]
return
1
;
}
int
merge_test_names
(
git_index
*
index
,
const
struct
merge_name_entry
expected
[],
size_t
expected_len
)
{
size_t
i
;
const
git_index_name_entry
*
name_entry
;
/*
dump_names(index);
*/
if
(
git_index_name_entrycount
(
index
)
!=
expected_len
)
return
0
;
for
(
i
=
0
;
i
<
expected_len
;
i
++
)
{
if
((
name_entry
=
git_index_name_get_byindex
(
index
,
i
))
==
NULL
)
return
0
;
if
(
!
name_entry_eq_merge_name_entry
(
&
expected
[
i
],
name_entry
))
return
0
;
}
return
1
;
}
int
merge_test_reuc
(
git_index
*
index
,
const
struct
merge_reuc_entry
expected
[],
size_t
expected_len
)
{
size_t
i
;
...
...
tests-clar/merge/trees/renames.c
0 → 100644
View file @
0462fba5
#include "clar_libgit2.h"
#include "git2/repository.h"
#include "git2/merge.h"
#include "buffer.h"
#include "merge.h"
#include "../merge_helpers.h"
#include "fileops.h"
static
git_repository
*
repo
;
#define TEST_REPO_PATH "merge-resolve"
#define BRANCH_RENAME_OURS "rename_conflict_ours"
#define BRANCH_RENAME_THEIRS "rename_conflict_theirs"
// Fixture setup and teardown
void
test_merge_trees_renames__initialize
(
void
)
{
repo
=
cl_git_sandbox_init
(
TEST_REPO_PATH
);
}
void
test_merge_trees_renames__cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
}
void
test_merge_trees_renames__index
(
void
)
{
git_index
*
index
;
git_merge_tree_opts
*
opts
=
NULL
;
struct
merge_index_entry
merge_index_entries
[]
=
{
{
0100644
,
"68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"
,
0
,
"0a-no-change.txt"
},
{
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
,
0
,
"0b-duplicated-in-ours.txt"
},
{
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
,
1
,
"0b-rewritten-in-ours.txt"
},
{
0100644
,
"e376fbdd06ebf021c92724da9f26f44212734e3e"
,
2
,
"0b-rewritten-in-ours.txt"
},
{
0100644
,
"b2d399ae15224e1d58066e3c8df70ce37de7a656"
,
3
,
"0b-rewritten-in-ours.txt"
},
{
0100644
,
"2f56120107d680129a5d9791b521cb1e73a2ed31"
,
0
,
"0c-duplicated-in-theirs.txt"
},
{
0100644
,
"2f56120107d680129a5d9791b521cb1e73a2ed31"
,
1
,
"0c-rewritten-in-theirs.txt"
},
{
0100644
,
"efc9121fdedaf08ba180b53ebfbcf71bd488ed09"
,
2
,
"0c-rewritten-in-theirs.txt"
},
{
0100644
,
"712ebba6669ea847d9829e4f1059d6c830c8b531"
,
3
,
"0c-rewritten-in-theirs.txt"
},
{
0100644
,
"0d872f8e871a30208305978ecbf9e66d864f1638"
,
0
,
"1a-newname-in-ours-edited-in-theirs.txt"
},
{
0100644
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
,
0
,
"1a-newname-in-ours.txt"
},
{
0100644
,
"ed9523e62e453e50dd9be1606af19399b96e397a"
,
0
,
"1b-newname-in-theirs-edited-in-ours.txt"
},
{
0100644
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
,
0
,
"1b-newname-in-theirs.txt"
},
{
0100644
,
"178940b450f238a56c0d75b7955cb57b38191982"
,
0
,
"2-newname-in-both.txt"
},
{
0100644
,
"18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"
,
2
,
"3a-newname-in-ours-deleted-in-theirs.txt"
},
{
0100644
,
"18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"
,
1
,
"3a-renamed-in-ours-deleted-in-theirs.txt"
},
{
0100644
,
"36219b49367146cb2e6a1555b5a9ebd4d0328495"
,
3
,
"3b-newname-in-theirs-deleted-in-ours.txt"
},
{
0100644
,
"36219b49367146cb2e6a1555b5a9ebd4d0328495"
,
1
,
"3b-renamed-in-theirs-deleted-in-ours.txt"
},
{
0100644
,
"227792b52aaa0b238bea00ec7e509b02623f168c"
,
2
,
"4a-newname-in-ours-added-in-theirs.txt"
},
{
0100644
,
"8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a"
,
3
,
"4a-newname-in-ours-added-in-theirs.txt"
},
{
0100644
,
"227792b52aaa0b238bea00ec7e509b02623f168c"
,
1
,
"4a-renamed-in-ours-added-in-theirs.txt"
},
{
0100644
,
"de872ee3618b894992e9d1e18ba2ebe256a112f9"
,
2
,
"4b-newname-in-theirs-added-in-ours.txt"
},
{
0100644
,
"98d52d07c0b0bbf2b46548f6aa521295c2cb55db"
,
3
,
"4b-newname-in-theirs-added-in-ours.txt"
},
{
0100644
,
"98d52d07c0b0bbf2b46548f6aa521295c2cb55db"
,
1
,
"4b-renamed-in-theirs-added-in-ours.txt"
},
{
0100644
,
"d3719a5ae8e4d92276b5313ce976f6ee5af2b436"
,
2
,
"5a-newname-in-ours-added-in-theirs.txt"
},
{
0100644
,
"98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714"
,
3
,
"5a-newname-in-ours-added-in-theirs.txt"
},
{
0100644
,
"d3719a5ae8e4d92276b5313ce976f6ee5af2b436"
,
1
,
"5a-renamed-in-ours-added-in-theirs.txt"
},
{
0100644
,
"d3719a5ae8e4d92276b5313ce976f6ee5af2b436"
,
3
,
"5a-renamed-in-ours-added-in-theirs.txt"
},
{
0100644
,
"385c8a0f26ddf79e9041e15e17dc352ed2c4cced"
,
2
,
"5b-newname-in-theirs-added-in-ours.txt"
},
{
0100644
,
"63247125386de9ec90a27ad36169307bf8a11a38"
,
3
,
"5b-newname-in-theirs-added-in-ours.txt"
},
{
0100644
,
"63247125386de9ec90a27ad36169307bf8a11a38"
,
1
,
"5b-renamed-in-theirs-added-in-ours.txt"
},
{
0100644
,
"63247125386de9ec90a27ad36169307bf8a11a38"
,
2
,
"5b-renamed-in-theirs-added-in-ours.txt"
},
{
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
,
2
,
"6-both-renamed-1-to-2-ours.txt"
},
{
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
,
3
,
"6-both-renamed-1-to-2-theirs.txt"
},
{
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
,
1
,
"6-both-renamed-1-to-2.txt"
},
{
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
,
1
,
"7-both-renamed-side-1.txt"
},
{
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
,
3
,
"7-both-renamed-side-1.txt"
},
{
0100644
,
"b69fe837e4cecfd4c9a40cdca7c138468687df07"
,
1
,
"7-both-renamed-side-2.txt"
},
{
0100644
,
"b69fe837e4cecfd4c9a40cdca7c138468687df07"
,
2
,
"7-both-renamed-side-2.txt"
},
{
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
,
2
,
"7-both-renamed.txt"
},
{
0100644
,
"b69fe837e4cecfd4c9a40cdca7c138468687df07"
,
3
,
"7-both-renamed.txt"
},
};
struct
merge_name_entry
merge_name_entries
[]
=
{
{
"3a-renamed-in-ours-deleted-in-theirs.txt"
,
"3a-newname-in-ours-deleted-in-theirs.txt"
,
""
},
{
"3b-renamed-in-theirs-deleted-in-ours.txt"
,
""
,
"3b-newname-in-theirs-deleted-in-ours.txt"
,
},
{
"4a-renamed-in-ours-added-in-theirs.txt"
,
"4a-newname-in-ours-added-in-theirs.txt"
,
""
,
},
{
"4b-renamed-in-theirs-added-in-ours.txt"
,
""
,
"4b-newname-in-theirs-added-in-ours.txt"
,
},
{
"5a-renamed-in-ours-added-in-theirs.txt"
,
"5a-newname-in-ours-added-in-theirs.txt"
,
"5a-renamed-in-ours-added-in-theirs.txt"
,
},
{
"5b-renamed-in-theirs-added-in-ours.txt"
,
"5b-renamed-in-theirs-added-in-ours.txt"
,
"5b-newname-in-theirs-added-in-ours.txt"
,
},
{
"6-both-renamed-1-to-2.txt"
,
"6-both-renamed-1-to-2-ours.txt"
,
"6-both-renamed-1-to-2-theirs.txt"
,
},
{
"7-both-renamed-side-1.txt"
,
"7-both-renamed.txt"
,
"7-both-renamed-side-1.txt"
,
},
{
"7-both-renamed-side-2.txt"
,
"7-both-renamed-side-2.txt"
,
"7-both-renamed.txt"
,
},
};
struct
merge_reuc_entry
merge_reuc_entries
[]
=
{
{
"1a-newname-in-ours-edited-in-theirs.txt"
,
0
,
0100644
,
0
,
""
,
"c3d02eeef75183df7584d8d13ac03053910c1301"
,
""
},
{
"1a-newname-in-ours.txt"
,
0
,
0100644
,
0
,
""
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
,
""
},
{
"1a-renamed-in-ours-edited-in-theirs.txt"
,
0100644
,
0
,
0100644
,
"c3d02eeef75183df7584d8d13ac03053910c1301"
,
""
,
"0d872f8e871a30208305978ecbf9e66d864f1638"
},
{
"1a-renamed-in-ours.txt"
,
0100644
,
0
,
0100644
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
,
""
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
},
{
"1b-newname-in-theirs-edited-in-ours.txt"
,
0
,
0
,
0100644
,
""
,
""
,
"241a1005cd9b980732741b74385b891142bcba28"
},
{
"1b-newname-in-theirs.txt"
,
0
,
0
,
0100644
,
""
,
""
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
},
{
"1b-renamed-in-theirs-edited-in-ours.txt"
,
0100644
,
0100644
,
0
,
"241a1005cd9b980732741b74385b891142bcba28"
,
"ed9523e62e453e50dd9be1606af19399b96e397a"
,
""
},
{
"1b-renamed-in-theirs.txt"
,
0100644
,
0100644
,
0
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
,
""
},
{
"2-newname-in-both.txt"
,
0
,
0100644
,
0100644
,
""
,
"178940b450f238a56c0d75b7955cb57b38191982"
,
"178940b450f238a56c0d75b7955cb57b38191982"
},
{
"2-renamed-in-both.txt"
,
0100644
,
0
,
0
,
"178940b450f238a56c0d75b7955cb57b38191982"
,
""
,
""
},
};
cl_git_pass
(
merge_trees_from_branches
(
&
index
,
repo
,
BRANCH_RENAME_OURS
,
BRANCH_RENAME_THEIRS
,
opts
));
cl_assert
(
merge_test_index
(
index
,
merge_index_entries
,
41
));
cl_assert
(
merge_test_names
(
index
,
merge_name_entries
,
9
));
cl_assert
(
merge_test_reuc
(
index
,
merge_reuc_entries
,
10
));
git_index_free
(
index
);
}
void
test_merge_trees_renames__no_rename_index
(
void
)
{
git_index
*
index
;
git_merge_tree_opts
opts
=
GIT_MERGE_TREE_OPTS_INIT
;
struct
merge_index_entry
merge_index_entries
[]
=
{
{
0100644
,
"68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"
,
0
,
"0a-no-change.txt"
},
{
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
,
0
,
"0b-duplicated-in-ours.txt"
},
{
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
,
1
,
"0b-rewritten-in-ours.txt"
},
{
0100644
,
"e376fbdd06ebf021c92724da9f26f44212734e3e"
,
2
,
"0b-rewritten-in-ours.txt"
},
{
0100644
,
"b2d399ae15224e1d58066e3c8df70ce37de7a656"
,
3
,
"0b-rewritten-in-ours.txt"
},
{
0100644
,
"2f56120107d680129a5d9791b521cb1e73a2ed31"
,
0
,
"0c-duplicated-in-theirs.txt"
},
{
0100644
,
"2f56120107d680129a5d9791b521cb1e73a2ed31"
,
1
,
"0c-rewritten-in-theirs.txt"
},
{
0100644
,
"efc9121fdedaf08ba180b53ebfbcf71bd488ed09"
,
2
,
"0c-rewritten-in-theirs.txt"
},
{
0100644
,
"712ebba6669ea847d9829e4f1059d6c830c8b531"
,
3
,
"0c-rewritten-in-theirs.txt"
},
{
0100644
,
"c3d02eeef75183df7584d8d13ac03053910c1301"
,
0
,
"1a-newname-in-ours-edited-in-theirs.txt"
},
{
0100644
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
,
0
,
"1a-newname-in-ours.txt"
},
{
0100644
,
"c3d02eeef75183df7584d8d13ac03053910c1301"
,
1
,
"1a-renamed-in-ours-edited-in-theirs.txt"
},
{
0100644
,
"0d872f8e871a30208305978ecbf9e66d864f1638"
,
3
,
"1a-renamed-in-ours-edited-in-theirs.txt"
},
{
0100644
,
"241a1005cd9b980732741b74385b891142bcba28"
,
0
,
"1b-newname-in-theirs-edited-in-ours.txt"
},
{
0100644
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
,
0
,
"1b-newname-in-theirs.txt"
},
{
0100644
,
"241a1005cd9b980732741b74385b891142bcba28"
,
1
,
"1b-renamed-in-theirs-edited-in-ours.txt"
},
{
0100644
,
"ed9523e62e453e50dd9be1606af19399b96e397a"
,
2
,
"1b-renamed-in-theirs-edited-in-ours.txt"
},
{
0100644
,
"178940b450f238a56c0d75b7955cb57b38191982"
,
0
,
"2-newname-in-both.txt"
},
{
0100644
,
"18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"
,
0
,
"3a-newname-in-ours-deleted-in-theirs.txt"
},
{
0100644
,
"36219b49367146cb2e6a1555b5a9ebd4d0328495"
,
0
,
"3b-newname-in-theirs-deleted-in-ours.txt"
},
{
0100644
,
"227792b52aaa0b238bea00ec7e509b02623f168c"
,
2
,
"4a-newname-in-ours-added-in-theirs.txt"
},
{
0100644
,
"8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a"
,
3
,
"4a-newname-in-ours-added-in-theirs.txt"
},
{
0100644
,
"de872ee3618b894992e9d1e18ba2ebe256a112f9"
,
2
,
"4b-newname-in-theirs-added-in-ours.txt"
},
{
0100644
,
"98d52d07c0b0bbf2b46548f6aa521295c2cb55db"
,
3
,
"4b-newname-in-theirs-added-in-ours.txt"
},
{
0100644
,
"d3719a5ae8e4d92276b5313ce976f6ee5af2b436"
,
2
,
"5a-newname-in-ours-added-in-theirs.txt"
},
{
0100644
,
"98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714"
,
3
,
"5a-newname-in-ours-added-in-theirs.txt"
},
{
0100644
,
"385c8a0f26ddf79e9041e15e17dc352ed2c4cced"
,
2
,
"5b-newname-in-theirs-added-in-ours.txt"
},
{
0100644
,
"63247125386de9ec90a27ad36169307bf8a11a38"
,
3
,
"5b-newname-in-theirs-added-in-ours.txt"
},
{
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
,
0
,
"6-both-renamed-1-to-2-ours.txt"
},
{
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
,
0
,
"6-both-renamed-1-to-2-theirs.txt"
},
{
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
,
2
,
"7-both-renamed.txt"
},
{
0100644
,
"b69fe837e4cecfd4c9a40cdca7c138468687df07"
,
3
,
"7-both-renamed.txt"
},
};
cl_git_pass
(
merge_trees_from_branches
(
&
index
,
repo
,
BRANCH_RENAME_OURS
,
BRANCH_RENAME_THEIRS
,
&
opts
));
cl_assert
(
merge_test_index
(
index
,
merge_index_entries
,
32
));
git_index_free
(
index
);
}
tests-clar/merge/trees/treediff.c
View file @
0462fba5
...
...
@@ -12,11 +12,17 @@ static git_repository *repo;
#define TREE_OID_ANCESTOR "0d52e3a556e189ba0948ae56780918011c1b167d"
#define TREE_OID_MASTER "1f81433e3161efbf250576c58fede7f6b836f3d3"
#define TREE_OID_BRANCH "eea9286df54245fea72c5b557291470eb825f38f"
#define TREE_OID_RENAMES1 "f5f9dd5886a6ee20272be0aafc790cba43b31931"
#define TREE_OID_RENAMES2 "5fbfbdc04b4eca46f54f4853a3c5a1dce28f5165"
#define TREE_OID_DF_ANCESTOR "b8a3a806d3950e8c0a03a34f234a92eff0e2c68d"
#define TREE_OID_DF_SIDE1 "ee1d6f164893c1866a323f072eeed36b855656be"
#define TREE_OID_DF_SIDE2 "6178885b38fe96e825ac0f492c0a941f288b37f6"
#define TREE_OID_RENAME_CONFLICT_ANCESTOR "476dbb3e207313d1d8aaa120c6ad204bf1295e53"
#define TREE_OID_RENAME_CONFLICT_OURS "c4efe31e9decccc8b2b4d3df9aac2cdfe2995618"
#define TREE_OID_RENAME_CONFLICT_THEIRS "9e7f4359c469f309b6057febf4c6e80742cbed5b"
void
test_merge_trees_treediff__initialize
(
void
)
{
repo
=
cl_git_sandbox_init
(
TEST_REPO_PATH
);
...
...
@@ -46,6 +52,20 @@ static void test_find_differences(
git_tree
*
ancestor_tree
,
*
ours_tree
,
*
theirs_tree
;
struct
treediff_cb_data
treediff_cb_data
=
{
0
};
git_merge_tree_opts
opts
=
GIT_MERGE_TREE_OPTS_INIT
;
opts
.
flags
|=
GIT_MERGE_TREE_FIND_RENAMES
;
opts
.
target_limit
=
1000
;
opts
.
rename_threshold
=
50
;
opts
.
metric
=
git__malloc
(
sizeof
(
git_diff_similarity_metric
));
cl_assert
(
opts
.
metric
!=
NULL
);
opts
.
metric
->
file_signature
=
git_diff_find_similar__hashsig_for_file
;
opts
.
metric
->
buffer_signature
=
git_diff_find_similar__hashsig_for_buf
;
opts
.
metric
->
free_signature
=
git_diff_find_similar__hashsig_free
;
opts
.
metric
->
similarity
=
git_diff_find_similar__calc_similarity
;
opts
.
metric
->
payload
=
(
void
*
)
GIT_HASHSIG_SMART_WHITESPACE
;
cl_git_pass
(
git_oid_fromstr
(
&
ancestor_oid
,
ancestor_oidstr
));
cl_git_pass
(
git_oid_fromstr
(
&
ours_oid
,
ours_oidstr
));
cl_git_pass
(
git_oid_fromstr
(
&
theirs_oid
,
theirs_oidstr
));
...
...
@@ -55,6 +75,7 @@ static void test_find_differences(
cl_git_pass
(
git_tree_lookup
(
&
theirs_tree
,
repo
,
&
theirs_oid
));
cl_git_pass
(
git_merge_diff_list__find_differences
(
merge_diff_list
,
ancestor_tree
,
ours_tree
,
theirs_tree
));
cl_git_pass
(
git_merge_diff_list__find_renames
(
repo
,
merge_diff_list
,
&
opts
));
/*
dump_merge_index(merge_index);
...
...
@@ -72,6 +93,8 @@ static void test_find_differences(
git_tree_free
(
theirs_tree
);
git_merge_diff_list__free
(
merge_diff_list
);
git__free
(
opts
.
metric
);
}
void
test_merge_trees_treediff__simple
(
void
)
...
...
@@ -277,3 +300,255 @@ void test_merge_trees_treediff__df_conflicts(void)
test_find_differences
(
TREE_OID_DF_ANCESTOR
,
TREE_OID_DF_SIDE1
,
TREE_OID_DF_SIDE2
,
treediff_conflict_data
,
20
);
}
void
test_merge_trees_treediff__strict_renames
(
void
)
{
struct
merge_index_conflict_data
treediff_conflict_data
[]
=
{
{
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"233c0919c998ed110a4b6ff36f353aec8b713487"
,
0
,
"added-in-master.txt"
,
GIT_DELTA_ADDED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"6212c31dab5e482247d7977e4f0dd3601decf13b"
,
0
,
"automergeable.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf"
,
0
,
"automergeable.txt"
,
GIT_DELTA_MODIFIED
},
{
0100644
,
"6212c31dab5e482247d7977e4f0dd3601decf13b"
,
0
,
"automergeable.txt"
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b"
,
0
,
"changed-in-master.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"11deab00b2d3a6f5a3073988ac050c2d7b6655e2"
,
0
,
"changed-in-master.txt"
,
GIT_DELTA_MODIFIED
},
{
0100644
,
"ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b"
,
0
,
"changed-in-master.txt"
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"d427e0b2e138501a3d15cc376077a3631e15bd46"
,
0
,
"conflicting.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"4e886e602529caa9ab11d71f86634bd1b6e0de10"
,
0
,
"conflicting.txt"
,
GIT_DELTA_MODIFIED
},
{
0100644
,
"d427e0b2e138501a3d15cc376077a3631e15bd46"
,
0
,
"conflicting.txt"
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"dfe3f22baa1f6fce5447901c3086bae368de6bdd"
,
0
,
"removed-in-branch.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"dfe3f22baa1f6fce5447901c3086bae368de6bdd"
,
0
,
"removed-in-branch.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"dfe3f22baa1f6fce5447901c3086bae368de6bdd"
,
0
,
"renamed-in-branch.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5"
,
0
,
"removed-in-master.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_DELETED
},
{
0100644
,
"5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5"
,
0
,
"removed-in-master.txt"
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"c8f06f2e3bb2964174677e91f0abead0e43c9e5d"
,
0
,
"renamed.txt"
,
GIT_DELTA_ADDED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"c8f06f2e3bb2964174677e91f0abead0e43c9e5d"
,
0
,
"unchanged.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"c8f06f2e3bb2964174677e91f0abead0e43c9e5d"
,
0
,
"unchanged.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"c8f06f2e3bb2964174677e91f0abead0e43c9e5d"
,
0
,
"copied.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_NONE
,
},
};
test_find_differences
(
TREE_OID_ANCESTOR
,
TREE_OID_MASTER
,
TREE_OID_RENAMES1
,
treediff_conflict_data
,
8
);
}
void
test_merge_trees_treediff__rename_conflicts
(
void
)
{
struct
merge_index_conflict_data
treediff_conflict_data
[]
=
{
{
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
,
0
,
"0b-duplicated-in-ours.txt"
,
GIT_DELTA_ADDED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"f0ce2b8e4986084d9b308fb72709e414c23eb5e6"
,
0
,
"0b-rewritten-in-ours.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"e376fbdd06ebf021c92724da9f26f44212734e3e"
,
0
,
"0b-rewritten-in-ours.txt"
,
GIT_DELTA_MODIFIED
},
{
0100644
,
"b2d399ae15224e1d58066e3c8df70ce37de7a656"
,
0
,
"0b-rewritten-in-ours.txt"
,
GIT_DELTA_MODIFIED
},
GIT_MERGE_DIFF_BOTH_MODIFIED
,
},
{
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"2f56120107d680129a5d9791b521cb1e73a2ed31"
,
0
,
"0c-duplicated-in-theirs.txt"
,
GIT_DELTA_ADDED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"2f56120107d680129a5d9791b521cb1e73a2ed31"
,
0
,
"0c-rewritten-in-theirs.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"efc9121fdedaf08ba180b53ebfbcf71bd488ed09"
,
0
,
"0c-rewritten-in-theirs.txt"
,
GIT_DELTA_MODIFIED
},
{
0100644
,
"712ebba6669ea847d9829e4f1059d6c830c8b531"
,
0
,
"0c-rewritten-in-theirs.txt"
,
GIT_DELTA_MODIFIED
},
GIT_MERGE_DIFF_BOTH_MODIFIED
,
},
{
{
0100644
,
"c3d02eeef75183df7584d8d13ac03053910c1301"
,
0
,
"1a-renamed-in-ours-edited-in-theirs.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"c3d02eeef75183df7584d8d13ac03053910c1301"
,
0
,
"1a-newname-in-ours-edited-in-theirs.txt"
,
GIT_DELTA_RENAMED
},
{
0100644
,
"0d872f8e871a30208305978ecbf9e66d864f1638"
,
0
,
"1a-renamed-in-ours-edited-in-theirs.txt"
,
GIT_DELTA_MODIFIED
},
GIT_MERGE_DIFF_RENAMED_MODIFIED
,
},
{
{
0100644
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
,
0
,
"1a-renamed-in-ours.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
,
0
,
"1a-newname-in-ours.txt"
,
GIT_DELTA_RENAMED
},
{
0100644
,
"d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"
,
0
,
"1a-renamed-in-ours.txt"
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"241a1005cd9b980732741b74385b891142bcba28"
,
0
,
"1b-renamed-in-theirs-edited-in-ours.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"ed9523e62e453e50dd9be1606af19399b96e397a"
,
0
,
"1b-renamed-in-theirs-edited-in-ours.txt"
,
GIT_DELTA_MODIFIED
},
{
0100644
,
"241a1005cd9b980732741b74385b891142bcba28"
,
0
,
"1b-newname-in-theirs-edited-in-ours.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_RENAMED_MODIFIED
,
},
{
{
0100644
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
,
0
,
"1b-renamed-in-theirs.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
,
0
,
"1b-renamed-in-theirs.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"
,
0
,
"1b-newname-in-theirs.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"178940b450f238a56c0d75b7955cb57b38191982"
,
0
,
"2-renamed-in-both.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"178940b450f238a56c0d75b7955cb57b38191982"
,
0
,
"2-newname-in-both.txt"
,
GIT_DELTA_RENAMED
},
{
0100644
,
"178940b450f238a56c0d75b7955cb57b38191982"
,
0
,
"2-newname-in-both.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_BOTH_RENAMED
,
},
{
{
0100644
,
"18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"
,
0
,
"3a-renamed-in-ours-deleted-in-theirs.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"
,
0
,
"3a-newname-in-ours-deleted-in-theirs.txt"
,
GIT_DELTA_RENAMED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_DELETED
},
GIT_MERGE_DIFF_RENAMED_DELETED
,
},
{
{
0100644
,
"36219b49367146cb2e6a1555b5a9ebd4d0328495"
,
0
,
"3b-renamed-in-theirs-deleted-in-ours.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_DELETED
},
{
0100644
,
"36219b49367146cb2e6a1555b5a9ebd4d0328495"
,
0
,
"3b-newname-in-theirs-deleted-in-ours.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_RENAMED_DELETED
,
},
{
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a"
,
0
,
"4a-newname-in-ours-added-in-theirs.txt"
,
GIT_DELTA_ADDED
},
GIT_MERGE_DIFF_RENAMED_ADDED
,
},
{
{
0100644
,
"227792b52aaa0b238bea00ec7e509b02623f168c"
,
0
,
"4a-renamed-in-ours-added-in-theirs.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"227792b52aaa0b238bea00ec7e509b02623f168c"
,
0
,
"4a-newname-in-ours-added-in-theirs.txt"
,
GIT_DELTA_RENAMED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_DELETED
},
GIT_MERGE_DIFF_RENAMED_ADDED
,
},
{
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"de872ee3618b894992e9d1e18ba2ebe256a112f9"
,
0
,
"4b-newname-in-theirs-added-in-ours.txt"
,
GIT_DELTA_ADDED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_RENAMED_ADDED
,
},
{
{
0100644
,
"98d52d07c0b0bbf2b46548f6aa521295c2cb55db"
,
0
,
"4b-renamed-in-theirs-added-in-ours.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_DELETED
},
{
0100644
,
"98d52d07c0b0bbf2b46548f6aa521295c2cb55db"
,
0
,
"4b-newname-in-theirs-added-in-ours.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_RENAMED_ADDED
,
},
{
{
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
,
0
,
"5-both-renamed-1-to-2.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
,
0
,
"5-both-renamed-1-to-2-ours.txt"
,
GIT_DELTA_RENAMED
},
{
0100644
,
"d8fa77b6833082c1ea36b7828a582d4c43882450"
,
0
,
"5-both-renamed-1-to-2-theirs.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2
,
},
{
{
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
,
0
,
"6-both-renamed-side-1.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
,
0
,
"6-both-renamed.txt"
,
GIT_DELTA_RENAMED
},
{
0100644
,
"b42712cfe99a1a500b2a51fe984e0b8a7702ba11"
,
0
,
"6-both-renamed-side-1.txt"
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1
,
},
{
{
0100644
,
"b69fe837e4cecfd4c9a40cdca7c138468687df07"
,
0
,
"6-both-renamed-side-2.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"b69fe837e4cecfd4c9a40cdca7c138468687df07"
,
0
,
"6-both-renamed-side-2.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"b69fe837e4cecfd4c9a40cdca7c138468687df07"
,
0
,
"6-both-renamed.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1
,
},
};
test_find_differences
(
TREE_OID_RENAME_CONFLICT_ANCESTOR
,
TREE_OID_RENAME_CONFLICT_OURS
,
TREE_OID_RENAME_CONFLICT_THEIRS
,
treediff_conflict_data
,
18
);
}
void
test_merge_trees_treediff__best_renames
(
void
)
{
struct
merge_index_conflict_data
treediff_conflict_data
[]
=
{
{
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"233c0919c998ed110a4b6ff36f353aec8b713487"
,
0
,
"added-in-master.txt"
,
GIT_DELTA_ADDED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"6212c31dab5e482247d7977e4f0dd3601decf13b"
,
0
,
"automergeable.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf"
,
0
,
"automergeable.txt"
,
GIT_DELTA_MODIFIED
},
{
0100644
,
"45299c1ca5e07bba1fd90843056fb559f96b1f5a"
,
0
,
"renamed-90.txt"
,
GIT_DELTA_RENAMED
},
GIT_MERGE_DIFF_RENAMED_MODIFIED
,
},
{
{
0100644
,
"ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b"
,
0
,
"changed-in-master.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"11deab00b2d3a6f5a3073988ac050c2d7b6655e2"
,
0
,
"changed-in-master.txt"
,
GIT_DELTA_MODIFIED
},
{
0100644
,
"ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b"
,
0
,
"changed-in-master.txt"
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"d427e0b2e138501a3d15cc376077a3631e15bd46"
,
0
,
"conflicting.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"4e886e602529caa9ab11d71f86634bd1b6e0de10"
,
0
,
"conflicting.txt"
,
GIT_DELTA_MODIFIED
},
{
0100644
,
"d427e0b2e138501a3d15cc376077a3631e15bd46"
,
0
,
"conflicting.txt"
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0100644
,
"5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5"
,
0
,
"removed-in-master.txt"
,
GIT_DELTA_UNMODIFIED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_DELETED
},
{
0100644
,
"5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5"
,
0
,
"removed-in-master.txt"
,
GIT_DELTA_UNMODIFIED
},
GIT_MERGE_DIFF_MODIFIED_DELETED
,
},
{
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"5843febcb23480df0b5edb22a21c59c772bb8e29"
,
0
,
"renamed-50.txt"
,
GIT_DELTA_ADDED
},
GIT_MERGE_DIFF_NONE
,
},
{
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0
,
""
,
0
,
""
,
GIT_DELTA_UNMODIFIED
},
{
0100644
,
"a77a56a49f8f3ae242e02717f18ebbc60c5cc543"
,
0
,
"renamed-75.txt"
,
GIT_DELTA_ADDED
},
GIT_MERGE_DIFF_NONE
,
},
};
test_find_differences
(
TREE_OID_ANCESTOR
,
TREE_OID_MASTER
,
TREE_OID_RENAMES2
,
treediff_conflict_data
,
7
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment