From: Junio C Hamano Date: Tue, 6 May 2008 02:16:16 +0000 (-0700) Subject: Merge branch 'lh/git-file' X-Git-Tag: v1.5.6-rc0~93 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/e2e2defc14a79ea5b4aaae23e33072f29c5965eb?ds=inline;hp=-c Merge branch 'lh/git-file' * lh/git-file: Teach GIT-VERSION-GEN about the .git file Teach git-submodule.sh about the .git file Teach resolve_gitlink_ref() about the .git file Add platform-independent .git "symlink" --- e2e2defc14a79ea5b4aaae23e33072f29c5965eb diff --combined cache.h index 5a28dddec9,2bda40c616..d5d5dad146 --- a/cache.h +++ b/cache.h @@@ -311,6 -311,7 +311,7 @@@ extern char *get_index_file(void) extern char *get_graft_file(void); extern int set_git_dir(const char *path); extern const char *get_git_work_tree(void); + extern const char *read_gitfile_gently(const char *path); #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" @@@ -474,20 -475,10 +475,20 @@@ static inline void hashclr(unsigned cha int git_mkstemp(char *path, size_t n, const char *template); +/* + * NOTE NOTE NOTE!! + * + * PERM_UMASK, OLD_PERM_GROUP and OLD_PERM_EVERYBODY enumerations must + * not be changed. Old repositories have core.sharedrepository written in + * numeric format, and therefore these values are preserved for compatibility + * reasons. + */ enum sharedrepo { - PERM_UMASK = 0, - PERM_GROUP, - PERM_EVERYBODY + PERM_UMASK = 0, + OLD_PERM_GROUP = 1, + OLD_PERM_EVERYBODY = 2, + PERM_GROUP = 0660, + PERM_EVERYBODY = 0664, }; int git_config_perm(const char *var, const char *value); int adjust_shared_perm(const char *path); @@@ -702,7 -693,6 +703,7 @@@ extern int git_parse_long(const char * extern int git_parse_ulong(const char *, unsigned long *); extern int git_config_int(const char *, const char *); extern unsigned long git_config_ulong(const char *, const char *); +extern int git_config_bool_or_int(const char *, const char *, int *); extern int git_config_bool(const char *, const char *); extern int git_config_string(const char **, const char *, const char *); extern int git_config_set(const char *, const char *); @@@ -726,8 -716,8 +727,8 @@@ extern const char *git_log_output_encod extern void maybe_flush_or_die(FILE *, const char *); extern int copy_fd(int ifd, int ofd); extern int copy_file(const char *dst, const char *src, int mode); -extern int read_in_full(int fd, void *buf, size_t count); -extern int write_in_full(int fd, const void *buf, size_t count); +extern ssize_t read_in_full(int fd, void *buf, size_t count); +extern ssize_t write_in_full(int fd, const void *buf, size_t count); extern void write_or_die(int fd, const void *buf, size_t count); extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg); extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg); diff --combined git-submodule.sh index ce0f00c8a4,5bff86022c..67f7a28cb3 --- a/git-submodule.sh +++ b/git-submodule.sh @@@ -300,7 -300,7 +300,7 @@@ cmd_update( continue fi - if ! test -d "$path"/.git + if ! test -d "$path"/.git -o -f "$path"/.git then module_clone "$path" "$url" || exit subsha1= @@@ -327,8 -327,7 +327,8 @@@ set_name_rev () cd "$1" && { git describe "$2" 2>/dev/null || git describe --tags "$2" 2>/dev/null || - git describe --contains --tags "$2" + git describe --contains "$2" 2>/dev/null || + git describe --all --always "$2" } ) ) test -z "$revname" || revname=" ($revname)" @@@ -343,7 -342,6 +343,7 @@@ # cmd_summary() { summary_limit=-1 + for_status= # parse $args after "submodule ... summary". while test $# -ne 0 @@@ -352,9 -350,6 +352,9 @@@ --cached) cached="$1" ;; + --for-status) + for_status="$1" + ;; -n|--summary-limit) if summary_limit=$(($2 + 0)) 2>/dev/null && test "$summary_limit" = "$2" then @@@ -402,8 -397,7 +402,8 @@@ done ) - test -n "$modules" && + test -z "$modules" && return + git diff-index $cached --raw $head -- $modules | grep -e '^:160000' -e '^:[0-7]* 160000' | cut -c2- | @@@ -505,14 -499,7 +505,14 @@@ echo fi echo - done + done | + if test -n "$for_status"; then + echo "# Modified submodules:" + echo "#" + sed -e 's|^|# |' -e 's|^# $|#|' + else + cat + fi } # # List all submodules, prefixed with: @@@ -555,7 -542,7 +555,7 @@@ cmd_status( do name=$(module_name "$path") || exit url=$(git config submodule."$name".url) - if test -z "$url" || ! test -d "$path"/.git + if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git then say "-$sha1 $path" continue; diff --combined refs.c index 4db73ed8f0,a81fb291f8..9b495eb16e --- a/refs.c +++ b/refs.c @@@ -352,6 -352,7 +352,7 @@@ int resolve_gitlink_ref(const char *pat { int len = strlen(path), retval; char *gitdir; + const char *tmp; while (len && path[len-1] == '/') len--; @@@ -359,17 -360,26 +360,27 @@@ return -1; gitdir = xmalloc(len + MAXREFLEN + 8); memcpy(gitdir, path, len); - memcpy(gitdir + len, "/.git/", 7); - - retval = resolve_gitlink_ref_recursive(gitdir, len+6, refname, result, 0); + memcpy(gitdir + len, "/.git", 6); + len += 5; + + tmp = read_gitfile_gently(gitdir); + if (tmp) { + free(gitdir); + len = strlen(tmp); + gitdir = xmalloc(len + MAXREFLEN + 3); + memcpy(gitdir, tmp, len); + } + gitdir[len] = '/'; + gitdir[++len] = '\0'; + retval = resolve_gitlink_ref_recursive(gitdir, len, refname, result, 0); free(gitdir); return retval; } const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag) { - int depth = MAXDEPTH, len; + int depth = MAXDEPTH; + ssize_t len; char buffer[256]; static char ref_buffer[256]; diff --combined setup.c index 1b4fa6a8c4,53580fde43..b8fd476395 --- a/setup.c +++ b/setup.c @@@ -314,6 -314,44 +314,44 @@@ static int check_repository_format_gent return 0; } + /* + * Try to read the location of the git directory from the .git file, + * return path to git directory if found. + */ + const char *read_gitfile_gently(const char *path) + { + char *buf; + struct stat st; + int fd; + size_t len; + + if (stat(path, &st)) + return NULL; + if (!S_ISREG(st.st_mode)) + return NULL; + fd = open(path, O_RDONLY); + if (fd < 0) + die("Error opening %s: %s", path, strerror(errno)); + buf = xmalloc(st.st_size + 1); + len = read_in_full(fd, buf, st.st_size); + close(fd); + if (len != st.st_size) + die("Error reading %s", path); + buf[len] = '\0'; + if (prefixcmp(buf, "gitdir: ")) + die("Invalid gitfile format: %s", path); + while (buf[len - 1] == '\n' || buf[len - 1] == '\r') + len--; + if (len < 9) + die("No path in gitfile: %s", path); + buf[len] = '\0'; + if (!is_git_directory(buf + 8)) + die("Not a git repository: %s", buf + 8); + path = make_absolute_path(buf + 8); + free(buf); + return path; + } + /* * We cannot decide in this function whether we are in the work tree or * not, since the config can only be read _after_ this function was called. @@@ -323,6 -361,7 +361,7 @@@ const char *setup_git_directory_gently( const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT); static char cwd[PATH_MAX+1]; const char *gitdirenv; + const char *gitfile_dir; int len, offset; /* @@@ -377,8 -416,10 +416,10 @@@ /* * Test in the following order (relative to the cwd): + * - .git (file containing "gitdir: ") * - .git/ * - ./ (bare) + * - ../.git * - ../.git/ * - ../ (bare) * - ../../.git/ @@@ -386,6 -427,12 +427,12 @@@ */ offset = len = strlen(cwd); for (;;) { + gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT); + if (gitfile_dir) { + if (set_git_dir(gitfile_dir)) + die("Repository setup failed"); + break; + } if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT)) break; if (is_git_directory(".")) { @@@ -428,53 -475,21 +475,53 @@@ int git_config_perm(const char *var, const char *value) { - if (value) { - int i; - if (!strcmp(value, "umask")) - return PERM_UMASK; - if (!strcmp(value, "group")) - return PERM_GROUP; - if (!strcmp(value, "all") || - !strcmp(value, "world") || - !strcmp(value, "everybody")) - return PERM_EVERYBODY; - i = atoi(value); - if (i > 1) - return i; + int i; + char *endptr; + + if (value == NULL) + return PERM_GROUP; + + if (!strcmp(value, "umask")) + return PERM_UMASK; + if (!strcmp(value, "group")) + return PERM_GROUP; + if (!strcmp(value, "all") || + !strcmp(value, "world") || + !strcmp(value, "everybody")) + return PERM_EVERYBODY; + + /* Parse octal numbers */ + i = strtol(value, &endptr, 8); + + /* If not an octal number, maybe true/false? */ + if (*endptr != 0) + return git_config_bool(var, value) ? PERM_GROUP : PERM_UMASK; + + /* + * Treat values 0, 1 and 2 as compatibility cases, otherwise it is + * a chmod value. + */ + switch (i) { + case PERM_UMASK: /* 0 */ + return PERM_UMASK; + case OLD_PERM_GROUP: /* 1 */ + return PERM_GROUP; + case OLD_PERM_EVERYBODY: /* 2 */ + return PERM_EVERYBODY; } - return git_config_bool(var, value); + + /* A filemode value was given: 0xxx */ + + if ((i & 0600) != 0600) + die("Problem with core.sharedRepository filemode value " + "(0%.3o).\nThe owner of files must always have " + "read and write permissions.", i); + + /* + * Mask filemode value. Others can not get write permission. + * x flags for directories are handled separately. + */ + return i & 0666; } int check_repository_format_version(const char *var, const char *value)