Merge branch 'jc/deprecate-recursive'
authorJunio C Hamano <junkio@cox.net>
Thu, 28 Sep 2006 04:41:24 +0000 (21:41 -0700)
committerJunio C Hamano <junkio@cox.net>
Thu, 28 Sep 2006 04:41:24 +0000 (21:41 -0700)
* jc/deprecate-recursive:
Deprecate merge-recursive.py

14 files changed:
Documentation/git-archive.txt
Documentation/git.txt
builtin-grep.c
builtin-update-index.c
dir.c
git-svn.perl
gitweb/gitweb.perl
grep.c
grep.h
interpolate.c
interpolate.h
read-cache.c
t/t3700-add.sh
t/t6001-rev-list-graft.sh [new file with mode: 0755]
index 913528d3732999fd3c5a4648b8544fc80827d3dc..031fcd5190bf4baef7d87534ef5b6a39fe8985a9 100644 (file)
@@ -40,6 +40,7 @@ OPTIONS
 
 <extra>::
        This can be any options that the archiver backend understand.
+       See next section.
 
 --remote=<repo>::
        Instead of making a tar archive from local repository,
@@ -52,6 +53,18 @@ path::
        If one or more paths are specified, include only these in the
        archive, otherwise include all files and subdirectories.
 
+BACKEND EXTRA OPTIONS
+---------------------
+
+zip
+~~~
+-0::
+       Store the files instead of deflating them.
+-9::
+       Highest and slowest compression level.  You can specify any
+       number from 1 to 9 to adjust compression speed and ratio.
+
+
 CONFIGURATION
 -------------
 By default, file and directories modes are set to 0666 or 0777 in tar
index 1bf5ef57e41eaa74836f75d089a07c3a40f2837e..2135b65516b372587a9a4fa13daf21df05a5d1ce 100644 (file)
@@ -266,6 +266,9 @@ gitlink:git-am[1]::
 gitlink:git-applymbox[1]::
        Apply patches from a mailbox, original version by Linus.
 
+gitlink:git-archive[1]::
+       Creates an archive of files from a named tree.
+
 gitlink:git-bisect[1]::
        Find the change that introduced a bug by binary search.
 
index 671878817386c72f16fe64cc62b6fa8daa62f102..4205e5d38dea6dee2d815a7434f87eacd089e4a9 100644 (file)
@@ -325,6 +325,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
                else
                        hit |= grep_file(opt, ce->name);
        }
+       free_grep_patterns(opt);
        return hit;
 }
 
@@ -694,5 +695,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                if (grep_object(&opt, paths, real_obj, list.objects[i].name))
                        hit = 1;
        }
+       free_grep_patterns(&opt);
        return !hit;
 }
index 0620e779b04146a01f9e06cbbcd535b106034bd6..a3c0a455ae5d1b8d7b7b6a8798ed7f038ab7bd72 100644 (file)
@@ -112,11 +112,13 @@ static int add_file_to_cache(const char *path)
        ce->ce_mode = create_ce_mode(st.st_mode);
        if (!trust_executable_bit) {
                /* If there is an existing entry, pick the mode bits
-                * from it.
+                * from it, otherwise force to 644.
                 */
                int pos = cache_name_pos(path, namelen);
                if (0 <= pos)
                        ce->ce_mode = active_cache[pos]->ce_mode;
+               else
+                       ce->ce_mode = create_ce_mode(S_IFREG | 0644);
        }
 
        if (index_path(ce->sha1, path, &st, !info_only))
diff --git a/dir.c b/dir.c
index e2f472ba7f5d3e5146f110dd3eaae9e5494854e2..96389b32e66af24896220e4738cd93bf2ac75704 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -283,7 +283,7 @@ static int dir_exists(const char *dirname, int len)
  * Also, we ignore the name ".git" (even if it is not a directory).
  * That likely will not change.
  */
-static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen)
+static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only)
 {
        DIR *fdir = opendir(path);
        int contents = 0;
@@ -314,7 +314,6 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
 
                        switch (DTYPE(de)) {
                        struct stat st;
-                       int subdir, rewind_base;
                        default:
                                continue;
                        case DT_UNKNOWN:
@@ -328,26 +327,30 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
                        case DT_DIR:
                                memcpy(fullname + baselen + len, "/", 2);
                                len++;
-                               rewind_base = dir->nr;
-                               subdir = read_directory_recursive(dir, fullname, fullname,
-                                                       baselen + len);
                                if (dir->show_other_directories &&
-                                   (subdir || !dir->hide_empty_directories) &&
                                    !dir_exists(fullname, baselen + len)) {
-                                       /* Rewind the read subdirectory */
-                                       while (dir->nr > rewind_base)
-                                               free(dir->entries[--dir->nr]);
+                                       if (dir->hide_empty_directories &&
+                                           !read_directory_recursive(dir,
+                                                   fullname, fullname,
+                                                   baselen + len, 1))
+                                               continue;
                                        break;
                                }
-                               contents += subdir;
+
+                               contents += read_directory_recursive(dir,
+                                       fullname, fullname, baselen + len, 0);
                                continue;
                        case DT_REG:
                        case DT_LNK:
                                break;
                        }
-                       add_name(dir, fullname, baselen + len);
                        contents++;
+                       if (check_only)
+                               goto exit_early;
+                       else
+                               add_name(dir, fullname, baselen + len);
                }
+exit_early:
                closedir(fdir);
 
                pop_exclude_per_directory(dir, exclude_stk);
@@ -393,7 +396,7 @@ int read_directory(struct dir_struct *dir, const char *path, const char *base, i
                }
        }
 
-       read_directory_recursive(dir, path, base, baselen);
+       read_directory_recursive(dir, path, base, baselen, 0);
        qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
        return dir->nr;
 }
index 017f45ac972cf030e545258af0e3793ad1b87e3f..f5c7d46341016a5ca77a52ad16fbcd8c3830678f 100755 (executable)
@@ -1247,6 +1247,7 @@ sub assert_svn_wc_clean {
        }
        my @status = grep(!/^Performing status on external/,(`svn status`));
        @status = grep(!/^\s*$/,@status);
+       @status = grep(!/^X/,@status) if $_no_ignore_ext;
        if (scalar @status) {
                print STDERR "Tree ($SVN_WC) is not clean:\n";
                print STDERR $_ foreach @status;
index 66be61933257bf1191d35a8d568df614cc2ac150..597d29f22fc931cf13574a8d2b0fde9f6b2f9908 100755 (executable)
@@ -617,7 +617,7 @@ sub format_subject_html {
 
        if (length($short) < length($long)) {
                return $cgi->a({-href => $href, -class => "list subject",
-                               -title => $long},
+                               -title => decode("utf8", $long, Encode::FB_DEFAULT)},
                       esc_html($short) . $extra);
        } else {
                return $cgi->a({-href => $href, -class => "list subject"},
diff --git a/grep.c b/grep.c
index cc8d6846a59563b6b902f576262ec97b73f01562..c411ddd4d52e2aa68edd979733dd0b15f51d5f32 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -138,16 +138,13 @@ void compile_grep_patterns(struct grep_opt *opt)
 {
        struct grep_pat *p;
 
-       if (opt->fixed)
-               return;
-
-       /* First compile regexps */
        for (p = opt->pattern_list; p; p = p->next) {
                switch (p->token) {
                case GREP_PATTERN: /* atom */
                case GREP_PATTERN_HEAD:
                case GREP_PATTERN_BODY:
-                       compile_regexp(p, opt);
+                       if (!opt->fixed)
+                               compile_regexp(p, opt);
                        break;
                default:
                        opt->extended = 1;
@@ -167,6 +164,46 @@ void compile_grep_patterns(struct grep_opt *opt)
                die("incomplete pattern expression: %s", p->pattern);
 }
 
+static void free_pattern_expr(struct grep_expr *x)
+{
+       switch (x->node) {
+       case GREP_NODE_ATOM:
+               break;
+       case GREP_NODE_NOT:
+               free_pattern_expr(x->u.unary);
+               break;
+       case GREP_NODE_AND:
+       case GREP_NODE_OR:
+               free_pattern_expr(x->u.binary.left);
+               free_pattern_expr(x->u.binary.right);
+               break;
+       }
+       free(x);
+}
+
+void free_grep_patterns(struct grep_opt *opt)
+{
+       struct grep_pat *p, *n;
+
+       for (p = opt->pattern_list; p; p = n) {
+               n = p->next;
+               switch (p->token) {
+               case GREP_PATTERN: /* atom */
+               case GREP_PATTERN_HEAD:
+               case GREP_PATTERN_BODY:
+                       regfree(&p->regexp);
+                       break;
+               default:
+                       break;
+               }
+               free(p);
+       }
+
+       if (!opt->extended)
+               return;
+       free_pattern_expr(opt->pattern_expression);
+}
+
 static char *end_of_line(char *cp, unsigned long *left)
 {
        unsigned long l = *left;
@@ -439,6 +476,8 @@ int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long
                lno++;
        }
 
+       free(prev);
+
        if (opt->status_only)
                return 0;
        if (opt->unmatch_name_only) {
diff --git a/grep.h b/grep.h
index 0b503ea6657692672c3365f3090151cc5e9e6681..af9098cfe8699680aeaa11790dad3e8d556ed395 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -73,6 +73,7 @@ struct grep_opt {
 
 extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
 extern void compile_grep_patterns(struct grep_opt *opt);
+extern void free_grep_patterns(struct grep_opt *opt);
 extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);
 
 #endif
index d82f1b51bbff4a545a2d5a0aebb91612cacd3d69..4570c123dce811bab8a89efe4c3b4a9a977e6c5a 100644 (file)
  */
 
 int interpolate(char *result, int reslen,
-               char *orig,
-               struct interp *interps, int ninterps)
+               const char *orig,
+               const struct interp *interps, int ninterps)
 {
-       char *src = orig;
+       const char *src = orig;
        char *dest = result;
        int newlen = 0;
        char *name, *value;
index 00c63a5622da8545f46fb6b170951b224679bc73..d16f9244f3de25ec9e554c6d9f5bae07de7bf2a0 100644 (file)
@@ -5,6 +5,11 @@
 #ifndef INTERPOLATE_H
 #define INTERPOLATE_H
 
+/*
+ * Convert a NUL-terminated string in buffer orig,
+ * performing substitutions on %-named sub-strings from
+ * the interpretation table.
+ */
 
 struct interp {
        char *name;
@@ -12,7 +17,7 @@ struct interp {
 };
 
 extern int interpolate(char *result, int reslen,
-                      char *orig,
-                      struct interp *interps, int ninterps);
+                      const char *orig,
+                      const struct interp *interps, int ninterps);
 
 #endif /* INTERPOLATE_H */
index 20c9d494ac94380c9074997e9cb3c69ff1c04a3f..97c38670b45d852b2f07f3d3addb2aaf6dbd8697 100644 (file)
@@ -347,11 +347,13 @@ int add_file_to_index(const char *path, int verbose)
        ce->ce_mode = create_ce_mode(st.st_mode);
        if (!trust_executable_bit) {
                /* If there is an existing entry, pick the mode bits
-                * from it.
+                * from it, otherwise force to 644.
                 */
                int pos = cache_name_pos(path, namelen);
                if (pos >= 0)
                        ce->ce_mode = active_cache[pos]->ce_mode;
+               else
+                       ce->ce_mode = create_ce_mode(S_IFREG | 0644);
        }
 
        if (index_path(ce->sha1, path, &st, 1))
index 6cd05c3d9096e8017a6bfb23982ea46e0ae93630..c20e4c29fcc864dff80e5ae73a8ad7ede1f794f0 100755 (executable)
@@ -19,4 +19,26 @@ test_expect_success \
     'Test that "git-add -- -q" works' \
     'touch -- -q && git-add -- -q'
 
+test_expect_success \
+       'git-add: Test that executable bit is not used if core.filemode=0' \
+       'git repo-config core.filemode 0 &&
+        echo foo >xfoo1 &&
+        chmod 755 xfoo1 &&
+        git-add xfoo1 &&
+        case "`git-ls-files --stage xfoo1`" in
+        100644" "*xfoo1) echo ok;;
+        *) echo fail; git-ls-files --stage xfoo1; exit 1;;
+        esac'
+
+test_expect_success \
+       'git-update-index --add: Test that executable bit is not used...' \
+       'git repo-config core.filemode 0 &&
+        echo foo >xfoo2 &&
+        chmod 755 xfoo2 &&
+        git-update-index --add xfoo2 &&
+        case "`git-ls-files --stage xfoo2`" in
+        100644" "*xfoo2) echo ok;;
+        *) echo fail; git-ls-files --stage xfoo2; exit 1;;
+        esac'
+
 test_done
diff --git a/t/t6001-rev-list-graft.sh b/t/t6001-rev-list-graft.sh
new file mode 100755 (executable)
index 0000000..b2131cd
--- /dev/null
@@ -0,0 +1,113 @@
+#!/bin/sh
+
+test_description='Revision traversal vs grafts and path limiter'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+       mkdir subdir &&
+       echo >fileA fileA &&
+       echo >subdir/fileB fileB &&
+       git add fileA subdir/fileB &&
+       git commit -a -m "Initial in one history." &&
+       A0=`git rev-parse --verify HEAD` &&
+
+       echo >fileA fileA modified &&
+       git commit -a -m "Second in one history." &&
+       A1=`git rev-parse --verify HEAD` &&
+
+       echo >subdir/fileB fileB modified &&
+       git commit -a -m "Third in one history." &&
+       A2=`git rev-parse --verify HEAD` &&
+
+       rm -f .git/refs/heads/master .git/index &&
+
+       echo >fileA fileA again &&
+       echo >subdir/fileB fileB again &&
+       git add fileA subdir/fileB &&
+       git commit -a -m "Initial in alternate history." &&
+       B0=`git rev-parse --verify HEAD` &&
+
+       echo >fileA fileA modified in alternate history &&
+       git commit -a -m "Second in alternate history." &&
+       B1=`git rev-parse --verify HEAD` &&
+
+       echo >subdir/fileB fileB modified in alternate history &&
+       git commit -a -m "Third in alternate history." &&
+       B2=`git rev-parse --verify HEAD` &&
+       : done
+'
+
+check () {
+       type=$1
+       shift
+
+       arg=
+       which=arg
+       rm -f test.expect
+       for a
+       do
+               if test "z$a" = z--
+               then
+                       which=expect
+                       child=
+                       continue
+               fi
+               if test "$which" = arg
+               then
+                       arg="$arg$a "
+                       continue
+               fi
+               if test "$type" = basic
+               then
+                       echo "$a"
+               else
+                       if test "z$child" != z
+                       then
+                               echo "$child $a"
+                       fi
+                       child="$a"
+               fi
+       done >test.expect
+       if test "$type" != basic && test "z$child" != z
+       then
+               echo >>test.expect $child
+       fi
+       if test $type = basic
+       then
+               git rev-list $arg >test.actual
+       elif test $type = parents
+       then
+               git rev-list --parents $arg >test.actual
+       elif test $type = parents-raw
+       then
+               git rev-list --parents --pretty=raw $arg |
+               sed -n -e 's/^commit //p' >test.actual
+       fi
+       diff test.expect test.actual
+}
+
+for type in basic parents parents-raw
+do
+       test_expect_success 'without grafts' "
+               rm -f .git/info/grafts
+               check $type $B2 -- $B2 $B1 $B0
+       "
+
+       test_expect_success 'with grafts' "
+               echo '$B0 $A2' >.git/info/grafts
+               check $type $B2 -- $B2 $B1 $B0 $A2 $A1 $A0
+       "
+
+       test_expect_success 'without grafts, with pathlimit' "
+               rm -f .git/info/grafts
+               check $type $B2 subdir -- $B2 $B0
+       "
+
+       test_expect_success 'with grafts, with pathlimit' "
+               echo '$B0 $A2' >.git/info/grafts
+               check $type $B2 subdir -- $B2 $B0 $A2 $A0
+       "
+
+done
+test_done