diff options
37 files changed, 584 insertions, 169 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile index 6dbe45b506..0d9ffb4ad9 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -25,10 +25,10 @@ DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) prefix?=$(HOME) -bin=$(prefix)/bin -mandir=$(prefix)/man -man1=$(mandir)/man1 -man7=$(mandir)/man7 +bindir?=$(prefix)/bin +mandir?=$(prefix)/man +man1dir=$(mandir)/man1 +man7dir=$(mandir)/man7 # DESTDIR= INSTALL?=install @@ -53,9 +53,9 @@ man1: $(DOC_MAN1) man7: $(DOC_MAN7) install: man - $(INSTALL) -d -m755 $(DESTDIR)$(man1) $(DESTDIR)$(man7) - $(INSTALL) $(DOC_MAN1) $(DESTDIR)$(man1) - $(INSTALL) $(DOC_MAN7) $(DESTDIR)$(man7) + $(INSTALL) -d -m755 $(DESTDIR)$(man1dir) $(DESTDIR)$(man7dir) + $(INSTALL) $(DOC_MAN1) $(DESTDIR)$(man1dir) + $(INSTALL) $(DOC_MAN7) $(DESTDIR)$(man7dir) # diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt index 4c357daf6a..0f7d274eab 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@ -11,7 +11,7 @@ SYNOPSIS 'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all] [--timeout=n] [--init-timeout=n] [--strict-paths] [--base-path=path] [--user-path | --user-path=path] - [directory...] + [--reuseaddr] [--detach] [--pid-file=file] [directory...] DESCRIPTION ----------- @@ -82,6 +82,17 @@ OPTIONS --verbose:: Log details about the incoming connections and requested files. +--reuseaddr:: + Use SO_REUSEADDR when binding the listening socket. + This allows the server to restart without waiting for + old connections to time out. + +--detach:: + Detach from the shell. Implies --syslog. + +--pid-file=file:: + Save the process id in 'file'. + <directory>:: A directory to add to the whitelist of allowed directories. Unless --strict-paths is specified this will also include subdirectories diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 4ca0014dac..67425dc035 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -9,8 +9,9 @@ git-format-patch - Prepare patches for e-mail submission SYNOPSIS -------- [verse] -'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--attach] +'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--attach] [--thread] [-s | --signoff] [--diff-options] [--start-number <n>] + [--in-reply-to=Message-Id] <since>[..<until>] DESCRIPTION @@ -35,6 +36,10 @@ they are created in the current working directory. If -n is specified, instead of "[PATCH] Subject", the first line is formatted as "[PATCH n/m] Subject". +If given --thread, git-format-patch will generate In-Reply-To and +References headers to make the second and subsequent patch mails appear +as replies to the first mail; this also generates a Message-Id header to +reference. OPTIONS ------- @@ -63,6 +68,15 @@ OPTIONS --attach:: Create attachments instead of inlining patches. +--thread:: + Add In-Reply-To and References headers to make the second and + subsequent mails appear as replies to the first. Also generates + the Message-Id header to reference. + +--in-reply-to=Message-Id:: + Make the first mail (or all the mails with --no-thread) appear as a + reply to the given Message-Id, which avoids breaking threads to + provide a new patch series. CONFIGURATION ------------- diff --git a/Documentation/git.txt b/Documentation/git.txt index ce3058182f..7310a2b8b8 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -8,7 +8,8 @@ git - the stupid content tracker SYNOPSIS -------- -'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ARGS] +'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate] + [--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS] DESCRIPTION ----------- @@ -41,6 +42,15 @@ OPTIONS environment variable. If no path is given 'git' will print the current setting and then exit. +-p|--paginate:: + Pipe all output into 'less' (or if set, $PAGER). + +--git-dir=<path>:: + Set the path to the repository. This can also be controlled by + setting the GIT_DIR environment variable. + +--bare:: + Same as --git-dir=`pwd`. FURTHER DOCUMENTATION --------------------- @@ -116,6 +116,8 @@ template_dir = $(prefix)/share/git-core/templates/ GIT_PYTHON_DIR = $(prefix)/share/git-core/python # DESTDIR= +export prefix bindir gitexecdir template_dir GIT_PYTHON_DIR + CC = gcc AR = ar TAR = tar @@ -575,7 +577,7 @@ git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css -e '/@@GITWEB_CGI@@/d' \ -e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \ -e '/@@GITWEB_CSS@@/d' \ - $@.sh > $@+ + $@.sh | sed "s|/usr/bin/git|$(bindir)/git|" > $@+ chmod +x $@+ mv $@+ $@ @@ -612,6 +614,8 @@ $(SIMPLE_PROGRAMS) : git-%$X : %.o $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIB_FILE) $(SIMPLE_LIB) +ssh-pull.o: ssh-fetch.c +ssh-push.o: ssh-upload.c git-local-fetch$X: fetch.o git-ssh-fetch$X: rsh.o fetch.o git-ssh-upload$X: rsh.o @@ -753,8 +757,8 @@ dist-doc: rm -fr .doc-tmp-dir mkdir .doc-tmp-dir .doc-tmp-dir/man1 .doc-tmp-dir/man7 $(MAKE) -C Documentation DESTDIR=./ \ - man1=../.doc-tmp-dir/man1 \ - man7=../.doc-tmp-dir/man7 \ + man1dir=../.doc-tmp-dir/man1 \ + man7dir=../.doc-tmp-dir/man7 \ install cd .doc-tmp-dir && $(TAR) cf ../$(manpages).tar . gzip -n -9 -f $(manpages).tar diff --git a/builtin-add.c b/builtin-add.c index 2d25698173..3a73a173f7 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -21,8 +21,7 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p for (specs = 0; pathspec[specs]; specs++) /* nothing */; - seen = xmalloc(specs); - memset(seen, 0, specs); + seen = xcalloc(specs, 1); src = dst = dir->entries; i = dir->nr; diff --git a/builtin-apply.c b/builtin-apply.c index c903146bb6..d4381d9a8f 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -120,7 +120,7 @@ struct fragment { struct patch { char *new_name, *old_name, *def_name; unsigned int old_mode, new_mode; - int is_rename, is_copy, is_new, is_delete, is_binary; + int is_rename, is_copy, is_new, is_delete, is_binary, is_reverse; #define BINARY_DELTA_DEFLATED 1 #define BINARY_LITERAL_DEFLATED 2 unsigned long deflate_origlen; @@ -1119,6 +1119,34 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) return offset + hdrsize + patchsize; } +#define swap(a,b) myswap((a),(b),sizeof(a)) + +#define myswap(a, b, size) do { \ + unsigned char mytmp[size]; \ + memcpy(mytmp, &a, size); \ + memcpy(&a, &b, size); \ + memcpy(&b, mytmp, size); \ +} while (0) + +static void reverse_patches(struct patch *p) +{ + for (; p; p = p->next) { + struct fragment *frag = p->fragments; + + swap(p->new_name, p->old_name); + swap(p->new_mode, p->old_mode); + swap(p->is_new, p->is_delete); + swap(p->lines_added, p->lines_deleted); + swap(p->old_sha1_prefix, p->new_sha1_prefix); + + for (; frag; frag = frag->next) { + swap(frag->newpos, frag->oldpos); + swap(frag->newlines, frag->oldlines); + } + p->is_reverse = !p->is_reverse; + } +} + static const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; static const char minuses[]= "----------------------------------------------------------------------"; @@ -1336,7 +1364,7 @@ static int apply_line(char *output, const char *patch, int plen) } static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, - int inaccurate_eof) + int reverse, int inaccurate_eof) { int match_beginning, match_end; char *buf = desc->buffer; @@ -1350,6 +1378,7 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, int pos, lines; while (size > 0) { + char first; int len = linelen(patch, size); int plen; @@ -1366,16 +1395,23 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, plen = len-1; if (len < size && patch[len] == '\\') plen--; - switch (*patch) { + first = *patch; + if (reverse) { + if (first == '-') + first = '+'; + else if (first == '+') + first = '-'; + } + switch (first) { case ' ': case '-': memcpy(old + oldsize, patch + 1, plen); oldsize += plen; - if (*patch == '-') + if (first == '-') break; /* Fall-through for ' ' */ case '+': - if (*patch != '+' || !no_add) + if (first != '+' || !no_add) newsize += apply_line(new + newsize, patch, plen); break; @@ -1499,6 +1535,12 @@ static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch) void *data; void *result; + /* Binary patch is irreversible */ + if (patch->is_reverse) + return error("cannot reverse-apply a binary patch to '%s'", + patch->new_name + ? patch->new_name : patch->old_name); + data = inflate_it(fragment->patch, fragment->size, patch->deflate_origlen); if (!data) @@ -1615,7 +1657,8 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch) return apply_binary(desc, patch); while (frag) { - if (apply_one_fragment(desc, frag, patch->inaccurate_eof) < 0) + if (apply_one_fragment(desc, frag, patch->is_reverse, + patch->inaccurate_eof) < 0) return error("patch failed: %s:%ld", name, frag->oldpos); frag = frag->next; @@ -1664,13 +1707,14 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry * return 0; } -static int check_patch(struct patch *patch) +static int check_patch(struct patch *patch, struct patch *prev_patch) { struct stat st; const char *old_name = patch->old_name; const char *new_name = patch->new_name; const char *name = old_name ? old_name : new_name; struct cache_entry *ce = NULL; + int ok_if_exists; if (old_name) { int changed = 0; @@ -1728,13 +1772,33 @@ static int check_patch(struct patch *patch) old_name, st_mode, patch->old_mode); } + if (new_name && prev_patch && prev_patch->is_delete && + !strcmp(prev_patch->old_name, new_name)) + /* A type-change diff is always split into a patch to + * delete old, immediately followed by a patch to + * create new (see diff.c::run_diff()); in such a case + * it is Ok that the entry to be deleted by the + * previous patch is still in the working tree and in + * the index. + */ + ok_if_exists = 1; + else + ok_if_exists = 0; + if (new_name && (patch->is_new | patch->is_rename | patch->is_copy)) { - if (check_index && cache_name_pos(new_name, strlen(new_name)) >= 0) + if (check_index && + cache_name_pos(new_name, strlen(new_name)) >= 0 && + !ok_if_exists) return error("%s: already exists in index", new_name); if (!cached) { - if (!lstat(new_name, &st)) - return error("%s: already exists in working directory", new_name); - if (errno != ENOENT) + struct stat nst; + if (!lstat(new_name, &nst)) { + if (S_ISDIR(nst.st_mode) || ok_if_exists) + ; /* ok */ + else + return error("%s: already exists in working directory", new_name); + } + else if ((errno != ENOENT) && (errno != ENOTDIR)) return error("%s: %s", new_name, strerror(errno)); } if (!patch->new_mode) { @@ -1762,10 +1826,13 @@ static int check_patch(struct patch *patch) static int check_patch_list(struct patch *patch) { + struct patch *prev_patch = NULL; int error = 0; - for (;patch ; patch = patch->next) - error |= check_patch(patch); + for (prev_patch = NULL; patch ; patch = patch->next) { + error |= check_patch(patch, prev_patch); + prev_patch = patch; + } return error; } @@ -2010,6 +2077,16 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned return; } + if (errno == EEXIST || errno == EACCES) { + /* We may be trying to create a file where a directory + * used to be. + */ + struct stat st; + errno = 0; + if (!lstat(path, &st) && S_ISDIR(st.st_mode) && !rmdir(path)) + errno = EEXIST; + } + if (errno == EEXIST) { unsigned int nr = getpid(); @@ -2044,32 +2121,42 @@ static void create_file(struct patch *patch) cache_tree_invalidate_path(active_cache_tree, path); } -static void write_out_one_result(struct patch *patch) +/* phase zero is to remove, phase one is to create */ +static void write_out_one_result(struct patch *patch, int phase) { if (patch->is_delete > 0) { - remove_file(patch); + if (phase == 0) + remove_file(patch); return; } if (patch->is_new > 0 || patch->is_copy) { - create_file(patch); + if (phase == 1) + create_file(patch); return; } /* * Rename or modification boils down to the same * thing: remove the old, write the new */ - remove_file(patch); + if (phase == 0) + remove_file(patch); + if (phase == 1) create_file(patch); } static void write_out_results(struct patch *list, int skipped_patch) { + int phase; + if (!list && !skipped_patch) die("No changes"); - while (list) { - write_out_one_result(list); - list = list->next; + for (phase = 0; phase < 2; phase++) { + struct patch *l = list; + while (l) { + write_out_one_result(l, phase); + l = l->next; + } } } @@ -2098,7 +2185,8 @@ static int use_patch(struct patch *p) return 1; } -static int apply_patch(int fd, const char *filename, int inaccurate_eof) +static int apply_patch(int fd, const char *filename, + int reverse, int inaccurate_eof) { unsigned long offset, size; char *buffer = read_patch_file(fd, &size); @@ -2118,6 +2206,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof) nr = parse_chunk(buffer + offset, size, patch); if (nr < 0) break; + if (reverse) + reverse_patches(patch); if (use_patch(patch)) { patch_stats(patch); *listp = patch; @@ -2182,6 +2272,7 @@ int cmd_apply(int argc, const char **argv, char **envp) { int i; int read_stdin = 1; + int reverse = 0; int inaccurate_eof = 0; const char *whitespace_option = NULL; @@ -2192,7 +2283,7 @@ int cmd_apply(int argc, const char **argv, char **envp) int fd; if (!strcmp(arg, "-")) { - apply_patch(0, "<stdin>", inaccurate_eof); + apply_patch(0, "<stdin>", reverse, inaccurate_eof); read_stdin = 0; continue; } @@ -2269,6 +2360,10 @@ int cmd_apply(int argc, const char **argv, char **envp) parse_whitespace_option(arg + 13); continue; } + if (!strcmp(arg, "-R") || !strcmp(arg, "--reverse")) { + reverse = 1; + continue; + } if (!strcmp(arg, "--inaccurate-eof")) { inaccurate_eof = 1; continue; @@ -2289,12 +2384,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, inaccurate_eof); + apply_patch(fd, arg, reverse, inaccurate_eof); close(fd); } set_default_whitespace_mode(whitespace_option); if (read_stdin) - apply_patch(0, "<stdin>", inaccurate_eof); + apply_patch(0, "<stdin>", reverse, inaccurate_eof); if (whitespace_error) { if (squelch_whitespace_errors && squelch_whitespace_errors < whitespace_error) { diff --git a/builtin-diff-files.c b/builtin-diff-files.c index 81ac2fe64a..2e10118623 100644 --- a/builtin-diff-files.c +++ b/builtin-diff-files.c @@ -18,8 +18,8 @@ int cmd_diff_files(int argc, const char **argv, char **envp) struct rev_info rev; int silent = 0; - git_config(git_default_config); /* no "diff" UI options */ init_revisions(&rev); + git_config(git_default_config); /* no "diff" UI options */ rev.abbrev = 0; argc = setup_revisions(argc, argv, &rev, NULL); diff --git a/builtin-diff-index.c b/builtin-diff-index.c index a1fa1b85cf..dc52c054ee 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -15,8 +15,8 @@ int cmd_diff_index(int argc, const char **argv, char **envp) int cached = 0; int i; - git_config(git_default_config); /* no "diff" UI options */ init_revisions(&rev); + git_config(git_default_config); /* no "diff" UI options */ rev.abbrev = 0; argc = setup_revisions(argc, argv, &rev, NULL); diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index b610668594..8957b459de 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -67,9 +67,9 @@ int cmd_diff_tree(int argc, const char **argv, char **envp) static struct rev_info *opt = &log_tree_opt; int read_stdin = 0; + init_revisions(opt); git_config(git_default_config); /* no "diff" UI options */ nr_sha1 = 0; - init_revisions(opt); opt->abbrev = 0; opt->diff = 1; argc = setup_revisions(argc, argv, opt, NULL); diff --git a/builtin-diff.c b/builtin-diff.c index cb38f44561..dca223235d 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -250,8 +250,9 @@ int cmd_diff(int argc, const char **argv, char **envp) * Other cases are errors. */ - git_config(git_diff_ui_config); init_revisions(&rev); + git_config(git_diff_ui_config); + diff_setup(&rev.diffopt); argc = setup_revisions(argc, argv, &rev, NULL); if (!rev.diffopt.output_format) { @@ -346,7 +347,15 @@ int cmd_diff(int argc, const char **argv, char **envp) return builtin_diff_index(&rev, argc, argv); else if (ents == 2) return builtin_diff_tree(&rev, argc, argv, ent); + else if ((ents == 3) && (ent[0].item->flags & UNINTERESTING)) { + /* diff A...B where there is one sane merge base between + * A and B. We have ent[0] == merge-base, ent[1] == A, + * and ent[2] == B. Show diff between the base and B. + */ + return builtin_diff_tree(&rev, argc, argv, ent); + } else - return builtin_diff_combined(&rev, argc, argv, ent, ents); + return builtin_diff_combined(&rev, argc, argv, + ent, ents); usage(builtin_diff_usage); } diff --git a/builtin-help.c b/builtin-help.c index 335fe5fedc..bc1b4da3bc 100644 --- a/builtin-help.c +++ b/builtin-help.c @@ -229,7 +229,7 @@ int cmd_version(int argc, const char **argv, char **envp) int cmd_help(int argc, const char **argv, char **envp) { - const char *help_cmd = argv[1]; + const char *help_cmd = argc > 1 ? argv[1] : NULL; if (!help_cmd) cmd_usage(0, git_exec_path(), NULL); else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a")) diff --git a/builtin-log.c b/builtin-log.c index 7e5cab15c1..88c835acba 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -10,6 +10,8 @@ #include "revision.h" #include "log-tree.h" #include "builtin.h" +#include <time.h> +#include <sys/time.h> /* this is in builtin-diff.c */ void add_head(struct rev_info *revs); @@ -47,8 +49,9 @@ int cmd_whatchanged(int argc, const char **argv, char **envp) { struct rev_info rev; - git_config(git_diff_ui_config); init_revisions(&rev); + git_config(git_diff_ui_config); + diff_setup(&rev.diffopt); rev.diff = 1; rev.diffopt.recursive = 1; rev.simplify_history = 0; @@ -62,8 +65,9 @@ int cmd_show(int argc, const char **argv, char **envp) { struct rev_info rev; - git_config(git_diff_ui_config); init_revisions(&rev); + git_config(git_diff_ui_config); + diff_setup(&rev.diffopt); rev.diff = 1; rev.diffopt.recursive = 1; rev.combine_merges = 1; @@ -79,8 +83,9 @@ int cmd_log(int argc, const char **argv, char **envp) { struct rev_info rev; - git_config(git_diff_ui_config); init_revisions(&rev); + git_config(git_diff_ui_config); + diff_setup(&rev.diffopt); rev.always_show_header = 1; cmd_log_init(argc, argv, envp, &rev); return cmd_log_walk(&rev); @@ -226,6 +231,18 @@ static void get_patch_ids(struct rev_info *rev, struct diff_options *options) o2->flags = flags2; } +static void gen_message_id(char *dest, unsigned int length, char *base) +{ + const char *committer = git_committer_info(1); + const char *email_start = strrchr(committer, '<'); + const char *email_end = strrchr(committer, '>'); + if(!email_start || !email_end || email_start > email_end - 1) + die("Could not extract email from committer identity."); + snprintf(dest, length, "%s.%lu.git.%.*s", base, + (unsigned long) time(NULL), + (int)(email_end - email_start - 1), email_start + 1); +} + int cmd_format_patch(int argc, const char **argv, char **envp) { struct commit *commit; @@ -237,8 +254,12 @@ int cmd_format_patch(int argc, const char **argv, char **envp) int start_number = -1; int keep_subject = 0; int ignore_if_in_upstream = 0; + int thread = 0; + const char *in_reply_to = NULL; struct diff_options patch_id_opts; char *add_signoff = NULL; + char message_id[1024]; + char ref_message_id[1024]; git_config(git_format_config); init_revisions(&rev); @@ -304,6 +325,16 @@ int cmd_format_patch(int argc, const char **argv, char **envp) rev.mime_boundary = argv[i] + 9; else if (!strcmp(argv[i], "--ignore-if-in-upstream")) ignore_if_in_upstream = 1; + else if (!strcmp(argv[i], "--thread")) + thread = 1; + else if (!strncmp(argv[i], "--in-reply-to=", 14)) + in_reply_to = argv[i] + 14; + else if (!strcmp(argv[i], "--in-reply-to")) { + i++; + if (i == argc) + die("Need a Message-Id for --in-reply-to"); + in_reply_to = argv[i]; + } else argv[j++] = argv[i]; } @@ -361,10 +392,23 @@ int cmd_format_patch(int argc, const char **argv, char **envp) if (numbered) rev.total = total + start_number - 1; rev.add_signoff = add_signoff; + rev.ref_message_id = in_reply_to; while (0 <= --nr) { int shown; commit = list[nr]; rev.nr = total - nr + (start_number - 1); + /* Make the second and subsequent mails replies to the first */ + if (thread) { + if (nr == (total - 2)) { + strncpy(ref_message_id, message_id, + sizeof(ref_message_id)); + ref_message_id[sizeof(ref_message_id)-1]='\0'; + rev.ref_message_id = ref_message_id; + } + gen_message_id(message_id, sizeof(message_id), + sha1_to_hex(commit->object.sha1)); + rev.message_id = message_id; + } if (!use_stdout) reopen_stdout(commit, rev.nr, keep_subject); shown = log_tree_commit(&rev, commit); diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index ac53f76f68..05dc1bfe71 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -446,7 +446,7 @@ static int read_one_header_line(char *line, int sz, FILE *in) break; } /* Count mbox From headers as headers */ - if (!ofs && !memcmp(line, "From ", 5)) + if (!ofs && (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6))) ofs = 1; return ofs; } diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 6df5d7c5cb..122b6f130b 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -507,7 +507,7 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old) } merge->ce_flags &= ~htons(CE_STAGEMASK); - add_cache_entry(merge, ADD_CACHE_OK_TO_ADD); + add_cache_entry(merge, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); return 1; } @@ -518,7 +518,7 @@ static int deleted_entry(struct cache_entry *ce, struct cache_entry *old) else verify_absent(ce->name, "removed"); ce->ce_mode = 0; - add_cache_entry(ce, ADD_CACHE_OK_TO_ADD); + add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); invalidate_ce_path(ce); return 1; } diff --git a/builtin-rm.c b/builtin-rm.c index 5deb811719..bb810ba41a 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -90,8 +90,7 @@ int cmd_rm(int argc, const char **argv, char **envp) seen = NULL; for (i = 0; pathspec[i] ; i++) /* nothing */; - seen = xmalloc(i); - memset(seen, 0, i); + seen = xcalloc(i, 1); for (i = 0; i < active_nr; i++) { struct cache_entry *ce = active_cache[i]; diff --git a/combine-diff.c b/combine-diff.c index 1bc1484645..919112bba9 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -639,8 +639,7 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent, /* deleted file */ result_size = 0; elem->mode = 0; - result = xmalloc(1); - result[0] = 0; + result = xcalloc(1, 1); } if (0 <= fd) close(fd); diff --git a/contrib/emacs/Makefile b/contrib/emacs/Makefile index d3619db510..350846de90 100644 --- a/contrib/emacs/Makefile +++ b/contrib/emacs/Makefile @@ -3,9 +3,9 @@ EMACS = emacs ELC = git.elc vc-git.elc -INSTALL = install +INSTALL ?= install INSTALL_ELC = $(INSTALL) -m 644 -prefix = $(HOME) +prefix ?= $(HOME) emacsdir = $(prefix)/share/emacs/site-lisp all: $(ELC) @@ -19,7 +19,7 @@ static const char daemon_usage[] = "git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n" " [--timeout=n] [--init-timeout=n] [--strict-paths]\n" " [--base-path=path] [--user-path | --user-path=path]\n" -" [--reuseaddr] [directory...]"; +" [--reuseaddr] [--detach] [--pid-file=file] [directory...]"; /* List of acceptable pathname prefixes */ static char **ok_paths = NULL; diff --git a/git-clone.sh b/git-clone.sh index 0368803883..a92b22a13d 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -266,7 +266,7 @@ yes,yes) echo "$repo/objects" >> "$GIT_DIR/objects/info/alternates" ;; esac - git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" + git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1 ;; *) case "$repo" in @@ -296,7 +296,7 @@ yes,yes) done rm -f "$GIT_DIR/TMP_ALT" fi - git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" + git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1 ;; http://*) if test -z "@@NO_CURL@@" diff --git a/git-cvsserver.perl b/git-cvsserver.perl index c30ef70427..2130d57020 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -81,7 +81,7 @@ my $methods = { # $state holds all the bits of information the clients sends us that could # potentially be useful when it comes to actually _doing_ something. -my $state = {}; +my $state = { prependdir => '' }; $log->info("--------------- STARTING -----------------"); my $TEMP_DIR = tempdir( CLEANUP => 1 ); @@ -547,12 +547,15 @@ sub req_Argument { my ( $cmd, $data ) = @_; - # TODO : Not quite sure how Argument and Argumentx differ, but I assume - # it's for multi-line arguments ... somehow ... + # Argumentx means: append to last Argument (with a newline in front) $log->debug("$cmd : $data"); - push @{$state->{arguments}}, $data; + if ( $cmd eq 'Argumentx') { + ${$state->{arguments}}[$#{$state->{arguments}}] .= "\n" . $data; + } else { + push @{$state->{arguments}}, $data; + } } # expand-modules \n @@ -1139,9 +1142,7 @@ sub req_ci exit; } - open FILE, ">", "$ENV{GIT_DIR}refs/heads/$state->{module}"; - print FILE $commithash; - close FILE; + print LOCKFILE $commithash; $updater->update(); @@ -1168,7 +1169,9 @@ sub req_ci } close LOCKFILE; - unlink($lockfile); + my $reffile = "$ENV{GIT_DIR}refs/heads/$state->{module}"; + unlink($reffile); + rename($lockfile, $reffile); chdir "/"; print "ok\n"; @@ -2129,12 +2132,6 @@ sub update # first lets get the commit list $ENV{GIT_DIR} = $self->{git_path}; - # prepare database queries - my $db_insert_rev = $self->{dbh}->prepare_cached("INSERT INTO revision (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1); - my $db_insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO commitmsgs (key, value) VALUES (?,?)",{},1); - my $db_delete_head = $self->{dbh}->prepare_cached("DELETE FROM head",{},1); - my $db_insert_head = $self->{dbh}->prepare_cached("INSERT INTO head (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1); - my $commitinfo = `git-cat-file commit $self->{module} 2>&1`; unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{40}/ ) { @@ -2323,7 +2320,7 @@ sub update author => $commit->{author}, mode => $git_perms, }; - $db_insert_rev->execute($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms); + $self->insert_rev($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms); } elsif ( $3 eq "M" ) { @@ -2337,7 +2334,7 @@ sub update author => $commit->{author}, mode => $git_perms, }; - $db_insert_rev->execute($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms); + $self->insert_rev($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms); } elsif ( $3 eq "A" ) { @@ -2351,7 +2348,7 @@ sub update author => $commit->{author}, mode => $git_perms, }; - $db_insert_rev->execute($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms); + $self->insert_rev($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms); } else { @@ -2408,7 +2405,7 @@ sub update }; - $db_insert_rev->execute($git_filename, $newrevision, $git_hash, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms); + $self->insert_rev($git_filename, $newrevision, $git_hash, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms); } } close FILELIST; @@ -2424,7 +2421,7 @@ sub update $head->{$file}{modified} = $commit->{date}; $head->{$file}{author} = $commit->{author}; - $db_insert_rev->execute($file, $head->{$file}{revision}, $head->{$file}{filehash}, $commit->{hash}, $commit->{date}, $commit->{author}, $head->{$file}{mode}); + $self->insert_rev($file, $head->{$file}{revision}, $head->{$file}{filehash}, $commit->{hash}, $commit->{date}, $commit->{author}, $head->{$file}{mode}); } } # END : "Detect deleted files" @@ -2433,7 +2430,7 @@ sub update if (exists $commit->{mergemsg}) { - $db_insert_mergelog->execute($commit->{hash}, $commit->{mergemsg}); + $self->insert_mergelog($commit->{hash}, $commit->{mergemsg}); } $lastpicked = $commit->{hash}; @@ -2441,10 +2438,10 @@ sub update $self->_set_prop("last_commit", $commit->{hash}); } - $db_delete_head->execute(); + $self->delete_head(); foreach my $file ( keys %$head ) { - $db_insert_head->execute( + $self->insert_head( $file, $head->{$file}{revision}, $head->{$file}{filehash}, @@ -2462,6 +2459,54 @@ sub update $self->{dbh}->commit() or die "Failed to commit changes to SQLite"; } +sub insert_rev +{ + my $self = shift; + my $name = shift; + my $revision = shift; + my $filehash = shift; + my $commithash = shift; + my $modified = shift; + my $author = shift; + my $mode = shift; + + my $insert_rev = $self->{dbh}->prepare_cached("INSERT INTO revision (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1); + $insert_rev->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode); +} + +sub insert_mergelog +{ + my $self = shift; + my $key = shift; + my $value = shift; + + my $insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO commitmsgs (key, value) VALUES (?,?)",{},1); + $insert_mergelog->execute($key, $value); +} + +sub delete_head +{ + my $self = shift; + + my $delete_head = $self->{dbh}->prepare_cached("DELETE FROM head",{},1); + $delete_head->execute(); +} + +sub insert_head +{ + my $self = shift; + my $name = shift; + my $revision = shift; + my $filehash = shift; + my $commithash = shift; + my $modified = shift; + my $author = shift; + my $mode = shift; + + my $insert_head = $self->{dbh}->prepare_cached("INSERT INTO head (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1); + $insert_head->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode); +} + sub _headrev { my $self = shift; diff --git a/git-fetch.sh b/git-fetch.sh index f7167abdf0..c2eebee798 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -225,9 +225,16 @@ reflist=$(get_remote_refs_for_fetch "$@") if test "$tags" then taglist=`IFS=" " && - git-ls-remote $upload_pack --tags "$remote" | + ( + git-ls-remote $upload_pack --tags "$remote" || + echo fail ouch + ) | while read sha1 name do + case "$sha1" in + fail) + exit 1 + esac case "$name" in *^*) continue ;; esac @@ -237,7 +244,7 @@ then else echo >&2 "warning: tag ${name} ignored" fi - done` + done` || exit if test "$#" -gt 1 then # remote URL plus explicit refspecs; we need to merge them. diff --git a/git-instaweb.sh b/git-instaweb.sh index 63b18b99f6..16cd351f7f 100755 --- a/git-instaweb.sh +++ b/git-instaweb.sh @@ -54,6 +54,10 @@ start_httpd () { fi done fi + if test $? != 0; then + echo "Could not execute http daemon $httpd." + exit 1 + fi } stop_httpd () { @@ -183,8 +187,10 @@ PerlPassEnv GIT_EXEC_DIR EOF else # plain-old CGI + list_mods=`echo "$httpd" | sed "s/-f$/-l/"` + $list_mods | grep 'mod_cgi\.c' >/dev/null 2>&1 || \ + echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf" cat >> "$conf" <<EOF -LoadModule cgi_module $module_path/mod_cgi.so AddHandler cgi-script .cgi <Location /gitweb.cgi> Options +ExecCGI @@ -232,4 +238,5 @@ esac start_httpd test -z "$browser" && browser=echo -$browser http://127.0.0.1:$port +url=http://127.0.0.1:$port +$browser $url || echo $url diff --git a/git-lost-found.sh b/git-lost-found.sh index ba6d587f31..b928f2ca52 100755 --- a/git-lost-found.sh +++ b/git-lost-found.sh @@ -12,7 +12,7 @@ fi laf="$GIT_DIR/lost-found" rm -fr "$laf" && mkdir -p "$laf/commit" "$laf/other" || exit -git fsck-objects | +git fsck-objects --full | while read dangling type sha1 do case "$dangling" in diff --git a/git-reset.sh b/git-reset.sh index 5c0224090a..36fc8ce25b 100755 --- a/git-reset.sh +++ b/git-reset.sh @@ -52,7 +52,8 @@ then else rm -f "$GIT_DIR/ORIG_HEAD" fi -git-update-ref -m "reset $reset_type $@" HEAD "$rev" +git-update-ref -m "reset $reset_type $*" HEAD "$rev" +update_ref_status=$? case "$reset_type" in --hard ) @@ -66,3 +67,5 @@ case "$reset_type" in esac rm -f "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/rr-cache/MERGE_RR" "$GIT_DIR/SQUASH_MSG" + +exit $update_ref_status @@ -35,6 +35,59 @@ static void prepend_to_path(const char *dir, int len) setenv("PATH", path, 1); } +static int handle_options(const char*** argv, int* argc) +{ + int handled = 0; + + while (*argc > 0) { + const char *cmd = (*argv)[0]; + if (cmd[0] != '-') + break; + + /* + * For legacy reasons, the "version" and "help" + * commands can be written with "--" prepended + * to make them look like flags. + */ + if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version")) + break; + + /* + * Check remaining flags. + */ + if (!strncmp(cmd, "--exec-path", 11)) { + cmd += 11; + if (*cmd == '=') + git_set_exec_path(cmd + 1); + else { + puts(git_exec_path()); + exit(0); + } + } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) { + setup_pager(); + } else if (!strcmp(cmd, "--git-dir")) { + if (*argc < 1) + return -1; + setenv("GIT_DIR", (*argv)[1], 1); + (*argv)++; + (*argc)--; + } else if (!strncmp(cmd, "--git-dir=", 10)) { + setenv("GIT_DIR", cmd + 10, 1); + } else if (!strcmp(cmd, "--bare")) { + static char git_dir[1024]; + setenv("GIT_DIR", getcwd(git_dir, 1024), 1); + } else { + fprintf(stderr, "Unknown option: %s\n", cmd); + cmd_usage(0, NULL, NULL); + } + + (*argv)++; + (*argc)--; + handled++; + } + return handled; +} + static const char *alias_command; static char *alias_string = NULL; @@ -106,7 +159,7 @@ static int handle_alias(int *argcp, const char ***argv) subdir = setup_git_directory_gently(&nongit); if (!nongit) { - int count; + int count, option_count; const char** new_argv; alias_command = (*argv)[0]; @@ -114,6 +167,10 @@ static int handle_alias(int *argcp, const char ***argv) if (alias_string) { count = split_cmdline(alias_string, &new_argv); + option_count = handle_options(&new_argv, &count); + memmove(new_argv - option_count, new_argv, + count * sizeof(char *)); + new_argv -= option_count; if (count < 1) die("empty alias for %s", alias_command); @@ -268,51 +325,19 @@ int main(int argc, const char **argv, char **envp) die("cannot handle %s internally", cmd); } - /* Default command: "help" */ - cmd = "help"; - /* Look for flags.. */ - while (argc > 1) { - cmd = *++argv; - argc--; - - if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) { - setup_pager(); - continue; - } - - if (strncmp(cmd, "--", 2)) - break; - - cmd += 2; - - /* - * For legacy reasons, the "version" and "help" - * commands can be written with "--" prepended - * to make them look like flags. - */ - if (!strcmp(cmd, "help")) - break; - if (!strcmp(cmd, "version")) - break; - - /* - * Check remaining flags (which by now must be - * "--exec-path", but maybe we will accept - * other arguments some day) - */ - if (!strncmp(cmd, "exec-path", 9)) { - cmd += 9; - if (*cmd == '=') { - git_set_exec_path(cmd + 1); - continue; - } - puts(git_exec_path()); - exit(0); - } - cmd_usage(0, NULL, NULL); + argv++; + argc--; + handle_options(&argv, &argc); + if (argc > 0) { + if (!strncmp(argv[0], "--", 2)) + argv[0] += 2; + } else { + /* Default command: "help" */ + argv[0] = "help"; + argc = 1; } - argv[0] = cmd; + cmd = argv[0]; /* * We search for git commands in the following order: diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi index 4106cb8eb6..243a2921f8 100755 --- a/gitweb/gitweb.cgi +++ b/gitweb/gitweb.cgi @@ -795,7 +795,7 @@ sub git_read_projects { if (-d $projects_list) { # search in directory my $dir = $projects_list; - opendir my $dh, $dir or return undef; + opendir my ($dh), $dir or return undef; while (my $dir = readdir($dh)) { if (-e "$projectroot/$dir/HEAD") { my $pr = { @@ -810,7 +810,7 @@ sub git_read_projects { # 'git%2Fgit.git Linus+Torvalds' # 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin' # 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman' - open my $fd , $projects_list or return undef; + open my ($fd), $projects_list or return undef; while (my $line = <$fd>) { chomp $line; my ($path, $owner) = split ' ', $line; @@ -1138,7 +1138,7 @@ sub git_summary { "</td>\n" . "<td>"; if (defined($comment)) { - print $cgi->a({-class => "list", -href => "$my_uri?" . esc_param("p=$project;a=tag;h=$tag{'id'}")}, $comment); + print $cgi->a({-class => "list", -href => "$my_uri?" . esc_param("p=$project;a=tag;h=$tag{'id'}")}, esc_html($comment)); } print "</td>\n" . "<td class=\"link\">"; diff --git a/http-fetch.c b/http-fetch.c index 12493fbed2..dc286b79f6 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1245,7 +1245,7 @@ int main(int argc, char **argv) arg++; } if (argc < arg + 2) { - usage("git-http-fetch [-c] [-t] [-a] [-d] [-v] [--recover] [-w ref] commit-id url"); + usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] commit-id url"); return 1; } commit_id = argv[arg]; diff --git a/local-fetch.c b/local-fetch.c index ffa4887570..a05ac16cd0 100644 --- a/local-fetch.c +++ b/local-fetch.c @@ -194,9 +194,9 @@ int fetch_ref(char *ref, unsigned char *sha1) } static const char local_pull_usage[] = -"git-local-fetch [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [-l] [-s] [-n] commit-id path"; +"git-local-fetch [-c] [-t] [-a] [-v] [-w filename] [--recover] [-l] [-s] [-n] commit-id path"; -/* +/* * By default we only use file copy. * If -l is specified, a hard link is attempted. * If -s is specified, then a symlink is attempted. diff --git a/log-tree.c b/log-tree.c index 3a6c84dab5..b67b8dd17a 100644 --- a/log-tree.c +++ b/log-tree.c @@ -97,6 +97,11 @@ void show_log(struct rev_info *opt, const char *sep) subject = "Subject: "; printf("From %s Mon Sep 17 00:00:00 2001\n", sha1); + if (opt->message_id) + printf("Message-Id: <%s>\n", opt->message_id); + if (opt->ref_message_id) + printf("In-Reply-To: <%s>\nReferences: <%s>\n", + opt->ref_message_id, opt->ref_message_id); if (opt->mime_boundary) { static char subject_buffer[1024]; static char buffer[1024]; diff --git a/revision.h b/revision.h index c010a08116..e23ec8f45a 100644 --- a/revision.h +++ b/revision.h @@ -61,6 +61,8 @@ struct rev_info { struct log_info *loginfo; int nr, total; const char *mime_boundary; + const char *message_id; + const char *ref_message_id; const char *add_signoff; const char *extra_headers; diff --git a/ssh-fetch.c b/ssh-fetch.c index 28f7fd9174..a8a6cfbb30 100644 --- a/ssh-fetch.c +++ b/ssh-fetch.c @@ -120,7 +120,7 @@ int fetch_ref(char *ref, unsigned char *sha1) static const char ssh_fetch_usage[] = MY_PROGRAM_NAME - " [-c] [-t] [-a] [-v] [-d] [--recover] [-w ref] commit-id url"; + " [-c] [-t] [-a] [-v] [--recover] [-w ref] commit-id url"; int main(int argc, char **argv) { char *commit_id; diff --git a/t/t4102-apply-rename.sh b/t/t4102-apply-rename.sh index fbb508d389..22da6a00cc 100755 --- a/t/t4102-apply-rename.sh +++ b/t/t4102-apply-rename.sh @@ -13,8 +13,8 @@ test_description='git-apply handling copy/rename patch. cat >test-patch <<\EOF diff --git a/foo b/bar similarity index 47% -copy from foo -copy to bar +rename from foo +rename to bar --- a/foo +++ b/bar @@ -1 +1 @@ @@ -39,4 +39,24 @@ else 'test -f bar && ls -l bar | grep "^-..x......"' fi +test_expect_success 'apply reverse' \ + 'git-apply -R --index --stat --summary --apply test-patch && + test "$(cat foo)" = "This is foo"' + +cat >test-patch <<\EOF +diff --git a/foo b/bar +similarity index 47% +copy from foo +copy to bar +--- a/foo ++++ b/bar +@@ -1 +1 @@ +-This is foo ++This is bar +EOF + +test_expect_success 'apply copy' \ + 'git-apply --index --stat --summary --apply test-patch && + test "$(cat bar)" = "This is bar" -a "$(cat foo)" = "This is foo"' + test_done diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh index 00bd8b15c6..ff052699a2 100755 --- a/t/t4103-apply-binary.sh +++ b/t/t4103-apply-binary.sh @@ -35,8 +35,8 @@ git-commit -m 'Second Version' git-diff-tree -p master binary >B.diff git-diff-tree -p -C master binary >C.diff -git-diff-tree -p --full-index master binary >BF.diff -git-diff-tree -p --full-index -C master binary >CF.diff +git-diff-tree -p --binary master binary >BF.diff +git-diff-tree -p --binary -C master binary >CF.diff test_expect_success 'stat binary diff -- should not fail.' \ 'git-checkout master diff --git a/t/t4112-apply-renames.sh b/t/t4112-apply-renames.sh index a06f6956d5..69e9603c78 100755 --- a/t/t4112-apply-renames.sh +++ b/t/t4112-apply-renames.sh @@ -11,31 +11,7 @@ test_description='git-apply should not get confused with rename/copy. # setup -mkdir -p include/arch/x86_64/klibc klibc/arch/x86_64/include/klibc - -cat >include/arch/x86_64/klibc/archsetjmp.h <<\EOF -/* - * arch/x86_64/include/klibc/archsetjmp.h - */ - -#ifndef _KLIBC_ARCHSETJMP_H -#define _KLIBC_ARCHSETJMP_H - -struct __jmp_buf { - unsigned long __rbx; - unsigned long __rsp; - unsigned long __rbp; - unsigned long __r12; - unsigned long __r13; - unsigned long __r14; - unsigned long __r15; - unsigned long __rip; -}; - -typedef struct __jmp_buf jmp_buf[1]; - -#endif /* _SETJMP_H */ -EOF +mkdir -p klibc/arch/x86_64/include/klibc cat >klibc/arch/x86_64/include/klibc/archsetjmp.h <<\EOF /* @@ -139,7 +115,7 @@ rename to include/arch/m32r/klibc/archsetjmp.h +#endif /* _KLIBC_ARCHSETJMP_H */ EOF -find include klibc -type f -print | xargs git-update-index --add -- +find klibc -type f -print | xargs git-update-index --add -- test_expect_success 'check rename/copy patch' 'git-apply --check patch' diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh new file mode 100755 index 0000000000..ca81d72157 --- /dev/null +++ b/t/t4114-apply-typechange.sh @@ -0,0 +1,105 @@ +#!/bin/sh +# +# Copyright (c) 2006 Eric Wong +# + +test_description='git-apply should not get confused with type changes. + +' + +. ./test-lib.sh + +test_expect_success 'setup repository and commits' ' + echo "hello world" > foo && + echo "hi planet" > bar && + git update-index --add foo bar && + git commit -m initial && + git branch initial && + rm -f foo && + ln -s bar foo && + git update-index foo && + git commit -m "foo symlinked to bar" && + git branch foo-symlinked-to-bar && + rm -f foo && + echo "how far is the sun?" > foo && + git update-index foo && + git commit -m "foo back to file" && + git branch foo-back-to-file && + rm -f foo && + git update-index --remove foo && + mkdir foo && + echo "if only I knew" > foo/baz && + git update-index --add foo/baz && + git commit -m "foo becomes a directory" && + git branch "foo-becomes-a-directory" && + echo "hello world" > foo/baz && + git update-index foo/baz && + git commit -m "foo/baz is the original foo" && + git branch foo-baz-renamed-from-foo + ' + +test_expect_success 'file renamed from foo to foo/baz' ' + git checkout -f initial && + git diff-tree -M -p HEAD foo-baz-renamed-from-foo > patch && + git apply --index < patch + ' +test_debug 'cat patch' + + +test_expect_success 'file renamed from foo/baz to foo' ' + git checkout -f foo-baz-renamed-from-foo && + git diff-tree -M -p HEAD initial > patch && + git apply --index < patch + ' +test_debug 'cat patch' + + +test_expect_success 'directory becomes file' ' + git checkout -f foo-becomes-a-directory && + git diff-tree -p HEAD initial > patch && + git apply --index < patch + ' +test_debug 'cat patch' + + +test_expect_success 'file becomes directory' ' + git checkout -f initial && + git diff-tree -p HEAD foo-becomes-a-directory > patch && + git apply --index < patch + ' +test_debug 'cat patch' + + +test_expect_success 'file becomes symlink' ' + git checkout -f initial && + git diff-tree -p HEAD foo-symlinked-to-bar > patch && + git apply --index < patch + ' +test_debug 'cat patch' + + +test_expect_success 'symlink becomes file' ' + git checkout -f foo-symlinked-to-bar && + git diff-tree -p HEAD foo-back-to-file > patch && + git apply --index < patch + ' +test_debug 'cat patch' + + +test_expect_success 'symlink becomes directory' ' + git checkout -f foo-symlinked-to-bar && + git diff-tree -p HEAD foo-becomes-a-directory > patch && + git apply --index < patch + ' +test_debug 'cat patch' + + +test_expect_success 'directory becomes symlink' ' + git checkout -f foo-becomes-a-directory && + git diff-tree -p HEAD foo-symlinked-to-bar > patch && + git apply --index < patch + ' +test_debug 'cat patch' + + +test_done diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index 811a4797a5..322eaadc73 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -38,4 +38,40 @@ test_expect_success \ 'git-diff-tree -r -M --name-status HEAD^ HEAD | \ grep -E "^R100.+path1/COPYING.+path0/COPYING"' +test_expect_success \ + 'adding another file' \ + 'cp ../../README path0/README && + git-add path0/README && + git-commit -m add2 -a' + +test_expect_success \ + 'moving whole subdirectory' \ + 'git-mv path0 path2' + +test_expect_success \ + 'commiting the change' \ + 'git-commit -m dir-move -a' + +test_expect_success \ + 'checking the commit' \ + 'git-diff-tree -r -M --name-status HEAD^ HEAD | \ + grep -E "^R100.+path0/COPYING.+path2/COPYING" && + git-diff-tree -r -M --name-status HEAD^ HEAD | \ + grep -E "^R100.+path0/README.+path2/README"' + +test_expect_success \ + 'moving whole subdirectory into subdirectory' \ + 'git-mv path2 path1' + +test_expect_success \ + 'commiting the change' \ + 'git-commit -m dir-move -a' + +test_expect_success \ + 'checking the commit' \ + 'git-diff-tree -r -M --name-status HEAD^ HEAD | \ + grep -E "^R100.+path2/COPYING.+path1/path2/COPYING" && + git-diff-tree -r -M --name-status HEAD^ HEAD | \ + grep -E "^R100.+path2/README.+path1/path2/README"' + test_done |