diff options
-rw-r--r-- | Documentation/git-grep.txt | 7 | ||||
-rw-r--r-- | Documentation/git-rebase.txt | 1 | ||||
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | builtin-apply.c | 25 | ||||
-rw-r--r-- | builtin-log.c | 2 | ||||
-rw-r--r-- | builtin-tar-tree.c | 4 | ||||
-rw-r--r-- | cache.h | 1 | ||||
-rw-r--r-- | compat/strlcpy.c | 13 | ||||
-rw-r--r-- | config.c | 6 | ||||
-rw-r--r-- | connect.c | 1 | ||||
-rw-r--r-- | diff.c | 31 | ||||
-rw-r--r-- | diff.h | 1 | ||||
-rwxr-xr-x | git-commit.sh | 19 | ||||
-rw-r--r-- | git-compat-util.h | 5 | ||||
-rwxr-xr-x | git-rebase.sh | 39 | ||||
-rw-r--r-- | http-fetch.c | 6 | ||||
-rw-r--r-- | http-push.c | 6 | ||||
-rw-r--r-- | ident.c | 4 | ||||
-rw-r--r-- | merge-index.c | 1 | ||||
-rw-r--r-- | path.c | 15 | ||||
-rw-r--r-- | pkt-line.h | 2 | ||||
-rw-r--r-- | sha1_name.c | 2 | ||||
-rwxr-xr-x | t/t3401-rebase-partial.sh | 13 | ||||
-rwxr-xr-x | t/t3403-rebase-skip.sh | 61 | ||||
-rw-r--r-- | xdiff/xdiff.h | 3 | ||||
-rw-r--r-- | xdiff/xdiffi.c | 12 | ||||
-rw-r--r-- | xdiff/xdiffi.h | 1 | ||||
-rw-r--r-- | xdiff/xmacros.h | 1 | ||||
-rw-r--r-- | xdiff/xprepare.c | 16 | ||||
-rw-r--r-- | xdiff/xutils.c | 51 | ||||
-rw-r--r-- | xdiff/xutils.h | 3 |
31 files changed, 263 insertions, 103 deletions
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 7b810dfda7..62a8e7f222 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -16,7 +16,7 @@ SYNOPSIS [-n] [-l | --files-with-matches] [-L | --files-without-match] [-c | --count] [-A <post-context>] [-B <pre-context>] [-C <context>] - [-f <file>] [-e <pattern>] + [-f <file>] [-e] <pattern> [<tree>...] [--] [<path>...] @@ -71,6 +71,11 @@ OPTIONS -f <file>:: Read patterns from <file>, one per line. +-e:: + The next parameter is the pattern. This option has to be + used for patterns starting with - and should be used in + scripts passing user input to grep. + `<tree>...`:: Search blobs in the trees for specified patterns. diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index c339c4525c..9d7bcaa38c 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -108,7 +108,6 @@ OPTIONS --skip:: Restart the rebasing process by skipping the current patch. - This does not work with the --merge option. --merge:: Use merging strategies to rebase. When the recursive (default) merge @@ -26,6 +26,8 @@ all: # # Define NO_STRCASESTR if you don't have strcasestr. # +# Define NO_STRLCPY if you don't have strlcpy. +# # Define NO_SETENV if you don't have setenv in the C library. # # Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link. @@ -240,9 +242,13 @@ LIBS = $(GITLIBS) -lz # because maintaining the nesting to match is a pain. If # we had "elif" things would have been much nicer... +ifeq ($(uname_S),Linux) + NO_STRLCPY = YesPlease +endif 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 @@ -259,6 +265,7 @@ ifeq ($(uname_S),SunOS) NEEDS_NSL = YesPlease SHELL_PATH = /bin/bash NO_STRCASESTR = YesPlease + NO_STRLCPY = YesPlease ifeq ($(uname_R),5.8) NEEDS_LIBICONV = YesPlease NO_UNSETENV = YesPlease @@ -276,6 +283,7 @@ ifeq ($(uname_O),Cygwin) NO_D_TYPE_IN_DIRENT = YesPlease NO_D_INO_IN_DIRENT = YesPlease NO_STRCASESTR = YesPlease + NO_STRLCPY = YesPlease NO_SYMLINK_HEAD = YesPlease NEEDS_LIBICONV = YesPlease # There are conflicting reports about this. @@ -305,12 +313,14 @@ ifeq ($(uname_S),NetBSD) endif ifeq ($(uname_S),AIX) NO_STRCASESTR=YesPlease + NO_STRLCPY = YesPlease NEEDS_LIBICONV=YesPlease endif ifeq ($(uname_S),IRIX64) NO_IPV6=YesPlease NO_SETENV=YesPlease NO_STRCASESTR=YesPlease + NO_STRLCPY = YesPlease NO_SOCKADDR_STORAGE=YesPlease SHELL_PATH=/usr/gnu/bin/bash ALL_CFLAGS += -DPATH_MAX=1024 @@ -403,6 +413,10 @@ ifdef NO_STRCASESTR COMPAT_CFLAGS += -DNO_STRCASESTR COMPAT_OBJS += compat/strcasestr.o endif +ifdef NO_STRLCPY + COMPAT_CFLAGS += -DNO_STRLCPY + COMPAT_OBJS += compat/strlcpy.o +endif ifdef NO_SETENV COMPAT_CFLAGS += -DNO_SETENV COMPAT_OBJS += compat/setenv.o diff --git a/builtin-apply.c b/builtin-apply.c index 6dd0472ae0..e9ead002d3 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -125,6 +125,7 @@ struct patch { unsigned long deflate_origlen; int lines_added, lines_deleted; int score; + int inaccurate_eof:1; struct fragment *fragments; char *result; unsigned long resultsize; @@ -1333,7 +1334,8 @@ static int apply_line(char *output, const char *patch, int plen) return plen; } -static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) +static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, + int inaccurate_eof) { int match_beginning, match_end; char *buf = desc->buffer; @@ -1386,13 +1388,11 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) size -= len; } -#ifdef NO_ACCURATE_DIFF - if (oldsize > 0 && old[oldsize - 1] == '\n' && + if (inaccurate_eof && oldsize > 0 && old[oldsize - 1] == '\n' && newsize > 0 && new[newsize - 1] == '\n') { oldsize--; newsize--; } -#endif oldlines = old; newlines = new; @@ -1614,7 +1614,7 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch) return apply_binary(desc, patch); while (frag) { - if (apply_one_fragment(desc, frag) < 0) + if (apply_one_fragment(desc, frag, patch->inaccurate_eof) < 0) return error("patch failed: %s:%ld", name, frag->oldpos); frag = frag->next; @@ -2097,7 +2097,7 @@ static int use_patch(struct patch *p) return 1; } -static int apply_patch(int fd, const char *filename) +static int apply_patch(int fd, const char *filename, int inaccurate_eof) { unsigned long offset, size; char *buffer = read_patch_file(fd, &size); @@ -2113,6 +2113,7 @@ static int apply_patch(int fd, const char *filename) int nr; patch = xcalloc(1, sizeof(*patch)); + patch->inaccurate_eof = inaccurate_eof; nr = parse_chunk(buffer + offset, size, patch); if (nr < 0) break; @@ -2180,6 +2181,8 @@ int cmd_apply(int argc, const char **argv, char **envp) { int i; int read_stdin = 1; + int inaccurate_eof = 0; + const char *whitespace_option = NULL; for (i = 1; i < argc; i++) { @@ -2188,7 +2191,7 @@ int cmd_apply(int argc, const char **argv, char **envp) int fd; if (!strcmp(arg, "-")) { - apply_patch(0, "<stdin>"); + apply_patch(0, "<stdin>", inaccurate_eof); read_stdin = 0; continue; } @@ -2265,6 +2268,10 @@ int cmd_apply(int argc, const char **argv, char **envp) parse_whitespace_option(arg + 13); continue; } + if (!strcmp(arg, "--inaccurate-eof")) { + inaccurate_eof = 1; + continue; + } if (check_index && prefix_length < 0) { prefix = setup_git_directory(); @@ -2281,12 +2288,12 @@ int cmd_apply(int argc, const char **argv, char **envp) usage(apply_usage); read_stdin = 0; set_default_whitespace_mode(whitespace_option); - apply_patch(fd, arg); + apply_patch(fd, arg, inaccurate_eof); close(fd); } set_default_whitespace_mode(whitespace_option); if (read_stdin) - apply_patch(0, "<stdin>"); + apply_patch(0, "<stdin>", inaccurate_eof); if (whitespace_error) { if (squelch_whitespace_errors && squelch_whitespace_errors < whitespace_error) { diff --git a/builtin-log.c b/builtin-log.c index 5a8a50b81d..44d2d136f5 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -115,7 +115,7 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject) int len = 0; if (output_directory) { - safe_strncpy(filename, output_directory, 1010); + strlcpy(filename, output_directory, 1010); len = strlen(filename); if (filename[len - 1] != '/') filename[len++] = '/'; diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index 39a61b6293..f2e48aae2a 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -233,8 +233,8 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, /* XXX: should we provide more meaningful info here? */ sprintf(header.uid, "%07o", 0); sprintf(header.gid, "%07o", 0); - safe_strncpy(header.uname, "git", sizeof(header.uname)); - safe_strncpy(header.gname, "git", sizeof(header.gname)); + strlcpy(header.uname, "git", sizeof(header.uname)); + strlcpy(header.gname, "git", sizeof(header.gname)); sprintf(header.devmajor, "%07o", 0); sprintf(header.devminor, "%07o", 0); @@ -216,7 +216,6 @@ enum sharedrepo { int git_config_perm(const char *var, const char *value); int adjust_shared_perm(const char *path); int safe_create_leading_directories(char *path); -size_t safe_strncpy(char *, const char *, size_t); char *enter_repo(char *path, int strict); /* Read and unpack a sha1 file into memory, write memory to a sha1 file */ diff --git a/compat/strlcpy.c b/compat/strlcpy.c new file mode 100644 index 0000000000..b66856a3a5 --- /dev/null +++ b/compat/strlcpy.c @@ -0,0 +1,13 @@ +#include <string.h> + +size_t gitstrlcpy(char *dest, const char *src, size_t size) +{ + size_t ret = strlen(src); + + if (size) { + size_t len = (ret >= size) ? size - 1 : ret; + memcpy(dest, src, len); + dest[len] = '\0'; + } + return ret; +} @@ -280,17 +280,17 @@ int git_default_config(const char *var, const char *value) } if (!strcmp(var, "user.name")) { - safe_strncpy(git_default_name, value, sizeof(git_default_name)); + strlcpy(git_default_name, value, sizeof(git_default_name)); return 0; } if (!strcmp(var, "user.email")) { - safe_strncpy(git_default_email, value, sizeof(git_default_email)); + strlcpy(git_default_email, value, sizeof(git_default_email)); return 0; } if (!strcmp(var, "i18n.commitencoding")) { - safe_strncpy(git_commit_encoding, value, sizeof(git_commit_encoding)); + strlcpy(git_commit_encoding, value, sizeof(git_commit_encoding)); return 0; } @@ -8,6 +8,7 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> +#include <signal.h> static char *server_capabilities = NULL; @@ -203,7 +203,7 @@ static void emit_rewrite_diff(const char *name_a, static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one) { if (!DIFF_FILE_VALID(one)) { - mf->ptr = ""; /* does not matter */ + mf->ptr = (char *)""; /* does not matter */ mf->size = 0; return 0; } @@ -395,7 +395,7 @@ static void show_stats(struct diffstat_t* data) } for (i = 0; i < data->nr; i++) { - char *prefix = ""; + const char *prefix = ""; char *name = data->files[i]->name; int added = data->files[i]->added; int deleted = data->files[i]->deleted; @@ -678,7 +678,7 @@ static void builtin_diff(const char *name_a, memset(&ecbdata, 0, sizeof(ecbdata)); ecbdata.label_path = lbl; ecbdata.color_diff = o->color_diff; - xpp.flags = XDF_NEED_MINIMAL; + xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; if (!diffopts) @@ -703,6 +703,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, struct diff_filespec *one, struct diff_filespec *two, struct diffstat_t *diffstat, + struct diff_options *o, int complete_rewrite) { mmfile_t mf1, mf2; @@ -732,7 +733,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, xdemitconf_t xecfg; xdemitcb_t ecb; - xpp.flags = XDF_NEED_MINIMAL; + xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = 0; xecfg.flags = 0; ecb.outf = xdiff_outf; @@ -917,7 +918,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) err_empty: err = -1; empty: - s->data = ""; + s->data = (char *)""; s->size = 0; return err; } @@ -1317,7 +1318,7 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o, if (DIFF_PAIR_UNMERGED(p)) { /* unmerged */ - builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, 0); + builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, 0); return; } @@ -1329,7 +1330,7 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o, if (p->status == DIFF_STATUS_MODIFIED && p->score) complete_rewrite = 1; - builtin_diffstat(name, other, p->one, p->two, diffstat, complete_rewrite); + builtin_diffstat(name, other, p->one, p->two, diffstat, o, complete_rewrite); } static void run_checkdiff(struct diff_filepair *p, struct diff_options *o) @@ -1408,7 +1409,7 @@ int diff_setup_done(struct diff_options *options) return 0; } -int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val) +static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val) { char c, *eq; int len; @@ -1534,6 +1535,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) } else if (!strcmp(arg, "--color")) options->color_diff = 1; + else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space")) + options->xdl_opts |= XDF_IGNORE_WHITESPACE; + else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change")) + options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE; else return 0; return 1; @@ -1720,16 +1725,12 @@ static void diff_flush_raw(struct diff_filepair *p, free((void*)path_two); } -static void diff_flush_name(struct diff_filepair *p, - int inter_name_termination, - int line_termination) +static void diff_flush_name(struct diff_filepair *p, int line_termination) { char *path = p->two->path; if (line_termination) path = quote_one(p->two->path); - else - path = p->two->path; printf("%s%c", path, line_termination); if (p->two->path != path) free(path); @@ -1950,9 +1951,7 @@ static void flush_one_pair(struct diff_filepair *p, options, diff_output_format); break; case DIFF_FORMAT_NAME: - diff_flush_name(p, - inter_name_termination, - line_termination); + diff_flush_name(p, line_termination); break; case DIFF_FORMAT_NO_OUTPUT: break; @@ -46,6 +46,7 @@ struct diff_options { int setup; int abbrev; const char *stat_sep; + long xdl_opts; int nr_paths; const char **paths; diff --git a/git-commit.sh b/git-commit.sh index e74fe640b8..128db6c52a 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -693,13 +693,18 @@ t) fi esac -sed -e ' - /^diff --git a\/.*/{ - s/// - q - } - /^#/d -' "$GIT_DIR"/COMMIT_EDITMSG | +if test -z "$no_edit" +then + sed -e ' + /^diff --git a\/.*/{ + s/// + q + } + /^#/d + ' "$GIT_DIR"/COMMIT_EDITMSG +else + cat "$GIT_DIR"/COMMIT_EDITMSG +fi | git-stripspace >"$GIT_DIR"/COMMIT_MSG if cnt=`grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG | diff --git a/git-compat-util.h b/git-compat-util.h index b3d4cf532e..93f558056d 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -79,6 +79,11 @@ extern void gitunsetenv(const char *); extern char *gitstrcasestr(const char *haystack, const char *needle); #endif +#ifdef NO_STRLCPY +#define strlcpy gitstrlcpy +extern size_t gitstrlcpy(char *, const char *, size_t); +#endif + static inline void *xmalloc(size_t size) { void *ret = malloc(size); diff --git a/git-rebase.sh b/git-rebase.sh index 91594775e6..9ad1c44d48 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -59,15 +59,16 @@ continue_merge () { if test -n "`git-diff-index HEAD`" then + printf "Committed: %0${prec}d" $msgnum git-commit -C "`cat $dotest/current`" else - echo "Previous merge succeeded automatically" + printf "Already applied: %0${prec}d" $msgnum fi + echo ' '`git-rev-list --pretty=oneline -1 HEAD | \ + sed 's/^[a-f0-9]\+ //'` prev_head=`git-rev-parse HEAD^0` - # save the resulting commit so we can read-tree on it later - echo "$prev_head" > "$dotest/cmt.$msgnum.result" echo "$prev_head" > "$dotest/prev_head" # onto the next patch: @@ -82,7 +83,7 @@ call_merge () { rv=$? case "$rv" in 0) - git-commit -C "$cmt" || die "commit failed: $MRESOLVEMSG" + return ;; 1) test -d "$GIT_DIR/rr-cache" && git-rerere @@ -100,23 +101,6 @@ call_merge () { } finish_rb_merge () { - set -e - - msgnum=1 - echo "Finalizing rebased commits..." - git-reset --hard "`cat $dotest/onto`" - end="`cat $dotest/end`" - while test "$msgnum" -le "$end" - do - git-read-tree `cat "$dotest/cmt.$msgnum.result"` - git-checkout-index -q -f -u -a - git-commit -C "`cat $dotest/cmt.$msgnum`" - - printf "Committed %0${prec}d" $msgnum - echo ' '`git-rev-list --pretty=oneline -1 HEAD | \ - sed 's/^[a-f0-9]\+ //'` - msgnum=$(($msgnum + 1)) - done rm -r "$dotest" echo "All done." } @@ -153,7 +137,18 @@ do --skip) if test -d "$dotest" then - die "--skip is not supported when using --merge" + prev_head="`cat $dotest/prev_head`" + end="`cat $dotest/end`" + msgnum="`cat $dotest/msgnum`" + msgnum=$(($msgnum + 1)) + onto="`cat $dotest/onto`" + while test "$msgnum" -le "$end" + do + call_merge "$msgnum" + continue_merge + done + finish_rb_merge + exit fi git am -3 --skip --resolvemsg="$RESOLVEMSG" exit diff --git a/http-fetch.c b/http-fetch.c index 2b63d89501..44eba5fd0d 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -584,8 +584,8 @@ static void process_alternates_response(void *callback_data) // skip 'objects' at end if (okay) { target = xmalloc(serverlen + posn - i - 6); - safe_strncpy(target, base, serverlen); - safe_strncpy(target + serverlen, data + i, posn - i - 6); + strlcpy(target, base, serverlen); + strlcpy(target + serverlen, data + i, posn - i - 6); if (get_verbosely) fprintf(stderr, "Also look at %s\n", target); @@ -727,7 +727,7 @@ xml_cdata(void *userData, const XML_Char *s, int len) if (ctx->cdata) free(ctx->cdata); ctx->cdata = xmalloc(len + 1); - safe_strncpy(ctx->cdata, s, len + 1); + strlcpy(ctx->cdata, s, len + 1); } static int remote_ls(struct alt_base *repo, const char *path, int flags, diff --git a/http-push.c b/http-push.c index 8d472f0202..3c89a17496 100644 --- a/http-push.c +++ b/http-push.c @@ -1271,7 +1271,7 @@ xml_cdata(void *userData, const XML_Char *s, int len) if (ctx->cdata) free(ctx->cdata); ctx->cdata = xmalloc(len + 1); - safe_strncpy(ctx->cdata, s, len + 1); + strlcpy(ctx->cdata, s, len + 1); } static struct remote_lock *lock_remote(char *path, long timeout) @@ -1473,7 +1473,7 @@ static void process_ls_object(struct remote_ls_ctx *ls) return; path += 8; obj_hex = xmalloc(strlen(path)); - safe_strncpy(obj_hex, path, 3); + strlcpy(obj_hex, path, 3); strcpy(obj_hex + 2, path + 3); one_remote_object(obj_hex); free(obj_hex); @@ -2172,7 +2172,7 @@ static void fetch_symref(char *path, char **symref, unsigned char *sha1) /* If it's a symref, set the refname; otherwise try for a sha1 */ if (!strncmp((char *)buffer.buffer, "ref: ", 5)) { *symref = xmalloc(buffer.posn - 5); - safe_strncpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 5); + strlcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 5); } else { get_sha1_hex(buffer.buffer, sha1); } @@ -71,9 +71,9 @@ int setup_ident(void) len = strlen(git_default_email); git_default_email[len++] = '.'; if (he && (domainname = strchr(he->h_name, '.'))) - safe_strncpy(git_default_email + len, domainname + 1, sizeof(git_default_email) - len); + strlcpy(git_default_email + len, domainname + 1, sizeof(git_default_email) - len); else - safe_strncpy(git_default_email + len, "(none)", sizeof(git_default_email) - len); + strlcpy(git_default_email + len, "(none)", sizeof(git_default_email) - len); } /* And set the default date */ datestamp(git_default_date, sizeof(git_default_date)); diff --git a/merge-index.c b/merge-index.c index 190e12fb7c..0498a6f45e 100644 --- a/merge-index.c +++ b/merge-index.c @@ -1,5 +1,6 @@ #include <sys/types.h> #include <sys/wait.h> +#include <signal.h> #include "cache.h" @@ -77,25 +77,12 @@ int git_mkstemp(char *path, size_t len, const char *template) pch += n; } - safe_strncpy(pch, template, len); + strlcpy(pch, template, len); return mkstemp(path); } -size_t safe_strncpy(char *dest, const char *src, size_t size) -{ - size_t ret = strlen(src); - - if (size) { - size_t len = (ret >= size) ? size - 1 : ret; - memcpy(dest, src, len); - dest[len] = '\0'; - } - return ret; -} - - int validate_symref(const char *path) { struct stat st; diff --git a/pkt-line.h b/pkt-line.h index 9abef24de3..9df653f6f5 100644 --- a/pkt-line.h +++ b/pkt-line.h @@ -1,6 +1,8 @@ #ifndef PKTLINE_H #define PKTLINE_H +#include "git-compat-util.h" + /* * Silly packetized line writing interface */ diff --git a/sha1_name.c b/sha1_name.c index cd85d1fa0f..f2cbafa496 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -262,7 +262,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) if (str[am] == '@' && str[am+1] == '{' && str[len-1] == '}') { int date_len = len - am - 3; char *date_spec = xmalloc(date_len + 1); - safe_strncpy(date_spec, str + am + 2, date_len + 1); + strlcpy(date_spec, str + am + 2, date_len + 1); at_time = approxidate(date_spec); free(date_spec); len = am; diff --git a/t/t3401-rebase-partial.sh b/t/t3401-rebase-partial.sh index 32dc9c5e74..360a67060e 100755 --- a/t/t3401-rebase-partial.sh +++ b/t/t3401-rebase-partial.sh @@ -37,7 +37,9 @@ test_expect_success \ test_expect_success \ 'pick top patch from topic branch into master' \ 'git-cherry-pick my-topic-branch^0 && - git-checkout -f my-topic-branch + git-checkout -f my-topic-branch && + git-branch master-merge master && + git-branch my-topic-branch-merge my-topic-branch ' test_debug \ @@ -50,4 +52,13 @@ test_expect_success \ 'rebase topic branch against new master and check git-am did not get halted' \ 'git-rebase master && test ! -d .dotest' +if test -z "$no_python" +then + test_expect_success \ + 'rebase --merge topic branch that was partially merged upstream' \ + 'git-checkout -f my-topic-branch-merge && + git-rebase --merge master-merge && + test ! -d .git/.dotest-merge' +fi + test_done diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh new file mode 100755 index 0000000000..8ab63c5276 --- /dev/null +++ b/t/t3403-rebase-skip.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# +# Copyright (c) 2006 Eric Wong +# + +test_description='git rebase --merge --skip tests' + +. ./test-lib.sh + +# we assume the default git-am -3 --skip strategy is tested independently +# and always works :) + +if test "$no_python"; then + echo "Skipping: no python => no recursive merge" + test_done + exit 0 +fi + +test_expect_success setup ' + echo hello > hello && + git add hello && + git commit -m "hello" && + git branch skip-reference && + + echo world >> hello && + git commit -a -m "hello world" && + echo goodbye >> hello && + git commit -a -m "goodbye" && + + git checkout -f skip-reference && + echo moo > hello && + git commit -a -m "we should skip this" && + echo moo > cow && + git add cow && + git commit -m "this should not be skipped" && + git branch pre-rebase skip-reference && + git branch skip-merge skip-reference + ' + +test_expect_failure 'rebase with git am -3 (default)' 'git rebase master' + +test_expect_success 'rebase --skip with am -3' ' + git reset --hard HEAD && + git rebase --skip + ' +test_expect_success 'checkout skip-merge' 'git checkout -f skip-merge' + +test_expect_failure 'rebase with --merge' 'git rebase --merge master' + +test_expect_success 'rebase --skip with --merge' ' + git reset --hard HEAD && + git rebase --skip + ' + +test_expect_success 'merge and reference trees equal' \ + 'test -z "`git-diff-tree skip-merge skip-reference`"' + +test_debug 'gitk --all & sleep 1' + +test_done + diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index 2540e8a2cc..2ce10b4c0d 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -29,6 +29,9 @@ extern "C" { #define XDF_NEED_MINIMAL (1 << 1) +#define XDF_IGNORE_WHITESPACE (1 << 2) +#define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3) +#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE) #define XDL_PATCH_NORMAL '-' #define XDL_PATCH_REVERSE '+' diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c index b95ade2c1b..ed7ad2041c 100644 --- a/xdiff/xdiffi.c +++ b/xdiff/xdiffi.c @@ -45,7 +45,7 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1, long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl, xdalgoenv_t *xenv); static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2); -static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo); +static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags); @@ -397,7 +397,7 @@ static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, } -static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo) { +static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) { long ix, ixo, ixs, ixref, grpsiz, nrec = xdf->nrec; char *rchg = xdf->rchg, *rchgo = xdfo->rchg; xrecord_t **recs = xdf->recs; @@ -440,7 +440,7 @@ static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo) { * the group. */ while (ixs > 0 && recs[ixs - 1]->ha == recs[ix - 1]->ha && - XDL_RECMATCH(recs[ixs - 1], recs[ix - 1])) { + xdl_recmatch(recs[ixs - 1]->ptr, recs[ixs - 1]->size, recs[ix - 1]->ptr, recs[ix - 1]->size, flags)) { rchg[--ixs] = 1; rchg[--ix] = 0; @@ -468,7 +468,7 @@ static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo) { * the group. */ while (ix < nrec && recs[ixs]->ha == recs[ix]->ha && - XDL_RECMATCH(recs[ixs], recs[ix])) { + xdl_recmatch(recs[ixs]->ptr, recs[ixs]->size, recs[ix]->ptr, recs[ix]->size, flags)) { rchg[ixs++] = 0; rchg[ix++] = 1; @@ -546,8 +546,8 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, return -1; } - if (xdl_change_compact(&xe.xdf1, &xe.xdf2) < 0 || - xdl_change_compact(&xe.xdf2, &xe.xdf1) < 0 || + if (xdl_change_compact(&xe.xdf1, &xe.xdf2, xpp->flags) < 0 || + xdl_change_compact(&xe.xdf2, &xe.xdf1, xpp->flags) < 0 || xdl_build_script(&xe, &xscr) < 0) { xdl_free_env(&xe); diff --git a/xdiff/xdiffi.h b/xdiff/xdiffi.h index dd8f3c986b..d3b72716b5 100644 --- a/xdiff/xdiffi.h +++ b/xdiff/xdiffi.h @@ -55,6 +55,5 @@ void xdl_free_script(xdchange_t *xscr); int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg); - #endif /* #if !defined(XDIFFI_H) */ diff --git a/xdiff/xmacros.h b/xdiff/xmacros.h index 78f02603b8..4c2fde80c1 100644 --- a/xdiff/xmacros.h +++ b/xdiff/xmacros.h @@ -33,7 +33,6 @@ #define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9') #define XDL_HASHLONG(v, b) (((unsigned long)(v) * GR_PRIME) >> ((CHAR_BIT * sizeof(unsigned long)) - (b))) #define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0) -#define XDL_RECMATCH(r1, r2) ((r1)->size == (r2)->size && memcmp((r1)->ptr, (r2)->ptr, (r1)->size) == 0) #define XDL_LE32_PUT(p, v) \ do { \ unsigned char *__p = (unsigned char *) (p); \ diff --git a/xdiff/xprepare.c b/xdiff/xprepare.c index add5a75c77..1be7b31950 100644 --- a/xdiff/xprepare.c +++ b/xdiff/xprepare.c @@ -43,12 +43,13 @@ typedef struct s_xdlclassifier { xdlclass_t **rchash; chastore_t ncha; long count; + long flags; } xdlclassifier_t; -static int xdl_init_classifier(xdlclassifier_t *cf, long size); +static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags); static void xdl_free_classifier(xdlclassifier_t *cf); static int xdl_classify_record(xdlclassifier_t *cf, xrecord_t **rhash, unsigned int hbits, xrecord_t *rec); @@ -63,9 +64,11 @@ static int xdl_optimize_ctxs(xdfile_t *xdf1, xdfile_t *xdf2); -static int xdl_init_classifier(xdlclassifier_t *cf, long size) { +static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags) { long i; + cf->flags = flags; + cf->hbits = xdl_hashbits((unsigned int) size); cf->hsize = 1 << cf->hbits; @@ -103,8 +106,9 @@ static int xdl_classify_record(xdlclassifier_t *cf, xrecord_t **rhash, unsigned line = rec->ptr; hi = (long) XDL_HASHLONG(rec->ha, cf->hbits); for (rcrec = cf->rchash[hi]; rcrec; rcrec = rcrec->next) - if (rcrec->ha == rec->ha && rcrec->size == rec->size && - !memcmp(line, rcrec->line, rec->size)) + if (rcrec->ha == rec->ha && + xdl_recmatch(rcrec->line, rcrec->size, + rec->ptr, rec->size, cf->flags)) break; if (!rcrec) { @@ -173,7 +177,7 @@ static int xdl_prepare_ctx(mmfile_t *mf, long narec, xpparam_t const *xpp, top = blk + bsize; } prev = cur; - hav = xdl_hash_record(&cur, top); + hav = xdl_hash_record(&cur, top, xpp->flags); if (nrec >= narec) { narec *= 2; if (!(rrecs = (xrecord_t **) xdl_realloc(recs, narec * sizeof(xrecord_t *)))) { @@ -268,7 +272,7 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, enl1 = xdl_guess_lines(mf1) + 1; enl2 = xdl_guess_lines(mf2) + 1; - if (xdl_init_classifier(&cf, enl1 + enl2 + 1) < 0) { + if (xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0) { return -1; } diff --git a/xdiff/xutils.c b/xdiff/xutils.c index f91b403475..f7bdd395ad 100644 --- a/xdiff/xutils.c +++ b/xdiff/xutils.c @@ -186,12 +186,61 @@ long xdl_guess_lines(mmfile_t *mf) { return nl + 1; } +int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags) +{ + int i1, i2; + + if (flags & XDF_IGNORE_WHITESPACE) { + for (i1 = i2 = 0; i1 < s1 && i2 < s2; i1++, i2++) { + if (isspace(l1[i1])) + while (isspace(l1[i1]) && i1 < s1) + i1++; + else if (isspace(l2[i2])) + while (isspace(l2[i2]) && i2 < s2) + i2++; + else if (l1[i1] != l2[i2]) + return l2[i2] - l1[i1]; + } + if (i1 >= s1) + return 1; + else if (i2 >= s2) + return -1; + } else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) { + for (i1 = i2 = 0; i1 < s1 && i2 < s2; i1++, i2++) { + if (isspace(l1[i1])) { + if (!isspace(l2[i2])) + return -1; + while (isspace(l1[i1]) && i1 < s1) + i1++; + while (isspace(l2[i2]) && i2 < s2) + i2++; + } else if (l1[i1] != l2[i2]) + return l2[i2] - l1[i1]; + } + if (i1 >= s1) + return 1; + else if (i2 >= s2) + return -1; + } else + return s1 == s2 && !memcmp(l1, l2, s1); + + return 0; +} -unsigned long xdl_hash_record(char const **data, char const *top) { +unsigned long xdl_hash_record(char const **data, char const *top, long flags) { unsigned long ha = 5381; char const *ptr = *data; for (; ptr < top && *ptr != '\n'; ptr++) { + if (isspace(*ptr) && (flags & XDF_WHITESPACE_FLAGS)) { + while (ptr < top && isspace(*ptr) && ptr[1] != '\n') + ptr++; + if (flags & XDF_IGNORE_WHITESPACE_CHANGE) { + ha += (ha << 5); + ha ^= (unsigned long) ' '; + } + continue; + } ha += (ha << 5); ha ^= (unsigned long) *ptr; } diff --git a/xdiff/xutils.h b/xdiff/xutils.h index 08691a2447..70d8b9838a 100644 --- a/xdiff/xutils.h +++ b/xdiff/xutils.h @@ -34,7 +34,8 @@ void *xdl_cha_alloc(chastore_t *cha); void *xdl_cha_first(chastore_t *cha); void *xdl_cha_next(chastore_t *cha); long xdl_guess_lines(mmfile_t *mf); -unsigned long xdl_hash_record(char const **data, char const *top); +int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags); +unsigned long xdl_hash_record(char const **data, char const *top, long flags); unsigned int xdl_hashbits(unsigned int size); int xdl_num_out(char *out, long val); long xdl_atol(char const *str, char const **next); |