Merge branch 'jc/read-tree'
authorJunio C Hamano <junkio@cox.net>
Tue, 25 Jul 2006 04:01:14 +0000 (21:01 -0700)
committerJunio C Hamano <junkio@cox.net>
Tue, 25 Jul 2006 04:01:14 +0000 (21:01 -0700)
* jc/read-tree:
checkout -f failed to check out a file if an existing directory interfered.

27 files changed:
Documentation/config.txt
Documentation/git-cvsexportcommit.txt
Documentation/git-tar-tree.txt
Makefile
builtin-show-branch.c
builtin-tar-tree.c
cache.h
config.c
contrib/emacs/git.el
diff.c
diff.h
environment.c
git-am.sh
git-cvsexportcommit.perl
git-fetch.sh
git-merge.sh
git-pull.sh
git-quiltimport.sh
git-rebase.sh
git-resolve.sh
git-svn.perl
log-tree.c
pack-objects.c
sha1_file.c
t/t6004-rev-list-path-optim.sh [new file with mode: 0755]
unpack-objects.c
upload-pack.c
index 0b434c1f1923fb10b2420a3295e59fd9d163f39b..465eb13e76dca5cf4daad9d5ea773f4743452c75 100644 (file)
@@ -97,6 +97,12 @@ core.compression::
        compression, and 1..9 are various speed/size tradeoffs, 9 being
        slowest.
 
+core.legacyheaders::
+       A boolean which enables the legacy object header format in case
+       you want to interoperate with old clients accessing the object
+       database directly (where the "http://" and "rsync://" protocols
+       count as direct access).
+
 alias.*::
        Command aliases for the gitlink:git[1] command wrapper - e.g.
        after defining "alias.last = cat-file commit HEAD", the invocation
@@ -193,6 +199,10 @@ merge.summary::
        Whether to include summaries of merged commits in newly created
        merge commit messages. False by default.
 
+pack.window::
+       The size of the window used by gitlink:git-pack-objects[1] when no
+       window size is given on the command line. Defaults to 10.
+
 pull.octopus::
        The default merge strategy to use when pulling multiple branches
        at once.
@@ -208,6 +218,17 @@ showbranch.default::
        The default set of branches for gitlink:git-show-branch[1].
        See gitlink:git-show-branch[1].
 
+tar.umask::
+       By default, git-link:git-tar-tree[1] sets file and directories modes
+       to 0666 or 0777. While this is both useful and acceptable for projects
+       such as the Linux Kernel, it might be excessive for other projects.
+       With this variable, it becomes possible to tell
+       git-link:git-tar-tree[1] to apply a specific umask to the modes above.
+       The special value "user" indicates that the user's current umask will
+       be used. This should be enough for most projects, as it will lead to
+       the same permissions as git-link:git-checkout[1] would use. The default
+       value remains 0, which means world read-write.
+
 user.email::
        Your email address to be recorded in any newly created commits.
        Can be overridden by the 'GIT_AUTHOR_EMAIL' and 'GIT_COMMITTER_EMAIL'
index 27ac72d98fcf8cf2cd0c0ab236e7646ecff7499d..092d0d6730294a5ce701522575bc1f8d91755a1d 100644 (file)
@@ -8,7 +8,7 @@ git-cvsexportcommit - Export a commit to a CVS checkout
 
 SYNOPSIS
 --------
-'git-cvsexportcommit' [-h] [-v] [-c] [-p] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
+'git-cvsexportcommit' [-h] [-v] [-c] [-p] [-a] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
 
 
 DESCRIPTION
@@ -36,9 +36,13 @@ OPTIONS
        commit if any hunks fail to apply or there were other problems.
 
 -p::
-       Be pedantic (paranoid) when applying patches. Invokes patch with 
+       Be pedantic (paranoid) when applying patches. Invokes patch with
        --fuzz=0
 
+-a::
+       Add authorship information. Adds Author line, and Committer (if
+       different from Author) to the message.
+
 -f::
        Force the merge even if the files are not up to date.
 
index f2675c41933fc4f824f871cc9185a6a1bf010d2b..7a99acf2ec92f9bbab84b664d10bb442482c4911 100644 (file)
@@ -37,7 +37,20 @@ OPTIONS
        Instead of making a tar archive from local repository,
        retrieve a tar archive from a remote repository.
 
-Examples
+CONFIGURATION
+-------------
+By default, file and directories modes are set to 0666 or 0777. It is
+possible to change this by setting the "umask" variable in the
+repository configuration as follows :
+
+[tar]
+        umask = 002    ;# group friendly
+
+The special umask value "user" indicates that the user's current umask
+will be used instead. The default value remains 0, which means world
+readable/writable files and directories.
+
+EXAMPLES
 --------
 git tar-tree HEAD junk | (cd /var/tmp/ && tar xf -)::
 
index 01fb9cfdbd2bc8c53366d1db6f9b7b7525823fa5..3e085dfa6fbabf1bcf758b795f32ea50a40880c2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -37,6 +37,18 @@ all:
 # tests.  These tests take up a significant amount of the total test time
 # but are not needed unless you plan to talk to SVN repos.
 #
+# Define NO_FINK if you are building on Darwin/Mac OS X, have Fink
+# installed in /sw, but don't want GIT to link against any libraries
+# installed there.  If defined you may specify your own (or Fink's)
+# include directories and library directories by defining CFLAGS
+# and LDFLAGS appropriately.
+#
+# Define NO_DARWIN_PORTS if you are building on Darwin/Mac OS X,
+# have DarwinPorts installed in /opt/local, but don't want GIT to
+# link against any libraries installed there.  If defined you may
+# specify your own (or DarwinPort's) include directories and
+# library directories by defining CFLAGS and LDFLAGS appropriately.
+#
 # Define PPC_SHA1 environment variable when running make to make use of
 # a bundled SHA1 routine optimized for PowerPC.
 #
@@ -254,15 +266,17 @@ ifeq ($(uname_S),Darwin)
        NEEDS_SSL_WITH_CRYPTO = YesPlease
        NEEDS_LIBICONV = YesPlease
        NO_STRLCPY = YesPlease
-       ## fink
-       ifeq ($(shell test -d /sw/lib && echo y),y)
-               ALL_CFLAGS += -I/sw/include
-               ALL_LDFLAGS += -L/sw/lib
+       ifndef NO_FINK
+               ifeq ($(shell test -d /sw/lib && echo y),y)
+                       ALL_CFLAGS += -I/sw/include
+                       ALL_LDFLAGS += -L/sw/lib
+               endif
        endif
-       ## darwinports
-       ifeq ($(shell test -d /opt/local/lib && echo y),y)
-               ALL_CFLAGS += -I/opt/local/include
-               ALL_LDFLAGS += -L/opt/local/lib
+       ifndef NO_DARWIN_PORTS
+               ifeq ($(shell test -d /opt/local/lib && echo y),y)
+                       ALL_CFLAGS += -I/opt/local/include
+                       ALL_LDFLAGS += -L/opt/local/lib
+               endif
        endif
 endif
 ifeq ($(uname_S),SunOS)
index 3d240ca435e3079530dd3515ce78bd20858e3a6f..82f75b72dea1a5e6c620003d5c0c4c414dfe42e3 100644 (file)
@@ -89,6 +89,8 @@ static int name_first_parent_chain(struct commit *c)
                        name_parent(c, p);
                        i++;
                }
+               else
+                       break;
                c = p;
        }
        return i;
index f2e48aae2a04822d26d255dddf36002f58f2093c..e5aaded820bddfe2d5175508cc9c422b55a66eec 100644 (file)
@@ -20,6 +20,7 @@ static char block[BLOCKSIZE];
 static unsigned long offset;
 
 static time_t archive_time;
+static int tar_umask;
 
 /* tries hard to write, either succeeds or dies in the attempt */
 static void reliable_write(const void *data, unsigned long size)
@@ -188,13 +189,13 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
        } else {
                if (S_ISDIR(mode)) {
                        *header.typeflag = TYPEFLAG_DIR;
-                       mode |= 0777;
+                       mode = (mode | 0777) & ~tar_umask;
                } else if (S_ISLNK(mode)) {
                        *header.typeflag = TYPEFLAG_LNK;
                        mode |= 0777;
                } else if (S_ISREG(mode)) {
                        *header.typeflag = TYPEFLAG_REG;
-                       mode |= (mode & 0100) ? 0777 : 0666;
+                       mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask;
                } else {
                        error("unsupported file mode: 0%o (SHA1: %s)",
                              mode, sha1_to_hex(sha1));
@@ -293,6 +294,20 @@ static void traverse_tree(struct tree_desc *tree, struct strbuf *path)
        }
 }
 
+int git_tar_config(const char *var, const char *value)
+{
+       if (!strcmp(var, "tar.umask")) {
+               if (!strcmp(value, "user")) {
+                       tar_umask = umask(0);
+                       umask(tar_umask);
+               } else {
+                       tar_umask = git_config_int(var, value);
+               }
+               return 0;
+       }
+       return git_default_config(var, value);
+}
+
 static int generate_tar(int argc, const char **argv, char** envp)
 {
        unsigned char sha1[20], tree_sha1[20];
@@ -305,7 +320,7 @@ static int generate_tar(int argc, const char **argv, char** envp)
        current_path.len = current_path.eof = 0;
 
        setup_git_directory();
-       git_config(git_default_config);
+       git_config(git_tar_config);
 
        switch (argc) {
        case 3:
diff --git a/cache.h b/cache.h
index d433d46f23c956aa13b9f0d97344f792234e94ab..eee5fc9f8d75af20a1d03d569c702980f6c04469 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -176,6 +176,7 @@ extern int commit_lock_file(struct lock_file *);
 extern void rollback_lock_file(struct lock_file *);
 
 /* Environment bits from configuration mechanism */
+extern int use_legacy_headers;
 extern int trust_executable_bit;
 extern int assume_unchanged;
 extern int prefer_symlink_refs;
index 8445f7dcab3bdf96326b8d6a3e1b8c8a8161cb23..0ac6aebbbcbd666d5bd8201ce28e1868bd6d5a30 100644 (file)
--- a/config.c
+++ b/config.c
@@ -279,6 +279,11 @@ int git_default_config(const char *var, const char *value)
                return 0;
        }
 
+       if (!strcmp(var, "core.legacyheaders")) {
+               use_legacy_headers = git_config_bool(var, value);
+               return 0;
+       }
+
        if (!strcmp(var, "core.compression")) {
                int level = git_config_int(var, value);
                if (level == -1)
index 34c995046d8cd783cf165e8d2e40cb0d11f85f59..68de9be0c7cca8645275a042900766b6ea2712c7 100644 (file)
@@ -55,7 +55,8 @@
 ;;;; ------------------------------------------------------------
 
 (defgroup git nil
-  "Git user interface")
+  "A user interface for the git versioning system."
+  :group 'tools)
 
 (defcustom git-committer-name nil
   "User name to use for commits.
@@ -83,6 +84,12 @@ then to `add-log-mailing-address' and then to `user-mail-address'."
   :group 'git
   :type 'boolean)
 
+(defcustom git-reuse-status-buffer t
+  "Whether `git-status' should try to reuse an existing buffer
+if there is already one that displays the same directory."
+  :group 'git
+  :type 'boolean)
+
 (defcustom git-per-dir-ignore-file ".gitignore"
   "Name of the per-directory ignore file."
   :group 'git
@@ -258,7 +265,7 @@ and returns the process output as a string."
     (set-buffer (find-file-noselect ignore-name))
     (goto-char (point-max))
     (unless (zerop (current-column)) (insert "\n"))
-    (insert name "\n")
+    (insert "/" name "\n")
     (sort-lines nil (point-min) (point-max))
     (save-buffer))
   (when created
@@ -584,6 +591,8 @@ and returns the process output as a string."
                             (condition-case nil (delete-file ".git/MERGE_HEAD") (error nil))
                             (with-current-buffer buffer (erase-buffer))
                             (git-set-files-state files 'uptodate)
+                            (when (file-directory-p ".git/rr-cache")
+                              (git-run-command nil nil "rerere"))
                             (git-refresh-files)
                             (git-refresh-ewoc-hf git-status)
                             (message "Committed %s." commit))
@@ -1001,12 +1010,28 @@ Commands:
   (set (make-local-variable 'list-buffers-directory) default-directory)
   (run-hooks 'git-status-mode-hook)))
 
+(defun git-find-status-buffer (dir)
+  "Find the git status buffer handling a specified directory."
+  (let ((list (buffer-list))
+        (fulldir (expand-file-name dir))
+        found)
+    (while (and list (not found))
+      (let ((buffer (car list)))
+        (with-current-buffer buffer
+          (when (and list-buffers-directory
+                     (string-equal fulldir (expand-file-name list-buffers-directory))
+                     (string-match "\\*git-status\\*$" (buffer-name buffer)))
+            (setq found buffer))))
+      (setq list (cdr list)))
+    found))
+
 (defun git-status (dir)
   "Entry point into git-status mode."
   (interactive "DSelect directory: ")
   (setq dir (git-get-top-dir dir))
   (if (file-directory-p (concat (file-name-as-directory dir) ".git"))
-      (let ((buffer (create-file-buffer (expand-file-name "*git-status*" dir))))
+      (let ((buffer (or (and git-reuse-status-buffer (git-find-status-buffer dir))
+                        (create-file-buffer (expand-file-name "*git-status*" dir)))))
         (switch-to-buffer buffer)
         (cd dir)
         (git-status-mode)
diff --git a/diff.c b/diff.c
index 8b44756136dbb040c7c82e07ca535be0b66ffb30..6a713764831e7521958f4b280f2e1d3911fb3cea 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -17,15 +17,6 @@ static int diff_detect_rename_default = 0;
 static int diff_rename_limit_default = -1;
 static int diff_use_color_default = 0;
 
-enum color_diff {
-       DIFF_RESET = 0,
-       DIFF_PLAIN = 1,
-       DIFF_METAINFO = 2,
-       DIFF_FRAGINFO = 3,
-       DIFF_FILE_OLD = 4,
-       DIFF_FILE_NEW = 5,
-};
-
 /* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
 static char diff_colors[][24] = {
        "\033[m",       /* reset */
@@ -33,7 +24,8 @@ static char diff_colors[][24] = {
        "\033[1m",      /* bold */
        "\033[36m",     /* cyan */
        "\033[31m",     /* red */
-       "\033[32m"      /* green */
+       "\033[32m",     /* green */
+       "\033[33m"      /* yellow */
 };
 
 static int parse_diff_color_slot(const char *var, int ofs)
@@ -48,6 +40,8 @@ static int parse_diff_color_slot(const char *var, int ofs)
                return DIFF_FILE_OLD;
        if (!strcasecmp(var+ofs, "new"))
                return DIFF_FILE_NEW;
+       if (!strcasecmp(var+ofs, "commit"))
+               return DIFF_COMMIT;
        die("bad config variable '%s'", var);
 }
 
@@ -370,7 +364,7 @@ struct emit_callback {
        const char **label_path;
 };
 
-static inline const char *get_color(int diff_use_color, enum color_diff ix)
+const char *diff_get_color(int diff_use_color, enum color_diff ix)
 {
        if (diff_use_color)
                return diff_colors[ix];
@@ -381,8 +375,8 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
 {
        int i;
        struct emit_callback *ecbdata = priv;
-       const char *set = get_color(ecbdata->color_diff, DIFF_METAINFO);
-       const char *reset = get_color(ecbdata->color_diff, DIFF_RESET);
+       const char *set = diff_get_color(ecbdata->color_diff, DIFF_METAINFO);
+       const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
 
        if (ecbdata->label_path[0]) {
                printf("%s--- %s%s\n", set, ecbdata->label_path[0], reset);
@@ -397,7 +391,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                ;
        if (2 <= i && i < len && line[i] == ' ') {
                ecbdata->nparents = i - 1;
-               set = get_color(ecbdata->color_diff, DIFF_FRAGINFO);
+               set = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO);
        }
        else if (len < ecbdata->nparents)
                set = reset;
@@ -410,7 +404,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                        else if (line[i] == '+')
                                color = DIFF_FILE_NEW;
                }
-               set = get_color(ecbdata->color_diff, color);
+               set = diff_get_color(ecbdata->color_diff, color);
        }
        if (len > 0 && line[len-1] == '\n')
                len--;
@@ -767,8 +761,8 @@ static void builtin_diff(const char *name_a,
        mmfile_t mf1, mf2;
        const char *lbl[2];
        char *a_one, *b_two;
-       const char *set = get_color(o->color_diff, DIFF_METAINFO);
-       const char *reset = get_color(o->color_diff, DIFF_RESET);
+       const char *set = diff_get_color(o->color_diff, DIFF_METAINFO);
+       const char *reset = diff_get_color(o->color_diff, DIFF_RESET);
 
        a_one = quote_two("a/", name_a);
        b_two = quote_two("b/", name_b);
diff --git a/diff.h b/diff.h
index a06f959938d1313e45daa610a1f3eb71b4c3f835..2cced530fa60ad7206b2cdb1b2509f42469e8f73 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -69,6 +69,17 @@ struct diff_options {
        add_remove_fn_t add_remove;
 };
 
+enum color_diff {
+       DIFF_RESET = 0,
+       DIFF_PLAIN = 1,
+       DIFF_METAINFO = 2,
+       DIFF_FRAGINFO = 3,
+       DIFF_FILE_OLD = 4,
+       DIFF_FILE_NEW = 5,
+       DIFF_COMMIT = 6,
+};
+const char *diff_get_color(int diff_use_color, enum color_diff ix);
+
 extern const char mime_boundary_leader[];
 
 extern void diff_tree_setup_paths(const char **paths, struct diff_options *);
index 97d42b172be5abbada30da97893c77e67a0bcde0..42f39d657ef0056667bb8814622e0dde2733e373 100644 (file)
@@ -11,6 +11,7 @@
 
 char git_default_email[MAX_GITNAME];
 char git_default_name[MAX_GITNAME];
+int use_legacy_headers = 1;
 int trust_executable_bit = 1;
 int assume_unchanged = 0;
 int prefer_symlink_refs = 0;
index db9a20a811199666fb64f34f1e54e0c841f494ee..04f01194356ea0c91a01eed682b068c15e313ee6 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -91,6 +91,7 @@ fall_back_3way () {
 }
 
 prec=4
+rloga=am
 dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary= ws= resolvemsg=
 
 while case "$#" in 0) break;; esac
@@ -130,6 +131,9 @@ do
        --resolvemsg=*)
        resolvemsg=$(echo "$1" | sed -e "s/^--resolvemsg=//"); shift ;;
 
+       --reflog-action=*)
+       rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`; shift ;;
+
        --)
        shift; break ;;
        -*)
@@ -152,8 +156,10 @@ fi
 
 if test -d "$dotest"
 then
-       test ",$#," = ",0," ||
-       die "previous dotest directory $dotest still exists but mbox given."
+       if test ",$#," != ",0," || ! tty -s
+       then
+               die "previous dotest directory $dotest still exists but mbox given."
+       fi
        resume=yes
 else
        # Make sure we are not given --skip nor --resolved
@@ -413,7 +419,7 @@ do
        parent=$(git-rev-parse --verify HEAD) &&
        commit=$(git-commit-tree $tree -p $parent <"$dotest/final-commit") &&
        echo Committed: $commit &&
-       git-update-ref -m "am: $SUBJECT" HEAD $commit $parent ||
+       git-update-ref -m "$rloga: $SUBJECT" HEAD $commit $parent ||
        stop_here $this
 
        if test -x "$GIT_DIR"/hooks/post-applypatch
index 5d13a54194d23ceaa50bc52a4f192156898d661a..99b3dc392afdd5ffb3e2aa8f6fe6b484c2e2f1fe 100755 (executable)
@@ -16,9 +16,9 @@
     die "GIT_DIR is not defined or is unreadable";
 }
 
-our ($opt_h, $opt_p, $opt_v, $opt_c, $opt_f, $opt_m );
+our ($opt_h, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m );
 
-getopts('hpvcfm:');
+getopts('hpvcfam:');
 
 $opt_h && usage();
 
@@ -29,7 +29,6 @@
                                     TMPDIR => 1,
                                     CLEANUP => 1);
 
-print Dumper(@ARGV);
 # resolve target commit
 my $commit;
 $commit = pop @ARGV;
 # find parents from the commit itself
 my @commit  = safe_pipe_capture('git-cat-file', 'commit', $commit);
 my @parents;
-foreach my $p (@commit) {
-    if ($p =~ m/^$/) { # end of commit headers, we're done
-       last;
+my $committer;
+my $author;
+my $stage = 'headers'; # headers, msg
+my $title;
+my $msg = '';
+
+foreach my $line (@commit) {
+    chomp $line;
+    if ($stage eq 'headers' && $line eq '') {
+       $stage = 'msg';
+       next;
     }
-    if ($p =~ m/^parent (\w{40})$/) { # found a parent
-       push @parents, $1;
+
+    if ($stage eq 'headers') {
+       if ($line =~ m/^parent (\w{40})$/) { # found a parent
+           push @parents, $1;
+       } elsif ($line =~ m/^author (.+) \d+ \+\d+$/) {
+           $author = $1;
+       } elsif ($line =~ m/^committer (.+) \d+ \+\d+$/) {
+           $committer = $1;
+       }
+    } else {
+       $msg .= $line . "\n";
+       unless ($title) {
+           $title = $line;
+       }
     }
 }
 
 
 # grab the commit message
 open(MSG, ">.msg") or die "Cannot open .msg for writing";
-print MSG $opt_m;
+if ($opt_m) {
+    print MSG $opt_m;
+}
+print MSG $msg;
+if ($opt_a) {
+    print MSG "\n\nAuthor: $author\n";
+    if ($author ne $committer) {
+       print MSG "Committer: $committer\n";
+    }
+}
 close MSG;
 
-`git-cat-file commit $commit | sed -e '1,/^\$/d' >> .msg`;
-$? && die "Error extracting the commit message";
-
 my (@afiles, @dfiles, @mfiles, @dirs);
 my @files = safe_pipe_capture('git-diff-tree', '-r', $parent, $commit);
 #print @files;
 }
 
 print "Commit to CVS\n";
+print "Patch: $title\n";
 my $commitfiles = join(' ', @afiles, @mfiles, @dfiles);
 my $cmd = "cvs commit -F .msg $commitfiles";
 
index ee99280a2ab3abdcc340d66661747968a60c84ec..f7167abdf09c815fc8614b47ded0c6bc4518d6f8 100755 (executable)
@@ -20,6 +20,7 @@ verbose=
 update_head_ok=
 exec=
 upload_pack=
+keep=--thin
 while case "$#" in 0) break ;; esac
 do
        case "$1" in
@@ -69,7 +70,8 @@ case "$#" in
 0)
        test -f "$GIT_DIR/branches/origin" ||
                test -f "$GIT_DIR/remotes/origin" ||
-                       die "Where do you want to fetch from today?"
+                       git-repo-config --get remote.origin.url >/dev/null ||
+                               die "Where do you want to fetch from today?"
        set origin ;;
 esac
 
@@ -347,7 +349,7 @@ fetch_main () {
     ( : subshell because we muck with IFS
       IFS="    $LF"
       (
-         git-fetch-pack $exec $keep --thin "$remote" $rref || echo failed "$remote"
+         git-fetch-pack $exec $keep "$remote" $rref || echo failed "$remote"
       ) |
       while read sha1 remote_name
       do
index 24e3b507ef1f907e7146a2653189f45a92db08fd..a9cfafb1dfba6e85834a33caf6b3c69910594bf6 100755 (executable)
@@ -58,7 +58,13 @@ squash_message () {
 }
 
 finish () {
-       test '' = "$2" || echo "$2"
+       if test '' = "$2"
+       then
+               rlogm="$rloga"
+       else
+               echo "$2"
+               rlogm="$rloga: $2"
+       fi
        case "$squash" in
        t)
                echo "Squash commit -- not updating HEAD"
@@ -70,7 +76,7 @@ finish () {
                        echo "No merge message -- not updating HEAD"
                        ;;
                *)
-                       git-update-ref HEAD "$1" "$head" || exit 1
+                       git-update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1
                        ;;
                esac
                ;;
@@ -88,6 +94,7 @@ finish () {
        esac
 }
 
+rloga=
 while case "$#" in 0) break ;; esac
 do
        case "$1" in
@@ -117,6 +124,9 @@ do
                        die "available strategies are: $all_strategies" ;;
                esac
                ;;
+       --reflog-action=*)
+               rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`
+               ;;
        -*)     usage ;;
        *)      break ;;
        esac
@@ -131,6 +141,7 @@ shift
 
 # All the rest are remote heads
 test "$#" = 0 && usage ;# we need at least one remote head.
+test "$rloga" = '' && rloga="merge: $@"
 
 remoteheads=
 for remote
@@ -316,7 +327,7 @@ if test '' != "$result_tree"
 then
     parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
     result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit
-    finish "$result_commit" "Merge $result_commit, made by $wt_strategy."
+    finish "$result_commit" "Merge made by $wt_strategy."
     dropsave
     exit 0
 fi
index d337bf4da31c8a86eeaee7b34b910611100ccca8..f380437997f053d15a177a941f3b8a1543c56a18 100755 (executable)
@@ -102,5 +102,6 @@ case "$strategy_args" in
 esac
 
 merge_name=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD") || exit
-git-merge $no_summary $no_commit $squash $strategy_args \
+git-merge "--reflog-action=pull $*" \
+       $no_summary $no_commit $squash $strategy_args \
        "$merge_name" HEAD $merge_head
index 364baff80645efb225e433dbf5845e678df60760..10135da3ac04e3175fa45ca26b5ea31605a47284 100755 (executable)
@@ -112,7 +112,7 @@ for patch_name in $(cat "$QUILT_PATCHES/series" | grep -v '^#'); do
                git-apply --index -C1 "$tmp_patch" &&
                tree=$(git-write-tree) &&
                commit=$((echo "$SUBJECT"; echo; cat "$tmp_msg") | git-commit-tree $tree -p $commit) &&
-               git-update-ref HEAD $commit || exit 4
+               git-update-ref -m "quiltimport: $patch_name" HEAD $commit || exit 4
        fi
 done
 rm -rf $tmp_dir || exit 5
index 1b9e986926cf5b7d25afc6e0dc81ff9fc56c370a..29028dd5fc0669cd2d7d3b956bfdd2583cc785b7 100755 (executable)
@@ -131,7 +131,8 @@ do
                        finish_rb_merge
                        exit
                fi
-               git am --resolved --3way --resolvemsg="$RESOLVEMSG"
+               git am --resolved --3way --resolvemsg="$RESOLVEMSG" \
+                       --reflog-action=rebase
                exit
                ;;
        --skip)
@@ -150,7 +151,8 @@ do
                        finish_rb_merge
                        exit
                fi
-               git am -3 --skip --resolvemsg="$RESOLVEMSG"
+               git am -3 --skip --resolvemsg="$RESOLVEMSG" \
+                       --reflog-action=rebase
                exit
                ;;
        --abort)
@@ -288,7 +290,8 @@ fi
 if test -z "$do_merge"
 then
        git-format-patch -k --stdout --full-index "$upstream"..ORIG_HEAD |
-       git am --binary -3 -k --resolvemsg="$RESOLVEMSG"
+       git am --binary -3 -k --resolvemsg="$RESOLVEMSG" \
+               --reflog-action=rebase
        exit $?
 fi
 
index 1c7aaefa2528b73fea3eee22b086b94fa91854c5..a7bc680d90cb503c50d25b15bcaba662c5f5b49e 100755 (executable)
@@ -15,6 +15,7 @@ dropheads() {
 
 head=$(git-rev-parse --verify "$1"^0) &&
 merge=$(git-rev-parse --verify "$2"^0) &&
+merge_name="$2" &&
 merge_msg="$3" || usage
 
 #
@@ -43,7 +44,8 @@ case "$common" in
 "$head")
        echo "Updating from $head to $merge"
        git-read-tree -u -m $head $merge || exit 1
-       git-update-ref HEAD "$merge" "$head"
+       git-update-ref -m "resolve $merge_name: Fast forward" \
+               HEAD "$merge" "$head"
        git-diff-tree -p $head $merge | git-apply --stat
        dropheads
        exit 0
@@ -100,6 +102,7 @@ if [ $? -ne 0 ]; then
 fi
 result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree -p $head -p $merge)
 echo "Committed merge $result_commit"
-git-update-ref HEAD "$result_commit" "$head"
+git-update-ref -m "resolve $merge_name: In-index merge" \
+       HEAD "$result_commit" "$head"
 git-diff-tree -p $head $result_commit | git-apply --stat
 dropheads
index 89ad840dbf46f722cc0be75b3d6b5f0b6dbf051d..6453771f9c2ce27dcecb7bf208cd60feb4881aa3 100755 (executable)
@@ -2709,6 +2709,12 @@ sub libsvn_fetch {
                        } else {
                                die "Unrecognized action: $m, ($f r$rev)\n";
                        }
+               } elsif ($t == $SVN::Node::dir && $m =~ /^[AR]$/) {
+                       my @traversed = ();
+                       libsvn_traverse($gui, '', $f, $rev, \@traversed);
+                       foreach (@traversed) {
+                               push @amr, [ $m, $_ ]
+                       }
                }
                $pool->clear;
        }
@@ -2778,7 +2784,7 @@ sub libsvn_parse_revision {
 }
 
 sub libsvn_traverse {
-       my ($gui, $pfx, $path, $rev) = @_;
+       my ($gui, $pfx, $path, $rev, $files) = @_;
        my $cwd = "$pfx/$path";
        my $pool = SVN::Pool->new;
        $cwd =~ s#^/+##g;
@@ -2786,10 +2792,15 @@ sub libsvn_traverse {
        foreach my $d (keys %$dirent) {
                my $t = $dirent->{$d}->kind;
                if ($t == $SVN::Node::dir) {
-                       libsvn_traverse($gui, $cwd, $d, $rev);
+                       libsvn_traverse($gui, $cwd, $d, $rev, $files);
                } elsif ($t == $SVN::Node::file) {
-                       print "\tA\t$cwd/$d\n" unless $_q;
-                       libsvn_get_file($gui, "$cwd/$d", $rev);
+                       my $file = "$cwd/$d";
+                       if (defined $files) {
+                               push @$files, $file;
+                       } else {
+                               print "\tA\t$file\n" unless $_q;
+                               libsvn_get_file($gui, $file, $rev);
+                       }
                }
        }
        $pool->clear;
@@ -2913,9 +2924,7 @@ sub libsvn_new_tree {
        }
        my ($paths, $rev, $author, $date, $msg) = @_;
        open my $gui, '| git-update-index -z --index-info' or croak $!;
-       my $pool = SVN::Pool->new;
-       libsvn_traverse($gui, '', $SVN_PATH, $rev, $pool);
-       $pool->clear;
+       libsvn_traverse($gui, '', $SVN_PATH, $rev);
        close $gui or croak $?;
        return libsvn_log_entry($rev, $author, $date, $msg);
 }
index 9d8d46fa0038202bd49dee9cf5d1a60f781e5d7d..3a6c84dab559cc0904ba6c339fdb97edba7e7983 100644 (file)
@@ -129,7 +129,8 @@ void show_log(struct rev_info *opt, const char *sep)
                        opt->diffopt.stat_sep = buffer;
                }
        } else {
-               printf("%s%s",
+               printf("%s%s%s",
+                      diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT),
                       opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ",
                       diff_unique_abbrev(commit->object.sha1, abbrev_commit));
                if (opt->parents)
@@ -138,6 +139,8 @@ void show_log(struct rev_info *opt, const char *sep)
                        printf(" (from %s)",
                               diff_unique_abbrev(parent->object.sha1,
                                                  abbrev_commit));
+               printf("%s",
+                      diff_get_color(opt->diffopt.color_diff, DIFF_RESET));
                putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n');
        }
 
index 04a48b925b4db0e302650f7383b5ccbb948665de..861c7f08ff1b68eee141442411b4706a1bcc2518 100644 (file)
@@ -63,6 +63,7 @@ static const char *base_name;
 static unsigned char pack_file_sha1[20];
 static int progress = 1;
 static volatile sig_atomic_t progress_update = 0;
+static int window = 10;
 
 /*
  * The object names in objects array are hashed with this hashtable,
@@ -1216,16 +1217,26 @@ static void setup_progress_signal(void)
        setitimer(ITIMER_REAL, &v, NULL);
 }
 
+static int git_pack_config(const char *k, const char *v)
+{
+       if(!strcmp(k, "pack.window")) {
+               window = git_config_int(k, v);
+               return 0;
+       }
+       return git_default_config(k, v);
+}
+
 int main(int argc, char **argv)
 {
        SHA_CTX ctx;
        char line[40 + 1 + PATH_MAX + 2];
-       int window = 10, depth = 10, pack_to_stdout = 0;
+       int depth = 10, pack_to_stdout = 0;
        struct object_entry **list;
        int num_preferred_base = 0;
        int i;
 
        setup_git_directory();
+       git_config(git_pack_config);
 
        progress = isatty(2);
        for (i = 1; i < argc; i++) {
index e666aec502f1aaadac62c72c152beeab15a8bd8e..43bc2ea0cf039bb9fd02c8313981e85bd7398d33 100644 (file)
@@ -684,26 +684,74 @@ static void *map_sha1_file_internal(const unsigned char *sha1,
        return map;
 }
 
-static int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void *buffer, unsigned long size)
+static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
 {
+       unsigned char c;
+       unsigned int word, bits;
+       unsigned long size;
+       static const char *typename[8] = {
+               NULL,   /* OBJ_EXT */
+               "commit", "tree", "blob", "tag",
+               NULL, NULL, NULL
+       };
+       const char *type;
+
        /* Get the data stream */
        memset(stream, 0, sizeof(*stream));
        stream->next_in = map;
        stream->avail_in = mapsize;
        stream->next_out = buffer;
-       stream->avail_out = size;
+       stream->avail_out = bufsiz;
+
+       /*
+        * Is it a zlib-compressed buffer? If so, the first byte
+        * must be 0x78 (15-bit window size, deflated), and the
+        * first 16-bit word is evenly divisible by 31
+        */
+       word = (map[0] << 8) + map[1];
+       if (map[0] == 0x78 && !(word % 31)) {
+               inflateInit(stream);
+               return inflate(stream, 0);
+       }
+
+       c = *map++;
+       mapsize--;
+       type = typename[(c >> 4) & 7];
+       if (!type)
+               return -1;
+
+       bits = 4;
+       size = c & 0xf;
+       while ((c & 0x80)) {
+               if (bits >= 8*sizeof(long))
+                       return -1;
+               c = *map++;
+               size += (c & 0x7f) << bits;
+               bits += 7;
+               mapsize--;
+       }
 
+       /* Set up the stream for the rest.. */
+       stream->next_in = map;
+       stream->avail_in = mapsize;
        inflateInit(stream);
-       return inflate(stream, 0);
+
+       /* And generate the fake traditional header */
+       stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", type, size);
+       return 0;
 }
 
 static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size)
 {
        int bytes = strlen(buffer) + 1;
        unsigned char *buf = xmalloc(1+size);
+       unsigned long n;
 
-       memcpy(buf, (char *) buffer + bytes, stream->total_out - bytes);
-       bytes = stream->total_out - bytes;
+       n = stream->total_out - bytes;
+       if (n > size)
+               n = size;
+       memcpy(buf, (char *) buffer + bytes, n);
+       bytes = n;
        if (bytes < size) {
                stream->next_out = buf + bytes;
                stream->avail_out = size - bytes;
@@ -1412,6 +1460,49 @@ static int write_buffer(int fd, const void *buf, size_t len)
        return 0;
 }
 
+static int write_binary_header(unsigned char *hdr, enum object_type type, unsigned long len)
+{
+       int hdr_len;
+       unsigned char c;
+
+       c = (type << 4) | (len & 15);
+       len >>= 4;
+       hdr_len = 1;
+       while (len) {
+               *hdr++ = c | 0x80;
+               hdr_len++;
+               c = (len & 0x7f);
+               len >>= 7;
+       }
+       *hdr = c;
+       return hdr_len;
+}
+
+static void setup_object_header(z_stream *stream, const char *type, unsigned long len)
+{
+       int obj_type, hdr;
+
+       if (use_legacy_headers) {
+               while (deflate(stream, 0) == Z_OK)
+                       /* nothing */;
+               return;
+       }
+       if (!strcmp(type, blob_type))
+               obj_type = OBJ_BLOB;
+       else if (!strcmp(type, tree_type))
+               obj_type = OBJ_TREE;
+       else if (!strcmp(type, commit_type))
+               obj_type = OBJ_COMMIT;
+       else if (!strcmp(type, tag_type))
+               obj_type = OBJ_TAG;
+       else
+               die("trying to generate bogus object of type '%s'", type);
+       hdr = write_binary_header(stream->next_out, obj_type, len);
+       stream->total_out = hdr;
+       stream->next_out += hdr;
+       stream->avail_out -= hdr;
+}
+
 int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
 {
        int size;
@@ -1457,7 +1548,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
        /* Set it up */
        memset(&stream, 0, sizeof(stream));
        deflateInit(&stream, zlib_compression_level);
-       size = deflateBound(&stream, len+hdrlen);
+       size = 8 + deflateBound(&stream, len+hdrlen);
        compressed = xmalloc(size);
 
        /* Compress it */
@@ -1467,8 +1558,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
        /* First header.. */
        stream.next_in = hdr;
        stream.avail_in = hdrlen;
-       while (deflate(&stream, 0) == Z_OK)
-               /* nothing */;
+       setup_object_header(&stream, type, len);
 
        /* Then the data itself.. */
        stream.next_in = buf;
diff --git a/t/t6004-rev-list-path-optim.sh b/t/t6004-rev-list-path-optim.sh
new file mode 100755 (executable)
index 0000000..5182dbb
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+test_description='git-rev-list trivial path optimization test'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+echo Hello > a &&
+git add a &&
+git commit -m "Initial commit" a
+'
+
+test_expect_success path-optimization '
+    commit=$(echo "Unchanged tree" | git-commit-tree "HEAD^{tree}" -p HEAD) &&
+    test $(git-rev-list $commit | wc -l) = 2 &&
+    test $(git-rev-list $commit -- . | wc -l) = 1
+'
+
+test_done
index 3b824b04a262b92808ba138b1922badbbb25da89..48c1ee7968cc6b40cb02cd99d35e66630f922041 100644 (file)
@@ -241,11 +241,6 @@ static void unpack_one(unsigned nr, unsigned total)
        }
 }
 
-/*
- * We unpack from the end, older files first. Now, usually
- * there are deltas etc, so we'll not actually write the
- * objects in that order, but we might as well try..
- */
 static void unpack_all(void)
 {
        int i;
index f6f5a7e3db6d45f3f174220fff682cd9fbf0ed72..07ecdb4281cfb32cf16dfc7c46c53e6e8d0247bc 100644 (file)
@@ -182,6 +182,8 @@ static void create_pack_file(void)
                ssize_t sz;
                int pe, pu, pollsize;
 
+               reset_timeout();
+
                pollsize = 0;
                pe = pu = -1;