diff options
-rw-r--r-- | Documentation/diff-options.txt | 3 | ||||
-rw-r--r-- | Documentation/git-apply.txt | 8 | ||||
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | apply.c | 123 | ||||
-rw-r--r-- | combine-diff.c | 12 | ||||
-rw-r--r-- | diff.c | 83 | ||||
-rw-r--r-- | diff.h | 3 | ||||
-rw-r--r-- | http-fetch.c | 8 | ||||
-rw-r--r-- | http-push.c | 6 |
9 files changed, 199 insertions, 61 deletions
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index ec6811c71..338014c81 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -4,6 +4,9 @@ -u:: Synonym for "-p". +--patch-with-raw:: + Generate patch but keep also the default raw diff output. + -z:: \0 line termination on output diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index 1c64a1aa8..e93ea1f26 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -11,7 +11,7 @@ SYNOPSIS [verse] 'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] - [--whitespace=<nowarn|warn|error|error-all|strip>] + [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] [<patch>...] DESCRIPTION @@ -73,6 +73,12 @@ OPTIONS Remove <n> leading slashes from traditional diff paths. The default is 1. +-C<n>:: + Ensure at least <n> lines of surrounding context match before + and after each change. When fewer lines of surrounding + context exist they all most match. By default no context is + ever ignored. + --apply:: If you use any of the options marked ``Turns off "apply"'' above, git-apply reads and outputs the @@ -116,7 +116,7 @@ SCRIPT_SH = \ git-add.sh git-bisect.sh git-branch.sh git-checkout.sh \ git-cherry.sh git-clean.sh git-clone.sh git-commit.sh \ git-count-objects.sh git-diff.sh git-fetch.sh \ - git-format-patch.sh git-log.sh git-ls-remote.sh \ + git-format-patch.sh git-ls-remote.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 \ @@ -167,6 +167,8 @@ PROGRAMS = \ git-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \ git-describe$X git-merge-tree$X git-blame$X git-imap-send$X +BUILT_INS = git-log$X + # what 'all' will build and 'install' will install, in gitexecdir ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS) @@ -246,6 +248,10 @@ ifeq ($(uname_S),SunOS) NO_UNSETENV = YesPlease NO_SETENV = YesPlease endif + ifeq ($(uname_R),5.9) + NO_UNSETENV = YesPlease + NO_SETENV = YesPlease + endif INSTALL = ginstall TAR = gtar ALL_CFLAGS += -D__EXTENSIONS__ @@ -448,7 +454,7 @@ LIB_OBJS += $(COMPAT_OBJS) export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir ### Build rules -all: $(ALL_PROGRAMS) git$X gitk +all: $(ALL_PROGRAMS) $(BUILT_INS) git$X gitk all: $(MAKE) -C templates @@ -461,6 +467,9 @@ git$X: git.c common-cmds.h $(GITLIBS) $(ALL_CFLAGS) -o $@ $(filter %.c,$^) \ $(ALL_LDFLAGS) $(LIBS) +$(BUILT_INS): git$X + rm -f $@ && ln git$X $@ + common-cmds.h: Documentation/git-*.txt ./generate-cmdlist.sh > $@ @@ -612,6 +621,7 @@ install: all $(MAKE) -C templates install $(INSTALL) -d -m755 '$(DESTDIR_SQ)$(GIT_PYTHON_DIR_SQ)' $(INSTALL) $(PYMODULES) '$(DESTDIR_SQ)$(GIT_PYTHON_DIR_SQ)' + $(foreach p,$(BUILT_INS), rm -f '$(DESTDIR_SQ)$(bindir_SQ)/$p' && ln '$(DESTDIR_SQ)$(bindir_SQ)/git$X' '$(DESTDIR_SQ)$(bindir_SQ)/$p' ;) install-doc: $(MAKE) -C Documentation install @@ -32,8 +32,9 @@ static int apply = 1; static int no_add = 0; static int show_index_info = 0; static int line_termination = '\n'; +static unsigned long p_context = -1; static const char apply_usage[] = -"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>..."; +"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>..."; static enum whitespace_eol { nowarn_whitespace, @@ -100,6 +101,7 @@ static int max_change, max_len; static int linenr = 1; struct fragment { + unsigned long leading, trailing; unsigned long oldpos, oldlines; unsigned long newpos, newlines; const char *patch; @@ -817,12 +819,15 @@ static int parse_fragment(char *line, unsigned long size, struct patch *patch, s int added, deleted; int len = linelen(line, size), offset; unsigned long oldlines, newlines; + unsigned long leading, trailing; offset = parse_fragment_header(line, len, fragment); if (offset < 0) return -1; oldlines = fragment->oldlines; newlines = fragment->newlines; + leading = 0; + trailing = 0; if (patch->is_new < 0) { patch->is_new = !oldlines; @@ -860,10 +865,14 @@ static int parse_fragment(char *line, unsigned long size, struct patch *patch, s case ' ': oldlines--; newlines--; + if (!deleted && !added) + leading++; + trailing++; break; case '-': deleted++; oldlines--; + trailing = 0; break; case '+': /* @@ -887,6 +896,7 @@ static int parse_fragment(char *line, unsigned long size, struct patch *patch, s } added++; newlines--; + trailing = 0; break; /* We allow "\ No newline at end of file". Depending @@ -904,6 +914,9 @@ static int parse_fragment(char *line, unsigned long size, struct patch *patch, s } if (oldlines || newlines) return -1; + fragment->leading = leading; + fragment->trailing = trailing; + /* If a fragment ends with an incomplete line, we failed to include * it in the above loop because we hit oldlines == newlines == 0 * before seeing it. @@ -1087,7 +1100,7 @@ static int read_old_data(struct stat *st, const char *path, void *buf, unsigned } } -static int find_offset(const char *buf, unsigned long size, const char *fragment, unsigned long fragsize, int line) +static int find_offset(const char *buf, unsigned long size, const char *fragment, unsigned long fragsize, int line, int *lines) { int i; unsigned long start, backwards, forwards; @@ -1148,6 +1161,7 @@ static int find_offset(const char *buf, unsigned long size, const char *fragment n = (i >> 1)+1; if (i & 1) n = -n; + *lines = n; return try; } @@ -1157,6 +1171,33 @@ static int find_offset(const char *buf, unsigned long size, const char *fragment return -1; } +static void remove_first_line(const char **rbuf, int *rsize) +{ + const char *buf = *rbuf; + int size = *rsize; + unsigned long offset; + offset = 0; + while (offset <= size) { + if (buf[offset++] == '\n') + break; + } + *rsize = size - offset; + *rbuf = buf + offset; +} + +static void remove_last_line(const char **rbuf, int *rsize) +{ + const char *buf = *rbuf; + int size = *rsize; + unsigned long offset; + offset = size - 1; + while (offset > 0) { + if (buf[--offset] == '\n') + break; + } + *rsize = offset + 1; +} + struct buffer_desc { char *buffer; unsigned long size; @@ -1192,7 +1233,10 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) int offset, size = frag->size; char *old = xmalloc(size); char *new = xmalloc(size); + const char *oldlines, *newlines; int oldsize = 0, newsize = 0; + unsigned long leading, trailing; + int pos, lines; while (size > 0) { int len = linelen(patch, size); @@ -1241,23 +1285,59 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) newsize--; } #endif - - offset = find_offset(buf, desc->size, old, oldsize, frag->newpos); - if (offset >= 0) { - int diff = newsize - oldsize; - unsigned long size = desc->size + diff; - unsigned long alloc = desc->alloc; - - if (size > alloc) { - alloc = size + 8192; - desc->alloc = alloc; - buf = xrealloc(buf, alloc); - desc->buffer = buf; + + oldlines = old; + newlines = new; + leading = frag->leading; + trailing = frag->trailing; + lines = 0; + pos = frag->newpos; + for (;;) { + offset = find_offset(buf, desc->size, oldlines, oldsize, pos, &lines); + if (offset >= 0) { + int diff = newsize - oldsize; + unsigned long size = desc->size + diff; + unsigned long alloc = desc->alloc; + + /* Warn if it was necessary to reduce the number + * of context lines. + */ + if ((leading != frag->leading) || (trailing != frag->trailing)) + fprintf(stderr, "Context reduced to (%ld/%ld) to apply fragment at %d\n", + leading, trailing, pos + lines); + + if (size > alloc) { + alloc = size + 8192; + desc->alloc = alloc; + buf = xrealloc(buf, alloc); + desc->buffer = buf; + } + desc->size = size; + memmove(buf + offset + newsize, buf + offset + oldsize, size - offset - newsize); + memcpy(buf + offset, newlines, newsize); + offset = 0; + + break; + } + + /* Am I at my context limits? */ + if ((leading <= p_context) && (trailing <= p_context)) + break; + /* Reduce the number of context lines + * Reduce both leading and trailing if they are equal + * otherwise just reduce the larger context. + */ + if (leading >= trailing) { + remove_first_line(&oldlines, &oldsize); + remove_first_line(&newlines, &newsize); + pos--; + leading--; + } + if (trailing > leading) { + remove_last_line(&oldlines, &oldsize); + remove_last_line(&newlines, &newsize); + trailing--; } - desc->size = size; - memmove(buf + offset + newsize, buf + offset + oldsize, size - offset - newsize); - memcpy(buf + offset, new, newsize); - offset = 0; } free(old); @@ -1882,6 +1962,7 @@ int main(int argc, char **argv) for (i = 1; i < argc; i++) { const char *arg = argv[i]; + char *end; int fd; if (!strcmp(arg, "-")) { @@ -1945,6 +2026,12 @@ int main(int argc, char **argv) line_termination = 0; continue; } + if (!strncmp(arg, "-C", 2)) { + p_context = strtoul(arg + 2, &end, 0); + if (*end != '\0') + die("unrecognized context count '%s'", arg + 2); + continue; + } if (!strncmp(arg, "--whitespace=", 13)) { whitespace_option = arg + 13; parse_whitespace_option(arg + 13); diff --git a/combine-diff.c b/combine-diff.c index eb0d757f4..5f6048b39 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -832,6 +832,7 @@ const char *diff_tree_combined_merge(const unsigned char *sha1, diffopts = *opt; diffopts.output_format = DIFF_FORMAT_NO_OUTPUT; + diffopts.with_raw = 0; diffopts.recursive = 1; /* count parents */ @@ -858,6 +859,17 @@ const char *diff_tree_combined_merge(const unsigned char *sha1, num_paths++; } if (num_paths) { + if (opt->with_raw) { + int saved_format = opt->output_format; + opt->output_format = DIFF_FORMAT_RAW; + for (p = paths; p; p = p->next) { + if (show_combined_diff(p, num_parent, dense, + header, opt)) + header = NULL; + } + opt->output_format = saved_format; + putchar(opt->line_termination); + } for (p = paths; p; p = p->next) { if (show_combined_diff(p, num_parent, dense, header, opt)) @@ -862,6 +862,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) const char *arg = av[0]; if (!strcmp(arg, "-p") || !strcmp(arg, "-u")) options->output_format = DIFF_FORMAT_PATCH; + else if (!strcmp(arg, "--patch-with-raw")) { + options->output_format = DIFF_FORMAT_PATCH; + options->with_raw = 1; + } else if (!strcmp(arg, "-z")) options->line_termination = 0; else if (!strncmp(arg, "-l", 2)) @@ -1048,13 +1052,13 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len) static void diff_flush_raw(struct diff_filepair *p, int line_termination, int inter_name_termination, - struct diff_options *options) + struct diff_options *options, + int output_format) { int two_paths; char status[10]; int abbrev = options->abbrev; const char *path_one, *path_two; - int output_format = options->output_format; path_one = p->one->path; path_two = p->two->path; @@ -1270,46 +1274,59 @@ static void diff_resolve_rename_copy(void) diff_debug_queue("resolve-rename-copy done", q); } -void diff_flush(struct diff_options *options) +static void flush_one_pair(struct diff_filepair *p, + int diff_output_format, + struct diff_options *options) { - struct diff_queue_struct *q = &diff_queued_diff; - int i; int inter_name_termination = '\t'; - int diff_output_format = options->output_format; int line_termination = options->line_termination; - if (!line_termination) inter_name_termination = 0; - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - - switch (p->status) { - case DIFF_STATUS_UNKNOWN: + switch (p->status) { + case DIFF_STATUS_UNKNOWN: + break; + case 0: + die("internal error in diff-resolve-rename-copy"); + break; + default: + switch (diff_output_format) { + case DIFF_FORMAT_PATCH: + diff_flush_patch(p, options); break; - case 0: - die("internal error in diff-resolve-rename-copy"); + case DIFF_FORMAT_RAW: + case DIFF_FORMAT_NAME_STATUS: + diff_flush_raw(p, line_termination, + inter_name_termination, + options, diff_output_format); + break; + case DIFF_FORMAT_NAME: + diff_flush_name(p, + inter_name_termination, + line_termination); + break; + case DIFF_FORMAT_NO_OUTPUT: break; - default: - switch (diff_output_format) { - case DIFF_FORMAT_PATCH: - diff_flush_patch(p, options); - break; - case DIFF_FORMAT_RAW: - case DIFF_FORMAT_NAME_STATUS: - diff_flush_raw(p, line_termination, - inter_name_termination, - options); - break; - case DIFF_FORMAT_NAME: - diff_flush_name(p, - inter_name_termination, - line_termination); - break; - case DIFF_FORMAT_NO_OUTPUT: - break; - } } + } +} + +void diff_flush(struct diff_options *options) +{ + struct diff_queue_struct *q = &diff_queued_diff; + int i; + int diff_output_format = options->output_format; + + if (options->with_raw) { + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + flush_one_pair(p, DIFF_FORMAT_RAW, options); + } + putchar(options->line_termination); + } + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + flush_one_pair(p, diff_output_format, options); diff_free_filepair(p); } free(q->queue); @@ -24,6 +24,7 @@ struct diff_options { const char *orderfile; const char *pickaxe; unsigned recursive:1, + with_raw:1, tree_in_recursive:1, full_index:1; int break_opt; @@ -116,6 +117,8 @@ extern void diffcore_std_no_resolve(struct diff_options *); " -z output diff-raw with lines terminated with NUL.\n" \ " -p output patch format.\n" \ " -u synonym for -p.\n" \ +" --patch-with-raw\n" \ +" output both a patch and the diff-raw format.\n" \ " --name-only show only names of changed files.\n" \ " --name-status show names and status of changed files.\n" \ " --full-index show full object name on index lines.\n" \ diff --git a/http-fetch.c b/http-fetch.c index 71a7dafd6..861644b27 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -597,7 +597,7 @@ static void process_alternates_response(void *callback_data) newalt->packs = NULL; path = strstr(target, "//"); if (path) { - path = index(path+2, '/'); + path = strchr(path+2, '/'); if (path) newalt->path_len = strlen(path); } @@ -678,7 +678,7 @@ static void xml_start_tag(void *userData, const char *name, const char **atts) { struct xml_ctx *ctx = (struct xml_ctx *)userData; - const char *c = index(name, ':'); + const char *c = strchr(name, ':'); int new_len; if (c == NULL) @@ -707,7 +707,7 @@ static void xml_end_tag(void *userData, const char *name) { struct xml_ctx *ctx = (struct xml_ctx *)userData; - const char *c = index(name, ':'); + const char *c = strchr(name, ':'); char *ep; ctx->userFunc(ctx, 1); @@ -1261,7 +1261,7 @@ int main(int argc, char **argv) alt->next = NULL; path = strstr(url, "//"); if (path) { - path = index(path+2, '/'); + path = strchr(path+2, '/'); if (path) alt->path_len = strlen(path); } diff --git a/http-push.c b/http-push.c index aa0bc1f6f..19a0f772e 100644 --- a/http-push.c +++ b/http-push.c @@ -1212,7 +1212,7 @@ static void xml_start_tag(void *userData, const char *name, const char **atts) { struct xml_ctx *ctx = (struct xml_ctx *)userData; - const char *c = index(name, ':'); + const char *c = strchr(name, ':'); int new_len; if (c == NULL) @@ -1241,7 +1241,7 @@ static void xml_end_tag(void *userData, const char *name) { struct xml_ctx *ctx = (struct xml_ctx *)userData; - const char *c = index(name, ':'); + const char *c = strchr(name, ':'); char *ep; ctx->userFunc(ctx, 1); @@ -2351,7 +2351,7 @@ int main(int argc, char **argv) char *path = strstr(arg, "//"); remote->url = arg; if (path) { - path = index(path+2, '/'); + path = strchr(path+2, '/'); if (path) remote->path_len = strlen(path); } |