Merge branch 'lt/diff-tree'
authorJunio C Hamano <junkio@cox.net>
Sat, 11 Feb 2006 02:47:41 +0000 (18:47 -0800)
committerJunio C Hamano <junkio@cox.net>
Sat, 11 Feb 2006 02:47:41 +0000 (18:47 -0800)
* lt/diff-tree:
  combine-diff: Record diff status a bit more faithfully
  find_unique_abbrev() simplification.
  combine-diff: move formatting logic to show_combined_diff()
  combined-diff: use diffcore before intersecting paths.
  diff-tree -c raw output

18 files changed:
Documentation/diff-options.txt
Makefile
commit-tree.c
count-delta.c
delta.h
git-commit.sh
git-status.sh [deleted file]
ident.c
index-pack.c
ls-files.c
pack-check.c
pack.h
patch-delta.c
rev-list.c
sha1_file.c
show-branch.c
t/t6000lib.sh
unpack-objects.c

index 5c85167..2a0275e 100644 (file)
 -C::
        Detect copies as well as renames.
 
+--diff-filter=[ACDMRTUXB*]::
+       Select only files that are Added (`A`), Copied (`C`),
+       Deleted (`D`), Modified (`M`), Renamed (`R`), have their
+       type (mode) changed (`T`), are Unmerged (`U`), are
+       Unknown (`X`), or have had their pairing Broken (`B`).
+       Any combination of the filter characters may be used.
+       When `*` (All-or-none) is added to the combination, all
+       paths are selected if there is any file that matches
+       other criteria in the comparison; if there is no file
+       that matches other criteria, nothing is selected.
+
 --find-copies-harder::
        For performance reasons, by default, -C option finds copies only 
        if the original file of the copy was modified in the same 
index 5c32934..f240e45 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -107,7 +107,7 @@ SCRIPT_SH = \
        git-merge-one-file.sh git-parse-remote.sh \
        git-prune.sh git-pull.sh git-push.sh git-rebase.sh \
        git-repack.sh git-request-pull.sh git-reset.sh \
-       git-resolve.sh git-revert.sh git-sh-setup.sh git-status.sh \
+       git-resolve.sh git-revert.sh git-sh-setup.sh \
        git-tag.sh git-verify-tag.sh git-whatchanged.sh \
        git-applymbox.sh git-applypatch.sh git-am.sh \
        git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
@@ -125,7 +125,7 @@ SCRIPT_PYTHON = \
 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
          $(patsubst %.perl,%,$(SCRIPT_PERL)) \
          $(patsubst %.py,%,$(SCRIPT_PYTHON)) \
-         git-cherry-pick git-show
+         git-cherry-pick git-show git-status
 
 # The ones that do not have to link with lcrypto nor lz.
 SIMPLE_PROGRAMS = \
@@ -443,6 +443,9 @@ git-cherry-pick: git-revert
 git-show: git-whatchanged
        cp $< $@
 
+git-status: git-commit
+       cp $< $@
+
 # These can record GIT_VERSION
 git$X git.spec \
        $(patsubst %.sh,%,$(SCRIPT_SH)) \
index 4634b50..b1c8dca 100644 (file)
@@ -86,13 +86,13 @@ int main(int argc, char **argv)
        unsigned int size;
 
        setup_ident();
+       setup_git_directory();
+
        git_config(git_default_config);
 
        if (argc < 2 || get_sha1_hex(argv[1], tree_sha1) < 0)
                usage(commit_tree_usage);
 
-       setup_git_directory();
-
        check_valid(tree_sha1, "tree");
        for (i = 2; i < argc; i += 2) {
                char *a, *b;
index 7559ff6..058a2aa 100644 (file)
  *
  * Number of bytes that are _not_ copied from the source is deletion,
  * and number of inserted literal bytes are addition, so sum of them
- * is the extent of damage.  xdelta can express an edit that copies
- * data inside of the destination which originally came from the
- * source.  We do not count that in the following routine, so we are
- * undercounting the source material that remains in the final output
- * that way.
+ * is the extent of damage.
  */
 int count_delta(void *delta_buf, unsigned long delta_size,
                unsigned long *src_copied, unsigned long *literal_added)
@@ -50,13 +46,10 @@ int count_delta(void *delta_buf, unsigned long delta_size,
                        if (cmd & 0x08) cp_off |= (*data++ << 24);
                        if (cmd & 0x10) cp_size = *data++;
                        if (cmd & 0x20) cp_size |= (*data++ << 8);
+                       if (cmd & 0x40) cp_size |= (*data++ << 16);
                        if (cp_size == 0) cp_size = 0x10000;
 
-                       if (cmd & 0x40)
-                               /* copy from dst */
-                               ;
-                       else
-                               copied_from_source += cp_size;
+                       copied_from_source += cp_size;
                        out += cp_size;
                } else {
                        /* write literal into dst */
diff --git a/delta.h b/delta.h
index 31d1820..a15350d 100644 (file)
--- a/delta.h
+++ b/delta.h
@@ -19,14 +19,14 @@ extern void *patch_delta(void *src_buf, unsigned long src_size,
 static inline unsigned long get_delta_hdr_size(const unsigned char **datap)
 {
        const unsigned char *data = *datap;
-       unsigned char cmd = *data++;
-       unsigned long size = cmd & ~0x80;
-       int i = 7;
-       while (cmd & 0x80) {
+       unsigned char cmd;
+       unsigned long size = 0;
+       int i = 0;
+       do {
                cmd = *data++;
                size |= (cmd & ~0x80) << i;
                i += 7;
-       }
+       } while (cmd & 0x80);
        *datap = data;
        return size;
 }
index 2538924..073ec81 100755 (executable)
@@ -3,13 +3,21 @@
 # Copyright (c) 2005 Linus Torvalds
 # Copyright (c) 2006 Junio C Hamano
 
-USAGE='[-a] [-i] [-s] [-v | --no-verify]  [-m <message> | -F <logfile> | (-C|-c) <commit>] [-e] [--author <author>] [<path>...]'
-
+USAGE='[-a] [-i] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit>] [-e] [--author <author>] [<path>...]'
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
 
-git-rev-parse --verify HEAD >/dev/null 2>&1 ||
-initial_commit=t
+git-rev-parse --verify HEAD >/dev/null 2>&1 || initial_commit=t
+branch=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD)
+
+case "$0" in
+*status)
+       status_only=t
+       unmerged_ok_if_status=--unmerged ;;
+*commit)
+       status_only=
+       unmerged_ok_if_status= ;;
+esac
 
 refuse_partial () {
        echo >&2 "$1"
@@ -17,23 +25,149 @@ refuse_partial () {
        exit 1
 }
 
-SAVE_INDEX="$GIT_DIR/save-index$$"
+THIS_INDEX="$GIT_DIR/index"
+NEXT_INDEX="$GIT_DIR/next-index$$"
+rm -f "$NEXT_INDEX"
 save_index () {
-       cp "$GIT_DIR/index" "$SAVE_INDEX"
+       cp "$THIS_INDEX" "$NEXT_INDEX"
+}
+
+report () {
+  header="#
+# $1:
+#   ($2)
+#
+"
+  trailer=""
+  while read status name newname
+  do
+    printf '%s' "$header"
+    header=""
+    trailer="#
+"
+    case "$status" in
+    M ) echo "#        modified: $name";;
+    D*) echo "#        deleted:  $name";;
+    T ) echo "#        typechange: $name";;
+    C*) echo "#        copied: $name -> $newname";;
+    R*) echo "#        renamed: $name -> $newname";;
+    A*) echo "#        new file: $name";;
+    U ) echo "#        unmerged: $name";;
+    esac
+  done
+  printf '%s' "$trailer"
+  [ "$header" ]
 }
 
 run_status () {
-       (
-               cd "$TOP"
-               if test '' != "$TMP_INDEX"
-               then
-                       GIT_INDEX_FILE="$TMP_INDEX" git-status
-               else
-                       git-status
-               fi
-       )
+    (
+       # We always show status for the whole tree.
+       cd "$TOP"
+
+       # If TMP_INDEX is defined, that means we are doing
+       # "--only" partial commit, and that index file is used
+       # to build the tree for the commit.  Otherwise, if
+       # NEXT_INDEX exists, that is the index file used to
+       # make the commit.  Otherwise we are using as-is commit
+       # so the regular index file is what we use to compare.
+       if test '' != "$TMP_INDEX"
+       then
+           GIT_INDEX_FILE="$TMP_INDEX"
+           export GIT_INDEX_FILE
+       elif test -f "$NEXT_INDEX"
+       then
+           GIT_INDEX_FILE="$NEXT_INDEX"
+           export GIT_INDEX_FILE
+       fi
+
+       case "$branch" in
+       refs/heads/master) ;;
+       *)  echo "# On branch $branch" ;;
+       esac
+
+       if test -z "$initial_commit"
+       then
+           git-diff-index -M --cached --name-status \
+               --diff-filter=MDTCRA HEAD |
+           sed -e '
+                   s/\\/\\\\/g
+                   s/ /\\ /g
+           ' |
+           report "Updated but not checked in" "will commit"
+           committable="$?"
+       else
+           echo '#
+# Initial commit
+#'
+           git-ls-files |
+           sed -e '
+                   s/\\/\\\\/g
+                   s/ /\\ /g
+                   s/^/A /
+           ' |
+           report "Updated but not checked in" "will commit"
+
+           committable="$?"
+       fi
+
+       git-diff-files  --name-status |
+       sed -e '
+               s/\\/\\\\/g
+               s/ /\\ /g
+       ' |
+       report "Changed but not updated" \
+           "use git-update-index to mark for commit"
+
+       if test -f "$GIT_DIR/info/exclude"
+       then
+           git-ls-files -z --others --directory \
+               --exclude-from="$GIT_DIR/info/exclude" \
+               --exclude-per-directory=.gitignore
+       else
+           git-ls-files -z --others --directory \
+               --exclude-per-directory=.gitignore
+       fi |
+       perl -e '$/ = "\0";
+           my $shown = 0;
+           while (<>) {
+               chomp;
+               s|\\|\\\\|g;
+               s|\t|\\t|g;
+               s|\n|\\n|g;
+               s/^/#   /;
+               if (!$shown) {
+                   print "#\n# Untracked files:\n";
+                   print "#   (use \"git add\" to add to commit)\n";
+                   print "#\n";
+                   $shown = 1;
+               }
+               print "$_\n";
+           }
+       '
+
+       if test -n "$verbose"
+       then
+           git-diff-index --cached -M -p --diff-filter=MDTCRA HEAD
+       fi
+       case "$committable" in
+       0)
+           echo "nothing to commit"
+           exit 1
+       esac
+       exit 0
+    )
 }
 
+trap '
+       test -z "$TMP_INDEX" || {
+               test -f "$TMP_INDEX" && rm -f "$TMP_INDEX"
+       }
+       rm -f "$NEXT_INDEX"
+' 0
+
+################################################################
+# Command line argument parsing and sanity checking
+
 all=
 also=
 only=
@@ -43,6 +177,7 @@ no_edit=
 log_given=
 log_message=
 verify=t
+verbose=
 signoff=
 force_author=
 while case "$#" in 0) break;; esac
@@ -172,9 +307,9 @@ do
       signoff=t
       shift
       ;;
-  -v|--v|--ve|--ver|--veri|--verif|--verify)
-      verify=t
-     shift
+  -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
+      verbose=t
+      shift
       ;;
   --)
       shift
@@ -189,6 +324,9 @@ do
   esac
 done
 
+################################################################
+# Sanity check options
+
 case "$log_given" in
 tt*)
   die "Only one of -c/-C/-F/-m can be used." ;;
@@ -207,9 +345,24 @@ case "$#,$also$only" in
   # Later when switch the defaults, we will replace them with these:
   # echo >&2 "assuming --only paths..."
   # also=
+
+  # If we are going to launch an editor, the message won't be
+  # shown without this...
+  test -z "$log_given$status_only" && sleep 1
   ;;
 esac
 unset only
+case "$all,$also,$#" in
+t,t,*)
+       die "Cannot use -a and -i at the same time." ;;
+t,,[1-9]*)
+       die "Paths with -a does not make sense." ;;
+,t,0)
+       die "No paths with -i does not make sense." ;;
+esac
+
+################################################################
+# Prepare index to have a tree to be committed
 
 TOP=`git-rev-parse --show-cdup`
 if test -z "$TOP"
@@ -218,29 +371,25 @@ then
 fi
 
 case "$all,$also" in
-t,t)
-       die "Cannot use -a and -i at the same time." ;;
 t,)
-       case "$#" in
-       0) ;;
-       *) die "Paths with -a does not make sense." ;;
-       esac
-
        save_index &&
        (
                cd "$TOP"
+               GIT_INDEX_FILE="$NEXT_INDEX"
+               export GIT_INDEX_FILE
                git-diff-files --name-only -z |
                git-update-index --remove -z --stdin
        )
        ;;
 ,t)
-       case "$#" in
-       0) die "No paths with -i does not make sense." ;;
-       esac
-
        save_index &&
        git-diff-files --name-only -z -- "$@"  |
-       (cd "$TOP" && git-update-index --remove -z --stdin)
+       (
+               cd "$TOP"
+               GIT_INDEX_FILE="$NEXT_INDEX"
+               export GIT_INDEX_FILE
+               git-update-index --remove -z --stdin
+       )
        ;;
 ,)
        case "$#" in
@@ -262,43 +411,68 @@ t,)
                refuse_partial "Different in index and the last commit:
 $dirty_in_index"
            fi
-           commit_only=`git-ls-files -- "$@"` ;;
+           commit_only=`git-ls-files -- "$@"`
+
+           # Build the temporary index and update the real index
+           # the same way.
+           if test -z "$initial_commit"
+           then
+               cp "$THIS_INDEX" "$TMP_INDEX"
+               GIT_INDEX_FILE="$TMP_INDEX" git-read-tree -m HEAD
+           else
+                   rm -f "$TMP_INDEX"
+           fi || exit
+
+           echo "$commit_only" |
+           GIT_INDEX_FILE="$TMP_INDEX" \
+           git-update-index --add --remove --stdin &&
+
+           save_index &&
+           echo "$commit_only" |
+           (
+               GIT_INDEX_FILE="$NEXT_INDEX"
+               export GIT_INDEX_FILE
+               git-update-index --remove --stdin
+           ) || exit
+           ;;
        esac
        ;;
 esac
 
-git-update-index -q --refresh || exit 1
-
-trap '
-       test -z "$TMP_INDEX" || {
-               test -f "$TMP_INDEX" && rm -f "$TMP_INDEX"
-       }
-       test -f "$SAVE_INDEX" && mv -f "$SAVE_INDEX" "$GIT_DIR/index"
-' 0
+################################################################
+# If we do as-is commit, the index file will be THIS_INDEX,
+# otherwise NEXT_INDEX after we make this commit.  We leave
+# the index as is if we abort.
 
-if test "$TMP_INDEX"
+if test -f "$NEXT_INDEX"
 then
-       if test -z "$initial_commit"
-       then
-               GIT_INDEX_FILE="$TMP_INDEX" git-read-tree HEAD
-       else
-               rm -f "$TMP_INDEX"
-       fi || exit
-       echo "$commit_only" |
-       GIT_INDEX_FILE="$TMP_INDEX" git-update-index --add --remove --stdin &&
-       save_index &&
-       echo "$commit_only" |
-       git-update-index --remove --stdin ||
-       exit
+       USE_INDEX="$NEXT_INDEX"
+else
+       USE_INDEX="$THIS_INDEX"
 fi
 
+GIT_INDEX_FILE="$USE_INDEX" \
+    git-update-index -q $unmerged_ok_if_status --refresh || exit
+
+################################################################
+# If the request is status, just show it and exit.
+
+case "$0" in
+*status)
+       run_status
+       exit $?
+esac
+
+################################################################
+# Grab commit message, write out tree and make commit.
+
 if test t = "$verify" && test -x "$GIT_DIR"/hooks/pre-commit
 then
        if test "$TMP_INDEX"
        then
                GIT_INDEX_FILE="$TMP_INDEX" "$GIT_DIR"/hooks/pre-commit
        else
-               "$GIT_DIR"/hooks/pre-commit
+               GIT_INDEX_FILE="$USE_INDEX" "$GIT_DIR"/hooks/pre-commit
        fi || exit
 fi
 
@@ -398,7 +572,6 @@ else
        PARENTS=""
 fi
 
-
 run_status >>"$GIT_DIR"/COMMIT_EDITMSG
 if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" ]
 then
@@ -429,8 +602,14 @@ t)
        fi
 esac
 
-grep -v '^#' < "$GIT_DIR"/COMMIT_EDITMSG |
-git-stripspace > "$GIT_DIR"/COMMIT_MSG
+sed -e '
+    /^diff --git a\/.*/{
+       s///
+       q
+    }
+    /^#/d
+' "$GIT_DIR"/COMMIT_EDITMSG |
+git-stripspace >"$GIT_DIR"/COMMIT_MSG
 
 if cnt=`grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG |
        git-stripspace |
@@ -439,14 +618,20 @@ if cnt=`grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG |
 then
        if test -z "$TMP_INDEX"
        then
-               tree=$(git-write-tree)
+               tree=$(GIT_INDEX_FILE="$USE_INDEX" git-write-tree)
        else
                tree=$(GIT_INDEX_FILE="$TMP_INDEX" git-write-tree) &&
                rm -f "$TMP_INDEX"
        fi &&
        commit=$(cat "$GIT_DIR"/COMMIT_MSG | git-commit-tree $tree $PARENTS) &&
        git-update-ref HEAD $commit $current &&
-       rm -f -- "$GIT_DIR/MERGE_HEAD"
+       rm -f -- "$GIT_DIR/MERGE_HEAD" &&
+       if test -f "$NEXT_INDEX"
+       then
+               mv "$NEXT_INDEX" "$THIS_INDEX"
+       else
+               : ;# happy
+       fi
 else
        echo >&2 "* no commit message?  aborting commit."
        false
@@ -459,8 +644,4 @@ if test -x "$GIT_DIR"/hooks/post-commit && test "$ret" = 0
 then
        "$GIT_DIR"/hooks/post-commit
 fi
-if test 0 -eq "$ret"
-then
-       rm -f "$SAVE_INDEX"
-fi
 exit "$ret"
diff --git a/git-status.sh b/git-status.sh
deleted file mode 100755 (executable)
index 10d781c..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-
-USAGE=''
-SUBDIRECTORY_OK='Yes'
-
-. git-sh-setup
-
-if [ "$#" != "0" ]
-then
-  usage
-fi
-
-report () {
-  header="#
-# $1:
-#   ($2)
-#
-"
-  trailer=""
-  while read status name newname
-  do
-    printf '%s' "$header"
-    header=""
-    trailer="#
-"
-    case "$status" in
-    M ) echo "#        modified: $name";;
-    D*) echo "#        deleted:  $name";;
-    T ) echo "#        typechange: $name";;
-    C*) echo "#        copied: $name -> $newname";;
-    R*) echo "#        renamed: $name -> $newname";;
-    A*) echo "#        new file: $name";;
-    U ) echo "#        unmerged: $name";;
-    esac
-  done
-  printf '%s' "$trailer"
-  [ "$header" ]
-}
-
-branch=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD)
-case "$branch" in
-refs/heads/master) ;;
-*)     echo "# On branch $branch" ;;
-esac
-
-git-update-index -q --unmerged --refresh || exit
-
-if GIT_DIR="$GIT_DIR" git-rev-parse --verify HEAD >/dev/null 2>&1
-then
-       git-diff-index -M --cached --name-status --diff-filter=MDTCRA HEAD |
-       sed -e '
-               s/\\/\\\\/g
-               s/ /\\ /g
-       ' |
-       report "Updated but not checked in" "will commit"
-
-       committable="$?"
-else
-       echo '#
-# Initial commit
-#'
-       git-ls-files |
-       sed -e '
-               s/\\/\\\\/g
-               s/ /\\ /g
-               s/^/A /
-       ' |
-       report "Updated but not checked in" "will commit"
-
-       committable="$?"
-fi
-
-git-diff-files  --name-status |
-sed -e '
-       s/\\/\\\\/g
-       s/ /\\ /g
-' |
-report "Changed but not updated" "use git-update-index to mark for commit"
-
-
-if test -f "$GIT_DIR/info/exclude"
-then
-    git-ls-files -z --others --directory \
-       --exclude-from="$GIT_DIR/info/exclude" \
-        --exclude-per-directory=.gitignore
-else
-    git-ls-files -z --others --directory \
-        --exclude-per-directory=.gitignore
-fi |
-perl -e '$/ = "\0";
-       my $shown = 0;
-       while (<>) {
-               chomp;
-               s|\\|\\\\|g;
-               s|\t|\\t|g;
-               s|\n|\\n|g;
-               s/^/#   /;
-               if (!$shown) {
-                       print "#\n# Untracked files:\n";
-                       print "#   (use \"git add\" to add to commit)\n#\n";
-                       $shown = 1;
-               }
-               print "$_\n";
-       }
-'
-
-case "$committable" in
-0)
-       echo "nothing to commit"
-       exit 1
-esac
-exit 0
diff --git a/ident.c b/ident.c
index 0461b8b..23b8cfc 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -167,6 +167,11 @@ static const char *get_ident(const char *name, const char *email,
                name = git_default_name;
        if (!email)
                email = git_default_email;
+
+       if (!*name || !*email)
+               die("empty ident %s <%s> not allowed",
+                   name, email);
+
        strcpy(date, git_default_date);
        if (date_str)
                parse_date(date_str, date, sizeof(date));
index 541d7bc..babe34b 100644 (file)
@@ -68,9 +68,9 @@ static void parse_pack_header(void)
        hdr = (void *)pack_base;
        if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
                die("packfile '%s' signature mismatch", pack_name);
-       if (hdr->hdr_version != htonl(PACK_VERSION))
-               die("packfile '%s' version %d different from ours %d",
-                   pack_name, ntohl(hdr->hdr_version), PACK_VERSION);
+       if (!pack_version_ok(hdr->hdr_version))
+               die("packfile '%s' version %d unsupported",
+                   pack_name, ntohl(hdr->hdr_version));
 
        nr_objects = ntohl(hdr->hdr_entries);
 
index 6af3b09..7024cf1 100644 (file)
@@ -474,8 +474,28 @@ static void show_files(void)
                const char *path = ".", *base = "";
                int baselen = prefix_len;
 
-               if (baselen)
+               if (baselen) {
                        path = base = prefix;
+                       if (exclude_per_dir) {
+                               char *p, *pp = xmalloc(baselen+1);
+                               memcpy(pp, prefix, baselen+1);
+                               p = pp;
+                               while (1) {
+                                       char save = *p;
+                                       *p = 0;
+                                       push_exclude_per_directory(pp, p-pp);
+                                       *p++ = save;
+                                       if (!save)
+                                               break;
+                                       p = strchr(p, '/');
+                                       if (p)
+                                               p++;
+                                       else
+                                               p = pp + baselen;
+                               }
+                               free(pp);
+                       }
+               }
                read_directory(path, base, baselen);
                qsort(dir, nr_dir, sizeof(struct nond_on_fs *), cmp_name);
                if (show_others)
index 511f294..67a7ecd 100644 (file)
@@ -16,9 +16,9 @@ static int verify_packfile(struct packed_git *p)
        hdr = p->pack_base;
        if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
                return error("Packfile %s signature mismatch", p->pack_name);
-       if (hdr->hdr_version != htonl(PACK_VERSION))
-               return error("Packfile version %d different from ours %d",
-                            ntohl(hdr->hdr_version), PACK_VERSION);
+       if (!pack_version_ok(hdr->hdr_version))
+               return error("Packfile version %d unsupported",
+                            ntohl(hdr->hdr_version));
        nr_objects = ntohl(hdr->hdr_entries);
        if (num_packed_objects(p) != nr_objects)
                return error("Packfile claims to have %d objects, "
diff --git a/pack.h b/pack.h
index 657deaa..9dafa2b 100644 (file)
--- a/pack.h
+++ b/pack.h
@@ -21,6 +21,7 @@ enum object_type {
  */
 #define PACK_SIGNATURE 0x5041434b      /* "PACK" */
 #define PACK_VERSION 2
+#define pack_version_ok(v) ((v) == htonl(2) || (v) == htonl(3))
 struct pack_header {
        unsigned int hdr_signature;
        unsigned int hdr_version;
index 98c27be..c0e1311 100644 (file)
@@ -44,16 +44,15 @@ void *patch_delta(void *src_buf, unsigned long src_size,
                cmd = *data++;
                if (cmd & 0x80) {
                        unsigned long cp_off = 0, cp_size = 0;
-                       const unsigned char *buf;
                        if (cmd & 0x01) cp_off = *data++;
                        if (cmd & 0x02) cp_off |= (*data++ << 8);
                        if (cmd & 0x04) cp_off |= (*data++ << 16);
                        if (cmd & 0x08) cp_off |= (*data++ << 24);
                        if (cmd & 0x10) cp_size = *data++;
                        if (cmd & 0x20) cp_size |= (*data++ << 8);
+                       if (cmd & 0x40) cp_size |= (*data++ << 16);
                        if (cp_size == 0) cp_size = 0x10000;
-                       buf = (cmd & 0x40) ? dst_buf : src_buf;
-                       memcpy(out, buf + cp_off, cp_size);
+                       memcpy(out, src_buf + cp_off, cp_size);
                        out += cp_size;
                } else {
                        memcpy(out, data, cmd);
index a554e07..63391fc 100644 (file)
@@ -32,6 +32,7 @@ static const char rev_list_usage[] =
 "    --objects\n"
 "    --unpacked\n"
 "    --header | --pretty\n"
+"    --abbrev=nr | --no-abbrev\n"
 "  special purpose:\n"
 "    --bisect"
 ;
@@ -43,6 +44,7 @@ static int tag_objects = 0;
 static int tree_objects = 0;
 static int blob_objects = 0;
 static int verbose_header = 0;
+static int abbrev = DEFAULT_ABBREV;
 static int show_parents = 0;
 static int hdr_termination = 0;
 static const char *commit_prefix = "";
@@ -96,7 +98,7 @@ static void show_commit(struct commit *commit)
 
        if (verbose_header) {
                static char pretty_header[16384];
-               pretty_print_commit(commit_format, commit, ~0, pretty_header, sizeof(pretty_header), 0);
+               pretty_print_commit(commit_format, commit, ~0, pretty_header, sizeof(pretty_header), abbrev);
                printf("%s%c", pretty_header, hdr_termination);
        }
        fflush(stdout);
@@ -795,6 +797,18 @@ int main(int argc, const char **argv)
                        verbose_header = 1;
                        continue;
                }
+               if (!strcmp(arg, "--no-abbrev")) {
+                       abbrev = 0;
+                       continue;
+               }
+               if (!strncmp(arg, "--abbrev=", 9)) {
+                       abbrev = strtoul(arg + 9, NULL, 10);
+                       if (abbrev && abbrev < MINIMUM_ABBREV)
+                               abbrev = MINIMUM_ABBREV;
+                       else if (40 < abbrev)
+                               abbrev = 40;
+                       continue;
+               }
                if (!strncmp(arg, "--pretty", 8)) {
                        commit_format = get_commit_format(arg+8);
                        verbose_header = 1;
index 20f6419..3d11a9b 100644 (file)
@@ -6,8 +6,6 @@
  * This handles basic git sha1 object files - packing, unpacking,
  * creation etc.
  */
-#include <sys/types.h>
-#include <dirent.h>
 #include "cache.h"
 #include "delta.h"
 #include "pack.h"
@@ -74,6 +72,8 @@ int adjust_shared_perm(const char *path)
 int safe_create_leading_directories(char *path)
 {
        char *pos = path;
+       struct stat st;
+
        if (*pos == '/')
                pos++;
 
@@ -82,12 +82,17 @@ int safe_create_leading_directories(char *path)
                if (!pos)
                        break;
                *pos = 0;
-               if (mkdir(path, 0777) < 0) {
-                       if (errno != EEXIST) {
+               if (!stat(path, &st)) {
+                       /* path exists */
+                       if (!S_ISDIR(st.st_mode)) {
                                *pos = '/';
-                               return -1;
+                               return -3;
                        }
                }
+               else if (mkdir(path, 0777)) {
+                       *pos = '/';
+                       return -1;
+               }
                else if (adjust_shared_perm(path)) {
                        *pos = '/';
                        return -2;
index ffe7456..511fd3b 100644 (file)
@@ -548,8 +548,8 @@ int main(int ac, char **av)
        int with_current_branch = 0;
        int head_at = -1;
 
-       git_config(git_show_branch_config);
        setup_git_directory();
+       git_config(git_show_branch_config);
 
        /* If nothing is specified, try the default first */
        if (ac == 1 && default_num) {
index 01f796e..c6752af 100755 (executable)
@@ -51,7 +51,12 @@ as_author()
 
        export GIT_AUTHOR_EMAIL="$_author"
        "$@"
-        export GIT_AUTHOR_EMAIL="$_save"
+       if test -z "$_save"
+       then
+               unset GIT_AUTHOR_EMAIL
+       else
+               export GIT_AUTHOR_EMAIL="$_save"
+       fi
 }
 
 commit_date()
index 4b5b5cb..815a1b3 100644 (file)
@@ -246,13 +246,12 @@ static void unpack_all(void)
 {
        int i;
        struct pack_header *hdr = fill(sizeof(struct pack_header));
-       unsigned version = ntohl(hdr->hdr_version);
        unsigned nr_objects = ntohl(hdr->hdr_entries);
 
        if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
                die("bad pack file");
-       if (version != PACK_VERSION)
-               die("unable to handle pack file version %d", version);
+       if (!pack_version_ok(hdr->hdr_version))
+               die("unknown pack file version %d", ntohl(hdr->hdr_version));
        fprintf(stderr, "Unpacking %d objects\n", nr_objects);
 
        use(sizeof(struct pack_header));