@matheusbsbs / matheus-bagliano / commits / 06cbe85503
Fork 0

Make core.sharedRepository more generic

git init --shared=0xxx, where '0xxx' is an octal number, will create a repository with file modes set to '0xxx'. Users with a safe umask value (0077) can use this option to force file modes. For example, '0640' is a group-readable but not group-writable regardless of user's umask value. Values compatible with old Git versions are written as they were before, for compatibility reasons. That is, "1" for "group" and "2" for "everybody". "git config core.sharedRepository 0xxx" is also handled. Signed-off-by: Heikki Orsila <heikki.orsila@iki.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Heikki Orsila committed Apr 16, 2008 at 11:34 UTC 06cbe8550324e0fd2290839bf3b9a92aa53b70ab
7 files changed +149 -38
Documentation/config.txt
+6 -1
@@ -261,7 +261,12 @@ core.sharedRepository::
261 group-writable). When 'all' (or 'world' or 'everybody'), the
262 repository will be readable by all users, additionally to being
263 group-shareable. When 'umask' (or 'false'), git will use permissions
264 - reported by umask(2). See linkgit:git-init[1]. False by default.
264 + reported by umask(2). When '0xxx', where '0xxx' is an octal number,
265 + files in the repository will have this mode value. '0xxx' will override
266 + user's umask value, and thus, users with a safe umask (0077) can use
267 + this option. Examples: '0660' is equivalent to 'group'. '0640' is a
268 + repository that is group-readable but not group-writable.
269 + See linkgit:git-init[1]. False by default.
270
271 core.warnAmbiguousRefs::
272 If true, git will warn you if the ref name you passed it is ambiguous
Documentation/git-init.txt
+7 -1
@@ -31,7 +31,7 @@ structure, some suggested "exclude patterns", and copies of non-executing
31 "hook" files. The suggested patterns and hook files are all modifiable and
32 extensible.
33
34 ---shared[={false|true|umask|group|all|world|everybody}]::
34 +--shared[={false|true|umask|group|all|world|everybody|0xxx}]::
35
36 Specify that the git repository is to be shared amongst several users. This
37 allows users belonging to the same group to push into that
@@ -52,6 +52,12 @@ is given:
52 - 'all' (or 'world' or 'everybody'): Same as 'group', but make the repository
53 readable by all users.
54
55 + - '0xxx': '0xxx' is an octal number and each file will have mode '0xxx'
56 + Any option except 'umask' can be set using this option. '0xxx' will
57 + override users umask(2) value, and thus, users with a safe umask (0077)
58 + can use this option. '0640' will create a repository which is group-readable
59 + but not writable. '0660' is equivalent to 'group'.
60 +
61 By default, the configuration flag receive.denyNonFastForwards is enabled
62 in shared repositories, so that you cannot force a non fast-forwarding push
63 into it.
builtin-init-db.c
+9 -2
@@ -400,9 +400,16 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
400 char buf[10];
401 /* We do not spell "group" and such, so that
402 * the configuration can be read by older version
403 - * of git.
403 + * of git. Note, we use octal numbers for new share modes,
404 + * and compatibility values for PERM_GROUP and
405 + * PERM_EVERYBODY.
406 */
405 - sprintf(buf, "%d", shared_repository);
407 + if (shared_repository == PERM_GROUP)
408 + sprintf(buf, "%d", OLD_PERM_GROUP);
409 + else if (shared_repository == PERM_EVERYBODY)
410 + sprintf(buf, "%d", OLD_PERM_EVERYBODY);
411 + else
412 + sprintf(buf, "0%o", shared_repository);
413 git_config_set("core.sharedrepository", buf);
414 git_config_set("receive.denyNonFastforwards", "true");
415 }
cache.h
+13 -3
@@ -474,10 +474,20 @@ static inline void hashclr(unsigned char *hash)
474
475 int git_mkstemp(char *path, size_t n, const char *template);
476
477 +/*
478 + * NOTE NOTE NOTE!!
479 + *
480 + * PERM_UMASK, OLD_PERM_GROUP and OLD_PERM_EVERYBODY enumerations must
481 + * not be changed. Old repositories have core.sharedrepository written in
482 + * numeric format, and therefore these values are preserved for compatibility
483 + * reasons.
484 + */
485 enum sharedrepo {
478 - PERM_UMASK = 0,
479 - PERM_GROUP,
480 - PERM_EVERYBODY
486 + PERM_UMASK = 0,
487 + OLD_PERM_GROUP = 1,
488 + OLD_PERM_EVERYBODY = 2,
489 + PERM_GROUP = 0660,
490 + PERM_EVERYBODY = 0664,
491 };
492 int git_config_perm(const char *var, const char *value);
493 int adjust_shared_perm(const char *path);
path.c
+18 -17
@@ -266,24 +266,25 @@ int adjust_shared_perm(const char *path)
266 if (lstat(path, &st) < 0)
267 return -1;
268 mode = st.st_mode;
269 - if (mode & S_IRUSR)
270 - mode |= (shared_repository == PERM_GROUP
271 - ? S_IRGRP
272 - : (shared_repository == PERM_EVERYBODY
273 - ? (S_IRGRP|S_IROTH)
274 - : 0));
275 -
276 - if (mode & S_IWUSR)
277 - mode |= S_IWGRP;
278 -
279 - if (mode & S_IXUSR)
280 - mode |= (shared_repository == PERM_GROUP
281 - ? S_IXGRP
282 - : (shared_repository == PERM_EVERYBODY
283 - ? (S_IXGRP|S_IXOTH)
284 - : 0));
285 - if (S_ISDIR(mode))
269 +
270 + if (shared_repository) {
271 + int tweak = shared_repository;
272 + if (!(mode & S_IWUSR))
273 + tweak &= ~0222;
274 + mode = (mode & ~0777) | tweak;
275 + } else {
276 + /* Preserve old PERM_UMASK behaviour */
277 + if (mode & S_IWUSR)
278 + mode |= S_IWGRP;
279 + }
280 +
281 + if (S_ISDIR(mode)) {
282 mode |= FORCE_DIR_SET_GID;
283 +
284 + /* Copy read bits to execute bits */
285 + mode |= (shared_repository & 0444) >> 2;
286 + }
287 +
288 if ((mode & st.st_mode) != mode && chmod(path, mode) < 0)
289 return -2;
290 return 0;
setup.c
+46 -14
@@ -428,21 +428,53 @@ const char *setup_git_directory_gently(int *nongit_ok)
428
429 int git_config_perm(const char *var, const char *value)
430 {
431 - if (value) {
432 - int i;
433 - if (!strcmp(value, "umask"))
434 - return PERM_UMASK;
435 - if (!strcmp(value, "group"))
436 - return PERM_GROUP;
437 - if (!strcmp(value, "all") ||
438 - !strcmp(value, "world") ||
439 - !strcmp(value, "everybody"))
440 - return PERM_EVERYBODY;
441 - i = atoi(value);
442 - if (i > 1)
443 - return i;
431 + int i;
432 + char *endptr;
433 +
434 + if (value == NULL)
435 + return PERM_GROUP;
436 +
437 + if (!strcmp(value, "umask"))
438 + return PERM_UMASK;
439 + if (!strcmp(value, "group"))
440 + return PERM_GROUP;
441 + if (!strcmp(value, "all") ||
442 + !strcmp(value, "world") ||
443 + !strcmp(value, "everybody"))
444 + return PERM_EVERYBODY;
445 +
446 + /* Parse octal numbers */
447 + i = strtol(value, &endptr, 8);
448 +
449 + /* If not an octal number, maybe true/false? */
450 + if (*endptr != 0)
451 + return git_config_bool(var, value) ? PERM_GROUP : PERM_UMASK;
452 +
453 + /*
454 + * Treat values 0, 1 and 2 as compatibility cases, otherwise it is
455 + * a chmod value.
456 + */
457 + switch (i) {
458 + case PERM_UMASK: /* 0 */
459 + return PERM_UMASK;
460 + case OLD_PERM_GROUP: /* 1 */
461 + return PERM_GROUP;
462 + case OLD_PERM_EVERYBODY: /* 2 */
463 + return PERM_EVERYBODY;
464 }
445 - return git_config_bool(var, value);
465 +
466 + /* A filemode value was given: 0xxx */
467 +
468 + if ((i & 0600) != 0600)
469 + die("Problem with core.sharedRepository filemode value "
470 + "(0%.3o).\nThe owner of files must always have "
471 + "read and write permissions.", i);
472 +
473 + /*
474 + * Mask filemode value. Others can not get write permission.
475 + * x flags for directories are handled separately.
476 + */
477 + return i & 0666;
478 }
479
480 int check_repository_format_version(const char *var, const char *value)
t/t1301-shared-repo.sh
+50
@@ -7,6 +7,16 @@ test_description='Test shared repository initialization'
7
8 . ./test-lib.sh
9
10 +# User must have read permissions to the repo -> failure on --shared=0400
11 +test_expect_success 'shared = 0400 (faulty permission u-w)' '
12 + mkdir sub && (
13 + cd sub && git init --shared=0400
14 + )
15 + ret="$?"
16 + rm -rf sub
17 + test $ret != "0"
18 +'
19 +
20 test_expect_success 'shared=all' '
21 mkdir sub &&
22 cd sub &&
@@ -33,4 +43,44 @@ test_expect_success 'update-server-info honors core.sharedRepository' '
43 esac
44 '
45
46 +for u in 0660:rw-rw---- \
47 + 0640:rw-r----- \
48 + 0600:rw------- \
49 + 0666:rw-rw-rw- \
50 + 0664:rw-rw-r--
51 +do
52 + x=$(expr "$u" : ".*:\([rw-]*\)") &&
53 + y=$(echo "$x" | sed -e "s/w/-/g") &&
54 + u=$(expr "$u" : "\([0-7]*\)") &&
55 + git config core.sharedrepository "$u" &&
56 + umask 0277 &&
57 +
58 + test_expect_success "shared = $u ($y) ro" '
59 +
60 + rm -f .git/info/refs &&
61 + git update-server-info &&
62 + actual="$(ls -l .git/info/refs)" &&
63 + actual=${actual%% *} &&
64 + test "x$actual" = "x-$y" || {
65 + ls -lt .git/info
66 + false
67 + }
68 + '
69 +
70 + umask 077 &&
71 + test_expect_success "shared = $u ($x) rw" '
72 +
73 + rm -f .git/info/refs &&
74 + git update-server-info &&
75 + actual="$(ls -l .git/info/refs)" &&
76 + actual=${actual%% *} &&
77 + test "x$actual" = "x-$x" || {
78 + ls -lt .git/info
79 + false
80 + }
81 +
82 + '
83 +
84 +done
85 +
86 test_done