diff options
198 files changed, 2476 insertions, 1458 deletions
@@ -5,22 +5,28 @@ # same person appearing not to be so. # +Alexander Gavrilov <angavrilov@gmail.com> Aneesh Kumar K.V <aneesh.kumar@gmail.com> Brian M. Carlson <sandals@crustytoothpaste.ath.cx> Chris Shoemaker <c.shoemaker@cox.net> Dana L. How <danahow@gmail.com> Dana L. How <how@deathvalley.cswitch.com> Daniel Barkalow <barkalow@iabervon.org> +David D. Kilzer <ddkilzer@kilzer.net> David Kågedal <davidk@lysator.liu.se> +David S. Miller <davem@davemloft.net> +Dirk Süsserott <newsletter@dirk.my1.cc> Fredrik Kuivinen <freku045@student.liu.se> H. Peter Anvin <hpa@bonde.sc.orionmulti.com> H. Peter Anvin <hpa@tazenda.sc.orionmulti.com> H. Peter Anvin <hpa@trantor.hos.anvin.org> Horst H. von Brand <vonbrand@inf.utfsm.cl> +İsmail Dönmez <ismail@pardus.org.tr> Jay Soffian <jaysoffian+git@gmail.com> Joachim Berdal Haga <cjhaga@fys.uio.no> Jon Loeliger <jdl@freescale.com> Jon Seymour <jon@blackcubes.dyndns.org> +Jonathan Nieder <jrnieder@uchicago.edu> Junio C Hamano <junio@twinsun.com> Karl Hasselström <kha@treskal.com> Kent Engstrom <kent@lysator.liu.se> @@ -30,9 +36,12 @@ Li Hong <leehong@pku.edu.cn> Lukas Sandström <lukass@etek.chalmers.se> Martin Langhoff <martin@catalyst.net.nz> Michael Coleman <tutufan@gmail.com> +Michael W. Olson <mwolson@gnu.org> Michele Ballabio <barra_cuda@katamail.com> Nanako Shiraishi <nanako3@bluebottle.com> +Nanako Shiraishi <nanako3@lavabit.com> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> +Philippe Bruhat <book@cpan.org> Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk> René Scharfe <rene.scharfe@lsrfire.ath.cx> Robert Fitzsimons <robfitz@273k.net> diff --git a/Documentation/RelNotes-1.5.6.4.txt b/Documentation/RelNotes-1.5.6.4.txt new file mode 100644 index 000000000..d8968f1ec --- /dev/null +++ b/Documentation/RelNotes-1.5.6.4.txt @@ -0,0 +1,47 @@ +GIT v1.5.6.4 Release Notes +========================== + +Fixes since v1.5.6.3 +-------------------- + +* Various commands could overflow its internal buffer on a platform + with small PATH_MAX value in a repository that has contents with + long pathnames. + +* There wasn't a way to make --pretty=format:%<> specifiers to honor + .mailmap name rewriting for authors and committers. Now you can with + %aN and %cN. + +* Bash completion wasted too many cycles; this has been optimized to be + usable again. + +* Bash completion lost ref part when completing something like "git show + pu:Makefile". + +* "git-cvsserver" did not clean up its temporary working area after annotate + request. + +* "git-daemon" called syslog() from its signal handler, which was a + no-no. + +* "git-fetch" into an empty repository used to remind that the fetch will + be huge by saying "no common commits", but this was an unnecessary + noise; it is already known by the user anyway. + +* "git-http-fetch" would have segfaulted when pack idx file retrieved + from the other side was corrupt. + +* "git-index-pack" used too much memory when dealing with a deep delta chain. + +* "git-mailinfo" (hence "git-am") did not correctly handle in-body [PATCH] + line to override the commit title taken from the mail Subject header. + +* "git-rebase -i -p" lost parents that are not involved in the history + being rewritten. + +* "git-rm" lost track of where the index file was when GIT_DIR was + specified as a relative path. + +* "git-rev-list --quiet" was not quiet as advertised. + +Contains other various documentation fixes. diff --git a/Documentation/RelNotes-1.6.0.txt b/Documentation/RelNotes-1.6.0.txt index 89ea1e938..7da62d08d 100644 --- a/Documentation/RelNotes-1.6.0.txt +++ b/Documentation/RelNotes-1.6.0.txt @@ -21,13 +21,19 @@ main git.git codebase. By default, packfiles created with this version uses delta-base-offset encoding introduced in v1.4.4. Pack idx files are using version 2 that allows larger packs and added robustness thanks to its CRC checking, -introduced in v1.5.2. +introduced in v1.5.2 and v1.4.4.5. If you want to keep your repositories +backwards compatible past these versions, set repack.useDeltaBaseOffset +to false or pack.indexVersion to 1, respectively. GIT_CONFIG, which was only documented as affecting "git config", but actually affected all git commands, now only affects "git config". GIT_LOCAL_CONFIG, also only documented as affecting "git config" and not different from GIT_CONFIG in a useful way, is removed. +The ".dotest" temporary area "git am" and "git rebase" use is now moved +inside the $GIT_DIR, to avoid mistakes of adding it to the project by +accident. + An ancient merge strategy "stupid" has been removed. @@ -67,7 +73,8 @@ Updates since v1.5.6 (performance, robustness, sanity etc.) -* even more documentation pages are now accessible via "man" and "git help". +* index-pack used too much memory when dealing with a deep delta chain. + This has been optimized. * reduced excessive inlining to shrink size of the "git" binary. @@ -79,6 +86,8 @@ Updates since v1.5.6 repack -a -f" can be used to fix such a corruption as long as necessary objects are available. +* Performance of "git-blame -C -C" operation is vastly improved. + * git-clone does not create refs in loose form anymore (it behaves as if you immediately ran git-pack-refs after cloning). This will help repositories with insanely large number of refs. @@ -92,6 +101,8 @@ Updates since v1.5.6 (usability, bells and whistles) +* even more documentation pages are now accessible via "man" and "git help". + * A new environment variable GIT_CEILING_DIRECTORIES can be used to stop the discovery process of the toplevel of working tree; this may be useful when you are working in a slow network disk and are outside any working tree, @@ -125,6 +136,9 @@ Updates since v1.5.6 * git-archive can be told to omit certain paths from its output using export-ignore attributes. +* git-archive uses the zlib default compression level when creating + zip archive. + * With -v option, git-branch describes the remote tracking statistics similar to the way git-checkout reports by how many commits your branch is ahead/behind. @@ -144,6 +158,8 @@ Updates since v1.5.6 * git-clone can clone from a remote whose URL would be rewritten by configuration stored in $HOME/.gitconfig now. +* git-cvsserver learned to respond to "cvs co -c". + * git-diff --check now checks leftover merge conflict markers. * When remote side used to have branch 'foo' and git-fetch finds that now @@ -155,6 +171,8 @@ Updates since v1.5.6 * fast-export learned to export and import marks file; this can be used to interface with fast-import incrementally. +* fast-import and fast-export learned to export and import gitlinks. + * git-rebase records the original tip of branch in ORIG_HEAD before it is rewound. @@ -188,6 +206,8 @@ Updates since v1.5.6 (internal) +* git-merge has been reimplemented in C. + Fixes since v1.5.6 ------------------ @@ -195,12 +215,8 @@ Fixes since v1.5.6 All of the fixes in v1.5.6 maintenance series are included in this release, unless otherwise noted. - * "git fetch" into an empty repository used to remind the fetch will - be huge by saying "no common commits", but it is already known by - the user anyway (need to backport 8cb560f to 'maint'). - --- exec >/var/tmp/1 -O=v1.5.6.3-350-g499027b +O=v1.5.6.4-432-g6796399 echo O=$(git describe refs/heads/master) git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 3558905a9..2b6d6c865 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p] - [--update | -u] [--refresh] [--ignore-errors] [--] + [--all | [--update | -u]] [--refresh] [--ignore-errors] [--] <filepattern>... DESCRIPTION @@ -86,6 +86,12 @@ OPTIONS command line. If no paths are specified, all tracked files in the current directory and its subdirectories are updated. +-A:: +--all:: + Update files that git already knows about (same as '\--update') + and add all untracked files that are not ignored by '.gitignore' + mechanism. + --refresh:: Don't add the file(s), but only refresh their stat() information in the index. diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index 2d7f16259..e010a1649 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -13,7 +13,7 @@ SYNOPSIS [--3way] [--interactive] [--binary] [--whitespace=<option>] [-C<n>] [-p<n>] [<mbox> | <Maildir>...] -'git am' (--skip | --resolved) +'git am' (--skip | --resolved | --abort) DESCRIPTION ----------- @@ -99,6 +99,9 @@ default. You could use `--no-utf8` to override this. or `--skip` to handle the failure. This is solely for internal use between 'git-rebase' and 'git-am'. +--abort:: + Restore the original branch and abort the patching operation. + DISCUSSION ---------- diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index a691173ba..50fb3d5d5 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -58,14 +58,14 @@ OPTIONS Usually the command automatically creates a commit with a commit log message stating which commit was cherry-picked. This flag applies the change necessary - to cherry-pick the named commit to your working tree, - but does not make the commit. In addition, when this - option is used, your working tree does not have to match + to cherry-pick the named commit to your working tree + and the index, but does not make the commit. In addition, + when this option is used, your index does not have to match the HEAD commit. The cherry-pick is done against the - beginning state of your working tree. + beginning state of your index. + This is useful when cherry-picking more than one commits' -effect to your working tree in a row. +effect to your index in a row. -s:: --signoff:: diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 2d01d0d10..c2f483a8d 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -481,6 +481,9 @@ in octal. Git only supports the following modes: what you want. * `100755` or `755`: A normal, but executable, file. * `120000`: A symlink, the content of the file will be the link target. +* `160000`: A gitlink, SHA-1 of the object refers to a commit in + another repository. Git links can only be specified by SHA or through + a commit mark. They are used to implement submodules. In both formats `<path>` is the complete path of the file to be added (if not already existing) or modified (if already existing). diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 019e4ca8f..a7487d3df 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -57,50 +57,31 @@ HOW MERGE WORKS A merge is always between the current `HEAD` and one or more commits (usually, branch head or tag), and the index file must -exactly match the -tree of `HEAD` commit (i.e. the contents of the last commit) when -it happens. In other words, `git diff --cached HEAD` must -report no changes. - -[NOTE] -This is a bit of a lie. In certain special cases, your index is -allowed to be different from the tree of the `HEAD` commit. The most -notable case is when your `HEAD` commit is already ahead of what -is being merged, in which case your index can have arbitrary -differences from your `HEAD` commit. Also, your index entries -may have differences from your `HEAD` commit that match -the result of a trivial merge (e.g. you received the same patch -from an external source to produce the same result as what you are -merging). For example, if a path did not exist in the common -ancestor and your head commit but exists in the tree you are -merging into your repository, and if you already happen to have -that path exactly in your index, the merge does not have to -fail. - -Otherwise, merge will refuse to do any harm to your repository -(that is, it may fetch the objects from remote, and it may even -update the local branch used to keep track of the remote branch -with `git pull remote rbranch:lbranch`, but your working tree, -`.git/HEAD` pointer and index file are left intact). In addition, -merge always sets `.git/ORIG_HEAD` to the original state of HEAD so -a problematic merge can be removed by using `git reset ORIG_HEAD`. - -You may have local modifications in the working tree files. In -other words, 'git-diff' is allowed to report changes. -However, the merge uses your working tree as the working area, -and in order to prevent the merge operation from losing such -changes, it makes sure that they do not interfere with the -merge. Those complex tables in read-tree documentation define -what it means for a path to "interfere with the merge". And if -your local modifications interfere with the merge, again, it -stops before touching anything. - -So in the above two "failed merge" case, you do not have to -worry about loss of data --- you simply were not ready to do -a merge, so no merge happened at all. You may want to finish -whatever you were in the middle of doing, and retry the same -pull after you are done and ready. - +match the tree of `HEAD` commit (i.e. the contents of the last commit) +when it starts out. In other words, `git diff --cached HEAD` must +report no changes. (One exception is when the changed index +entries are already in the same state that would result from +the merge anyway.) + +Three kinds of merge can happen: + +* The merged commit is already contained in `HEAD`. This is the + simplest case, called "Already up-to-date." + +* `HEAD` is already contained in the merged commit. This is the + most common case especially when involved through 'git pull': + you are tracking an upstream repository, committed no local + changes and now you want to update to a newer upstream revision. + Your `HEAD` (and the index) is updated to at point the merged + commit, without creating an extra merge commit. This is + called "Fast-forward". + +* Both the merged commit and `HEAD` are independent and must be + tied together by a merge commit that has them both as its parents. + The rest of this section describes this "True merge" case. + +The chosen merge strategy merges the two commits into a single +new source tree. When things cleanly merge, these things happen: 1. The results are updated both in the index file and in your @@ -142,12 +123,13 @@ After seeing a conflict, you can do two things: * Decide not to merge. The only clean-up you need are to reset the index file to the `HEAD` commit to reverse 2. and to clean - up working tree changes made by 2. and 3.; 'git-reset' can + up working tree changes made by 2. and 3.; 'git-reset --hard' can be used for this. * Resolve the conflicts. `git diff` would report only the - conflicting paths because of the above 2. and 3. Edit the - working tree files into a desirable shape, 'git-add' or 'git-rm' + conflicting paths because of the above 2. and 3. + Edit the working tree files into a desirable shape + ('git mergetool' can ease this task), 'git-add' or 'git-rm' them, to make the index file contain what the merge result should be, and run 'git-commit' to commit the result. diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index 5411edca9..271850f51 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -43,16 +43,16 @@ OPTIONS -n:: --no-commit:: Usually the command automatically creates a commit with - a commit log message stating which commit was reverted. - This flag applies the change necessary to revert the - named commit to your working tree, but does not make the - commit. In addition, when this option is used, your - working tree does not have to match the HEAD commit. - The revert is done against the beginning state of your - working tree. + a commit log message stating which commit was + reverted. This flag applies the change necessary + to revert the named commit to your working tree + and the index, but does not make the commit. In addition, + when this option is used, your index does not have to match + the HEAD commit. The revert is done against the + beginning state of your index. + This is useful when reverting more than one commits' -effect to your working tree in a row. +effect to your index in a row. -s:: --signoff:: diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index 76702a0a5..829b03201 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -16,6 +16,48 @@ SYNOPSIS 'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...] +DESCRIPTION +----------- +Submodules allow foreign repositories to be embedded within +a dedicated subdirectory of the source tree, always pointed +at a particular commit. + +They are not to be confused with remotes, which are meant mainly +for branches of the same project; submodules are meant for +different projects you would like to make part of your source tree, +while the history of the two projects still stays completely +independent and you cannot modify the contents of the submodule +from within the main project. +If you want to merge the project histories and want to treat the +aggregated whole as a single project from then on, you may want to +add a remote for the other project and use the 'subtree' merge strategy, +instead of treating the other project as a submodule. Directories +that come from both projects can be cloned and checked out as a whole +if you choose to go that route. + +Submodules are composed from a so-called `gitlink` tree entry +in the main repository that refers to a particular commit object +within the inner repository that is completely separate. +A record in the `.gitmodules` file at the root of the source +tree assigns a logical name to the submodule and describes +the default URL the submodule shall be cloned from. +The logical name can be used for overriding this URL within your +local repository configuration (see 'submodule init'). + +This command will manage the tree entries and contents of the +gitmodules file for you, as well as inspect the status of your +submodules and update them. +When adding a new submodule to the tree, the 'add' subcommand +is to be used. However, when pulling a tree containing submodules, +these will not be checked out by default; +the 'init' and 'update' subcommands will maintain submodules +checked out and at appropriate revision in your working tree. +You can briefly inspect the up-to-date status of your submodules +using the 'status' subcommand and get a detailed overview of the +difference between the index and checkouts using the 'summary' +subcommand. + + COMMANDS -------- add:: @@ -56,10 +98,15 @@ status:: repository. This command is the default command for 'git-submodule'. init:: - Initialize the submodules, i.e. register in .git/config each submodule - name and url found in .gitmodules. The key used in .git/config is - `submodule.$name.url`. This command does not alter existing information - in .git/config. + Initialize the submodules, i.e. register each submodule name + and url found in .gitmodules into .git/config. + The key used in .git/config is `submodule.$name.url`. + This command does not alter existing information in .git/config. + You can then customize the submodule clone URLs in .git/config + for your local setup and proceed to 'git submodule update'; + you can also just use 'git submodule update --init' without + the explicit 'init' step if you do not intend to customize + any submodule locations. update:: Update the registered submodules, i.e. clone missing submodules and diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index a91fd214d..6b930bc16 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -88,6 +88,16 @@ OPTIONS sometimes helpful when working with a big project on a filesystem that has very slow lstat(2) system call (e.g. cifs). ++ +This option can be also used as a coarse file-level mechanism +to ignore uncommitted changes in tracked files (akin to what +`.gitignore` does for untracked files). +You should remember that an explicit 'git add' operation will +still cause the file to be refreshed from the working tree. +Git will fail (gracefully) in case it needs to modify this file +in the index e.g. when merging in a commit; +thus, in case the assumed-untracked file is changed upstream, +you will need to handle the situation manually. -g:: --again:: diff --git a/Documentation/git.txt b/Documentation/git.txt index 27b9d31f7..44ea35e94 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,12 +43,13 @@ unreleased) version of git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.5.6.3/git.html[documentation for release 1.5.6.3] +* link:v1.5.6.4/git.html[documentation for release 1.5.6.4] * release notes for - link:RelNotes-1.5.6.3.txt[1.5.6.3]. - link:RelNotes-1.5.6.2.txt[1.5.6.2]. - link:RelNotes-1.5.6.1.txt[1.5.6.1]. + link:RelNotes-1.5.6.4.txt[1.5.6.4], + link:RelNotes-1.5.6.3.txt[1.5.6.3], + link:RelNotes-1.5.6.2.txt[1.5.6.2], + link:RelNotes-1.5.6.1.txt[1.5.6.1], link:RelNotes-1.5.6.txt[1.5.6]. * link:v1.5.5.4/git.html[documentation for release 1.5.5.4] diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt index fc0efd8ec..59321a2e8 100644 --- a/Documentation/gitignore.txt +++ b/Documentation/gitignore.txt @@ -13,9 +13,14 @@ DESCRIPTION ----------- A `gitignore` file specifies intentionally untracked files that -git should ignore. Each line in a `gitignore` file specifies a -pattern. - +git should ignore. +Note that all the `gitignore` files really concern only files +that are not already tracked by git; +in order to ignore uncommitted changes in already tracked files, +please refer to the 'git update-index --assume-unchanged' +documentation. + +Each line in a `gitignore` file specifies a pattern. When deciding whether to ignore a path, git normally checks `gitignore` patterns from multiple sources, with the following order of precedence, from highest to lowest (within one level of diff --git a/Documentation/technical/api-run-command.txt b/Documentation/technical/api-run-command.txt index 3e1342acf..75aa5d492 100644 --- a/Documentation/technical/api-run-command.txt +++ b/Documentation/technical/api-run-command.txt @@ -30,7 +30,7 @@ Functions start_command() followed by finish_command(). Takes a pointer to a `struct child_process` that specifies the details. -`run_command_v_opt`, `run_command_v_opt_dir`, `run_command_v_opt_cd_env`:: +`run_command_v_opt`, `run_command_v_opt_cd`, `run_command_v_opt_cd_env`:: Convenience functions that encapsulate a sequence of start_command() followed by finish_command(). The argument argv @@ -324,6 +324,7 @@ endif export PERL_PATH LIB_FILE=libgit.a +COMPAT_LIB = compat/lib.a XDIFF_LIB=xdiff/lib.a LIB_H += archive.h @@ -741,7 +742,7 @@ ifneq (,$(findstring MINGW,$(uname_S))) COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" - COMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o + COMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o compat/winansi.o EXTLIBS += -lws2_32 X = .exe template_dir = ../share/git-core/templates/ @@ -1203,6 +1204,12 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) +$(COMPAT_LIB): $(COMPAT_OBJS) + $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(COMPAT_OBJS) + +git-shell$X: abspath.o ctype.o exec_cmd.o quote.o strbuf.o usage.o wrapper.o shell.o $(COMPAT_LIB) + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(COMPAT_LIB) + $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) builtin-revert.o wt-status.o: wt-status.h @@ -1298,7 +1305,7 @@ check: common-cmds.h for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done remove-dashes: - ./fixup-builtins $(BUILT_INS) + ./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS) ### Installation rules @@ -1399,7 +1406,7 @@ distclean: clean clean: $(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \ - $(LIB_FILE) $(XDIFF_LIB) + $(LIB_FILE) $(XDIFF_LIB) $(COMPAT_LIB) $(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X $(RM) $(TEST_PROGRAMS) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope* diff --git a/archive-tar.c b/archive-tar.c index 99db58f1c..13029619e 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -2,9 +2,7 @@ * Copyright (c) 2005, 2006 Rene Scharfe */ #include "cache.h" -#include "commit.h" #include "tar.h" -#include "builtin.h" #include "archive.h" #define RECORDSIZE (512) @@ -13,11 +11,7 @@ static char block[BLOCKSIZE]; static unsigned long offset; -static time_t archive_time; static int tar_umask = 002; -static int verbose; -static const struct commit *commit; -static size_t base_len; /* writes out the whole block, but only if it is full */ static void write_if_needed(void) @@ -114,22 +108,24 @@ static unsigned int ustar_header_chksum(const struct ustar_header *header) return chksum; } -static int get_path_prefix(const struct strbuf *path, int maxlen) +static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen) { - int i = path->len; + size_t i = pathlen; if (i > maxlen) i = maxlen; do { i--; - } while (i > 0 && path->buf[i] != '/'); + } while (i > 0 && path[i] != '/'); return i; } -static void write_entry(const unsigned char *sha1, struct strbuf *path, - unsigned int mode, void *buffer, unsigned long size) +static int write_tar_entry(struct archiver_args *args, + const unsigned char *sha1, const char *path, size_t pathlen, + unsigned int mode, void *buffer, unsigned long size) { struct ustar_header header; struct strbuf ext_header; + int err = 0; memset(&header, 0, sizeof(header)); strbuf_init(&ext_header, 0); @@ -143,8 +139,6 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, mode = 0100666; sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1)); } else { - if (verbose) - fprintf(stderr, "%.*s\n", (int)path->len, path->buf); if (S_ISDIR(mode) || S_ISGITLINK(mode)) { *header.typeflag = TYPEFLAG_DIR; mode = (mode | 0777) & ~tar_umask; @@ -155,24 +149,24 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, *header.typeflag = TYPEFLAG_REG; mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask; } else { - error("unsupported file mode: 0%o (SHA1: %s)", - mode, sha1_to_hex(sha1)); - return; + return error("unsupported file mode: 0%o (SHA1: %s)", + mode, sha1_to_hex(sha1)); } - if (path->len > sizeof(header.name)) { - int plen = get_path_prefix(path, sizeof(header.prefix)); - int rest = path->len - plen - 1; + if (pathlen > sizeof(header.name)) { + size_t plen = get_path_prefix(path, pathlen, + sizeof(header.prefix)); + size_t rest = pathlen - plen - 1; if (plen > 0 && rest <= sizeof(header.name)) { - memcpy(header.prefix, path->buf, plen); - memcpy(header.name, path->buf + plen + 1, rest); + memcpy(header.prefix, path, plen); + memcpy(header.name, path + plen + 1, rest); } else { sprintf(header.name, "%s.data", sha1_to_hex(sha1)); strbuf_append_ext_header(&ext_header, "path", - path->buf, path->len); + path, pathlen); } } else - memcpy(header.name, path->buf, path->len); + memcpy(header.name, path, pathlen); } if (S_ISLNK(mode) && buffer) { @@ -187,7 +181,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, sprintf(header.mode, "%07o", mode & 07777); sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0); - sprintf(header.mtime, "%011lo", archive_time); + sprintf(header.mtime, "%011lo", args->time); sprintf(header.uid, "%07o", 0); sprintf(header.gid, "%07o", 0); @@ -202,22 +196,30 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, sprintf(header.chksum, "%07o", ustar_header_chksum(&header)); if (ext_header.len > 0) { - write_entry(sha1, NULL, 0, ext_header.buf, ext_header.len); + err = write_tar_entry(args, sha1, NULL, 0, 0, ext_header.buf, + ext_header.len); + if (err) + return err; } strbuf_release(&ext_header); write_blocked(&header, sizeof(header)); if (S_ISREG(mode) && buffer && size > 0) write_blocked(buffer, size); + return err; } -static void write_global_extended_header(const unsigned char *sha1) +static int write_global_extended_header(struct archiver_args *args) { + const unsigned char *sha1 = args->commit_sha1; struct strbuf ext_header; + int err; strbuf_init(&ext_header, 0); strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40); - write_entry(NULL, NULL, 0, ext_header.buf, ext_header.len); + err = write_tar_entry(args, NULL, NULL, 0, 0, ext_header.buf, + ext_header.len); strbuf_release(&ext_header); + return err; } static int git_tar_config(const char *var, const char *value, void *cb) @@ -234,64 +236,17 @@ static int git_tar_config(const char *var, const char *value, void *cb) return git_default_config(var, value, cb); } -static int write_tar_entry(const unsigned char *sha1, - const char *base, int baselen, - const char *filename, unsigned mode, int stage) -{ - static struct strbuf path = STRBUF_INIT; - void *buffer; - enum object_type type; - unsigned long size; - - strbuf_reset(&path); - strbuf_grow(&path, PATH_MAX); - strbuf_add(&path, base, baselen); - strbuf_addstr(&path, filename); - if (is_archive_path_ignored(path.buf + base_len)) - return 0; - if (S_ISDIR(mode) || S_ISGITLINK(mode)) { - strbuf_addch(&path, '/'); - buffer = NULL; - size = 0; - } else { - buffer = sha1_file_to_archive(path.buf + base_len, sha1, mode, - &type, &size, commit); - if (!buffer) - die("cannot read %s", sha1_to_hex(sha1)); - } - - write_entry(sha1, &path, mode, buffer, size); - free(buffer); - - return READ_TREE_RECURSIVE; -} - int write_tar_archive(struct archiver_args *args) { - int plen = args->base ? strlen(args->base) : 0; + int err = 0; git_config(git_tar_config, NULL); - archive_time = args->time; - verbose = args->verbose; - commit = args->commit; - base_len = args->base ? strlen(args->base) : 0; - if (args->commit_sha1) - write_global_extended_header(args->commit_sha1); - - if (args->base && plen > 0 && args->base[plen - 1] == '/') { - char *base = xstrdup(args->base); - int baselen = strlen(base); - - while (baselen > 0 && base[baselen - 1] == '/') - base[--baselen] = '\0'; - write_tar_entry(args->tree->object.sha1, "", 0, base, 040777, 0); - free(base); - } - read_tree_recursive(args->tree, args->base, plen, 0, - args->pathspec, write_tar_entry); - write_trailer(); - - return 0; + err = write_global_extended_header(args); + if (!err) + err = write_archive_entries(args, write_tar_entry); + if (!err) + write_trailer(); + return err; } diff --git a/archive-zip.c b/archive-zip.c index 5742762ac..cf285044e 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -2,18 +2,10 @@ * Copyright (c) 2006 Rene Scharfe */ #include "cache.h" -#include "commit.h" -#include "blob.h" -#include "tree.h" -#include "quote.h" -#include "builtin.h" #include "archive.h" -static int verbose; static int zip_date; static int zip_time; -static const struct commit *commit; -static size_t base_len; static unsigned char *zip_dir; static unsigned int zip_dir_size; @@ -96,7 +88,7 @@ static void copy_le32(unsigned char *dest, unsigned int n) } static void *zlib_deflate(void *data, unsigned long size, - unsigned long *compressed_size) + int compression_level, unsigned long *compressed_size) { z_stream stream; unsigned long maxsize; @@ -104,7 +96,7 @@ static void *zlib_deflate(void *data, unsigned long size, int result; memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, zlib_compression_level); + deflateInit(&stream, compression_level); maxsize = deflateBound(&stream, size); buffer = xmalloc(maxsize); @@ -128,33 +120,9 @@ static void *zlib_deflate(void *data, unsigned long size, return buffer; } -static char *construct_path(const char *base, int baselen, - const char *filename, int isdir, int *pathlen) -{ - int filenamelen = strlen(filename); - int len = baselen + filenamelen; - char *path, *p; - - if (isdir) - len++; - p = path = xmalloc(len + 1); - - memcpy(p, base, baselen); - p += baselen; - memcpy(p, filename, filenamelen); - p += filenamelen; - if (isdir) - *p++ = '/'; - *p = '\0'; - - *pathlen = len; - - return path; -} - -static int write_zip_entry(const unsigned char *sha1, - const char *base, int baselen, - const char *filename, unsigned mode, int stage) +static int write_zip_entry(struct archiver_args *args, + const unsigned char *sha1, const char *path, size_t pathlen, + unsigned int mode, void *buffer, unsigned long size) { struct zip_local_header header; struct zip_dir_header dirent; @@ -163,33 +131,20 @@ static int write_zip_entry(const unsigned char *sha1, unsigned long uncompressed_size; unsigned long crc; unsigned long direntsize; - unsigned long size; int method; - int result = -1; - int pathlen; unsigned char *out; - char *path; - enum object_type type; - void *buffer = NULL; void *deflated = NULL; crc = crc32(0, NULL, 0); - path = construct_path(base, baselen, filename, S_ISDIR(mode), &pathlen); - if (is_archive_path_ignored(path + base_len)) - return 0; - if (verbose) - fprintf(stderr, "%s\n", path); if (pathlen > 0xffff) { - error("path too long (%d chars, SHA1: %s): %s", pathlen, - sha1_to_hex(sha1), path); - goto out; + return error("path too long (%d chars, SHA1: %s): %s", + (int)pathlen, sha1_to_hex(sha1), path); } if (S_ISDIR(mode) || S_ISGITLINK(mode)) { method = 0; attr2 = 16; - result = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0); out = NULL; uncompressed_size = 0; compressed_size = 0; @@ -197,25 +152,20 @@ static int write_zip_entry(const unsigned char *sha1, method = 0; attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) : (mode & 0111) ? ((mode) << 16) : 0; - if (S_ISREG(mode) && zlib_compression_level != 0) + if (S_ISREG(mode) && args->compression_level != 0) method = 8; - result = 0; - buffer = sha1_file_to_archive(path + base_len, sha1, mode, - &type, &size, commit); - if (!buffer) - die("cannot read %s", sha1_to_hex(sha1)); crc = crc32(crc, buffer, size); out = buffer; uncompressed_size = size; compressed_size = size; } else { - error("unsupported file mode: 0%o (SHA1: %s)", mode, - sha1_to_hex(sha1)); - goto out; + return error("unsupported file mode: 0%o (SHA1: %s)", mode, + sha1_to_hex(sha1)); } if (method == 8) { - deflated = zlib_deflate(buffer, size, &compressed_size); + deflated = zlib_deflate(buffer, size, args->compression_level, + &compressed_size); if (deflated && compressed_size - 6 < size) { /* ZLIB --> raw compressed data (see RFC 1950) */ /* CMF and FLG ... */ @@ -278,12 +228,9 @@ static int write_zip_entry(const unsigned char *sha1, zip_offset += compressed_size; } -out: - free(buffer); free(deflated); - free(path); - return result; + return 0; } static void write_zip_trailer(const unsigned char *sha1) @@ -316,43 +263,18 @@ static void dos_time(time_t *time, int *dos_date, int *dos_time) int write_zip_archive(struct archiver_args *args) { - int plen = strlen(args->base); + int err; dos_time(&args->time, &zip_date, &zip_time); zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE); zip_dir_size = ZIP_DIRECTORY_MIN_SIZE; - verbose = args->verbose; - commit = args->commit; - base_len = args->base ? strlen(args->base) : 0; - - if (args->base && plen > 0 && args->base[plen - 1] == '/') { - char *base = xstrdup(args->base); - int baselen = strlen(base); - - while (baselen > 0 && base[baselen - 1] == '/') - base[--baselen] = '\0'; - write_zip_entry(args->tree->object.sha1, "", 0, base, 040777, 0); - free(base); - } - read_tree_recursive(args->tree, args->base, plen, 0, - args->pathspec, write_zip_entry); - write_zip_trailer(args->commit_sha1); - - free(zip_dir); - return 0; -} + err = write_archive_entries(args, write_zip_entry); + if (!err) + write_zip_trailer(args->commit_sha1); -void *parse_extra_zip_args(int argc, const char **argv) -{ - for (; argc > 0; argc--, argv++) { - const char *arg = argv[0]; + free(zip_dir); - if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0') - zlib_compression_level = arg[1] - '0'; - else - die("Unknown argument for zip format: %s", arg); - } - return NULL; + return err; } @@ -1,6 +1,7 @@ #include "cache.h" #include "commit.h" #include "attr.h" +#include "archive.h" static void format_subst(const struct commit *commit, const char *src, size_t len, @@ -35,34 +36,9 @@ static void format_subst(const struct commit *commit, free(to_free); } -static int convert_to_archive(const char *path, - const void *src, size_t len, - struct strbuf *buf, - const struct commit *commit) -{ - static struct git_attr *attr_export_subst; - struct git_attr_check check[1]; - - if (!commit) - return 0; - - if (!attr_export_subst) - attr_export_subst = git_attr("export-subst", 12); - - check[0].attr = attr_export_subst; - if (git_checkattr(path, ARRAY_SIZE(check), check)) - return 0; - if (!ATTR_TRUE(check[0].value)) - return 0; - - format_subst(commit, src, len, buf); - return 1; -} - -void *sha1_file_to_archive(const char *path, const unsigned char *sha1, - unsigned int mode, enum object_type *type, - unsigned long *sizep, - const struct commit *commit) +static void *sha1_file_to_archive(const char *path, const unsigned char *sha1, + unsigned int mode, enum object_type *type, + unsigned long *sizep, const struct commit *commit) { void *buffer; @@ -74,7 +50,8 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1, strbuf_init(&buf, 0); strbuf_attach(&buf, buffer, *sizep, *sizep + 1); convert_to_working_tree(path, buf.buf, buf.len, &buf); - convert_to_archive(path, buf.buf, buf.len, &buf, commit); + if (commit) + format_subst(commit, buf.buf, buf.len, &buf); buffer = strbuf_detach(&buf, &size); *sizep = size; } @@ -82,16 +59,99 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1, return buffer; } -int is_archive_path_ignored(const char *path) +static void setup_archive_check(struct git_attr_check *check) { static struct git_attr *attr_export_ignore; - struct git_attr_check check[1]; + static struct git_attr *attr_export_subst; - if (!attr_export_ignore) + if (!attr_export_ignore) { attr_export_ignore = git_attr("export-ignore", 13); - + attr_export_subst = git_attr("export-subst", 12); + } check[0].attr = attr_export_ignore; - if (git_checkattr(path, ARRAY_SIZE(check), check)) - return 0; - return ATTR_TRUE(check[0].value); + check[1].attr = attr_export_subst; +} + +struct archiver_context { + struct archiver_args *args; + write_archive_entry_fn_t write_entry; +}; + +static int write_archive_entry(const unsigned char *sha1, const char *base, + int baselen, const char *filename, unsigned mode, int stage, + void *context) +{ + static struct strbuf path = STRBUF_INIT; + struct archiver_context *c = context; + struct archiver_args *args = c->args; + write_archive_entry_fn_t write_entry = c->write_entry; + struct git_attr_check check[2]; + const char *path_without_prefix; + int convert = 0; + int err; + enum object_type type; + unsigned long size; + void *buffer; + + strbuf_reset(&path); + strbuf_grow(&path, PATH_MAX); + strbuf_add(&path, base, baselen); + strbuf_addstr(&path, filename); + path_without_prefix = path.buf + args->baselen; + + setup_archive_check(check); + if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) { + if (ATTR_TRUE(check[0].value)) + return 0; + convert = ATTR_TRUE(check[1].value); + } + + if (S_ISDIR(mode) || S_ISGITLINK(mode)) { + strbuf_addch(&path, '/'); + if (args->verbose) + fprintf(stderr, "%.*s\n", (int)path.len, path.buf); + err = write_entry(args, sha1, path.buf, path.len, mode, NULL, 0); + if (err) + return err; + return READ_TREE_RECURSIVE; + } + + buffer = sha1_file_to_archive(path_without_prefix, sha1, mode, + &type, &size, convert ? args->commit : NULL); + if (!buffer) + return error("cannot read %s", sha1_to_hex(sha1)); + if (args->verbose) + fprintf(stderr, "%.*s\n", (int)path.len, path.buf); + err = write_entry(args, sha1, path.buf, path.len, mode, buffer, size); + free(buffer); + return err; +} + +int write_archive_entries(struct archiver_args *args, + write_archive_entry_fn_t write_entry) +{ + struct archiver_context context; + int err; + + if (args->baselen > 0 && args->base[args->baselen - 1] == '/') { + size_t len = args->baselen; + + while (len > 1 && args->base[len - 2] == '/') + len--; + if (args->verbose) + fprintf(stderr, "%.*s\n", (int)len, args->base); + err = write_entry(args, args->tree->object.sha1, args->base, + len, 040777, NULL, 0); + if (err) + return err; + } + + context.args = args; + context.write_entry = write_entry; + + err = read_tree_recursive(args->tree, args->base, args->baselen, 0, + args->pathspec, write_archive_entry, &context); + if (err == READ_TREE_RECURSIVE) + err = 0; + return err; } @@ -6,29 +6,27 @@ struct archiver_args { const char *base; + size_t baselen; struct tree *tree; const unsigned char *commit_sha1; const struct commit *commit; time_t time; const char **pathspec; unsigned int verbose : 1; - void *extra; + int compression_level; }; typedef int (*write_archive_fn_t)(struct archiver_args *); -typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv); +typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, void *buffer, unsigned long size); struct archiver { const char *name; - struct archiver_args args; write_archive_fn_t write_archive; - parse_extra_args_fn_t parse_extra; + unsigned int flags; }; -extern int parse_archive_args(int argc, - const char **argv, - struct archiver *ar); +extern int parse_archive_args(int argc, const char **argv, const struct archiver **ar, struct archiver_args *args); extern void parse_treeish_arg(const char **treeish, struct archiver_args *ar_args, @@ -41,9 +39,7 @@ extern void parse_pathspec_arg(const char **pathspec, */ extern int write_tar_archive(struct archiver_args *); extern int write_zip_archive(struct archiver_args *); -extern void *parse_extra_zip_args(int argc, const char **argv); -extern void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size, const struct commit *commit); -extern int is_archive_path_ignored(const char *path); +extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry); #endif /* ARCHIVE_H */ @@ -459,7 +459,9 @@ static void prepare_attr_stack(const char *path, int dirlen) { struct attr_stack *elem, *info; int len; - char pathbuf[PATH_MAX]; + struct strbuf pathbuf; + + strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE)); /* * At the bottom of the attribute stack is the built-in @@ -510,13 +512,14 @@ static void prepare_attr_stack(const char *path, int dirlen) len = strlen(attr_stack->origin); if (dirlen <= len) break; - memcpy(pathbuf, path, dirlen); - memcpy(pathbuf + dirlen, "/", 2); - cp = strchr(pathbuf + len + 1, '/'); + strbuf_reset(&pathbuf); + strbuf_add(&pathbuf, path, dirlen); + strbuf_addch(&pathbuf, '/'); + cp = strchr(pathbuf.buf + len + 1, '/'); strcpy(cp + 1, GITATTRIBUTES_FILE); - elem = read_attr(pathbuf, 0); + elem = read_attr(pathbuf.buf, 0); *cp = '\0'; - elem->origin = strdup(pathbuf); + elem->origin = strdup(pathbuf.buf); elem->prev = attr_stack; attr_stack = elem; debug_push(elem); diff --git a/builtin-add.c b/builtin-add.c index 9930cf53f..fc3f96eae 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -16,7 +16,7 @@ #include "parse-options.h" static const char * const builtin_add_usage[] = { - "git-add [options] [--] <filepattern>...", + "git add [options] [--] <filepattern>...", NULL }; static int patch_interactive = 0, add_interactive = 0; @@ -140,9 +140,8 @@ static void refresh(int verbose, const char **pathspec) for (specs = 0; pathspec[specs]; specs++) /* nothing */; seen = xcalloc(specs, 1); - if (read_cache() < 0) - die("index file corrupt"); - refresh_index(&the_index, verbose ? 0 : REFRESH_QUIET, pathspec, seen); + refresh_index(&the_index, verbose ? REFRESH_SAY_CHANGED : REFRESH_QUIET, + pathspec, seen); for (i = 0; i < specs; i++) { if (!seen[i]) die("pathspec '%s' did not match any files", pathspec[i]); @@ -192,7 +191,7 @@ static const char ignore_error[] = "The following paths are ignored by one of your .gitignore files:\n"; static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0; -static int ignore_add_errors; +static int ignore_add_errors, addremove; static struct option builtin_add_options[] = { OPT__DRY_RUN(&show_only), @@ -202,6 +201,7 @@ static struct option builtin_add_options[] = { OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"), OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"), OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"), + OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"), OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"), OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"), OPT_END(), @@ -216,13 +216,36 @@ static int add_config(const char *var, const char *value, void *cb) return git_default_config(var, value, cb); } +static int add_files(struct dir_struct *dir, int flags) +{ + int i, exit_status = 0; + + if (dir->ignored_nr) { + fprintf(stderr, ignore_error); + for (i = 0; i < dir->ignored_nr; i++) + fprintf(stderr, "%s\n", dir->ignored[i]->name); + fprintf(stderr, "Use -f if you really want to add them.\n"); + die("no files added"); + } + + for (i = 0; i < dir->nr; i++) + if (add_file_to_cache(dir->entries[i]->name, flags)) { + if (!ignore_add_errors) + die("adding files failed"); + exit_status = 1; + } + return exit_status; +} + int cmd_add(int argc, const char **argv, const char *prefix) { int exit_status = 0; - int i, newfd; + int newfd; const char **pathspec; struct dir_struct dir; int flags; + int add_new_files; + int require_pathspec; argc = parse_options(argc, argv, builtin_add_options, builtin_add_usage, 0); @@ -233,53 +256,51 @@ int cmd_add(int argc, const char **argv, const char *prefix) git_config(add_config, NULL); + if (addremove && take_worktree_changes) + die("-A and -u are mutually incompatible"); + if (addremove && !argc) { + static const char *here[2] = { ".", NULL }; + argc = 1; + argv = here; + } + + add_new_files = !take_worktree_changes && !refresh_only; + require_pathspec = !take_worktree_changes; + newfd = hold_locked_index(&lock_file, 1); flags = ((verbose ? ADD_CACHE_VERBOSE : 0) | (show_only ? ADD_CACHE_PRETEND : 0) | (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0)); - if (take_worktree_changes) { - const char **pathspec; - if (read_cache() < 0) - die("index file corrupt"); - pathspec = get_pathspec(prefix, argv); - exit_status = add_files_to_cache(prefix, pathspec, flags); - goto finish; - } - - if (argc == 0) { + if (require_pathspec && argc == 0) { fprintf(stderr, "Nothing specified, nothing added.\n"); fprintf(stderr, "Maybe you wanted to say 'git add .'?\n"); return 0; } pathspec = get_pathspec(prefix, argv); - if (refresh_only) { - refresh(verbose, pathspec); - goto finish; - } - - fill_directory(&dir, pathspec, ignored_too); + /* + * If we are adding new files, we need to scan the working + * tree to find the ones that match pathspecs; this needs + * to be done before we read the index. + */ + if (add_new_files) + fill_directory(&dir, pathspec, ignored_too); if (read_cache() < 0) die("index file corrupt"); - if (dir.ignored_nr) { - fprintf(stderr, ignore_error); - for (i = 0; i < dir.ignored_nr; i++) { - fprintf(stderr, "%s\n", dir.ignored[i]->name); - } - fprintf(stderr, "Use -f if you really want to add them.\n"); - die("no files added"); + if (refresh_only) { + refresh(verbose, pathspec); + goto finish; } - for (i = 0; i < dir.nr; i++) - if (add_file_to_cache(dir.entries[i]->name, flags)) { - if (!ignore_add_errors) - die("adding files failed"); - exit_status = 1; - } + if (take_worktree_changes || addremove) + exit_status |= add_files_to_cache(prefix, pathspec, flags); + + if (add_new_files) + exit_status |= add_files(&dir, flags); finish: if (active_cache_changed) { diff --git a/builtin-apply.c b/builtin-apply.c index d13313f10..e15471b5b 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -46,7 +46,7 @@ static const char *fake_ancestor; static int line_termination = '\n'; static unsigned long p_context = ULONG_MAX; static const char apply_usage[] = -"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>..."; +"git apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>..."; static enum ws_error_action { nowarn_ws_error, diff --git a/builtin-archive.c b/builtin-archive.c index c2e0c1ea5..df9772469 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -7,22 +7,17 @@ #include "archive.h" #include "commit.h" #include "tree-walk.h" -#include "exec_cmd.h" #include "pkt-line.h" #include "sideband.h" -#include "attr.h" static const char archive_usage[] = \ -"git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]"; +"git archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]"; -static struct archiver_desc -{ - const char *name; - write_archive_fn_t write_archive; - parse_extra_args_fn_t parse_extra; -} archivers[] = { - { "tar", write_tar_archive, NULL }, - { "zip", write_zip_archive, parse_extra_zip_args }, +#define USES_ZLIB_COMPRESSION 1 + +const struct archiver archivers[] = { + { "tar", write_tar_archive }, + { "zip", write_zip_archive, USES_ZLIB_COMPRESSION }, }; static int run_remote_archiver(const char *remote, int argc, @@ -79,21 +74,15 @@ static int run_remote_archiver(const char *remote, int argc, return !!rv; } -static int init_archiver(const char *name, struct archiver *ar) +static const struct archiver *lookup_archiver(const char *name) { - int rv = -1, i; + int i; for (i = 0; i < ARRAY_SIZE(archivers); i++) { - if (!strcmp(name, archivers[i].name)) { - memset(ar, 0, sizeof(*ar)); - ar->name = archivers[i].name; - ar->write_archive = archivers[i].write_archive; - ar->parse_extra = archivers[i].parse_extra; - rv = 0; - break; - } + if (!strcmp(name, archivers[i].name)) + return &archivers[i]; } - return rv; + return NULL; } void parse_pathspec_arg(const char **pathspec, struct archiver_args *ar_args) @@ -145,12 +134,12 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args, ar_args->time = archive_time; } -int parse_archive_args(int argc, const char **argv, struct archiver *ar) +int parse_archive_args(int argc, const char **argv, const struct archiver **ar, + struct archiver_args *args) { - const char *extra_argv[MAX_EXTRA_ARGS]; - int extra_argc = 0; const char *format = "tar"; const char *base = ""; + int compression_level = -1; int verbose = 0; int i; @@ -178,29 +167,34 @@ int parse_archive_args(int argc, const char **argv, struct archiver *ar) i++; break; } - if (arg[0] == '-') { - if (extra_argc > MAX_EXTRA_ARGS - 1) - die("Too many extra options"); - extra_argv[extra_argc++] = arg; + if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0') { + compression_level = arg[1] - '0'; continue; } + if (arg[0] == '-') + die("Unknown argument: %s", arg); break; } /* We need at least one parameter -- tree-ish */ if (argc - 1 < i) usage(archive_usage); - if (init_archiver(format, ar) < 0) + *ar = lookup_archiver(format); + if (!*ar) die("Unknown archive format '%s'", format); - if (extra_argc) { - if (!ar->parse_extra) - die("'%s' format does not handle %s", - ar->name, extra_argv[0]); - ar->args.extra = ar->parse_extra(extra_argc, extra_argv); + args->compression_level = Z_DEFAULT_COMPRESSION; + if (compression_level != -1) { + if ((*ar)->flags & USES_ZLIB_COMPRESSION) + args->compression_level = compression_level; + else { + die("Argument not supported for format '%s': -%d", + format, compression_level); + } } - ar->args.verbose = verbose; - ar->args.base = base; + args->verbose = verbose; + args->base = base; + args->baselen = strlen(base); return i; } @@ -238,7 +232,8 @@ static const char *extract_remote_arg(int *ac, const char **av) int cmd_archive(int argc, const char **argv, const char *prefix) { - struct archiver ar; + const struct archiver *ar = NULL; + struct archiver_args args; int tree_idx; const char *remote = NULL; @@ -248,14 +243,13 @@ int cmd_archive(int argc, const char **argv, const char *prefix) setvbuf(stderr, NULL, _IOLBF, BUFSIZ); - memset(&ar, 0, sizeof(ar)); - tree_idx = parse_archive_args(argc, argv, &ar); + tree_idx = parse_archive_args(argc, argv, &ar, &args); if (prefix == NULL) prefix = setup_git_directory(); argv += tree_idx; - parse_treeish_arg(argv, &ar.args, prefix); - parse_pathspec_arg(argv + 1, &ar.args); + parse_treeish_arg(argv, &args, prefix); + parse_pathspec_arg(argv + 1, &args); - return ar.write_archive(&ar.args); + return ar->write_archive(&args); } diff --git a/builtin-blame.c b/builtin-blame.c index 06c7de429..9bced3b26 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -20,7 +20,7 @@ #include "mailmap.h" #include "parse-options.h" -static char blame_usage[] = "git-blame [options] [rev-opts] [rev] [--] file"; +static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file"; static const char *blame_opt_usage[] = { blame_usage, @@ -153,6 +153,10 @@ struct blame_entry { */ char guilty; + /* true if the entry has been scanned for copies in the current parent + */ + char scanned; + /* the line number of the first line of this group in the * suspect's file; internally all line numbers are 0 based. */ @@ -1008,7 +1012,8 @@ static int find_move_in_parent(struct scoreboard *sb, while (made_progress) { made_progress = 0; for (e = sb->ent; e; e = e->next) { - if (e->guilty || !same_suspect(e->suspect, target)) + if (e->guilty || !same_suspect(e->suspect, target) || + ent_score(sb, e) < blame_move_score) continue; find_copy_in_blob(sb, e, parent, split, &file_p); if (split[1].suspect && @@ -1033,6 +1038,7 @@ struct blame_list { */ static struct blame_list *setup_blame_list(struct scoreboard *sb, struct origin *target, + int min_score, int *num_ents_p) { struct blame_entry *e; @@ -1040,12 +1046,16 @@ static struct blame_list *setup_blame_list(struct scoreboard *sb, struct blame_list *blame_list = NULL; for (e = sb->ent, num_ents = 0; e; e = e->next) - if (!e->guilty && same_suspect(e->suspect, target)) + if (!e->scanned && !e->guilty && + same_suspect(e->suspect, target) && + min_score < ent_score(sb, e)) num_ents++; if (num_ents) { blame_list = xcalloc(num_ents, sizeof(struct blame_list)); for (e = sb->ent, i = 0; e; e = e->next) - if (!e->guilty && same_suspect(e->suspect, target)) + if (!e->scanned && !e->guilty && + same_suspect(e->suspect, target) && + min_score < ent_score(sb, e)) blame_list[i++].ent = e; } *num_ents_p = num_ents; @@ -1053,6 +1063,16 @@ static struct blame_list *setup_blame_list(struct scoreboard *sb, } /* + * Reset the scanned status on all entries. + */ +static void reset_scanned_flag(struct scoreboard *sb) +{ + struct blame_entry *e; + for (e = sb->ent; e; e = e->next) + e->scanned = 0; +} + +/* * For lines target is suspected for, see if we can find code movement * across file boundary from the parent commit. porigin is the path * in the parent we already tried. @@ -1070,7 +1090,7 @@ static int find_copy_in_parent(struct scoreboard *sb, struct blame_list *blame_list; int num_ents; - blame_list = setup_blame_list(sb, target, &num_ents); + blame_list = setup_blame_list(sb, target, blame_copy_score, &num_ents); if (!blame_list) return 1; /* nothing remains for this target */ @@ -1144,18 +1164,21 @@ static int find_copy_in_parent(struct scoreboard *sb, split_blame(sb, split, blame_list[j].ent); made_progress = 1; } + else + blame_list[j].ent->scanned = 1; decref_split(split); } free(blame_list); if (!made_progress) break; - blame_list = setup_blame_list(sb, target, &num_ents); + blame_list = setup_blame_list(sb, target, blame_copy_score, &num_ents); if (!blame_list) { retval = 1; break; } } + reset_scanned_flag(sb); diff_flush(&diff_opts); diff_tree_release_paths(&diff_opts); return retval; diff --git a/builtin-branch.c b/builtin-branch.c index 7dae22c01..b885bd132 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -15,10 +15,10 @@ #include "branch.h" static const char * const builtin_branch_usage[] = { - "git-branch [options] [-r | -a] [--merged | --no-merged]", - "git-branch [options] [-l] [-f] <branchname> [<start-point>]", - "git-branch [options] [-r] (-d | -D) <branchname>", - "git-branch [options] (-m | -M) [<oldbranch>] <newbranch>", + "git branch [options] [-r | -a] [--merged | --no-merged]", + "git branch [options] [-l] [-f] <branchname> [<start-point>]", + "git branch [options] [-r] (-d | -D) <branchname>", + "git branch [options] (-m | -M) [<oldbranch>] <newbranch>", NULL }; diff --git a/builtin-cat-file.c b/builtin-cat-file.c index 880e75af5..7441a56ac 100644 --- a/builtin-cat-file.c +++ b/builtin-cat-file.c @@ -202,8 +202,8 @@ static int batch_objects(int print_contents) } static const char * const cat_file_usage[] = { - "git-cat-file [-t|-s|-e|-p|<type>] <sha1>", - "git-cat-file [--batch|--batch-check] < <list_of_sha1s>", + "git cat-file [-t|-s|-e|-p|<type>] <sha1>", + "git cat-file [--batch|--batch-check] < <list_of_sha1s>", NULL }; diff --git a/builtin-check-attr.c b/builtin-check-attr.c index 6afdfa10a..cb783fc77 100644 --- a/builtin-check-attr.c +++ b/builtin-check-attr.c @@ -4,7 +4,7 @@ #include "quote.h" static const char check_attr_usage[] = -"git-check-attr attr... [--] pathname..."; +"git check-attr attr... [--] pathname..."; int cmd_check_attr(int argc, const char **argv, const char *prefix) { diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c index eb1fc9aa6..71ebabf99 100644 --- a/builtin-checkout-index.c +++ b/builtin-checkout-index.c @@ -154,7 +154,7 @@ static void checkout_all(const char *prefix, int prefix_length) } static const char checkout_cache_usage[] = -"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>..."; +"git checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>..."; static struct lock_file lock_file; diff --git a/builtin-checkout.c b/builtin-checkout.c index d6641c2c5..fbd5105a8 100644 --- a/builtin-checkout.c +++ b/builtin-checkout.c @@ -43,7 +43,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new, } static int update_some(const unsigned char *sha1, const char *base, int baselen, - const char *pathname, unsigned mode, int stage) + const char *pathname, unsigned mode, int stage, void *context) { int len; struct cache_entry *ce; @@ -67,7 +67,7 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen, static int read_tree_some(struct tree *tree, const char **pathspec) { - read_tree_recursive(tree, "", 0, 0, pathspec, update_some); + read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL); /* update the index with the given tree's info * for all args, expanding wildcards, and exit diff --git a/builtin-clean.c b/builtin-clean.c index 80a7ff9ae..48bf29f40 100644 --- a/builtin-clean.c +++ b/builtin-clean.c @@ -15,7 +15,7 @@ static int force = -1; /* unset */ static const char *const builtin_clean_usage[] = { - "git-clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...", + "git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...", NULL }; diff --git a/builtin-clone.c b/builtin-clone.c index ec3620960..352224591 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -29,7 +29,7 @@ * */ static const char * const builtin_clone_usage[] = { - "git-clone [options] [--] <repo> [<dir>]", + "git clone [options] [--] <repo> [<dir>]", NULL }; @@ -95,35 +95,38 @@ static char *get_repo_path(const char *repo, int *is_bundle) static char *guess_dir_name(const char *repo, int is_bundle) { - const char *p, *start, *end, *limit; - int after_slash_or_colon; - - /* Guess dir name from repository: strip trailing '/', - * strip trailing '[:/]*.{git,bundle}', strip leading '.*[/:]'. */ - - after_slash_or_colon = 1; - limit = repo + strlen(repo); - start = repo; - end = limit; - for (p = repo; p < limit; p++) { - const char *prefix = is_bundle ? ".bundle" : ".git"; - if (!prefixcmp(p, prefix)) { - if (!after_slash_or_colon) - end = p; - p += strlen(prefix) - 1; - } else if (!prefixcmp(p, ".bundle")) { - if (!after_slash_or_colon) - end = p; - p += 7; - } else if (*p == '/' || *p == ':') { - if (end == limit) - end = p; - after_slash_or_colon = 1; - } else if (after_slash_or_colon) { - start = p; - end = limit; - after_slash_or_colon = 0; - } + const char *end = repo + strlen(repo), *start; + + /* + * Strip trailing slashes and /.git + */ + while (repo < end && is_dir_sep(end[-1])) + end--; + if (end - repo > 5 && is_dir_sep(end[-5]) && + !strncmp(end - 4, ".git", 4)) { + end -= 5; + while (repo < end && is_dir_sep(end[-1])) + end--; + } + + /* + * Find last component, but be prepared that repo could have + * the form "remote.example.com:foo.git", i.e. no slash + * in the directory part. + */ + start = end; + while (repo < start && !is_dir_sep(start[-1]) && start[-1] != ':') + start--; + + /* + * Strip .{bundle,git}. + */ + if (is_bundle) { + if (end - start > 7 && !strncmp(end - 7, ".bundle", 7)) + end -= 7; + } else { + if (end - start > 4 && !strncmp(end - 4, ".git", 4)) + end -= 4; } return xstrndup(start, end - start); diff --git a/builtin-commit.c b/builtin-commit.c index bdc83df55..ed3fe3f7e 100644 --- a/builtin-commit.c +++ b/builtin-commit.c @@ -26,12 +26,12 @@ #include "unpack-trees.h" static const char * const builtin_commit_usage[] = { - "git-commit [options] [--] <filepattern>...", + "git commit [options] [--] <filepattern>...", NULL }; static const char * const builtin_status_usage[] = { - "git-status [options] [--] <filepattern>...", + "git status [options] [--] <filepattern>...", NULL }; diff --git a/builtin-config.c b/builtin-config.c index 39f63d7b1..0cf191a11 100644 --- a/builtin-config.c +++ b/builtin-config.c @@ -3,7 +3,7 @@ #include "color.h" static const char git_config_set_usage[] = -"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]"; +"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]"; static char *key; static regex_t *key_regexp; diff --git a/builtin-count-objects.c b/builtin-count-objects.c index f00306fb6..91b548747 100644 --- a/builtin-count-objects.c +++ b/builtin-count-objects.c @@ -67,7 +67,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose, } static char const * const count_objects_usage[] = { - "git-count-objects [-v]", + "git count-objects [-v]", NULL }; diff --git a/builtin-describe.c b/builtin-describe.c index e515f9ca9..ec404c839 100644 --- a/builtin-describe.c +++ b/builtin-describe.c @@ -10,7 +10,7 @@ #define MAX_TAGS (FLAG_BITS - 1) static const char * const describe_usage[] = { - "git-describe [options] <committish>*", + "git describe [options] <committish>*", NULL }; @@ -20,7 +20,7 @@ static int tags; /* But allow any tags if --tags is specified */ static int longformat; static int abbrev = DEFAULT_ABBREV; static int max_candidates = 10; -const char *pattern = NULL; +static const char *pattern; static int always; struct commit_name { diff --git a/builtin-diff-files.c b/builtin-diff-files.c index 384d87126..9bf10bb37 100644 --- a/builtin-diff-files.c +++ b/builtin-diff-files.c @@ -10,7 +10,7 @@ #include "builtin.h" static const char diff_files_usage[] = -"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]" +"git diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]" COMMON_DIFF_OPTIONS_HELP; int cmd_diff_files(int argc, const char **argv, const char *prefix) diff --git a/builtin-diff-index.c b/builtin-diff-index.c index 2f44ebfcd..17d851b29 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -5,7 +5,7 @@ #include "builtin.h" static const char diff_cache_usage[] = -"git-diff-index [-m] [--cached] " +"git diff-index [-m] [--cached] " "[<common diff options>] <tree-ish> [<path>...]" COMMON_DIFF_OPTIONS_HELP; diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index 9d2a48fd6..415cb1612 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -53,7 +53,7 @@ static int diff_tree_stdin(char *line) } static const char diff_tree_usage[] = -"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] " +"git diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] " "[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n" " -r diff recursively\n" " --root include the initial commit as diff against /dev/null\n" diff --git a/builtin-diff.c b/builtin-diff.c index 4c289e798..faaa85a1d 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -21,7 +21,7 @@ struct blobinfo { }; static const char builtin_diff_usage[] = -"git-diff <options> <rev>{0,2} -- <path>*"; +"git diff <options> <rev>{0,2} -- <path>*"; static void stuff_change(struct diff_options *opt, unsigned old_mode, unsigned new_mode, diff --git a/builtin-fast-export.c b/builtin-fast-export.c index 75132bacf..a443d5946 100644 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -18,7 +18,7 @@ #include "parse-options.h" static const char *fast_export_usage[] = { - "git-fast-export [rev-list-opts]", + "git fast-export [rev-list-opts]", NULL }; @@ -136,9 +136,18 @@ static void show_filemodify(struct diff_queue_struct *q, if (is_null_sha1(spec->sha1)) printf("D %s\n", spec->path); else { - struct object *object = lookup_object(spec->sha1); - printf("M %06o :%d %s\n", spec->mode, - get_object_mark(object), spec->path); + /* + * Links refer to objects in another repositories; + * output the SHA-1 verbatim. + */ + if (S_ISGITLINK(spec->mode)) + printf("M %06o %s %s\n", spec->mode, + sha1_to_hex(spec->sha1), spec->path); + else { + struct object *object = lookup_object(spec->sha1); + printf("M %06o :%d %s\n", spec->mode, + get_object_mark(object), spec->path); + } } } } @@ -196,8 +205,10 @@ static void handle_commit(struct commit *commit, struct rev_info *rev) diff_root_tree_sha1(commit->tree->object.sha1, "", &rev->diffopt); + /* Export the referenced blobs, and remember the marks. */ for (i = 0; i < diff_queued_diff.nr; i++) - handle_object(diff_queued_diff.queue[i]->two->sha1); + if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode)) + handle_object(diff_queued_diff.queue[i]->two->sha1); mark_next_object(&commit->object); if (!is_encoding_utf8(encoding)) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 1ea704063..273239af3 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -18,7 +18,7 @@ static struct fetch_pack_args args = { }; static const char fetch_pack_usage[] = -"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]"; +"git fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]"; #define COMPLETE (1U << 0) #define COMMON (1U << 1) diff --git a/builtin-fetch.c b/builtin-fetch.c index 97fdc51e3..61de50a02 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -12,7 +12,7 @@ #include "parse-options.h" static const char * const builtin_fetch_usage[] = { - "git-fetch [options] [<repository> <refspec>...]", + "git fetch [options] [<repository> <refspec>...]", NULL }; diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index dbd7d2dda..df02ba7af 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -6,7 +6,7 @@ #include "tag.h" static const char *fmt_merge_msg_usage = - "git-fmt-merge-msg [--log] [--no-log] [--file <file>]"; + "git fmt-merge-msg [--log] [--no-log] [--file <file>]"; static int merge_summary; diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index fef93d748..76282ad79 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -831,7 +831,7 @@ int opt_parse_sort(const struct option *opt, const char *arg, int unset) } static char const * const for_each_ref_usage[] = { - "git-for-each-ref [options] [<pattern>]", + "git for-each-ref [options] [<pattern>]", NULL }; diff --git a/builtin-fsck.c b/builtin-fsck.c index b0f9648f8..7326dc33a 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -539,7 +539,7 @@ static int fsck_cache_tree(struct cache_tree *it) } static char const * const fsck_usage[] = { - "git-fsck [options] [<object>...]", + "git fsck [options] [<object>...]", NULL }; diff --git a/builtin-gc.c b/builtin-gc.c index f5625bb9f..fac200e0b 100644 --- a/builtin-gc.c +++ b/builtin-gc.c @@ -18,7 +18,7 @@ #define FAILED_RUN "failed to run %s" static const char * const builtin_gc_usage[] = { - "git-gc [options]", + "git gc [options]", NULL }; diff --git a/builtin-grep.c b/builtin-grep.c index ef299108f..631129ddf 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -427,33 +427,35 @@ static int grep_tree(struct grep_opt *opt, const char **paths, struct name_entry entry; char *down; int tn_len = strlen(tree_name); - char *path_buf = xmalloc(PATH_MAX + tn_len + 100); + struct strbuf pathbuf; + + strbuf_init(&pathbuf, PATH_MAX + tn_len); if (tn_len) { - tn_len = sprintf(path_buf, "%s:", tree_name); - down = path_buf + tn_len; - strcat(down, base); - } - else { - down = path_buf; - strcpy(down, base); + strbuf_add(&pathbuf, tree_name, tn_len); + strbuf_addch(&pathbuf, ':'); + tn_len = pathbuf.len; } - len = strlen(path_buf); + strbuf_addstr(&pathbuf, base); + len = pathbuf.len; while (tree_entry(tree, &entry)) { - strcpy(path_buf + len, entry.path); + int te_len = tree_entry_len(entry.path, entry.sha1); + pathbuf.len = len; + strbuf_add(&pathbuf, entry.path, te_len); if (S_ISDIR(entry.mode)) /* Match "abc/" against pathspec to * decide if we want to descend into "abc" * directory. */ - strcpy(path_buf + len + tree_entry_len(entry.path, entry.sha1), "/"); + strbuf_addch(&pathbuf, '/'); + down = pathbuf.buf + tn_len; if (!pathspec_matches(paths, down)) ; else if (S_ISREG(entry.mode)) - hit |= grep_sha1(opt, entry.sha1, path_buf, tn_len); + hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len); else if (S_ISDIR(entry.mode)) { enum object_type type; struct tree_desc sub; @@ -469,6 +471,7 @@ static int grep_tree(struct grep_opt *opt, const char **paths, free(data); } } + strbuf_release(&pathbuf); return hit; } @@ -495,7 +498,7 @@ static int grep_object(struct grep_opt *opt, const char **paths, } static const char builtin_grep_usage[] = -"git-grep <option>* <rev>* [-e] <pattern> [<path>...]"; +"git grep <option>* [-e] <pattern> <rev>* [[--] <path>...]"; static const char emsg_invalid_context_len[] = "%s: invalid context length argument"; diff --git a/builtin-init-db.c b/builtin-init-db.c index 5ba213a59..38b4fcb6d 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -354,7 +354,7 @@ static int guess_repository_type(const char *git_dir) } static const char init_db_usage[] = -"git-init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]"; +"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]"; /* * If you want to, you can share the DB area with any number of branches. diff --git a/builtin-log.c b/builtin-log.c index 430d87661..f4975cf35 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -313,7 +313,7 @@ static int show_object(const unsigned char *sha1, int show_tag_object, static int show_tree_object(const unsigned char *sha1, const char *base, int baselen, - const char *pathname, unsigned mode, int stage) + const char *pathname, unsigned mode, int stage, void *context) { printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : ""); return 0; @@ -366,7 +366,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) name, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); read_tree_recursive((struct tree *)o, "", 0, 0, NULL, - show_tree_object); + show_tree_object, NULL); break; case OBJ_COMMIT: rev.pending.nr = rev.pending.alloc = 0; @@ -1082,7 +1082,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags) } static const char cherry_usage[] = -"git-cherry [-v] <upstream> [<head>] [<limit>]"; +"git cherry [-v] <upstream> [<head>] [<limit>]"; int cmd_cherry(int argc, const char **argv, const char *prefix) { struct rev_info revs; diff --git a/builtin-ls-files.c b/builtin-ls-files.c index 75ba42246..e8d568eed 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -423,7 +423,7 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_ } static const char ls_files_usage[] = - "git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* " + "git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* " "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] " "[ --exclude-per-directory=<filename> ] [--exclude-standard] " "[--full-name] [--abbrev] [--] [<file>]*"; diff --git a/builtin-ls-remote.c b/builtin-ls-remote.c index 06ab8da1f..c21b841e7 100644 --- a/builtin-ls-remote.c +++ b/builtin-ls-remote.c @@ -4,7 +4,7 @@ #include "remote.h" static const char ls_remote_usage[] = -"git-ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>"; +"git ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>"; /* * Is there one among the list of patterns that match the tail part diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c index f4a75ddbc..d25767a1f 100644 --- a/builtin-ls-tree.c +++ b/builtin-ls-tree.c @@ -23,7 +23,7 @@ static int chomp_prefix; static const char *ls_tree_prefix; static const char ls_tree_usage[] = - "git-ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]"; + "git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]"; static int show_recursive(const char *base, int baselen, const char *pathname) { @@ -56,7 +56,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname) } static int show_tree(const unsigned char *sha1, const char *base, int baselen, - const char *pathname, unsigned mode, int stage) + const char *pathname, unsigned mode, int stage, void *context) { int retval = 0; const char *type = blob_type; @@ -189,7 +189,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) tree = parse_tree_indirect(sha1); if (!tree) die("not a tree object"); - read_tree_recursive(tree, "", 0, 0, pathspec, show_tree); + read_tree_recursive(tree, "", 0, 0, pathspec, show_tree, NULL); return 0; } diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index 13f0502b9..b99a5b6f9 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -5,14 +5,15 @@ #include "cache.h" #include "builtin.h" #include "utf8.h" +#include "strbuf.h" static FILE *cmitmsg, *patchfile, *fin, *fout; static int keep_subject; static const char *metainfo_charset; -static char line[1000]; -static char name[1000]; -static char email[1000]; +static struct strbuf line = STRBUF_INIT; +static struct strbuf name = STRBUF_INIT; +static struct strbuf email = STRBUF_INIT; static enum { TE_DONTCARE, TE_QP, TE_BASE64, @@ -21,74 +22,79 @@ static enum { TYPE_TEXT, TYPE_OTHER, } message_type; -static char charset[256]; +static struct strbuf charset = STRBUF_INIT; static int patch_lines; -static char **p_hdr_data, **s_hdr_data; +static struct strbuf **p_hdr_data, **s_hdr_data; #define MAX_HDR_PARSED 10 #define MAX_BOUNDARIES 5 -static char *sanity_check(char *name, char *email) +static void get_sane_name(struct strbuf *out, struct strbuf *name, struct strbuf *email) { - int len = strlen(name); - if (len < 3 || len > 60) - return email; - if (strchr(name, '@') || strchr(name, '<') || strchr(name, '>')) - return email; - return name; + struct strbuf *src = name; + if (name->len < 3 || 60 < name->len || strchr(name->buf, '@') || + strchr(name->buf, '<') || strchr(name->buf, '>')) + src = email; + else if (name == out) + return; + strbuf_reset(out); + strbuf_addbuf(out, src); } -static int bogus_from(char *line) +static void parse_bogus_from(const struct strbuf *line) { /* John Doe <johndoe> */ - char *bra, *ket, *dst, *cp; + char *bra, *ket; /* This is fallback, so do not bother if we already have an * e-mail address. */ - if (*email) - return 0; + if (email.len) + return; - bra = strchr(line, '<'); + bra = strchr(line->buf, '<'); if (!bra) - return 0; + return; ket = strchr(bra, '>'); if (!ket) - return 0; + return; - for (dst = email, cp = bra+1; cp < ket; ) - *dst++ = *cp++; - *dst = 0; - for (cp = line; isspace(*cp); cp++) - ; - for (bra--; isspace(*bra); bra--) - *bra = 0; - cp = sanity_check(cp, email); - strcpy(name, cp); - return 1; + strbuf_reset(&email); + strbuf_add(&email, bra + 1, ket - bra - 1); + + strbuf_reset(&name); + strbuf_add(&name, line->buf, bra - line->buf); + strbuf_trim(&name); + get_sane_name(&name, &name, &email); } -static int handle_from(char *in_line) +static void handle_from(const struct strbuf *from) { - char line[1000]; char *at; - char *dst; + size_t el; + struct strbuf f; - strcpy(line, in_line); - at = strchr(line, '@'); - if (!at) - return bogus_from(line); + strbuf_init(&f, from->len); + strbuf_addbuf(&f, from); + + at = strchr(f.buf, '@'); + if (!at) { + parse_bogus_from(from); + return; + } /* * If we already have one email, don't take any confusing lines */ - if (*email && strchr(at+1, '@')) - return 0; + if (email.len && strchr(at + 1, '@')) { + strbuf_release(&f); + return; + } /* Pick up the string around '@', possibly delimited with <> - * pair; that is the email part. White them out while copying. + * pair; that is the email part. */ - while (at > line) { + while (at > f.buf) { char c = at[-1]; if (isspace(c)) break; @@ -98,56 +104,35 @@ static int handle_from(char *in_line) } at--; } - dst = email; - for (;;) { - unsigned char c = *at; - if (!c || c == '>' || isspace(c)) { - if (c == '>') - *at = ' '; - break; - } - *at++ = ' '; - *dst++ = c; - } - *dst++ = 0; + el = strcspn(at, " \n\t\r\v\f>"); + strbuf_reset(&email); + strbuf_add(&email, at, el); + strbuf_remove(&f, at - f.buf, el + 1); /* The remainder is name. It could be "John Doe <john.doe@xz>" - * or "john.doe@xz (John Doe)", but we have whited out the + * or "john.doe@xz (John Doe)", but we have removed the * email part, so trim from both ends, possibly removing * the () pair at the end. */ - at = line + strlen(line); - while (at > line) { - unsigned char c = *--at; - if (!isspace(c)) { - at[(c == ')') ? 0 : 1] = 0; - break; - } - } + strbuf_trim(&f); + if (f.buf[0] == '(') + strbuf_remove(&name, 0, 1); + if (f.len && f.buf[f.len - 1] == ')') + strbuf_setlen(&f, f.len - 1); - at = line; - for (;;) { - unsigned char c = *at; - if (!c || !isspace(c)) { - if (c == '(') - at++; - break; - } - at++; - } - at = sanity_check(at, email); - strcpy(name, at); - return 1; + get_sane_name(&name, &f, &email); + strbuf_release(&f); } -static int handle_header(char *line, char *data, int ofs) +static void handle_header(struct strbuf **out, const struct strbuf *line) { - if (!line || !data) - return 1; + if (!*out) { + *out = xmalloc(sizeof(struct strbuf)); + strbuf_init(*out, line->len); + } else + strbuf_reset(*out); - strcpy(data, line+ofs); - - return 0; + strbuf_addbuf(*out, line); } /* NOTE NOTE NOTE. We do not claim we do full MIME. We just attempt @@ -156,13 +141,13 @@ static int handle_header(char *line, char *data, int ofs) * case insensitively. */ -static int slurp_attr(const char *line, const char *name, char *attr) +static int slurp_attr(const char *line, const char *name, struct strbuf *attr) { const char *ends, *ap = strcasestr(line, name); size_t sz; if (!ap) { - *attr = 0; + strbuf_setlen(attr, 0); return 0; } ap += strlen(name); @@ -173,182 +158,171 @@ static int slurp_attr(const char *line, const char *name, char *attr) else ends = "; \t"; sz = strcspn(ap, ends); - memcpy(attr, ap, sz); - attr[sz] = 0; + strbuf_add(attr, ap, sz); return 1; } -struct content_type { - char *boundary; - int boundary_len; -}; - -static struct content_type content[MAX_BOUNDARIES]; +static struct strbuf *content[MAX_BOUNDARIES]; -static struct content_type *content_top = content; +static struct strbuf **content_top = content; -static int handle_content_type(char *line) +static void handle_content_type(struct strbuf *line) { - char boundary[256]; + struct strbuf *boundary = xmalloc(sizeof(struct strbuf)); + strbuf_init(boundary, line->len); - if (strcasestr(line, "text/") == NULL) + if (!strcasestr(line->buf, "text/")) message_type = TYPE_OTHER; - if (slurp_attr(line, "boundary=", boundary + 2)) { - memcpy(boundary, "--", 2); + if (slurp_attr(line->buf, "boundary=", boundary)) { + strbuf_insert(boundary, 0, "--", 2); if (content_top++ >= &content[MAX_BOUNDARIES]) { fprintf(stderr, "Too many boundaries to handle\n"); exit(1); } - content_top->boundary_len = strlen(boundary); - content_top->boundary = xmalloc(content_top->boundary_len+1); - strcpy(content_top->boundary, boundary); + *content_top = boundary; + boundary = NULL; } - if (slurp_attr(line, "charset=", charset)) { - int i, c; - for (i = 0; (c = charset[i]) != 0; i++) - charset[i] = tolower(c); + if (slurp_attr(line->buf, "charset=", &charset)) + strbuf_tolower(&charset); + + if (boundary) { + strbuf_release(boundary); + free(boundary); } - return 0; } -static int handle_content_transfer_encoding(char *line) +static void handle_content_transfer_encoding(const struct strbuf *line) { - if (strcasestr(line, "base64")) + if (strcasestr(line->buf, "base64")) transfer_encoding = TE_BASE64; - else if (strcasestr(line, "quoted-printable")) + else if (strcasestr(line->buf, "quoted-printable")) transfer_encoding = TE_QP; else transfer_encoding = TE_DONTCARE; - return 0; } -static int is_multipart_boundary(const char *line) +static int is_multipart_boundary(const struct strbuf *line) { - return (!memcmp(line, content_top->boundary, content_top->boundary_len)); + return !strbuf_cmp(line, *content_top); } -static int eatspace(char *line) +static void cleanup_subject(struct strbuf *subject) { - int len = strlen(line); - while (len > 0 && isspace(line[len-1])) - line[--len] = 0; - return len; -} - -static char *cleanup_subject(char *subject) -{ - for (;;) { - char *p; - int len, remove; - switch (*subject) { + char *pos; + size_t remove; + while (subject->len) { + switch (*subject->buf) { case 'r': case 'R': - if (!memcmp("e:", subject+1, 2)) { - subject += 3; + if (subject->len <= 3) + break; + if (!memcmp(subject->buf + 1, "e:", 2)) { + strbuf_remove(subject, 0, 3); continue; } break; case ' ': case '\t': case ':': - subject++; + strbuf_remove(subject, 0, 1); continue; - case '[': - p = strchr(subject, ']'); - if (!p) { - subject++; - continue; - } - len = strlen(p); - remove = p - subject; - if (remove <= len *2) { - subject = p+1; - continue; - } + if ((pos = strchr(subject->buf, ']'))) { + remove = pos - subject->buf; + if (remove <= (subject->len - remove) * 2) { + strbuf_remove(subject, 0, remove + 1); + continue; + } + } else + strbuf_remove(subject, 0, 1); break; } - eatspace(subject); - return subject; + strbuf_trim(subject); + return; } } -static void cleanup_space(char *buf) +static void cleanup_space(struct strbuf *sb) { - unsigned char c; - while ((c = *buf) != 0) { - buf++; - if (isspace(c)) { - buf[-1] = ' '; - c = *buf; - while (isspace(c)) { - int len = strlen(buf); - memmove(buf, buf+1, len); - c = *buf; - } + size_t pos, cnt; + for (pos = 0; pos < sb->len; pos++) { + if (isspace(sb->buf[pos])) { + sb->buf[pos] = ' '; + for (cnt = 0; isspace(sb->buf[pos + cnt + 1]); cnt++); + strbuf_remove(sb, pos + 1, cnt); } } } -static void decode_header(char *it, unsigned itsize); +static void decode_header(struct strbuf *line); static const char *header[MAX_HDR_PARSED] = { "From","Subject","Date", }; -static int check_header(char *line, unsigned linesize, char **hdr_data, int overwrite) +static inline int cmp_header(const struct strbuf *line, const char *hdr) { - int i; + int len = strlen(hdr); + return !strncasecmp(line->buf, hdr, len) && line->len > len && + line->buf[len] == ':' && isspace(line->buf[len + 1]); +} +static int check_header(const struct strbuf *line, + struct strbuf *hdr_data[], int overwrite) +{ + int i, ret = 0, len; + struct strbuf sb = STRBUF_INIT; /* search for the interesting parts */ for (i = 0; header[i]; i++) { int len = strlen(header[i]); - if ((!hdr_data[i] || overwrite) && - !strncasecmp(line, header[i], len) && - line[len] == ':' && isspace(line[len + 1])) { + if ((!hdr_data[i] || overwrite) && cmp_header(line, header[i])) { /* Unwrap inline B and Q encoding, and optionally * normalize the meta information to utf8. */ - decode_header(line + len + 2, linesize - len - 2); - hdr_data[i] = xmalloc(1000 * sizeof(char)); - if (! handle_header(line, hdr_data[i], len + 2)) { - return 1; - } + strbuf_add(&sb, line->buf + len + 2, line->len - len - 2); + decode_header(&sb); + handle_header(&hdr_data[i], &sb); + ret = 1; + goto check_header_out; } } /* Content stuff */ - if (!strncasecmp(line, "Content-Type", 12) && - line[12] == ':' && isspace(line[12 + 1])) { - decode_header(line + 12 + 2, linesize - 12 - 2); - if (! handle_content_type(line)) { - return 1; - } - } - if (!strncasecmp(line, "Content-Transfer-Encoding", 25) && - line[25] == ':' && isspace(line[25 + 1])) { - decode_header(line + 25 + 2, linesize - 25 - 2); - if (! handle_content_transfer_encoding(line)) { - return 1; - } + if (cmp_header(line, "Content-Type")) { + len = strlen("Content-Type: "); + strbuf_add(&sb, line->buf + len, line->len - len); + decode_header(&sb); + strbuf_insert(&sb, 0, "Content-Type: ", len); + handle_content_type(&sb); + ret = 1; + goto check_header_out; + } + if (cmp_header(line, "Content-Transfer-Encoding")) { + len = strlen("Content-Transfer-Encoding: "); + strbuf_add(&sb, line->buf + len, line->len - len); + decode_header(&sb); + handle_content_transfer_encoding(&sb); + ret = 1; + goto check_header_out; } /* for inbody stuff */ - if (!memcmp(">From", line, 5) && isspace(line[5])) - return 1; - if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) { + if (!prefixcmp(line->buf, ">From") && isspace(line->buf[5])) { + ret = 1; /* Should this return 0? */ + goto check_header_out; + } + if (!prefixcmp(line->buf, "[PATCH]") && isspace(line->buf[7])) { for (i = 0; header[i]; i++) { if (!memcmp("Subject", header[i], 7)) { - if (!hdr_data[i]) - hdr_data[i] = xmalloc(linesize + 20); - if (! handle_header(line, hdr_data[i], 0)) { - return 1; - } + handle_header(&hdr_data[i], line); + ret = 1; + goto check_header_out; } } } - /* no match */ - return 0; +check_header_out: + strbuf_release(&sb); + return ret; } -static int is_rfc2822_header(char *line) +static int is_rfc2822_header(const struct strbuf *line) { /* * The section that defines the loosest possible @@ -359,15 +333,15 @@ static int is_rfc2822_header(char *line) * ftext = %d33-57 / %59-126 */ int ch; - char *cp = line; + char *cp = line->buf; /* Count mbox From headers as headers */ - if (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6)) + if (!prefixcmp(cp, "From ") || !prefixcmp(cp, ">From ")) return 1; while ((ch = *cp++)) { if (ch == ':') - return cp != line; + return 1; if ((33 <= ch && ch <= 57) || (59 <= ch && ch <= 126)) continue; @@ -376,34 +350,20 @@ static int is_rfc2822_header(char *line) return 0; } -/* - * sz is size of 'line' buffer in bytes. Must be reasonably - * long enough to hold one physical real-world e-mail line. - */ -static int read_one_header_line(char *line, int sz, FILE *in) +static int read_one_header_line(struct strbuf *line, FILE *in) { - int len; - - /* - * We will read at most (sz-1) bytes and then potentially - * re-add NUL after it. Accessing line[sz] after this is safe - * and we can allow len to grow up to and including sz. - */ - sz--; - /* Get the first part of the line. */ - if (!fgets(line, sz, in)) + if (strbuf_getline(line, in, '\n')) return 0; /* * Is it an empty line or not a valid rfc2822 header? * If so, stop here, and return false ("not a header") */ - len = eatspace(line); - if (!len || !is_rfc2822_header(line)) { + strbuf_rtrim(line); + if (!line->len || !is_rfc2822_header(line)) { /* Re-add the newline */ - line[len] = '\n'; - line[len + 1] = '\0'; + strbuf_addch(line, '\n'); return 0; } @@ -412,65 +372,53 @@ static int read_one_header_line(char *line, int sz, FILE *in) * Yuck, 2822 header "folding" */ for (;;) { - int peek, addlen; - static char continuation[1000]; + int peek; + struct strbuf continuation = STRBUF_INIT; peek = fgetc(in); ungetc(peek, in); if (peek != ' ' && peek != '\t') break; - if (!fgets(continuation, sizeof(continuation), in)) + if (strbuf_getline(&continuation, in, '\n')) break; - addlen = eatspace(continuation); - if (len < sz - 1) { - if (addlen >= sz - len) - addlen = sz - len - 1; - memcpy(line + len, continuation, addlen); - line[len] = '\n'; - len += addlen; - } + continuation.buf[0] = '\n'; + strbuf_rtrim(&continuation); + strbuf_addbuf(line, &continuation); } - line[len] = 0; return 1; } -static int decode_q_segment(char *in, char *ot, unsigned otsize, char *ep, int rfc2047) +static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047) { - char *otbegin = ot; - char *otend = ot + otsize; + const char *in = q_seg->buf; int c; - while ((c = *in++) != 0 && (in <= ep)) { - if (ot == otend) { - *--ot = '\0'; - return -1; - } + struct strbuf *out = xmalloc(sizeof(struct strbuf)); + strbuf_init(out, q_seg->len); + + while ((c = *in++) != 0) { if (c == '=') { int d = *in++; if (d == '\n' || !d) break; /* drop trailing newline */ - *ot++ = ((hexval(d) << 4) | hexval(*in++)); + strbuf_addch(out, (hexval(d) << 4) | hexval(*in++)); continue; } if (rfc2047 && c == '_') /* rfc2047 4.2 (2) */ c = 0x20; - *ot++ = c; + strbuf_addch(out, c); } - *ot = 0; - return (ot - otbegin); + return out; } -static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep) +static struct strbuf *decode_b_segment(const struct strbuf *b_seg) { /* Decode in..ep, possibly in-place to ot */ int c, pos = 0, acc = 0; - char *otbegin = ot; - char *otend = ot + otsize; + const char *in = b_seg->buf; + struct strbuf *out = xmalloc(sizeof(struct strbuf)); + strbuf_init(out, b_seg->len); - while ((c = *in++) != 0 && (in <= ep)) { - if (ot == otend) { - *--ot = '\0'; - return -1; - } + while ((c = *in++) != 0) { if (c == '+') c = 62; else if (c == '/') @@ -495,21 +443,20 @@ static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep) acc = (c << 2); break; case 1: - *ot++ = (acc | (c >> 4)); + strbuf_addch(out, (acc | (c >> 4))); acc = (c & 15) << 4; break; case 2: - *ot++ = (acc | (c >> 2)); + strbuf_addch(out, (acc | (c >> 2))); acc = (c & 3) << 6; break; case 3: - *ot++ = (acc | c); + strbuf_addch(out, (acc | c)); acc = pos = 0; break; } } - *ot = 0; - return (ot - otbegin); + return out; } /* @@ -523,16 +470,16 @@ static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep) * Otherwise, we default to assuming it is Latin1 for historical * reasons. */ -static const char *guess_charset(const char *line, const char *target_charset) +static const char *guess_charset(const struct strbuf *line, const char *target_charset) { if (is_encoding_utf8(target_charset)) { - if (is_utf8(line)) + if (is_utf8(line->buf)) return NULL; } return "latin1"; } -static void convert_to_utf8(char *line, unsigned linesize, const char *charset) +static void convert_to_utf8(struct strbuf *line, const char *charset) { char *out; @@ -544,112 +491,118 @@ static void convert_to_utf8(char *line, unsigned linesize, const char *charset) if (!strcmp(metainfo_charset, charset)) return; - out = reencode_string(line, metainfo_charset, charset); + out = reencode_string(line->buf, metainfo_charset, charset); if (!out) die("cannot convert from %s to %s\n", charset, metainfo_charset); - strlcpy(line, out, linesize); - free(out); + strbuf_attach(line, out, strlen(out), strlen(out)); } -static int decode_header_bq(char *it, unsigned itsize) +static int decode_header_bq(struct strbuf *it) { - char *in, *out, *ep, *cp, *sp; - char outbuf[1000]; + char *in, *ep, *cp; + struct strbuf outbuf = STRBUF_INIT, *dec; + struct strbuf charset_q = STRBUF_INIT, piecebuf = STRBUF_INIT; int rfc2047 = 0; - in = it; - out = outbuf; - while ((ep = strstr(in, "=?")) != NULL) { - int sz, encoding; - char charset_q[256], piecebuf[256]; + in = it->buf; + while (in - it->buf <= it->len && (ep = strstr(in, "=?")) != NULL) { + int encoding; + strbuf_reset(&charset_q); + strbuf_reset(&piecebuf); rfc2047 = 1; if (in != ep) { - sz = ep - in; - memcpy(out, in, sz); - out += sz; - in += sz; + strbuf_add(&outbuf, in, ep - in); + in = ep; } /* E.g. * ep : "=?iso-2022-jp?B?GyR...?= foo" * ep : "=?ISO-8859-1?Q?Foo=FCbar?= baz" */ ep += 2; - cp = strchr(ep, '?'); - if (!cp) - return rfc2047; /* no munging */ - for (sp = ep; sp < cp; sp++) - charset_q[sp - ep] = tolower(*sp); - charset_q[cp - ep] = 0; + + if (ep - it->buf >= it->len || !(cp = strchr(ep, '?'))) + goto decode_header_bq_out; + + if (cp + 3 - it->buf > it->len) + goto decode_header_bq_out; + strbuf_add(&charset_q, ep, cp - ep); + strbuf_tolower(&charset_q); + encoding = cp[1]; if (!encoding || cp[2] != '?') - return rfc2047; /* no munging */ + goto decode_header_bq_out; ep = strstr(cp + 3, "?="); if (!ep) - return rfc2047; /* no munging */ + goto decode_header_bq_out; + strbuf_add(&piecebuf, cp + 3, ep - cp - 3); switch (tolower(encoding)) { default: - return rfc2047; /* no munging */ + goto decode_header_bq_out; case 'b': - sz = decode_b_segment(cp + 3, piecebuf, sizeof(piecebuf), ep); + dec = decode_b_segment(&piecebuf); break; case 'q': - sz = decode_q_segment(cp + 3, piecebuf, sizeof(piecebuf), ep, 1); + dec = decode_q_segment(&piecebuf, 1); break; } - if (sz < 0) - return rfc2047; if (metainfo_charset) - convert_to_utf8(piecebuf, sizeof(piecebuf), charset_q); + convert_to_utf8(dec, charset_q.buf); - sz = strlen(piecebuf); - if (outbuf + sizeof(outbuf) <= out + sz) - return rfc2047; /* no munging */ - strcpy(out, piecebuf); - out += sz; + strbuf_addbuf(&outbuf, dec); + strbuf_release(dec); + free(dec); in = ep + 2; } - strcpy(out, in); - strlcpy(it, outbuf, itsize); + strbuf_addstr(&outbuf, in); + strbuf_reset(it); + strbuf_addbuf(it, &outbuf); +decode_header_bq_out: + strbuf_release(&outbuf); + strbuf_release(&charset_q); + strbuf_release(&piecebuf); return rfc2047; } -static void decode_header(char *it, unsigned itsize) +static void decode_header(struct strbuf *it) { - - if (decode_header_bq(it, itsize)) + if (decode_header_bq(it)) return; /* otherwise "it" is a straight copy of the input. * This can be binary guck but there is no charset specified. */ if (metainfo_charset) - convert_to_utf8(it, itsize, ""); + convert_to_utf8(it, ""); } -static int decode_transfer_encoding(char *line, unsigned linesize, int inputlen) +static void decode_transfer_encoding(struct strbuf *line) { - char *ep; + struct strbuf *ret; switch (transfer_encoding) { case TE_QP: - ep = line + inputlen; - return decode_q_segment(line, line, linesize, ep, 0); + ret = decode_q_segment(line, 0); + break; case TE_BASE64: - ep = line + inputlen; - return decode_b_segment(line, line, linesize, ep); + ret = decode_b_segment(line); + break; case TE_DONTCARE: default: - return inputlen; + return; } + strbuf_reset(line); + strbuf_addbuf(line, ret); + strbuf_release(ret); + free(ret); } -static int handle_filter(char *line, unsigned linesize, int linelen); +static void handle_filter(struct strbuf *line); static int find_boundary(void) { - while(fgets(line, sizeof(line), fin) != NULL) { - if (is_multipart_boundary(line)) + while (!strbuf_getline(&line, fin, '\n')) { + if (is_multipart_boundary(&line)) return 1; } return 0; @@ -657,12 +610,17 @@ static int find_boundary(void) static int handle_boundary(void) { - char newline[]="\n"; + struct strbuf newline = STRBUF_INIT; + + strbuf_addch(&newline, '\n'); again: - if (!memcmp(line+content_top->boundary_len, "--", 2)) { + if (line.len >= (*content_top)->len + 2 && + !memcmp(line.buf + (*content_top)->len, "--", 2)) { /* we hit an end boundary */ /* pop the current boundary off the stack */ - free(content_top->boundary); + strbuf_release(*content_top); + free(*content_top); + *content_top = NULL; /* technically won't happen as is_multipart_boundary() will fail first. But just in case.. @@ -672,7 +630,8 @@ again: "can't recover\n"); exit(1); } - handle_filter(newline, sizeof(newline), strlen(newline)); + handle_filter(&newline); + strbuf_release(&newline); /* skip to the next boundary */ if (!find_boundary()) @@ -682,39 +641,44 @@ again: /* set some defaults */ transfer_encoding = TE_DONTCARE; - charset[0] = 0; + strbuf_reset(&charset); message_type = TYPE_TEXT; /* slurp in this section's info */ - while (read_one_header_line(line, sizeof(line), fin)) - check_header(line, sizeof(line), p_hdr_data, 0); + while (read_one_header_line(&line, fin)) + check_header(&line, p_hdr_data, 0); + strbuf_release(&newline); /* eat the blank line after section info */ - return (fgets(line, sizeof(line), fin) != NULL); + return (strbuf_getline(&line, fin, '\n') == 0); } -static inline int patchbreak(const char *line) +static inline int patchbreak(const struct strbuf *line) { + size_t i; + /* Beginning of a "diff -" header? */ - if (!memcmp("diff -", line, 6)) + if (!prefixcmp(line->buf, "diff -")) return 1; /* CVS "Index: " line? */ - if (!memcmp("Index: ", line, 7)) + if (!prefixcmp(line->buf, "Index: ")) return 1; /* * "--- <filename>" starts patches without headers * "---<sp>*" is a manual separator */ - if (!memcmp("---", line, 3)) { - line += 3; + if (line->len < 4) + return 0; + + if (!prefixcmp(line->buf, "---")) { /* space followed by a filename? */ - if (line[0] == ' ' && !isspace(line[1])) + if (line->buf[3] == ' ' && !isspace(line->buf[4])) return 1; /* Just whitespace? */ - for (;;) { - unsigned char c = *line++; + for (i = 3; i < line->len; i++) { + unsigned char c = line->buf[i]; if (c == '\n') return 1; if (!isspace(c)) @@ -725,32 +689,24 @@ static inline int patchbreak(const char *line) return 0; } - -static int handle_commit_msg(char *line, unsigned linesize) +static int handle_commit_msg(struct strbuf *line) { static int still_looking = 1; - char *endline = line + linesize; if (!cmitmsg) return 0; if (still_looking) { - char *cp = line; - if (isspace(*line)) { - for (cp = line + 1; *cp; cp++) { - if (!isspace(*cp)) - break; - } - if (!*cp) - return 0; - } - if ((still_looking = check_header(cp, endline - cp, s_hdr_data, 0)) != 0) + strbuf_ltrim(line); + if (!line->len) + return 0; + if ((still_looking = check_header(line, s_hdr_data, 0)) != 0) return 0; } /* normalize the log message to UTF-8. */ if (metainfo_charset) - convert_to_utf8(line, endline - line, charset); + convert_to_utf8(line, charset.buf); if (patchbreak(line)) { fclose(cmitmsg); @@ -758,142 +714,132 @@ static int handle_commit_msg(char *line, unsigned linesize) return 1; } - fputs(line, cmitmsg); + fputs(line->buf, cmitmsg); return 0; } -static int handle_patch(char *line, int len) +static void handle_patch(const struct strbuf *line) { - fwrite(line, 1, len, patchfile); + fwrite(line->buf, 1, line->len, patchfile); patch_lines++; - return 0; } -static int handle_filter(char *line, unsigned linesize, int linelen) +static void handle_filter(struct strbuf *line) { static int filter = 0; - /* filter tells us which part we left off on - * a non-zero return indicates we hit a filter point - */ + /* filter tells us which part we left off on */ switch (filter) { case 0: - if (!handle_commit_msg(line, linesize)) + if (!handle_commit_msg(line)) break; filter++; case 1: - if (!handle_patch(line, linelen)) - break; - filter++; - default: - return 1; + handle_patch(line); + break; } - - return 0; } static void handle_body(void) { - int rc = 0; - static char newline[2000]; - static char *np = newline; - int len = strlen(line); + int len = 0; + struct strbuf prev = STRBUF_INIT; /* Skip up to the first boundary */ - if (content_top->boundary) { + if (*content_top) { if (!find_boundary()) - return; + goto handle_body_out; } do { + strbuf_setlen(&line, line.len + len); + /* process any boundary lines */ - if (content_top->boundary && is_multipart_boundary(line)) { + if (*content_top && is_multipart_boundary(&line)) { /* flush any leftover */ - if (np != newline) - handle_filter(newline, sizeof(newline), - np - newline); + if (line.len) + handle_filter(&line); + if (!handle_boundary()) - return; - len = strlen(line); + goto handle_body_out; } /* Unwrap transfer encoding */ - len = decode_transfer_encoding(line, sizeof(line), len); - if (len < 0) { - error("Malformed input line"); - return; - } + decode_transfer_encoding(&line); switch (transfer_encoding) { case TE_BASE64: case TE_QP: { - char *op = line; + struct strbuf **lines, **it, *sb; + + /* Prepend any previous partial lines */ + strbuf_insert(&line, 0, prev.buf, prev.len); + strbuf_reset(&prev); /* binary data most likely doesn't have newlines */ if (message_type != TYPE_TEXT) { - rc = handle_filter(line, sizeof(line), len); + handle_filter(&line); break; } - /* * This is a decoded line that may contain * multiple new lines. Pass only one chunk * at a time to handle_filter() */ - do { - while (op < line + len && *op != '\n') - *np++ = *op++; - *np = *op; - if (*np != 0) { - /* should be sitting on a new line */ - *(++np) = 0; - op++; - rc = handle_filter(newline, sizeof(newline), np - newline); - np = newline; - } - } while (op < line + len); + lines = strbuf_split(&line, '\n'); + for (it = lines; (sb = *it); it++) { + if (*(it + 1) == NULL) /* The last line */ + if (sb->buf[sb->len - 1] != '\n') { + /* Partial line, save it for later. */ + strbuf_addbuf(&prev, sb); + break; + } + handle_filter(sb); + } /* - * The partial chunk is saved in newline and will be + * The partial chunk is saved in "prev" and will be * appended by the next iteration of read_line_with_nul(). */ + strbuf_list_free(lines); break; } default: - rc = handle_filter(line, sizeof(line), len); + handle_filter(&line); } - if (rc) - /* nothing left to filter */ - break; - } while ((len = read_line_with_nul(line, sizeof(line), fin))); - return; + strbuf_reset(&line); + if (strbuf_avail(&line) < 100) + strbuf_grow(&line, 100); + } while ((len = read_line_with_nul(line.buf, strbuf_avail(&line), fin))); + +handle_body_out: + strbuf_release(&prev); } -static void output_header_lines(FILE *fout, const char *hdr, char *data) +static void output_header_lines(FILE *fout, const char *hdr, const struct strbuf *data) { + const char *sp = data->buf; while (1) { - char *ep = strchr(data, '\n'); + char *ep = strchr(sp, '\n'); int len; if (!ep) - len = strlen(data); + len = strlen(sp); else - len = ep - data; - fprintf(fout, "%s: %.*s\n", hdr, len, data); + len = ep - sp; + fprintf(fout, "%s: %.*s\n", hdr, len, sp); if (!ep) break; - data = ep + 1; + sp = ep + 1; } } static void handle_info(void) { - char *sub; - char *hdr; + struct strbuf *hdr; int i; for (i = 0; header[i]; i++) { - /* only print inbody headers if we output a patch file */ if (patch_lines && s_hdr_data[i]) hdr = s_hdr_data[i]; @@ -903,20 +849,18 @@ static void handle_info(void) continue; if (!memcmp(header[i], "Subject", 7)) { - if (keep_subject) - sub = hdr; - else { - sub = cleanup_subject(hdr); - cleanup_space(sub); + if (!keep_subject) { + cleanup_subject(hdr); + cleanup_space(hdr); } - output_header_lines(fout, "Subject", sub); + output_header_lines(fout, "Subject", hdr); } else if (!memcmp(header[i], "From", 4)) { handle_from(hdr); - fprintf(fout, "Author: %s\n", name); - fprintf(fout, "Email: %s\n", email); + fprintf(fout, "Author: %s\n", name.buf); + fprintf(fout, "Email: %s\n", email.buf); } else { cleanup_space(hdr); - fprintf(fout, "%s: %s\n", header[i], hdr); + fprintf(fout, "%s: %s\n", header[i], hdr->buf); } } fprintf(fout, "\n"); @@ -943,8 +887,8 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, return -1; } - p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *)); - s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *)); + p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*p_hdr_data)); + s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*s_hdr_data)); do { peek = fgetc(in); @@ -952,8 +896,8 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, ungetc(peek, in); /* process the email header */ - while (read_one_header_line(line, sizeof(line), fin)) - check_header(line, sizeof(line), p_hdr_data, 1); + while (read_one_header_line(&line, fin)) + check_header(&line, p_hdr_data, 1); handle_body(); handle_info(); @@ -962,7 +906,7 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, } static const char mailinfo_usage[] = - "git-mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info"; + "git mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info"; int cmd_mailinfo(int argc, const char **argv, const char *prefix) { diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c index e8cbe678e..13c60c39a 100644 --- a/builtin-mailsplit.c +++ b/builtin-mailsplit.c @@ -9,7 +9,7 @@ #include "path-list.h" static const char git_mailsplit_usage[] = -"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]"; +"git mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]"; static int is_from_line(const char *line, int len) { diff --git a/builtin-merge-base.c b/builtin-merge-base.c index bcf9395aa..1cb2925d2 100644 --- a/builtin-merge-base.c +++ b/builtin-merge-base.c @@ -20,7 +20,7 @@ static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_al } static const char merge_base_usage[] = -"git-merge-base [--all] <commit-id> <commit-id>"; +"git merge-base [--all] <commit-id> <commit-id>"; int cmd_merge_base(int argc, const char **argv, const char *prefix) { diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c index 3731853f8..652a2c32b 100644 --- a/builtin-merge-recursive.c +++ b/builtin-merge-recursive.c @@ -248,7 +248,7 @@ struct tree *write_tree_from_memory(void) static int save_files_dirs(const unsigned char *sha1, const char *base, int baselen, const char *path, - unsigned int mode, int stage) + unsigned int mode, int stage, void *context) { int len = strlen(path); char *newpath = xmalloc(baselen + len + 1); @@ -268,7 +268,7 @@ static int save_files_dirs(const unsigned char *sha1, static int get_files_dirs(struct tree *tree) { int n; - if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs) != 0) + if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, NULL)) return 0; n = current_file_set.nr + current_directory_set.nr; return n; diff --git a/builtin-merge.c b/builtin-merge.c index 129b4e62d..e97c79e60 100644 --- a/builtin-merge.c +++ b/builtin-merge.c @@ -50,11 +50,9 @@ static size_t use_strategies_nr, use_strategies_alloc; static const char *branch; static struct strategy all_strategy[] = { - { "recur", NO_TRIVIAL }, { "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL }, { "octopus", DEFAULT_OCTOPUS }, { "resolve", 0 }, - { "stupid", 0 }, { "ours", NO_FAST_FORWARD | NO_TRIVIAL }, { "subtree", NO_FAST_FORWARD | NO_TRIVIAL }, }; @@ -68,10 +66,11 @@ static int option_parse_message(const struct option *opt, if (unset) strbuf_setlen(buf, 0); - else { + else if (arg) { strbuf_addf(buf, "%s\n\n", arg); have_message = 1; - } + } else + return error("switch `m' requires a value"); return 0; } diff --git a/builtin-mv.c b/builtin-mv.c index 5530e11b8..ba9cedab6 100644 --- a/builtin-mv.c +++ b/builtin-mv.c @@ -11,7 +11,7 @@ #include "parse-options.h" static const char * const builtin_mv_usage[] = { - "git-mv [options] <source>... <destination>", + "git mv [options] <source>... <destination>", NULL }; diff --git a/builtin-name-rev.c b/builtin-name-rev.c index f153da012..85612c4dc 100644 --- a/builtin-name-rev.c +++ b/builtin-name-rev.c @@ -172,7 +172,7 @@ static void show_name(const struct object *obj, } static char const * const name_rev_usage[] = { - "git-name-rev [options] ( --all | --stdin | <commit>... )", + "git name-rev [options] ( --all | --stdin | <commit>... )", NULL }; diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c index ff90aefa1..34246df4e 100644 --- a/builtin-pack-refs.c +++ b/builtin-pack-refs.c @@ -3,7 +3,7 @@ #include "pack-refs.h" static char const * const pack_refs_usage[] = { - "git-pack-refs [options]", + "git pack-refs [options]", NULL }; diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c index 241afbbab..10cb8df84 100644 --- a/builtin-prune-packed.c +++ b/builtin-prune-packed.c @@ -3,7 +3,7 @@ #include "progress.h" static const char prune_packed_usage[] = -"git-prune-packed [-n] [-q]"; +"git prune-packed [-n] [-q]"; #define DRY_RUN 01 #define VERBOSE 02 diff --git a/builtin-prune.c b/builtin-prune.c index bd3d2f67f..7de4cabe0 100644 --- a/builtin-prune.c +++ b/builtin-prune.c @@ -7,7 +7,7 @@ #include "parse-options.h" static const char * const prune_usage[] = { - "git-prune [-n] [--expire <time>] [--] [<head>...]", + "git prune [-n] [--expire <time>] [--] [<head>...]", NULL }; static int show_only; diff --git a/builtin-push.c b/builtin-push.c index b35aad68e..c1ed68d93 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -10,11 +10,11 @@ #include "parse-options.h" static const char * const push_usage[] = { - "git-push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]", + "git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]", NULL, }; -static int thin, verbose; +static int thin; static const char *receivepack; static const char **refspec; @@ -84,7 +84,7 @@ static int do_push(const char *repo, int flags) if (thin) transport_set_option(transport, TRANS_OPT_THIN, "yes"); - if (verbose) + if (flags & TRANSPORT_PUSH_VERBOSE) fprintf(stderr, "Pushing to %s\n", remote->url[i]); err = transport_push(transport, refspec_nr, refspec, flags); err |= transport_disconnect(transport); @@ -101,22 +101,19 @@ static int do_push(const char *repo, int flags) int cmd_push(int argc, const char **argv, const char *prefix) { int flags = 0; - int all = 0; - int mirror = 0; - int dry_run = 0; - int force = 0; int tags = 0; int rc; const char *repo = NULL; /* default repository */ struct option options[] = { - OPT__VERBOSE(&verbose), + OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE), OPT_STRING( 0 , "repo", &repo, "repository", "repository"), - OPT_BOOLEAN( 0 , "all", &all, "push all refs"), - OPT_BOOLEAN( 0 , "mirror", &mirror, "mirror all refs"), + OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL), + OPT_BIT( 0 , "mirror", &flags, "mirror all refs", + (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), OPT_BOOLEAN( 0 , "tags", &tags, "push tags"), - OPT_BOOLEAN( 0 , "dry-run", &dry_run, "dry run"), - OPT_BOOLEAN('f', "force", &force, "force updates"), + OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN), + OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE), OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"), OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"), @@ -125,18 +122,8 @@ int cmd_push(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, options, push_usage, 0); - if (force) - flags |= TRANSPORT_PUSH_FORCE; - if (dry_run) - flags |= TRANSPORT_PUSH_DRY_RUN; - if (verbose) - flags |= TRANSPORT_PUSH_VERBOSE; if (tags) add_refspec("refs/tags/*"); - if (all) - flags |= TRANSPORT_PUSH_ALL; - if (mirror) - flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE); if (argc > 0) { repo = argv[0]; diff --git a/builtin-reflog.c b/builtin-reflog.c index 125d455b9..0c34e3781 100644 --- a/builtin-reflog.c +++ b/builtin-reflog.c @@ -13,9 +13,9 @@ */ static const char reflog_expire_usage[] = -"git-reflog (show|expire) [--verbose] [--dry-run] [--stale-fix] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>..."; +"git reflog (show|expire) [--verbose] [--dry-run] [--stale-fix] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>..."; static const char reflog_delete_usage[] = -"git-reflog delete [--verbose] [--dry-run] [--rewrite] [--updateref] <refs>..."; +"git reflog delete [--verbose] [--dry-run] [--rewrite] [--updateref] <refs>..."; static unsigned long default_reflog_expire; static unsigned long default_reflog_expire_unreachable; @@ -630,7 +630,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) */ static const char reflog_usage[] = -"git-reflog (expire | ...)"; +"git reflog (expire | ...)"; int cmd_reflog(int argc, const char **argv, const char *prefix) { diff --git a/builtin-remote.c b/builtin-remote.c index 1491354a9..db12668cf 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -147,6 +147,15 @@ struct branch_info { static struct path_list branch_list; +static const char *abbrev_ref(const char *name, const char *prefix) +{ + const char *abbrev = skip_prefix(name, prefix); + if (abbrev) + return abbrev; + return name; +} +#define abbrev_branch(name) abbrev_ref((name), "refs/heads/") + static int config_read_branches(const char *key, const char *value, void *cb) { if (!prefixcmp(key, "branch.")) { @@ -176,18 +185,12 @@ static int config_read_branches(const char *key, const char *value, void *cb) info->remote = xstrdup(value); } else { char *space = strchr(value, ' '); - const char *ptr = skip_prefix(value, "refs/heads/"); - if (ptr) - value = ptr; + value = abbrev_branch(value); while (space) { char *merge; merge = xstrndup(value, space - value); path_list_append(merge, &info->merge); - ptr = skip_prefix(space + 1, "refs/heads/"); - if (ptr) - value = ptr; - else - value = space + 1; + value = abbrev_branch(space + 1); space = strchr(value, ' '); } path_list_append(xstrdup(value), &info->merge); @@ -219,12 +222,7 @@ static int handle_one_branch(const char *refname, refspec.dst = (char *)refname; if (!remote_find_tracking(states->remote, &refspec)) { struct path_list_item *item; - const char *name, *ptr; - ptr = skip_prefix(refspec.src, "refs/heads/"); - if (ptr) - name = ptr; - else - name = refspec.src; + const char *name = abbrev_branch(refspec.src); /* symbolic refs pointing nowhere were handled already */ if ((flags & REF_ISSYMREF) || unsorted_path_list_has_path(&states->tracked, @@ -253,7 +251,6 @@ static int get_ref_states(const struct ref *ref, struct ref_states *states) struct path_list *target = &states->tracked; unsigned char sha1[20]; void *util = NULL; - const char *ptr; if (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1)) target = &states->new; @@ -262,10 +259,7 @@ static int get_ref_states(const struct ref *ref, struct ref_states *states) if (hashcmp(sha1, ref->new_sha1)) util = &states; } - ptr = skip_prefix(ref->name, "refs/heads/"); - if (!ptr) - ptr = ref->name; - path_list_append(ptr, target)->util = util; + path_list_append(abbrev_branch(ref->name), target)->util = util; } free_refs(fetch_map); @@ -460,10 +454,8 @@ static int append_ref_to_tracked_list(const char *refname, memset(&refspec, 0, sizeof(refspec)); refspec.dst = (char *)refname; - if (!remote_find_tracking(states->remote, &refspec)) { - path_list_append(skip_prefix(refspec.src, "refs/heads/"), - &states->tracked); - } + if (!remote_find_tracking(states->remote, &refspec)) + path_list_append(abbrev_branch(refspec.src), &states->tracked); return 0; } @@ -530,15 +522,10 @@ static int show(int argc, const char **argv) "es" : ""); for (i = 0; i < states.remote->push_refspec_nr; i++) { struct refspec *spec = states.remote->push + i; - const char *p = "", *q = ""; - if (spec->src) - p = skip_prefix(spec->src, "refs/heads/"); - if (spec->dst) - q = skip_prefix(spec->dst, "refs/heads/"); printf(" %s%s%s%s", spec->force ? "+" : "", - p ? p : spec->src, - spec->dst ? ":" : "", - q ? q : spec->dst); + abbrev_branch(spec->src), + spec->dst ? ":" : "", + spec->dst ? abbrev_branch(spec->dst) : ""); } printf("\n"); } @@ -588,7 +575,7 @@ static int prune(int argc, const char **argv) result |= delete_ref(refname, NULL); printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned", - skip_prefix(refname, "refs/remotes/")); + abbrev_ref(refname, "refs/remotes/")); } /* NEEDSWORK: free remote */ diff --git a/builtin-rerere.c b/builtin-rerere.c index 5d40e1693..580580502 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -6,7 +6,7 @@ #include "xdiff-interface.h" static const char git_rerere_usage[] = -"git-rerere [clear | status | diff | gc]"; +"git rerere [clear | status | diff | gc]"; /* these values are days */ static int cutoff_noresolve = 15; diff --git a/builtin-reset.c b/builtin-reset.c index a0321694c..4d246c31b 100644 --- a/builtin-reset.c +++ b/builtin-reset.c @@ -20,8 +20,8 @@ #include "parse-options.h" static const char * const git_reset_usage[] = { - "git-reset [--mixed | --soft | --hard] [-q] [<commit>]", - "git-reset [--mixed] <commit> [--] <paths>...", + "git reset [--mixed | --soft | --hard] [-q] [<commit>]", + "git reset [--mixed] <commit> [--] <paths>...", NULL }; @@ -96,7 +96,7 @@ static int update_index_refresh(int fd, struct lock_file *index_lock) if (read_cache() < 0) return error("Could not read index"); - result = refresh_cache(0) ? 1 : 0; + result = refresh_cache(REFRESH_SAY_CHANGED) ? 1 : 0; if (write_cache(fd, active_cache, active_nr) || commit_locked_index(index_lock)) return error ("Could not refresh index"); diff --git a/builtin-rev-list.c b/builtin-rev-list.c index b4a2c447f..893762c80 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -17,7 +17,7 @@ #define COUNTED (1u<<16) static const char rev_list_usage[] = -"git-rev-list [OPTION] <commit-id>... [ -- paths... ]\n" +"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n" " limiting output:\n" " --max-count=nr\n" " --max-age=epoch\n" @@ -590,6 +590,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) revs.commit_format = CMIT_FMT_UNSPECIFIED; argc = setup_revisions(argc, argv, &revs, NULL); + quiet = DIFF_OPT_TST(&revs.diffopt, QUIET); for (i = 1 ; i < argc; i++) { const char *arg = argv[i]; @@ -621,10 +622,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) read_revisions_from_stdin(&revs); continue; } - if (!strcmp(arg, "--quiet")) { - quiet = 1; - continue; - } usage(rev_list_usage); } diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c index a7860ed75..aa71f4a4f 100644 --- a/builtin-rev-parse.c +++ b/builtin-rev-parse.c @@ -268,7 +268,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) { static int keep_dashdash = 0; static char const * const parseopt_usage[] = { - "git-rev-parse --parseopt [options] -- [<args>...]", + "git rev-parse --parseopt [options] -- [<args>...]", NULL }; static struct option parseopt_opts[] = { diff --git a/builtin-revert.c b/builtin-revert.c index f3d452418..e9da870d2 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -24,12 +24,12 @@ */ static const char * const revert_usage[] = { - "git-revert [options] <commit-ish>", + "git revert [options] <commit-ish>", NULL }; static const char * const cherry_pick_usage[] = { - "git-cherry-pick [options] <commit-ish>", + "git cherry-pick [options] <commit-ish>", NULL }; diff --git a/builtin-rm.c b/builtin-rm.c index 22c9bd1c6..ee8247b08 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -11,7 +11,7 @@ #include "parse-options.h" static const char * const builtin_rm_usage[] = { - "git-rm [options] [--] <file>...", + "git rm [options] [--] <file>...", NULL }; @@ -146,11 +146,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix) git_config(git_default_config, NULL); - newfd = hold_locked_index(&lock_file, 1); - - if (read_cache() < 0) - die("index file corrupt"); - argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0); if (!argc) usage_with_options(builtin_rm_usage, builtin_rm_options); @@ -158,6 +153,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix) if (!index_only) setup_work_tree(); + newfd = hold_locked_index(&lock_file, 1); + + if (read_cache() < 0) + die("index file corrupt"); + pathspec = get_pathspec(prefix, argv); seen = NULL; for (i = 0; pathspec[i] ; i++) diff --git a/builtin-send-pack.c b/builtin-send-pack.c index a708d0af4..7588d2288 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -8,7 +8,7 @@ #include "send-pack.h" static const char send_pack_usage[] = -"git-send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n" +"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n" " --all and explicit <ref> specification are mutually exclusive."; static struct send_pack_args args = { diff --git a/builtin-shortlog.c b/builtin-shortlog.c index f8bcbfce4..94c472385 100644 --- a/builtin-shortlog.c +++ b/builtin-shortlog.c @@ -10,7 +10,7 @@ #include "parse-options.h" static char const * const shortlog_usage[] = { - "git-shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]", + "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]", "", "[rev-opts] are documented in git-rev-list(1)", NULL diff --git a/builtin-show-branch.c b/builtin-show-branch.c index 93047f511..233eed499 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -4,7 +4,7 @@ #include "builtin.h" static const char show_branch_usage[] = -"git-show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>"; +"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>"; static const char show_branch_usage_reflog[] = "--reflog is incompatible with --all, --remotes, --independent or --merge-base"; diff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c index b49bdb690..bfc78bb3f 100644 --- a/builtin-symbolic-ref.c +++ b/builtin-symbolic-ref.c @@ -4,7 +4,7 @@ #include "parse-options.h" static const char * const git_symbolic_ref_usage[] = { - "git-symbolic-ref [options] name [ref]", + "git symbolic-ref [options] name [ref]", NULL }; diff --git a/builtin-tag.c b/builtin-tag.c index a70922b21..c2cca6cb6 100644 --- a/builtin-tag.c +++ b/builtin-tag.c @@ -14,10 +14,10 @@ #include "parse-options.h" static const char * const git_tag_usage[] = { - "git-tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]", - "git-tag -d <tagname>...", - "git-tag -l [-n[<num>]] [<pattern>]", - "git-tag -v <tagname>...", + "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]", + "git tag -d <tagname>...", + "git tag -l [-n[<num>]] [<pattern>]", + "git tag -v <tagname>...", NULL }; diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index b04719ef2..f4bea4a32 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -8,7 +8,7 @@ #include "quote.h" static const char tar_tree_usage[] = -"git-tar-tree [--remote=<repo>] <tree-ish> [basedir]\n" +"git tar-tree [--remote=<repo>] <tree-ish> [basedir]\n" "*** Note that this command is now deprecated; use git-archive instead."; int cmd_tar_tree(int argc, const char **argv, const char *prefix) diff --git a/builtin-update-index.c b/builtin-update-index.c index 9e0d7ab11..38eb53ccb 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -387,7 +387,7 @@ static void read_index_info(int line_termination) } static const char update_index_usage[] = -"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>..."; +"git update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>..."; static unsigned char head_sha1[20]; static unsigned char merge_head_sha1[20]; diff --git a/builtin-update-ref.c b/builtin-update-ref.c index d90d11d2e..56a0b1b39 100644 --- a/builtin-update-ref.c +++ b/builtin-update-ref.c @@ -4,8 +4,8 @@ #include "parse-options.h" static const char * const git_update_ref_usage[] = { - "git-update-ref [options] -d <refname> [<oldval>]", - "git-update-ref [options] <refname> <newval> [<oldval>]", + "git update-ref [options] -d <refname> [<oldval>]", + "git update-ref [options] <refname> <newval> [<oldval>]", NULL }; diff --git a/builtin-upload-archive.c b/builtin-upload-archive.c index 371400d49..13a6c6203 100644 --- a/builtin-upload-archive.c +++ b/builtin-upload-archive.c @@ -8,18 +8,19 @@ #include "sideband.h" static const char upload_archive_usage[] = - "git-upload-archive <repo>"; + "git upload-archive <repo>"; static const char deadchild[] = -"git-upload-archive: archiver died with error"; +"git upload-archive: archiver died with error"; static const char lostchild[] = -"git-upload-archive: archiver process was lost"; +"git upload-archive: archiver process was lost"; static int run_upload_archive(int argc, const char **argv, const char *prefix) { - struct archiver ar; + const struct archiver *ar; + struct archiver_args args; const char *sent_argv[MAX_ARGS]; const char *arg_cmd = "argument "; char *p, buf[4096]; @@ -65,12 +66,12 @@ static int run_upload_archive(int argc, const char **argv, const char *prefix) sent_argv[sent_argc] = NULL; /* parse all options sent by the client */ - treeish_idx = parse_archive_args(sent_argc, sent_argv, &ar); + treeish_idx = parse_archive_args(sent_argc, sent_argv, &ar, &args); - parse_treeish_arg(sent_argv + treeish_idx, &ar.args, prefix); - parse_pathspec_arg(sent_argv + treeish_idx + 1, &ar.args); + parse_treeish_arg(sent_argv + treeish_idx, &args, prefix); + parse_pathspec_arg(sent_argv + treeish_idx + 1, &args); - return ar.write_archive(&ar.args); + return ar->write_archive(&args); } static void error_clnt(const char *fmt, ...) diff --git a/builtin-verify-tag.c b/builtin-verify-tag.c index 92eaa89a4..7d837f0f9 100644 --- a/builtin-verify-tag.c +++ b/builtin-verify-tag.c @@ -12,7 +12,7 @@ #include <signal.h> static const char builtin_verify_tag_usage[] = - "git-verify-tag [-v|--verbose] <tag>..."; + "git verify-tag [-v|--verbose] <tag>..."; #define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----" diff --git a/builtin-write-tree.c b/builtin-write-tree.c index c21879974..52a3c015f 100644 --- a/builtin-write-tree.c +++ b/builtin-write-tree.c @@ -9,7 +9,7 @@ #include "cache-tree.h" static const char write_tree_usage[] = -"git-write-tree [--missing-ok] [--prefix=<prefix>/]"; +"git write-tree [--missing-ok] [--prefix=<prefix>/]"; int cmd_write_tree(int argc, const char **argv, const char *unused_prefix) { diff --git a/cache-tree.c b/cache-tree.c index 73cb34070..5f8ee87bb 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -507,7 +507,7 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size) return read_one(&buffer, &size); } -struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path) +static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path) { while (*path) { const char *slash; diff --git a/cache-tree.h b/cache-tree.h index 44aad426d..cf8b79087 100644 --- a/cache-tree.h +++ b/cache-tree.h @@ -28,8 +28,6 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size); int cache_tree_fully_valid(struct cache_tree *); int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int, int); -struct cache_tree *cache_tree_find(struct cache_tree *, const char *); - #define WRITE_TREE_UNREADABLE_INDEX (-1) #define WRITE_TREE_UNMERGED_INDEX (-2) #define WRITE_TREE_PREFIX_ERROR (-3) @@ -397,7 +397,8 @@ extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st); #define REFRESH_UNMERGED 0x0002 /* allow unmerged */ #define REFRESH_QUIET 0x0004 /* be quiet about it */ #define REFRESH_IGNORE_MISSING 0x0008 /* ignore non-existent */ -#define REFRESH_IGNORE_SUBMODULES 0x0008 /* ignore submodules */ +#define REFRESH_IGNORE_SUBMODULES 0x0010 /* ignore submodules */ +#define REFRESH_SAY_CHANGED 0x0020 /* say "changed" not "needs update" */ extern int refresh_index(struct index_state *, unsigned int flags, const char **pathspec, char *seen); struct lock_file { diff --git a/compat/mingw.c b/compat/mingw.c index c0bc849e4..772cad510 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -536,7 +536,8 @@ static char *lookup_prog(const char *dir, const char *cmd, int isexe, int exe_on return xstrdup(path); path[strlen(path)-4] = '\0'; if ((!exe_only || isexe) && access(path, F_OK) == 0) - return xstrdup(path); + if (!(GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY)) + return xstrdup(path); return NULL; } diff --git a/compat/mingw.h b/compat/mingw.h index 5a3bcee29..8ffec51e7 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -194,6 +194,17 @@ sig_handler_t mingw_signal(int sig, sig_handler_t handler); #define signal mingw_signal /* + * ANSI emulation wrappers + */ + +int winansi_fputs(const char *str, FILE *stream); +int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2))); +int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3))); +#define fputs winansi_fputs +#define printf(...) winansi_printf(__VA_ARGS__) +#define fprintf(...) winansi_fprintf(__VA_ARGS__) + +/* * git specific compatibility */ diff --git a/compat/winansi.c b/compat/winansi.c new file mode 100644 index 000000000..e2d96dfe6 --- /dev/null +++ b/compat/winansi.c @@ -0,0 +1,345 @@ +/* + * Copyright 2008 Peter Harris <git@peter.is-a-geek.org> + */ + +#include <windows.h> +#include "../git-compat-util.h" + +/* + Functions to be wrapped: +*/ +#undef printf +#undef fprintf +#undef fputs +/* TODO: write */ + +/* + ANSI codes used by git: m, K + + This file is git-specific. Therefore, this file does not attempt + to implement any codes that are not used by git. + + TODO: K +*/ + +static HANDLE console; +static WORD plain_attr; +static WORD attr; +static int negative; + +static void init(void) +{ + CONSOLE_SCREEN_BUFFER_INFO sbi; + + static int initialized = 0; + if (initialized) + return; + + console = GetStdHandle(STD_OUTPUT_HANDLE); + if (console == INVALID_HANDLE_VALUE) + console = NULL; + + if (!console) + return; + + GetConsoleScreenBufferInfo(console, &sbi); + attr = plain_attr = sbi.wAttributes; + negative = 0; + + initialized = 1; +} + + +#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) +#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) + +static void set_console_attr(void) +{ + WORD attributes = attr; + if (negative) { + attributes &= ~FOREGROUND_ALL; + attributes &= ~BACKGROUND_ALL; + + /* This could probably use a bitmask + instead of a series of ifs */ + if (attr & FOREGROUND_RED) + attributes |= BACKGROUND_RED; + if (attr & FOREGROUND_GREEN) + attributes |= BACKGROUND_GREEN; + if (attr & FOREGROUND_BLUE) + attributes |= BACKGROUND_BLUE; + + if (attr & BACKGROUND_RED) + attributes |= FOREGROUND_RED; + if (attr & BACKGROUND_GREEN) + attributes |= FOREGROUND_GREEN; + if (attr & BACKGROUND_BLUE) + attributes |= FOREGROUND_BLUE; + } + SetConsoleTextAttribute(console, attributes); +} + +static const char *set_attr(const char *str) +{ + const char *func; + size_t len = strspn(str, "0123456789;"); + func = str + len; + + switch (*func) { + case 'm': + do { + long val = strtol(str, (char **)&str, 10); + switch (val) { + case 0: /* reset */ + attr = plain_attr; + negative = 0; + break; + case 1: /* bold */ + attr |= FOREGROUND_INTENSITY; + break; + case 2: /* faint */ + case 22: /* normal */ + attr &= ~FOREGROUND_INTENSITY; + break; + case 3: /* italic */ + /* Unsupported */ + break; + case 4: /* underline */ + case 21: /* double underline */ + /* Wikipedia says this flag does nothing */ + /* Furthermore, mingw doesn't define this flag + attr |= COMMON_LVB_UNDERSCORE; */ + break; + case 24: /* no underline */ + /* attr &= ~COMMON_LVB_UNDERSCORE; */ + break; + case 5: /* slow blink */ + case 6: /* fast blink */ + /* We don't have blink, but we do have + background intensity */ + attr |= BACKGROUND_INTENSITY; + break; + case 25: /* no blink */ + attr &= ~BACKGROUND_INTENSITY; + break; + case 7: /* negative */ + negative = 1; + break; + case 27: /* positive */ + negative = 0; + break; + case 8: /* conceal */ + case 28: /* reveal */ + /* Unsupported */ + break; + case 30: /* Black */ + attr &= ~FOREGROUND_ALL; + break; + case 31: /* Red */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_RED; + break; + case 32: /* Green */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_GREEN; + break; + case 33: /* Yellow */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_RED | FOREGROUND_GREEN; + break; + case 34: /* Blue */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_BLUE; + break; + case 35: /* Magenta */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_RED | FOREGROUND_BLUE; + break; + case 36: /* Cyan */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_GREEN | FOREGROUND_BLUE; + break; + case 37: /* White */ + attr |= FOREGROUND_RED | + FOREGROUND_GREEN | + FOREGROUND_BLUE; + break; + case 38: /* Unknown */ + break; + case 39: /* reset */ + attr &= ~FOREGROUND_ALL; + attr |= (plain_attr & FOREGROUND_ALL); + break; + case 40: /* Black */ + attr &= ~BACKGROUND_ALL; + break; + case 41: /* Red */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_RED; + break; + case 42: /* Green */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_GREEN; + break; + case 43: /* Yellow */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_RED | BACKGROUND_GREEN; + break; + case 44: /* Blue */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_BLUE; + break; + case 45: /* Magenta */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_RED | BACKGROUND_BLUE; + break; + case 46: /* Cyan */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_GREEN | BACKGROUND_BLUE; + break; + case 47: /* White */ + attr |= BACKGROUND_RED | + BACKGROUND_GREEN | + BACKGROUND_BLUE; + break; + case 48: /* Unknown */ + break; + case 49: /* reset */ + attr &= ~BACKGROUND_ALL; + attr |= (plain_attr & BACKGROUND_ALL); + break; + default: + /* Unsupported code */ + break; + } + str++; + } while (*(str-1) == ';'); + + set_console_attr(); + break; + case 'K': + /* TODO */ + break; + default: + /* Unsupported code */ + break; + } + + return func + 1; +} + +static int ansi_emulate(const char *str, FILE *stream) +{ + int rv = 0; + const char *pos = str; + + while (*pos) { + pos = strstr(str, "\033["); + if (pos) { + size_t len = pos - str; + + if (len) { + size_t out_len = fwrite(str, 1, len, stream); + rv += out_len; + if (out_len < len) + return rv; + } + + str = pos + 2; + rv += 2; + + fflush(stream); + + pos = set_attr(str); + rv += pos - str; + str = pos; + } else { + rv += strlen(str); + fputs(str, stream); + return rv; + } + } + return rv; +} + +int winansi_fputs(const char *str, FILE *stream) +{ + int rv; + + if (!isatty(fileno(stream))) + return fputs(str, stream); + + init(); + + if (!console) + return fputs(str, stream); + + rv = ansi_emulate(str, stream); + + if (rv >= 0) + return 0; + else + return EOF; +} + +static int winansi_vfprintf(FILE *stream, const char *format, va_list list) +{ + int len, rv; + char small_buf[256]; + char *buf = small_buf; + va_list cp; + + if (!isatty(fileno(stream))) + goto abort; + + init(); + + if (!console) + goto abort; + + va_copy(cp, list); + len = vsnprintf(small_buf, sizeof(small_buf), format, cp); + va_end(cp); + + if (len > sizeof(small_buf) - 1) { + buf = malloc(len + 1); + if (!buf) + goto abort; + + len = vsnprintf(buf, len + 1, format, list); + } + + rv = ansi_emulate(buf, stream); + + if (buf != small_buf) + free(buf); + return rv; + +abort: + rv = vfprintf(stream, format, list); + return rv; +} + +int winansi_fprintf(FILE *stream, const char *format, ...) +{ + va_list list; + int rv; + + va_start(list, format); + rv = winansi_vfprintf(stream, format, list); + va_end(list); + + return rv; +} + +int winansi_printf(const char *format, ...) +{ + va_list list; + int rv; + + va_start(list, format); + rv = winansi_vfprintf(stdout, format, list); + va_end(list); + + return rv; +} diff --git a/contrib/examples/git-merge.sh b/contrib/examples/git-merge.sh index 8026ccff4..e9588eec3 100755 --- a/contrib/examples/git-merge.sh +++ b/contrib/examples/git-merge.sh @@ -5,8 +5,8 @@ OPTIONS_KEEPDASHDASH= OPTIONS_SPEC="\ -git-merge [options] <remote>... -git-merge [options] <msg> HEAD <remote> +git merge [options] <remote>... +git merge [options] <msg> HEAD <remote> -- stat show a diffstat at the end of the merge n don't show a diffstat at the end of the merge @@ -18,7 +18,7 @@ static int verbose; static int reuseaddr; static const char daemon_usage[] = -"git-daemon [--verbose] [--syslog] [--export-all]\n" +"git daemon [--verbose] [--syslog] [--export-all]\n" " [--timeout=n] [--init-timeout=n] [--strict-paths]\n" " [--base-path=path] [--base-path-relaxed]\n" " [--user-path | --user-path=path]\n" diff --git a/diff-lib.c b/diff-lib.c index b17722d66..e7eaff9a6 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -171,7 +171,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) if (silent_on_removed) continue; diff_addremove(&revs->diffopt, '-', ce->ce_mode, - ce->sha1, ce->name, NULL); + ce->sha1, ce->name); continue; } changed = ce_match_stat(ce, &st, ce_option); @@ -184,7 +184,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) newmode = ce_mode_from_stat(ce, st.st_mode); diff_change(&revs->diffopt, oldmode, newmode, ce->sha1, (changed ? null_sha1 : ce->sha1), - ce->name, NULL); + ce->name); } diffcore_std(&revs->diffopt); @@ -208,7 +208,7 @@ static void diff_index_show_file(struct rev_info *revs, const unsigned char *sha1, unsigned int mode) { diff_addremove(&revs->diffopt, prefix[0], mode, - sha1, ce->name, NULL); + sha1, ce->name); } static int get_stat_data(struct cache_entry *ce, @@ -312,7 +312,7 @@ static int show_modified(struct oneway_unpack_data *cbdata, return 0; diff_change(&revs->diffopt, oldmode, mode, - old->sha1, sha1, old->name, NULL); + old->sha1, sha1, old->name); return 0; } @@ -3412,9 +3412,8 @@ int diff_result_code(struct diff_options *opt, int status) void diff_addremove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, - const char *base, const char *path) + const char *concatpath) { - char concatpath[PATH_MAX]; struct diff_filespec *one, *two; if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode)) @@ -3436,9 +3435,6 @@ void diff_addremove(struct diff_options *options, addremove = (addremove == '+' ? '-' : addremove == '-' ? '+' : addremove); - if (!path) path = ""; - sprintf(concatpath, "%s%s", base, path); - if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) return; @@ -3459,9 +3455,8 @@ void diff_change(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *base, const char *path) + const char *concatpath) { - char concatpath[PATH_MAX]; struct diff_filespec *one, *two; if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode) @@ -3474,8 +3469,6 @@ void diff_change(struct diff_options *options, tmp = old_mode; old_mode = new_mode; new_mode = tmp; tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c; } - if (!path) path = ""; - sprintf(concatpath, "%s%s", base, path); if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) @@ -14,12 +14,12 @@ typedef void (*change_fn_t)(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *base, const char *path); + const char *fullpath); typedef void (*add_remove_fn_t)(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, - const char *base, const char *path); + const char *fullpath); typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, struct diff_options *options, void *data); @@ -164,14 +164,13 @@ extern void diff_addremove(struct diff_options *, int addremove, unsigned mode, const unsigned char *sha1, - const char *base, - const char *path); + const char *fullpath); extern void diff_change(struct diff_options *, unsigned mode1, unsigned mode2, const unsigned char *sha1, const unsigned char *sha2, - const char *base, const char *path); + const char *fullpath); extern void diff_unmerge(struct diff_options *, const char *path, diff --git a/fast-import.c b/fast-import.c index e72b28679..7089e6f9e 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1868,6 +1868,7 @@ static void file_change_m(struct branch *b) case S_IFREG | 0644: case S_IFREG | 0755: case S_IFLNK: + case S_IFGITLINK: case 0644: case 0755: /* ok */ @@ -1900,7 +1901,20 @@ static void file_change_m(struct branch *b) p = uq.buf; } - if (inline_data) { + if (S_ISGITLINK(mode)) { + if (inline_data) + die("Git links cannot be specified 'inline': %s", + command_buf.buf); + else if (oe) { + if (oe->type != OBJ_COMMIT) + die("Not a commit (actually a %s): %s", + typename(oe->type), command_buf.buf); + } + /* + * Accept the sha1 without checking; it expected to be in + * another repository. + */ + } else if (inline_data) { static struct strbuf buf = STRBUF_INIT; if (p != uq.buf) { @@ -2374,7 +2388,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) } static const char fast_import_usage[] = -"git-fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]"; +"git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]"; int main(int argc, const char **argv) { diff --git a/fixup-builtins b/fixup-builtins index 49e861d2a..63dfa4c47 100755 --- a/fixup-builtins +++ b/fixup-builtins @@ -1,16 +1,16 @@ #!/bin/sh while [ "$1" ] do - old="$1" - new=$(echo "$1" | sed 's/git-/git /') - echo "Converting '$old' to '$new'" - git ls-files '*.sh' | while read file - do - sed "s/\\<$old\\>/$new/g" < $file > $file.new - chmod --reference=$file $file.new - mv $file.new $file - done + if [ "$1" != "git-sh-setup" -a "$1" != "git-parse-remote" -a "$1" != "git-svn" ]; then + old="$1" + new=$(echo "$1" | sed 's/git-/git /') + echo "Converting '$old' to '$new'" + sed -i "s/\\<$old\\>/$new/g" $(git ls-files '*.sh') + fi shift done + +sed -i 's/git merge-one-file/git-merge-one-file/g +s/git rebase-todo/git-rebase-todo/g' $(git ls-files '*.sh') git update-index --refresh >& /dev/null exit 0 @@ -5,9 +5,9 @@ SUBDIRECTORY_OK=Yes OPTIONS_KEEPDASHDASH= OPTIONS_SPEC="\ -git-am [options] [<mbox>|<Maildir>...] -git-am [options] --resolved -git-am [options] --skip +git am [options] [<mbox>|<Maildir>...] +git am [options] --resolved +git am [options] --skip -- d,dotest= (removed -- do not use) i,interactive run interactively @@ -22,6 +22,7 @@ p= pass it through git-apply resolvemsg= override error message when patch failure occurs r,resolved to be used after a patch failure skip skip the current patch +abort restore the original branch and abort the patching operation. rebasing (internal use for git-rebase)" . git-sh-setup @@ -54,6 +55,7 @@ stop_here_user_resolve () { fi echo "When you have resolved this problem run \"$cmdline --resolved\"." echo "If you would prefer to skip this patch, instead run \"$cmdline --skip\"." + echo "To restore the original branch and stop patching run \"$cmdline --abort\"." stop_here $1 } @@ -120,7 +122,7 @@ It does not apply to blobs recorded in its index." prec=4 dotest="$GIT_DIR/rebase" -sign= utf8=t keep= skip= interactive= resolved= binary= rebasing= +sign= utf8=t keep= skip= interactive= resolved= binary= rebasing= abort= resolvemsg= resume= git_apply_opt= @@ -145,6 +147,8 @@ do resolved=t ;; --skip) skip=t ;; + --abort) + abort=t ;; --rebasing) rebasing=t threeway=t keep=t binary=t ;; -d|--dotest) @@ -177,7 +181,7 @@ fi if test -d "$dotest" then - case "$#,$skip$resolved" in + case "$#,$skip$resolved$abort" in 0,*t*) # Explicit resume command and we do not have file, so # we are happy. @@ -197,9 +201,18 @@ then esac || die "previous rebase directory $dotest still exists but mbox given." resume=yes + + case "$abort" in + t) + git rerere clear + git read-tree --reset -u HEAD ORIG_HEAD + git reset ORIG_HEAD + rm -fr "$dotest" + exit ;; + esac else - # Make sure we are not given --skip nor --resolved - test ",$skip,$resolved," = ,,, || + # Make sure we are not given --skip, --resolved, nor --abort + test "$skip$resolved$abort" = "" || die "Resolve operation not in progress, we are not resuming." # Start afresh. diff --git a/git-archimport.perl b/git-archimport.perl index 9a7a90640..98f3ede56 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -9,7 +9,7 @@ =head1 Invocation - git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] + git archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] [ -D depth] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ] Imports a project from one or more Arch repositories. It will follow branches @@ -74,7 +74,7 @@ our($opt_h,$opt_f,$opt_v,$opt_T,$opt_t,$opt_D,$opt_a,$opt_o); sub usage() { print STDERR <<END; -Usage: ${\basename $0} # fetch/update GIT from Arch +Usage: git archimport # fetch/update GIT from Arch [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] [ -D depth ] [ -t tempdir ] repository/arch-branch [ repository/arch-branch] ... END diff --git a/git-bisect.sh b/git-bisect.sh index 991b2ef37..3cac20db7 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -149,7 +149,7 @@ bisect_start() { echo "$start_head" >"$GIT_DIR/BISECT_START" && sq "$@" >"$GIT_DIR/BISECT_NAMES" && eval "$eval" && - echo "git-bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit + echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit # # Check if we can proceed to the next bisect state. # @@ -169,7 +169,7 @@ bisect_write() { esac git update-ref "refs/bisect/$tag" "$rev" || exit echo "# $state: $(git show-branch $rev)" >>"$GIT_DIR/BISECT_LOG" - test -n "$nolog" || echo "git-bisect $state $rev" >>"$GIT_DIR/BISECT_LOG" + test -n "$nolog" || echo "git bisect $state $rev" >>"$GIT_DIR/BISECT_LOG" } bisect_state() { @@ -426,9 +426,13 @@ bisect_clean_state() { bisect_replay () { test -r "$1" || die "cannot read $1 for replaying" bisect_reset - while read bisect command rev + while read git bisect command rev do - test "$bisect" = "git-bisect" || continue + test "$git $bisect" = "git bisect" -o "$git" = "git-bisect" || continue + if test "$git" = "git-bisect"; then + rev="$command" + command="$bisect" + fi case "$command" in start) cmd="bisect_start $rev" diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index c6c70e9eb..6d9f0ef0f 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -370,7 +370,7 @@ sleep(1); sub usage { print STDERR <<END; -Usage: GIT_DIR=/path/to/.git ${\basename $0} [-h] [-p] [-v] [-c] [-f] [-u] [-w cvsworkdir] [-m msgprefix] [ parent ] commit +Usage: GIT_DIR=/path/to/.git git cvsexportcommit [-h] [-p] [-v] [-c] [-f] [-u] [-w cvsworkdir] [-m msgprefix] [ parent ] commit END exit(1); } diff --git a/git-cvsimport.perl b/git-cvsimport.perl index cacbfc025..e2664ef01 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -36,7 +36,7 @@ sub usage(;$) { my $msg = shift; print(STDERR "Error: $msg\n") if $msg; print STDERR <<END; -Usage: ${\basename $0} # fetch/update GIT from CVS +Usage: git cvsimport # fetch/update GIT from CVS [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file] [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k] [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit] diff --git a/git-cvsserver.perl b/git-cvsserver.perl index 920bbe15a..b0a805c68 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -101,7 +101,7 @@ my $work = $log->info("--------------- STARTING -----------------"); my $usage = - "Usage: git-cvsserver [options] [pserver|server] [<directory> ...]\n". + "Usage: git cvsserver [options] [pserver|server] [<directory> ...]\n". " --base-path <path> : Prepend to requested CVSROOT\n". " --strict-paths : Don't allow recursing into subdirectories\n". " --export-all : Don't check for gitcvs.enabled in config\n". @@ -801,6 +801,18 @@ sub req_co argsplit("co"); + # Provide list of modules, if -c was used. + if (exists $state->{opt}{c}) { + my $showref = `git show-ref --heads`; + for my $line (split '\n', $showref) { + if ( $line =~ m% refs/heads/(.*)$% ) { + print "M $1\t$1\n"; + } + } + print "ok\n"; + return 1; + } + my $module = $state->{args}[0]; $state->{module} = $module; my $checkout_path = $module; @@ -947,21 +959,15 @@ sub req_update # projects (heads in this case) to checkout. # if ($state->{module} eq '') { - my $heads_dir = $state->{CVSROOT} . '/refs/heads'; - if (!opendir HEADS, $heads_dir) { - print "E [server aborted]: Failed to open directory, " - . "$heads_dir: $!\nerror\n"; - return 0; - } + my $showref = `git show-ref --heads`; print "E cvs update: Updating .\n"; - while (my $head = readdir(HEADS)) { - if (-f $state->{CVSROOT} . '/refs/heads/' . $head) { - print "E cvs update: New directory `$head'\n"; - } - } - closedir HEADS; - print "ok\n"; - return 1; + for my $line (split '\n', $showref) { + if ( $line =~ m% refs/heads/(.*)$% ) { + print "E cvs update: New directory `$1'\n"; + } + } + print "ok\n"; + return 1; } @@ -1884,7 +1890,7 @@ sub req_annotate } # done; get out of the tempdir - cleanupWorkDir(); + cleanupWorkTree(); print "ok\n"; diff --git a/git-instaweb.sh b/git-instaweb.sh index af0fde538..0843372b5 100755 --- a/git-instaweb.sh +++ b/git-instaweb.sh @@ -6,7 +6,7 @@ PERL='@@PERL@@' OPTIONS_KEEPDASHDASH= OPTIONS_SPEC="\ -git-instaweb [options] (--start | --stop | --restart) +git instaweb [options] (--start | --stop | --restart) -- l,local only bind on 127.0.0.1 p,port= the port to bind to diff --git a/git-pull.sh b/git-pull.sh index 809e537a4..6afd4e2f4 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -121,7 +121,7 @@ test true = "$rebase" && { "refs/remotes/$origin/$reflist" 2>/dev/null)" } orig_head=$(git rev-parse --verify HEAD 2>/dev/null) -git-fetch --update-head-ok "$@" || exit 1 +git fetch --update-head-ok "$@" || exit 1 curr_head=$(git rev-parse --verify HEAD 2>/dev/null) if test "$curr_head" != "$orig_head" diff --git a/git-quiltimport.sh b/git-quiltimport.sh index d1efa1d74..c9aecfd91 100755 --- a/git-quiltimport.sh +++ b/git-quiltimport.sh @@ -1,7 +1,7 @@ #!/bin/sh OPTIONS_KEEPDASHDASH= OPTIONS_SPEC="\ -git-quiltimport [options] +git quiltimport [options] -- n,dry-run dry run author= author name and email address for patches without any diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index da79a2456..e63a864c7 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -174,6 +174,8 @@ pick_one_preserving_merges () { new_parents="$new_parents $new_p" ;; esac + else + new_parents="$new_parents $p" fi done case $fast_forward in diff --git a/git-rebase.sh b/git-rebase.sh index 56cf6f031..6ef575481 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -376,8 +376,7 @@ fi # Detach HEAD and reset the tree echo "First, rewinding head to replay your work on top of it..." -git checkout "$onto^0" >/dev/null 2>&1 || - die "could not detach HEAD" +git checkout -q "$onto^0" || die "could not detach HEAD" git update-ref ORIG_HEAD $branch # If the $onto is a proper descendant of the tip of the branch, then diff --git a/git-relink.perl b/git-relink.perl index 15fb93202..937c69a74 100755 --- a/git-relink.perl +++ b/git-relink.perl @@ -163,7 +163,7 @@ sub link_two_files($$) { sub usage() { - print("Usage: $0 [--safe] <dir> [<dir> ...] <master_dir> \n"); + print("Usage: git relink [--safe] <dir> [<dir> ...] <master_dir> \n"); print("All directories should contain a .git/objects/ subdirectory.\n"); print("Options\n"); print("\t--safe\t" . diff --git a/git-repack.sh b/git-repack.sh index 8c3bc134a..683960b04 100755 --- a/git-repack.sh +++ b/git-repack.sh @@ -5,7 +5,7 @@ OPTIONS_KEEPDASHDASH= OPTIONS_SPEC="\ -git-repack [options] +git repack [options] -- a pack everything in a single pack A same as -a, and turn unreachable objects loose diff --git a/git-send-email.perl b/git-send-email.perl index 6adb66947..2e4a44ad2 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -38,7 +38,7 @@ package main; sub usage { print <<EOT; -git-send-email [options] <file | directory>... +git send-email [options] <file | directory>... Options: --from Specify the "From:" line of the email to be sent. diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 9cceb21a8..dbdf209ec 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -32,15 +32,16 @@ if test -n "$OPTIONS_SPEC"; then echo exit $? )" else + dashless=$(basename "$0" | sed -e 's/-/ /') usage() { - die "Usage: $0 $USAGE" + die "Usage: $dashless $USAGE" } if [ -z "$LONG_USAGE" ] then - LONG_USAGE="Usage: $0 $USAGE" + LONG_USAGE="Usage: $dashless $USAGE" else - LONG_USAGE="Usage: $0 $USAGE + LONG_USAGE="Usage: $dashless $USAGE $LONG_USAGE" fi diff --git a/git-svn.perl b/git-svn.perl index 3750e47c2..2e0e55242 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -261,7 +261,7 @@ sub usage { my $fd = $exit ? \*STDERR : \*STDOUT; print $fd <<""; git-svn - bidirectional operations between a single Subversion tree and git -Usage: $0 <command> [options] [arguments]\n +Usage: git svn <command> [options] [arguments]\n print $fd "Available commands:\n" unless $cmd; @@ -1226,7 +1226,7 @@ sub linearize_history { sub find_file_type_and_diff_status { my ($path) = @_; - return ('dir', '') if $path eq '.'; + return ('dir', '') if $path eq ''; my $diff_output = command_oneline(qw(diff --cached --name-status --), $path) || ""; diff --git a/hash-object.c b/hash-object.c index 48d522368..46c06a955 100644 --- a/hash-object.c +++ b/hash-object.c @@ -52,7 +52,7 @@ static void hash_stdin_paths(const char *type, int write_objects) } static const char hash_object_usage[] = -"git-hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]"; +"git hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]"; int main(int argc, char **argv) { @@ -40,7 +40,7 @@ static struct option builtin_help_options[] = { }; static const char * const builtin_help_usage[] = { - "git-help [--all] [--man|--web|--info] [command]", + "git help [--all] [--man|--web|--info] [command]", NULL }; diff --git a/http-push.c b/http-push.c index 2cd068a6f..680528885 100644 --- a/http-push.c +++ b/http-push.c @@ -14,7 +14,7 @@ #include <expat.h> static const char http_push_usage[] = -"git-http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n"; +"git http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n"; #ifndef XML_STATUS_OK enum XML_Status { diff --git a/http-walker.c b/http-walker.c index 51c18f268..9dc6b27b4 100644 --- a/http-walker.c +++ b/http-walker.c @@ -442,6 +442,8 @@ static int setup_index(struct walker *walker, struct alt_base *repo, unsigned ch return -1; new_pack = parse_pack_index(sha1); + if (!new_pack) + return -1; /* parse_pack_index() already issued error message */ new_pack->next = repo->packs; repo->packs = new_pack; return 0; diff --git a/index-pack.c b/index-pack.c index 25db5db24..ac20a46d1 100644 --- a/index-pack.c +++ b/index-pack.c @@ -10,7 +10,7 @@ #include "fsck.h" static const char index_pack_usage[] = -"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }"; +"git index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }"; struct object_entry { @@ -26,6 +26,14 @@ union delta_base { off_t offset; }; +struct base_data { + struct base_data *base; + struct base_data *child; + struct object_entry *obj; + void *data; + unsigned long size; +}; + /* * Even if sizeof(union delta_base) == 24 on 64-bit archs, we really want * to memcmp() only the first 20 bytes. @@ -43,6 +51,8 @@ struct delta_entry static struct object_entry *objects; static struct delta_entry *deltas; +static struct base_data *base_cache; +static size_t base_cache_used; static int nr_objects; static int nr_deltas; static int nr_resolved_deltas; @@ -211,6 +221,46 @@ static void bad_object(unsigned long offset, const char *format, ...) die("pack has bad object at offset %lu: %s", offset, buf); } +static void prune_base_data(struct base_data *retain) +{ + struct base_data *b = base_cache; + for (b = base_cache; + base_cache_used > delta_base_cache_limit && b; + b = b->child) { + if (b->data && b != retain) { + free(b->data); + b->data = NULL; + base_cache_used -= b->size; + } + } +} + +static void link_base_data(struct base_data *base, struct base_data *c) +{ + if (base) + base->child = c; + else + base_cache = c; + + c->base = base; + c->child = NULL; + base_cache_used += c->size; + prune_base_data(c); +} + +static void unlink_base_data(struct base_data *c) +{ + struct base_data *base = c->base; + if (base) + base->child = NULL; + else + base_cache = NULL; + if (c->data) { + free(c->data); + base_cache_used -= c->size; + } +} + static void *unpack_entry_data(unsigned long offset, unsigned long size) { z_stream stream; @@ -426,33 +476,60 @@ static void sha1_object(const void *data, unsigned long size, } } -static void resolve_delta(struct object_entry *delta_obj, void *base_data, - unsigned long base_size, enum object_type type) +static void *get_base_data(struct base_data *c) +{ + if (!c->data) { + struct object_entry *obj = c->obj; + + if (obj->type == OBJ_REF_DELTA || obj->type == OBJ_OFS_DELTA) { + void *base = get_base_data(c->base); + void *raw = get_data_from_pack(obj); + c->data = patch_delta( + base, c->base->size, + raw, obj->size, + &c->size); + free(raw); + if (!c->data) + bad_object(obj->idx.offset, "failed to apply delta"); + } else + c->data = get_data_from_pack(obj); + + base_cache_used += c->size; + prune_base_data(c); + } + return c->data; +} + +static void resolve_delta(struct object_entry *delta_obj, + struct base_data *base_obj, enum object_type type) { void *delta_data; unsigned long delta_size; - void *result; - unsigned long result_size; union delta_base delta_base; int j, first, last; + struct base_data result; delta_obj->real_type = type; delta_data = get_data_from_pack(delta_obj); delta_size = delta_obj->size; - result = patch_delta(base_data, base_size, delta_data, delta_size, - &result_size); + result.data = patch_delta(get_base_data(base_obj), base_obj->size, + delta_data, delta_size, + &result.size); free(delta_data); - if (!result) + if (!result.data) bad_object(delta_obj->idx.offset, "failed to apply delta"); - sha1_object(result, result_size, type, delta_obj->idx.sha1); + sha1_object(result.data, result.size, type, delta_obj->idx.sha1); nr_resolved_deltas++; + result.obj = delta_obj; + link_base_data(base_obj, &result); + hashcpy(delta_base.sha1, delta_obj->idx.sha1); if (!find_delta_children(&delta_base, &first, &last)) { for (j = first; j <= last; j++) { struct object_entry *child = objects + deltas[j].obj_no; if (child->real_type == OBJ_REF_DELTA) - resolve_delta(child, result, result_size, type); + resolve_delta(child, &result, type); } } @@ -462,11 +539,11 @@ static void resolve_delta(struct object_entry *delta_obj, void *base_data, for (j = first; j <= last; j++) { struct object_entry *child = objects + deltas[j].obj_no; if (child->real_type == OBJ_OFS_DELTA) - resolve_delta(child, result, result_size, type); + resolve_delta(child, &result, type); } } - free(result); + unlink_base_data(&result); } static int compare_delta_entry(const void *a, const void *b) @@ -481,7 +558,6 @@ static void parse_pack_objects(unsigned char *sha1) { int i; struct delta_entry *delta = deltas; - void *data; struct stat st; /* @@ -496,7 +572,7 @@ static void parse_pack_objects(unsigned char *sha1) nr_objects); for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; - data = unpack_raw_entry(obj, &delta->base); + void *data = unpack_raw_entry(obj, &delta->base); obj->real_type = obj->type; if (obj->type == OBJ_REF_DELTA || obj->type == OBJ_OFS_DELTA) { nr_deltas++; @@ -545,6 +621,7 @@ static void parse_pack_objects(unsigned char *sha1) struct object_entry *obj = &objects[i]; union delta_base base; int j, ref, ref_first, ref_last, ofs, ofs_first, ofs_last; + struct base_data base_obj; if (obj->type == OBJ_REF_DELTA || obj->type == OBJ_OFS_DELTA) continue; @@ -555,22 +632,24 @@ static void parse_pack_objects(unsigned char *sha1) ofs = !find_delta_children(&base, &ofs_first, &ofs_last); if (!ref && !ofs) continue; - data = get_data_from_pack(obj); + base_obj.data = get_data_from_pack(obj); + base_obj.size = obj->size; + base_obj.obj = obj; + link_base_data(NULL, &base_obj); + if (ref) for (j = ref_first; j <= ref_last; j++) { struct object_entry *child = objects + deltas[j].obj_no; if (child->real_type == OBJ_REF_DELTA) - resolve_delta(child, data, - obj->size, obj->type); + resolve_delta(child, &base_obj, obj->type); } if (ofs) for (j = ofs_first; j <= ofs_last; j++) { struct object_entry *child = objects + deltas[j].obj_no; if (child->real_type == OBJ_OFS_DELTA) - resolve_delta(child, data, - obj->size, obj->type); + resolve_delta(child, &base_obj, obj->type); } - free(data); + unlink_base_data(&base_obj); display_progress(progress, nr_resolved_deltas); } } @@ -601,7 +680,8 @@ static int write_compressed(int fd, void *in, unsigned int size, uint32_t *obj_c return size; } -static void append_obj_to_pack(const unsigned char *sha1, void *buf, +static struct object_entry *append_obj_to_pack( + const unsigned char *sha1, void *buf, unsigned long size, enum object_type type) { struct object_entry *obj = &objects[nr_objects++]; @@ -622,6 +702,7 @@ static void append_obj_to_pack(const unsigned char *sha1, void *buf, obj[1].idx.offset = obj[0].idx.offset + n; obj[1].idx.offset += write_compressed(output_fd, buf, size, &obj[0].idx.crc32); hashcpy(obj->idx.sha1, sha1); + return obj; } static int delta_pos_compare(const void *_a, const void *_b) @@ -656,28 +737,31 @@ static void fix_unresolved_deltas(int nr_unresolved) for (i = 0; i < n; i++) { struct delta_entry *d = sorted_by_pos[i]; - void *data; - unsigned long size; enum object_type type; int j, first, last; + struct base_data base_obj; if (objects[d->obj_no].real_type != OBJ_REF_DELTA) continue; - data = read_sha1_file(d->base.sha1, &type, &size); - if (!data) + base_obj.data = read_sha1_file(d->base.sha1, &type, &base_obj.size); + if (!base_obj.data) continue; + if (check_sha1_signature(d->base.sha1, base_obj.data, + base_obj.size, typename(type))) + die("local object %s is corrupt", sha1_to_hex(d->base.sha1)); + base_obj.obj = append_obj_to_pack(d->base.sha1, base_obj.data, + base_obj.size, type); + link_base_data(NULL, &base_obj); + find_delta_children(&d->base, &first, &last); for (j = first; j <= last; j++) { struct object_entry *child = objects + deltas[j].obj_no; if (child->real_type == OBJ_REF_DELTA) - resolve_delta(child, data, size, type); + resolve_delta(child, &base_obj, type); } - if (check_sha1_signature(d->base.sha1, data, size, typename(type))) - die("local object %s is corrupt", sha1_to_hex(d->base.sha1)); - append_obj_to_pack(d->base.sha1, data, size, type); - free(data); + unlink_base_data(&base_obj); display_progress(progress, nr_resolved_deltas); } free(sorted_by_pos); diff --git a/pack-redundant.c b/pack-redundant.c index f5cd0ac59..25b81a445 100644 --- a/pack-redundant.c +++ b/pack-redundant.c @@ -11,7 +11,7 @@ #define BLKSIZE 512 static const char pack_redundant_usage[] = -"git-pack-redundant [ --verbose ] [ --alt-odb ] < --all | <.pack filename> ...>"; +"git pack-redundant [ --verbose ] [ --alt-odb ] < --all | <.pack filename> ...>"; static int load_all_packs, verbose, alt_odb; diff --git a/parse-options.c b/parse-options.c index 2fd5edbf5..987b01571 100644 --- a/parse-options.c +++ b/parse-options.c @@ -214,7 +214,7 @@ is_abbreviated: return -2; } -void check_typos(const char *arg, const struct option *options) +static void check_typos(const char *arg, const struct option *options) { if (strlen(arg) < 3) return; diff --git a/read-cache.c b/read-cache.c index d801f9d1c..a50a85112 100644 --- a/read-cache.c +++ b/read-cache.c @@ -528,7 +528,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, ce = create_alias_ce(ce, alias); ce->ce_flags |= CE_ADDED; - /* It was suspected to be recily clean, but it turns out to be Ok */ + /* It was suspected to be racily clean, but it turns out to be Ok */ was_same = (alias && !ce_stage(alias) && !hashcmp(alias->sha1, ce->sha1) && @@ -980,7 +980,10 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p int not_new = (flags & REFRESH_IGNORE_MISSING) != 0; int ignore_submodules = (flags & REFRESH_IGNORE_SUBMODULES) != 0; unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0; + const char *needs_update_message; + needs_update_message = ((flags & REFRESH_SAY_CHANGED) + ? "locally modified" : "needs update"); for (i = 0; i < istate->cache_nr; i++) { struct cache_entry *ce, *new; int cache_errno = 0; @@ -1019,7 +1022,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p } if (quiet) continue; - printf("%s: needs update\n", ce->name); + printf("%s: %s\n", ce->name, needs_update_message); has_errors = 1; continue; } @@ -278,10 +278,13 @@ static int do_plain_rerere(struct path_list *rr, int fd) if (has_resolution(name)) { if (!merge(name, path)) { - fprintf(stderr, "Resolved '%s' using " - "previous resolution.\n", path); if (rerere_autoupdate) path_list_insert(path, &update); + fprintf(stderr, + "%s '%s' using previous resolution.\n", + rerere_autoupdate + ? "Staged" : "Resolved", + path); goto mark_resolved; } } diff --git a/revision.c b/revision.c index 846af7bd2..3897fec53 100644 --- a/revision.c +++ b/revision.c @@ -260,7 +260,7 @@ static int tree_difference = REV_TREE_SAME; static void file_add_remove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, - const char *base, const char *path) + const char *fullpath) { int diff = REV_TREE_DIFFERENT; @@ -286,7 +286,7 @@ static void file_change(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *base, const char *path) + const char *fullpath) { tree_difference = REV_TREE_DIFFERENT; DIFF_OPT_SET(options, HAS_CHANGES); @@ -60,6 +60,18 @@ void strbuf_grow(struct strbuf *sb, size_t extra) ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); } +void strbuf_trim(struct strbuf *sb) +{ + char *b = sb->buf; + while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1])) + sb->len--; + while (sb->len > 0 && isspace(*b)) { + b++; + sb->len--; + } + memmove(sb->buf, b, sb->len); + sb->buf[sb->len] = '\0'; +} void strbuf_rtrim(struct strbuf *sb) { while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1])) @@ -67,7 +79,65 @@ void strbuf_rtrim(struct strbuf *sb) sb->buf[sb->len] = '\0'; } -int strbuf_cmp(struct strbuf *a, struct strbuf *b) +void strbuf_ltrim(struct strbuf *sb) +{ + char *b = sb->buf; + while (sb->len > 0 && isspace(*b)) { + b++; + sb->len--; + } + memmove(sb->buf, b, sb->len); + sb->buf[sb->len] = '\0'; +} + +void strbuf_tolower(struct strbuf *sb) +{ + int i; + for (i = 0; i < sb->len; i++) + sb->buf[i] = tolower(sb->buf[i]); +} + +struct strbuf **strbuf_split(const struct strbuf *sb, int delim) +{ + int alloc = 2, pos = 0; + char *n, *p; + struct strbuf **ret; + struct strbuf *t; + + ret = xcalloc(alloc, sizeof(struct strbuf *)); + p = n = sb->buf; + while (n < sb->buf + sb->len) { + int len; + n = memchr(n, delim, sb->len - (n - sb->buf)); + if (pos + 1 >= alloc) { + alloc = alloc * 2; + ret = xrealloc(ret, sizeof(struct strbuf *) * alloc); + } + if (!n) + n = sb->buf + sb->len - 1; + len = n - p + 1; + t = xmalloc(sizeof(struct strbuf)); + strbuf_init(t, len); + strbuf_add(t, p, len); + ret[pos] = t; + ret[++pos] = NULL; + p = ++n; + } + return ret; +} + +void strbuf_list_free(struct strbuf **sbs) +{ + struct strbuf **s = sbs; + + while (*s) { + strbuf_release(*s); + free(*s++); + } + free(sbs); +} + +int strbuf_cmp(const struct strbuf *a, const struct strbuf *b) { int cmp; if (a->len < b->len) { @@ -61,7 +61,7 @@ static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) { } /*----- strbuf size related -----*/ -static inline size_t strbuf_avail(struct strbuf *sb) { +static inline size_t strbuf_avail(const struct strbuf *sb) { return sb->alloc ? sb->alloc - sb->len - 1 : 0; } @@ -77,8 +77,14 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) { #define strbuf_reset(sb) strbuf_setlen(sb, 0) /*----- content related -----*/ +extern void strbuf_trim(struct strbuf *); extern void strbuf_rtrim(struct strbuf *); -extern int strbuf_cmp(struct strbuf *, struct strbuf *); +extern void strbuf_ltrim(struct strbuf *); +extern int strbuf_cmp(const struct strbuf *, const struct strbuf *); +extern void strbuf_tolower(struct strbuf *); + +extern struct strbuf **strbuf_split(const struct strbuf *, int delim); +extern void strbuf_list_free(struct strbuf **); /*----- add data in your buffer -----*/ static inline void strbuf_addch(struct strbuf *sb, int c) { @@ -98,7 +104,7 @@ extern void strbuf_add(struct strbuf *, const void *, size_t); static inline void strbuf_addstr(struct strbuf *sb, const char *s) { strbuf_add(sb, s, strlen(s)); } -static inline void strbuf_addbuf(struct strbuf *sb, struct strbuf *sb2) { +static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) { strbuf_add(sb, sb2->buf, sb2->len); } extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len); diff --git a/t/Makefile b/t/Makefile index a778865ae..0d65cedaa 100644 --- a/t/Makefile +++ b/t/Makefile @@ -26,7 +26,7 @@ clean: $(RM) -r 'trash directory' test-results aggregate-results: - ./aggregate-results.sh test-results/t*-* + '$(SHELL_PATH_SQ)' ./aggregate-results.sh test-results/t*-* # we can test NO_OPTIMIZE_COMMITS independently of LC_ALL full-svn-test: diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh index 52e88e304..d5bab75d7 100755 --- a/t/aggregate-results.sh +++ b/t/aggregate-results.sh @@ -10,9 +10,9 @@ for file do while read type value do - case $type in - '') - continue ;; + case $type in + '') + continue ;; fixed) fixed=$(($fixed + $value)) ;; success) @@ -20,9 +20,9 @@ do failed) failed=$(($failed + $value)) ;; broken) - broken=$(( $broken + $value)) ;; + broken=$(($broken + $value)) ;; total) - total=$(( $total + $value)) ;; + total=$(($total + $value)) ;; esac done <"$file" done diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index 5d3bd9dda..a841df2a9 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -98,7 +98,7 @@ LoadModule dav_module $SVN_HTTPD_MODULE_PATH/mod_dav.so LoadModule dav_svn_module $SVN_HTTPD_MODULE_PATH/mod_dav_svn.so <Location /$repo_base_path> DAV svn - SVNPath $rawsvnrepo + SVNPath "$rawsvnrepo" </Location> EOF "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k start diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index d7cbc5c6d..70df15cbd 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -63,7 +63,7 @@ test_expect_failure 'pretend we have fixed a known breakage' ' # updating a new file without --add should fail. test_expect_success 'git update-index without --add should fail adding.' ' - ! git update-index should-be-empty + test_must_fail git update-index should-be-empty ' # and with --add it should succeed, even if it is empty (it used to fail). @@ -83,7 +83,7 @@ test_expect_success \ # Removing paths. rm -f should-be-empty full-of-directories test_expect_success 'git update-index without --remove should fail removing.' ' - ! git update-index should-be-empty + test_must_fail git update-index should-be-empty ' test_expect_success \ @@ -217,7 +217,7 @@ test_expect_success \ 'git update-index --index-info < badobjects' test_expect_success 'writing this tree without --missing-ok.' ' - ! git write-tree + test_must_fail git write-tree ' test_expect_success \ diff --git a/t/t0001-init.sh b/t/t0001-init.sh index d31887f9b..2a38d98cb 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -83,11 +83,11 @@ test_expect_success 'init --bare' ' ( unset GIT_DIR GIT_WORK_TREE GIT_CONFIG - mkdir git-init-bare.git && - cd git-init-bare.git && + mkdir init-bare.git && + cd init-bare.git && git init --bare ) && - check_config git-init-bare.git true unset + check_config init-bare.git true unset ' test_expect_success 'GIT_DIR non-bare' ' diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index 2bfeac986..1be7446d8 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -52,7 +52,7 @@ test_expect_success 'safecrlf: autocrlf=input, all CRLF' ' git config core.safecrlf true && for w in I am all CRLF; do echo $w; done | append_cr >allcrlf && - ! git add allcrlf + test_must_fail git add allcrlf ' test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' ' @@ -61,7 +61,7 @@ test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' ' git config core.safecrlf true && for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed && - ! git add mixed + test_must_fail git add mixed ' test_expect_success 'safecrlf: autocrlf=true, all LF' ' @@ -70,7 +70,7 @@ test_expect_success 'safecrlf: autocrlf=true, all LF' ' git config core.safecrlf true && for w in I am all LF; do echo $w; done >alllf && - ! git add alllf + test_must_fail git add alllf ' test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' ' @@ -79,7 +79,7 @@ test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' ' git config core.safecrlf true && for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed && - ! git add mixed + test_must_fail git add mixed ' test_expect_success 'safecrlf: print warning only once' ' diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh index c5360e23d..b177174ef 100755 --- a/t/t0050-filesystem.sh +++ b/t/t0050-filesystem.sh @@ -43,7 +43,7 @@ test_expect_success "detection of case insensitive filesystem during repo init" else test_expect_success "detection of case insensitive filesystem during repo init" ' - ! git config --bool core.ignorecase >/dev/null || + test_must_fail git config --bool core.ignorecase >/dev/null || test $(git config --bool core.ignorecase) = false ' fi diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index 05262954a..1ec053513 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description=git-hash-object +test_description="git-hash-object" . ./test-lib.sh diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh index dcb3108c2..09a819933 100755 --- a/t/t1200-tutorial.sh +++ b/t/t1200-tutorial.sh @@ -102,7 +102,7 @@ echo "Lots of fun" >>example git commit -m 'Some fun.' -i hello example test_expect_success 'git resolve now fails' ' - ! git merge -m "Merge work in mybranch" mybranch + test_must_fail git merge -m "Merge work in mybranch" mybranch ' cat > hello << EOF diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index afe7e663f..64567fb94 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -201,7 +201,7 @@ test_expect_success 'non-match value' \ 'test wow = $(git config --get nextsection.nonewline !for)' test_expect_success 'ambiguous get' ' - ! git config --get nextsection.nonewline + test_must_fail git config --get nextsection.nonewline ' test_expect_success 'get multivar' \ @@ -223,15 +223,15 @@ EOF test_expect_success 'multivar replace' 'cmp .git/config expect' test_expect_success 'ambiguous value' ' - ! git config nextsection.nonewline + test_must_fail git config nextsection.nonewline ' test_expect_success 'ambiguous unset' ' - ! git config --unset nextsection.nonewline + test_must_fail git config --unset nextsection.nonewline ' test_expect_success 'invalid unset' ' - ! git config --unset somesection.nonewline + test_must_fail git config --unset somesection.nonewline ' git config --unset nextsection.nonewline "wow3$" @@ -248,7 +248,7 @@ EOF test_expect_success 'multivar unset' 'cmp .git/config expect' -test_expect_success 'invalid key' '! git config inval.2key blabla' +test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla' test_expect_success 'correct key' 'git config 123456.a123 987' @@ -430,7 +430,8 @@ EOF test_expect_success "rename succeeded" "test_cmp expect .git/config" test_expect_success "rename non-existing section" ' - ! git config --rename-section branch."world domination" branch.drei + test_must_fail git config --rename-section \ + branch."world domination" branch.drei ' test_expect_success "rename succeeded" "test_cmp expect .git/config" @@ -545,11 +546,11 @@ test_expect_success bool ' test_expect_success 'invalid bool (--get)' ' git config bool.nobool foobar && - ! git config --bool --get bool.nobool' + test_must_fail git config --bool --get bool.nobool' test_expect_success 'invalid bool (set)' ' - ! git config --bool bool.nobool foobar' + test_must_fail git config --bool bool.nobool foobar' rm .git/config @@ -669,7 +670,7 @@ EOF test_expect_success 'quoting' 'cmp .git/config expect' test_expect_success 'key with newline' ' - ! git config "key.with + test_must_fail git config "key.with newline" 123' test_expect_success 'value with newline' 'git config key.sub value.with\\\ diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh index 9be0770e7..8d305b437 100755 --- a/t/t1302-repo-version.sh +++ b/t/t1302-repo-version.sh @@ -41,7 +41,7 @@ test_expect_success 'gitdir required mode on normal repos' ' cd test && git apply --check --index ../test.patch)' test_expect_success 'gitdir required mode on unsupported repo' ' - (cd test2 && ! git apply --check --index ../test.patch) + (cd test2 && test_must_fail git apply --check --index ../test.patch) ' test_done diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index ca99d3761..b31e4b1ac 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -76,7 +76,7 @@ test_expect_success "delete $m (by HEAD)" ' rm -f .git/$m test_expect_success '(not) create HEAD with old sha1' " - ! git update-ref HEAD $A $B + test_must_fail git update-ref HEAD $A $B " test_expect_success "(not) prior created .git/$m" " ! test -f .git/$m @@ -87,7 +87,7 @@ test_expect_success \ "create HEAD" \ "git update-ref HEAD $A" test_expect_success '(not) change HEAD with wrong SHA1' " - ! git update-ref HEAD $B $Z + test_must_fail git update-ref HEAD $B $Z " test_expect_success "(not) changed .git/$m" " ! test $B"' = $(cat .git/'"$m"') diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh index 5141fab7c..f7e1a735e 100755 --- a/t/t2000-checkout-cache-clash.sh +++ b/t/t2000-checkout-cache-clash.sh @@ -38,7 +38,7 @@ date >path1 test_expect_success \ 'git checkout-index without -f should fail on conflicting work tree.' \ - '! git checkout-index -a' + 'test_must_fail git checkout-index -a' test_expect_success \ 'git checkout-index with -f should succeed.' \ diff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh index 9beaecd18..6ef2dcfd8 100755 --- a/t/t2100-update-cache-badpath.sh +++ b/t/t2100-update-cache-badpath.sh @@ -46,6 +46,6 @@ for p in path0/file0 path1/file1 path2 path3 do test_expect_success \ "git update-index to add conflicting path $p should fail." \ - "! git update-index --add -- $p" + "test_must_fail git update-index --add -- $p" done test_done diff --git a/t/t2103-update-index-ignore-missing.sh b/t/t2103-update-index-ignore-missing.sh new file mode 100755 index 000000000..332694e7d --- /dev/null +++ b/t/t2103-update-index-ignore-missing.sh @@ -0,0 +1,89 @@ +#!/bin/sh + +test_description='update-index with options' + +. ./test-lib.sh + +test_expect_success basics ' + >one && + >two && + >three && + + # need --add when adding + test_must_fail git update-index one && + test -z "$(git ls-files)" && + git update-index --add one && + test zone = "z$(git ls-files)" && + + # update-index is atomic + echo 1 >one && + test_must_fail git update-index one two && + echo "M one" >expect && + git diff-files --name-status >actual && + test_cmp expect actual && + + git update-index --add one two three && + for i in one three two; do echo $i; done >expect && + git ls-files >actual && + test_cmp expect actual && + + test_tick && + ( + test_create_repo xyzzy && + cd xyzzy && + >file && + git add file + git commit -m "sub initial" + ) && + git add xyzzy && + + test_tick && + git commit -m initial && + git tag initial +' + +test_expect_success '--ignore-missing --refresh' ' + git reset --hard initial && + echo 2 >one && + test_must_fail git update-index --refresh && + echo 1 >one && + git update-index --refresh && + rm -f two && + test_must_fail git update-index --refresh && + git update-index --ignore-missing --refresh + +' + +test_expect_success '--unmerged --refresh' ' + git reset --hard initial && + info=$(git ls-files -s one | sed -e "s/ 0 / 1 /") && + git rm --cached one && + echo "$info" | git update-index --index-info && + test_must_fail git update-index --refresh && + git update-index --unmerged --refresh && + echo 2 >two && + test_must_fail git update-index --unmerged --refresh >actual && + grep two actual && + ! grep one actual && + ! grep three actual +' + +test_expect_success '--ignore-submodules --refresh (1)' ' + git reset --hard initial && + rm -f two && + test_must_fail git update-index --ignore-submodules --refresh +' + +test_expect_success '--ignore-submodules --refresh (2)' ' + git reset --hard initial && + test_tick && + ( + cd xyzzy && + git commit -m "sub second" --allow-empty + ) && + test_must_fail git update-index --refresh && + test_must_fail git update-index --ignore-missing --refresh && + git update-index --ignore-submodules --refresh +' + +test_done diff --git a/t/t2202-add-addremove.sh b/t/t2202-add-addremove.sh new file mode 100755 index 000000000..6a8151064 --- /dev/null +++ b/t/t2202-add-addremove.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description='git add --all' + +. ./test-lib.sh + +test_expect_success setup ' + ( + echo .gitignore + echo will-remove + ) >expect && + ( + echo actual + echo expect + echo ignored + ) >.gitignore && + >will-remove && + git add --all && + test_tick && + git commit -m initial && + git ls-files >actual && + test_cmp expect actual +' + +test_expect_success 'git add --all' ' + ( + echo .gitignore + echo not-ignored + echo "M .gitignore" + echo "A not-ignored" + echo "D will-remove" + ) >expect && + >ignored && + >not-ignored && + echo modification >>.gitignore && + rm -f will-remove && + git add --all && + git update-index --refresh && + git ls-files >actual && + git diff-index --name-status --cached HEAD >>actual && + test_cmp expect actual +' + +test_done diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh index f4da86993..af8c4121a 100755 --- a/t/t3020-ls-files-error-unmatch.sh +++ b/t/t3020-ls-files-error-unmatch.sh @@ -17,7 +17,7 @@ git-commit -m "add foo bar" test_expect_success \ 'git ls-files --error-unmatch should fail with unmatched path.' \ - '! git ls-files --error-unmatch foo bar-does-not-match' + 'test_must_fail git ls-files --error-unmatch foo bar-does-not-match' test_expect_success \ 'git ls-files --error-unmatch should succeed eith matched paths.' \ diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 8d8768688..7c583c805 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -78,13 +78,13 @@ test_expect_success \ test_expect_success 'git branch -m o/o o should fail when o/p exists' ' git branch o/o && git branch o/p && - ! git branch -m o/o o + test_must_fail git branch -m o/o o ' test_expect_success 'git branch -m q r/q should fail when r exists' ' git branch q && git branch r && - ! git branch -m q r/q + test_must_fail git branch -m q r/q ' mv .git/config .git/config-saved @@ -110,14 +110,14 @@ test_expect_success \ test_expect_success 'config information was renamed, too' \ "test $(git config branch.s.dummy) = Hello && - ! git config branch.s/s/dummy" + test_must_fail git config branch.s/s/dummy" test_expect_success \ 'git branch -m u v should fail when the reflog for u is a symlink' ' git branch -l u && mv .git/logs/refs/heads/u real-u && ln -s real-u .git/logs/refs/heads/u && - ! git branch -m u v + test_must_fail git branch -m u v ' test_expect_success 'test tracking setup via --track' \ diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh index b64ccfbc5..c2dec1c63 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -43,7 +43,7 @@ test_expect_success 'git branch c/d should barf if branch c exists' ' git branch c && git pack-refs --all && rm -f .git/refs/heads/c && - ! git branch c/d + test_must_fail git branch c/d ' test_expect_success \ @@ -72,7 +72,7 @@ test_expect_success \ test_expect_success 'git branch i/j/k should barf if branch i exists' ' git branch i && git pack-refs --all --prune && - ! git branch i/j/k + test_must_fail git branch i/j/k ' test_expect_success \ diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index 0a2609965..0d33c71da 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -32,7 +32,7 @@ test_expect_success setup ' ' test_expect_success 'rebase with git am -3 (default)' ' - ! git rebase master + test_must_fail git rebase master ' test_expect_success 'rebase --skip with am -3' ' @@ -43,7 +43,7 @@ test_expect_success 'rebase moves back to skip-reference' ' test refs/heads/skip-reference = $(git symbolic-ref HEAD) && git branch post-rebase && git reset --hard pre-rebase && - ! git rebase master && + test_must_fail git rebase master && echo "hello" > hello && git add hello && git rebase --continue && @@ -53,7 +53,9 @@ test_expect_success 'rebase moves back to skip-reference' ' test_expect_success 'checkout skip-merge' 'git checkout -f skip-merge' -test_expect_success 'rebase with --merge' '! git rebase --merge master' +test_expect_success 'rebase with --merge' ' + test_must_fail git rebase --merge master +' test_expect_success 'rebase --skip with --merge' ' git rebase --skip diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh index 7c92e261f..0ab52da90 100755 --- a/t/t3502-cherry-pick-merge.sh +++ b/t/t3502-cherry-pick-merge.sh @@ -35,7 +35,7 @@ test_expect_success 'cherry-pick a non-merge with -m should fail' ' git reset --hard && git checkout a^0 && - ! git cherry-pick -m 1 b && + test_must_fail git cherry-pick -m 1 b && git diff --exit-code a -- ' @@ -44,7 +44,7 @@ test_expect_success 'cherry pick a merge without -m should fail' ' git reset --hard && git checkout a^0 && - ! git cherry-pick c && + test_must_fail git cherry-pick c && git diff --exit-code a -- ' @@ -71,7 +71,7 @@ test_expect_success 'cherry pick a merge relative to nonexistent parent should f git reset --hard && git checkout b^0 && - ! git cherry-pick -m 3 c + test_must_fail git cherry-pick -m 3 c ' @@ -79,7 +79,7 @@ test_expect_success 'revert a non-merge with -m should fail' ' git reset --hard && git checkout c^0 && - ! git revert -m 1 b && + test_must_fail git revert -m 1 b && git diff --exit-code c ' @@ -88,7 +88,7 @@ test_expect_success 'revert a merge without -m should fail' ' git reset --hard && git checkout c^0 && - ! git revert c && + test_must_fail git revert c && git diff --exit-code c ' @@ -115,7 +115,7 @@ test_expect_success 'revert a merge relative to nonexistent parent should fail' git reset --hard && git checkout c^0 && - ! git revert -m 3 c && + test_must_fail git revert -m 3 c && git diff --exit-code c ' diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index f542f0af4..79c06adf1 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -67,7 +67,7 @@ test_expect_success \ echo "other content" > foo git add foo echo "yet another content" > foo - ! git rm --cached foo + test_must_fail git rm --cached foo ' test_expect_success \ @@ -82,7 +82,7 @@ test_expect_success \ test_expect_success \ 'Post-check that foo exists but is not in index after git rm foo' \ - '[ -f foo ] && ! git ls-files --error-unmatch foo' + '[ -f foo ] && test_must_fail git ls-files --error-unmatch foo' test_expect_success \ 'Pre-check that bar exists and is in index before "git rm bar"' \ @@ -94,7 +94,7 @@ test_expect_success \ test_expect_success \ 'Post-check that bar does not exist and is not in index after "git rm -f bar"' \ - '! [ -f bar ] && ! git ls-files --error-unmatch bar' + '! [ -f bar ] && test_must_fail git ls-files --error-unmatch bar' test_expect_success \ 'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' \ @@ -109,7 +109,7 @@ if test "$test_failed_remove" = y; then chmod a-w . test_expect_success \ 'Test that "git rm -f" fails if its rm fails' \ - '! git rm -f baz' + 'test_must_fail git rm -f baz' chmod 775 . else test_expect_success 'skipping removal failure (perhaps running as root?)' : @@ -151,7 +151,7 @@ test_expect_success 'Re-add foo and baz' ' test_expect_success 'Modify foo -- rm should refuse' ' echo >>foo && - ! git rm foo baz && + test_must_fail git rm foo baz && test -f foo && test -f baz && git ls-files --error-unmatch foo baz @@ -161,8 +161,8 @@ test_expect_success 'Modified foo -- rm -f should work' ' git rm -f foo baz && test ! -f foo && test ! -f baz && - ! git ls-files --error-unmatch foo && - ! git ls-files --error-unmatch bar + test_must_fail git ls-files --error-unmatch foo && + test_must_fail git ls-files --error-unmatch bar ' test_expect_success 'Re-add foo and baz for HEAD tests' ' @@ -173,7 +173,7 @@ test_expect_success 'Re-add foo and baz for HEAD tests' ' ' test_expect_success 'foo is different in index from HEAD -- rm should refuse' ' - ! git rm foo baz && + test_must_fail git rm foo baz && test -f foo && test -f baz && git ls-files --error-unmatch foo baz @@ -183,8 +183,8 @@ test_expect_success 'but with -f it should work.' ' git rm -f foo baz && test ! -f foo && test ! -f baz && - ! git ls-files --error-unmatch foo - ! git ls-files --error-unmatch baz + test_must_fail git ls-files --error-unmatch foo + test_must_fail git ls-files --error-unmatch baz ' test_expect_success 'Recursive test setup' ' @@ -195,14 +195,14 @@ test_expect_success 'Recursive test setup' ' ' test_expect_success 'Recursive without -r fails' ' - ! git rm frotz && + test_must_fail git rm frotz && test -d frotz && test -f frotz/nitfol ' test_expect_success 'Recursive with -r but dirty' ' echo qfwfq >>frotz/nitfol - ! git rm -r frotz && + test_must_fail git rm -r frotz && test -d frotz && test -f frotz/nitfol ' @@ -214,7 +214,19 @@ test_expect_success 'Recursive with -r -f' ' ' test_expect_success 'Remove nonexistent file returns nonzero exit status' ' - ! git rm nonexistent + test_must_fail git rm nonexistent +' + +test_expect_success 'Call "rm" from outside the work tree' ' + mkdir repo && + cd repo && + git init && + echo something > somefile && + git add somefile && + git commit -m "add a file" && + (cd .. && + git --git-dir=repo/.git --work-tree=repo rm somefile) && + test_must_fail git ls-files --error-unmatch somefile ' test_done diff --git a/t/t3700-add.sh b/t/t3700-add.sh index e83fa1f68..7d123d17f 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -85,12 +85,12 @@ test_expect_success '.gitignore is honored' ' ' test_expect_success 'error out when attempting to add ignored ones without -f' ' - ! git add a.?? && + test_must_fail git add a.?? && ! (git ls-files | grep "\\.ig") ' test_expect_success 'error out when attempting to add ignored ones without -f' ' - ! git add d.?? && + test_must_fail git add d.?? && ! (git ls-files | grep "\\.ig") ' diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 0922c708f..a27fccc8d 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -144,7 +144,7 @@ test_expect_success 'check with no whitespace errors' ' test_expect_success 'check with trailing whitespace' ' echo "foo(); " > x && - ! git diff --check + test_must_fail git diff --check ' @@ -152,7 +152,7 @@ test_expect_success 'check with space before tab in indent' ' # indent has space followed by hard tab echo " foo();" > x && - ! git diff --check + test_must_fail git diff --check ' @@ -181,7 +181,7 @@ test_expect_success 'check staged with trailing whitespace' ' echo "foo(); " > x && git add x && - ! git diff --cached --check + test_must_fail git diff --cached --check ' @@ -190,7 +190,7 @@ test_expect_success 'check staged with space before tab in indent' ' # indent has space followed by hard tab echo " foo();" > x && git add x && - ! git diff --cached --check + test_must_fail git diff --cached --check ' @@ -206,7 +206,7 @@ test_expect_success 'check with trailing whitespace (diff-index)' ' echo "foo(); " > x && git add x && - ! git diff-index --check HEAD + test_must_fail git diff-index --check HEAD ' @@ -215,7 +215,7 @@ test_expect_success 'check with space before tab in indent (diff-index)' ' # indent has space followed by hard tab echo " foo();" > x && git add x && - ! git diff-index --check HEAD + test_must_fail git diff-index --check HEAD ' @@ -231,7 +231,7 @@ test_expect_success 'check staged with trailing whitespace (diff-index)' ' echo "foo(); " > x && git add x && - ! git diff-index --cached --check HEAD + test_must_fail git diff-index --cached --check HEAD ' @@ -240,7 +240,7 @@ test_expect_success 'check staged with space before tab in indent (diff-index)' # indent has space followed by hard tab echo " foo();" > x && git add x && - ! git diff-index --cached --check HEAD + test_must_fail git diff-index --cached --check HEAD ' @@ -256,7 +256,7 @@ test_expect_success 'check with trailing whitespace (diff-tree)' ' echo "foo(); " > x && git commit -m "another commit" x && - ! git diff-tree --check HEAD^ HEAD + test_must_fail git diff-tree --check HEAD^ HEAD ' @@ -265,7 +265,7 @@ test_expect_success 'check with space before tab in indent (diff-tree)' ' # indent has space followed by hard tab echo " foo();" > x && git commit -m "yet another" x && - ! git diff-tree --check HEAD^ HEAD + test_must_fail git diff-tree --check HEAD^ HEAD ' @@ -281,7 +281,7 @@ test_expect_success 'check trailing whitespace (trailing-space: on)' ' git config core.whitespace "trailing-space" && echo "foo (); " > x && - ! git diff --check + test_must_fail git diff --check ' @@ -299,7 +299,7 @@ test_expect_success 'check space before tab in indent (space-before-tab: on)' ' # indent contains space followed by HT git config core.whitespace "space-before-tab" && echo " foo (); " > x && - ! git diff --check + test_must_fail git diff --check ' @@ -315,7 +315,7 @@ test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' ' git config core.whitespace "indent-with-non-tab" && echo " foo ();" > x && - ! git diff --check + test_must_fail git diff --check ' @@ -323,7 +323,7 @@ test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: git config core.whitespace "indent-with-non-tab" && echo " foo ();" > x && - ! git diff --check + test_must_fail git diff --check ' diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 6d3ef6c60..833d6cbcf 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -54,7 +54,7 @@ test_expect_success 'custom pattern' ' test_expect_success 'last regexp must not be negated' ' git config diff.java.funcname "!static" && - ! git diff --no-index Beer.java Beer-correct.java + test_must_fail git diff --no-index Beer.java Beer-correct.java ' test_done diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh index 1b58233da..7da0b4bb8 100755 --- a/t/t4103-apply-binary.sh +++ b/t/t4103-apply-binary.sh @@ -48,22 +48,22 @@ test_expect_success 'stat binary diff (copy) -- should not fail.' \ test_expect_success 'check binary diff -- should fail.' \ 'git-checkout master && - ! git apply --check B.diff' + test_must_fail git apply --check B.diff' test_expect_success 'check binary diff (copy) -- should fail.' \ 'git-checkout master && - ! git apply --check C.diff' + test_must_fail git apply --check C.diff' test_expect_success \ 'check incomplete binary diff with replacement -- should fail.' ' git-checkout master && - ! git apply --check --allow-binary-replacement B.diff + test_must_fail git apply --check --allow-binary-replacement B.diff ' test_expect_success \ 'check incomplete binary diff with replacement (copy) -- should fail.' ' git-checkout master && - ! git apply --check --allow-binary-replacement C.diff + test_must_fail git apply --check --allow-binary-replacement C.diff ' test_expect_success 'check binary diff with replacement.' \ @@ -84,19 +84,19 @@ do_reset () { test_expect_success 'apply binary diff -- should fail.' \ 'do_reset && - ! git apply B.diff' + test_must_fail git apply B.diff' test_expect_success 'apply binary diff -- should fail.' \ 'do_reset && - ! git apply --index B.diff' + test_must_fail git apply --index B.diff' test_expect_success 'apply binary diff (copy) -- should fail.' \ 'do_reset && - ! git apply C.diff' + test_must_fail git apply C.diff' test_expect_success 'apply binary diff (copy) -- should fail.' \ 'do_reset && - ! git apply --index C.diff' + test_must_fail git apply --index C.diff' test_expect_success 'apply binary diff without replacement.' \ 'do_reset && diff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh index d74103988..66fa51591 100755 --- a/t/t4113-apply-ending.sh +++ b/t/t4113-apply-ending.sh @@ -30,7 +30,7 @@ test_expect_success setup \ # test test_expect_success 'apply at the end' \ - '! git apply --index test-patch' + 'test_must_fail git apply --index test-patch' cat >test-patch <<\EOF diff a/file b/file @@ -48,6 +48,6 @@ c' git update-index file test_expect_success 'apply at the beginning' \ - '! git apply --index test-patch' + 'test_must_fail git apply --index test-patch' test_done diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 5cbd5ef67..98ba020d8 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -182,7 +182,7 @@ test_expect_success 'am -3 falls back to 3-way merge' ' test_expect_success 'am pauses on conflict' ' git checkout lorem2^^ && - ! git am lorem-move.patch && + test_must_fail git am lorem-move.patch && test -d .git/rebase ' @@ -195,7 +195,7 @@ test_expect_success 'am --skip works' ' test_expect_success 'am --resolved works' ' git checkout lorem2^^ && - ! git am lorem-move.patch && + test_must_fail git am lorem-move.patch && test -d .git/rebase && echo resolved >>file && git add file && @@ -212,13 +212,13 @@ test_expect_success 'am takes patches from a Pine mailbox' ' ' test_expect_success 'am fails on mail without patch' ' - ! git am <failmail && + test_must_fail git am <failmail && rm -r .git/rebase/ ' test_expect_success 'am fails on empty patch' ' echo "---" >>failmail && - ! git am <failmail && + test_must_fail git am <failmail && git am --skip && ! test -d .git/rebase ' diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh new file mode 100755 index 000000000..dda7e2c28 --- /dev/null +++ b/t/t4151-am-abort.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +test_description='am --abort' + +. ./test-lib.sh + +test_expect_success setup ' + for i in a b c d e f g + do + echo $i + done >file-1 && + cp file-1 file-2 && + test_tick && + git add file-1 file-2 && + git commit -m initial && + git tag initial && + for i in 2 3 4 5 + do + echo $i >>file-1 && + test_tick && + git commit -a -m $i || break + done && + git format-patch initial && + git checkout -b side initial && + echo local change >file-2-expect +' + +for with3 in '' ' -3' +do + test_expect_success "am$with3 stops at a patch that does not apply" ' + + git reset --hard initial && + cp file-2-expect file-2 && + + test_must_fail git am$with3 000[124]-*.patch && + git log --pretty=tformat:%s >actual && + for i in 3 2 initial + do + echo $i + done >expect && + test_cmp expect actual + ' + + test_expect_success "am --abort goes back after failed am$with3" ' + git-am --abort && + git rev-parse HEAD >actual && + git rev-parse initial >expect && + test_cmp expect actual && + test_cmp file-2-expect file-2 && + git diff-index --exit-code --cached HEAD && + test ! -f .git/rr-cache/MERGE_RR + ' + +done + +test_done diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index b5a420299..b68ab11f2 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -45,7 +45,7 @@ git commit -q -a -m second test_expect_success 'nothing recorded without rerere' ' (rm -rf .git/rr-cache; git config rerere.enabled false) && - ! git merge first && + test_must_fail git merge first && ! test -d .git/rr-cache ' @@ -54,7 +54,7 @@ test_expect_success 'conflicting merge' ' git reset --hard && mkdir .git/rr-cache && git config --unset rerere.enabled && - ! git merge first + test_must_fail git merge first ' sha1=$(sed -e 's/ .*//' .git/MERGE_RR) @@ -65,7 +65,7 @@ test_expect_success 'rerere.enabled works, too' ' rm -rf .git/rr-cache && git config rerere.enabled true && git reset --hard && - ! git merge first && + test_must_fail git merge first && grep ^=======$ $rr/preimage ' @@ -134,7 +134,7 @@ test_expect_success 'another conflicting merge' ' git checkout -b third master && git show second^:a1 | sed "s/To die: t/To die! T/" > a1 && git commit -q -a -m third && - ! git pull . first + test_must_fail git pull . first ' git show first:a1 | sed 's/To die: t/To die! T/' > expect @@ -189,7 +189,7 @@ test_expect_success 'file2 added differently in two branches' ' echo Bello > file2 && git add file2 && git commit -m version2 && - ! git merge fourth && + test_must_fail git merge fourth && sha1=$(sed -e "s/ .*//" .git/MERGE_RR) && rr=.git/rr-cache/$sha1 && echo Cello > file2 && diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 983a39398..645583f9d 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -266,7 +266,7 @@ test_expect_success \ test_expect_success \ 'make sure index-pack detects the SHA1 collision' \ - '! git-index-pack -o bad.idx test-3.pack' + 'test_must_fail git-index-pack -o bad.idx test-3.pack' test_expect_success \ 'honor pack.packSizeLimit' \ diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index ecec59163..0639772ac 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -118,7 +118,7 @@ test_expect_success \ test_expect_success \ '[index v1] 4) confirm that the pack is actually corrupted' \ - '! git fsck --full $commit' + 'test_must_fail git fsck --full $commit' test_expect_success \ '[index v1] 5) pack-objects happily reuses corrupted data' \ @@ -127,7 +127,7 @@ test_expect_success \ test_expect_success \ '[index v1] 6) newly created pack is BAD !' \ - '! git verify-pack -v "test-4-${pack1}.pack"' + 'test_must_fail git verify-pack -v "test-4-${pack1}.pack"' test_expect_success \ '[index v2] 1) stream pack to repository' \ @@ -156,11 +156,11 @@ test_expect_success \ test_expect_success \ '[index v2] 4) confirm that the pack is actually corrupted' \ - '! git fsck --full $commit' + 'test_must_fail git fsck --full $commit' test_expect_success \ '[index v2] 5) pack-objects refuses to reuse corrupted data' \ - '! git pack-objects test-5 <obj-list' + 'test_must_fail git pack-objects test-5 <obj-list' test_expect_success \ '[index v2] 6) verify-pack detects CRC mismatch' \ @@ -173,7 +173,8 @@ test_expect_success \ ( while read obj do git cat-file -p $obj >/dev/null || exit 1 done <obj-list ) && - err=$(! git verify-pack ".git/objects/pack/pack-${pack1}.pack" 2>&1) && + err=$(test_must_fail git verify-pack \ + ".git/objects/pack/pack-${pack1}.pack" 2>&1) && echo "$err" | grep "CRC mismatch"' test_done diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index 2fff30015..ee769d669 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -61,7 +61,8 @@ EOF chmod u+x victim/.git/hooks/post-update test_expect_success push ' - ! git-send-pack --force ./victim/.git master tofail >send.out 2>send.err + test_must_fail git-send-pack --force ./victim/.git \ + master tofail >send.out 2>send.err ' test_expect_success 'updated as expected' ' diff --git a/t/t5404-tracking-branches.sh b/t/t5404-tracking-branches.sh index 64fe2615a..c24003565 100755 --- a/t/t5404-tracking-branches.sh +++ b/t/t5404-tracking-branches.sh @@ -35,7 +35,9 @@ test_expect_success 'prepare pushable branches' ' git commit -a -m aa-master ' -test_expect_success 'mixed-success push returns error' '! git push' +test_expect_success 'mixed-success push returns error' ' + test_must_fail git push +' test_expect_success 'check tracking branches updated correctly after push' ' test "$(git rev-parse origin/master)" = "$(git rev-parse master)" diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh index 46b2cb4e4..59e80a5ea 100755 --- a/t/t5406-remote-rejects.sh +++ b/t/t5406-remote-rejects.sh @@ -17,7 +17,7 @@ test_expect_success 'setup' ' git commit -a -m 2 ' -test_expect_success 'push reports error' '! git push 2>stderr' +test_expect_success 'push reports error' 'test_must_fail git push 2>stderr' test_expect_success 'individual ref reports error' 'grep rejected stderr' diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 140e87458..362cf7e92 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -177,6 +177,6 @@ test_expect_success "clone shallow object count" \ "test \"count: 18\" = \"$(grep count count.shallow)\"" test_expect_success "pull in shallow repo with missing merge base" \ - "(cd shallow && ! git pull --depth 4 .. A)" + "(cd shallow && test_must_fail git pull --depth 4 .. A)" test_done diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 1e192a220..be9ee9326 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -164,7 +164,7 @@ test_expect_success 'prune' ' git fetch origin && git remote prune origin && git rev-parse refs/remotes/origin/side2 && - ! git rev-parse refs/remotes/origin/side) + test_must_fail git rev-parse refs/remotes/origin/side) ' cat > test/expect << EOF @@ -179,7 +179,7 @@ test_expect_success 'prune --dry-run' ' (cd test && git remote prune --dry-run origin > output && git rev-parse refs/remotes/origin/side2 && - ! git rev-parse refs/remotes/origin/side && + test_must_fail git rev-parse refs/remotes/origin/side && (cd ../one && git branch -m side side2) && test_cmp expect output) @@ -194,10 +194,10 @@ test_expect_success 'add --mirror && prune' ' git branch -m side2 side) && (cd mirror && git rev-parse --verify refs/heads/side2 && - ! git rev-parse --verify refs/heads/side && + test_must_fail git rev-parse --verify refs/heads/side && git fetch origin && git remote prune origin && - ! git rev-parse --verify refs/heads/side2 && + test_must_fail git rev-parse --verify refs/heads/side2 && git rev-parse --verify refs/heads/side) ' @@ -212,10 +212,10 @@ test_expect_success 'add alt && prune' ' git branch -m side side2) && (cd alttst && git rev-parse --verify refs/remotes/origin/side && - ! git rev-parse --verify refs/remotes/origin/side2 && + test_must_fail git rev-parse --verify refs/remotes/origin/side2 && git fetch alt && git remote prune alt && - ! git rev-parse --verify refs/remotes/origin/side && + test_must_fail git rev-parse --verify refs/remotes/origin/side && git rev-parse --verify refs/remotes/origin/side2) ' @@ -320,7 +320,7 @@ test_expect_success '"remote show" does not show symbolic refs' ' test_expect_success 'reject adding remote with an invalid name' ' - ! git remote add some:url desired-name + test_must_fail git remote add some:url desired-name ' diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index df7750f7d..13d1d826c 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -104,7 +104,7 @@ test_expect_success 'fetch must not resolve short tag name' ' cd five && git init && - ! git fetch .. anno:five + test_must_fail git fetch .. anno:five ' @@ -117,7 +117,7 @@ test_expect_success 'fetch must not resolve short remote name' ' cd six && git init && - ! git fetch .. six:six + test_must_fail git fetch .. six:six ' @@ -143,7 +143,7 @@ test_expect_success 'create bundle 2' ' test_expect_success 'unbundle 1' ' cd "$D/bundle" && git checkout -b some-branch && - ! git fetch "$D/bundle1" master:master + test_must_fail git fetch "$D/bundle1" master:master ' test_expect_success 'bundle 1 has only 3 files ' ' @@ -236,7 +236,7 @@ test_expect_success 'fetch with a non-applying branch.<name>.merge' ' # the strange name is: a\!'b test_expect_success 'quoting of a strangely named repo' ' - ! git fetch "a\\!'\''b" > result 2>&1 && + test_must_fail git fetch "a\\!'\''b" > result 2>&1 && cat result && grep "fatal: '\''a\\\\!'\''b'\''" result ' @@ -264,7 +264,7 @@ test_expect_success 'explicit fetch should not update tracking' ' git fetch origin master && n=$(git rev-parse --verify refs/remotes/origin/master) && test "$o" = "$n" && - ! git rev-parse --verify refs/remotes/origin/side + test_must_fail git rev-parse --verify refs/remotes/origin/side ) ' @@ -278,7 +278,7 @@ test_expect_success 'explicit pull should not update tracking' ' git pull origin master && n=$(git rev-parse --verify refs/remotes/origin/master) && test "$o" = "$n" && - ! git rev-parse --verify refs/remotes/origin/side + test_must_fail git rev-parse --verify refs/remotes/origin/side ) ' diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 6805032a0..f0030ad00 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -178,7 +178,7 @@ test_expect_success 'failed (non-fast-forward) push with matching heads' ' mk_test heads/master && git push testrepo : && git commit --amend -massaged && - ! git push testrepo && + test_must_fail git push testrepo && check_push_result $the_commit heads/master && git reset --hard $the_commit @@ -374,7 +374,7 @@ test_expect_success 'push with +HEAD' ' # Without force rewinding should fail git reset --hard HEAD^ && - ! git push testrepo HEAD && + test_must_fail git push testrepo HEAD && check_push_result $the_commit heads/local && # With force rewinding should succeed @@ -448,7 +448,7 @@ test_expect_success 'push does not update local refs on failure' ' git clone parent child && (cd child && echo two >foo && git commit -a -m two && - ! git push && + test_must_fail git push && test $(git rev-parse master) != \ $(git rev-parse remotes/origin/master)) @@ -459,7 +459,7 @@ test_expect_success 'allow deleting an invalid remote ref' ' pwd && rm -f testrepo/.git/objects/??/* && git push testrepo :refs/heads/master && - (cd testrepo && ! git rev-parse --verify refs/heads/master) + (cd testrepo && test_must_fail git rev-parse --verify refs/heads/master) ' diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh index 8b0509106..1a15817cd 100755 --- a/t/t5530-upload-pack-error.sh +++ b/t/t5530-upload-pack-error.sh @@ -27,7 +27,7 @@ test_expect_success 'setup and corrupt repository' ' ' test_expect_success 'fsck fails' ' - ! git fsck + test_must_fail git fsck ' test_expect_success 'upload-pack fails due to error in pack-objects' ' @@ -46,7 +46,7 @@ test_expect_success 'corrupt repo differently' ' ' test_expect_success 'fsck fails' ' - ! git fsck + test_must_fail git fsck ' test_expect_success 'upload-pack fails due to error in rev-list' ' @@ -66,7 +66,7 @@ test_expect_success 'create empty repository' ' test_expect_success 'fetch fails' ' - ! git fetch .. master + test_must_fail git fetch .. master ' diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh index 21dbb557b..f8c17cd96 100755 --- a/t/t5540-http-push.sh +++ b/t/t5540-http-push.sh @@ -73,7 +73,7 @@ test_expect_failure 'create and delete remote branch' ' git push origin :dev && git branch -d -r origin/dev && git fetch && - ! git show-ref --verify refs/remotes/origin/dev + test_must_fail git show-ref --verify refs/remotes/origin/dev ' stop_httpd diff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh index acf34cec8..3c013e2b6 100755 --- a/t/t5600-clone-fail-cleanup.sh +++ b/t/t5600-clone-fail-cleanup.sh @@ -13,7 +13,7 @@ remove the directory before attempting a clone again.' test_expect_success \ 'clone of non-existent source should fail' \ - '! git-clone foo bar' + 'test_must_fail git-clone foo bar' test_expect_success \ 'failed clone should not leave a directory' \ @@ -29,7 +29,7 @@ test_create_repo foo # current path not to the target dir test_expect_success \ 'clone of non-existent (relative to $PWD) source should fail' \ - '! git-clone ../foo baz' + 'test_must_fail git-clone ../foo baz' test_expect_success \ 'clone should work now that source exists' \ diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh index 74e9e6618..f674c48ca 100755 --- a/t/t6023-merge-file.sh +++ b/t/t6023-merge-file.sh @@ -67,7 +67,7 @@ test_expect_success "merge result added missing LF" \ cp test.txt backup.txt test_expect_success "merge with conflicts" \ - "! git merge-file test.txt orig.txt new3.txt" + "test_must_fail git merge-file test.txt orig.txt new3.txt" cat > expect.txt << EOF <<<<<<< test.txt @@ -90,7 +90,7 @@ test_expect_success "expected conflict markers" "test_cmp test.txt expect.txt" cp backup.txt test.txt test_expect_success "merge with conflicts, using -L" \ - "! git merge-file -L 1 -L 2 test.txt orig.txt new3.txt" + "test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt" cat > expect.txt << EOF <<<<<<< 1 @@ -114,7 +114,7 @@ test_expect_success "expected conflict markers, with -L" \ sed "s/ tu / TU /" < new1.txt > new5.txt test_expect_success "conflict in removed tail" \ - "! git merge-file -p orig.txt new1.txt new5.txt > out" + "test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out" cat > expect << EOF Dominus regit me, @@ -135,7 +135,8 @@ EOF test_expect_success "expected conflict markers" "test_cmp expect out" test_expect_success 'binary files cannot be merged' ' - ! git merge-file -p orig.txt ../test4012.png new1.txt 2> merge.err && + test_must_fail git merge-file -p \ + orig.txt ../test4012.png new1.txt 2> merge.err && grep "Cannot merge binary files" merge.err ' @@ -144,7 +145,7 @@ sed -e "s/deerit.$/deerit,/" -e "s/me;$/me,/" < new5.txt > new7.txt test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' ' - ! git merge-file -p new6.txt new5.txt new7.txt > output && + test_must_fail git merge-file -p new6.txt new5.txt new7.txt > output && test 1 = $(grep ======= < output | wc -l) ' @@ -154,7 +155,8 @@ sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit --/" < new7.txt > new9.txt test_expect_success 'ZEALOUS_ALNUM' ' - ! git merge-file -p new8.txt new5.txt new9.txt > merge.out && + test_must_fail git merge-file -p \ + new8.txt new5.txt new9.txt > merge.out && test 1 = $(grep ======= < merge.out | wc -l) ' diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh index 6a6a13002..802d0d06e 100755 --- a/t/t6024-recursive-merge.sh +++ b/t/t6024-recursive-merge.sh @@ -60,7 +60,9 @@ git update-index a1 && GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F ' -test_expect_success "combined merge conflicts" "! git merge -m final G" +test_expect_success "combined merge conflicts" " + test_must_fail git merge -m final G +" cat > expect << EOF <<<<<<< HEAD:a1 @@ -90,7 +92,7 @@ test_expect_success 'refuse to merge binary files' ' printf "\0\0" > binary-file && git add binary-file && git commit -m binary2 && - ! git merge F > merge.out 2> merge.err && + test_must_fail git merge F > merge.out 2> merge.err && grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \ merge.err ' diff --git a/t/t6025-merge-symlinks.sh b/t/t6025-merge-symlinks.sh index 6004deb43..fc58456a1 100755 --- a/t/t6025-merge-symlinks.sh +++ b/t/t6025-merge-symlinks.sh @@ -33,7 +33,7 @@ git-commit -m b-file' test_expect_success \ 'merge master into b-symlink, which has a different symbolic link' ' git-checkout b-symlink && -! git-merge master' +test_must_fail git-merge master' test_expect_success \ 'the merge result must be a file' ' @@ -42,7 +42,7 @@ test -f symlink' test_expect_success \ 'merge master into b-file, which has a file instead of a symbolic link' ' git-reset --hard && git-checkout b-file && -! git-merge master' +test_must_fail git-merge master' test_expect_success \ 'the merge result must be a file' ' @@ -52,7 +52,7 @@ test_expect_success \ 'merge b-file, which has a file instead of a symbolic link, into master' ' git-reset --hard && git-checkout master && -! git-merge b-file' +test_must_fail git-merge b-file' test_expect_success \ 'the merge result must be a file' ' diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh index 2328b6994..efc831363 100755 --- a/t/t6101-rev-parse-parents.sh +++ b/t/t6101-rev-parse-parents.sh @@ -26,7 +26,7 @@ test_expect_success 'final^1^1^1 = final^^^' "test $(git rev-parse final^1^1^1) test_expect_success 'final^1^2' "test $(git rev-parse start2) = $(git rev-parse final^1^2)" test_expect_success 'final^1^2 != final^1^1' "test $(git rev-parse final^1^2) != $(git rev-parse final^1^1)" test_expect_success 'final^1^3 not valid' "if git rev-parse --verify final^1^3; then false; else :; fi" -test_expect_success '--verify start2^1' '! git rev-parse --verify start2^1' +test_expect_success '--verify start2^1' 'test_must_fail git rev-parse --verify start2^1' test_expect_success '--verify start2^0' 'git rev-parse --verify start2^0' test_expect_success 'repack for next test' 'git repack -a -d' diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index fa382c58d..336cfaa1c 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -80,7 +80,7 @@ test_expect_success \ test_expect_success \ 'do not move directory over existing directory' \ - 'mkdir path0 && mkdir path0/path2 && ! git mv path2 path0' + 'mkdir path0 && mkdir path0/path2 && test_must_fail git mv path2 path0' test_expect_success \ 'move into "."' \ @@ -149,7 +149,7 @@ test_expect_success 'absolute pathname outside should fail' '( >sub/file && git add sub/file && - ! git mv sub "$out/out" && + test_must_fail git mv sub "$out/out" && test -d sub && ! test -d ../in && git ls-files --error-unmatch sub/file diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 241c70dc6..bc7ce2cbb 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -30,17 +30,17 @@ test_expect_success 'looking for a tag in an empty tree should fail' \ '! (tag_exists mytag)' test_expect_success 'creating a tag in an empty tree should fail' ' - ! git-tag mynotag && + test_must_fail git-tag mynotag && ! tag_exists mynotag ' test_expect_success 'creating a tag for HEAD in an empty tree should fail' ' - ! git-tag mytaghead HEAD && + test_must_fail git-tag mytaghead HEAD && ! tag_exists mytaghead ' test_expect_success 'creating a tag for an unknown revision should fail' ' - ! git-tag mytagnorev aaaaaaaaaaa && + test_must_fail git-tag mytagnorev aaaaaaaaaaa && ! tag_exists mytagnorev ' @@ -85,16 +85,16 @@ test_expect_success \ test_expect_success \ 'trying to create a tag with the name of one existing should fail' \ - '! git tag mytag' + 'test_must_fail git tag mytag' test_expect_success \ 'trying to create a tag with a non-valid name should fail' ' test `git-tag -l | wc -l` -eq 1 && - ! git tag "" && - ! git tag .othertag && - ! git tag "other tag" && - ! git tag "othertag^" && - ! git tag "other~tag" && + test_must_fail git tag "" && + test_must_fail git tag .othertag && + test_must_fail git tag "other tag" && + test_must_fail git tag "othertag^" && + test_must_fail git tag "other~tag" && test `git-tag -l | wc -l` -eq 1 ' @@ -107,7 +107,7 @@ test_expect_success 'creating a tag using HEAD directly should succeed' ' test_expect_success 'trying to delete an unknown tag should fail' ' ! tag_exists unknown-tag && - ! git-tag -d unknown-tag + test_must_fail git-tag -d unknown-tag ' cat >expect <<EOF @@ -141,13 +141,13 @@ test_expect_success \ 'trying to delete two tags, existing and not, should fail in the 2nd' ' tag_exists mytag && ! tag_exists myhead && - ! git-tag -d mytag anothertag && + test_must_fail git-tag -d mytag anothertag && ! tag_exists mytag && ! tag_exists myhead ' test_expect_success 'trying to delete an already deleted tag should fail' \ - '! git-tag -d mytag' + 'test_must_fail git-tag -d mytag' # listing various tags with pattern matching: @@ -266,15 +266,15 @@ test_expect_success \ ' test_expect_success 'trying to verify an unknown tag should fail' \ - '! git-tag -v unknown-tag' + 'test_must_fail git-tag -v unknown-tag' test_expect_success \ 'trying to verify a non-annotated and non-signed tag should fail' \ - '! git-tag -v non-annotated-tag' + 'test_must_fail git-tag -v non-annotated-tag' test_expect_success \ 'trying to verify many non-annotated or unknown tags, should fail' \ - '! git-tag -v unknown-tag1 non-annotated-tag unknown-tag2' + 'test_must_fail git-tag -v unknown-tag1 non-annotated-tag unknown-tag2' # creating annotated tags: @@ -334,7 +334,7 @@ test_expect_success \ 'trying to create a tag with a non-existing -F file should fail' ' ! test -f nonexistingfile && ! tag_exists notag && - ! git-tag -F nonexistingfile notag && + test_must_fail git-tag -F nonexistingfile notag && ! tag_exists notag ' @@ -343,11 +343,12 @@ test_expect_success \ echo "message file 1" >msgfile1 && echo "message file 2" >msgfile2 && ! tag_exists msgtag && - ! git-tag -m "message 1" -F msgfile1 msgtag && + test_must_fail git-tag -m "message 1" -F msgfile1 msgtag && ! tag_exists msgtag && - ! git-tag -F msgfile1 -m "message 1" msgtag && + test_must_fail git-tag -F msgfile1 -m "message 1" msgtag && ! tag_exists msgtag && - ! git-tag -m "message 1" -F msgfile1 -m "message 2" msgtag && + test_must_fail git-tag -m "message 1" -F msgfile1 \ + -m "message 2" msgtag && ! tag_exists msgtag ' @@ -591,19 +592,19 @@ fi test_expect_success \ 'trying to verify an annotated non-signed tag should fail' ' tag_exists annotated-tag && - ! git-tag -v annotated-tag + test_must_fail git-tag -v annotated-tag ' test_expect_success \ 'trying to verify a file-annotated non-signed tag should fail' ' tag_exists file-annotated-tag && - ! git-tag -v file-annotated-tag + test_must_fail git-tag -v file-annotated-tag ' test_expect_success \ 'trying to verify two annotated non-signed tags should fail' ' tag_exists annotated-tag file-annotated-tag && - ! git-tag -v annotated-tag file-annotated-tag + test_must_fail git-tag -v annotated-tag file-annotated-tag ' # creating and verifying signed tags: @@ -651,13 +652,14 @@ test_expect_success 'sign with a given key id' ' test_expect_success 'sign with an unknown id (1)' ' - ! git tag -u author@example.com -m "Another message" o-signed-tag + test_must_fail git tag -u author@example.com \ + -m "Another message" o-signed-tag ' test_expect_success 'sign with an unknown id (2)' ' - ! git tag -u DEADBEEF -m "Another message" o-signed-tag + test_must_fail git tag -u DEADBEEF -m "Another message" o-signed-tag ' @@ -718,7 +720,7 @@ test_expect_success \ 'trying to create a signed tag with non-existing -F file should fail' ' ! test -f nonexistingfile && ! tag_exists nosigtag && - ! git-tag -s -F nonexistingfile nosigtag && + test_must_fail git-tag -s -F nonexistingfile nosigtag && ! tag_exists nosigtag ' @@ -730,10 +732,11 @@ test_expect_success 'verifying two signed tags in one command should succeed' \ test_expect_success \ 'verifying many signed and non-signed tags should fail' ' - ! git-tag -v signed-tag annotated-tag && - ! git-tag -v file-annotated-tag file-signed-tag && - ! git-tag -v annotated-tag file-signed-tag file-annotated-tag && - ! git-tag -v signed-tag annotated-tag file-signed-tag + test_must_fail git-tag -v signed-tag annotated-tag && + test_must_fail git-tag -v file-annotated-tag file-signed-tag && + test_must_fail git-tag -v annotated-tag \ + file-signed-tag file-annotated-tag && + test_must_fail git-tag -v signed-tag annotated-tag file-signed-tag ' test_expect_success 'verifying a forged tag should fail' ' @@ -741,7 +744,7 @@ test_expect_success 'verifying a forged tag should fail' ' sed -e "s/signed-tag/forged-tag/" | git mktag) && git tag forged-tag $forged && - ! git-tag -v forged-tag + test_must_fail git-tag -v forged-tag ' # blank and empty messages for signed tags: @@ -1031,7 +1034,7 @@ test_expect_success \ git config user.signingkey BobTheMouse test_expect_success \ 'git-tag -s fails if gpg is misconfigured' \ - '! git tag -s -m tail tag-gpg-failure' + 'test_must_fail git tag -s -m tail tag-gpg-failure' git config --unset user.signingkey # try to verify without gpg: @@ -1039,7 +1042,7 @@ git config --unset user.signingkey rm -rf gpghome test_expect_success \ 'verify signed tag fails when public key is not present' \ - '! git-tag -v signed-tag' + 'test_must_fail git-tag -v signed-tag' test_expect_success \ 'git-tag -a fails if tag annotation is empty' ' diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index 96d15083f..29f5678b4 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -52,10 +52,10 @@ secondfile: EOF test_expect_success 'giving a non existing revision should fail' ' - ! git reset aaaaaa && - ! git reset --mixed aaaaaa && - ! git reset --soft aaaaaa && - ! git reset --hard aaaaaa && + test_must_fail git reset aaaaaa && + test_must_fail git reset --mixed aaaaaa && + test_must_fail git reset --soft aaaaaa && + test_must_fail git reset --hard aaaaaa && check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc ' @@ -63,29 +63,29 @@ test_expect_success 'reset --soft with unmerged index should fail' ' touch .git/MERGE_HEAD && echo "100644 44c5b5884550c17758737edcced463447b91d42b 1 un" | git update-index --index-info && - ! git reset --soft HEAD && + test_must_fail git reset --soft HEAD && rm .git/MERGE_HEAD && git rm --cached -- un ' test_expect_success \ 'giving paths with options different than --mixed should fail' ' - ! git reset --soft -- first && - ! git reset --hard -- first && - ! git reset --soft HEAD^ -- first && - ! git reset --hard HEAD^ -- first && + test_must_fail git reset --soft -- first && + test_must_fail git reset --hard -- first && + test_must_fail git reset --soft HEAD^ -- first && + test_must_fail git reset --hard HEAD^ -- first && check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc ' test_expect_success 'giving unrecognized options should fail' ' - ! git reset --other && - ! git reset -o && - ! git reset --mixed --other && - ! git reset --mixed -o && - ! git reset --soft --other && - ! git reset --soft -o && - ! git reset --hard --other && - ! git reset --hard -o && + test_must_fail git reset --other && + test_must_fail git reset -o && + test_must_fail git reset --mixed --other && + test_must_fail git reset --mixed -o && + test_must_fail git reset --soft --other && + test_must_fail git reset --soft -o && + test_must_fail git reset --hard --other && + test_must_fail git reset --hard -o && check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc ' @@ -102,8 +102,8 @@ test_expect_success \ echo "3rd line in branch2" >>secondfile && git commit -a -m "change in branch2" && - ! git merge branch1 && - ! git reset --soft && + test_must_fail git merge branch1 && + test_must_fail git reset --soft && printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile && git commit -a -m "the change in branch2" && @@ -126,7 +126,7 @@ test_expect_success \ echo "3rd line in branch4" >>secondfile && git checkout -m branch3 && - ! git reset --soft && + test_must_fail git reset --soft && printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile && git commit -a -m "the line in branch3" && @@ -326,7 +326,7 @@ test_expect_success '--hard reset to HEAD should clear a failed merge' ' echo "3rd line in branch2" >>secondfile && git commit -a -m "change in branch2" && - ! git pull . branch1 && + test_must_fail git pull . branch1 && git reset --hard && check_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb ' @@ -388,7 +388,7 @@ test_expect_success 'test --mixed <paths>' ' echo 4 > file4 && echo 5 > file1 && git add file1 file3 file4 && - ! git reset HEAD -- file1 file2 file3 && + test_must_fail git reset HEAD -- file1 file2 file3 && git diff > output && test_cmp output expect && git diff --cached > output && @@ -402,11 +402,11 @@ test_expect_success 'test resetting the index at give paths' ' >sub/file2 && git update-index --add sub/file1 sub/file2 && T=$(git write-tree) && - ! git reset HEAD sub/file2 && + test_must_fail git reset HEAD sub/file2 && U=$(git write-tree) && echo "$T" && echo "$U" && - ! git diff-index --cached --exit-code "$T" && + test_must_fail git diff-index --cached --exit-code "$T" && test "$T" != "$U" ' @@ -419,7 +419,7 @@ test_expect_success 'resetting an unmodified path is a no-op' ' ' cat > expect << EOF -file2: needs update +file2: locally modified EOF test_expect_success '--mixed refreshes the index' ' diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh index b25a77f91..cdecebe45 100755 --- a/t/t7103-reset-bare.sh +++ b/t/t7103-reset-bare.sh @@ -17,7 +17,7 @@ test_expect_success 'setup bare' ' ' test_expect_success 'hard reset is not allowed' ' - ! git reset --hard HEAD^ + test_must_fail git reset --hard HEAD^ ' test_expect_success 'soft reset is allowed' ' diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index bd7723970..2b51c0d7d 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -316,14 +316,14 @@ test_expect_success 'git-clean -d -X' ' test_expect_success 'clean.requireForce defaults to true' ' git config --unset clean.requireForce && - ! git-clean + test_must_fail git clean ' test_expect_success 'clean.requireForce' ' git config clean.requireForce true && - ! git-clean + test_must_fail git clean ' diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 6c7b90248..cbc0c34ce 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -75,7 +75,7 @@ test_expect_success 'init should register submodule url in .git/config' ' then echo "[OOPS] init succeeded but submodule url is wrong" false - elif ! git config submodule.example.url ./.subrepo + elif test_must_fail git config submodule.example.url ./.subrepo then echo "[OOPS] init succeeded but update of url failed" false diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh index 5becb3ec5..f919c8d34 100755 --- a/t/t7402-submodule-rebase.sh +++ b/t/t7402-submodule-rebase.sh @@ -71,7 +71,7 @@ test_expect_success 'rebase with dirty file and submodule fails' ' test_tick && git commit -m rewrite file && echo dirty > file && - ! git rebase --onto HEAD~2 HEAD^ + test_must_fail git rebase --onto HEAD~2 HEAD^ ' diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh index baed6ce96..d89f91a6f 100755 --- a/t/t7500-commit.sh +++ b/t/t7500-commit.sh @@ -23,12 +23,12 @@ test_expect_success 'a basic commit in an empty tree should succeed' ' test_expect_success 'nonexistent template file should return error' ' echo changes >> foo && git add foo && - ! git commit --template "$PWD"/notexist + test_must_fail git commit --template "$PWD"/notexist ' test_expect_success 'nonexistent template file in config should return error' ' git config commit.template "$PWD"/notexist && - ! git commit && + test_must_fail git commit && git config --unset commit.template ' @@ -37,12 +37,12 @@ TEMPLATE="$PWD"/template test_expect_success 'unedited template should not commit' ' echo "template line" > "$TEMPLATE" && - ! git commit --template "$TEMPLATE" + test_must_fail git commit --template "$TEMPLATE" ' test_expect_success 'unedited template with comments should not commit' ' echo "# comment in template" >> "$TEMPLATE" && - ! git commit --template "$TEMPLATE" + test_must_fail git commit --template "$TEMPLATE" ' test_expect_success 'a Signed-off-by line by itself should not commit' ' diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index d3370ff7f..0edd9ddf7 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -19,7 +19,7 @@ test_expect_success \ test_expect_success \ "fail initial amend" \ - "! git-commit --amend" + "test_must_fail git-commit --amend" test_expect_success \ "initial commit" \ @@ -27,16 +27,16 @@ test_expect_success \ test_expect_success \ "invalid options 1" \ - "! git-commit -m foo -m bar -F file" + "test_must_fail git-commit -m foo -m bar -F file" test_expect_success \ "invalid options 2" \ - "! git-commit -C HEAD -m illegal" + "test_must_fail git-commit -C HEAD -m illegal" test_expect_success \ "using paths with -a" \ "echo King of the bongo >file && - ! git-commit -m foo -a file" + test_must_fail git-commit -m foo -a file" test_expect_success \ "using paths with --interactive" \ @@ -45,11 +45,11 @@ test_expect_success \ test_expect_success \ "using invalid commit with -C" \ - "! git-commit -C bogus" + "test_must_fail git-commit -C bogus" test_expect_success \ "testing nothing to commit" \ - "! git-commit -m initial" + "test_must_fail git-commit -m initial" test_expect_success \ "next commit" \ @@ -59,7 +59,7 @@ test_expect_success \ test_expect_success \ "commit message from non-existing file" \ "echo 'more bongo: bongo bongo bongo bongo' >file && \ - ! git-commit -F gah -a" + test_must_fail git-commit -F gah -a" # Empty except stray tabs and spaces on a few lines. sed -e 's/@$//' >msg <<EOF @@ -70,7 +70,7 @@ Signed-off-by: hula EOF test_expect_success \ "empty commit message" \ - "! git-commit -F msg -a" + "test_must_fail git-commit -F msg -a" test_expect_success \ "commit message from file" \ @@ -91,7 +91,7 @@ test_expect_success \ test_expect_success \ "passing -m and -F" \ "echo 'enough with the bongos' >file && \ - ! git-commit -F msg -m amending ." + test_must_fail git-commit -F msg -m amending ." test_expect_success \ "using message from other commit" \ diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh index 2dd5a5e30..b06909599 100755 --- a/t/t7503-pre-commit-hook.sh +++ b/t/t7503-pre-commit-hook.sh @@ -56,7 +56,7 @@ test_expect_success 'with failing hook' ' echo "another" >> file && git add file && - ! git commit -m "another" + test_must_fail git commit -m "another" ' diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh index 88577af95..47680e6df 100755 --- a/t/t7504-commit-msg-hook.sh +++ b/t/t7504-commit-msg-hook.sh @@ -105,7 +105,7 @@ test_expect_success 'with failing hook' ' echo "another" >> file && git add file && - ! git commit -m "another" + test_must_fail git commit -m "another" ' diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index d4cf6289a..5eeb6c2b2 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -126,7 +126,7 @@ verify_merge() { echo "[OOPS] unmerged files" false fi && - if ! git diff --exit-code + if test_must_fail git diff --exit-code then echo "[OOPS] working tree != index" false @@ -222,36 +222,12 @@ test_expect_success 'setup' ' test_debug 'gitk --all' test_expect_success 'test option parsing' ' - if git merge -$ c1 - then - echo "[OOPS] -$ accepted" - false - fi && - if git merge --no-such c1 - then - echo "[OOPS] --no-such accepted" - false - fi && - if git merge -s foobar c1 - then - echo "[OOPS] -s foobar accepted" - false - fi && - if git merge -s=foobar c1 - then - echo "[OOPS] -s=foobar accepted" - false - fi && - if git merge -m - then - echo "[OOPS] missing commit msg accepted" - false - fi && - if git merge - then - echo "[OOPS] missing commit references accepted" - false - fi + test_must_fail git merge -$ c1 && + test_must_fail git merge --no-such c1 && + test_must_fail git merge -s foobar c1 && + test_must_fail git merge -s=foobar c1 && + test_must_fail git merge -m && + test_must_fail git merge ' test_expect_success 'merge c0 with c1' ' diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index 6b0483f3e..9285071c4 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -35,7 +35,7 @@ test_expect_success 'custom mergetool' ' git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" && git config mergetool.mytool.trustExitCode true && git checkout branch1 && - ! git merge master >/dev/null 2>&1 && + test_must_fail git merge master >/dev/null 2>&1 && ( yes "" | git mergetool file1>/dev/null 2>&1 ) && ( yes "" | git mergetool file2>/dev/null 2>&1 ) && test "$(cat file1)" = "master updated" && diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 3e4eb63f1..1c857cf4a 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -13,7 +13,7 @@ test_expect_success \ test_expect_success \ 'Setup helper tool' \ - '(echo "#!/bin/sh" + '(echo "#!$SHELL_PATH" echo shift echo output=1 echo "while test -f commandline\$output; do output=\$((\$output+1)); done" @@ -91,7 +91,7 @@ test_expect_success 'reject long lines' ' clean_fake_sendmail && cp $patches longline.patch && echo $z512$z512 >>longline.patch && - ! git send-email \ + test_must_fail git send-email \ --from="Example <nobody@example.com>" \ --to=nobody@example.com \ --smtp-server="$(pwd)/fake.sendmail" \ @@ -138,7 +138,7 @@ test_expect_success 'Valid In-Reply-To when prompting' ' ' test_expect_success 'setup fake editor' ' - (echo "#!/bin/sh" && + (echo "#!$SHELL_PATH" && echo "echo fake edit >>\"\$1\"" ) >fake-editor && chmod +x fake-editor @@ -235,7 +235,7 @@ test_expect_success 'sendemail.cc unset' ' test_expect_success '--compose adds MIME for utf8 body' ' clean_fake_sendmail && - (echo "#!/bin/sh" && + (echo "#!$SHELL_PATH" && echo "echo utf8 body: àéìöú >>\"\$1\"" ) >fake-editor-utf8 && chmod +x fake-editor-utf8 && @@ -254,7 +254,7 @@ test_expect_success '--compose adds MIME for utf8 body' ' test_expect_success '--compose respects user mime type' ' clean_fake_sendmail && - (echo "#!/bin/sh" && + (echo "#!$SHELL_PATH" && echo "(echo MIME-Version: 1.0" echo " echo Content-Type: text/plain\\; charset=iso-8859-1" echo " echo Content-Transfer-Encoding: 8bit" diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index 3bc616412..843a5013b 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -63,7 +63,7 @@ test_expect_success "$name" " git update-index --remove dir/file && git update-index --add dir/file/file && git commit -m '$name' && - ! git-svn set-tree --find-copies-harder --rmdir \ + test_must_fail git-svn set-tree --find-copies-harder --rmdir \ remotes/git-svn..mybranch" || true @@ -77,7 +77,7 @@ test_expect_success "$name" ' git update-index --remove -- bar/zzz && git update-index --add -- bar && git commit -m "$name" && - ! git-svn set-tree --find-copies-harder --rmdir \ + test_must_fail git-svn set-tree --find-copies-harder --rmdir \ remotes/git-svn..mybranch2' || true @@ -91,7 +91,7 @@ test_expect_success "$name" ' echo yyy > bar/zzz/yyy && git update-index --add bar/zzz/yyy && git commit -m "$name" && - ! git-svn set-tree --find-copies-harder --rmdir \ + test_must_fail git-svn set-tree --find-copies-harder --rmdir \ remotes/git-svn..mybranch3' || true @@ -105,7 +105,7 @@ test_expect_success "$name" ' echo asdf > dir && git update-index --add -- dir && git commit -m "$name" && - ! git-svn set-tree --find-copies-harder --rmdir \ + test_must_fail git-svn set-tree --find-copies-harder --rmdir \ remotes/git-svn..mybranch4' || true @@ -216,7 +216,7 @@ test_expect_success "$name" "test_cmp a expected" test_expect_success 'exit if remote refs are ambigious' " git config --add svn-remote.svn.fetch \ bar:refs/remotes/git-svn && - ! git-svn migrate + test_must_fail git-svn migrate " test_expect_success 'exit if init-ing a would clobber a URL' ' @@ -224,7 +224,7 @@ test_expect_success 'exit if init-ing a would clobber a URL' ' svn mkdir -m "mkdir bar" "${svnrepo}2/bar" && git config --unset svn-remote.svn.fetch \ "^bar:refs/remotes/git-svn$" && - ! git-svn init "${svnrepo}2/bar" + test_must_fail git-svn init "${svnrepo}2/bar" ' test_expect_success \ diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh index 27a65e05d..08bf1f08e 100755 --- a/t/t9106-git-svn-commit-diff-clobber.sh +++ b/t/t9106-git-svn-commit-diff-clobber.sh @@ -27,7 +27,7 @@ test_expect_success 'commit change from svn side' ' test_expect_success 'commit conflicting change from git' ' echo second line from git >> file && git commit -a -m "second line from git" && - ! git-svn commit-diff -r1 HEAD~1 HEAD "$svnrepo" + test_must_fail git-svn commit-diff -r1 HEAD~1 HEAD "$svnrepo" ' test_expect_success 'commit complementing change from git' ' @@ -52,7 +52,7 @@ test_expect_success 'dcommit fails to commit because of conflict' ' rm -rf t.svn && echo "fourth line from git" >> file && git commit -a -m "fourth line from git" && - ! git-svn dcommit + test_must_fail git-svn dcommit ' test_expect_success 'dcommit does the svn equivalent of an index merge' " @@ -83,7 +83,7 @@ test_expect_success 'multiple dcommit from git-svn will not clobber svn' " git commit -a -m 'new file' && echo clobber > file && git commit -a -m 'clobber' && - ! git svn dcommit + test_must_fail git svn dcommit " diff --git a/t/t9106-git-svn-dcommit-clobber-series.sh b/t/t9106-git-svn-dcommit-clobber-series.sh index f8f4718c3..bc37db9d6 100755 --- a/t/t9106-git-svn-dcommit-clobber-series.sh +++ b/t/t9106-git-svn-dcommit-clobber-series.sh @@ -57,7 +57,7 @@ test_expect_success 'change file but in unrelated area' " test_expect_success 'attempt to dcommit with a dirty index' ' echo foo >>file && git add file && - ! git svn dcommit + test_must_fail git svn dcommit ' test_done diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh index b1dc32d05..3e32e84e6 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -100,7 +100,7 @@ test_expect_success \ git commit -a -m "generation 2" && id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && - ! git cvsexportcommit -c $id + test_must_fail git cvsexportcommit -c $id )' #test_expect_success \ @@ -112,7 +112,7 @@ test_expect_success \ # git commit -a -m "generation 3" && # id=$(git rev-list --max-count=1 HEAD) && # (cd "$CVSWORK" && -# ! git cvsexportcommit -c $id +# test_must_fail git cvsexportcommit -c $id # )' # We reuse the state from two tests back here @@ -222,7 +222,7 @@ test_expect_success \ git commit -a -m "Update two" && id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && - ! git-cvsexportcommit -c $id + test_must_fail git-cvsexportcommit -c $id )' case "$(git config --bool core.filemode)" in diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 5edf56f19..1fc06c5a2 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -166,7 +166,7 @@ M 755 0000000000000000000000000000000000000001 zero1 INPUT_END test_expect_success 'B: fail on invalid blob sha1' ' - ! git-fast-import <input + test_must_fail git-fast-import <input ' rm -f .git/objects/pack_* .git/objects/index_* @@ -181,7 +181,7 @@ from refs/heads/master INPUT_END test_expect_success 'B: fail on invalid branch name ".badbranchname"' ' - ! git-fast-import <input + test_must_fail git-fast-import <input ' rm -f .git/objects/pack_* .git/objects/index_* @@ -196,7 +196,7 @@ from refs/heads/master INPUT_END test_expect_success 'B: fail on invalid branch name "bad[branch]name"' ' - ! git-fast-import <input + test_must_fail git-fast-import <input ' rm -f .git/objects/pack_* .git/objects/index_* @@ -340,7 +340,7 @@ from refs/heads/branch^0 INPUT_END test_expect_success 'E: rfc2822 date, --date-format=raw' ' - ! git-fast-import --date-format=raw <input + test_must_fail git-fast-import --date-format=raw <input ' test_expect_success \ 'E: rfc2822 date, --date-format=rfc2822' \ @@ -918,4 +918,156 @@ test_expect_success \ grep "progress " <input >expect && test_cmp expect actual' +### +### series P (gitlinks) +### + +cat >input <<INPUT_END +blob +mark :1 +data 10 +test file + +reset refs/heads/sub +commit refs/heads/sub +mark :2 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 12 +sub_initial +M 100644 :1 file + +blob +mark :3 +data <<DATAEND +[submodule "sub"] + path = sub + url = "`pwd`/sub" +DATAEND + +commit refs/heads/subuse1 +mark :4 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 8 +initial +from refs/heads/master +M 100644 :3 .gitmodules +M 160000 :2 sub + +blob +mark :5 +data 20 +test file +more data + +commit refs/heads/sub +mark :6 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 11 +sub_second +from :2 +M 100644 :5 file + +commit refs/heads/subuse1 +mark :7 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 7 +second +from :4 +M 160000 :6 sub + +INPUT_END + +test_expect_success \ + 'P: supermodule & submodule mix' \ + 'git-fast-import <input && + git checkout subuse1 && + rm -rf sub && mkdir sub && cd sub && + git init && + git fetch .. refs/heads/sub:refs/heads/master && + git checkout master && + cd .. && + git submodule init && + git submodule update' + +SUBLAST=$(git-rev-parse --verify sub) +SUBPREV=$(git-rev-parse --verify sub^) + +cat >input <<INPUT_END +blob +mark :1 +data <<DATAEND +[submodule "sub"] + path = sub + url = "`pwd`/sub" +DATAEND + +commit refs/heads/subuse2 +mark :2 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 8 +initial +from refs/heads/master +M 100644 :1 .gitmodules +M 160000 $SUBPREV sub + +commit refs/heads/subuse2 +mark :3 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 7 +second +from :2 +M 160000 $SUBLAST sub + +INPUT_END + +test_expect_success \ + 'P: verbatim SHA gitlinks' \ + 'git branch -D sub && + git gc && git prune && + git-fast-import <input && + test $(git-rev-parse --verify subuse2) = $(git-rev-parse --verify subuse1)' + +test_tick +cat >input <<INPUT_END +commit refs/heads/subuse3 +mark :1 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +corrupt +COMMIT + +from refs/heads/subuse2 +M 160000 inline sub +data <<DATA +$SUBPREV +DATA + +INPUT_END + +test_expect_success 'P: fail on inline gitlink' ' + ! git-fast-import <input' + +test_tick +cat >input <<INPUT_END +blob +mark :1 +data <<DATA +$SUBPREV +DATA + +commit refs/heads/subuse3 +mark :2 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +corrupt +COMMIT + +from refs/heads/subuse2 +M 160000 :1 sub + +INPUT_END + +test_expect_success 'P: fail on blob mark in gitlink' ' + ! git-fast-import <input' + test_done diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh index f1bc5ceef..8324f6e3b 100755 --- a/t/t9301-fast-export.sh +++ b/t/t9301-fast-export.sh @@ -59,7 +59,7 @@ test_expect_success 'fast-export master~2..master' ' test $MASTER != $(git rev-parse --verify refs/heads/partial) && git diff master..partial && git diff master^..partial^ && - ! git rev-parse partial~2) + test_must_fail git rev-parse partial~2) ' @@ -125,7 +125,7 @@ test_expect_success 'set up faked signed tag' ' test_expect_success 'signed-tags=abort' ' - ! git fast-export --signed-tags=abort sign-your-name + test_must_fail git fast-export --signed-tags=abort sign-your-name ' @@ -143,4 +143,46 @@ test_expect_success 'signed-tags=strip' ' ' +test_expect_success 'setup submodule' ' + + git checkout -f master && + mkdir sub && + cd sub && + git init && + echo test file > file && + git add file && + git commit -m sub_initial && + cd .. && + git submodule add "`pwd`/sub" sub && + git commit -m initial && + test_tick && + cd sub && + echo more data >> file && + git add file && + git commit -m sub_second && + cd .. && + git add sub && + git commit -m second + +' + +test_expect_success 'submodule fast-export | fast-import' ' + + SUBENT1=$(git ls-tree master^ sub) && + SUBENT2=$(git ls-tree master sub) && + rm -rf new && + mkdir new && + git --git-dir=new/.git init && + git fast-export --signed-tags=strip --all | + (cd new && + git fast-import && + test "$SUBENT1" = "$(git ls-tree refs/heads/master^ sub)" && + test "$SUBENT2" = "$(git ls-tree refs/heads/master sub)" && + git checkout master && + git submodule init && + git submodule update && + cmp sub/file ../sub/file) + +' + test_done diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index e97aaa6c2..4b91f8d4c 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -438,6 +438,13 @@ test_expect_success 'cvs update (-p)' ' test -z "$(cat failures)" ' +cd "$WORKDIR" +test_expect_success 'cvs update (module list supports packed refs)' ' + GIT_DIR="$SERVERDIR" git pack-refs --all && + GIT_CONFIG="$git_config" cvs -n up -d 2> out && + grep "cvs update: New directory \`master'\''" < out +' + #------------ # CVS STATUS #------------ @@ -470,4 +477,15 @@ test_expect_success 'cvs status (no subdirs in header)' ' ! grep / <../out ' +#------------ +# CVS CHECKOUT +#------------ + +cd "$WORKDIR" +test_expect_success 'cvs co -c (shows module database)' ' + GIT_CONFIG="$git_config" cvs co -c > out && + grep "^master[ ]\+master$" < out && + ! grep -v "^master[ ]\+master$" < out +' + test_done diff --git a/t/t9600-cvsimport.sh b/t/t9600-cvsimport.sh index 1e01e5c74..0d7786a8c 100755 --- a/t/t9600-cvsimport.sh +++ b/t/t9600-cvsimport.sh @@ -5,6 +5,7 @@ test_description='git-cvsimport basic tests' CVSROOT=$(pwd)/cvsroot export CVSROOT +unset CVS_SERVER # for clean cvsps cache HOME=$(pwd) export HOME diff --git a/t/test-lib.sh b/t/test-lib.sh index 8e2849b5c..11c027571 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -379,7 +379,7 @@ test_external_without_stderr () { test_must_fail () { "$@" - test $? -gt 0 -a $? -le 129 + test $? -gt 0 -a $? -le 129 -o $? -gt 192 } # test_cmp is a helper function to compare actual and expected output. diff --git a/tree-diff.c b/tree-diff.c index e1e2e6c6c..bbb126fc4 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -15,6 +15,15 @@ static char *malloc_base(const char *base, int baselen, const char *path, int pa return newbase; } +static char *malloc_fullname(const char *base, int baselen, const char *path, int pathlen) +{ + char *fullname = xmalloc(baselen + pathlen + 1); + memcpy(fullname, base, baselen); + memcpy(fullname + baselen, path, pathlen); + fullname[baselen + pathlen] = 0; + return fullname; +} + static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen); @@ -24,6 +33,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const const char *path1, *path2; const unsigned char *sha1, *sha2; int cmp, pathlen1, pathlen2; + char *fullname; sha1 = tree_entry_extract(t1, &path1, &mode1); sha2 = tree_entry_extract(t2, &path2, &mode2); @@ -55,15 +65,20 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) { int retval; char *newbase = malloc_base(base, baselen, path1, pathlen1); - if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) + if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) { + newbase[baselen + pathlen1] = 0; opt->change(opt, mode1, mode2, - sha1, sha2, base, path1); + sha1, sha2, newbase); + newbase[baselen + pathlen1] = '/'; + } retval = diff_tree_sha1(sha1, sha2, newbase, opt); free(newbase); return retval; } - opt->change(opt, mode1, mode2, sha1, sha2, base, path1); + fullname = malloc_fullname(base, baselen, path1, pathlen1); + opt->change(opt, mode1, mode2, sha1, sha2, fullname); + free(fullname); return 0; } @@ -205,10 +220,10 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree unsigned mode; const char *path; const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode); + int pathlen = tree_entry_len(path, sha1); if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) { enum object_type type; - int pathlen = tree_entry_len(path, sha1); char *newbase = malloc_base(base, baselen, path, pathlen); struct tree_desc inner; void *tree; @@ -224,7 +239,9 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree free(tree); free(newbase); } else { - opt->add_remove(opt, prefix[0], mode, sha1, base, path); + char *fullname = malloc_fullname(base, baselen, path, pathlen); + opt->add_remove(opt, prefix[0], mode, sha1, fullname); + free(fullname); } } @@ -29,7 +29,7 @@ static int read_one_entry_opt(const unsigned char *sha1, const char *base, int b return add_cache_entry(ce, opt); } -static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage) +static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) { return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); @@ -39,7 +39,7 @@ static int read_one_entry(const unsigned char *sha1, const char *base, int basel * This is used when the caller knows there is no existing entries at * the stage that will conflict with the entry being added. */ -static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage) +static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) { return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, ADD_CACHE_JUST_APPEND); @@ -92,7 +92,7 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns int read_tree_recursive(struct tree *tree, const char *base, int baselen, int stage, const char **match, - read_tree_fn_t fn) + read_tree_fn_t fn, void *context) { struct tree_desc desc; struct name_entry entry; @@ -106,7 +106,7 @@ int read_tree_recursive(struct tree *tree, if (!match_tree_entry(base, baselen, entry.path, entry.mode, match)) continue; - switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage)) { + switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) { case 0: continue; case READ_TREE_RECURSIVE: @@ -126,7 +126,7 @@ int read_tree_recursive(struct tree *tree, retval = read_tree_recursive(lookup_tree(entry.sha1), newbase, baselen + pathlen + 1, - stage, match, fn); + stage, match, fn, context); free(newbase); if (retval) return -1; @@ -174,7 +174,7 @@ int read_tree(struct tree *tree, int stage, const char **match) if (!fn) fn = read_one_entry_quick; - err = read_tree_recursive(tree, "", 0, stage, match, fn); + err = read_tree_recursive(tree, "", 0, stage, match, fn, NULL); if (fn == read_one_entry || err) return err; @@ -21,12 +21,12 @@ int parse_tree(struct tree *tree); struct tree *parse_tree_indirect(const unsigned char *sha1); #define READ_TREE_RECURSIVE 1 -typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int); +typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int, void *); extern int read_tree_recursive(struct tree *tree, const char *base, int baselen, int stage, const char **match, - read_tree_fn_t fn); + read_tree_fn_t fn, void *context); extern int read_tree(struct tree *tree, int stage, const char **paths); diff --git a/update-server-info.c b/update-server-info.c index 0b6c3835b..7e8209ea4 100644 --- a/update-server-info.c +++ b/update-server-info.c @@ -1,7 +1,7 @@ #include "cache.h" static const char update_server_info_usage[] = -"git-update-server-info [--force]"; +"git update-server-info [--force]"; int main(int ac, char **av) { @@ -133,6 +133,44 @@ ssize_t xwrite(int fd, const void *buf, size_t len) } } +ssize_t read_in_full(int fd, void *buf, size_t count) +{ + char *p = buf; + ssize_t total = 0; + + while (count > 0) { + ssize_t loaded = xread(fd, p, count); + if (loaded <= 0) + return total ? total : loaded; + count -= loaded; + p += loaded; + total += loaded; + } + + return total; +} + +ssize_t write_in_full(int fd, const void *buf, size_t count) +{ + const char *p = buf; + ssize_t total = 0; + + while (count > 0) { + ssize_t written = xwrite(fd, p, count); + if (written < 0) + return -1; + if (!written) { + errno = ENOSPC; + return -1; + } + count -= written; + p += written; + total += written; + } + + return total; +} + int xdup(int fd) { int ret = dup(fd); diff --git a/write_or_die.c b/write_or_die.c index e4c8e225f..4c29255df 100644 --- a/write_or_die.c +++ b/write_or_die.c @@ -45,44 +45,6 @@ void maybe_flush_or_die(FILE *f, const char *desc) } } -ssize_t read_in_full(int fd, void *buf, size_t count) -{ - char *p = buf; - ssize_t total = 0; - - while (count > 0) { - ssize_t loaded = xread(fd, p, count); - if (loaded <= 0) - return total ? total : loaded; - count -= loaded; - p += loaded; - total += loaded; - } - - return total; -} - -ssize_t write_in_full(int fd, const void *buf, size_t count) -{ - const char *p = buf; - ssize_t total = 0; - - while (count > 0) { - ssize_t written = xwrite(fd, p, count); - if (written < 0) - return -1; - if (!written) { - errno = ENOSPC; - return -1; - } - count -= written; - p += written; - total += written; - } - - return total; -} - void fsync_or_die(int fd, const char *msg) { if (fsync(fd) < 0) { |