In a variable-args function, the code for writing into a strbuf is
non-trivial. We ended up cutting and pasting it in several places
because there was no vprintf-style function for strbufs (which in turn
was held up by a lack of va_copy).
Now that we have a fallback va_copy, we can add strbuf_vaddf, the
strbuf equivalent of vsprintf. And we can clean up the cut and paste
mess.
Signed-off-by: Jeff King <peff@peff.net>
Improved-by: Christian Couder <christian.couder@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* en/merge-recursive: (41 commits)
t6022: Use -eq not = to test output of wc -l
merge-recursive:make_room_for_directories - work around dumb compilers
merge-recursive: Remove redundant path clearing for D/F conflicts
merge-recursive: Make room for directories in D/F conflicts
handle_delete_modify(): Check whether D/F conflicts are still present
merge_content(): Check whether D/F conflicts are still present
conflict_rename_rename_1to2(): Fix checks for presence of D/F conflicts
conflict_rename_delete(): Check whether D/F conflicts are still present
merge-recursive: Delay modify/delete conflicts if D/F conflict present
merge-recursive: Delay content merging for renames
merge-recursive: Delay handling of rename/delete conflicts
merge-recursive: Move handling of double rename of one file to other file
merge-recursive: Move handling of double rename of one file to two
merge-recursive: Avoid doubly merging rename/add conflict contents
merge-recursive: Update merge_content() call signature
merge-recursive: Update conflict_rename_rename_1to2() call signature
merge-recursive: Structure process_df_entry() to handle more cases
merge-recursive: Have process_entry() skip D/F or rename entries
merge-recursive: New function to assist resolving renames in-core only
merge-recursive: New data structures for deferring of D/F conflicts
...
Conflicts:
t/t6020-merge-df.sh
t/t6036-recursive-corner-cases.sh
Some vintage of gcc does not seem to notice last_len is only used when
last_file is already set to non-NULL at which point last_len is also
set.
Noticed on FreeBSD 8
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The code had several places where individual checks were done to remove
files that could be in the way of directories in D/F conflicts. Not all
D/F conflicts could have a path cleared for them in such a manner, however,
leading to the need to create make_room_for_directories_of_df_conflicts()
as done in the previous patch. That new function could not have been
incorporated into the code sooner, since not all relevant code paths had
been deferred to process_df_entry() yet, leading to the creation of even
more of these now-redundant path removals.
Clean out all of these extra D/F path clearing cases.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When there are unmerged entries present, make sure to check for D/F
conflicts first and remove any files present in HEAD that would be in the
way of creating files below the correspondingly named directory. Such
files will be processed again at the end of the merge in
process_df_entry(); at that time we will be able to tell if we need to
and can reinstate the file, whether we need to place its contents in a
different file due to the directory still being present, etc.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
If all the paths below some directory involved in a D/F conflict were not
removed during the rest of the merge, then the contents of the file whose
path conflicted needs to be recorded in file with an alternative filename.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
If all the paths below some directory involved in a D/F conflict were not
removed during the rest of the merge, then the contents of the file whose
path conflicted needs to be recorded in file with an alternative filename.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This function is called from process_df_entry(), near the end of the merge.
Rather than just checking whether one of the sides of the merge had a
directory at the same path as one of our files, check whether that
directory is still present by this point of our merge.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
If all the paths below some directory involved in a D/F conflict were not
removed during the rest of the merge, then the contents of the file whose
path conflicted needs to be recorded in file with an alternative filename.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When handling merges with modify/delete conflicts, if the modified path is
involved in a D/F conflict, handle the issue in process_df_entry() rather
than process_entry().
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Move the handling of content merging for renames from process_renames() to
process_df_entry().
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Move the handling of rename/delete conflicts from process_renames() to
process_df_entry().
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Move the handling of rename/rename conflicts where one file is renamed on
both sides to the same file, from process_renames() to process_entry().
Here we avoid the three way merge logic by just using
update_stages_and_entry() to move the higher stage entries in the index
from the rename source to the rename destination, and then allow
process_entry() to do its magic.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Move the handling of rename/rename conflicts where one file is renamed to
two different files, from process_renames() to process_df_entry().
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When a commit moves A to B while another commit created B (or moved C to
B), and these two different commits serve as different merge-bases for a
later merge, c94736a (merge-recursive: don't segfault while handling
rename clashes 2009-07-30) added some special code to avoid segfaults.
Since that commit, the two versions of B are merged in place (which could
be potentially conflicting) and the intermediate result is used as the
virtual ancestor.
However, right before this special merge, try_merge was turned on, meaning
that process_renames() would try an alternative merge that ignores the
'add' part of the conflict, and, if the merge is clean, store that as the
new virtual ancestor. This could cause incorrect merging of criss-cross
merges; it would typically result in just recording a slightly confusing
merge base, but in some cases it could cause silent acceptance of one side
of a merge as the final resolution when a conflict should have been
flagged.
When we do a special merge for such a rename/add conflict between
merge-bases, turn try_merge off to avoid an inappropriate second merge.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Enable calling merge_content() and providing more information about renames
and D/F conflicts (which we will want to do from process_df_entry()).
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
To facilitate having this function called later using information stored
in a rename_df_conflict_info struct, accept a diff_filepair instead of a
rename.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Modify process_df_entry() (mostly just indentation level changes) to
get it ready for handling more D/F conflict type cases.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
If an entry has an associated rename_df_conflict_info, skip it and allow
it to be processed by process_df_entry().
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
process_renames() and process_entry() have nearly identical code for
doing three-way file merging to resolve content changes. Since we are
already deferring some of the current rename handling in order to better
handle D/F conflicts, it seems to make sense to defer content merging as
well and remove the (nearly) duplicated code sections for handling this
merging.
To facilitate this process, add a new update_stages_and_entry() function
which will map the higher stage index entries from two files involved in a
rename into the resulting rename destination's index entries, and update
the associated stage_data structure.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Since we need to resolve paths (including renames) in-core first and defer
checking of D/F conflicts (namely waiting to see if directories are still
in the way after all paths are resolved) before updating files involved in
D/F conflicts, we will need to first process_renames, then record some
information about the rename needed at D/F resolution time, and then make
use of that information when resolving D/F conflicts at the end.
This commit adds some relevant data structures for storing the necessary
information.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This move is in preparation for merge_content growing and being called from
multiple places in order to handle D/F conflicts.
I also snuck in a small change to the output in the case that the merged
content for the file matches the current file contents, to make it better
match (and thus more able to take over) how other merge_file() calls in
process_renames() are handled.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This move is in preparation for the function being called from multiple
places in order to handle D/F conflicts.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This move is in preparation for the function growing and being called from
multiple places in order to handle D/F conflicts.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Since we want to resolve merges in-core and then detect at the end whether
D/F conflicts remain in the way, we should just apply renames in-core and
let logic elsewhere check for D/F conflicts.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The names conflict_rename_rename and conflict_rename_rename_2 did not make
it clear what they were handling. Since the first of these handles one
file being renamed in both branches to different files, while the latter
handles two different files being renamed to the same thing, add a little
'1to2' and '2to1' suffix on these and an explanatory comment to make their
intent clearer.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
process_renames() had a variable named "stage" and derived variables
src_other and dst_other whose purpose was not immediately obvious; also,
I want to extend the scope of this variable and use it later, so it should
have a more descriptive name. Do so, and add a brief comment explaining
how it is used and what it relates to.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In 3734893 (merge-recursive: Fix D/F conflicts 2010-07-09),
process_df_entry() was added to process_renames() and process_entry() but
in a somewhat restrictive manner. Modify the code slightly to make it
clearer how we could chain more such functions if necessary, and alter
process_df_entry() to handle such chaining.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The recursive merge strategy turns on rename detection but leaves the
rename threshold at the default. Add a strategy option to allow the user
to specify a rename threshold to use.
Signed-off-by: Kevin Ballard <kevin@sb.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In merge-recursive.c, whenever there was a rename where a file name on one
side of the rename matches a directory name on the other side of the merge,
then the very first check that
string_list_has_string(&o->current_directory_set, ren1_dst)
would trigger forcing it into marking it as a rename/directory conflict.
However, if the path is only renamed on one side and a simple three-way
merge between the separate files resolves cleanly, then we don't need to
mark it as a rename/directory conflict. So, we can simply move the check
for rename/directory conflicts after we've verified that there isn't a
rename/rename conflict and that a threeway content merge doesn't work.
This changes the particular error message one gets in the case where the
directory name that a file on one side of the rename matches is not also
part of the rename pair. For example, with commits containing the files:
COMMON -> (HEAD, MERGE )
--------- --------------- -------
sub/file1 -> (sub/file1, newsub)
<NULL> -> (newsub/newfile, <NULL>)
then previously when one tried to merge MERGE into HEAD, one would get
CONFLICT (rename/directory): Rename sub/file1->newsub in HEAD directory newsub added in merge
Renaming sub/file1 to newsub~HEAD instead
Adding newsub/newfile
Automatic merge failed; fix conflicts and then commit the result.
After this patch, the error message will instead become:
Removing newsub
Adding newsub/newfile
CONFLICT (file/directory): There is a directory with name newsub in merge. Adding newsub as newsub~HEAD
Automatic merge failed; fix conflicts and then commit the result.
That makes more sense to me, because git can't know that there's a conflict
until after it's tried resolving paths involving newsub/newfile to see if
they are still in the way at the end (and if newsub/newfile is not in the
way at the end, there should be no conflict at all, which did not hold with
git previously).
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* dg/local-mod-error-messages:
t7609-merge-co-error-msgs: test non-fast forward case too.
Move "show_all_errors = 1" to setup_unpack_trees_porcelain()
setup_unpack_trees_porcelain: take the whole options struct as parameter
Move set_porcelain_error_msgs to unpack-trees.c and rename it
Conflicts:
merge-recursive.c
>Due to this this (and maybe all the tests) need to depend on the
>SYMLINKS prereq.
Here's a third attempt with no use of symlinks in the test:
Skip the entire rename/add conflict case if the file added on the
other branch has the same contents as the file being renamed. This
avoids giving the user an extra copy of the same file and presenting a
conflict that is confusing and pointless.
A simple test of this case has been added in
t/t3030-merge-recursive.sh.
Signed-off-by: Ken Schalk <ken.schalk@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* jn/merge-renormalize:
merge-recursive --renormalize
rerere: never renormalize
rerere: migrate to parse-options API
t4200 (rerere): modernize style
ll-merge: let caller decide whether to renormalize
ll-merge: make flag easier to populate
Documentation/technical: document ll_merge
merge-trees: let caller decide whether to renormalize
merge-trees: push choice to renormalize away from low level
t6038 (merge.renormalize): check that it can be turned off
t6038 (merge.renormalize): try checkout -m and cherry-pick
t6038 (merge.renormalize): style nitpicks
Don't expand CRLFs when normalizing text during merge
Try normalizing files to avoid delete/modify conflicts when merging
Avoid conflicts when merging branches with mixed normalization
Conflicts:
builtin/rerere.c
t/t4200-rerere.sh
This is a preparation patch to let setup_unpack_trees_porcelain set
show_all_errors itself.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The function is currently dealing only with error messages, but the
intent of calling it is really to notify the unpack-tree mechanics that
it is running in porcelain mode.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* en/d-f-conflict-fix:
merge-recursive: Avoid excessive output for and reprocessing of renames
merge-recursive: Fix multiple file rename across D/F conflict
t6031: Add a testcase covering multiple renames across a D/F conflict
merge-recursive: Fix typo
Mark tests that use symlinks as needing SYMLINKS prerequisite
t/t6035-merge-dir-to-symlink.sh: Remove TODO on passing test
fast-import: Improve robustness when D->F changes provided in wrong order
fast-export: Fix output order of D/F changes
merge_recursive: Fix renames across paths below D/F conflicts
merge-recursive: Fix D/F conflicts
Add a rename + D/F conflict testcase
Add additional testcases for D/F conflicts
Conflicts:
merge-recursive.c
Add support for merging with ignoring line endings (specifically
--ignore-space-at-eol) when using recursive merging. This is
as a strategy-option, so that you can do:
git merge --strategy-option=ignore-space-at-eol <branch>
and
git rebase --strategy-option=ignore-space-at-eol <branch>
This can be useful for coping with line-ending damage (Xcode 3.1 has a
nasty habit of converting all CRLFs to LFs, and VC6 tends to just use
CRLFs for inserted lines).
The only option I need is ignore-space-at-eol, but while at it,
include the other xdiff whitespace options (ignore-space-change,
ignore-all-space), too.
[jn: with documentation]
Signed-off-by: Justin Frankel <justin@cockos.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Teach the merge-recursive strategy a --patience option to use the
"patience diff" algorithm, which tends to improve results when
cherry-picking a patch that reorders functions at the same time as
refactoring them.
To support this, struct merge_options and ll_merge_options gain an
xdl_opts member, so programs can use arbitrary xdiff flags (think
"XDF_IGNORE_WHITESPACE") in a git-aware merge.
git merge and git rebase can be passed the -Xpatience option to
use this.
[jn: split from --ignore-space patch; with documentation]
Signed-off-by: Justin Frankel <justin@cockos.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Keeping track of the flag bits is proving more trouble than it's
worth. Instead, use a pointer to an options struct like most similar
APIs do.
Callers with no special requests can pass NULL to request the default
options.
Cc: Bert Wesarg <bert.wesarg@googlemail.com>
Cc: Avery Pennarun <apenwarr@gmail.com>
Helped-by: Justin Frankel <justin@cockos.com>
Helped-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
There are two very similar blocks of code that recognize options for
the "recursive" merge strategy. Unify them.
No functional change intended.
Cc: Avery Pennarun <apenwarr@gmail.com>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* hv/submodule-find-ff-merge:
Implement automatic fast-forward merge for submodules
setup_revisions(): Allow walking history in a submodule
Teach ref iteration module about submodules
Conflicts:
submodule.c
* dg/local-mod-error-messages:
t7609: test merge and checkout error messages
unpack_trees: group error messages by type
merge-recursive: distinguish "removed" and "overwritten" messages
merge-recursive: porcelain messages for checkout
Turn unpack_trees_options.msgs into an array + enum
Conflicts:
t/t3400-rebase.sh
In 5a2580d (merge_recursive: Fix renames across paths below D/F conflicts
2010-07-09) and ae74548 (merge-recursive: Fix multiple file rename across
D/F conflict 2010-08-17), renames across D/F conflicts were fixed by
making process_renames() consider as unprocessed renames whose dst_entry
"still" had higher stage entries. The assumption was that those higher
stage entries would have been cleared out of dst_entry by that point in
cases where the conflict could be resolved (normal renames with no D/F
conflicts). That is not the case -- higher stage entries will remain in
all cases.
Fix this by checking for higher stage entries corresponding to D/F
conflicts, namely that stages 2 and 3 have exactly one nonzero mode between
them. The nonzero mode stage corresponds to a file at the path, while the
stage with a zero mode will correspond to a directory at that path (since
rename/delete conflicts will have already been handled before this codepath
is reached.)
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* cc/find-commit-subject:
blame: use find_commit_subject() instead of custom code
merge-recursive: use find_commit_subject() instead of custom code
bisect: use find_commit_subject() instead of custom code
revert: rename variables related to subject in get_message()
revert: refactor code to find commit subject in find_commit_subject()
revert: fix off by one read when searching the end of a commit subject
In 5a2580d (merge_recursive: Fix renames across paths below D/F conflicts
2010-07-09), detection was added for renames across paths involved in a
directory<->file conflict. However, the change accidentally involved
reusing an outer loop index ('i') in an inner loop, changing its values
and causing a slightly different type of breakage for cases where there are
multiple renames across the D/F conflict. Fix by creating a new temporary
variable 'i'.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>