Merge branch 'sp/maint-bash-completion-optim' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 16 Jul 2008 22:25:24 +0000 (15:25 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 16 Jul 2008 22:25:24 +0000 (15:25 -0700)
* sp/maint-bash-completion-optim:
bash completion: Resolve git show ref:path<tab> losing ref: portion
bash completion: Append space after file names have been completed
bash completion: Don't offer "a.." as a completion for "a."
bash completion: Improve responsiveness of git-log completion

28 files changed:
Documentation/RelNotes-1.5.6.3.txt
Documentation/git-cherry-pick.txt
Documentation/git-mailinfo.txt
Documentation/git-revert.txt
Documentation/git.txt
attr.c
builtin-grep.c
builtin-mailinfo.c
daemon.c
diff-lib.c
diff.c
diff.h
git-am.sh
git-cvsserver.perl
git-rebase--interactive.sh
path.c
revision.c
sha1_file.c
t/t0004-unwritable.sh
t/t1301-shared-repo.sh
t/t5100-mailinfo.sh
t/t5100/0010 [new file with mode: 0644]
t/t5100/info0010 [new file with mode: 0644]
t/t5100/msg0010 [new file with mode: 0644]
t/t5100/patch0010 [new file with mode: 0644]
t/t5100/sample.mbox
t/t7600-merge.sh
tree-diff.c
index dd0559b64a07e6ba010374d49bb19cf3b1169142..942611299d59abd4bdd820e1258662067a304d62 100644 (file)
@@ -4,8 +4,16 @@ GIT v1.5.6.3 Release Notes
 Fixes since v1.5.6.2
 --------------------
 
+* Setting core.sharerepository to traditional "true" value was supposed to make
+  the repository group writable but should not affect permission for others.
+  However, since 1.5.6, it was broken to drop permission for others when umask is
+  022, making the repository unreadable by others.
+
 * Setting GIT_TRACE will report spawning of external process via run_command().
 
+* Using an object with very deep delta chain pinned memory needed for extracting
+  intermediate base objects unnecessarily long, leading to excess memory usage.
+
 * Bash completion script did not notice '--' marker on the command
   line and tried the relatively slow "ref completion" even when
   completing arguments after one.
@@ -14,6 +22,12 @@ Fixes since v1.5.6.2
   tree file for it confused "racy-git avoidance" logic into thinking
   that the path is now unchanged.
 
+* The section that describes attributes related to git-archive were placed
+  in a wrong place in the gitattributes(5) manual page.
+
+* "git am" was not helpful to the users when it detected that the committer
+  information is not set up properly yet.
+
 * "git clone" had a leftover debugging fprintf().
 
 * "git clone -q" was not quiet enough as it used to and gave object count
@@ -23,8 +37,10 @@ Fixes since v1.5.6.2
   good thing if the remote side is well packed but otherwise not,
   especially for a project that is not really big.
 
-* The section that describes attributes related to git-archive were placed
-  in a wrong place in the gitattributes(5) manual page.
+* "git daemon" used to call syslog() from a signal handler, which
+  could raise signals of its own but generally is not reentrant.  This
+  was fixed by restructuring the code to report syslog() after the handler
+  returns.
 
 * When "git push" tries to remove a remote ref, and corresponding
   tracking ref is missing, we used to report error (i.e. failure to
@@ -34,9 +50,3 @@ Fixes since v1.5.6.2
   MIME multipart mail correctly.
 
 Contains other various documentation fixes.
-
---
-exec >/var/tmp/1
-O=v1.5.6.2-23-ge965647
-echo O=$(git describe maint)
-git shortlog --no-merges $O..maint
index 5ac9cfb0ef2e2eb26ebe5cce6a5c7ed54d4e39ec..4ef5af4ca9ff31933c14f3d965348d67be9f983f 100644 (file)
@@ -58,14 +58,14 @@ OPTIONS
        Usually the command automatically creates a commit with
        a commit log message stating which commit was
        cherry-picked.  This flag applies the change necessary
-       to cherry-pick the named commit to your working tree,
-       but does not make the commit.  In addition, when this
-       option is used, your working tree does not have to match
+       to cherry-pick the named commit to your working tree
+       and the index, but does not make the commit.  In addition,
+       when this option is used, your index does not have to match
        the HEAD commit.  The cherry-pick is done against the
-       beginning state of your working tree.
+       beginning state of your index.
 +
 This is useful when cherry-picking more than one commits'
-effect to your working tree in a row.
+effect to your index in a row.
 
 -s::
 --signoff::
index 183dc1dd75c1268b199257496ac778e0d5dd7743..1e126f4a5c82d5b3829d9826f613a376590c54d8 100644 (file)
@@ -8,7 +8,7 @@ git-mailinfo - Extracts patch and authorship from a single e-mail message
 
 SYNOPSIS
 --------
-'git-mailinfo' [-k] [-u | --encoding=<encoding>] <msg> <patch>
+'git-mailinfo' [-k] [-u | --encoding=<encoding> | -n] <msg> <patch>
 
 
 DESCRIPTION
@@ -46,6 +46,9 @@ conversion, even with this flag.
        from what is specified by i18n.commitencoding, this flag
        can be used to override it.
 
+-n::
+       Disable all charset re-coding of the metadata.
+
 <msg>::
        The commit log message extracted from e-mail, usually
        except the title line which comes from e-mail Subject.
index 5b49b813862c5318701e40f1a798ca04cd1d3a63..f7f4bd4689a3b160d27bc28e54a8c9a0e12e81cc 100644 (file)
@@ -43,16 +43,16 @@ OPTIONS
 -n::
 --no-commit::
        Usually the command automatically creates a commit with
-       a commit log message stating which commit was reverted.
-       This flag applies the change necessary to revert the
-       named commit to your working tree, but does not make the
-       commit.  In addition, when this option is used, your
-       working tree does not have to match the HEAD commit.
-       The revert is done against the beginning state of your
-       working tree.
+       a commit log message stating which commit was
+       reverted.  This flag applies the change necessary
+       to revert the named commit to your working tree
+       and the index, but does not make the commit.  In addition,
+       when this option is used, your index does not have to match
+       the HEAD commit.  The revert is done against the
+       beginning state of your index.
 +
 This is useful when reverting more than one commits'
-effect to your working tree in a row.
+effect to your index in a row.
 
 -s::
 --signoff::
index 0d6fe9cf79a5d6c65d3c94cb237cf85ccade2aef..33ae79b9d559b80816b9c26af389a0be6de41162 100644 (file)
@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.5.6.2/git.html[documentation for release 1.5.6.2]
+* link:v1.5.6.3/git.html[documentation for release 1.5.6.3]
 
 * release notes for
+  link:RelNotes-1.5.6.3.txt[1.5.6.3].
   link:RelNotes-1.5.6.2.txt[1.5.6.2].
   link:RelNotes-1.5.6.1.txt[1.5.6.1].
   link:RelNotes-1.5.6.txt[1.5.6].
diff --git a/attr.c b/attr.c
index 0fb47d34346ca96addde5cb3722fa5e586057285..17f6a4dca521d9690377f2e93a0192d8a874d2ad 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -459,7 +459,9 @@ static void prepare_attr_stack(const char *path, int dirlen)
 {
        struct attr_stack *elem, *info;
        int len;
-       char pathbuf[PATH_MAX];
+       struct strbuf pathbuf;
+
+       strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));
 
        /*
         * At the bottom of the attribute stack is the built-in
@@ -510,13 +512,14 @@ static void prepare_attr_stack(const char *path, int dirlen)
                        len = strlen(attr_stack->origin);
                        if (dirlen <= len)
                                break;
-                       memcpy(pathbuf, path, dirlen);
-                       memcpy(pathbuf + dirlen, "/", 2);
-                       cp = strchr(pathbuf + len + 1, '/');
+                       strbuf_reset(&pathbuf);
+                       strbuf_add(&pathbuf, path, dirlen);
+                       strbuf_addch(&pathbuf, '/');
+                       cp = strchr(pathbuf.buf + len + 1, '/');
                        strcpy(cp + 1, GITATTRIBUTES_FILE);
-                       elem = read_attr(pathbuf, 0);
+                       elem = read_attr(pathbuf.buf, 0);
                        *cp = '\0';
-                       elem->origin = strdup(pathbuf);
+                       elem->origin = strdup(pathbuf.buf);
                        elem->prev = attr_stack;
                        attr_stack = elem;
                        debug_push(elem);
index ef299108f529fa5fa931d765828f04535c3a6351..647535061c350b68f1583fc12b049a37eb17481c 100644 (file)
@@ -427,33 +427,35 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
        struct name_entry entry;
        char *down;
        int tn_len = strlen(tree_name);
-       char *path_buf = xmalloc(PATH_MAX + tn_len + 100);
+       struct strbuf pathbuf;
+
+       strbuf_init(&pathbuf, PATH_MAX + tn_len);
 
        if (tn_len) {
-               tn_len = sprintf(path_buf, "%s:", tree_name);
-               down = path_buf + tn_len;
-               strcat(down, base);
-       }
-       else {
-               down = path_buf;
-               strcpy(down, base);
+               strbuf_add(&pathbuf, tree_name, tn_len);
+               strbuf_addch(&pathbuf, ':');
+               tn_len = pathbuf.len;
        }
-       len = strlen(path_buf);
+       strbuf_addstr(&pathbuf, base);
+       len = pathbuf.len;
 
        while (tree_entry(tree, &entry)) {
-               strcpy(path_buf + len, entry.path);
+               int te_len = tree_entry_len(entry.path, entry.sha1);
+               pathbuf.len = len;
+               strbuf_add(&pathbuf, entry.path, te_len);
 
                if (S_ISDIR(entry.mode))
                        /* Match "abc/" against pathspec to
                         * decide if we want to descend into "abc"
                         * directory.
                         */
-                       strcpy(path_buf + len + tree_entry_len(entry.path, entry.sha1), "/");
+                       strbuf_addch(&pathbuf, '/');
 
+               down = pathbuf.buf + tn_len;
                if (!pathspec_matches(paths, down))
                        ;
                else if (S_ISREG(entry.mode))
-                       hit |= grep_sha1(opt, entry.sha1, path_buf, tn_len);
+                       hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
                else if (S_ISDIR(entry.mode)) {
                        enum object_type type;
                        struct tree_desc sub;
@@ -469,6 +471,7 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
                        free(data);
                }
        }
+       strbuf_release(&pathbuf);
        return hit;
 }
 
index fa6e8f90a4d54eb07f2af80620e35e617c94d605..13f0502b9e0bca9e4119896c01786b99cc54441e 100644 (file)
@@ -334,7 +334,9 @@ static int check_header(char *line, unsigned linesize, char **hdr_data, int over
                return 1;
        if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
                for (i = 0; header[i]; i++) {
-                       if (!memcmp("Subject: ", header[i], 9)) {
+                       if (!memcmp("Subject", header[i], 7)) {
+                               if (!hdr_data[i])
+                                       hdr_data[i] = xmalloc(linesize + 20);
                                if (! handle_header(line, hdr_data[i], 0)) {
                                        return 1;
                                }
@@ -960,7 +962,7 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
 }
 
 static const char mailinfo_usage[] =
-       "git-mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info";
+       "git-mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info";
 
 int cmd_mailinfo(int argc, const char **argv, const char *prefix)
 {
index 63cd12cd9c1909edbaab49aea066ff6fe03c3542..ce3a6f58f3c5c6bb88617510422c4053e0d545a2 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -694,23 +694,47 @@ static void kill_some_children(int signo, unsigned start, unsigned stop)
        }
 }
 
+static void check_dead_children(void)
+{
+       unsigned spawned, reaped, deleted;
+
+       spawned = children_spawned;
+       reaped = children_reaped;
+       deleted = children_deleted;
+
+       while (deleted < reaped) {
+               pid_t pid = dead_child[deleted % MAX_CHILDREN];
+               const char *dead = pid < 0 ? " (with error)" : "";
+
+               if (pid < 0)
+                       pid = -pid;
+
+               /* XXX: Custom logging, since we don't wanna getpid() */
+               if (verbose) {
+                       if (log_syslog)
+                               syslog(LOG_INFO, "[%d] Disconnected%s",
+                                               pid, dead);
+                       else
+                               fprintf(stderr, "[%d] Disconnected%s\n",
+                                               pid, dead);
+               }
+               remove_child(pid, deleted, spawned);
+               deleted++;
+       }
+       children_deleted = deleted;
+}
+
 static void check_max_connections(void)
 {
        for (;;) {
                int active;
-               unsigned spawned, reaped, deleted;
+               unsigned spawned, deleted;
+
+               check_dead_children();
 
                spawned = children_spawned;
-               reaped = children_reaped;
                deleted = children_deleted;
 
-               while (deleted < reaped) {
-                       pid_t pid = dead_child[deleted % MAX_CHILDREN];
-                       remove_child(pid, deleted, spawned);
-                       deleted++;
-               }
-               children_deleted = deleted;
-
                active = spawned - deleted;
                if (active <= max_connections)
                        break;
@@ -760,18 +784,10 @@ static void child_handler(int signo)
 
                if (pid > 0) {
                        unsigned reaped = children_reaped;
+                       if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
+                               pid = -pid;
                        dead_child[reaped % MAX_CHILDREN] = pid;
                        children_reaped = reaped + 1;
-                       /* XXX: Custom logging, since we don't wanna getpid() */
-                       if (verbose) {
-                               const char *dead = "";
-                               if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
-                                       dead = " (with error)";
-                               if (log_syslog)
-                                       syslog(LOG_INFO, "[%d] Disconnected%s", pid, dead);
-                               else
-                                       fprintf(stderr, "[%d] Disconnected%s\n", pid, dead);
-                       }
                        continue;
                }
                break;
@@ -928,8 +944,18 @@ static int service_loop(int socknum, int *socklist)
 
        for (;;) {
                int i;
+               int timeout;
 
-               if (poll(pfd, socknum, -1) < 0) {
+               /*
+                * This 1-sec timeout could lead to idly looping but it is
+                * here so that children culled in child_handler() are reported
+                * without too much delay.  We could probably set up a pipe
+                * to ourselves that we poll, and write to the fd from child_handler()
+                * to wake us up (and consume it when the poll() returns...
+                */
+               timeout = (children_spawned != children_deleted) ? 1000 : -1;
+               i = poll(pfd, socknum, timeout);
+               if (i < 0) {
                        if (errno != EINTR) {
                                error("poll failed, resuming: %s",
                                      strerror(errno));
@@ -937,6 +963,10 @@ static int service_loop(int socknum, int *socklist)
                        }
                        continue;
                }
+               if (i == 0) {
+                       check_dead_children();
+                       continue;
+               }
 
                for (i = 0; i < socknum; i++) {
                        if (pfd[i].revents & POLLIN) {
index b17722d66a7008b822125bb96ab1b7921e8b627b..e7eaff9a68ccbcc692522c9956f0dae9af45f3f1 100644 (file)
@@ -171,7 +171,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                        if (silent_on_removed)
                                continue;
                        diff_addremove(&revs->diffopt, '-', ce->ce_mode,
-                                      ce->sha1, ce->name, NULL);
+                                      ce->sha1, ce->name);
                        continue;
                }
                changed = ce_match_stat(ce, &st, ce_option);
@@ -184,7 +184,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                newmode = ce_mode_from_stat(ce, st.st_mode);
                diff_change(&revs->diffopt, oldmode, newmode,
                            ce->sha1, (changed ? null_sha1 : ce->sha1),
-                           ce->name, NULL);
+                           ce->name);
 
        }
        diffcore_std(&revs->diffopt);
@@ -208,7 +208,7 @@ static void diff_index_show_file(struct rev_info *revs,
                                 const unsigned char *sha1, unsigned int mode)
 {
        diff_addremove(&revs->diffopt, prefix[0], mode,
-                      sha1, ce->name, NULL);
+                      sha1, ce->name);
 }
 
 static int get_stat_data(struct cache_entry *ce,
@@ -312,7 +312,7 @@ static int show_modified(struct oneway_unpack_data *cbdata,
                return 0;
 
        diff_change(&revs->diffopt, oldmode, mode,
-                   old->sha1, sha1, old->name, NULL);
+                   old->sha1, sha1, old->name);
        return 0;
 }
 
diff --git a/diff.c b/diff.c
index 78c4d3a35a975d0ffef51dbe999d14938d0a90e3..386de826d3a050e5dfce55636fc2e65129b6da2b 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -3356,9 +3356,8 @@ int diff_result_code(struct diff_options *opt, int status)
 void diff_addremove(struct diff_options *options,
                    int addremove, unsigned mode,
                    const unsigned char *sha1,
-                   const char *base, const char *path)
+                   const char *concatpath)
 {
-       char concatpath[PATH_MAX];
        struct diff_filespec *one, *two;
 
        if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode))
@@ -3380,9 +3379,6 @@ void diff_addremove(struct diff_options *options,
                addremove = (addremove == '+' ? '-' :
                             addremove == '-' ? '+' : addremove);
 
-       if (!path) path = "";
-       sprintf(concatpath, "%s%s", base, path);
-
        if (options->prefix &&
            strncmp(concatpath, options->prefix, options->prefix_length))
                return;
@@ -3403,9 +3399,8 @@ void diff_change(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
                 const unsigned char *old_sha1,
                 const unsigned char *new_sha1,
-                const char *base, const char *path)
+                const char *concatpath)
 {
-       char concatpath[PATH_MAX];
        struct diff_filespec *one, *two;
 
        if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode)
@@ -3418,8 +3413,6 @@ void diff_change(struct diff_options *options,
                tmp = old_mode; old_mode = new_mode; new_mode = tmp;
                tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
        }
-       if (!path) path = "";
-       sprintf(concatpath, "%s%s", base, path);
 
        if (options->prefix &&
            strncmp(concatpath, options->prefix, options->prefix_length))
diff --git a/diff.h b/diff.h
index 5dc0cb595b64868ca8b8e26e5311d2df102c89e0..50fb5ddb0bec02b0cd5498d6ecc37d44bf874476 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -14,12 +14,12 @@ typedef void (*change_fn_t)(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
                 const unsigned char *old_sha1,
                 const unsigned char *new_sha1,
-                const char *base, const char *path);
+                const char *fullpath);
 
 typedef void (*add_remove_fn_t)(struct diff_options *options,
                    int addremove, unsigned mode,
                    const unsigned char *sha1,
-                   const char *base, const char *path);
+                   const char *fullpath);
 
 typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
                struct diff_options *options, void *data);
@@ -164,14 +164,13 @@ extern void diff_addremove(struct diff_options *,
                           int addremove,
                           unsigned mode,
                           const unsigned char *sha1,
-                          const char *base,
-                          const char *path);
+                          const char *fullpath);
 
 extern void diff_change(struct diff_options *,
                        unsigned mode1, unsigned mode2,
                        const unsigned char *sha1,
                        const unsigned char *sha2,
-                       const char *base, const char *path);
+                       const char *fullpath);
 
 extern void diff_unmerge(struct diff_options *,
                         const char *path,
index 2c517ede590c5c3274b03d1c980f9a847cc7d643..83b277acfdeafa1f745c3c96bc10eef320a2d6ec 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -30,7 +30,8 @@ set_reflog_action am
 require_work_tree
 cd_to_toplevel
 
-git var GIT_COMMITTER_IDENT >/dev/null || exit
+git var GIT_COMMITTER_IDENT >/dev/null ||
+       die "You need to set your committer info first"
 
 stop_here () {
     echo "$1" >"$dotest/next"
index 920bbe15a3bbc7768d47a2adbc84aa81264e2226..b00d1c29cd3a7d2cd8bbcd7ea4f531e050fcfcb9 100755 (executable)
@@ -1884,7 +1884,7 @@ sub req_annotate
     }
 
     # done; get out of the tempdir
-    cleanupWorkDir();
+    cleanupWorkTree();
 
     print "ok\n";
 
index a64d9d57ab5943ac4e065866ce0ccd7de5364a9a..e3f65bd8808112aebf98f554bd24df38a5e6408c 100755 (executable)
@@ -162,6 +162,8 @@ pick_one_preserving_merges () {
                                new_parents="$new_parents $new_p"
                                ;;
                        esac
+               else
+                       new_parents="$new_parents $p"
                fi
        done
        case $fast_forward in
diff --git a/path.c b/path.c
index 6e3df1849965be6a88fac89c007f9b5fe960f825..c1d567996d225c03f58c1208f4806f74f64e92e1 100644 (file)
--- a/path.c
+++ b/path.c
@@ -272,7 +272,7 @@ int adjust_shared_perm(const char *path)
                int tweak = shared_repository;
                if (!(mode & S_IWUSR))
                        tweak &= ~0222;
-               mode = (mode & ~0777) | tweak;
+               mode |= tweak;
        } else {
                /* Preserve old PERM_UMASK behaviour */
                if (mode & S_IWUSR)
index fc667552592daa3c894d0df4e97469d1809dbf27..8dc3ca7bf696c14ad73f4ebe0fe845cba298c20e 100644 (file)
@@ -259,7 +259,7 @@ static int tree_difference = REV_TREE_SAME;
 static void file_add_remove(struct diff_options *options,
                    int addremove, unsigned mode,
                    const unsigned char *sha1,
-                   const char *base, const char *path)
+                   const char *fullpath)
 {
        int diff = REV_TREE_DIFFERENT;
 
@@ -285,7 +285,7 @@ static void file_change(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
                 const unsigned char *old_sha1,
                 const unsigned char *new_sha1,
-                const char *base, const char *path)
+                const char *fullpath)
 {
        tree_difference = REV_TREE_DIFFERENT;
        DIFF_OPT_SET(options, HAS_CHANGES);
index d1c406081e29eab9843a5268b611af1a3e014227..10346b681e3575d17945f64513e2b0fecbcc01fc 100644 (file)
@@ -1609,6 +1609,7 @@ static void *unpack_delta_entry(struct packed_git *p,
        off_t base_offset;
 
        base_offset = get_delta_base(p, w_curs, &curpos, *type, obj_offset);
+       unuse_pack(w_curs);
        base = cache_or_unpack_entry(p, base_offset, &base_size, type, 0);
        if (!base)
                die("failed to read delta base object"
index 9255c63c08f06399525ca098d0374ad7d197e0b7..63e1217e7162435c3da8ec7984b5f6a53b3a10e2 100755 (executable)
@@ -8,6 +8,7 @@ test_expect_success setup '
 
        >file &&
        git add file &&
+       test_tick &&
        git commit -m initial &&
        echo >file &&
        git add file
@@ -17,11 +18,11 @@ test_expect_success setup '
 test_expect_success 'write-tree should notice unwritable repository' '
 
        (
-               chmod a-w .git/objects
+               chmod a-w .git/objects .git/objects/?? &&
                test_must_fail git write-tree
        )
        status=$?
-       chmod 775 .git/objects
+       chmod 775 .git/objects .git/objects/??
        (exit $status)
 
 '
@@ -29,11 +30,11 @@ test_expect_success 'write-tree should notice unwritable repository' '
 test_expect_success 'commit should notice unwritable repository' '
 
        (
-               chmod a-w .git/objects
+               chmod a-w .git/objects .git/objects/?? &&
                test_must_fail git commit -m second
        )
        status=$?
-       chmod 775 .git/objects
+       chmod 775 .git/objects .git/objects/??
        (exit $status)
 
 '
@@ -41,12 +42,12 @@ test_expect_success 'commit should notice unwritable repository' '
 test_expect_success 'update-index should notice unwritable repository' '
 
        (
-               echo a >file &&
-               chmod a-w .git/objects
+               echo 6O >file &&
+               chmod a-w .git/objects .git/objects/?? &&
                test_must_fail git update-index file
        )
        status=$?
-       chmod 775 .git/objects
+       chmod 775 .git/objects .git/objects/??
        (exit $status)
 
 '
@@ -55,11 +56,11 @@ test_expect_success 'add should notice unwritable repository' '
 
        (
                echo b >file &&
-               chmod a-w .git/objects
+               chmod a-w .git/objects .git/objects/?? &&
                test_must_fail git add file
        )
        status=$?
-       chmod 775 .git/objects
+       chmod 775 .git/objects .git/objects/??
        (exit $status)
 
 '
index 6c78c8bc9b76828c258f524e73b40d7daff7c305..dc85e8b60a5c10e57047d1692e383f177e2c478d 100755 (executable)
@@ -17,6 +17,29 @@ test_expect_success 'shared = 0400 (faulty permission u-w)' '
        test $ret != "0"
 '
 
+for u in 002 022
+do
+       test_expect_success "shared=1 does not clear bits preset by umask $u" '
+               mkdir sub && (
+                       cd sub &&
+                       umask $u &&
+                       git init --shared=1 &&
+                       test 1 = "$(git config core.sharedrepository)"
+               ) &&
+               actual=$(ls -l sub/.git/HEAD)
+               case "$actual" in
+               -rw-rw-r--*)
+                       : happy
+                       ;;
+               *)
+                       echo Oops, .git/HEAD is not 0664 but $actual
+                       false
+                       ;;
+               esac
+       '
+       rm -rf sub
+done
+
 test_expect_success 'shared=all' '
        mkdir sub &&
        cd sub &&
index 577ecc210a55a5da10552a4415c4cbb5e321039b..e9f3e72c7ee5584d956d46126956c641a7d53905 100755 (executable)
@@ -11,7 +11,7 @@ test_expect_success 'split sample box' \
        'git mailsplit -o. ../t5100/sample.mbox >last &&
        last=`cat last` &&
        echo total is $last &&
-       test `cat last` = 9'
+       test `cat last` = 10'
 
 for mail in `echo 00*`
 do
diff --git a/t/t5100/0010 b/t/t5100/0010
new file mode 100644 (file)
index 0000000..f5892c9
--- /dev/null
@@ -0,0 +1,35 @@
+From b9704a518e21158433baa2cc2d591fea687967f6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Lukas=20Sandstr=C3=B6m?= <lukass@etek.chalmers.se>
+Date: Thu, 10 Jul 2008 23:41:33 +0200
+Subject: Re: discussion that lead to this patch
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+[PATCH] git-mailinfo: Fix getting the subject from the body
+
+"Subject: " isn't in the static array "header", and thus
+memcmp("Subject: ", header[i], 7) will never match.
+
+Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
+---
+ builtin-mailinfo.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 962aa34..2d1520f 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -334,7 +334,7 @@ static int check_header(char *line, unsigned linesize, char **hdr_data, int over
+               return 1;
+       if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
+               for (i = 0; header[i]; i++) {
+-                      if (!memcmp("Subject: ", header[i], 9)) {
++                      if (!memcmp("Subject", header[i], 7)) {
+                               if (! handle_header(line, hdr_data[i], 0)) {
+                                       return 1;
+                               }
+-- 
+1.5.6.2.455.g1efb2
+
diff --git a/t/t5100/info0010 b/t/t5100/info0010
new file mode 100644 (file)
index 0000000..1791241
--- /dev/null
@@ -0,0 +1,5 @@
+Author: Lukas Sandström
+Email: lukass@etek.chalmers.se
+Subject: git-mailinfo: Fix getting the subject from the body
+Date: Thu, 10 Jul 2008 23:41:33 +0200
+
diff --git a/t/t5100/msg0010 b/t/t5100/msg0010
new file mode 100644 (file)
index 0000000..a96c230
--- /dev/null
@@ -0,0 +1,5 @@
+"Subject: " isn't in the static array "header", and thus
+memcmp("Subject: ", header[i], 7) will never match.
+
+Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/t/t5100/patch0010 b/t/t5100/patch0010
new file mode 100644 (file)
index 0000000..f055481
--- /dev/null
@@ -0,0 +1,20 @@
+---
+ builtin-mailinfo.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 962aa34..2d1520f 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -334,7 +334,7 @@ static int check_header(char *line, unsigned linesize, char **hdr_data, int over
+               return 1;
+       if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
+               for (i = 0; header[i]; i++) {
+-                      if (!memcmp("Subject: ", header[i], 9)) {
++                      if (!memcmp("Subject", header[i], 7)) {
+                               if (! handle_header(line, hdr_data[i], 0)) {
+                                       return 1;
+                               }
+-- 
+1.5.6.2.455.g1efb2
+
index 0476b96c33de8bbc6c4b3bc4f510e9fc50aa6440..aba57f922b33b6ab708afbbf82c7e56f6e37bb8d 100644 (file)
@@ -430,3 +430,38 @@ index b426a14..97756ec 100644
 =20
 =20
  2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the
+From b9704a518e21158433baa2cc2d591fea687967f6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Lukas=20Sandstr=C3=B6m?= <lukass@etek.chalmers.se>
+Date: Thu, 10 Jul 2008 23:41:33 +0200
+Subject: Re: discussion that lead to this patch
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+[PATCH] git-mailinfo: Fix getting the subject from the body
+
+"Subject: " isn't in the static array "header", and thus
+memcmp("Subject: ", header[i], 7) will never match.
+
+Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
+---
+ builtin-mailinfo.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 962aa34..2d1520f 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -334,7 +334,7 @@ static int check_header(char *line, unsigned linesize, char **hdr_data, int over
+               return 1;
+       if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
+               for (i = 0; header[i]; i++) {
+-                      if (!memcmp("Subject: ", header[i], 9)) {
++                      if (!memcmp("Subject", header[i], 7)) {
+                               if (! handle_header(line, hdr_data[i], 0)) {
+                                       return 1;
+                               }
+-- 
+1.5.6.2.455.g1efb2
+
index d21cd290d3d8e3d912b94045f3d3d9db8bdd7e7d..daf45b7ffa5bc80a4129a7f4b48dce36711d4c87 100755 (executable)
@@ -222,36 +222,12 @@ test_expect_success 'setup' '
 test_debug 'gitk --all'
 
 test_expect_success 'test option parsing' '
-       if git merge -$ c1
-       then
-               echo "[OOPS] -$ accepted"
-               false
-       fi &&
-       if git merge --no-such c1
-       then
-               echo "[OOPS] --no-such accepted"
-               false
-       fi &&
-       if git merge -s foobar c1
-       then
-               echo "[OOPS] -s foobar accepted"
-               false
-       fi &&
-       if git merge -s=foobar c1
-       then
-               echo "[OOPS] -s=foobar accepted"
-               false
-       fi &&
-       if git merge -m
-       then
-               echo "[OOPS] missing commit msg accepted"
-               false
-       fi &&
-       if git merge
-       then
-               echo "[OOPS] missing commit references accepted"
-               false
-       fi
+       test_must_fail git merge -$ c1 &&
+       test_must_fail git merge --no-such c1 &&
+       test_must_fail git merge -s foobar c1 &&
+       test_must_fail git merge -s=foobar c1 &&
+       test_must_fail git merge -m &&
+       test_must_fail git merge
 '
 
 test_expect_success 'merge c0 with c1' '
index e1e2e6c6ce3c4effffb26e9aed7c6bdd2b00a5ae..bbb126fc46cfb28a0bc92cc0842c0dc72017751d 100644 (file)
@@ -15,6 +15,15 @@ static char *malloc_base(const char *base, int baselen, const char *path, int pa
        return newbase;
 }
 
+static char *malloc_fullname(const char *base, int baselen, const char *path, int pathlen)
+{
+       char *fullname = xmalloc(baselen + pathlen + 1);
+       memcpy(fullname, base, baselen);
+       memcpy(fullname + baselen, path, pathlen);
+       fullname[baselen + pathlen] = 0;
+       return fullname;
+}
+
 static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
                       const char *base, int baselen);
 
@@ -24,6 +33,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
        const char *path1, *path2;
        const unsigned char *sha1, *sha2;
        int cmp, pathlen1, pathlen2;
+       char *fullname;
 
        sha1 = tree_entry_extract(t1, &path1, &mode1);
        sha2 = tree_entry_extract(t2, &path2, &mode2);
@@ -55,15 +65,20 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
        if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) {
                int retval;
                char *newbase = malloc_base(base, baselen, path1, pathlen1);
-               if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE))
+               if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
+                       newbase[baselen + pathlen1] = 0;
                        opt->change(opt, mode1, mode2,
-                                   sha1, sha2, base, path1);
+                                   sha1, sha2, newbase);
+                       newbase[baselen + pathlen1] = '/';
+               }
                retval = diff_tree_sha1(sha1, sha2, newbase, opt);
                free(newbase);
                return retval;
        }
 
-       opt->change(opt, mode1, mode2, sha1, sha2, base, path1);
+       fullname = malloc_fullname(base, baselen, path1, pathlen1);
+       opt->change(opt, mode1, mode2, sha1, sha2, fullname);
+       free(fullname);
        return 0;
 }
 
@@ -205,10 +220,10 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
        unsigned mode;
        const char *path;
        const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode);
+       int pathlen = tree_entry_len(path, sha1);
 
        if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) {
                enum object_type type;
-               int pathlen = tree_entry_len(path, sha1);
                char *newbase = malloc_base(base, baselen, path, pathlen);
                struct tree_desc inner;
                void *tree;
@@ -224,7 +239,9 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
                free(tree);
                free(newbase);
        } else {
-               opt->add_remove(opt, prefix[0], mode, sha1, base, path);
+               char *fullname = malloc_fullname(base, baselen, path, pathlen);
+               opt->add_remove(opt, prefix[0], mode, sha1, fullname);
+               free(fullname);
        }
 }