summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-archive.txt13
-rw-r--r--Documentation/git.txt3
-rw-r--r--builtin-grep.c2
-rw-r--r--builtin-update-index.c4
-rw-r--r--dir.c27
-rwxr-xr-xgit-svn.perl1
-rwxr-xr-xgitweb/gitweb.perl2
-rw-r--r--grep.c49
-rw-r--r--grep.h1
-rw-r--r--interpolate.c6
-rw-r--r--interpolate.h9
-rw-r--r--read-cache.c4
-rwxr-xr-xt/t3700-add.sh22
-rwxr-xr-xt/t6001-rev-list-graft.sh113
14 files changed, 231 insertions, 25 deletions
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index 913528d373..031fcd5190 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -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
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 1bf5ef57e4..2135b65516 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -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.
diff --git a/builtin-grep.c b/builtin-grep.c
index 6718788173..4205e5d38d 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -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;
}
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 0620e779b0..a3c0a455ae 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -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 e2f472ba7f..96389b32e6 100644
--- 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;
}
diff --git a/git-svn.perl b/git-svn.perl
index 017f45ac97..f5c7d46341 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -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;
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 66be619332..597d29f22f 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -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 cc8d6846a5..c411ddd4d5 100644
--- 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 0b503ea665..af9098cfe8 100644
--- 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
diff --git a/interpolate.c b/interpolate.c
index d82f1b51bb..4570c123dc 100644
--- a/interpolate.c
+++ b/interpolate.c
@@ -25,10 +25,10 @@
*/
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;
diff --git a/interpolate.h b/interpolate.h
index 00c63a5622..d16f9244f3 100644
--- a/interpolate.h
+++ b/interpolate.h
@@ -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 */
diff --git a/read-cache.c b/read-cache.c
index 20c9d494ac..97c38670b4 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -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))
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 6cd05c3d90..c20e4c29fc 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -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
index 0000000000..b2131cdacd
--- /dev/null
+++ b/t/t6001-rev-list-graft.sh
@@ -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