diff options
-rw-r--r-- | Documentation/git-ls-files.txt | 9 | ||||
-rw-r--r-- | Documentation/tutorial.txt | 18 | ||||
-rw-r--r-- | cache.h | 2 | ||||
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | environment.c | 1 | ||||
-rwxr-xr-x | git-clone.sh | 16 | ||||
-rwxr-xr-x | git-merge.sh | 11 | ||||
-rw-r--r-- | init-db.c | 32 | ||||
-rw-r--r-- | ls-files.c | 2 | ||||
-rw-r--r-- | mailinfo.c | 2 | ||||
-rw-r--r-- | setup.c | 2 | ||||
-rw-r--r-- | sha1_file.c | 32 | ||||
-rw-r--r-- | show-branch.c | 71 |
13 files changed, 163 insertions, 41 deletions
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt index 2f308ecda9..186f3bb57a 100644 --- a/Documentation/git-ls-files.txt +++ b/Documentation/git-ls-files.txt @@ -13,7 +13,8 @@ SYNOPSIS (-[c|d|o|i|s|u|k|m])\* [-x <pattern>|--exclude=<pattern>] [-X <file>|--exclude-from=<file>] - [--exclude-per-directory=<file>] [--] [<file>]\* + [--exclude-per-directory=<file>] + [--full-name] [--] [<file>]\* DESCRIPTION ----------- @@ -77,6 +78,12 @@ OPTIONS K:: to be killed ? other +--full-name:: + When run from a subdirectory, the command usually + outputs paths relative to the current directory. This + option forces paths to be output relative to the project + top directory. + --:: Do not interpret any more arguments as options. diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index 3a5c56e24e..edd91cbbe4 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -1695,6 +1695,24 @@ You still need to create UNIX user accounts for each developer, and put them in the same group. Make sure that the repository shared among these developers is writable by that group. +. Initializing the shared repository with `git-init-db --shared` +helps somewhat. + +. Run the following in the shared repository: ++ +------------ +$ chgrp -R $group repo.git +$ find repo.git -type d -print | xargs chmod ug+rwx,g+s +$ GIT_DIR=repo.git git repo-config core.sharedrepository true +------------ + +The above measures make sure that directories lazily created in +`$GIT_DIR` are writable by group members. You, as the +repository administrator, are still responsible to make sure +your developers belong to that shared repository group and set +their umask to a value no stricter than 027 (i.e. at least allow +reading and searching by group members). + You can implement finer grained branch policies using update hooks. There is a document ("control access to branches") in Documentation/howto by Carl Baldwin and JC outlining how to (1) @@ -159,6 +159,7 @@ extern void rollback_index_file(struct cache_file *); extern int trust_executable_bit; extern int only_use_symrefs; extern int diff_rename_limit_default; +extern int shared_repository; #define GIT_REPO_VERSION 0 extern int repository_format_version; @@ -183,6 +184,7 @@ extern const unsigned char null_sha1[20]; int git_mkstemp(char *path, size_t n, const char *template); +int adjust_shared_perm(const char *path); int safe_create_leading_directories(char *path); char *safe_strncpy(char *, const char *, size_t); char *enter_repo(char *path, int strict); diff --git a/debian/changelog b/debian/changelog index 8d6c0667c7..d7f7591079 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,6 +10,12 @@ git-core (1.0.0.GIT-0) unstable; urgency=low -- Junio C Hamano <junkio@cox.net> Wed, 21 Dec 2005 12:12:05 -0800 +git-core (1.0.4-0) unstable; urgency=low + + * GIT 1.0.4. + + -- Junio C Hamano <junkio@cox.net> Sat, 24 Dec 2005 00:01:20 -0800 + git-core (1.0.3-0) unstable; urgency=low * GIT 1.0.3 maintenance release. diff --git a/environment.c b/environment.c index 0886ad38f9..0596fc647b 100644 --- a/environment.c +++ b/environment.c @@ -15,6 +15,7 @@ int trust_executable_bit = 1; int only_use_symrefs = 0; int repository_format_version = 0; char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8"; +int shared_repository = 0; static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file; diff --git a/git-clone.sh b/git-clone.sh index bfc6c2d79f..377d59e62c 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -31,25 +31,11 @@ clone_dumb_http () { cd "$2" && clone_tmp='.git/clone-tmp' && mkdir -p "$clone_tmp" || exit 1 - http_fetch "$1/info/refs" "$clone_tmp/refs" && - http_fetch "$1/objects/info/packs" "$clone_tmp/packs" || { + http_fetch "$1/info/refs" "$clone_tmp/refs" || { echo >&2 "Cannot get remote repository information. Perhaps git-update-server-info needs to be run there?" exit 1; } - while read type name - do - case "$type" in - P) ;; - *) continue ;; - esac && - - idx=`expr "$name" : '\(.*\)\.pack'`.idx - http_fetch "$1/objects/pack/$name" ".git/objects/pack/$name" && - http_fetch "$1/objects/pack/$idx" ".git/objects/pack/$idx" && - git-verify-pack ".git/objects/pack/$idx" || exit 1 - done <"$clone_tmp/packs" - while read sha1 refname do name=`expr "$refname" : 'refs/\(.*\)'` && diff --git a/git-merge.sh b/git-merge.sh index e50fbb1160..0a158ef779 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -209,6 +209,7 @@ case "$use_strategies" in esac result_tree= best_cnt=-1 best_strategy= wt_strategy= +merge_was_ok= for strategy in $use_strategies do test "$wt_strategy" = '' || { @@ -228,6 +229,7 @@ do exit=$? if test "$no_commit" = t && test "$exit" = 0 then + merge_was_ok=t exit=1 ;# pretend it left conflicts. fi @@ -293,4 +295,11 @@ do done >"$GIT_DIR/MERGE_HEAD" echo $merge_msg >"$GIT_DIR/MERGE_MSG" -die "Automatic merge failed/prevented; fix up by hand" +if test "$merge_was_ok" = t +then + echo >&2 \ + "Automatic merge went well; stopped before committing as requested" + exit 0 +else + die "Automatic merge failed; fix up by hand" +fi @@ -9,7 +9,7 @@ #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates/" #endif -static void safe_create_dir(const char *dir) +static void safe_create_dir(const char *dir, int share) { if (mkdir(dir, 0777) < 0) { if (errno != EEXIST) { @@ -17,6 +17,8 @@ static void safe_create_dir(const char *dir) exit(1); } } + else if (share && adjust_shared_perm(dir)) + die("Could not make %s writable by group\n", dir); } static int copy_file(const char *dst, const char *src, int mode) @@ -32,6 +34,10 @@ static int copy_file(const char *dst, const char *src, int mode) } status = copy_fd(fdi, fdo); close(fdo); + + if (!status && adjust_shared_perm(dst)) + return -1; + return status; } @@ -48,7 +54,7 @@ static void copy_templates_1(char *path, int baselen, * with the way the namespace under .git/ is organized, should * be really carefully chosen. */ - safe_create_dir(path); + safe_create_dir(path, 1); while ((de = readdir(dir)) != NULL) { struct stat st_git, st_template; int namelen; @@ -176,11 +182,11 @@ static void create_default_files(const char *git_dir, char *template_path) * Create .git/refs/{heads,tags} */ strcpy(path + len, "refs"); - safe_create_dir(path); + safe_create_dir(path, 1); strcpy(path + len, "refs/heads"); - safe_create_dir(path); + safe_create_dir(path, 1); strcpy(path + len, "refs/tags"); - safe_create_dir(path); + safe_create_dir(path, 1); /* First copy the templates -- we might have the default * config file there, in which case we would want to read @@ -220,7 +226,7 @@ static void create_default_files(const char *git_dir, char *template_path) } static const char init_db_usage[] = -"git-init-db [--template=<template-directory>]"; +"git-init-db [--template=<template-directory>] [--shared]"; /* * If you want to, you can share the DB area with any number of branches. @@ -239,6 +245,8 @@ int main(int argc, char **argv) char *arg = argv[1]; if (!strncmp(arg, "--template=", 11)) template_dir = arg+11; + else if (!strcmp(arg, "--shared")) + shared_repository = 1; else die(init_db_usage); } @@ -251,7 +259,7 @@ int main(int argc, char **argv) git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; fprintf(stderr, "defaulting to local storage area\n"); } - safe_create_dir(git_dir); + safe_create_dir(git_dir, 0); /* Check to see if the repository version is right. * Note that a newly created repository does not have @@ -270,10 +278,14 @@ int main(int argc, char **argv) path = xmalloc(len + 40); memcpy(path, sha1_dir, len); - safe_create_dir(sha1_dir); + safe_create_dir(sha1_dir, 1); strcpy(path+len, "/pack"); - safe_create_dir(path); + safe_create_dir(path, 1); strcpy(path+len, "/info"); - safe_create_dir(path); + safe_create_dir(path, 1); + + if (shared_repository) + git_config_set("core.sharedRepository", "true"); + return 0; } diff --git a/ls-files.c b/ls-files.c index f3f1a6a663..5e9ac712af 100644 --- a/ls-files.c +++ b/ls-files.c @@ -562,7 +562,7 @@ static void verify_pathspec(void) static const char ls_files_usage[] = "git-ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed|modified])* " "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] " - "[ --exclude-per-directory=<filename> ] [--] [<file>]*"; + "[ --exclude-per-directory=<filename> ] [--full-name] [--] [<file>]*"; int main(int argc, const char **argv) { diff --git a/mailinfo.c b/mailinfo.c index 9f95f37651..0265a29a38 100644 --- a/mailinfo.c +++ b/mailinfo.c @@ -472,7 +472,7 @@ static void convert_to_utf8(char *line, char *charset) char *in, *out; size_t insize, outsize, nrc; char outbuf[4096]; /* cheat */ - static char latin_one[] = "latin-1"; + static char latin_one[] = "latin1"; char *input_charset = *charset ? charset : latin_one; iconv_t conv = iconv_open(metainfo_charset, input_charset); @@ -180,6 +180,8 @@ int check_repository_format_version(const char *var, const char *value) { if (strcmp(var, "core.repositoryformatversion") == 0) repository_format_version = git_config_int(var, value); + else if (strcmp(var, "core.sharedrepository") == 0) + shared_repository = git_config_bool(var, value); return 0; } diff --git a/sha1_file.c b/sha1_file.c index 6b7577dbc4..8bebbb255f 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -48,6 +48,29 @@ int get_sha1_hex(const char *hex, unsigned char *sha1) return 0; } +int adjust_shared_perm(const char *path) +{ + struct stat st; + int mode; + + if (!shared_repository) + return 0; + if (lstat(path, &st) < 0) + return -1; + mode = st.st_mode; + if (mode & S_IRUSR) + mode |= S_IRGRP; + if (mode & S_IWUSR) + mode |= S_IWGRP; + if (mode & S_IXUSR) + mode |= S_IXGRP; + if (S_ISDIR(mode)) + mode |= S_ISGID; + if (chmod(path, mode) < 0) + return -2; + return 0; +} + int safe_create_leading_directories(char *path) { char *pos = path; @@ -59,11 +82,16 @@ int safe_create_leading_directories(char *path) if (!pos) break; *pos = 0; - if (mkdir(path, 0777) < 0) + if (mkdir(path, 0777) < 0) { if (errno != EEXIST) { *pos = '/'; return -1; } + } + else if (adjust_shared_perm(path)) { + *pos = '/'; + return -2; + } *pos++ = '/'; } return 0; @@ -1255,6 +1283,8 @@ static int link_temp_to_file(const char *tmpfile, char *filename) if (dir) { *dir = 0; mkdir(filename, 0777); + if (adjust_shared_perm(filename)) + return -2; *dir = '/'; if (!link(tmpfile, filename)) return 0; diff --git a/show-branch.c b/show-branch.c index 3fe62b7177..15b1968781 100644 --- a/show-branch.c +++ b/show-branch.c @@ -284,10 +284,54 @@ static void show_one_commit(struct commit *commit, int no_name) static char *ref_name[MAX_REVS + 1]; static int ref_name_cnt; +static const char *find_digit_prefix(const char *s, int *v) +{ + const char *p; + int ver; + char ch; + + for (p = s, ver = 0; + '0' <= (ch = *p) && ch <= '9'; + p++) + ver = ver * 10 + ch - '0'; + *v = ver; + return p; +} + + +static int version_cmp(const char *a, const char *b) +{ + while (1) { + int va, vb; + + a = find_digit_prefix(a, &va); + b = find_digit_prefix(b, &vb); + if (va != vb) + return va - vb; + + while (1) { + int ca = *a; + int cb = *b; + if ('0' <= ca && ca <= '9') + ca = 0; + if ('0' <= cb && cb <= '9') + cb = 0; + if (ca != cb) + return ca - cb; + if (!ca) + break; + a++; + b++; + } + if (!*a && !*b) + return 0; + } +} + static int compare_ref_name(const void *a_, const void *b_) { const char * const*a = a_, * const*b = b_; - return strcmp(*a, *b); + return version_cmp(*a, *b); } static void sort_ref_range(int bottom, int top) @@ -299,8 +343,15 @@ static void sort_ref_range(int bottom, int top) static int append_ref(const char *refname, const unsigned char *sha1) { struct commit *commit = lookup_commit_reference_gently(sha1, 1); + int i; + if (!commit) return 0; + /* Avoid adding the same thing twice */ + for (i = 0; i < ref_name_cnt; i++) + if (!strcmp(refname, ref_name[i])) + return 0; + if (MAX_REVS <= ref_name_cnt) { fprintf(stderr, "warning: ignoring %s; " "cannot handle more than %d refs\n", @@ -512,19 +563,17 @@ int main(int ac, char **av) if (1 < independent + merge_base + (extra != 0)) usage(show_branch_usage); + /* If nothing is specified, show all branches by default */ + if (ac + all_heads + all_tags == 0) + all_heads = 1; + if (all_heads + all_tags) snarf_refs(all_heads, all_tags); - - if (ac) { - while (0 < ac) { - append_one_rev(*av); - ac--; av++; - } - } - else { - /* If no revs given, then add heads */ - snarf_refs(1, 0); + while (0 < ac) { + append_one_rev(*av); + ac--; av++; } + if (!ref_name_cnt) { fprintf(stderr, "No revs to be shown.\n"); exit(0); |