[PATCH/RFC] init, clone: support --real-git-dir for .git file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Instead of creating the repository at $GIT_DIR, --real-git-dir will
tell git to put the repository there, then make $GIT_DIR a .git file
that points to --real-git-dir.

Signed-off-by: Nguyán ThÃi Ngác Duy <pclouds@xxxxxxxxx>
---
 This makes '.git symbolic link' (what's its official name?) more
 convenient to use. Previously whenever I need to create a .git link,
 I need to open docs to see its format. Now all I need to do is

  git init --real-git-dir=/where/real/git/is
  git clone --real-git-dir=/where/real/git/is something

 I intend to make 'git init --real-git-dir' move current repo to
 somewhere else if called on existing repo.

 Long term I'd like to see a init/clone hook, where I can tell git
 "when I ask you to create a repo/worktree at foo, put the real repo
 at ~/git/foo"

 I could use a better option name too, any suggestions?

 builtin/clone.c   |    7 ++++++-
 builtin/init-db.c |   38 +++++++++++++++++++++++++++++++++++++-
 cache.h           |    1 +
 3 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 60d9a64..74e487a 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -42,6 +42,7 @@ static int option_local, option_no_hardlinks, option_shared, option_recursive;
 static char *option_template, *option_reference, *option_depth;
 static char *option_origin = NULL;
 static char *option_branch = NULL;
+static const char *real_git_dir;
 static char *option_upload_pack = "git-upload-pack";
 static int option_verbosity;
 static int option_progress;
@@ -80,6 +81,8 @@ static struct option builtin_clone_options[] = {
 		   "path to git-upload-pack on the remote"),
 	OPT_STRING(0, "depth", &option_depth, "depth",
 		    "create a shallow clone of that depth"),
+	OPT_STRING(0, "real-git-dir", &real_git_dir, "git-dir",
+		   "directory where real repository is cloned to"),
 
 	OPT_END()
 };
@@ -466,7 +469,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
 	if (safe_create_leading_directories_const(git_dir) < 0)
 		die("could not create leading directories of '%s'", git_dir);
-	set_git_dir(make_absolute_path(git_dir));
+	set_git_dir_init(git_dir, real_git_dir);
+	if (real_git_dir)
+		git_dir = real_git_dir;
 
 	if (0 <= option_verbosity)
 		printf("Cloning into %s%s...\n",
diff --git a/builtin/init-db.c b/builtin/init-db.c
index fbeb380..7a0fb50 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -21,6 +21,7 @@
 static int init_is_bare_repository = 0;
 static int init_shared_repository = -1;
 static const char *init_db_template_dir;
+static const char *git_link;
 
 static void safe_create_dir(const char *dir, int share)
 {
@@ -311,10 +312,42 @@ static void create_object_directory(void)
 	free(path);
 }
 
+int set_git_dir_init(const char *git_dir, const char *real_git_dir)
+{
+	if (real_git_dir) {
+		struct stat st;
+
+		if (!stat(git_dir, &st))
+			die("%s already exists", git_dir);
+		git_link = git_dir;
+	}
+	else {
+		real_git_dir = git_dir;
+		git_link = NULL;
+	}
+	set_git_dir(make_absolute_path(real_git_dir));
+	return 0;
+}
+
 int init_db(const char *template_dir, unsigned int flags)
 {
 	int reinit;
 
+	if (git_link) {
+		struct stat st;
+		FILE *fp;
+
+		/* TODO: allow --real-git-dir to move repo elsewhere */
+		if (!lstat(git_link, &st))
+			die("%s already exists", git_link);
+
+		fp = fopen(git_link, "w");
+		if (!fp)
+			die("Could not create git link %s", git_link);
+		fprintf(fp, "gitdir: %s\n", get_git_dir());
+		fclose(fp);
+	}
+
 	safe_create_dir(get_git_dir(), 0);
 
 	init_is_bare_repository = is_bare_repository();
@@ -414,6 +447,7 @@ static const char *const init_db_usage[] = {
 int cmd_init_db(int argc, const char **argv, const char *prefix)
 {
 	const char *git_dir;
+	const char *real_git_dir = NULL;
 	const char *work_tree;
 	const char *template_dir = NULL;
 	unsigned int flags = 0;
@@ -427,6 +461,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 			"specify that the git repository is to be shared amongst several users",
 			PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
 		OPT_BIT('q', "quiet", &flags, "be quiet", INIT_DB_QUIET),
+		OPT_STRING(0, "real-git-dir", &real_git_dir, "git-dir",
+			   "directory where real .git is initialized"),
 		OPT_END()
 	};
 
@@ -522,7 +558,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 			set_git_work_tree(make_absolute_path(work_tree));
 	}
 
-	set_git_dir(make_absolute_path(git_dir));
+	set_git_dir_init(git_dir, real_git_dir);
 
 	return init_db(template_dir, flags);
 }
diff --git a/cache.h b/cache.h
index 08a9022..0b006b8 100644
--- a/cache.h
+++ b/cache.h
@@ -436,6 +436,7 @@ extern void verify_non_filename(const char *prefix, const char *name);
 
 #define INIT_DB_QUIET 0x0001
 
+extern int set_git_dir_init(const char *git_dir, const char *real_git_dir);
 extern int init_db(const char *template_dir, unsigned int flags);
 
 #define alloc_nr(x) (((x)+16)*3/2)
-- 
1.7.4.74.g639db

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]