From: Junio C Hamano Date: Sun, 2 Mar 2008 23:11:07 +0000 (-0800) Subject: Merge branch 'mk/maint-parse-careful' X-Git-Tag: v1.5.5-rc0~93 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/eadbcd498a18d60467883aeb6c0726048e7382a2?ds=inline;hp=-c Merge branch 'mk/maint-parse-careful' * mk/maint-parse-careful: receive-pack: use strict mode for unpacking objects index-pack: introduce checking mode unpack-objects: prevent writing of inconsistent objects unpack-object: cache for non written objects add common fsck error printing function builtin-fsck: move common object checking code to fsck.c builtin-fsck: reports missing parent commits Remove unused object-ref code builtin-fsck: move away from object-refs to fsck_walk add generic, type aware object chain walker Conflicts: Makefile builtin-fsck.c --- eadbcd498a18d60467883aeb6c0726048e7382a2 diff --combined Documentation/config.txt index 4027726f2e,72d3a345ec..2091caa111 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@@ -139,51 -139,6 +139,51 @@@ core.autocrlf: "text" (i.e. be subjected to the autocrlf mechanism) is decided purely based on the contents. +core.safecrlf:: + If true, makes git check if converting `CRLF` as controlled by + `core.autocrlf` is reversible. Git will verify if a command + modifies a file in the work tree either directly or indirectly. + For example, committing a file followed by checking out the + same file should yield the original file in the work tree. If + this is not the case for the current setting of + `core.autocrlf`, git will reject the file. The variable can + be set to "warn", in which case git will only warn about an + irreversible conversion but continue the operation. ++ +CRLF conversion bears a slight chance of corrupting data. +autocrlf=true will convert CRLF to LF during commit and LF to +CRLF during checkout. A file that contains a mixture of LF and +CRLF before the commit cannot be recreated by git. For text +files this is the right thing to do: it corrects line endings +such that we have only LF line endings in the repository. +But for binary files that are accidentally classified as text the +conversion can corrupt data. ++ +If you recognize such corruption early you can easily fix it by +setting the conversion type explicitly in .gitattributes. Right +after committing you still have the original file in your work +tree and this file is not yet corrupted. You can explicitly tell +git that this file is binary and git will handle the file +appropriately. ++ +Unfortunately, the desired effect of cleaning up text files with +mixed line endings and the undesired effect of corrupting binary +files cannot be distinguished. In both cases CRLFs are removed +in an irreversible way. For text files this is the right thing +to do because CRLFs are line endings, while for binary files +converting CRLFs corrupts data. ++ +Note, this safety check does not mean that a checkout will generate a +file identical to the original file for a different setting of +`core.autocrlf`, but only for the current one. For example, a text +file with `LF` would be accepted with `core.autocrlf=input` and could +later be checked out with `core.autocrlf=true`, in which case the +resulting file would contain `CRLF`, although the original file +contained `LF`. However, in both work trees the line endings would be +consistent, that is either all `LF` or all `CRLF`, but never mixed. A +file with mixed line endings would be reported by the `core.safecrlf` +mechanism. + core.symlinks:: If false, symbolic links are checked out as small plain files that contain the link text. linkgit:git-update-index[1] and @@@ -353,10 -308,6 +353,10 @@@ core.whitespace: error (enabled by default). * `indent-with-non-tab` treats a line that is indented with 8 or more space characters as an error (not enabled by default). +* `cr-at-eol` treats a carriage-return at the end of line as + part of the line terminator, i.e. with it, `trailing-space` + does not trigger if the character before such a carriage-return + is not a whitespace (not enabled by default). alias.*:: Command aliases for the linkgit:git[1] command wrapper - e.g. @@@ -379,14 -330,10 +379,14 @@@ apply.whitespace: branch.autosetupmerge:: Tells `git-branch` and `git-checkout` to setup new branches - so that linkgit:git-pull[1] will appropriately merge from that - remote branch. Note that even if this option is not set, + so that linkgit:git-pull[1] will appropriately merge from the + starting point branch. Note that even if this option is not set, this behavior can be chosen per-branch using the `--track` - and `--no-track` options. This option defaults to true. + and `--no-track` options. The valid settings are: `false` -- no + automatic setup is done; `true` -- automatic setup is done when the + starting point is a remote branch; `always` -- automatic setup is + done when the starting point is either a local branch or remote + branch. This option defaults to true. branch..remote:: When in branch , it tells `git fetch` which remote to fetch. @@@ -497,13 -444,6 +497,13 @@@ color.status.: commit.template:: Specify a file to use as the template for new commit messages. +color.ui:: + When set to `always`, always use colors in all git commands which + are capable of colored output. When false (or `never`), never. When + set to `true` or `auto`, use colors only when the output is to the + terminal. When more specific variables of color.* are set, they always + take precedence over this setting. Defaults to false. + diff.autorefreshindex:: When using `git diff` to compare with work tree files, do not consider stat-only change as changed. @@@ -816,8 -756,6 +816,8 @@@ pack.threads: warning. This is meant to reduce packing time on multiprocessor machines. The required amount of memory for the delta search window is however multiplied by the number of threads. + Specifying 0 will cause git to auto-detect the number of CPU's + and set the number of threads accordingly. pack.indexVersion:: Specify the default pack index version. Valid values are 1 for @@@ -828,12 -766,6 +828,12 @@@ whenever the corresponding pack is larger than 2 GB. Otherwise the default is 1. +pack.packSizeLimit: + The default maximum size of a pack. This setting only affects + packing to a file, i.e. the git:// protocol is unaffected. It + can be overridden by the `\--max-pack-size` option of + linkgit:git-repack[1]. + pull.octopus:: The default merge strategy to use when pulling multiple branches at once. @@@ -903,17 -835,6 +903,17 @@@ tar.umask: archiving user's umask will be used instead. See umask(2) and linkgit:git-archive[1]. +url..insteadOf:: + Any URL that starts with this value will be rewritten to + start, instead, with . In cases where some site serves a + large number of repositories, and serves them with multiple + access methods, and some users need to use different access + methods, this feature allows people to specify any of the + equivalent URLs and have git automatically rewrite the URL to + the best alternative for the particular user, even for a + never-before-seen repository on the site. When more than one + insteadOf strings match a given URL, the longest match is used. + user.email:: Your email address to be recorded in any newly created commits. Can be overridden by the 'GIT_AUTHOR_EMAIL', 'GIT_COMMITTER_EMAIL', and @@@ -939,6 -860,12 +939,12 @@@ imap: The configuration variables in the 'imap' section are described in linkgit:git-imap-send[1]. + receive.fsckObjects:: + If it is set to true, git-receive-pack will check all received + objects. It will abort in the case of a malformed object or a + broken link. The result of an abort are only dangling objects. + The default value is true. + receive.unpackLimit:: If the number of objects received in a push is below this limit then the objects will be unpacked into loose object diff --combined Makefile index c2f84a76f6,8ff0c772f1..71f01d16b1 --- a/Makefile +++ b/Makefile @@@ -3,9 -3,6 +3,9 @@@ all: # Define V=1 to have a more verbose compile. # +# Define FREAD_READS_DIRECTORIES if your are on a system which succeeds +# when attempting to read from an fopen'ed directory. +# # Define NO_OPENSSL environment variable if you do not have OpenSSL. # This also implies MOZILLA_SHA1. # @@@ -140,10 -137,6 +140,10 @@@ # Define THREADED_DELTA_SEARCH if you have pthreads and wish to exploit # parallel delta searching when packing objects. # +# Define INTERNAL_QSORT to use Git's implementation of qsort(), which +# is a simplified version of the merge sort used in glibc. This is +# recommended if Git triggers O(n^2) behavior in your platform's qsort(). +# GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE @$(SHELL_PATH) ./GIT-VERSION-GEN @@@ -226,7 -219,7 +226,7 @@@ BASIC_CFLAGS BASIC_LDFLAGS = SCRIPT_SH = \ - git-bisect.sh git-checkout.sh \ + git-bisect.sh \ git-clone.sh \ git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \ git-pull.sh git-rebase.sh git-rebase--interactive.sh \ @@@ -238,7 -231,7 +238,7 @@@ git-lost-found.sh git-quiltimport.sh git-submodule.sh \ git-filter-branch.sh \ git-stash.sh \ - git-help--browse.sh + git-web--browse.sh SCRIPT_PERL = \ git-add--interactive.perl \ @@@ -265,23 -258,23 +265,23 @@@ PROGRAMS = git-upload-pack$X \ git-pack-redundant$X git-var$X \ git-merge-tree$X git-imap-send$X \ - git-merge-recursive$X \ $(EXTRA_PROGRAMS) # Empty... EXTRA_PROGRAMS = +# List built-in command $C whose implementation cmd_$C() is not in +# builtin-$C.o but is linked in as part of some other command. BUILT_INS = \ git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \ git-get-tar-commit-id$X git-init$X git-repo-config$X \ git-fsck-objects$X git-cherry-pick$X git-peek-remote$X git-status$X \ + git-merge-subtree$X \ $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS)) # what 'all' will build and 'install' will install, in gitexecdir ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) -ALL_PROGRAMS += git-merge-subtree$X - # what 'all' will build but not install in gitexecdir OTHER_PROGRAMS = git$X gitweb/gitweb.cgi @@@ -304,7 -297,7 +304,7 @@@ LIB_H = run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \ tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \ utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \ - mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h + mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h fsck.h DIFF_OBJS = \ diff.o diff-lib.o diffcore-break.o diffcore-order.o \ @@@ -319,7 -312,7 +319,7 @@@ LIB_OBJS = patch-ids.o \ object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \ sideband.o reachable.o reflog-walk.o \ - quote.o read-cache.o refs.o run-command.o dir.o object-refs.o \ + quote.o read-cache.o refs.o run-command.o dir.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ revision.o pager.o tree-walk.o xdiff-interface.o \ @@@ -327,8 -320,7 +327,8 @@@ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \ convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \ - transport.o bundle.o walker.o parse-options.o ws.o archive.o fsck.o + transport.o bundle.o walker.o parse-options.o ws.o archive.o branch.o \ - alias.o ++ alias.o fsck.o BUILTIN_OBJS = \ builtin-add.o \ @@@ -340,7 -332,6 +340,7 @@@ builtin-bundle.o \ builtin-cat-file.o \ builtin-check-attr.o \ + builtin-checkout.o \ builtin-checkout-index.o \ builtin-check-ref-format.o \ builtin-clean.o \ @@@ -371,7 -362,6 +371,7 @@@ builtin-merge-base.o \ builtin-merge-file.o \ builtin-merge-ours.o \ + builtin-merge-recursive.o \ builtin-mv.o \ builtin-name-rev.o \ builtin-pack-objects.o \ @@@ -628,10 -618,6 +628,10 @@@ endi ifdef NO_C99_FORMAT BASIC_CFLAGS += -DNO_C99_FORMAT endif +ifdef FREAD_READS_DIRECTORIES + COMPAT_CFLAGS += -DFREAD_READS_DIRECTORIES + COMPAT_OBJS += compat/fopen.o +endif ifdef NO_SYMLINK_HEAD BASIC_CFLAGS += -DNO_SYMLINK_HEAD endif @@@ -736,15 -722,10 +736,15 @@@ ifdef NO_MEMME COMPAT_CFLAGS += -DNO_MEMMEM COMPAT_OBJS += compat/memmem.o endif +ifdef INTERNAL_QSORT + COMPAT_CFLAGS += -DINTERNAL_QSORT + COMPAT_OBJS += compat/qsort.o +endif ifdef THREADED_DELTA_SEARCH BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH EXTLIBS += -lpthread + LIB_OBJS += thread-utils.o endif ifeq ($(TCLTK_PATH),) @@@ -812,7 -793,7 +812,7 @@@ export TAR INSTALL DESTDIR SHELL_PAT ### Build rules -all:: $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) +all:: $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS ifneq (,$X) $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$p';) endif @@@ -838,10 -819,12 +838,10 @@@ git$X: git.o $(BUILTIN_OBJS) $(GITLIBS help.o: help.c common-cmds.h GIT-CFLAGS $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \ + '-DGIT_HTML_PATH="$(htmldir_SQ)"' \ '-DGIT_MAN_PATH="$(mandir_SQ)"' \ '-DGIT_INFO_PATH="$(infodir_SQ)"' $< -git-merge-subtree$X: git-merge-recursive$X - $(QUIET_BUILT_IN)$(RM) $@ && ln git-merge-recursive$X $@ - $(BUILT_INS): git$X $(QUIET_BUILT_IN)$(RM) $@ && ln git$X $@ @@@ -856,6 -839,7 +856,6 @@@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : % -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \ -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ - -e 's|@@HTMLDIR@@|$(htmldir_SQ)|g' \ $@.sh >$@+ && \ chmod +x $@+ && \ mv $@+ $@ @@@ -1011,9 -995,6 +1011,9 @@@ GIT-CFLAGS: .FORCE-GIT-CFLAG echo "$$FLAGS" >GIT-CFLAGS; \ fi +GIT-BUILD-OPTIONS: .FORCE-GIT-BUILD-OPTIONS + @echo SHELL_PATH=\''$(SHELL_PATH_SQ)'\' >$@ + ### Detect Tck/Tk interpreter path changes ifndef NO_TCLTK TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)') @@@ -1106,7 -1087,7 +1106,7 @@@ git.spec: git.spec.i mv $@+ $@ GIT_TARNAME=git-$(GIT_VERSION) -dist: git.spec git-archive configure +dist: git.spec git-archive$(X) configure ./git-archive --format=tar \ --prefix=$(GIT_TARNAME)/ HEAD^{tree} > $(GIT_TARNAME).tar @mkdir -p $(GIT_TARNAME) @@@ -1169,11 -1150,10 +1169,11 @@@ ifndef NO_TCLT $(MAKE) -C gitk-git clean $(MAKE) -C git-gui clean endif - $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS + $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS .PHONY: all install clean strip .PHONY: .FORCE-GIT-VERSION-FILE TAGS tags cscope .FORCE-GIT-CFLAGS +.PHONY: .FORCE-GIT-BUILD-OPTIONS ### Check documentation # diff --combined builtin-fetch-pack.c index 5ea48ca7db,410414d91f..b23e886d75 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@@ -7,7 -7,6 +7,7 @@@ #include "pack.h" #include "sideband.h" #include "fetch-pack.h" +#include "remote.h" #include "run-command.h" static int transfer_unpack_limit = -1; @@@ -386,7 -385,6 +386,6 @@@ static int everything_local(struct ref int retval; unsigned long cutoff = 0; - track_object_refs = 0; save_commit_buffer = 0; for (ref = *refs; ref; ref = ref->next) { @@@ -538,10 -536,8 +537,10 @@@ static int get_pack(int xd[2], char **p cmd.git_cmd = 1; if (start_command(&cmd)) die("fetch-pack: unable to fork off %s", argv[0]); - if (do_keep && pack_lockfile) + if (do_keep && pack_lockfile) { *pack_lockfile = index_pack_lockfile(cmd.out); + close(cmd.out); + } if (finish_command(&cmd)) die("%s failed", argv[0]); @@@ -551,14 -547,14 +550,14 @@@ } static struct ref *do_fetch_pack(int fd[2], + const struct ref *orig_ref, int nr_match, char **match, char **pack_lockfile) { - struct ref *ref; + struct ref *ref = copy_ref_list(orig_ref); unsigned char sha1[20]; - get_remote_heads(fd[0], &ref, 0, NULL, 0); if (is_repository_shallow() && !server_supports("shallow")) die("Server does not support shallow clients"); if (server_supports("multi_ack")) { @@@ -576,6 -572,10 +575,6 @@@ fprintf(stderr, "Server supports side-band\n"); use_sideband = 1; } - if (!ref) { - packet_flush(fd[1]); - die("no matching remote head"); - } if (everything_local(&ref, nr_match, match)) { packet_flush(fd[1]); goto all_done; @@@ -649,10 -649,8 +648,10 @@@ static void fetch_pack_setup(void int cmd_fetch_pack(int argc, const char **argv, const char *prefix) { int i, ret, nr_heads; - struct ref *ref; + struct ref *ref = NULL; char *dest = NULL, **heads; + int fd[2]; + struct child_process *conn; nr_heads = 0; heads = NULL; @@@ -707,33 -705,9 +706,33 @@@ if (!dest) usage(fetch_pack_usage); - ref = fetch_pack(&args, dest, nr_heads, heads, NULL); + conn = git_connect(fd, (char *)dest, args.uploadpack, + args.verbose ? CONNECT_VERBOSE : 0); + if (conn) { + get_remote_heads(fd[0], &ref, 0, NULL, 0); + + ref = fetch_pack(&args, fd, conn, ref, dest, nr_heads, heads, NULL); + close(fd[0]); + close(fd[1]); + if (finish_connect(conn)) + ref = NULL; + } else { + ref = NULL; + } ret = !ref; + if (!ret && nr_heads) { + /* If the heads to pull were given, we should have + * consumed all of them by matching the remote. + * Otherwise, 'git-fetch remote no-such-ref' would + * silently succeed without issuing an error. + */ + for (i = 0; i < nr_heads; i++) + if (heads[i] && heads[i][0]) { + error("no such remote ref %s", heads[i]); + ret = 1; + } + } while (ref) { printf("%s %s\n", sha1_to_hex(ref->old_sha1), ref->name); @@@ -744,15 -718,16 +743,15 @@@ } struct ref *fetch_pack(struct fetch_pack_args *my_args, + int fd[], struct child_process *conn, + const struct ref *ref, const char *dest, int nr_heads, char **heads, char **pack_lockfile) { - int i, ret; - int fd[2]; - struct child_process *conn; - struct ref *ref; struct stat st; + struct ref *ref_cpy; fetch_pack_setup(); memcpy(&args, my_args, sizeof(args)); @@@ -761,15 -736,29 +760,15 @@@ st.st_mtime = 0; } - conn = git_connect(fd, (char *)dest, args.uploadpack, - args.verbose ? CONNECT_VERBOSE : 0); if (heads && nr_heads) nr_heads = remove_duplicates(nr_heads, heads); - ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile); - close(fd[0]); - close(fd[1]); - ret = finish_connect(conn); - - if (!ret && nr_heads) { - /* If the heads to pull were given, we should have - * consumed all of them by matching the remote. - * Otherwise, 'git-fetch remote no-such-ref' would - * silently succeed without issuing an error. - */ - for (i = 0; i < nr_heads; i++) - if (heads[i] && heads[i][0]) { - error("no such remote ref %s", heads[i]); - ret = 1; - } + if (!ref) { + packet_flush(fd[1]); + die("no matching remote head"); } + ref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile); - if (!ret && args.depth > 0) { + if (args.depth > 0) { struct cache_time mtime; char *shallow = git_path("shallow"); int fd; @@@ -797,5 -786,8 +796,5 @@@ } } - if (ret) - ref = NULL; - - return ref; + return ref_cpy; } diff --combined builtin-fsck.c index cc7524be80,d545650c8c..78a6e1ff71 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@@ -8,6 -8,7 +8,7 @@@ #include "pack.h" #include "cache-tree.h" #include "tree-walk.h" + #include "fsck.h" #include "parse-options.h" #define REACHABLE 0x0001 @@@ -54,13 -55,75 +55,75 @@@ static int objerror(struct object *obj return -1; } - static int objwarning(struct object *obj, const char *err, ...) + static int fsck_error_func(struct object *obj, int type, const char *err, ...) { va_list params; va_start(params, err); - objreport(obj, "warning", err, params); + objreport(obj, (type == FSCK_WARN) ? "warning" : "error", err, params); va_end(params); - return -1; + return (type == FSCK_WARN) ? 0 : 1; + } + + static int mark_object(struct object *obj, int type, void *data) + { + struct tree *tree = NULL; + struct object *parent = data; + int result; + + if (!obj) { + printf("broken link from %7s %s\n", + typename(parent->type), sha1_to_hex(parent->sha1)); + printf("broken link from %7s %s\n", + (type == OBJ_ANY ? "unknown" : typename(type)), "unknown"); + errors_found |= ERROR_REACHABLE; + return 1; + } + + if (type != OBJ_ANY && obj->type != type) + objerror(parent, "wrong object type in link"); + + if (obj->flags & REACHABLE) + return 0; + obj->flags |= REACHABLE; + if (!obj->parsed) { + if (parent && !has_sha1_file(obj->sha1)) { + printf("broken link from %7s %s\n", + typename(parent->type), sha1_to_hex(parent->sha1)); + printf(" to %7s %s\n", + typename(obj->type), sha1_to_hex(obj->sha1)); + errors_found |= ERROR_REACHABLE; + } + return 1; + } + + if (obj->type == OBJ_TREE) { + obj->parsed = 0; + tree = (struct tree *)obj; + if (parse_tree(tree) < 0) + return 1; /* error already displayed */ + } + result = fsck_walk(obj, mark_object, obj); + if (tree) { + free(tree->buffer); + tree->buffer = NULL; + } + if (result < 0) + result = 1; + + return result; + } + + static void mark_object_reachable(struct object *obj) + { + mark_object(obj, OBJ_ANY, 0); + } + + static int mark_used(struct object *obj, int type, void *data) + { + if (!obj) + return 1; + obj->used = 1; + return 0; } /* @@@ -68,8 -131,6 +131,6 @@@ */ static void check_reachable_object(struct object *obj) { - const struct object_refs *refs; - /* * We obviously want the object to be parsed, * except if it was in a pack-file and we didn't @@@ -82,25 -143,6 +143,6 @@@ errors_found |= ERROR_REACHABLE; return; } - - /* - * Check that everything that we try to reference is also good. - */ - refs = lookup_object_refs(obj); - if (refs) { - unsigned j; - for (j = 0; j < refs->count; j++) { - struct object *ref = refs->ref[j]; - if (ref->parsed || - (has_sha1_file(ref->sha1))) - continue; - printf("broken link from %7s %s\n", - typename(obj->type), sha1_to_hex(obj->sha1)); - printf(" to %7s %s\n", - typename(ref->type), sha1_to_hex(ref->sha1)); - errors_found |= ERROR_REACHABLE; - } - } } /* @@@ -204,230 -246,56 +246,56 @@@ static void check_connectivity(void } } - /* - * The entries in a tree are ordered in the _path_ order, - * which means that a directory entry is ordered by adding - * a slash to the end of it. - * - * So a directory called "a" is ordered _after_ a file - * called "a.c", because "a/" sorts after "a.c". - */ - #define TREE_UNORDERED (-1) - #define TREE_HAS_DUPS (-2) - - static int verify_ordered(unsigned mode1, const char *name1, unsigned mode2, const char *name2) + static int fsck_sha1(const unsigned char *sha1) { - int len1 = strlen(name1); - int len2 = strlen(name2); - int len = len1 < len2 ? len1 : len2; - unsigned char c1, c2; - int cmp; - - cmp = memcmp(name1, name2, len); - if (cmp < 0) + struct object *obj = parse_object(sha1); + if (!obj) { + errors_found |= ERROR_OBJECT; + return error("%s: object corrupt or missing", + sha1_to_hex(sha1)); + } + if (obj->flags & SEEN) return 0; - if (cmp > 0) - return TREE_UNORDERED; - - /* - * Ok, the first characters are the same. - * Now we need to order the next one, but turn - * a '\0' into a '/' for a directory entry. - */ - c1 = name1[len]; - c2 = name2[len]; - if (!c1 && !c2) - /* - * git-write-tree used to write out a nonsense tree that has - * entries with the same name, one blob and one tree. Make - * sure we do not have duplicate entries. - */ - return TREE_HAS_DUPS; - if (!c1 && S_ISDIR(mode1)) - c1 = '/'; - if (!c2 && S_ISDIR(mode2)) - c2 = '/'; - return c1 < c2 ? 0 : TREE_UNORDERED; - } - - static int fsck_tree(struct tree *item) - { - int retval; - int has_full_path = 0; - int has_empty_name = 0; - int has_zero_pad = 0; - int has_bad_modes = 0; - int has_dup_entries = 0; - int not_properly_sorted = 0; - struct tree_desc desc; - unsigned o_mode; - const char *o_name; - const unsigned char *o_sha1; + obj->flags |= SEEN; if (verbose) - fprintf(stderr, "Checking tree %s\n", - sha1_to_hex(item->object.sha1)); - - init_tree_desc(&desc, item->buffer, item->size); - - o_mode = 0; - o_name = NULL; - o_sha1 = NULL; - while (desc.size) { - unsigned mode; - const char *name; - const unsigned char *sha1; - - sha1 = tree_entry_extract(&desc, &name, &mode); - - if (strchr(name, '/')) - has_full_path = 1; - if (!*name) - has_empty_name = 1; - has_zero_pad |= *(char *)desc.buffer == '0'; - update_tree_entry(&desc); - - switch (mode) { - /* - * Standard modes.. - */ - case S_IFREG | 0755: - case S_IFREG | 0644: - case S_IFLNK: - case S_IFDIR: - case S_IFGITLINK: - break; - /* - * This is nonstandard, but we had a few of these - * early on when we honored the full set of mode - * bits.. - */ - case S_IFREG | 0664: - if (!check_strict) - break; - default: - has_bad_modes = 1; - } + fprintf(stderr, "Checking %s %s\n", + typename(obj->type), sha1_to_hex(obj->sha1)); - if (o_name) { - switch (verify_ordered(o_mode, o_name, mode, name)) { - case TREE_UNORDERED: - not_properly_sorted = 1; - break; - case TREE_HAS_DUPS: - has_dup_entries = 1; - break; - default: - break; - } - } + if (fsck_walk(obj, mark_used, 0)) + objerror(obj, "broken links"); + if (fsck_object(obj, check_strict, fsck_error_func)) + return -1; - o_mode = mode; - o_name = name; - o_sha1 = sha1; - } - free(item->buffer); - item->buffer = NULL; + if (obj->type == OBJ_TREE) { + struct tree *item = (struct tree *) obj; - retval = 0; - if (has_full_path) { - objwarning(&item->object, "contains full pathnames"); + free(item->buffer); + item->buffer = NULL; } - if (has_empty_name) { - objwarning(&item->object, "contains empty pathname"); - } - if (has_zero_pad) { - objwarning(&item->object, "contains zero-padded file modes"); - } - if (has_bad_modes) { - objwarning(&item->object, "contains bad file modes"); - } - if (has_dup_entries) { - retval = objerror(&item->object, "contains duplicate file entries"); - } - if (not_properly_sorted) { - retval = objerror(&item->object, "not properly sorted"); - } - return retval; - } - static int fsck_commit(struct commit *commit) - { - char *buffer = commit->buffer; - unsigned char tree_sha1[20], sha1[20]; + if (obj->type == OBJ_COMMIT) { + struct commit *commit = (struct commit *) obj; - if (verbose) - fprintf(stderr, "Checking commit %s\n", - sha1_to_hex(commit->object.sha1)); - - if (!commit->date) - return objerror(&commit->object, "invalid author/committer line"); - - if (memcmp(buffer, "tree ", 5)) - return objerror(&commit->object, "invalid format - expected 'tree' line"); - if (get_sha1_hex(buffer+5, tree_sha1) || buffer[45] != '\n') - return objerror(&commit->object, "invalid 'tree' line format - bad sha1"); - buffer += 46; - while (!memcmp(buffer, "parent ", 7)) { - if (get_sha1_hex(buffer+7, sha1) || buffer[47] != '\n') - return objerror(&commit->object, "invalid 'parent' line format - bad sha1"); - buffer += 48; - } - if (memcmp(buffer, "author ", 7)) - return objerror(&commit->object, "invalid format - expected 'author' line"); - free(commit->buffer); - commit->buffer = NULL; - if (!commit->tree) - return objerror(&commit->object, "could not load commit's tree %s", tree_sha1); - if (!commit->parents && show_root) - printf("root %s\n", sha1_to_hex(commit->object.sha1)); - return 0; - } + free(commit->buffer); + commit->buffer = NULL; - static int fsck_tag(struct tag *tag) - { - struct object *tagged = tag->tagged; + if (!commit->parents && show_root) + printf("root %s\n", sha1_to_hex(commit->object.sha1)); + } - if (verbose) - fprintf(stderr, "Checking tag %s\n", - sha1_to_hex(tag->object.sha1)); + if (obj->type == OBJ_TAG) { + struct tag *tag = (struct tag *) obj; - if (!tagged) { - return objerror(&tag->object, "could not load tagged object"); + if (show_tags && tag->tagged) { + printf("tagged %s %s", typename(tag->tagged->type), sha1_to_hex(tag->tagged->sha1)); + printf(" (%s) in %s\n", tag->tag, sha1_to_hex(tag->object.sha1)); + } } - if (!show_tags) - return 0; - printf("tagged %s %s", typename(tagged->type), sha1_to_hex(tagged->sha1)); - printf(" (%s) in %s\n", tag->tag, sha1_to_hex(tag->object.sha1)); return 0; } - static int fsck_sha1(const unsigned char *sha1) - { - struct object *obj = parse_object(sha1); - if (!obj) { - errors_found |= ERROR_OBJECT; - return error("%s: object corrupt or missing", - sha1_to_hex(sha1)); - } - if (obj->flags & SEEN) - return 0; - obj->flags |= SEEN; - if (obj->type == OBJ_BLOB) - return 0; - if (obj->type == OBJ_TREE) - return fsck_tree((struct tree *) obj); - if (obj->type == OBJ_COMMIT) - return fsck_commit((struct commit *) obj); - if (obj->type == OBJ_TAG) - return fsck_tag((struct tag *) obj); - - /* By now, parse_object() would've returned NULL instead. */ - return objerror(obj, "unknown type '%d' (internal fsck error)", - obj->type); - } - /* * This is the sorting chunk size: make it reasonably * big so that we can sort well.. @@@ -538,13 -406,13 +406,13 @@@ static int fsck_handle_reflog_ent(unsig obj = lookup_object(osha1); if (obj) { obj->used = 1; - mark_reachable(obj, REACHABLE); + mark_object_reachable(obj); } } obj = lookup_object(nsha1); if (obj) { obj->used = 1; - mark_reachable(obj, REACHABLE); + mark_object_reachable(obj); } return 0; } @@@ -574,7 -442,7 +442,7 @@@ static int fsck_handle_ref(const char * error("%s: not a commit", refname); default_refs++; obj->used = 1; - mark_reachable(obj, REACHABLE); + mark_object_reachable(obj); return 0; } @@@ -660,7 -528,7 +528,7 @@@ static int fsck_cache_tree(struct cache sha1_to_hex(it->sha1)); return 1; } - mark_reachable(obj, REACHABLE); + mark_object_reachable(obj); obj->used = 1; if (obj->type != OBJ_TREE) err |= objerror(obj, "non-tree in cache-tree"); @@@ -693,7 -561,6 +561,6 @@@ int cmd_fsck(int argc, const char **arg { int i, heads; - track_object_refs = 1; errors_found = 0; argc = parse_options(argc, argv, fsck_opts, fsck_usage, 0); @@@ -741,7 -608,7 +608,7 @@@ continue; obj->used = 1; - mark_reachable(obj, REACHABLE); + mark_object_reachable(obj); heads++; continue; } @@@ -765,7 -632,7 +632,7 @@@ struct blob *blob; struct object *obj; - mode = ntohl(active_cache[i]->ce_mode); + mode = active_cache[i]->ce_mode; if (S_ISGITLINK(mode)) continue; blob = lookup_blob(active_cache[i]->sha1); @@@ -773,7 -640,7 +640,7 @@@ continue; obj = &blob->object; obj->used = 1; - mark_reachable(obj, REACHABLE); + mark_object_reachable(obj); } if (active_cache_tree) fsck_cache_tree(active_cache_tree); diff --combined builtin-pack-objects.c index 1bba6e6a64,6f8f388bdf..6c8b662e78 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@@ -16,7 -16,6 +16,7 @@@ #include "progress.h" #ifdef THREADED_DELTA_SEARCH +#include "thread-utils.h" #include #endif @@@ -69,7 -68,7 +69,7 @@@ static int allow_ofs_delta static const char *base_name; static int progress = 1; static int window = 10; -static uint32_t pack_size_limit; +static uint32_t pack_size_limit, pack_size_limit_cfg; static int depth = 50; static int delta_search_threads = 1; static int pack_to_stdout; @@@ -1429,7 -1428,8 +1429,7 @@@ static int try_delta(struct unpacked *t * accounting lock. Compiler will optimize the strangeness * away when THREADED_DELTA_SEARCH is not defined. */ - if (trg_entry->delta_data) - free(trg_entry->delta_data); + free(trg_entry->delta_data); cache_lock(); if (trg_entry->delta_data) { delta_cache_size -= trg_entry->delta_size; @@@ -1852,11 -1852,11 +1852,11 @@@ static int git_pack_config(const char * } if (!strcmp(k, "pack.threads")) { delta_search_threads = git_config_int(k, v); - if (delta_search_threads < 1) + if (delta_search_threads < 0) die("invalid number of threads specified (%d)", delta_search_threads); #ifndef THREADED_DELTA_SEARCH - if (delta_search_threads > 1) + if (delta_search_threads != 1) warning("no threads support, ignoring %s", k); #endif return 0; @@@ -1867,10 -1867,6 +1867,10 @@@ die("bad pack.indexversion=%d", pack_idx_default_version); return 0; } + if (!strcmp(k, "pack.packsizelimit")) { + pack_size_limit_cfg = git_config_ulong(k, v); + return 0; + } return git_default_config(k, v); } @@@ -2013,7 -2009,6 +2013,6 @@@ static void get_object_list(int ac, con init_revisions(&revs, NULL); save_commit_buffer = 0; - track_object_refs = 0; setup_revisions(ac, av, &revs, NULL); while (fgets(line, sizeof(line), stdin) != NULL) { @@@ -2033,8 -2028,7 +2032,8 @@@ die("bad revision '%s'", line); } - prepare_revision_walk(&revs); + if (prepare_revision_walk(&revs)) + die("revision walk setup failed"); mark_edges_uninteresting(revs.commits, &revs, show_edge); traverse_commit_list(&revs, show_commit, show_object); @@@ -2101,7 -2095,6 +2100,7 @@@ int cmd_pack_objects(int argc, const ch } if (!prefixcmp(arg, "--max-pack-size=")) { char *end; + pack_size_limit_cfg = 0; pack_size_limit = strtoul(arg+16, &end, 0) * 1024 * 1024; if (!arg[16] || *end) usage(pack_usage); @@@ -2122,10 -2115,10 +2121,10 @@@ if (!prefixcmp(arg, "--threads=")) { char *end; delta_search_threads = strtoul(arg+10, &end, 0); - if (!arg[10] || *end || delta_search_threads < 1) + if (!arg[10] || *end || delta_search_threads < 0) usage(pack_usage); #ifndef THREADED_DELTA_SEARCH - if (delta_search_threads > 1) + if (delta_search_threads != 1) warning("no threads support, " "ignoring %s", arg); #endif @@@ -2226,20 -2219,12 +2225,20 @@@ if (pack_to_stdout != !base_name) usage(pack_usage); + if (!pack_to_stdout && !pack_size_limit) + pack_size_limit = pack_size_limit_cfg; + if (pack_to_stdout && pack_size_limit) die("--max-pack-size cannot be used to build a pack for transfer."); if (!pack_to_stdout && thin) die("--thin cannot be used to build an indexable pack."); +#ifdef THREADED_DELTA_SEARCH + if (!delta_search_threads) /* --threads=0 means autodetect */ + delta_search_threads = online_cpus(); +#endif + prepare_packed_git(); if (progress) diff --combined builtin-rev-list.c index 6754e7f124,14e86ceabc..d0a1416921 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@@ -25,9 -25,6 +25,9 @@@ static const char rev_list_usage[] " --no-merges\n" " --remove-empty\n" " --all\n" +" --branches\n" +" --tags\n" +" --remotes\n" " --stdin\n" " --quiet\n" " ordering output:\n" @@@ -63,8 -60,6 +63,8 @@@ static void show_commit(struct commit * fputs(header_prefix, stdout); if (commit->object.flags & BOUNDARY) putchar('-'); + else if (commit->object.flags & UNINTERESTING) + putchar('^'); else if (revs.left_right) { if (commit->object.flags & SYMMETRIC_LEFT) putchar('<'); @@@ -89,7 -84,7 +89,7 @@@ else putchar('\n'); - if (revs.verbose_header) { + if (revs.verbose_header && commit->buffer) { struct strbuf buf; strbuf_init(&buf, 0); pretty_print_commit(revs.commit_format, commit, @@@ -610,12 -605,10 +610,11 @@@ int cmd_rev_list(int argc, const char * usage(rev_list_usage); save_commit_buffer = revs.verbose_header || revs.grep_filter; - track_object_refs = 0; if (bisect_list) revs.limited = 1; - prepare_revision_walk(&revs); + if (prepare_revision_walk(&revs)) + die("revision walk setup failed"); if (revs.tree_objects) mark_edges_uninteresting(revs.commits, &revs, show_edge); diff --combined cache.h index f16d341f52,d3b898708b..e230302623 --- a/cache.h +++ b/cache.h @@@ -3,7 -3,6 +3,7 @@@ #include "git-compat-util.h" #include "strbuf.h" +#include "hash.h" #include SHA1_HEADER #include @@@ -95,148 -94,66 +95,148 @@@ struct cache_time * We save the fields in big-endian order to allow using the * index file over NFS transparently. */ +struct ondisk_cache_entry { + struct cache_time ctime; + struct cache_time mtime; + unsigned int dev; + unsigned int ino; + unsigned int mode; + unsigned int uid; + unsigned int gid; + unsigned int size; + unsigned char sha1[20]; + unsigned short flags; + char name[FLEX_ARRAY]; /* more */ +}; + struct cache_entry { - struct cache_time ce_ctime; - struct cache_time ce_mtime; + unsigned int ce_ctime; + unsigned int ce_mtime; unsigned int ce_dev; unsigned int ce_ino; unsigned int ce_mode; unsigned int ce_uid; unsigned int ce_gid; unsigned int ce_size; + unsigned int ce_flags; unsigned char sha1[20]; - unsigned short ce_flags; + struct cache_entry *next; char name[FLEX_ARRAY]; /* more */ }; #define CE_NAMEMASK (0x0fff) #define CE_STAGEMASK (0x3000) -#define CE_UPDATE (0x4000) #define CE_VALID (0x8000) #define CE_STAGESHIFT 12 -#define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT)) -#define ce_namelen(ce) (CE_NAMEMASK & ntohs((ce)->ce_flags)) +/* In-memory only */ +#define CE_UPDATE (0x10000) +#define CE_REMOVE (0x20000) +#define CE_UPTODATE (0x40000) + +#define CE_HASHED (0x100000) +#define CE_UNHASHED (0x200000) + +/* + * Copy the sha1 and stat state of a cache entry from one to + * another. But we never change the name, or the hash state! + */ +#define CE_STATE_MASK (CE_HASHED | CE_UNHASHED) +static inline void copy_cache_entry(struct cache_entry *dst, struct cache_entry *src) +{ + unsigned int state = dst->ce_flags & CE_STATE_MASK; + + /* Don't copy hash chain and name */ + memcpy(dst, src, offsetof(struct cache_entry, next)); + + /* Restore the hash state */ + dst->ce_flags = (dst->ce_flags & ~CE_STATE_MASK) | state; +} + +/* + * We don't actually *remove* it, we can just mark it invalid so that + * we won't find it in lookups. + * + * Not only would we have to search the lists (simple enough), but + * we'd also have to rehash other hash buckets in case this makes the + * hash bucket empty (common). So it's much better to just mark + * it. + */ +static inline void remove_index_entry(struct cache_entry *ce) +{ + ce->ce_flags |= CE_UNHASHED; +} + +static inline unsigned create_ce_flags(size_t len, unsigned stage) +{ + if (len >= CE_NAMEMASK) + len = CE_NAMEMASK; + return (len | (stage << CE_STAGESHIFT)); +} + +static inline size_t ce_namelen(const struct cache_entry *ce) +{ + size_t len = ce->ce_flags & CE_NAMEMASK; + if (len < CE_NAMEMASK) + return len; + return strlen(ce->name + CE_NAMEMASK) + CE_NAMEMASK; +} + #define ce_size(ce) cache_entry_size(ce_namelen(ce)) -#define ce_stage(ce) ((CE_STAGEMASK & ntohs((ce)->ce_flags)) >> CE_STAGESHIFT) +#define ondisk_ce_size(ce) ondisk_cache_entry_size(ce_namelen(ce)) +#define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT) +#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE) +#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE) #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644) static inline unsigned int create_ce_mode(unsigned int mode) { if (S_ISLNK(mode)) - return htonl(S_IFLNK); + return S_IFLNK; if (S_ISDIR(mode) || S_ISGITLINK(mode)) - return htonl(S_IFGITLINK); - return htonl(S_IFREG | ce_permissions(mode)); + return S_IFGITLINK; + return S_IFREG | ce_permissions(mode); } static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode) { extern int trust_executable_bit, has_symlinks; if (!has_symlinks && S_ISREG(mode) && - ce && S_ISLNK(ntohl(ce->ce_mode))) + ce && S_ISLNK(ce->ce_mode)) return ce->ce_mode; if (!trust_executable_bit && S_ISREG(mode)) { - if (ce && S_ISREG(ntohl(ce->ce_mode))) + if (ce && S_ISREG(ce->ce_mode)) return ce->ce_mode; return create_ce_mode(0666); } return create_ce_mode(mode); } +static inline int ce_to_dtype(const struct cache_entry *ce) +{ + unsigned ce_mode = ntohl(ce->ce_mode); + if (S_ISREG(ce_mode)) + return DT_REG; + else if (S_ISDIR(ce_mode) || S_ISGITLINK(ce_mode)) + return DT_DIR; + else if (S_ISLNK(ce_mode)) + return DT_LNK; + else + return DT_UNKNOWN; +} #define canon_mode(mode) \ (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK) #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7) +#define ondisk_cache_entry_size(len) ((offsetof(struct ondisk_cache_entry,name) + (len) + 8) & ~7) struct index_state { struct cache_entry **cache; unsigned int cache_nr, cache_alloc, cache_changed; struct cache_tree *cache_tree; time_t timestamp; - void *mmap; - size_t mmap_size; + void *alloc; + unsigned name_hash_initialized : 1; + struct hash_table name_hash; }; extern struct index_state the_index; @@@ -252,7 -169,6 +252,7 @@@ #define read_cache_from(path) read_index_from(&the_index, (path)) #define write_cache(newfd, cache, entries) write_index(&the_index, (newfd)) #define discard_cache() discard_index(&the_index) +#define unmerged_cache() unmerged_index(&the_index) #define cache_name_pos(name, namelen) index_name_pos(&the_index,(name),(namelen)) #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option)) #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos)) @@@ -261,7 -177,6 +261,7 @@@ #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL) #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options)) #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options)) +#define cache_name_exists(name, namelen) index_name_exists(&the_index, (name), (namelen)) #endif enum object_type { @@@ -274,6 -189,7 +274,7 @@@ /* 5 for future expansion */ OBJ_OFS_DELTA = 6, OBJ_REF_DELTA = 7, + OBJ_ANY, OBJ_MAX, }; @@@ -347,9 -263,7 +348,9 @@@ extern int read_index(struct index_stat extern int read_index_from(struct index_state *, const char *path); extern int write_index(struct index_state *, int newfd); extern int discard_index(struct index_state *); +extern int unmerged_index(struct index_state *); extern int verify_path(const char *path); +extern int index_name_exists(struct index_state *istate, const char *name, int namelen); extern int index_name_pos(struct index_state *, const char *name, int namelen); #define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */ #define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */ @@@ -417,23 -331,6 +418,23 @@@ extern size_t packed_git_limit extern size_t delta_base_cache_limit; extern int auto_crlf; +enum safe_crlf { + SAFE_CRLF_FALSE = 0, + SAFE_CRLF_FAIL = 1, + SAFE_CRLF_WARN = 2, +}; + +extern enum safe_crlf safe_crlf; + +enum branch_track { + BRANCH_TRACK_NEVER = 0, + BRANCH_TRACK_REMOTE, + BRANCH_TRACK_ALWAYS, + BRANCH_TRACK_EXPLICIT, +}; + +extern enum branch_track git_branch_track; + #define GIT_REPO_VERSION 0 extern int repository_format_version; extern int check_repository_format(void); @@@ -694,9 -591,6 +695,9 @@@ extern int git_config_set_multivar(cons extern int git_config_rename_section(const char *, const char *); extern const char *git_etc_gitconfig(void); extern int check_repository_format_version(const char *var, const char *value); +extern int git_env_bool(const char *, int); +extern int git_config_system(void); +extern int git_config_global(void); extern int config_error_nonbool(const char *); #define MAX_GITNAME (1000) @@@ -709,7 -603,6 +710,7 @@@ extern const char *git_log_output_encod /* IO helper functions */ extern void maybe_flush_or_die(FILE *, const char *); extern int copy_fd(int ifd, int ofd); +extern int copy_file(const char *dst, const char *src, int mode); extern int read_in_full(int fd, void *buf, size_t count); extern int write_in_full(int fd, const void *buf, size_t count); extern void write_or_die(int fd, const void *buf, size_t count); @@@ -743,8 -636,7 +744,8 @@@ extern void trace_argv_printf(const cha /* convert.c */ /* returns 1 if *dst was used */ -extern int convert_to_git(const char *path, const char *src, size_t len, struct strbuf *dst); +extern int convert_to_git(const char *path, const char *src, size_t len, + struct strbuf *dst, enum safe_crlf checksafe); extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst); /* add */ @@@ -763,7 -655,6 +764,7 @@@ void shift_tree(const unsigned char *, #define WS_TRAILING_SPACE 01 #define WS_SPACE_BEFORE_TAB 02 #define WS_INDENT_WITH_NON_TAB 04 +#define WS_CR_AT_EOL 010 #define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB) extern unsigned whitespace_rule_cfg; extern unsigned whitespace_rule(const char *); @@@ -772,13 -663,10 +773,13 @@@ extern unsigned check_and_emit_line(con FILE *stream, const char *set, const char *reset, const char *ws); extern char *whitespace_error_string(unsigned ws); +extern int ws_fix_copy(char *, const char *, int, unsigned, int *); /* ls-files */ int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen); int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset); void overlay_tree_on_cache(const char *tree_name, const char *prefix); +char *alias_lookup(const char *alias); + #endif /* CACHE_H */ diff --combined commit.h index 80d65b96da,3ad3dd9af1..a1e9591426 --- a/commit.h +++ b/commit.h @@@ -71,21 -71,6 +71,21 @@@ extern void pretty_print_commit(enum cm int abbrev, const char *subject, const char *after_subject, enum date_mode, int non_ascii_present); +void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb, + const char *line, enum date_mode dmode, + const char *encoding); +void pp_title_line(enum cmit_fmt fmt, + const char **msg_p, + struct strbuf *sb, + const char *subject, + const char *after_subject, + const char *encoding, + int plain_non_ascii); +void pp_remainder(enum cmit_fmt fmt, + const char **msg_p, + struct strbuf *sb, + int indent); + /** Removes the first commit from a list sorted by date, and adds all * of its parents. @@@ -116,6 -101,7 +116,7 @@@ struct commit_graft struct commit_graft *read_graft_line(char *buf, int len); int register_commit_graft(struct commit_graft *, int); int read_graft_file(const char *graft_file); + struct commit_graft *lookup_commit_graft(const unsigned char *sha1); extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup); diff --combined receive-pack.c index a971433db1,f5440ff4d4..0ca2a80bf0 --- a/receive-pack.c +++ b/receive-pack.c @@@ -10,6 -10,7 +10,7 @@@ static const char receive_pack_usage[] = "git-receive-pack "; static int deny_non_fast_forwards = 0; + static int receive_fsck_objects = 1; static int receive_unpack_limit = -1; static int transfer_unpack_limit = -1; static int unpack_limit = 100; @@@ -35,6 -36,11 +36,11 @@@ static int receive_pack_config(const ch return 0; } + if (strcmp(var, "receive.fsckobjects") == 0) { + receive_fsck_objects = git_config_bool(var, value); + return 0; + } + return git_default_config(var, value); } @@@ -132,7 -138,6 +138,7 @@@ static int run_hook(const char *hook_na break; } } + close(proc.in); return hook_status(finish_command(&proc), hook_name); } @@@ -368,11 -373,13 +374,13 @@@ static const char *unpack(void ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries)); if (ntohl(hdr.hdr_entries) < unpack_limit) { - int code; - const char *unpacker[3]; - unpacker[0] = "unpack-objects"; - unpacker[1] = hdr_arg; - unpacker[2] = NULL; + int code, i = 0; + const char *unpacker[4]; + unpacker[i++] = "unpack-objects"; + if (receive_fsck_objects) + unpacker[i++] = "--strict"; + unpacker[i++] = hdr_arg; + unpacker[i++] = NULL; code = run_command_v_opt(unpacker, RUN_GIT_CMD); switch (code) { case 0: @@@ -393,8 -400,8 +401,8 @@@ return "unpacker exited with error code"; } } else { - const char *keeper[6]; - int s, status; + const char *keeper[7]; + int s, status, i = 0; char keep_arg[256]; struct child_process ip; @@@ -402,12 -409,14 +410,14 @@@ if (gethostname(keep_arg + s, sizeof(keep_arg) - s)) strcpy(keep_arg + s, "localhost"); - keeper[0] = "index-pack"; - keeper[1] = "--stdin"; - keeper[2] = "--fix-thin"; - keeper[3] = hdr_arg; - keeper[4] = keep_arg; - keeper[5] = NULL; + keeper[i++] = "index-pack"; + keeper[i++] = "--stdin"; + if (receive_fsck_objects) + keeper[i++] = "--strict"; + keeper[i++] = "--fix-thin"; + keeper[i++] = hdr_arg; + keeper[i++] = keep_arg; + keeper[i++] = NULL; memset(&ip, 0, sizeof(ip)); ip.argv = keeper; ip.out = -1; @@@ -415,7 -424,6 +425,7 @@@ if (start_command(&ip)) return "index-pack fork failed"; pack_lockfile = index_pack_lockfile(ip.out); + close(ip.out); status = finish_command(&ip); if (!status) { reprepare_packed_git(); diff --combined tag.c index 990134fe7a,d19f56d60c..4470d2bf78 --- a/tag.c +++ b/tag.c @@@ -9,10 -9,7 +9,10 @@@ const char *tag_type = "tag" struct object *deref_tag(struct object *o, const char *warn, int warnlen) { while (o && o->type == OBJ_TAG) - o = parse_object(((struct tag *)o)->tagged->sha1); + if (((struct tag *)o)->tagged) + o = parse_object(((struct tag *)o)->tagged->sha1); + else + o = NULL; if (!o && warn) { if (!warnlen) warnlen = strlen(warn); @@@ -87,12 -84,6 +87,6 @@@ int parse_tag_buffer(struct tag *item, item->tagged = NULL; } - if (item->tagged && track_object_refs) { - struct object_refs *refs = alloc_object_refs(1); - refs->ref[0] = item->tagged; - set_object_refs(&item->object, refs); - } - return 0; } diff --combined tree.c index 87708ef420,113e1bb0a4..4b1825c2ad --- a/tree.c +++ b/tree.c @@@ -142,8 -142,8 +142,8 @@@ static int cmp_cache_name_compare(cons ce1 = *((const struct cache_entry **)a_); ce2 = *((const struct cache_entry **)b_); - return cache_name_compare(ce1->name, ntohs(ce1->ce_flags), - ce2->name, ntohs(ce2->ce_flags)); + return cache_name_compare(ce1->name, ce1->ce_flags, + ce2->name, ce2->ce_flags); } int read_tree(struct tree *tree, int stage, const char **match) @@@ -202,52 -202,6 +202,6 @@@ struct tree *lookup_tree(const unsigne return (struct tree *) obj; } - /* - * NOTE! Tree refs to external git repositories - * (ie gitlinks) do not count as real references. - * - * You don't have to have those repositories - * available at all, much less have the objects - * accessible from the current repository. - */ - static void track_tree_refs(struct tree *item) - { - int n_refs = 0, i; - struct object_refs *refs; - struct tree_desc desc; - struct name_entry entry; - - /* Count how many entries there are.. */ - init_tree_desc(&desc, item->buffer, item->size); - while (tree_entry(&desc, &entry)) { - if (S_ISGITLINK(entry.mode)) - continue; - n_refs++; - } - - /* Allocate object refs and walk it again.. */ - i = 0; - refs = alloc_object_refs(n_refs); - init_tree_desc(&desc, item->buffer, item->size); - while (tree_entry(&desc, &entry)) { - struct object *obj; - - if (S_ISGITLINK(entry.mode)) - continue; - if (S_ISDIR(entry.mode)) - obj = &lookup_tree(entry.sha1)->object; - else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) - obj = &lookup_blob(entry.sha1)->object; - else { - warning("in tree %s: entry %s has bad mode %.6o\n", - sha1_to_hex(item->object.sha1), entry.path, entry.mode); - obj = lookup_unknown_object(entry.sha1); - } - refs->ref[i++] = obj; - } - set_object_refs(&item->object, refs); - } - int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size) { if (item->object.parsed) @@@ -256,8 -210,6 +210,6 @@@ item->buffer = buffer; item->size = size; - if (track_object_refs) - track_tree_refs(item); return 0; } diff --combined upload-pack.c index b26d05331d,ba9ba59976..e5421db9c5 --- a/upload-pack.c +++ b/upload-pack.c @@@ -129,8 -129,7 +129,8 @@@ static int do_rev_list(int fd, void *cr } setup_revisions(0, NULL, &revs, NULL); } - prepare_revision_walk(&revs); + if (prepare_revision_walk(&revs)) + die("revision walk setup failed"); mark_edges_uninteresting(revs.commits, &revs, show_edge); traverse_commit_list(&revs, show_commit, show_object); return 0; @@@ -393,7 -392,6 +393,6 @@@ static int get_common_commits(void char hex[41], last_hex[41]; int len; - track_object_refs = 0; save_commit_buffer = 0; for(;;) { @@@ -577,8 -575,7 +576,8 @@@ static int send_ref(const char *refname } if (o->type == OBJ_TAG) { o = deref_tag(o, refname, 0); - packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname); + if (o) + packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname); } return 0; }