All of lore.kernel.org
 help / color / mirror / Atom feed
From: Petr Baudis <pasky@suse.cz>
To: git@vger.kernel.org
Subject: [PATCH 5/7] git mv: Support moving submodules
Date: Wed, 16 Jul 2008 21:11:29 +0200	[thread overview]
Message-ID: <20080716191129.19772.41903.stgit@localhost> (raw)
In-Reply-To: <20080716190753.19772.93357.stgit@localhost>

This patch adds support for moving submodules to 'git mv', including
rewriting of the .gitmodules file to reflect the movement.

The usage of struct path_list here is a bit abusive, but keeps the
code simple and hopefully still reasonably readable. The horrid
index_path_src_sha1 hack is unfortunately much worse, however the author
is currently unaware of any more reasonable solution of the problem.

Signed-off-by: Petr Baudis <pasky@suse.cz>
---

 builtin-mv.c |   55 +++++++++++++++++++++++++++++++++++++++++++++++++------
 cache.h      |    2 ++
 sha1_file.c  |   10 ++++++++++
 3 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/builtin-mv.c b/builtin-mv.c
index 158a83d..30c4e7d 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -9,6 +9,7 @@
 #include "cache-tree.h"
 #include "path-list.h"
 #include "parse-options.h"
+#include "submodule.h"
 
 static const char * const builtin_mv_usage[] = {
 	"git-mv [options] <source>... <destination>",
@@ -60,6 +61,24 @@ static const char *add_slash(const char *path)
 	return path;
 }
 
+static int ce_is_gitlink(int i)
+{
+	return i < 0 ? 0 : S_ISGITLINK(active_cache[i]->ce_mode);
+}
+
+static void rename_submodule(struct path_list_item *i)
+{
+	char *key = submodule_by_path(i->path);
+
+	config_exclusive_filename = ".gitmodules";
+	if (git_config_set(key, (const char *) i->util))
+		die("cannot update .gitmodules");
+	config_exclusive_filename = NULL;
+
+	free(key);
+}
+
+
 static struct lock_file lock_file;
 
 int cmd_mv(int argc, const char **argv, const char *prefix)
@@ -77,9 +96,12 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 	struct stat st;
 	struct path_list overwritten = {NULL, 0, 0, 0};
 	struct path_list src_for_dst = {NULL, 0, 0, 0};
+	/* .util contains sha1 for submodules */
 	struct path_list added = {NULL, 0, 0, 0};
 	struct path_list deleted = {NULL, 0, 0, 0};
 	struct path_list changed = {NULL, 0, 0, 0};
+	/* .path is source path, .util is destination path */
+	struct path_list submodules = {NULL, 0, 0, 0};
 
 	git_config(git_default_config, NULL);
 
@@ -99,7 +121,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 		/* special case: "." was normalized to "" */
 		destination = copy_pathspec(dest_path[0], argv, argc, 1);
 	else if (!lstat(dest_path[0], &st) &&
-			S_ISDIR(st.st_mode)) {
+			S_ISDIR(st.st_mode) &&
+			!ce_is_gitlink(cache_name_pos(dest_path[0], strlen(dest_path[0])))) {
 		dest_path[0] = add_slash(dest_path[0]);
 		destination = copy_pathspec(dest_path[0], argv, argc, 1);
 	} else {
@@ -111,7 +134,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 	/* Checking */
 	for (i = 0; i < argc; i++) {
 		const char *src = source[i], *dst = destination[i];
-		int length, src_is_dir;
+		int length, src_is_dir, src_cache_pos;
 		const char *bad = NULL;
 
 		if (show_only)
@@ -126,7 +149,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 		} else if ((src_is_dir = S_ISDIR(st.st_mode))
 				&& lstat(dst, &st) == 0)
 			bad = "cannot move directory over file";
-		else if (src_is_dir) {
+		else if ((src_cache_pos = cache_name_pos(src, length)) < 0 && src_is_dir) {
 			const char *src_w_slash = add_slash(src);
 			int len_w_slash = length + 1;
 			int first, last;
@@ -193,7 +216,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 				} else
 					bad = "Cannot overwrite";
 			}
-		} else if (cache_name_pos(src, length) < 0)
+		} else if (src_cache_pos < 0)
 			bad = "not under version control";
 		else if (path_list_has_path(&src_for_dst, dst))
 			bad = "multiple sources for the same target";
@@ -218,6 +241,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 	for (i = 0; i < argc; i++) {
 		const char *src = source[i], *dst = destination[i];
 		enum update_mode mode = modes[i];
+		struct path_list_item *last = NULL;
+		int j;
 		if (show_only || verbose)
 			printf("Renaming %s to %s\n", src, dst);
 		if (!show_only && mode != INDEX &&
@@ -227,14 +252,24 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 		if (mode == WORKING_DIRECTORY)
 			continue;
 
-		assert(cache_name_pos(src, strlen(src)) >= 0);
+		j = cache_name_pos(src, strlen(src));
+		assert(j >= 0);
 
 		path_list_insert(src, &deleted);
 		/* destination can be a directory with 1 file inside */
 		if (path_list_has_path(&overwritten, dst))
 			path_list_insert(dst, &changed);
 		else
-			path_list_insert(dst, &added);
+			last = path_list_insert(dst, &added);
+		if (ce_is_gitlink(j)) {
+			path_list_insert(src, &submodules)->util = (void *) dst;
+			/* We will note the original HEAD sha1; the submodule
+			 * may not be checked out, in which case we would have
+			 * no way to re-obtain it later when adding the new
+			 * entry. */
+			assert(last);
+			last->util = active_cache[j]->sha1;
+		}
 	}
 
 	if (show_only) {
@@ -254,13 +289,21 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 
 		for (i = 0; i < added.nr; i++) {
 			const char *path = added.items[i].path;
+			index_path_src_sha1 = added.items[i].util;
 			if (add_file_to_cache(path, verbose ? ADD_CACHE_VERBOSE : 0))
 				die("updating index entries failed");
+			index_path_src_sha1 = NULL;
 		}
 
 		for (i = 0; i < deleted.nr; i++)
 			remove_file_from_cache(deleted.items[i].path);
 
+		for (i = 0; i < submodules.nr; i++)
+			rename_submodule(&submodules.items[i]);
+
+		if (submodules.nr > 0 && add_file_to_cache(".gitmodules", 0))
+			die("cannot add new .gitmodules to the index");
+
 		if (active_cache_changed) {
 			if (write_cache(newfd, active_cache, active_nr) ||
 			    commit_locked_index(&lock_file))
diff --git a/cache.h b/cache.h
index a779d92..998b5fb 100644
--- a/cache.h
+++ b/cache.h
@@ -387,6 +387,8 @@ extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
 extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
 extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
 
+extern unsigned char *index_path_src_sha1;
+
 extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
 extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
diff --git a/sha1_file.c b/sha1_file.c
index e281c14..4da6048 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2416,12 +2416,22 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
 	return ret;
 }
 
+unsigned char *index_path_src_sha1;
+
 int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object)
 {
 	int fd;
 	char *target;
 	size_t len;
 
+	if (index_path_src_sha1) {
+		/* SHA1 for this path was prepared by the caller specially;
+		 * e.g. comes from original cache entry in some cases of
+		 * a rename. */
+		memcpy(sha1, index_path_src_sha1, 20);
+		return 0;
+	}
+
 	switch (st->st_mode & S_IFMT) {
 	case S_IFREG:
 		fd = open(path, O_RDONLY);

  parent reply	other threads:[~2008-07-16 19:12 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-16 19:11 [RFC][PATCH 0/7] Submodule support in git mv, git rm Petr Baudis
2008-07-16 19:11 ` [PATCH 1/7] git-mv: Remove dead code branch Petr Baudis
2008-07-16 19:11 ` [PATCH 2/7] t7400: Add short "git submodule add" testsuite Petr Baudis
2008-07-16 19:11 ` [PATCH 3/7] git submodule add: Fix naming clash handling Petr Baudis
2008-07-16 19:11 ` [PATCH 4/7] submodule.*: Introduce simple C interface for submodule lookup by path Petr Baudis
2008-07-16 19:11 ` Petr Baudis [this message]
2008-07-17  2:37   ` [PATCH 5/7] git mv: Support moving submodules Junio C Hamano
2008-07-17 13:06     ` Petr Baudis
2008-07-17 22:31       ` [PATCH] git-mv: Keep moved index entries inact Petr Baudis
2008-07-17 22:34         ` [PATCH] git mv: Support moving submodules Petr Baudis
2008-07-19 23:54         ` [PATCH] git-mv: Keep moved index entries inact Junio C Hamano
2008-07-21  0:23           ` Petr Baudis
2008-07-21  0:25             ` [PATCHv2] " Petr Baudis
2008-07-21  4:36               ` Junio C Hamano
2008-07-26  6:46               ` Junio C Hamano
2008-07-27 13:41                 ` Petr Baudis
2008-07-27 13:47                   ` [PATCH] t/t7001-mv.sh: Propose ability to use git-mv on conflicting entries Petr Baudis
2008-07-28  1:13                     ` Junio C Hamano
2008-07-28  1:21                       ` Junio C Hamano
2008-07-28 14:20                 ` [PATCHv2] git-mv: Keep moved index entries inact SZEDER Gábor
2008-07-28 15:06                   ` Johannes Schindelin
2008-07-28 15:14                     ` Johannes Schindelin
2008-07-28 18:24                       ` Johannes Schindelin
2008-07-28 19:19                     ` Junio C Hamano
2008-07-28 23:41                       ` Johannes Schindelin
2008-07-28 23:55                         ` Johannes Schindelin
2008-07-29  0:17                       ` Petr Baudis
2008-07-29  0:46                         ` Junio C Hamano
2008-07-29  5:23                           ` Junio C Hamano
2008-08-04  7:49                 ` Not going beyond symbolic links Junio C Hamano
2008-08-04  7:51                   ` [PATCH 1/2] update-index: refuse to add working tree items beyond symlinks Junio C Hamano
2008-08-04  7:52                   ` [PATCH 2/2] add: " Junio C Hamano
2008-08-05  0:21                   ` Not going beyond symbolic links Linus Torvalds
2008-08-05  0:54                     ` Junio C Hamano
2008-08-05  1:43                       ` Linus Torvalds
2008-08-05  1:59                         ` Johannes Schindelin
2008-08-05  2:28                           ` Linus Torvalds
2008-08-05  6:11                             ` Junio C Hamano
2008-08-05 12:54                               ` Dmitry Potapov
2008-08-05 23:57                                 ` Junio C Hamano
2008-08-05 17:15                               ` Linus Torvalds
2008-08-05  4:44                           ` Junio C Hamano
2008-08-05 11:23                             ` Johannes Schindelin
2008-08-05  3:01                         ` Junio C Hamano
2008-08-05  3:04                           ` david
2008-08-07  6:52                     ` Junio C Hamano
2008-08-08  1:45                       ` [PATCH] powerpc: Do not ignore arch/powerpc/include Junio C Hamano
2008-08-08  3:13                         ` Stephen Rothwell
2008-08-08 20:55                       ` Not going beyond symbolic links Junio C Hamano
2008-08-08 23:45                         ` Linus Torvalds
2008-07-21  1:20             ` [PATCH] git-mv: Keep moved index entries inact Johannes Schindelin
2008-07-21  7:18               ` Petr Baudis
2008-07-21  7:38                 ` Junio C Hamano
2008-07-16 19:11 ` [PATCH 6/7] git rm: Support for removing submodules Petr Baudis
2008-07-16 22:41   ` Johannes Schindelin
2008-07-17 12:35     ` Petr Baudis
2008-07-17 12:59       ` Johannes Schindelin
2008-07-16 19:11 ` [PATCH 7/7] t7403: Submodule git mv, git rm testsuite Petr Baudis

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=20080716191129.19772.41903.stgit@localhost \
    --to=pasky@suse.cz \
    --cc=git@vger.kernel.org \
    /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.