зеркало из https://github.com/microsoft/git.git
Merge branch 'en/rename-directory-detection'
Rename detection logic in "diff" family that is used in "merge" has learned to guess when all of x/a, x/b and x/c have moved to z/a, z/b and z/c, it is likely that x/d added in the meantime would also want to move to z/d by taking the hint that the entire directory 'x' moved to 'z'. A bug causing dirty files involved in a rename to be overwritten during merge has also been fixed as part of this work. * en/rename-directory-detection: (29 commits) merge-recursive: ensure we write updates for directory-renamed file merge-recursive: avoid spurious rename/rename conflict from dir renames directory rename detection: new testcases showcasing a pair of bugs merge-recursive: fix remaining directory rename + dirty overwrite cases merge-recursive: fix overwriting dirty files involved in renames merge-recursive: avoid clobbering untracked files with directory renames merge-recursive: apply necessary modifications for directory renames merge-recursive: when comparing files, don't include trees merge-recursive: check for file level conflicts then get new name merge-recursive: add computation of collisions due to dir rename & merging merge-recursive: check for directory level conflicts merge-recursive: add get_directory_renames() merge-recursive: make a helper function for cleanup for handle_renames merge-recursive: split out code for determining diff_filepairs merge-recursive: make !o->detect_rename codepath more obvious merge-recursive: fix leaks of allocated renames and diff_filepairs merge-recursive: introduce new functions to handle rename logic merge-recursive: move the get_renames() function directory rename detection: tests for handling overwriting dirty files directory rename detection: tests for handling overwriting untracked files ...
This commit is contained in:
Коммит
e4bb62fa1e
1243
merge-recursive.c
1243
merge-recursive.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,6 +1,7 @@
|
|||
#ifndef MERGE_RECURSIVE_H
|
||||
#define MERGE_RECURSIVE_H
|
||||
|
||||
#include "unpack-trees.h"
|
||||
#include "string-list.h"
|
||||
|
||||
struct merge_options {
|
||||
|
@ -27,6 +28,32 @@ struct merge_options {
|
|||
struct strbuf obuf;
|
||||
struct hashmap current_file_dir_set;
|
||||
struct string_list df_conflict_file_set;
|
||||
struct unpack_trees_options unpack_opts;
|
||||
};
|
||||
|
||||
/*
|
||||
* For dir_rename_entry, directory names are stored as a full path from the
|
||||
* toplevel of the repository and do not include a trailing '/'. Also:
|
||||
*
|
||||
* dir: original name of directory being renamed
|
||||
* non_unique_new_dir: if true, could not determine new_dir
|
||||
* new_dir: final name of directory being renamed
|
||||
* possible_new_dirs: temporary used to help determine new_dir; see comments
|
||||
* in get_directory_renames() for details
|
||||
*/
|
||||
struct dir_rename_entry {
|
||||
struct hashmap_entry ent; /* must be the first member! */
|
||||
char *dir;
|
||||
unsigned non_unique_new_dir:1;
|
||||
struct strbuf new_dir;
|
||||
struct string_list possible_new_dirs;
|
||||
};
|
||||
|
||||
struct collision_entry {
|
||||
struct hashmap_entry ent; /* must be the first member! */
|
||||
char *target_file;
|
||||
struct string_list source_files;
|
||||
unsigned reported_already:1;
|
||||
};
|
||||
|
||||
/* merge_trees() but with recursive ancestor consolidation */
|
||||
|
|
16
strbuf.c
16
strbuf.c
|
@ -1,5 +1,6 @@
|
|||
#include "cache.h"
|
||||
#include "refs.h"
|
||||
#include "string-list.h"
|
||||
#include "utf8.h"
|
||||
|
||||
int starts_with(const char *str, const char *prefix)
|
||||
|
@ -171,6 +172,21 @@ struct strbuf **strbuf_split_buf(const char *str, size_t slen,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void strbuf_add_separated_string_list(struct strbuf *str,
|
||||
const char *sep,
|
||||
struct string_list *slist)
|
||||
{
|
||||
struct string_list_item *item;
|
||||
int sep_needed = 0;
|
||||
|
||||
for_each_string_list_item(item, slist) {
|
||||
if (sep_needed)
|
||||
strbuf_addstr(str, sep);
|
||||
strbuf_addstr(str, item->string);
|
||||
sep_needed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void strbuf_list_free(struct strbuf **sbs)
|
||||
{
|
||||
struct strbuf **s = sbs;
|
||||
|
|
16
strbuf.h
16
strbuf.h
|
@ -1,6 +1,8 @@
|
|||
#ifndef STRBUF_H
|
||||
#define STRBUF_H
|
||||
|
||||
struct string_list;
|
||||
|
||||
/**
|
||||
* strbuf's are meant to be used with all the usual C string and memory
|
||||
* APIs. Given that the length of the buffer is known, it's often better to
|
||||
|
@ -531,6 +533,20 @@ static inline struct strbuf **strbuf_split(const struct strbuf *sb,
|
|||
return strbuf_split_max(sb, terminator, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds all strings of a string list to the strbuf, separated by the given
|
||||
* separator. For example, if sep is
|
||||
* ', '
|
||||
* and slist contains
|
||||
* ['element1', 'element2', ..., 'elementN'],
|
||||
* then write:
|
||||
* 'element1, element2, ..., elementN'
|
||||
* to str. If only one element, just write "element1" to str.
|
||||
*/
|
||||
extern void strbuf_add_separated_string_list(struct strbuf *str,
|
||||
const char *sep,
|
||||
struct string_list *slist);
|
||||
|
||||
/**
|
||||
* Free a NULL-terminated list of strbufs (for example, the return
|
||||
* values of the strbuf_split*() functions).
|
||||
|
|
|
@ -141,7 +141,7 @@ test_expect_success 'cherry-pick "-" works with arguments' '
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_failure 'cherry-pick works with dirty renamed file' '
|
||||
test_expect_success 'cherry-pick works with dirty renamed file' '
|
||||
test_commit to-rename &&
|
||||
git checkout -b unrelated &&
|
||||
test_commit unrelated &&
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -92,7 +92,7 @@ test_expect_success 'will not overwrite removed file with staged changes' '
|
|||
test_cmp important c1.c
|
||||
'
|
||||
|
||||
test_expect_failure 'will not overwrite unstaged changes in renamed file' '
|
||||
test_expect_success 'will not overwrite unstaged changes in renamed file' '
|
||||
git reset --hard c1 &&
|
||||
git mv c1.c other.c &&
|
||||
git commit -m rename &&
|
||||
|
|
|
@ -1509,8 +1509,8 @@ static int verify_uptodate_1(const struct cache_entry *ce,
|
|||
add_rejected_path(o, error_type, ce->name);
|
||||
}
|
||||
|
||||
static int verify_uptodate(const struct cache_entry *ce,
|
||||
struct unpack_trees_options *o)
|
||||
int verify_uptodate(const struct cache_entry *ce,
|
||||
struct unpack_trees_options *o)
|
||||
{
|
||||
if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
|
||||
return 0;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef UNPACK_TREES_H
|
||||
#define UNPACK_TREES_H
|
||||
|
||||
#include "tree-walk.h"
|
||||
#include "string-list.h"
|
||||
|
||||
#define MAX_UNPACK_TREES 8
|
||||
|
@ -78,6 +79,9 @@ struct unpack_trees_options {
|
|||
extern int unpack_trees(unsigned n, struct tree_desc *t,
|
||||
struct unpack_trees_options *options);
|
||||
|
||||
int verify_uptodate(const struct cache_entry *ce,
|
||||
struct unpack_trees_options *o);
|
||||
|
||||
int threeway_merge(const struct cache_entry * const *stages,
|
||||
struct unpack_trees_options *o);
|
||||
int twoway_merge(const struct cache_entry * const *src,
|
||||
|
|
Загрузка…
Ссылка в новой задаче