Subject: [PATCH] clone: add --perm option to clone an shared repository

From: Roy Lee <[email-masked]>
Date: Sun, 21 Jun 2009 20:17:52 +0800

The term 'shared' used here is in the same context with git init.
Unfortunately the 'shared' option has been taken, so I took the "perm"
as a place holder in this patch. Any comments?

Signed-off-by: Roy Lee <[email-masked]>
---
 Documentation/git-clone.txt |   40 +++++++++++++++++++++++++++++++++++++++-
 builtin-clone.c             |    7 +++++++
 2 files changed, 46 insertions(+), 1 deletions(-)

diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index b14de6c..b35818d 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -12,7 +12,8 @@ SYNOPSIS
 'git clone' [--template=<template_directory>]
 	  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
 	  [-o <name>] [-u <upload-pack>] [--reference <repository>]
-	  [--depth <depth>] [--] <repository> [<directory>]
+	  [--depth <depth>] [--perm[=<permissions>]]
+	  [--] <repository> [<directory>]
 
 DESCRIPTION
 -----------
@@ -139,6 +140,43 @@ then the cloned repository will become corrupt.
 	with a long history, and would want to send in fixes
 	as patches.
 
+--perm[={false|true|umask|group|all|world|everybody|0xxx}]::
+
+Specify that the git repository is to be shared amongst several users.  This
+allows users belonging to the same group to push into that
+repository.  When specified, the config variable "core.sharedRepository" is
+set so that files and directories under `$GIT_DIR` are created with the
+requested permissions.  When not specified, git will use permissions reported
+by umask(2).
+
+The option can have the following values, defaulting to 'group' if no value
+is given:
+
+ - 'umask' (or 'false'): Use permissions reported by umask(2). The default,
+   when `--perm` is not specified.
+
+ - 'group' (or 'true'): Make the repository group-writable, (and g+sx, since
+   the git group may be not the primary group of all users).
+   This is used to loosen the permissions of an otherwise safe umask(2) value.
+   Note that the umask still applies to the other permission bits (e.g. if
+   umask is '0022', using 'group' will not remove read privileges from other
+   (non-group) users). See '0xxx' for how to exactly specify the repository
+   permissions.
+
+ - 'all' (or 'world' or 'everybody'): Same as 'group', but make the repository
+   readable by all users.
+
+ - '0xxx': '0xxx' is an octal number and each file will have mode '0xxx'.
+   '0xxx' will override users' umask(2) value (and not only loosen permissions
+   as 'group' and 'all' does). '0640' will create a repository which is
+   group-readable, but not group-writable or accessible to others. '0660' will
+   create a repo that is readable and writable to the current user and group,
+   but inaccessible to others.
+
+By default, the configuration flag receive.denyNonFastForwards is enabled
+in shared repositories, so that you cannot force a non fast-forwarding push
+into it.
+
 <repository>::
 	The (possibly remote) repository to clone from.  See the
 	<<URLS,URLS>> section below for more information on specifying
diff --git a/builtin-clone.c b/builtin-clone.c
index 2ceacb7..ee31d64 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -40,6 +40,7 @@ static const char * const builtin_clone_usage[] = {
 static int option_quiet, option_no_checkout, option_bare, option_mirror;
 static int option_local, option_no_hardlinks, option_shared;
 static char *option_template, *option_reference, *option_depth;
+static char *option_perm = NULL;
 static char *option_origin = NULL;
 static char *option_upload_pack = "git-upload-pack";
 static int option_verbose;
@@ -59,6 +60,9 @@ static struct option builtin_clone_options[] = {
 		    "don't use local hardlinks, always copy"),
 	OPT_BOOLEAN('s', "shared", &option_shared,
 		    "setup as shared repository"),
+	{ OPTION_STRING, 0, "perm", &option_perm, "mode",
+		    "the repository is to be shared amongst several users",
+		    PARSE_OPT_OPTARG, NULL, (intptr_t)"group" },
 	OPT_STRING(0, "template", &option_template, "path",
 		   "path the template repository"),
 	OPT_STRING(0, "reference", &option_reference, "repo",
@@ -376,6 +380,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		option_no_checkout = 1;
 	}
 
+	if (option_perm)
+		shared_repository = git_config_perm("arg", option_perm);
+
 	if (!option_origin)
 		option_origin = "origin";
 
-- 
1.6.3.2.316.gda4e.dirty