diff --git a/Documentation/RelNotes-1.5.5.txt b/Documentation/RelNotes-1.5.5.txt index e31ae6a293..14beed49ba 100644 --- a/Documentation/RelNotes-1.5.5.txt +++ b/Documentation/RelNotes-1.5.5.txt @@ -124,6 +124,9 @@ Updates since v1.5.4 * "git gc" now automatically prunes unreachable objects that are two weeks old or older. + * "git gc --auto" can be disabled more easily by just setting gc.auto + to zero. It also tolerates more packfiles by default. + * "git grep" now knows "--name-only" is a synonym for the "-l" option. * "git help " now reports "'git ' is alias to ", @@ -201,6 +204,6 @@ this release, unless otherwise noted. --- exec >/var/tmp/1 -O=v1.5.4.4-620-gc817faa +O=v1.5.5-rc1 echo O=`git describe refs/heads/master` git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint diff --git a/Documentation/config.txt b/Documentation/config.txt index 0865f4e01a..3017d640cf 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -582,7 +582,7 @@ gc.autopacklimit:: When there are more than this many packs that are not marked with `*.keep` file in the repository, `git gc --auto` consolidates them into one larger pack. The - default value is 20. Setting this to 0 disables it. + default value is 50. Setting this to 0 disables it. gc.packrefs:: `git gc` does not run `git pack-refs` in a bare repository by diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 96f6767075..c29a4f8126 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -385,6 +385,9 @@ new commit. Omitting the `from` command in the first commit of a new branch will cause fast-import to create that commit with no ancestor. This tends to be desired only for the initial commit of a project. +If the frontend creates all files from scratch when making a new +branch, a `merge` command may be used instead of `from` to start +the commit with an empty tree. Omitting the `from` command on existing branches is usually desired, as the current commit on that branch is automatically assumed to be the first ancestor of the new commit. @@ -427,13 +430,15 @@ existing value of the branch. `merge` ^^^^^^^ -Includes one additional ancestor commit, and makes the current -commit a merge commit. An unlimited number of `merge` commands per +Includes one additional ancestor commit. If the `from` command is +omitted when creating a new branch, the first `merge` commit will be +the first ancestor of the current commit, and the branch will start +out with no files. An unlimited number of `merge` commands per commit are permitted by fast-import, thereby establishing an n-way merge. However Git's other tools never create commits with more than 15 additional ancestors (forming a 16-way merge). For this reason it is suggested that frontends do not use more than 15 `merge` -commands per commit. +commands per commit; 16, if starting a new, empty branch. Here `` is any of the commit specification expressions also accepted by `from` (see above). diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index 543a1cf105..2a78549be5 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -25,7 +25,7 @@ Otherwise, all information (including original commit times or merge information) will be preserved. The command will only rewrite the _positive_ refs mentioned in the -command line (i.e. if you pass 'a..b', only 'b' will be rewritten). +command line (e.g. if you pass 'a..b', only 'b' will be rewritten). If you specify no filters, the commits will be recommitted without any changes, which would normally have no effect. Nevertheless, this may be useful in the future for compensating for some git bugs or such, @@ -42,7 +42,7 @@ Always verify that the rewritten version is correct: The original refs, if different from the rewritten ones, will be stored in the namespace 'refs/original/'. -Note that since this operation is extensively I/O expensive, it might +Note that since this operation is very I/O expensive, it might be a good idea to redirect the temporary directory off-disk with the '-d' option, e.g. on tmpfs. Reportedly the speedup is very noticeable. @@ -51,14 +51,15 @@ Filters ~~~~~~~ The filters are applied in the order as listed below. The -argument is always evaluated in shell using the 'eval' command (with the -notable exception of the commit filter, for technical reasons). +argument is always evaluated in the shell context using the 'eval' command +(with the notable exception of the commit filter, for technical reasons). Prior to that, the $GIT_COMMIT environment variable will be set to contain the id of the commit being rewritten. Also, GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, -and GIT_COMMITTER_DATE are set according to the current commit. If any -evaluation of returns a non-zero exit status, the whole operation -will be aborted. +and GIT_COMMITTER_DATE are set according to the current commit. The values +of these variables after the filters have run, are used for the new commit. +If any evaluation of returns a non-zero exit status, the whole +operation will be aborted. A 'map' function is available that takes an "original sha1 id" argument and outputs a "rewritten sha1 id" if the commit has been already @@ -71,9 +72,9 @@ OPTIONS ------- --env-filter :: - This is the filter for modifying the environment in which - the commit will be performed. Specifically, you might want - to rewrite the author/committer name/email/time environment + This filter may be used if you only need to modify the environment + in which the commit will be performed. Specifically, you might + want to rewrite the author/committer name/email/time environment variables (see linkgit:git-commit[1] for details). Do not forget to re-export the variables. @@ -149,7 +150,7 @@ definition impossible to preserve signatures at any rate.) -d :: Use this option to set the path to the temporary directory used for rewriting. When applying a tree filter, the command needs to - temporary checkout the tree to some directory, which may consume + temporarily check out the tree to some directory, which may consume considerable space in case of large projects. By default it does this in the '.git-rewrite/' directory but you can override that choice by this parameter. diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt index 229a7c9b30..d424a4ecbe 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.txt @@ -19,8 +19,15 @@ created from prior invocations of linkgit:git-add[1]. Users are encouraged to run this task on a regular basis within each repository to maintain good disk space utilization and good -operating performance. Some git commands may automatically run -`git-gc`; see the `--auto` flag below for details. +operating performance. + +Some git commands may automatically run `git-gc`; see the `--auto` flag +below for details. If you know what you're doing and all you want is to +disable this behavior permanently without further considerations, just do: + +---------------------- +$ git config --global gc.auto 0 +---------------------- OPTIONS ------- diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 336d797e80..9d0a10c562 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -216,6 +216,9 @@ sendemail.chainreplyto:: sendemail.smtpserver:: Default SMTP server to use. +sendemail.smtpserverport:: + Default SMTP server port to use. + sendemail.smtpuser:: Default SMTP-AUTH username. diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt index 7df0266ba8..1276f858ad 100644 --- a/Documentation/merge-strategies.txt +++ b/Documentation/merge-strategies.txt @@ -33,3 +33,10 @@ ours:: merge is always the current branch head. It is meant to be used to supersede old development history of side branches. + +subtree:: + This is a modified recursive strategy. When merging trees A and + B, if B corresponds to a subtree of A, B is first adjusted to + match the tree structure of A, instead of reading the trees at + the same level. This adjustment is also done to the common + ancestor tree. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 6ddf04d216..d0b60f40d8 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.4.GIT +DEF_VER=v1.5.5-rc1.GIT LF=' ' diff --git a/Makefile b/Makefile index fa5956736c..dc2338e42d 100644 --- a/Makefile +++ b/Makefile @@ -232,59 +232,82 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ BASIC_CFLAGS = BASIC_LDFLAGS = -SCRIPT_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 \ - git-repack.sh git-request-pull.sh \ - git-sh-setup.sh \ - git-am.sh \ - git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \ - git-merge-resolve.sh \ - git-lost-found.sh git-quiltimport.sh git-submodule.sh \ - git-filter-branch.sh \ - git-stash.sh \ - git-web--browse.sh +SCRIPT_SH += git-am.sh +SCRIPT_SH += git-bisect.sh +SCRIPT_SH += git-clone.sh +SCRIPT_SH += git-filter-branch.sh +SCRIPT_SH += git-lost-found.sh +SCRIPT_SH += git-merge-octopus.sh +SCRIPT_SH += git-merge-one-file.sh +SCRIPT_SH += git-merge-resolve.sh +SCRIPT_SH += git-merge.sh +SCRIPT_SH += git-merge-stupid.sh +SCRIPT_SH += git-mergetool.sh +SCRIPT_SH += git-parse-remote.sh +SCRIPT_SH += git-pull.sh +SCRIPT_SH += git-quiltimport.sh +SCRIPT_SH += git-rebase--interactive.sh +SCRIPT_SH += git-rebase.sh +SCRIPT_SH += git-repack.sh +SCRIPT_SH += git-request-pull.sh +SCRIPT_SH += git-sh-setup.sh +SCRIPT_SH += git-stash.sh +SCRIPT_SH += git-submodule.sh +SCRIPT_SH += git-web--browse.sh -SCRIPT_PERL = \ - git-add--interactive.perl \ - git-archimport.perl git-cvsimport.perl git-relink.perl \ - git-cvsserver.perl git-cvsexportcommit.perl \ - git-send-email.perl git-svn.perl +SCRIPT_PERL += git-add--interactive.perl +SCRIPT_PERL += git-archimport.perl +SCRIPT_PERL += git-cvsexportcommit.perl +SCRIPT_PERL += git-cvsimport.perl +SCRIPT_PERL += git-cvsserver.perl +SCRIPT_PERL += git-relink.perl +SCRIPT_PERL += git-send-email.perl +SCRIPT_PERL += git-svn.perl SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.perl,%,$(SCRIPT_PERL)) \ git-instaweb -# ... and all the rest that could be moved out of bindir to gitexecdir -PROGRAMS = \ - git-fetch-pack$X \ - git-hash-object$X git-index-pack$X \ - git-fast-import$X \ - git-merge-index$X git-mktag$X git-mktree$X git-patch-id$X \ - git-receive-pack$X \ - git-send-pack$X git-shell$X \ - git-show-index$X \ - git-unpack-file$X \ - git-update-server-info$X \ - git-upload-pack$X \ - git-pack-redundant$X git-var$X \ - git-merge-tree$X \ - $(POSIX_ONLY_PROGRAMS) \ - $(EXTRA_PROGRAMS) - # Empty... EXTRA_PROGRAMS = +# ... and all the rest that could be moved out of bindir to gitexecdir +PROGRAMS += $(EXTRA_PROGRAMS) +PROGRAMS += git-fast-import$X +PROGRAMS += git-fetch-pack$X +PROGRAMS += git-hash-object$X +PROGRAMS += git-index-pack$X +PROGRAMS += git-merge-index$X +PROGRAMS += git-merge-tree$X +PROGRAMS += git-mktag$X +PROGRAMS += git-mktree$X +PROGRAMS += git-pack-redundant$X +PROGRAMS += git-patch-id$X +PROGRAMS += git-receive-pack$X +PROGRAMS += git-send-pack$X +PROGRAMS += git-shell$X +PROGRAMS += git-show-index$X +PROGRAMS += git-unpack-file$X +PROGRAMS += git-update-server-info$X +PROGRAMS += git-upload-pack$X +PROGRAMS += git-var$X + # 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)) +BUILT_INS += $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS)) + +BUILT_INS += git-cherry-pick$X +BUILT_INS += git-cherry$X +BUILT_INS += git-format-patch$X +BUILT_INS += git-fsck-objects$X +BUILT_INS += git-get-tar-commit-id$X +BUILT_INS += git-init$X +BUILT_INS += git-merge-subtree$X +BUILT_INS += git-peek-remote$X +BUILT_INS += git-repo-config$X +BUILT_INS += git-show$X +BUILT_INS += git-status$X +BUILT_INS += git-whatchanged$X # what 'all' will build and 'install' will install, in gitexecdir ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) @@ -305,113 +328,215 @@ export PERL_PATH LIB_FILE=libgit.a XDIFF_LIB=xdiff/lib.a -LIB_H = \ - archive.h blob.h cache.h cache-tree.h commit.h csum-file.h delta.h grep.h \ - diff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.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 ll-merge.h fsck.h \ - pack-revindex.h compat/mingw.h +LIB_H += archive.h +LIB_H += attr.h +LIB_H += blob.h +LIB_H += builtin.h +LIB_H += cache.h +LIB_H += cache-tree.h +LIB_H += commit.h +LIB_H += compat/mingw.h +LIB_H += csum-file.h +LIB_H += decorate.h +LIB_H += delta.h +LIB_H += diffcore.h +LIB_H += diff.h +LIB_H += dir.h +LIB_H += fsck.h +LIB_H += git-compat-util.h +LIB_H += grep.h +LIB_H += hash.h +LIB_H += list-objects.h +LIB_H += ll-merge.h +LIB_H += log-tree.h +LIB_H += mailmap.h +LIB_H += object.h +LIB_H += pack.h +LIB_H += pack-revindex.h +LIB_H += parse-options.h +LIB_H += patch-ids.h +LIB_H += path-list.h +LIB_H += pkt-line.h +LIB_H += progress.h +LIB_H += quote.h +LIB_H += reflog-walk.h +LIB_H += refs.h +LIB_H += remote.h +LIB_H += revision.h +LIB_H += run-command.h +LIB_H += sideband.h +LIB_H += strbuf.h +LIB_H += tag.h +LIB_H += transport.h +LIB_H += tree.h +LIB_H += tree-walk.h +LIB_H += unpack-trees.h +LIB_H += utf8.h -DIFF_OBJS = \ - diff.o diff-lib.o diffcore-break.o diffcore-order.o \ - diffcore-pickaxe.o diffcore-rename.o tree-diff.o combine-diff.o \ - diffcore-delta.o log-tree.o +LIB_OBJS += alias.o +LIB_OBJS += alloc.o +LIB_OBJS += archive.o +LIB_OBJS += archive-tar.o +LIB_OBJS += archive-zip.o +LIB_OBJS += attr.o +LIB_OBJS += base85.o +LIB_OBJS += blob.o +LIB_OBJS += branch.o +LIB_OBJS += bundle.o +LIB_OBJS += cache-tree.o +LIB_OBJS += color.o +LIB_OBJS += combine-diff.o +LIB_OBJS += commit.o +LIB_OBJS += config.o +LIB_OBJS += connect.o +LIB_OBJS += convert.o +LIB_OBJS += copy.o +LIB_OBJS += csum-file.o +LIB_OBJS += ctype.o +LIB_OBJS += date.o +LIB_OBJS += decorate.o +LIB_OBJS += diffcore-break.o +LIB_OBJS += diffcore-delta.o +LIB_OBJS += diffcore-order.o +LIB_OBJS += diffcore-pickaxe.o +LIB_OBJS += diffcore-rename.o +LIB_OBJS += diff-delta.o +LIB_OBJS += diff-lib.o +LIB_OBJS += diff.o +LIB_OBJS += dir.o +LIB_OBJS += entry.o +LIB_OBJS += environment.o +LIB_OBJS += exec_cmd.o +LIB_OBJS += fsck.o +LIB_OBJS += grep.o +LIB_OBJS += hash.o +LIB_OBJS += help.o +LIB_OBJS += ident.o +LIB_OBJS += interpolate.o +LIB_OBJS += list-objects.o +LIB_OBJS += ll-merge.o +LIB_OBJS += lockfile.o +LIB_OBJS += log-tree.o +LIB_OBJS += mailmap.o +LIB_OBJS += match-trees.o +LIB_OBJS += merge-file.o +LIB_OBJS += object.o +LIB_OBJS += pack-check.o +LIB_OBJS += pack-revindex.o +LIB_OBJS += pack-write.o +LIB_OBJS += pager.o +LIB_OBJS += parse-options.o +LIB_OBJS += patch-delta.o +LIB_OBJS += patch-ids.o +LIB_OBJS += path-list.o +LIB_OBJS += path.o +LIB_OBJS += pkt-line.o +LIB_OBJS += pretty.o +LIB_OBJS += progress.o +LIB_OBJS += quote.o +LIB_OBJS += reachable.o +LIB_OBJS += read-cache.o +LIB_OBJS += reflog-walk.o +LIB_OBJS += refs.o +LIB_OBJS += remote.o +LIB_OBJS += revision.o +LIB_OBJS += run-command.o +LIB_OBJS += server-info.o +LIB_OBJS += setup.o +LIB_OBJS += sha1_file.o +LIB_OBJS += sha1_name.o +LIB_OBJS += shallow.o +LIB_OBJS += sideband.o +LIB_OBJS += strbuf.o +LIB_OBJS += symlinks.o +LIB_OBJS += tag.o +LIB_OBJS += trace.o +LIB_OBJS += transport.o +LIB_OBJS += tree-diff.o +LIB_OBJS += tree.o +LIB_OBJS += tree-walk.o +LIB_OBJS += unpack-trees.o +LIB_OBJS += usage.o +LIB_OBJS += utf8.o +LIB_OBJS += walker.o +LIB_OBJS += write_or_die.o +LIB_OBJS += ws.o +LIB_OBJS += wt-status.o +LIB_OBJS += xdiff-interface.o -LIB_OBJS = \ - blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \ - date.o diff-delta.o entry.o exec_cmd.o ident.o \ - pretty.o interpolate.o hash.o \ - lockfile.o \ - 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 \ - 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 \ - write_or_die.o trace.o list-objects.o grep.o match-trees.o \ - 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 branch.o \ - ll-merge.o alias.o fsck.o pack-revindex.o - -BUILTIN_OBJS = \ - builtin-add.o \ - builtin-annotate.o \ - builtin-apply.o \ - builtin-archive.o \ - builtin-blame.o \ - builtin-branch.o \ - 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 \ - builtin-commit.o \ - builtin-commit-tree.o \ - builtin-count-objects.o \ - builtin-describe.o \ - builtin-diff.o \ - builtin-diff-files.o \ - builtin-diff-index.o \ - builtin-diff-tree.o \ - builtin-fast-export.o \ - builtin-fetch.o \ - builtin-fetch-pack.o \ - builtin-fetch--tool.o \ - builtin-fmt-merge-msg.o \ - builtin-for-each-ref.o \ - builtin-fsck.o \ - builtin-gc.o \ - builtin-grep.o \ - builtin-init-db.o \ - builtin-log.o \ - builtin-ls-files.o \ - builtin-ls-tree.o \ - builtin-ls-remote.o \ - builtin-mailinfo.o \ - builtin-mailsplit.o \ - 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 \ - builtin-prune.o \ - builtin-prune-packed.o \ - builtin-push.o \ - builtin-read-tree.o \ - builtin-reflog.o \ - builtin-remote.o \ - builtin-send-pack.o \ - builtin-config.o \ - builtin-rerere.o \ - builtin-reset.o \ - builtin-rev-list.o \ - builtin-rev-parse.o \ - builtin-revert.o \ - builtin-rm.o \ - builtin-shortlog.o \ - builtin-show-branch.o \ - builtin-stripspace.o \ - builtin-symbolic-ref.o \ - builtin-tag.o \ - builtin-tar-tree.o \ - builtin-unpack-objects.o \ - builtin-update-index.o \ - builtin-update-ref.o \ - builtin-upload-archive.o \ - builtin-verify-pack.o \ - builtin-verify-tag.o \ - builtin-write-tree.o \ - builtin-show-ref.o \ - builtin-pack-refs.o +BUILTIN_OBJS += builtin-add.o +BUILTIN_OBJS += builtin-annotate.o +BUILTIN_OBJS += builtin-apply.o +BUILTIN_OBJS += builtin-archive.o +BUILTIN_OBJS += builtin-blame.o +BUILTIN_OBJS += builtin-branch.o +BUILTIN_OBJS += builtin-bundle.o +BUILTIN_OBJS += builtin-cat-file.o +BUILTIN_OBJS += builtin-check-attr.o +BUILTIN_OBJS += builtin-check-ref-format.o +BUILTIN_OBJS += builtin-checkout-index.o +BUILTIN_OBJS += builtin-checkout.o +BUILTIN_OBJS += builtin-clean.o +BUILTIN_OBJS += builtin-commit-tree.o +BUILTIN_OBJS += builtin-commit.o +BUILTIN_OBJS += builtin-config.o +BUILTIN_OBJS += builtin-count-objects.o +BUILTIN_OBJS += builtin-describe.o +BUILTIN_OBJS += builtin-diff-files.o +BUILTIN_OBJS += builtin-diff-index.o +BUILTIN_OBJS += builtin-diff-tree.o +BUILTIN_OBJS += builtin-diff.o +BUILTIN_OBJS += builtin-fast-export.o +BUILTIN_OBJS += builtin-fetch--tool.o +BUILTIN_OBJS += builtin-fetch-pack.o +BUILTIN_OBJS += builtin-fetch.o +BUILTIN_OBJS += builtin-fmt-merge-msg.o +BUILTIN_OBJS += builtin-for-each-ref.o +BUILTIN_OBJS += builtin-fsck.o +BUILTIN_OBJS += builtin-gc.o +BUILTIN_OBJS += builtin-grep.o +BUILTIN_OBJS += builtin-init-db.o +BUILTIN_OBJS += builtin-log.o +BUILTIN_OBJS += builtin-ls-files.o +BUILTIN_OBJS += builtin-ls-remote.o +BUILTIN_OBJS += builtin-ls-tree.o +BUILTIN_OBJS += builtin-mailinfo.o +BUILTIN_OBJS += builtin-mailsplit.o +BUILTIN_OBJS += builtin-merge-base.o +BUILTIN_OBJS += builtin-merge-file.o +BUILTIN_OBJS += builtin-merge-ours.o +BUILTIN_OBJS += builtin-merge-recursive.o +BUILTIN_OBJS += builtin-mv.o +BUILTIN_OBJS += builtin-name-rev.o +BUILTIN_OBJS += builtin-pack-objects.o +BUILTIN_OBJS += builtin-pack-refs.o +BUILTIN_OBJS += builtin-prune-packed.o +BUILTIN_OBJS += builtin-prune.o +BUILTIN_OBJS += builtin-push.o +BUILTIN_OBJS += builtin-read-tree.o +BUILTIN_OBJS += builtin-reflog.o +BUILTIN_OBJS += builtin-remote.o +BUILTIN_OBJS += builtin-rerere.o +BUILTIN_OBJS += builtin-reset.o +BUILTIN_OBJS += builtin-rev-list.o +BUILTIN_OBJS += builtin-rev-parse.o +BUILTIN_OBJS += builtin-revert.o +BUILTIN_OBJS += builtin-rm.o +BUILTIN_OBJS += builtin-send-pack.o +BUILTIN_OBJS += builtin-shortlog.o +BUILTIN_OBJS += builtin-show-branch.o +BUILTIN_OBJS += builtin-show-ref.o +BUILTIN_OBJS += builtin-stripspace.o +BUILTIN_OBJS += builtin-symbolic-ref.o +BUILTIN_OBJS += builtin-tag.o +BUILTIN_OBJS += builtin-tar-tree.o +BUILTIN_OBJS += builtin-unpack-objects.o +BUILTIN_OBJS += builtin-update-index.o +BUILTIN_OBJS += builtin-update-ref.o +BUILTIN_OBJS += builtin-upload-archive.o +BUILTIN_OBJS += builtin-verify-pack.o +BUILTIN_OBJS += builtin-verify-tag.o +BUILTIN_OBJS += builtin-write-tree.o GITLIBS = $(LIB_FILE) $(XDIFF_LIB) EXTLIBS = /mingw/lib/libz.a @@ -629,9 +754,8 @@ endif EXTLIBS += -lz ifndef NO_POSIX_ONLY_PROGRAMS - POSIX_ONLY_PROGRAMS = \ - git-daemon$X \ - git-imap-send$X + PROGRAMS += git-daemon$X + PROGRAMS += git-imap-send$X endif ifndef NO_OPENSSL OPENSSL_LIBSSL = -lssl diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 30c9ba78fa..4feaa73888 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -26,6 +26,8 @@ static const char fetch_pack_usage[] = #define SEEN (1U << 3) #define POPPED (1U << 4) +static int marked; + /* * After sending this many "have"s if we do not get any new ACK , we * give up traversing our history. @@ -61,6 +63,16 @@ static int rev_list_insert_ref(const char *path, const unsigned char *sha1, int return 0; } +static int clear_marks(const char *path, const unsigned char *sha1, int flag, void *cb_data) +{ + struct object *o = deref_tag(parse_object(sha1), path, 0); + + if (o && o->type == OBJ_COMMIT) + clear_commit_marks((struct commit *)o, + COMMON | COMMON_REF | SEEN | POPPED); + return 0; +} + /* This function marks a rev and its ancestors as common. In some cases, it is desirable to mark only the ancestors (for example @@ -153,6 +165,10 @@ static int find_common(int fd[2], unsigned char *result_sha1, unsigned in_vain = 0; int got_continue = 0; + if (marked) + for_each_ref(clear_marks, NULL); + marked = 1; + for_each_ref(rev_list_insert_ref, NULL); fetching = 0; diff --git a/builtin-fetch.c b/builtin-fetch.c index b2b9935ed6..a11548c894 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -652,5 +652,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) signal(SIGINT, unlock_pack_on_signal); atexit(unlock_pack); - return do_fetch(transport, parse_ref_spec(ref_nr, refs), ref_nr); + return do_fetch(transport, + parse_fetch_refspec(ref_nr, refs), ref_nr); } diff --git a/builtin-gc.c b/builtin-gc.c index 95917d74a8..8cef36f6a4 100644 --- a/builtin-gc.c +++ b/builtin-gc.c @@ -25,7 +25,7 @@ static const char * const builtin_gc_usage[] = { static int pack_refs = 1; static int aggressive_window = -1; static int gc_auto_threshold = 6700; -static int gc_auto_pack_limit = 20; +static int gc_auto_pack_limit = 50; static char *prune_expire = "2.weeks.ago"; #define MAX_ADD 10 @@ -160,10 +160,10 @@ static int too_many_packs(void) static int need_to_gc(void) { /* - * Setting gc.auto and gc.autopacklimit to 0 or negative can - * disable the automatic gc. + * Setting gc.auto to 0 or negative can disable the + * automatic gc. */ - if (gc_auto_threshold <= 0 && gc_auto_pack_limit <= 0) + if (gc_auto_threshold <= 0) return 0; /* diff --git a/builtin-remote.c b/builtin-remote.c index 24e692953b..9c15173032 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -207,7 +207,10 @@ static int handle_one_branch(const char *refname, if (!remote_find_tracking(states->remote, &refspec)) { struct path_list_item *item; const char *name = skip_prefix(refspec.src, "refs/heads/"); - if (unsorted_path_list_has_path(&states->tracked, name) || + /* symbolic refs pointing nowhere were handled already */ + if ((flags & REF_ISSYMREF) || + unsorted_path_list_has_path(&states->tracked, + name) || unsorted_path_list_has_path(&states->new, name)) return 0; diff --git a/builtin-rev-list.c b/builtin-rev-list.c index d0a1416921..edc0bd35bb 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -33,6 +33,7 @@ static const char rev_list_usage[] = " ordering output:\n" " --topo-order\n" " --date-order\n" +" --reverse\n" " formatting output:\n" " --parents\n" " --objects | --objects-edge\n" diff --git a/builtin-send-pack.c b/builtin-send-pack.c index 930e0fb3fd..bb9c33a650 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -537,7 +537,7 @@ static void verify_remote_names(int nr_heads, const char **heads) int i; for (i = 0; i < nr_heads; i++) { - const char *remote = strchr(heads[i], ':'); + const char *remote = strrchr(heads[i], ':'); remote = remote ? (remote + 1) : heads[i]; switch (check_ref_format(remote)) { diff --git a/compat/mingw.c b/compat/mingw.c index 7c8fd0e158..a5b43bcf6f 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -175,6 +175,33 @@ int mingw_fstat(int fd, struct mingw_stat *buf) return -1; } +static inline void time_t_to_filetime(time_t t, FILETIME *ft) +{ + long long winTime = t * 10000000LL + 116444736000000000LL; + ft->dwLowDateTime = winTime; + ft->dwHighDateTime = winTime >> 32; +} + +int mingw_utime (const char *file_name, const struct utimbuf *times) +{ + FILETIME mft, aft; + int fh, rc; + + /* must have write permission */ + if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0) + return -1; + + time_t_to_filetime(times->modtime, &mft); + time_t_to_filetime(times->actime, &aft); + if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) { + errno = EINVAL; + rc = -1; + } else + rc = 0; + close(fh); + return rc; +} + unsigned int sleep (unsigned int seconds) { Sleep(seconds*1000); diff --git a/compat/mingw.h b/compat/mingw.h index c7db345d58..0e18b78b14 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -174,6 +174,9 @@ int mingw_fstat(int fd, struct mingw_stat *buf); static inline int mingw_stat(const char *file_name, struct mingw_stat *buf) { return mingw_lstat(file_name, buf); } +int mingw_utime(const char *file_name, const struct utimbuf *times); +#define utime mingw_utime + pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env); void mingw_execvp(const char *cmd, char *const *argv); #define execvp mingw_execvp diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 650ea34176..3cb0330ec2 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -627,6 +627,8 @@ class P4Submit(Command): if self.interactive: submitTemplate = self.prepareLogMessage(template, logMessage) + if os.environ.has_key("P4DIFF"): + del(os.environ["P4DIFF"]) diff = read_pipe("p4 diff -du ...") for newFile in filesToAdd: @@ -650,7 +652,10 @@ class P4Submit(Command): defaultEditor = "vi" if platform.system() == "Windows": defaultEditor = "notepad" - editor = os.environ.get("EDITOR", defaultEditor); + if os.environ.has_key("P4EDITOR"): + editor = os.environ.get("P4EDITOR") + else: + editor = os.environ.get("EDITOR", defaultEditor); system(editor + " " + fileName) tmpFile = open(fileName, "rb") message = tmpFile.read() @@ -882,21 +887,21 @@ class P4Sync(Command): while j < len(filedata): stat = filedata[j] j += 1 - text = '' + text = []; while j < len(filedata) and filedata[j]['code'] in ('text', 'unicode', 'binary'): - tmp = filedata[j]['data'] - if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'): - tmp = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', tmp) - elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'): - tmp = re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', tmp) - text += tmp + text.append(filedata[j]['data']) j += 1 - + text = ''.join(text) if not stat.has_key('depotFile'): sys.stderr.write("p4 print fails with: %s\n" % repr(stat)) continue + if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'): + text = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text) + elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'): + text = re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text) + contents[stat['depotFile']] = text for f in filesForCommit: diff --git a/entry.c b/entry.c index 44f4b897d4..222aaa374b 100644 --- a/entry.c +++ b/entry.c @@ -218,7 +218,6 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t * to emulate by hand - much easier to let the system * just do the right thing) */ - unlink(path); if (S_ISDIR(st.st_mode)) { /* If it is a gitlink, leave it alone! */ if (S_ISGITLINK(ce->ce_mode)) @@ -226,7 +225,8 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t if (!state->force) return error("%s is a directory", path); remove_subtree(path); - } + } else if (unlink(path)) + return error("unable to unlink old '%s' (%s)", path, strerror(errno)); } else if (state->not_new) return 0; create_directories(path, state); diff --git a/fast-import.c b/fast-import.c index 76af3d9763..41555ce401 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1518,6 +1518,8 @@ static int update_branch(struct branch *b) struct ref_lock *lock; unsigned char old_sha1[20]; + if (is_null_sha1(b->sha1)) + return 0; if (read_ref(b->name, old_sha1)) hashclr(old_sha1); lock = lock_any_ref_for_update(b->name, old_sha1, 0); diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh index 9ee3f80452..e1eb963266 100755 --- a/git-merge-one-file.sh +++ b/git-merge-one-file.sh @@ -48,10 +48,11 @@ case "${1:-.}${2:-.}${3:-.}" in ;; "..$3") echo "Adding $4" - test -f "$4" || { + if test -f "$4" + then echo "ERROR: untracked $4 is overwritten by the merge." exit 1 - } + fi git update-index --add --cacheinfo "$7" "$3" "$4" && exec git checkout-index -u -f -- "$4" ;; diff --git a/git-svn.perl b/git-svn.perl index bba22c1321..0c2b791eab 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -3665,7 +3665,7 @@ sub escape_uri_only { my ($uri) = @_; my @tmp; foreach (split m{/}, $uri) { - s/([^\w.-])/sprintf("%%%02X",ord($1))/eg; + s/([^\w.%-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg; push @tmp, $_; } join('/', @tmp); diff --git a/remote.c b/remote.c index f3f7375eea..40ed24633f 100644 --- a/remote.c +++ b/remote.c @@ -393,42 +393,123 @@ static void read_config(void) alias_all_urls(); } -struct refspec *parse_ref_spec(int nr_refspec, const char **refspec) +static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch) { int i; + int st; struct refspec *rs = xcalloc(sizeof(*rs), nr_refspec); + for (i = 0; i < nr_refspec; i++) { - const char *sp, *ep, *gp; - sp = refspec[i]; - if (*sp == '+') { + size_t llen, rlen; + int is_glob; + const char *lhs, *rhs; + + llen = rlen = is_glob = 0; + + lhs = refspec[i]; + if (*lhs == '+') { rs[i].force = 1; - sp++; + lhs++; } - gp = strchr(sp, '*'); - ep = strchr(sp, ':'); - if (gp && ep && gp > ep) - gp = NULL; - if (ep) { - if (ep[1]) { - const char *glob = strchr(ep + 1, '*'); - if (!glob) - gp = NULL; - if (gp) - rs[i].dst = xstrndup(ep + 1, - glob - ep - 1); - else - rs[i].dst = xstrdup(ep + 1); + + rhs = strrchr(lhs, ':'); + if (rhs) { + rhs++; + rlen = strlen(rhs); + is_glob = (2 <= rlen && !strcmp(rhs + rlen - 2, "/*")); + rs[i].dst = xstrndup(rhs, rlen - is_glob * 2); + } + + llen = (rhs ? (rhs - lhs - 1) : strlen(lhs)); + if (is_glob != (2 <= llen && !memcmp(lhs + llen - 2, "/*", 2))) + goto invalid; + + if (is_glob) { + llen -= 2; + rlen -= 2; + } + rs[i].pattern = is_glob; + rs[i].src = xstrndup(lhs, llen); + + if (fetch) { + /* + * LHS + * - empty is allowed; it means HEAD. + * - otherwise it must be a valid looking ref. + */ + if (!*rs[i].src) + ; /* empty is ok */ + else { + st = check_ref_format(rs[i].src); + if (st && st != CHECK_REF_FORMAT_ONELEVEL) + goto invalid; + } + /* + * RHS + * - missing is allowed. + * - empty is ok; it means not to store. + * - otherwise it must be a valid looking ref. + */ + if (!rs[i].dst) { + ; /* ok */ + } else if (!*rs[i].dst) { + ; /* ok */ + } else { + st = check_ref_format(rs[i].dst); + if (st && st != CHECK_REF_FORMAT_ONELEVEL) + goto invalid; } } else { - ep = sp + strlen(sp); + /* + * LHS + * - empty is allowed; it means delete. + * - when wildcarded, it must be a valid looking ref. + * - otherwise, it must be an extended SHA-1, but + * there is no existing way to validate this. + */ + if (!*rs[i].src) + ; /* empty is ok */ + else if (is_glob) { + st = check_ref_format(rs[i].src); + if (st && st != CHECK_REF_FORMAT_ONELEVEL) + goto invalid; + } + else + ; /* anything goes, for now */ + /* + * RHS + * - missing is allowed, but LHS then must be a + * valid looking ref. + * - empty is not allowed. + * - otherwise it must be a valid looking ref. + */ + if (!rs[i].dst) { + st = check_ref_format(rs[i].src); + if (st && st != CHECK_REF_FORMAT_ONELEVEL) + goto invalid; + } else if (!*rs[i].dst) { + goto invalid; + } else { + st = check_ref_format(rs[i].dst); + if (st && st != CHECK_REF_FORMAT_ONELEVEL) + goto invalid; + } } - if (gp) { - rs[i].pattern = 1; - ep = gp; - } - rs[i].src = xstrndup(sp, ep - sp); } return rs; + + invalid: + die("Invalid refspec '%s'", refspec[i]); +} + +struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec) +{ + return parse_refspec_internal(nr_refspec, refspec, 1); +} + +struct refspec *parse_push_refspec(int nr_refspec, const char **refspec) +{ + return parse_refspec_internal(nr_refspec, refspec, 0); } static int valid_remote_nick(const char *name) @@ -459,8 +540,8 @@ struct remote *remote_get(const char *name) add_url_alias(ret, name); if (!ret->url) return NULL; - ret->fetch = parse_ref_spec(ret->fetch_refspec_nr, ret->fetch_refspec); - ret->push = parse_ref_spec(ret->push_refspec_nr, ret->push_refspec); + ret->fetch = parse_fetch_refspec(ret->fetch_refspec_nr, ret->fetch_refspec); + ret->push = parse_push_refspec(ret->push_refspec_nr, ret->push_refspec); return ret; } @@ -473,11 +554,11 @@ int for_each_remote(each_remote_fn fn, void *priv) if (!r) continue; if (!r->fetch) - r->fetch = parse_ref_spec(r->fetch_refspec_nr, - r->fetch_refspec); + r->fetch = parse_fetch_refspec(r->fetch_refspec_nr, + r->fetch_refspec); if (!r->push) - r->push = parse_ref_spec(r->push_refspec_nr, - r->push_refspec); + r->push = parse_push_refspec(r->push_refspec_nr, + r->push_refspec); result = fn(r, priv); } return result; @@ -543,7 +624,8 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec) if (!fetch->dst) continue; if (fetch->pattern) { - if (!prefixcmp(needle, key)) { + if (!prefixcmp(needle, key) && + needle[strlen(key)] == '/') { *result = xmalloc(strlen(value) + strlen(needle) - strlen(key) + 1); @@ -790,7 +872,9 @@ static const struct refspec *check_pattern_match(const struct refspec *rs, { int i; for (i = 0; i < rs_nr; i++) { - if (rs[i].pattern && !prefixcmp(src->name, rs[i].src)) + if (rs[i].pattern && + !prefixcmp(src->name, rs[i].src) && + src->name[strlen(rs[i].src)] == '/') return rs + i; } return NULL; @@ -805,7 +889,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, int nr_refspec, const char **refspec, int flags) { struct refspec *rs = - parse_ref_spec(nr_refspec, (const char **) refspec); + parse_push_refspec(nr_refspec, (const char **) refspec); int send_all = flags & MATCH_REFS_ALL; int send_mirror = flags & MATCH_REFS_MIRROR; @@ -989,7 +1073,7 @@ int get_fetch_map(const struct ref *remote_refs, struct ref ***tail, int missing_ok) { - struct ref *ref_map, *rm; + struct ref *ref_map, **rmp; if (refspec->pattern) { ref_map = get_expanded_map(remote_refs, refspec); @@ -1006,10 +1090,20 @@ int get_fetch_map(const struct ref *remote_refs, } } - for (rm = ref_map; rm; rm = rm->next) { - if (rm->peer_ref && check_ref_format(rm->peer_ref->name + 5)) - die("* refusing to create funny ref '%s' locally", - rm->peer_ref->name); + for (rmp = &ref_map; *rmp; ) { + if ((*rmp)->peer_ref) { + int st = check_ref_format((*rmp)->peer_ref->name + 5); + if (st && st != CHECK_REF_FORMAT_ONELEVEL) { + struct ref *ignore = *rmp; + error("* Ignoring funny ref '%s' locally", + (*rmp)->peer_ref->name); + *rmp = (*rmp)->next; + free(ignore->peer_ref); + free(ignore); + continue; + } + } + rmp = &((*rmp)->next); } if (ref_map) diff --git a/remote.h b/remote.h index f1dedf15f6..7e9ae792dc 100644 --- a/remote.h +++ b/remote.h @@ -67,7 +67,8 @@ void free_refs(struct ref *ref); */ void ref_remove_duplicates(struct ref *ref_map); -struct refspec *parse_ref_spec(int nr_refspec, const char **refspec); +struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec); +struct refspec *parse_push_refspec(int nr_refspec, const char **refspec); int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, int nr_refspec, const char **refspec, int all); diff --git a/revision.c b/revision.c index 63bf2c5c2d..196fedc9d1 100644 --- a/revision.c +++ b/revision.c @@ -564,14 +564,39 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs) free_patch_ids(&ids); } -static void add_to_list(struct commit_list **p, struct commit *commit, struct commit_list *n) +/* How many extra uninteresting commits we want to see.. */ +#define SLOP 5 + +static int still_interesting(struct commit_list *src, unsigned long date, int slop) { - p = &commit_list_insert(commit, p)->next; - *p = n; + /* + * No source list at all? We're definitely done.. + */ + if (!src) + return 0; + + /* + * Does the destination list contain entries with a date + * before the source list? Definitely _not_ done. + */ + if (date < src->item->date) + return SLOP; + + /* + * Does the source list still have interesting commits in + * it? Definitely not done.. + */ + if (!everybody_uninteresting(src)) + return SLOP; + + /* Ok, we're closing in.. */ + return slop-1; } static int limit_list(struct rev_info *revs) { + int slop = SLOP; + unsigned long date = ~0ul; struct commit_list *list = revs->commits; struct commit_list *newlist = NULL; struct commit_list **p = &newlist; @@ -591,16 +616,19 @@ static int limit_list(struct rev_info *revs) return -1; if (obj->flags & UNINTERESTING) { mark_parents_uninteresting(commit); - if (everybody_uninteresting(list)) { - if (revs->show_all) - add_to_list(p, commit, list); - break; - } - if (!revs->show_all) + if (revs->show_all) + p = &commit_list_insert(commit, p)->next; + slop = still_interesting(list, date, slop); + if (slop) continue; + /* If showing all, add the whole pending list to the end */ + if (revs->show_all) + *p = list; + break; } if (revs->min_age != -1 && (commit->date > revs->min_age)) continue; + date = commit->date; p = &commit_list_insert(commit, p)->next; show = show_early_output; diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index 9ee35e7901..9decd2e1e8 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -49,8 +49,28 @@ poke() { test-chmtime +1 "$1" } -SVN_HTTPD_MODULE_PATH=${SVN_HTTPD_MODULE_PATH-'/usr/lib/apache2/modules'} -SVN_HTTPD_PATH=${SVN_HTTPD_PATH-'/usr/sbin/apache2'} +for d in \ + "$SVN_HTTPD_PATH" \ + /usr/sbin/apache2 \ + /usr/sbin/httpd \ +; do + if test -f "$d" + then + SVN_HTTPD_PATH="$d" + break + fi +done +for d in \ + "$SVN_HTTPD_MODULE_PATH" \ + /usr/lib/apache2/modules \ + /usr/libexec/apache2 \ +; do + if test -d "$d" + then + SVN_HTTPD_MODULE_PATH="$d" + break + fi +done start_httpd () { if test -z "$SVN_HTTPD_PORT" @@ -66,6 +86,7 @@ ServerName "git-svn test" ServerRoot "$GIT_DIR" DocumentRoot "$GIT_DIR" PidFile "$GIT_DIR/httpd.pid" +LockFile logs/accept.lock Listen 127.0.0.1:$SVN_HTTPD_PORT LoadModule dav_module $SVN_HTTPD_MODULE_PATH/mod_dav.so LoadModule dav_svn_module $SVN_HTTPD_MODULE_PATH/mod_dav_svn.so diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh index 6c065bfa21..17f519f547 100755 --- a/t/t1000-read-tree-m-3way.sh +++ b/t/t1000-read-tree-m-3way.sh @@ -214,7 +214,7 @@ test_expect_success '1 - must not have an entry not in A.' " rm -f .git/index XX && echo XX >XX && git update-index --add XX && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -254,7 +254,7 @@ test_expect_success \ cp .orig-A/AN AN && echo extra >>AN && git update-index --add AN && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -271,7 +271,7 @@ test_expect_success \ cp .orig-A/AA AA && git update-index --add AA && echo extra >>AA && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -280,7 +280,7 @@ test_expect_success \ cp .orig-A/AA AA && echo extra >>AA && git update-index --add AA && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -306,7 +306,7 @@ test_expect_success \ cp .orig-A/LL LL && echo extra >>LL && git update-index --add LL && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -314,7 +314,7 @@ test_expect_success \ rm -f .git/index DD && echo DD >DD git update-index --add DD && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -322,7 +322,7 @@ test_expect_success \ rm -f .git/index DM && cp .orig-B/DM DM && git update-index --add DM && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -330,7 +330,7 @@ test_expect_success \ rm -f .git/index DN && cp .orig-B/DN DN && git update-index --add DN && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -347,7 +347,7 @@ test_expect_success \ cp .orig-A/MD MD && git update-index --add MD && echo extra >>MD && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -356,7 +356,7 @@ test_expect_success \ cp .orig-A/MD MD && echo extra >>MD && git update-index --add MD && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -373,7 +373,7 @@ test_expect_success \ cp .orig-A/ND ND && git update-index --add ND && echo extra >>ND && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -382,7 +382,7 @@ test_expect_success \ cp .orig-A/ND ND && echo extra >>ND && git update-index --add ND && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -399,7 +399,7 @@ test_expect_success \ cp .orig-A/MM MM && git update-index --add MM && echo extra >>MM && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -408,7 +408,7 @@ test_expect_success \ cp .orig-A/MM MM && echo extra >>MM && git update-index --add MM && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -434,7 +434,7 @@ test_expect_success \ cp .orig-A/SS SS && echo extra >>SS && git update-index --add SS && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -477,7 +477,7 @@ test_expect_success \ cp .orig-A/NM NM && git update-index --add NM && echo extra >>NM && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -486,7 +486,7 @@ test_expect_success \ cp .orig-A/NM NM && echo extra >>NM && git update-index --add NM && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -512,7 +512,7 @@ test_expect_success \ cp .orig-A/NN NN && echo extra >>NN && git update-index --add NN && - ! git read-tree -m $tree_O $tree_A $tree_B + test_must_fail git read-tree -m $tree_O $tree_A $tree_B " # #16 diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh index d609a551ae..bc6dc95e9c 100755 --- a/t/t1004-read-tree-m-u-wf.sh +++ b/t/t1004-read-tree-m-u-wf.sh @@ -116,4 +116,128 @@ test_expect_success 'three-way not complaining on an untracked file' ' git read-tree -m -u --exclude-per-directory=.gitignore branch-point master side ' +test_expect_success '3-way not overwriting local changes (setup)' ' + + git reset --hard && + git checkout -b side-a branch-point && + echo >>file1 "new line to be kept in the merge result" && + git commit -a -m "side-a changes file1" && + git checkout -b side-b branch-point && + echo >>file2 "new line to be kept in the merge result" && + git commit -a -m "side-b changes file2" && + git checkout side-a + +' + +test_expect_success '3-way not overwriting local changes (our side)' ' + + # At this point, file1 from side-a should be kept as side-b + # did not touch it. + + git reset --hard && + + echo >>file1 "local changes" && + git read-tree -m -u branch-point side-a side-b && + grep "new line to be kept" file1 && + grep "local changes" file1 + +' + +test_expect_success '3-way not overwriting local changes (their side)' ' + + # At this point, file2 from side-b should be taken as side-a + # did not touch it. + + git reset --hard && + + echo >>file2 "local changes" && + test_must_fail git read-tree -m -u branch-point side-a side-b && + ! grep "new line to be kept" file2 && + grep "local changes" file2 + +' + +test "$no_symlinks" || { +test_expect_success 'funny symlink in work tree' ' + + git reset --hard && + git checkout -b sym-b side-b && + mkdir -p a && + >a/b && + git add a/b && + git commit -m "side adds a/b" && + + rm -fr a && + git checkout -b sym-a side-a && + mkdir -p a && + ln -s ../b a/b && + git add a/b && + git commit -m "we add a/b" && + + git read-tree -m -u sym-a sym-a sym-b + +' + +test_expect_success 'funny symlink in work tree, un-unlink-able' ' + + rm -fr a b && + git reset --hard && + + git checkout sym-a && + chmod a-w a && + test_must_fail git read-tree -m -u sym-a sym-a sym-b + +' + +# clean-up from the above test +chmod a+w a +rm -fr a b +} # $no_symlinks + +test_expect_success 'D/F setup' ' + + git reset --hard && + + git checkout side-a && + rm -f subdir/file2 && + mkdir subdir/file2 && + echo qfwfq >subdir/file2/another && + git add subdir/file2/another && + test_tick && + git commit -m "side-a changes file2 to directory" + +' + +test_expect_success 'D/F' ' + + git checkout side-b && + git read-tree -m -u branch-point side-b side-a && + git ls-files -u >actual && + ( + a=$(git rev-parse branch-point:subdir/file2) + b=$(git rev-parse side-a:subdir/file2/another) + echo "100644 $a 1 subdir/file2" + echo "100644 $a 2 subdir/file2" + echo "100644 $b 3 subdir/file2/another" + ) >expect && + test_cmp actual expect + +' + +test_expect_success 'D/F resolve' ' + + git reset --hard && + git checkout side-b && + git merge-resolve branch-point -- side-b side-a + +' + +test_expect_success 'D/F recursive' ' + + git reset --hard && + git checkout side-b && + git merge-recursive branch-point -- side-b side-a + +' + test_done diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 38e91809bf..f068f1957f 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -155,16 +155,6 @@ test_expect_success 'test tracking setup via config' \ test $(git config branch.my3.remote) = local && test $(git config branch.my3.merge) = refs/heads/master' -test_expect_success 'avoid ambiguous track' ' - git config branch.autosetupmerge true && - git config remote.ambi1.url = lalala && - git config remote.ambi1.fetch = refs/heads/lalala:refs/heads/master && - git config remote.ambi2.url = lilili && - git config remote.ambi2.fetch = refs/heads/lilili:refs/heads/master && - git branch all1 master && - test -z "$(git config branch.all1.merge)" -' - test_expect_success 'test overriding tracking setup via --no-track' \ 'git config branch.autosetupmerge true && git config remote.local.url . && @@ -226,4 +216,14 @@ test_expect_success \ test -f .git/logs/refs/heads/g/h/i && diff expect .git/logs/refs/heads/g/h/i' +test_expect_success 'avoid ambiguous track' ' + git config branch.autosetupmerge true && + git config remote.ambi1.url lalala && + git config remote.ambi1.fetch refs/heads/lalala:refs/heads/master && + git config remote.ambi2.url lilili && + git config remote.ambi2.fetch refs/heads/lilili:refs/heads/master && + git branch all1 master && + test -z "$(git config branch.all1.merge)" +' + test_done diff --git a/t/t4150-am-subdir.sh b/t/t4150-am-subdir.sh index 52069b469b..3cb7965644 100755 --- a/t/t4150-am-subdir.sh +++ b/t/t4150-am-subdir.sh @@ -56,7 +56,11 @@ test_expect_success 'am regularly from file in subdirectory' ' test_cmp expect actual ' -test_expect_success 'am regularly from file in subdirectory with full path' ' +case $(uname -s) in +*MINGW*) test_expect=test_expect_failure;; +*) test_expect=test_expect_success;; +esac +$test_expect 'am regularly from file in subdirectory with full path' ' rm -fr subdir && git checkout initial && P=$(pwd) && diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index ecfc999aaa..004a8dc5ed 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -237,4 +237,14 @@ test_expect_success 'update default (overridden, with funny whitespace)' ' ' +test_expect_success '"remote show" does not show symbolic refs' ' + + git clone one three && + (cd three && + git remote show origin > output && + ! grep HEAD < output && + ! grep -i stale < output) + +' + test_done diff --git a/t/t5511-refspec.sh b/t/t5511-refspec.sh new file mode 100755 index 0000000000..670a8f1c99 --- /dev/null +++ b/t/t5511-refspec.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +test_description='refspec parsing' + +. ./test-lib.sh + +test_refspec () { + + kind=$1 refspec=$2 expect=$3 + git config remote.frotz.url "." && + git config --remove-section remote.frotz && + git config remote.frotz.url "." && + git config "remote.frotz.$kind" "$refspec" && + if test "$expect" != invalid + then + title="$kind $refspec" + test='git ls-remote frotz' + else + title="$kind $refspec (invalid)" + test='test_must_fail git ls-remote frotz' + fi + test_expect_success "$title" "$test" +} + +test_refspec push '' invalid +test_refspec push ':' invalid + +test_refspec fetch '' +test_refspec fetch ':' + +test_refspec push 'refs/heads/*:refs/remotes/frotz/*' +test_refspec push 'refs/heads/*:refs/remotes/frotz' invalid +test_refspec push 'refs/heads:refs/remotes/frotz/*' invalid +test_refspec push 'refs/heads/master:refs/remotes/frotz/xyzzy' + + +# These have invalid LHS, but we do not have a formal "valid sha-1 +# expression syntax checker" so they are not checked with the current +# code. They will be caught downstream anyway, but we may want to +# have tighter check later... + +: test_refspec push 'refs/heads/master::refs/remotes/frotz/xyzzy' invalid +: test_refspec push 'refs/heads/maste :refs/remotes/frotz/xyzzy' invalid + +test_refspec fetch 'refs/heads/*:refs/remotes/frotz/*' +test_refspec fetch 'refs/heads/*:refs/remotes/frotz' invalid +test_refspec fetch 'refs/heads:refs/remotes/frotz/*' invalid +test_refspec fetch 'refs/heads/master:refs/remotes/frotz/xyzzy' +test_refspec fetch 'refs/heads/master::refs/remotes/frotz/xyzzy' invalid +test_refspec fetch 'refs/heads/maste :refs/remotes/frotz/xyzzy' invalid + +test_refspec push 'master~1:refs/remotes/frotz/backup' +test_refspec fetch 'master~1:refs/remotes/frotz/backup' invalid +test_refspec push 'HEAD~4:refs/remotes/frotz/new' +test_refspec fetch 'HEAD~4:refs/remotes/frotz/new' invalid + +test_refspec push 'HEAD' +test_refspec fetch 'HEAD' +test_refspec push 'refs/heads/ nitfol' invalid +test_refspec fetch 'refs/heads/ nitfol' invalid + +test_refspec push 'HEAD:' invalid +test_refspec fetch 'HEAD:' +test_refspec push 'refs/heads/ nitfol:' invalid +test_refspec fetch 'refs/heads/ nitfol:' invalid + +test_refspec push ':refs/remotes/frotz/deleteme' +test_refspec fetch ':refs/remotes/frotz/HEAD-to-me' +test_refspec push ':refs/remotes/frotz/delete me' invalid +test_refspec fetch ':refs/remotes/frotz/HEAD to me' invalid + +test_done diff --git a/t/t6009-rev-list-parent.sh b/t/t6009-rev-list-parent.sh index f248a3293c..c8a96a9a99 100755 --- a/t/t6009-rev-list-parent.sh +++ b/t/t6009-rev-list-parent.sh @@ -27,7 +27,7 @@ test_expect_success setup ' git log --pretty=oneline --abbrev-commit ' -test_expect_failure 'one is ancestor of others and should not be shown' ' +test_expect_success 'one is ancestor of others and should not be shown' ' git rev-list one --not four >result && >expect && diff --git a/t/t6031-merge-recursive.sh b/t/t6031-merge-recursive.sh index c8310aee4f..a8ce5569cb 100755 --- a/t/t6031-merge-recursive.sh +++ b/t/t6031-merge-recursive.sh @@ -3,6 +3,11 @@ test_description='merge-recursive: handle file mode' . ./test-lib.sh +if test "$(git config --bool core.filemode)" = false; then + say "executable bit not honored - skipping tests" + test_done +fi + test_expect_success 'mode change in one branch: keep changed version' ' : >file1 && git add file1 && diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 553131fcf4..6827249da5 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -78,7 +78,7 @@ test_expect_success 'filter subdirectory only' ' test_expect_success 'subdirectory filter result looks okay' ' test 2 = $(git rev-list sub | wc -l) && git show sub:new && - ! git show sub:subdir + test_must_fail git show sub:subdir ' test_expect_success 'setup and filter history that requires --full-history' ' @@ -100,7 +100,7 @@ test_expect_success 'subdirectory filter result looks okay' ' test 3 = $(git rev-list -1 --parents sub-master | wc -w) && git show sub-master^:new && git show sub-master^2:new && - ! git show sub:subdir + test_must_fail git show sub:subdir ' test_expect_success 'use index-filter to move into a subdirectory' ' @@ -114,7 +114,7 @@ test_expect_success 'use index-filter to move into a subdirectory' ' test_expect_success 'stops when msg filter fails' ' old=$(git rev-parse HEAD) && - ! git-filter-branch -f --msg-filter false HEAD && + test_must_fail git-filter-branch -f --msg-filter false HEAD && test $old = $(git rev-parse HEAD) && rm -rf .git-rewrite ' @@ -151,8 +151,8 @@ test_expect_success "remove a certain author's commits" ' ' test_expect_success 'barf on invalid name' ' - ! git filter-branch -f master xy-problem && - ! git filter-branch -f HEAD^ + test_must_fail git filter-branch -f master xy-problem && + test_must_fail git filter-branch -f HEAD^ ' test_expect_success '"map" works in commit filter' ' @@ -174,7 +174,7 @@ test_expect_success 'Name needing quotes' ' git add foo && git commit -m "Adding a file" && git filter-branch --tree-filter "rm -fr foo" && - ! git ls-files --error-unmatch "foo/$name" && + test_must_fail git ls-files --error-unmatch "foo/$name" && test $(git rev-parse --verify rerere) != $(git rev-parse --verify A) ' diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh new file mode 100755 index 0000000000..9a4eabe523 --- /dev/null +++ b/t/t9120-git-svn-clone-with-percent-escapes.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# Copyright (c) 2008 Kevin Ballard +# + +test_description='git-svn clone with percent escapes' +. ./lib-git-svn.sh + +test_expect_success 'setup svnrepo' " + mkdir project project/trunk project/branches project/tags && + echo foo > project/trunk/foo && + svn import -m '$test_description' project '$svnrepo/pr ject' && + rm -rf project && + start_httpd +" + +if test "$SVN_HTTPD_PORT" = "" +then + test_expect_failure 'test clone with percent escapes - needs SVN_HTTPD_PORT set' 'false' +else + test_expect_success 'test clone with percent escapes' ' + git svn clone "$svnrepo/pr%20ject" clone && + cd clone && + git rev-parse refs/remotes/git-svn && + cd .. + ' +fi + +stop_httpd + +test_done diff --git a/t/test-lib.sh b/t/test-lib.sh index 0815190a2f..b23f8fd847 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -396,7 +396,12 @@ fi # Test repository test=trash -rm -fr "$test" +rm -fr "$test" || { + trap - exit + echo >&5 "FATAL: Cannot prepare test area" + exit 1 +} + test_create_repo $test cd "$test" diff --git a/test-chmtime.c b/test-chmtime.c index 8a1e6b8479..90da448ebe 100644 --- a/test-chmtime.c +++ b/test-chmtime.c @@ -3,38 +3,6 @@ static const char usage_str[] = "(+|=|=+|=-|-) ..."; -#ifdef __MINGW32__ -static inline void time_t_to_filetime(time_t t, FILETIME *ft) -{ - long long winTime = t * 10000000LL + 116444736000000000LL; - ft->dwLowDateTime = winTime; - ft->dwHighDateTime = winTime >> 32; -} - -int git_utime (const char *file_name, const struct utimbuf *times) -{ - FILETIME mft, aft; - int fh, rc; - - /* must have write permission */ - if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0) - return -1; - - time_t_to_filetime(times->modtime, &mft); - time_t_to_filetime(times->actime, &aft); - if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) { - errno = EINVAL; - rc = -1; - } else - rc = 0; - close(fh); - return rc; -} - -int git_utime(const char *file_name, const struct utimbuf *times); -#define utime git_utime -#endif /* __MINGW32__ */ - int main(int argc, const char *argv[]) { int i; diff --git a/unpack-trees.c b/unpack-trees.c index 93019abdc1..a59f47557a 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -54,13 +54,14 @@ static void unlink_entry(char *name, char *last_symlink) } static struct checkout state; -static void check_updates(struct unpack_trees_options *o) +static int check_updates(struct unpack_trees_options *o) { unsigned cnt = 0, total = 0; struct progress *progress = NULL; char last_symlink[PATH_MAX]; struct index_state *index = &o->result; int i; + int errs = 0; if (o->update && o->verbose_update) { for (total = cnt = 0; cnt < index->cache_nr; cnt++) { @@ -90,12 +91,13 @@ static void check_updates(struct unpack_trees_options *o) if (ce->ce_flags & CE_UPDATE) { ce->ce_flags &= ~CE_UPDATE; if (o->update) { - checkout_entry(ce, &state, NULL); + errs |= checkout_entry(ce, &state, NULL); *last_symlink = '\0'; } } } stop_progress(&progress); + return errs != 0; } static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_options *o) @@ -369,7 +371,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options return unpack_failed(o, "Merge requires file-level merging"); o->src_index = NULL; - check_updates(o); + if (check_updates(o)) + return -1; if (o->dst_index) *o->dst_index = o->result; return 0; @@ -595,16 +598,19 @@ static int verify_absent(struct cache_entry *ce, const char *action, static int merged_entry(struct cache_entry *merge, struct cache_entry *old, struct unpack_trees_options *o) { + int update = CE_UPDATE; + if (old) { /* * See if we can re-use the old CE directly? * That way we get the uptodate stat info. * - * This also removes the UPDATE flag on - * a match. + * This also removes the UPDATE flag on a match; otherwise + * we will end up overwriting local changes in the work tree. */ if (same(old, merge)) { copy_cache_entry(merge, old); + update = 0; } else { if (verify_uptodate(old, o)) return -1; @@ -617,7 +623,7 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old, invalidate_ce_path(merge, o); } - add_entry(o, merge, CE_UPDATE, CE_STAGEMASK); + add_entry(o, merge, update, CE_STAGEMASK); return 1; }