提交 96379f04 编写于 作者: J Junio C Hamano

Merge branch 'en/merge-directory-renames'

"git merge-recursive" backend recently learned a new heuristics to
infer file movement based on how other files in the same directory
moved.  As this is inherently less robust heuristics than the one
based on the content similarity of the file itself (rather than
based on what its neighbours are doing), it sometimes gives an
outcome unexpected by the end users.  This has been toned down to
leave the renamed paths in higher/conflicted stages in the index so
that the user can examine and confirm the result.

* en/merge-directory-renames:
  merge-recursive: switch directory rename detection default
  merge-recursive: give callers of handle_content_merge() access to contents
  merge-recursive: track information associated with directory renames
  t6043: fix copied test description to match its purpose
  merge-recursive: switch from (oid,mode) pairs to a diff_filespec
  merge-recursive: cleanup handle_rename_* function signatures
  merge-recursive: track branch where rename occurred in rename struct
  merge-recursive: remove ren[12]_other fields from rename_conflict_info
  merge-recursive: shrink rename_conflict_info
  merge-recursive: move some struct declarations together
  merge-recursive: use 'ci' for rename_conflict_info variable name
  merge-recursive: rename locals 'o' and 'a' to 'obuf' and 'abuf'
  merge-recursive: rename diff_filespec 'one' to 'o'
  merge-recursive: rename merge_options argument from 'o' to 'opt'
  Use 'unsigned short' for mode, like diff_filespec does
......@@ -39,9 +39,22 @@ merge.renameLimit::
is turned off.
merge.renames::
Whether and how Git detects renames. If set to "false",
rename detection is disabled. If set to "true", basic rename
detection is enabled. Defaults to the value of diff.renames.
Whether Git detects renames. If set to "false", rename detection
is disabled. If set to "true", basic rename detection is enabled.
Defaults to the value of diff.renames.
merge.directoryRenames::
Whether Git detects directory renames, affecting what happens at
merge time to new files added to a directory on one side of
history when that directory was renamed on the other side of
history. If merge.directoryRenames is set to "false", directory
rename detection is disabled, meaning that such new files will be
left behind in the old directory. If set to "true", directory
rename detection is enabled, meaning that such new files will be
moved into the new directory. If set to "conflict", a conflict
will be reported for such paths. If merge.renames is false,
merge.directoryRenames is ignored and treated as false. Defaults
to "conflict".
merge.renormalize::
Tell Git that canonical representation of files in the
......
......@@ -415,7 +415,7 @@ static void parse_treeish_arg(const char **argv,
if (prefix) {
struct object_id tree_oid;
unsigned int mode;
unsigned short mode;
int err;
err = get_tree_entry(&tree->object.oid, prefix, &tree_oid,
......
......@@ -99,7 +99,7 @@ static void verify_working_tree_path(struct repository *r,
for (parents = work_tree->parents; parents; parents = parents->next) {
const struct object_id *commit_oid = &parents->item->object.oid;
struct object_id blob_oid;
unsigned mode;
unsigned short mode;
if (!get_tree_entry(commit_oid, path, &blob_oid, &mode) &&
oid_object_info(r, &blob_oid, NULL) == OBJ_BLOB)
......
......@@ -52,7 +52,7 @@ struct blame_origin {
struct blame_entry *suspects;
mmfile_t file;
struct object_id blob_oid;
unsigned mode;
unsigned short mode;
/* guilty gets set when shipping any suspects to the final
* blame list instead of other commits
*/
......
......@@ -110,7 +110,7 @@ static int check_local_mod(struct object_id *head, int index_only)
const struct cache_entry *ce;
const char *name = list.entry[i].name;
struct object_id oid;
unsigned mode;
unsigned short mode;
int local_changes = 0;
int staged_changes = 0;
......
......@@ -597,7 +597,7 @@ static struct cache_entry *read_one_ent(const char *which,
struct object_id *ent, const char *path,
int namelen, int stage)
{
unsigned mode;
unsigned short mode;
struct object_id oid;
struct cache_entry *ce;
......
......@@ -1333,7 +1333,7 @@ static inline int hex2chr(const char *s)
#define FALLBACK_DEFAULT_ABBREV 7
struct object_context {
unsigned mode;
unsigned short mode;
/*
* symlink_path is only used by get_tree_entry_follow_symlinks,
* and only for symlinks that point outside the repository.
......
......@@ -604,7 +604,7 @@ static int fsck_tree(struct tree *item, struct fsck_options *options)
o_name = NULL;
while (desc.size) {
unsigned mode;
unsigned short mode;
const char *name;
const struct object_id *oid;
......
......@@ -498,7 +498,7 @@ static struct commit *check_single_commit(struct rev_info *revs)
static void fill_blob_sha1(struct commit *commit, struct diff_filespec *spec)
{
unsigned mode;
unsigned short mode;
struct object_id oid;
if (get_tree_entry(&commit->object.oid, spec->path, &oid, &mode))
......
......@@ -140,7 +140,7 @@ static void match_trees(const struct object_id *hash1,
while (one.size) {
const char *path;
const struct object_id *elem;
unsigned mode;
unsigned short mode;
int score;
elem = tree_entry_extract(&one, &path, &mode);
......@@ -196,7 +196,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,
rewrite_here = NULL;
while (desc.size) {
const char *name;
unsigned mode;
unsigned short mode;
tree_entry_extract(&desc, &name, &mode);
if (strlen(name) == toplen &&
......@@ -285,7 +285,7 @@ void shift_tree(const struct object_id *hash1,
if (add_score < del_score) {
/* We need to pick a subtree of two */
unsigned mode;
unsigned short mode;
if (!*del_prefix)
return;
......@@ -313,7 +313,7 @@ void shift_tree_by(const struct object_id *hash1,
const char *shift_prefix)
{
struct object_id sub1, sub2;
unsigned mode1, mode2;
unsigned short mode1, mode2;
unsigned candidate = 0;
/* Can hash2 be a tree at shift_prefix in tree hash1? */
......
此差异已折叠。
......@@ -988,7 +988,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
combine_notes_fn combine_notes, int flags)
{
struct object_id oid, object_oid;
unsigned mode;
unsigned short mode;
struct leaf_node root_tree;
if (!t)
......
......@@ -1608,7 +1608,7 @@ static void diagnose_invalid_oid_path(const char *prefix,
int object_name_len)
{
struct object_id oid;
unsigned mode;
unsigned short mode;
if (!prefix)
prefix = "";
......
......@@ -42,7 +42,7 @@ test_expect_success 'rebase --interactive: directory rename detected' '
git checkout B^0 &&
set_fake_editor &&
FAKE_LINES="1" git rebase --interactive A &&
FAKE_LINES="1" git -c merge.directoryRenames=true rebase --interactive A &&
git ls-files -s >out &&
test_line_count = 5 out &&
......@@ -58,7 +58,7 @@ test_expect_failure 'rebase (am): directory rename detected' '
git checkout B^0 &&
git rebase A &&
git -c merge.directoryRenames=true rebase A &&
git ls-files -s >out &&
test_line_count = 5 out &&
......@@ -74,7 +74,7 @@ test_expect_success 'rebase --merge: directory rename detected' '
git checkout B^0 &&
git rebase --merge A &&
git -c merge.directoryRenames=true rebase --merge A &&
git ls-files -s >out &&
test_line_count = 5 out &&
......@@ -92,7 +92,7 @@ test_expect_failure 'am: directory rename detected' '
git format-patch -1 B &&
git am --3way 0001*.patch &&
git -c merge.directoryRenames=true am --3way 0001*.patch &&
git ls-files -s >out &&
test_line_count = 5 out &&
......
此差异已折叠。
......@@ -466,7 +466,7 @@ test_expect_success '3a-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
git checkout A^0 &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
test_i18ngrep ! "Skipped bar/bq" out &&
test_must_be_empty err &&
......@@ -495,7 +495,7 @@ test_expect_success '3a-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
git checkout B^0 &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
test_i18ngrep ! "Skipped bar/bq" out &&
test_must_be_empty err &&
......@@ -560,7 +560,7 @@ test_expect_success '3b-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
git checkout A^0 &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
test_i18ngrep ! "Skipped bar/bq" out &&
test_must_be_empty err &&
......@@ -589,7 +589,7 @@ test_expect_success '3b-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
git checkout B^0 &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
test_i18ngrep ! "Skipped bar/bq" out &&
test_must_be_empty err &&
......
......@@ -181,7 +181,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
struct tree_desc *t, struct tree_desc *tp,
int imin)
{
unsigned mode;
unsigned short mode;
const char *path;
const struct object_id *oid;
int pathlen;
......
......@@ -500,7 +500,7 @@ struct dir_state {
struct object_id oid;
};
static int find_tree_entry(struct tree_desc *t, const char *name, struct object_id *result, unsigned *mode)
static int find_tree_entry(struct tree_desc *t, const char *name, struct object_id *result, unsigned short *mode)
{
int namelen = strlen(name);
while (t->size) {
......@@ -535,7 +535,7 @@ static int find_tree_entry(struct tree_desc *t, const char *name, struct object_
return -1;
}
int get_tree_entry(const struct object_id *tree_oid, const char *name, struct object_id *oid, unsigned *mode)
int get_tree_entry(const struct object_id *tree_oid, const char *name, struct object_id *oid, unsigned short *mode)
{
int retval;
void *tree;
......@@ -585,7 +585,7 @@ int get_tree_entry(const struct object_id *tree_oid, const char *name, struct ob
* See the code for enum get_oid_result for a description of
* the return values.
*/
enum get_oid_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode)
enum get_oid_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned short *mode)
{
int retval = MISSING_OBJECT;
struct dir_state *parents = NULL;
......
......@@ -16,7 +16,7 @@ struct tree_desc {
unsigned int size;
};
static inline const struct object_id *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep)
static inline const struct object_id *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned short *modep)
{
*pathp = desc->entry.path;
*modep = desc->entry.mode;
......@@ -51,7 +51,7 @@ struct traverse_info;
typedef int (*traverse_callback_t)(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *);
int traverse_trees(struct index_state *istate, int n, struct tree_desc *t, struct traverse_info *info);
enum get_oid_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode);
enum get_oid_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned short *mode);
struct traverse_info {
const char *traverse_path;
......@@ -66,7 +66,7 @@ struct traverse_info {
int show_all_errors;
};
int get_tree_entry(const struct object_id *, const char *, struct object_id *, unsigned *);
int get_tree_entry(const struct object_id *, const char *, struct object_id *, unsigned short *);
extern char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n);
extern void setup_traverse_info(struct traverse_info *info, const char *base);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册