git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Elijah Newren <newren@gmail.com>
To: gitster@pobox.com
Cc: git@vger.kernel.org, Jim Foucar <jgfouca@sandia.gov>,
	Elijah Newren <newren@gmail.com>
Subject: [PATCHv2 37/56] merge-recursive: When we detect we can skip an update, actually skip it
Date: Thu, 11 Aug 2011 23:20:10 -0600	[thread overview]
Message-ID: <1313126429-17368-38-git-send-email-newren@gmail.com> (raw)
In-Reply-To: <1313126429-17368-1-git-send-email-newren@gmail.com>

In 882fd11 (merge-recursive: Delay content merging for renames 2010-09-20),
there was code that checked for whether we could skip updating a file in
the working directory, based on whether the merged version matched the
current working copy.  Due to the desire to handle directory/file conflicts
that were resolvable, that commit deferred content merging by first
updating the index with the unmerged entries and then moving the actual
merging (along with the skip-the-content-update check) to another function
that ran later in the merge process.  As part moving the content merging
code, a bug was introduced such that although the message about skipping
the update would be printed (whenever GIT_MERGE_VERBOSITY was sufficiently
high), the file would be unconditionally updated in the working copy
anyway.

When we detect that the file does not need to be updated in the working
copy, update the index appropriately and then return early before updating
the working copy.

Note that there was a similar change in b2c8c0a (merge-recursive: When we
detect we can skip an update, actually skip it 2011-02-28), but it was
reverted by 6db4105 (Revert "Merge branch 'en/merge-recursive'"
2011-05-19) since it did not fix both of the relevant types of unnecessary
update breakages and, worse, it made use of some band-aids that caused
other problems.  The reason this change works is due to the changes earlier
in this series to (a) record_df_conflict_files instead of just unlinking
them early, (b) allowing make_room_for_path() to remove D/F entries,
(c) the splitting of update_stages_and_entry() to have its functionality
called at different points, and (d) making the pathnames of the files
involved in the merge available to merge_content().

Signed-off-by: Elijah Newren <newren@gmail.com>
---
Changes since v1:
  (1) Moved to later in the series (used to be patch #29).
  (2) Changed the "was_tracked" logic to use information about what
      paths were involved in renames to determine whether the file
      really 'was tracked' before the merge started.  Thus, the code
      is now about checking "!path_renamed_outside_HEAD" rather than
      "was_tracked(path)" (The latter was problematic because it tells
      us whether path was tracked once unpack_trees finishes() rather
      than whether the path was tracked before the merge started.)
  (3) Added another minor tweak to get the expected "Skipped" messages
      that t6022.12 expects.  We need to report that we are skipping
      the update even if the content is only on the other side of the
      merge and we need to update the working directory contents.  At
      least, that's what the author of t6022.12 who put the message in
      explicitly expected.

 merge-recursive.c       |   19 ++++++++++++++++---
 t/t6022-merge-rename.sh |    4 ++--
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index bc99f1a..ccf71d3 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1356,6 +1356,7 @@ static int merge_content(struct merge_options *o,
 {
 	const char *reason = "content";
 	char *side1 = NULL, *side2 = NULL;
+	const char *path1 = NULL, *path2 = NULL;
 	struct merge_file_info mfi;
 	struct diff_filespec one, a, b;
 	unsigned df_conflict_remains = 0;
@@ -1373,7 +1374,6 @@ static int merge_content(struct merge_options *o,
 	b.mode = b_mode;
 
 	if (rename_conflict_info) {
-		const char *path1, *path2;
 		struct diff_filepair *pair1 = rename_conflict_info->pair1;
 
 		path1 = (o->branch1 == rename_conflict_info->branch1) ?
@@ -1399,9 +1399,22 @@ static int merge_content(struct merge_options *o,
 	free(side2);
 
 	if (mfi.clean && !df_conflict_remains &&
-	    sha_eq(mfi.sha, a_sha) && mfi.mode == a.mode)
+	    sha_eq(mfi.sha, a_sha) && mfi.mode == a_mode) {
+		int path_renamed_outside_HEAD;
 		output(o, 3, "Skipped %s (merged same as existing)", path);
-	else
+		/*
+		 * The content merge resulted in the same file contents we
+		 * already had.  We can return early if those file contents
+		 * are recorded at the correct path (which may not be true
+		 * if the merge involves a rename).
+		 */
+		path_renamed_outside_HEAD = !path2 || !strcmp(path, path2);
+		if (!path_renamed_outside_HEAD) {
+			add_cacheinfo(mfi.mode, mfi.sha, path,
+				      0 /*stage*/, 1 /*refresh*/, 0 /*options*/);
+			return mfi.clean;
+		}
+	} else
 		output(o, 2, "Auto-merging %s", path);
 
 	if (!mfi.clean) {
diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh
index 4695cbc..d96d3c5 100755
--- a/t/t6022-merge-rename.sh
+++ b/t/t6022-merge-rename.sh
@@ -631,7 +631,7 @@ test_expect_success 'setup avoid unnecessary update, normal rename' '
 	git commit -m "Random, unrelated changes"
 '
 
-test_expect_failure 'avoid unnecessary update, normal rename' '
+test_expect_success 'avoid unnecessary update, normal rename' '
 	git checkout -q avoid-unnecessary-update-1^0 &&
 	test-chmtime =1000000000 rename &&
 	test-chmtime -v +0 rename >expect &&
@@ -664,7 +664,7 @@ test_expect_success 'setup to test avoiding unnecessary update, with D/F conflic
 	git commit -m "Only unrelated changes"
 '
 
-test_expect_failure 'avoid unnecessary update, with D/F conflict' '
+test_expect_success 'avoid unnecessary update, with D/F conflict' '
 	git checkout -q avoid-unnecessary-update-2^0 &&
 	test-chmtime =1000000000 df &&
 	test-chmtime -v +0 df >expect &&
-- 
1.7.6.100.gac5c1

  parent reply	other threads:[~2011-08-12  5:22 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-12  5:19 [PATCHv2 00/57] Re-roll of en/merge-recursive from pu Elijah Newren
2011-08-12  5:19 ` [PATCHv2 01/56] t6042: Add a testcase where git deletes an untracked file Elijah Newren
2011-08-12  5:19 ` [PATCHv2 02/56] t6042: Add failing testcase for rename/modify/add-source conflict Elijah Newren
2011-08-12  5:19 ` [PATCHv2 03/56] t6042: Add a pair of cases where undetected renames cause issues Elijah Newren
2011-08-12  5:19 ` [PATCHv2 04/56] t6042: Add a testcase where undetected rename causes silent file deletion Elijah Newren
2011-08-12  5:19 ` [PATCHv2 05/56] t6042: Add tests for content issues with modify/rename/directory conflicts Elijah Newren
2011-08-12  5:19 ` [PATCHv2 06/56] t6042: Ensure rename/rename conflicts leave index and workdir in sane state Elijah Newren
2011-08-12  5:19 ` [PATCHv2 07/56] t6042: Add failing testcases for rename/rename/add-{source,dest} conflicts Elijah Newren
2011-08-12  5:19 ` [PATCHv2 08/56] t6036: Add differently resolved modify/delete conflict in criss-cross test Elijah Newren
2011-08-12  5:19 ` [PATCHv2 09/56] t6036: criss-cross with weird content can fool git into clean merge Elijah Newren
2011-08-12  5:19 ` [PATCHv2 10/56] t6036: tests for criss-cross merges with various directory/file conflicts Elijah Newren
2011-08-12  5:19 ` [PATCHv2 11/56] t6036: criss-cross w/ rename/rename(1to2)/modify+rename/rename(2to1)/modify Elijah Newren
2011-08-12  5:19 ` [PATCHv2 12/56] t6036: criss-cross + rename/rename(1to2)/add-source + modify/modify Elijah Newren
2011-08-12  5:19 ` [PATCHv2 13/56] t6022: Remove unnecessary untracked files to make test cleaner Elijah Newren
2011-08-12  5:19 ` [PATCHv2 14/56] t6022: New tests checking for unnecessary updates of files Elijah Newren
2011-08-12  5:19 ` [PATCHv2 15/56] t6022: Add testcase for merging a renamed file with a simple change Elijah Newren
2011-08-12  5:19 ` [PATCHv2 16/56] merge-recursive: Make BUG message more legible by adding a newline Elijah Newren
2011-08-12  5:19 ` [PATCHv2 17/56] merge-recursive: Correct a comment Elijah Newren
2011-08-12  5:19 ` [PATCHv2 18/56] merge-recursive: Mark some diff_filespec struct arguments const Elijah Newren
2011-08-12  5:19 ` [PATCHv2 19/56] merge-recursive: Consolidate different update_stages functions Elijah Newren
2011-08-12  5:19 ` [PATCHv2 20/56] merge-recursive: Remember to free generated unique path names Elijah Newren
2011-08-12  5:19 ` [PATCHv2 21/56] merge-recursive: Avoid working directory changes during recursive case Elijah Newren
2011-08-12  5:19 ` [PATCHv2 22/56] merge-recursive: Fix recursive case with D/F conflict via add/add conflict Elijah Newren
2011-08-12  5:19 ` [PATCHv2 23/56] merge-recursive: Fix sorting order and directory change assumptions Elijah Newren
2011-08-12  5:19 ` [PATCHv2 24/56] merge-recursive: Fix code checking for D/F conflicts still being present Elijah Newren
2011-08-12  5:19 ` [PATCHv2 25/56] merge-recursive: Save D/F conflict filenames instead of unlinking them Elijah Newren
2011-08-12  5:19 ` [PATCHv2 26/56] merge-recursive: Split was_tracked() out of would_lose_untracked() Elijah Newren
2011-08-12  5:20 ` [PATCHv2 27/56] string-list: Add API to remove an item from an unsorted list Elijah Newren
2011-08-12  7:00   ` Johannes Sixt
2011-08-12  9:27     ` Alex Riesen
2011-08-12 22:14     ` Elijah Newren
2011-08-13  9:08       ` Johannes Sixt
2011-08-12  5:20 ` [PATCHv2 28/56] merge-recursive: Allow make_room_for_path() to remove D/F entries Elijah Newren
2011-08-12  5:20 ` [PATCHv2 29/56] merge-recursive: Split update_stages_and_entry; only update stages at end Elijah Newren
2011-08-12  5:20 ` [PATCHv2 30/56] merge-recursive: Fix deletion of untracked file in rename/delete conflicts Elijah Newren
2011-08-12  5:20 ` [PATCHv2 31/56] merge-recursive: Make dead code for rename/rename(2to1) conflicts undead Elijah Newren
2011-08-12  5:20 ` [PATCHv2 32/56] merge-recursive: Add comments about handling rename/add-source cases Elijah Newren
2011-08-12  5:20 ` [PATCHv2 33/56] merge-recursive: Improve handling of rename target vs. directory addition Elijah Newren
2011-08-12  5:20 ` [PATCHv2 34/56] merge-recursive: Consolidate process_entry() and process_df_entry() Elijah Newren
2011-08-12  5:20 ` [PATCHv2 35/56] merge-recursive: Cleanup and consolidation of rename_conflict_info Elijah Newren
2011-08-12  5:20 ` [PATCHv2 36/56] merge-recursive: Provide more info in conflict markers with file renames Elijah Newren
2011-08-12  5:20 ` Elijah Newren [this message]
2011-08-12  5:20 ` [PATCHv2 38/56] merge-recursive: Fix modify/delete resolution in the recursive case Elijah Newren
2011-08-12  5:20 ` [PATCHv2 39/56] merge-recursive: Introduce a merge_file convenience function Elijah Newren
2011-08-12  5:20 ` [PATCHv2 40/56] merge-recursive: Fix rename/rename(1to2) resolution for virtual merge base Elijah Newren
2011-08-12  5:20 ` [PATCHv2 41/56] merge-recursive: Small cleanups for conflict_rename_rename_1to2 Elijah Newren
2011-08-12  5:20 ` [PATCHv2 42/56] merge-recursive: Defer rename/rename(2to1) handling until process_entry Elijah Newren
2011-08-12  5:20 ` [PATCHv2 43/56] merge-recursive: Record more data needed for merging with dual renames Elijah Newren
2011-08-12  5:20 ` [PATCHv2 44/56] merge-recursive: Create function for merging with branchname:file markers Elijah Newren
2011-08-12  5:20 ` [PATCHv2 45/56] merge-recursive: Consider modifications in rename/rename(2to1) conflicts Elijah Newren
2011-08-12  5:20 ` [PATCHv2 46/56] merge-recursive: Make modify/delete handling code reusable Elijah Newren
2011-08-12  5:20 ` [PATCHv2 47/56] merge-recursive: Have conflict_rename_delete reuse modify/delete code Elijah Newren
2011-08-12  5:20 ` [PATCHv2 48/56] merge-recursive: add handling for rename/rename/add-dest/add-dest Elijah Newren
2011-08-12  5:20 ` [PATCHv2 49/56] merge-recursive: Fix working copy handling for rename/rename/add/add Elijah Newren
2011-08-12  5:20 ` [PATCHv2 50/56] t3030: fix accidental success in symlink rename Elijah Newren
2011-08-12  5:20 ` [PATCHv2 51/56] t6022: Add testcase for spurious "refusing to lose untracked" messages Elijah Newren
2011-08-12  5:20 ` [PATCHv2 52/56] merge-recursive: Fix spurious 'refusing to lose untracked file...' messages Elijah Newren
2011-08-12  5:20 ` [PATCHv2 53/56] t6022: Additional tests checking for unnecessary updates of files Elijah Newren
2011-08-12  5:20 ` [PATCHv2 54/56] merge-recursive: Avoid unnecessary file rewrites Elijah Newren
2011-08-12  5:20 ` [PATCHv2 55/56] t6036: criss-cross + rename/rename(1to2)/add-dest + simple modify Elijah Newren
2011-08-12  5:20 ` [PATCHv2 56/56] merge-recursive: Fix virtual merge base for rename/rename(1to2)/add-dest Elijah Newren
2011-08-12  5:48 ` [PATCHv2 00/57] Re-roll of en/merge-recursive from pu Junio C Hamano
2011-08-12 21:59   ` Elijah Newren
2011-08-13  2:37     ` Elijah Newren
2011-08-13  2:23 ` [PATCHv2 57/57] merge-recursive: Don't re-sort a list whose order we depend upon Elijah Newren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1313126429-17368-38-git-send-email-newren@gmail.com \
    --to=newren@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jgfouca@sandia.gov \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).