All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefan Beller <sbeller@google.com>
To: sbeller@google.com, gitster@pobox.com
Cc: git@vger.kernel.org, bmwill@google.com, novalis@novalis.org,
	sandals@crustytoothpaste.net, hvoigt@hvoigt.net,
	jrnieder@gmail.com, ramsay@ramsayjones.plus.com
Subject: [PATCH 16/19] unpack-trees: check if we can perform the operation for submodules
Date: Tue, 14 Mar 2017 14:46:39 -0700	[thread overview]
Message-ID: <20170314214642.7701-17-sbeller@google.com> (raw)
In-Reply-To: <20170314214642.7701-1-sbeller@google.com>

In a later patch we'll support submodule entries to be
in sync with the tree in working tree changing commands,
such as checkout or read-tree.

When a new submodule entry changes in the tree, we need to
check if there are conflicts (directory/file conflicts)
for the tree. Add this check for submodules to be
performed before the working tree is touched.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 unpack-trees.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 unpack-trees.h |   1 +
 2 files changed, 123 insertions(+), 9 deletions(-)

diff --git a/unpack-trees.c b/unpack-trees.c
index 616a0ae4b2..8333da2cc9 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -10,6 +10,8 @@
 #include "attr.h"
 #include "split-index.h"
 #include "dir.h"
+#include "submodule.h"
+#include "submodule-config.h"
 
 /*
  * Error messages expected by scripts out of plumbing commands such as
@@ -45,6 +47,9 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = {
 
 	/* ERROR_WOULD_LOSE_ORPHANED_REMOVED */
 	"Working tree file '%s' would be removed by sparse checkout update.",
+
+	/* ERROR_WOULD_LOSE_SUBMODULE */
+	"Submodule '%s' cannot checkout new HEAD.",
 };
 
 #define ERRORMSG(o,type) \
@@ -161,6 +166,8 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
 		_("The following working tree files would be overwritten by sparse checkout update:\n%s");
 	msgs[ERROR_WOULD_LOSE_ORPHANED_REMOVED] =
 		_("The following working tree files would be removed by sparse checkout update:\n%s");
+	msgs[ERROR_WOULD_LOSE_SUBMODULE] =
+		_("Submodule '%s' cannot checkout new HEAD");
 
 	opts->show_all_errors = 1;
 	/* rejected paths may not have a static buffer */
@@ -240,12 +247,75 @@ static void display_error_msgs(struct unpack_trees_options *o)
 		fprintf(stderr, _("Aborting\n"));
 }
 
+static int check_submodule_move_head(const struct cache_entry *ce,
+				     const char *old_id,
+				     const char *new_id,
+				     struct unpack_trees_options *o)
+{
+	const struct submodule *sub = submodule_from_ce(ce);
+	if (!sub)
+		return 0;
+
+	switch (sub->update_strategy.type) {
+	case SM_UPDATE_UNSPECIFIED:
+	case SM_UPDATE_CHECKOUT:
+		if (submodule_move_head(ce->name, old_id, new_id, SUBMODULE_MOVE_HEAD_DRY_RUN))
+			return o->gently ? -1 :
+				add_rejected_path(o, ERROR_WOULD_LOSE_SUBMODULE, ce->name);
+		return 0;
+	case SM_UPDATE_NONE:
+		return 0;
+	case SM_UPDATE_REBASE:
+	case SM_UPDATE_MERGE:
+	case SM_UPDATE_COMMAND:
+	default:
+		warning(_("submodule update strategy not supported for submodule '%s'"), ce->name);
+		return -1;
+	}
+}
+
+static void reload_gitmodules_file(struct index_state *index,
+				   struct checkout *state)
+{
+	int i;
+	for (i = 0; i < index->cache_nr; i++) {
+		struct cache_entry *ce = index->cache[i];
+		if (ce->ce_flags & CE_UPDATE) {
+			int r = strcmp(ce->name, ".gitmodules");
+			if (r < 0)
+				continue;
+			else if (r == 0) {
+				submodule_free();
+				checkout_entry(ce, state, NULL);
+				gitmodules_config();
+				git_config(submodule_config, NULL);
+			} else
+				break;
+		}
+	}
+}
+
 /*
  * Unlink the last component and schedule the leading directories for
  * removal, such that empty directories get removed.
  */
 static void unlink_entry(const struct cache_entry *ce)
 {
+	const struct submodule *sub = submodule_from_ce(ce);
+	if (sub) {
+		switch (sub->update_strategy.type) {
+		case SM_UPDATE_UNSPECIFIED:
+		case SM_UPDATE_CHECKOUT:
+		case SM_UPDATE_REBASE:
+		case SM_UPDATE_MERGE:
+			submodule_move_head(ce->name, "HEAD", NULL,
+					    SUBMODULE_MOVE_HEAD_FORCE);
+			break;
+		case SM_UPDATE_NONE:
+		case SM_UPDATE_COMMAND:
+			return; /* Do not touch the submodule. */
+		}
+	}
 	if (!check_leading_path(ce->name, ce_namelen(ce)))
 		return;
 	if (remove_or_warn(ce->ce_mode, ce->name))
@@ -301,6 +371,9 @@ static int check_updates(struct unpack_trees_options *o)
 	remove_marked_cache_entries(index);
 	remove_scheduled_dirs();
 
+	if (should_update_submodules() && o->update && !o->dry_run)
+		reload_gitmodules_file(index, &state);
+
 	for (i = 0; i < index->cache_nr; i++) {
 		struct cache_entry *ce = index->cache[i];
 
@@ -1358,17 +1431,26 @@ static int verify_uptodate_1(const struct cache_entry *ce,
 	if (!lstat(ce->name, &st)) {
 		int flags = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE;
 		unsigned changed = ie_match_stat(o->src_index, ce, &st, flags);
+
+		if (submodule_from_ce(ce)) {
+			int r = check_submodule_move_head(ce,
+				"HEAD", oid_to_hex(&ce->oid), o);
+			if (r)
+				return o->gently ? -1 :
+					add_rejected_path(o, error_type, ce->name);
+			return 0;
+		}
+
 		if (!changed)
 			return 0;
 		/*
-		 * NEEDSWORK: the current default policy is to allow
-		 * submodule to be out of sync wrt the superproject
-		 * index.  This needs to be tightened later for
-		 * submodules that are marked to be automatically
-		 * checked out.
+		 * Historic default policy was to allow submodule to be out
+		 * of sync wrt the superproject index. If the submodule was
+		 * not considered interesting above, we don't care here.
 		 */
 		if (S_ISGITLINK(ce->ce_mode))
 			return 0;
+
 		errno = 0;
 	}
 	if (errno == ENOENT)
@@ -1412,7 +1494,11 @@ static int verify_clean_submodule(const char *old_sha1,
 				  enum unpack_trees_error_types error_type,
 				  struct unpack_trees_options *o)
 {
-	return 0;
+	if (!submodule_from_ce(ce))
+		return 0;
+
+	return check_submodule_move_head(ce, old_sha1,
+					 oid_to_hex(&ce->oid), o);
 }
 
 static int verify_clean_subdirectory(const struct cache_entry *ce,
@@ -1578,9 +1664,15 @@ static int verify_absent_1(const struct cache_entry *ce,
 		path = xmemdupz(ce->name, len);
 		if (lstat(path, &st))
 			ret = error_errno("cannot stat '%s'", path);
-		else
-			ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL,
-						 &st, error_type, o);
+		else {
+			if (submodule_from_ce(ce))
+				ret = check_submodule_move_head(ce,
+								oid_to_hex(&ce->oid),
+								NULL, o);
+			else
+				ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL,
+							 &st, error_type, o);
+		}
 		free(path);
 		return ret;
 	} else if (lstat(ce->name, &st)) {
@@ -1588,6 +1680,10 @@ static int verify_absent_1(const struct cache_entry *ce,
 			return error_errno("cannot stat '%s'", ce->name);
 		return 0;
 	} else {
+		if (submodule_from_ce(ce))
+			return check_submodule_move_head(ce, oid_to_hex(&ce->oid),
+							 NULL, o);
+
 		return check_ok_to_remove(ce->name, ce_namelen(ce),
 					  ce_to_dtype(ce), ce, &st,
 					  error_type, o);
@@ -1643,6 +1739,15 @@ static int merged_entry(const struct cache_entry *ce,
 			return -1;
 		}
 		invalidate_ce_path(merge, o);
+
+		if (submodule_from_ce(ce)) {
+			int ret = check_submodule_move_head(ce, NULL,
+							    oid_to_hex(&ce->oid),
+							    o);
+			if (ret)
+				return ret;
+		}
+
 	} else if (!(old->ce_flags & CE_CONFLICTED)) {
 		/*
 		 * See if we can re-use the old CE directly?
@@ -1663,6 +1768,14 @@ static int merged_entry(const struct cache_entry *ce,
 			update |= old->ce_flags & (CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);
 			invalidate_ce_path(old, o);
 		}
+
+		if (submodule_from_ce(ce)) {
+			int ret = check_submodule_move_head(ce, oid_to_hex(&old->oid),
+							    oid_to_hex(&ce->oid),
+							    o);
+			if (ret)
+				return ret;
+		}
 	} else {
 		/*
 		 * Previously unmerged entry left as an existence
diff --git a/unpack-trees.h b/unpack-trees.h
index 36a73a6d00..6c48117b84 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -21,6 +21,7 @@ enum unpack_trees_error_types {
 	ERROR_SPARSE_NOT_UPTODATE_FILE,
 	ERROR_WOULD_LOSE_ORPHANED_OVERWRITTEN,
 	ERROR_WOULD_LOSE_ORPHANED_REMOVED,
+	ERROR_WOULD_LOSE_SUBMODULE,
 	NB_UNPACK_TREES_ERROR_TYPES
 };
 
-- 
2.12.0.rc1.49.g0cfd38c5f6.dirty


  parent reply	other threads:[~2017-03-14 21:47 UTC|newest]

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20170223225735.10994-1-sbeller@google.com/>
2017-03-02  0:47 ` [RFCv6 PATCH 00/18] Checkout aware of Submodules! Stefan Beller
2017-03-02  0:47   ` [PATCH 01/18] lib-submodule-update.sh: reorder create_lib_submodule_repo Stefan Beller
2017-03-02  0:47   ` [PATCH 02/18] lib-submodule-update.sh: do not use ./. as submodule remote Stefan Beller
2017-03-02  0:47   ` [PATCH 03/18] lib-submodule-update: teach test_submodule_content the -C <dir> flag Stefan Beller
2017-03-02  2:11     ` Eric Wong
2017-03-06 20:30       ` Stefan Beller
2017-03-06 20:35         ` Stefan Beller
2017-03-02  0:47   ` [PATCH 04/18] lib-submodule-update.sh: replace sha1 by hash Stefan Beller
2017-03-02  0:47   ` [PATCH 05/18] lib-submodule-update.sh: define tests for recursing into submodules Stefan Beller
2017-03-02  0:47   ` [PATCH 06/18] make is_submodule_populated gently Stefan Beller
2017-03-02  0:47   ` [PATCH 07/18] connect_work_tree_and_git_dir: safely create leading directories Stefan Beller
2017-03-02  0:47   ` [PATCH 08/18] update submodules: add submodule config parsing Stefan Beller
2017-03-02  0:47   ` [PATCH 09/18] update submodules: add a config option to determine if submodules are updated Stefan Beller
2017-03-02  0:47   ` [PATCH 10/18] submodules: introduce check to see whether to touch a submodule Stefan Beller
2017-03-02  0:47   ` [PATCH 11/18] update submodules: move up prepare_submodule_repo_env Stefan Beller
2017-03-02  0:47   ` [PATCH 12/18] update submodules: add submodule_move_head Stefan Beller
2017-03-02  0:47   ` [PATCH 13/18] unpack-trees: pass old oid to verify_clean_submodule Stefan Beller
2017-03-02  0:47   ` [PATCH 14/18] unpack-trees: check if we can perform the operation for submodules Stefan Beller
2017-03-02  0:47   ` [PATCH 15/18] read-cache, remove_marked_cache_entries: wipe selected submodules Stefan Beller
2017-03-02  0:47   ` [PATCH 16/18] entry.c: update submodules when interesting Stefan Beller
2017-03-02  0:47   ` [PATCH 17/18] builtin/checkout: add --recurse-submodules switch Stefan Beller
2017-03-02  0:47   ` [PATCH 18/18] builtin/read-tree: " Stefan Beller
2017-03-06 20:59   ` [RFCv7 PATCH 00/18] Checkout aware of Submodules! Stefan Beller
2017-03-06 20:59     ` [PATCH 01/18] lib-submodule-update.sh: reorder create_lib_submodule_repo Stefan Beller
2017-03-06 20:59     ` [PATCH 02/18] lib-submodule-update.sh: do not use ./. as submodule remote Stefan Beller
2017-03-06 20:59     ` [PATCH 03/18] lib-submodule-update: teach test_submodule_content the -C <dir> flag Stefan Beller
2017-03-06 22:21       ` Junio C Hamano
2017-03-06 20:59     ` [PATCH 04/18] lib-submodule-update.sh: replace sha1 by hash Stefan Beller
2017-03-06 20:59     ` [PATCH 05/18] lib-submodule-update.sh: define tests for recursing into submodules Stefan Beller
2017-03-07 22:26       ` Junio C Hamano
2017-03-06 20:59     ` [PATCH 06/18] make is_submodule_populated gently Stefan Beller
2017-03-06 20:59     ` [PATCH 07/18] connect_work_tree_and_git_dir: safely create leading directories Stefan Beller
2017-03-06 20:59     ` [PATCH 08/18] update submodules: add submodule config parsing Stefan Beller
2017-03-06 20:59     ` [PATCH 09/18] update submodules: add a config option to determine if submodules are updated Stefan Beller
2017-03-06 20:59     ` [PATCH 10/18] submodules: introduce check to see whether to touch a submodule Stefan Beller
2017-03-06 20:59     ` [PATCH 11/18] update submodules: move up prepare_submodule_repo_env Stefan Beller
2017-03-06 20:59     ` [PATCH 12/18] update submodules: add submodule_move_head Stefan Beller
2017-03-06 20:59     ` [PATCH 13/18] unpack-trees: pass old oid to verify_clean_submodule Stefan Beller
2017-03-06 20:59     ` [PATCH 14/18] unpack-trees: check if we can perform the operation for submodules Stefan Beller
2017-03-06 20:59     ` [PATCH 15/18] read-cache, remove_marked_cache_entries: wipe selected submodules Stefan Beller
2017-03-07 22:42       ` Junio C Hamano
2017-03-07 23:37         ` Stefan Beller
2017-03-08  1:14           ` Junio C Hamano
2017-03-08 22:39             ` Stefan Beller
2017-03-08 23:37               ` Junio C Hamano
2017-03-06 20:59     ` [PATCH 16/18] entry.c: update submodules when interesting Stefan Beller
2017-03-07 22:42       ` Junio C Hamano
2017-03-07 23:04         ` Junio C Hamano
2017-03-07 23:08           ` Stefan Beller
2017-03-08  1:08             ` Junio C Hamano
2017-03-06 20:59     ` [PATCH 17/18] builtin/checkout: add --recurse-submodules switch Stefan Beller
2017-03-06 20:59     ` [PATCH 18/18] builtin/read-tree: " Stefan Beller
2017-03-07 22:42       ` Junio C Hamano
2017-03-09 22:15     ` [RFCv8 PATCH 00/17] Checkout aware of Submodules! Stefan Beller
2017-03-09 22:15       ` [PATCH 01/17] lib-submodule-update.sh: reorder create_lib_submodule_repo Stefan Beller
2017-03-09 22:15       ` [PATCH 02/17] lib-submodule-update.sh: do not use ./. as submodule remote Stefan Beller
2017-03-09 22:15       ` [PATCH 03/17] lib-submodule-update: teach test_submodule_content the -C <dir> flag Stefan Beller
2017-03-09 22:15       ` [PATCH 04/17] lib-submodule-update.sh: replace sha1 by hash Stefan Beller
2017-03-09 22:15       ` [PATCH 05/17] lib-submodule-update.sh: define tests for recursing into submodules Stefan Beller
2017-03-09 22:15       ` [PATCH 06/17] make is_submodule_populated gently Stefan Beller
2017-03-09 22:15       ` [PATCH 07/17] connect_work_tree_and_git_dir: safely create leading directories Stefan Beller
2017-03-09 23:29         ` Brandon Williams
2017-03-12  7:06           ` Junio C Hamano
2017-03-09 22:15       ` [PATCH 08/17] update submodules: add submodule config parsing Stefan Beller
2017-03-09 22:15       ` [PATCH 09/17] update submodules: add a config option to determine if submodules are updated Stefan Beller
2017-03-09 22:15       ` [PATCH 10/17] submodules: introduce check to see whether to touch a submodule Stefan Beller
2017-03-09 22:15       ` [PATCH 11/17] update submodules: move up prepare_submodule_repo_env Stefan Beller
2017-03-09 22:15       ` [PATCH 12/17] update submodules: add submodule_move_head Stefan Beller
2017-03-09 23:37         ` Brandon Williams
2017-03-12  7:09           ` Junio C Hamano
2017-03-13 17:24             ` Brandon Williams
2017-03-13 20:50             ` Stefan Beller
2017-03-09 23:40         ` Brandon Williams
2017-03-09 23:43         ` Brandon Williams
2017-03-09 22:15       ` [PATCH 13/17] unpack-trees: pass old oid to verify_clean_submodule Stefan Beller
2017-03-09 22:15       ` [PATCH 14/17] unpack-trees: check if we can perform the operation for submodules Stefan Beller
2017-03-09 22:15       ` [PATCH 15/17] entry.c: create submodules when interesting Stefan Beller
2017-03-09 22:15       ` [PATCH 16/17] builtin/checkout: add --recurse-submodules switch Stefan Beller
2017-03-09 22:15       ` [PATCH 17/17] builtin/read-tree: " Stefan Beller
2017-03-14 21:46       ` [PATCHv9 00/19] Checkout aware of Submodules! Stefan Beller
2017-03-14 21:46         ` [PATCH 01/19] connect_work_tree_and_git_dir: safely create leading directories Stefan Beller
2017-03-14 21:46         ` [PATCH 02/19] submodule--helper.c: remove duplicate code Stefan Beller
2017-03-14 21:46         ` [PATCH 03/19] lib-submodule-update.sh: reorder create_lib_submodule_repo Stefan Beller
2017-03-14 21:46         ` [PATCH 04/19] lib-submodule-update.sh: do not use ./. as submodule remote Stefan Beller
2017-03-14 21:46         ` [PATCH 05/19] lib-submodule-update: teach test_submodule_content the -C <dir> flag Stefan Beller
2017-03-14 21:46         ` [PATCH 06/19] lib-submodule-update.sh: replace sha1 by hash Stefan Beller
2017-03-14 21:46         ` [PATCH 07/19] lib-submodule-update.sh: define tests for recursing into submodules Stefan Beller
2017-03-14 21:46         ` [PATCH 08/19] make is_submodule_populated gently Stefan Beller
2017-03-14 21:46         ` [PATCH 09/19] update submodules: add submodule config parsing Stefan Beller
2017-03-14 21:46         ` [PATCH 10/19] update submodules: add a config option to determine if submodules are updated Stefan Beller
2017-03-14 21:46         ` [PATCH 11/19] submodules: introduce check to see whether to touch a submodule Stefan Beller
2017-03-14 21:46         ` [PATCH 12/19] update submodules: move up prepare_submodule_repo_env Stefan Beller
2017-03-14 21:46         ` [PATCH 13/19] submodule.c: get_super_prefix_or_empty Stefan Beller
2017-03-14 21:46         ` [PATCH 14/19] update submodules: add submodule_move_head Stefan Beller
2017-03-14 21:46         ` [PATCH 15/19] unpack-trees: pass old oid to verify_clean_submodule Stefan Beller
2017-03-14 21:46         ` Stefan Beller [this message]
2017-03-14 21:46         ` [PATCH 17/19] entry.c: create submodules when interesting Stefan Beller
2017-03-14 21:46         ` [PATCH 18/19] builtin/checkout: add --recurse-submodules switch Stefan Beller
2017-03-14 21:46         ` [PATCH 19/19] builtin/read-tree: " Stefan Beller
2017-03-15  0:41         ` [PATCHv9 00/19] Checkout aware of Submodules! Brandon Williams

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=20170314214642.7701-17-sbeller@google.com \
    --to=sbeller@google.com \
    --cc=bmwill@google.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=hvoigt@hvoigt.net \
    --cc=jrnieder@gmail.com \
    --cc=novalis@novalis.org \
    --cc=ramsay@ramsayjones.plus.com \
    --cc=sandals@crustytoothpaste.net \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.