From: Jens Lehmann <Jens.Lehmann@web.de>
To: Git Mailing List <git@vger.kernel.org>
Cc: Junio C Hamano <gitster@pobox.com>,
Phil Hord <phil.hord@gmail.com>, Heiko Voigt <hvoigt@hvoigt.net>,
"W. Trevor King" <wking@tremily.us>,
Peter Collingbourne <peter@pcc.me.uk>
Subject: [PATCH/RFC 2/3] Teach mv to move submodules using a gitfile
Date: Wed, 03 Apr 2013 21:56:55 +0200 [thread overview]
Message-ID: <515C8987.2060804@web.de> (raw)
In-Reply-To: <515C88FE.9020203@web.de>
When moving a submodule which uses a gitfile to point to the git directory
stored in .git/modules/<name> of the superproject two changes must be made
to make the submodule work: the .git file and the core.worktree setting
must be adjusted to point from work tree to git directory and back.
Achieve that by remembering which submodule uses a gitfile by storing the
result of read_gitfile() of each submodule. If that is not NULL the new
function connect_work_tree_and_git_dir() is called after renaming the
submodule's work tree which updates the two settings to the new values.
Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
---
builtin/mv.c | 19 ++++++++++++++----
submodule.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
submodule.h | 1 +
t/t7001-mv.sh | 19 ++++++++++++++++++
4 files changed, 99 insertions(+), 4 deletions(-)
diff --git a/builtin/mv.c b/builtin/mv.c
index 361028d..609bbb8 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -9,6 +9,7 @@
#include "cache-tree.h"
#include "string-list.h"
#include "parse-options.h"
+#include "submodule.h"
static const char * const builtin_mv_usage[] = {
N_("git mv [options] <source>... <destination>"),
@@ -65,7 +66,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
OPT_BOOLEAN('k', NULL, &ignore_errors, N_("skip move/rename errors")),
OPT_END(),
};
- const char **source, **destination, **dest_path;
+ const char **source, **destination, **dest_path, **submodule_gitfile;
enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes;
struct stat st;
struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
@@ -84,6 +85,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
source = copy_pathspec(prefix, argv, argc, 0);
modes = xcalloc(argc, sizeof(enum update_mode));
dest_path = copy_pathspec(prefix, argv + argc, 1, 0);
+ submodule_gitfile = xcalloc(argc, sizeof(char *));
if (dest_path[0][0] == '\0')
/* special case: "." was normalized to "" */
@@ -119,8 +121,14 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
else if (src_is_dir) {
int first = cache_name_pos(src, length);
if (first >= 0) {
+ struct strbuf submodule_dotgit = STRBUF_INIT;
if (!S_ISGITLINK(active_cache[first]->ce_mode))
die (_("Huh? Directory %s is in index and no submodule?"), src);
+ strbuf_addf(&submodule_dotgit, "%s/.git", src);
+ submodule_gitfile[i] = read_gitfile(submodule_dotgit.buf);
+ if (submodule_gitfile[i])
+ submodule_gitfile[i] = xstrdup(submodule_gitfile[i]);
+ strbuf_release(&submodule_dotgit);
} else {
const char *src_w_slash = add_slash(src);
int last, len_w_slash = length + 1;
@@ -215,9 +223,12 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
int pos;
if (show_only || verbose)
printf(_("Renaming %s to %s\n"), src, dst);
- if (!show_only && mode != INDEX &&
- rename(src, dst) < 0 && !ignore_errors)
- die_errno (_("renaming '%s' failed"), src);
+ if (!show_only && mode != INDEX) {
+ if (rename(src, dst) < 0 && !ignore_errors)
+ die_errno (_("renaming '%s' failed"), src);
+ if (submodule_gitfile[i])
+ connect_work_tree_and_git_dir(dst, submodule_gitfile[i]);
+ }
if (mode == WORKING_DIRECTORY)
continue;
diff --git a/submodule.c b/submodule.c
index 975bc87..eba9b42 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1001,3 +1001,67 @@ int merge_submodule(unsigned char result[20], const char *path,
free(merges.objects);
return 0;
}
+
+/* Update gitfile and core.worktree setting to connect work tree and git dir */
+void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir)
+{
+ struct strbuf core_worktree_setting = STRBUF_INIT;
+ struct strbuf configfile_name = STRBUF_INIT;
+ struct strbuf gitfile_content = STRBUF_INIT;
+ struct strbuf gitfile_name = STRBUF_INIT;
+ const char *real_work_tree = real_path(work_tree);
+ const char *pathspec[] = { real_work_tree, git_dir, NULL };
+ const char *max_prefix = common_prefix(pathspec);
+ FILE *fp;
+
+ if (max_prefix) { /* skip common prefix */
+ size_t max_prefix_len = strlen(max_prefix);
+ real_work_tree += max_prefix_len;
+ git_dir += max_prefix_len;
+ }
+
+ /*
+ * Update gitfile
+ */
+ strbuf_addstr(&gitfile_content, "gitdir: ");
+ if (real_work_tree[0]) {
+ const char *s = real_work_tree;
+ do {
+ strbuf_addstr(&gitfile_content, "../");
+ s++;
+ } while ((s = strchr(s, '/')));
+ }
+ strbuf_addstr(&gitfile_content, git_dir);
+ strbuf_addch(&gitfile_content, '\n');
+
+ strbuf_addf(&gitfile_name, "%s/.git", work_tree);
+ fp = fopen(gitfile_name.buf, "w");
+ if (!fp)
+ die(_("Could not create git link %s"), gitfile_name.buf);
+ fprintf(fp, gitfile_content.buf);
+ fclose(fp);
+
+ strbuf_release(&gitfile_content);
+ strbuf_release(&gitfile_name);
+
+ /*
+ * Update core.worktree setting
+ */
+ if (git_dir[0]) {
+ const char *s = git_dir;
+ do {
+ strbuf_addstr(&core_worktree_setting, "../");
+ s++;
+ } while ((s = strchr(s, '/')));
+ }
+ strbuf_addstr(&core_worktree_setting, real_work_tree);
+
+ strbuf_addf(&configfile_name, "%s/config", git_dir);
+ if (git_config_set_in_file(configfile_name.buf, "core.worktree",
+ core_worktree_setting.buf))
+ die(_("Could not set core.worktree in %s"),
+ configfile_name.buf);
+
+ strbuf_release(&core_worktree_setting);
+ strbuf_release(&configfile_name);
+}
diff --git a/submodule.h b/submodule.h
index 3dc1b3f..0c27c53 100644
--- a/submodule.h
+++ b/submodule.h
@@ -35,5 +35,6 @@ int merge_submodule(unsigned char result[20], const char *path, const unsigned c
int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name,
struct string_list *needs_pushing);
int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
+void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
#endif
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 4c57f61..d824464 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -289,4 +289,23 @@ test_expect_success 'git mv moves a submodule with a .git directory and no .gitm
git diff-files --quiet
'
+test_expect_success 'git mv moves a submodule with gitfile' '
+ rm -rf mod/sub &&
+ git reset --hard &&
+ git submodule update &&
+ entry="$(git ls-files --stage sub | cut -f 1)" &&
+ (
+ cd mod &&
+ git mv ../sub/ .
+ ) &&
+ ! test -e sub &&
+ [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
+ (
+ cd mod/sub &&
+ git status
+ ) &&
+ git update-index --refresh &&
+ git diff-files --quiet
+'
+
test_done
--
1.8.2.377.g1bdb7d0
next prev parent reply other threads:[~2013-04-03 19:57 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-03 19:54 [PATCH/RFC 0/3] Teach mv to move submodules Jens Lehmann
2013-04-03 19:56 ` [PATCH/RFC 1/3] Teach mv to move submodules together with their work trees Jens Lehmann
2013-04-11 9:12 ` Ramkumar Ramachandra
2013-04-11 16:27 ` Junio C Hamano
2013-04-11 16:46 ` Junio C Hamano
2013-04-03 19:56 ` Jens Lehmann [this message]
2013-04-09 23:08 ` [PATCH/RFC 2/3] Teach mv to move submodules using a gitfile Junio C Hamano
2013-04-10 16:59 ` Jens Lehmann
2013-04-10 21:06 ` [PATCH v2 " Jens Lehmann
2013-04-11 8:37 ` Ramkumar Ramachandra
2013-04-11 18:43 ` Junio C Hamano
2013-04-03 19:57 ` [PATCH/RFC 3/3] Teach mv to update the path entry in .gitmodules for moved submodules Jens Lehmann
2013-04-11 10:06 ` Ramkumar Ramachandra
2013-04-11 16:59 ` Junio C Hamano
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
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=515C8987.2060804@web.de \
--to=jens.lehmann@web.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=hvoigt@hvoigt.net \
--cc=peter@pcc.me.uk \
--cc=phil.hord@gmail.com \
--cc=wking@tremily.us \
/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.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
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 read-only IMAP folder(s) and NNTP newsgroup(s).