Code

Merge branch 'jm/format-patch-no-auto-n-when-k-is-given'
authorJunio C Hamano <gitster@pobox.com>
Sat, 23 May 2009 08:40:22 +0000 (01:40 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 23 May 2009 08:40:22 +0000 (01:40 -0700)
* jm/format-patch-no-auto-n-when-k-is-given:
  format-patch let -k override a config-specified format.numbered

117 files changed:
Documentation/RelNotes-1.6.3.1.txt [new file with mode: 0644]
Documentation/RelNotes-1.6.4.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-add.txt
Documentation/git-branch.txt
Documentation/git-check-ref-format.txt
Documentation/git-clone.txt
Documentation/git-config.txt
Documentation/git-ls-tree.txt
Documentation/git-rebase.txt
Documentation/git-show-branch.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/technical/api-parse-options.txt
Makefile
RelNotes
alias.c
archive-tar.c
builtin-add.c
builtin-apply.c
builtin-branch.c
builtin-checkout.c
builtin-clone.c
builtin-fetch-pack.c
builtin-fetch.c
builtin-for-each-ref.c
builtin-grep.c
builtin-ls-files.c
builtin-prune-packed.c
builtin-prune.c
builtin-receive-pack.c
builtin-remote.c
builtin-rerere.c
builtin-send-pack.c
builtin-show-branch.c
builtin-tag.c
builtin-verify-tag.c
bundle.c
contrib/completion/git-completion.bash
decorate.c
diff.c
dir.c
entry.c
fast-import.c
git-compat-util.h
git-merge-one-file.sh
git-send-email.perl
git-submodule.sh
git-svn.perl
gitweb/gitweb.perl
graph.c
grep.c
grep.h
http-push.c
http-walker.c
ll-merge.c
lockfile.c
merge-recursive.c
object.c
pack-refs.c
parse-options.c
parse-options.h
perl/Git.pm
refs.c
rerere.c
send-pack.h
server-info.c
sha1_file.c
t/lib-git-svn.sh
t/t0040-parse-options.sh
t/t2014-switch.sh [new file with mode: 0755]
t/t3031-merge-criscross.sh [new file with mode: 0755]
t/t3702-add-edit.sh [new file with mode: 0755]
t/t3900-i18n-commit.sh
t/t4014-format-patch.sh
t/t4021-format-patch-numbered.sh
t/t4202-log.sh
t/t7201-co.sh
t/t7406-submodule-reference.sh [new file with mode: 0755]
t/t9100-git-svn-basic.sh
t/t9101-git-svn-props.sh
t/t9102-git-svn-deep-rmdir.sh
t/t9103-git-svn-tracked-directory-removed.sh
t/t9104-git-svn-follow-parent.sh
t/t9105-git-svn-commit-diff.sh
t/t9106-git-svn-commit-diff-clobber.sh
t/t9107-git-svn-migrate.sh
t/t9108-git-svn-glob.sh
t/t9109-git-svn-multi-glob.sh
t/t9113-git-svn-dcommit-new-file.sh
t/t9114-git-svn-dcommit-merge.sh
t/t9116-git-svn-log.sh
t/t9117-git-svn-init-clone.sh
t/t9118-git-svn-funky-branch-names.sh
t/t9119-git-svn-info.sh
t/t9120-git-svn-clone-with-percent-escapes.sh
t/t9122-git-svn-author.sh
t/t9123-git-svn-rebuild-with-rewriteroot.sh
t/t9124-git-svn-dcommit-auto-props.sh
t/t9125-git-svn-multi-glob-branch-names.sh
t/t9127-git-svn-partial-rebuild.sh
t/t9128-git-svn-cmd-branch.sh
t/t9129-git-svn-i18n-commitencoding.sh
t/t9130-git-svn-authors-file.sh
t/t9133-git-svn-nested-git-repo.sh
t/t9134-git-svn-ignore-paths.sh
t/t9137-git-svn-dcommit-clobber-series.sh
t/t9138-git-svn-authors-prog.sh [new file with mode: 0755]
t/t9700-perl-git.sh
t/t9700/test.pl
templates/hooks--pre-commit.sample
templates/hooks--update.sample
test-parse-options.c
transport.c
transport.h
unpack-trees.c
wrapper.c

diff --git a/Documentation/RelNotes-1.6.3.1.txt b/Documentation/RelNotes-1.6.3.1.txt
new file mode 100644 (file)
index 0000000..2400b72
--- /dev/null
@@ -0,0 +1,10 @@
+GIT v1.6.3.1 Release Notes
+==========================
+
+Fixes since v1.6.3
+------------------
+
+* "git checkout -b new-branch" with a staged change in the index
+  incorrectly primed the in-index cache-tree, resulting a wrong tree
+  object to be written out of the index.  This is a grave regression
+  since the last 1.6.2.X maintenance release.
diff --git a/Documentation/RelNotes-1.6.4.txt b/Documentation/RelNotes-1.6.4.txt
new file mode 100644 (file)
index 0000000..b70ec11
--- /dev/null
@@ -0,0 +1,59 @@
+GIT v1.6.4 Release Notes
+========================
+
+With the next major release, "git push" into a branch that is
+currently checked out will be refused by default.  You can choose
+what should happen upon such a push by setting the configuration
+variable receive.denyCurrentBranch in the receiving repository.
+
+To ease the transition plan, the receiving repository of such a
+push running this release will issue a big warning when the
+configuration variable is missing.  Please refer to:
+
+  http://git.or.cz/gitwiki/GitFaq#non-bare
+  http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
+
+for more details on the reason why this change is needed and the
+transition plan.
+
+For a similar reason, "git push $there :$killed" to delete the branch
+$killed in a remote repository $there, if $killed branch is the current
+branch pointed at by its HEAD, gets a large warning.  You can choose what
+should happen upon such a push by setting the configuration variable
+receive.denyDeleteCurrent in the receiving repository.
+
+When the user does not tell "git push" what to push, it has always
+pushed matching refs.  For some people it is unexpected, and a new
+configuration variable push.default has been introduced to allow
+changing a different default behaviour.  To advertise the new feature,
+a big warning is issued if this is not configured and a git push without
+arguments is attempted.
+
+
+Updates since v1.6.3
+--------------------
+
+(subsystems)
+
+(performance)
+
+(usability, bells and whistles)
+
+(developers)
+
+
+Fixes since v1.6.3
+------------------
+
+All of the fixes in v1.6.3.X maintenance series are included in this
+release, unless otherwise noted.
+
+Here are fixes that this release has, but have not been backported to
+v1.6.3.X series.
+
+
+---
+exec >/var/tmp/1
+echo O=$(git describe master)
+O=v1.6.3
+git shortlog --no-merges $O..master ^maint
index 5dcad94f841c395beb21961ebdacd341d76b25c9..2c031620c50f8e3eaaa652aaf43ee261eab8f957 100644 (file)
@@ -604,6 +604,12 @@ color.pager::
        A boolean to enable/disable colored output when the pager is in
        use (default is true).
 
+color.showbranch::
+       A boolean to enable/disable color in the output of
+       linkgit:git-show-branch[1]. May be set to `always`,
+       `false` (or `never`) or `auto` (or `true`), in which case colors are used
+       only when the output is to a terminal. Defaults to false.
+
 color.status::
        A boolean to enable/disable color in the output of
        linkgit:git-status[1]. May be set to `always`,
index d938b422893067feb1a430edb34fb51ef7db6d85..ab1943c71243df245f84ede7a69e4c666a8d8834 100644 (file)
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
-         [--all | [--update | -u]] [--intent-to-add | -N]
+         [--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
          [--refresh] [--ignore-errors] [--] <filepattern>...
 
 DESCRIPTION
@@ -76,6 +76,15 @@ OPTIONS
        bypassed and the 'patch' subcommand is invoked using each of
        the specified filepatterns before exiting.
 
+-e, \--edit::
+       Open the diff vs. the index in an editor and let the user
+       edit it.  After the editor was closed, adjust the hunk headers
+       and apply the patch to the index.
++
+*NOTE*: Obviously, if you change anything else than the first character
+on lines beginning with a space or a minus, the patch will no longer
+apply.
+
 -u::
 --update::
        Update only files that git already knows about, staging modified
index cbd427587188d81726445183f772f02982736e6a..ae201deb7af44c61e793ab408e916c5b6520800d 100644 (file)
@@ -111,6 +111,7 @@ OPTIONS
 --no-abbrev::
        Display the full sha1s in the output listing rather than abbreviating them.
 
+-t::
 --track::
        When creating a new branch, set up configuration to mark the
        start-point branch as "upstream" from the new branch. This
index c1ce26884e73f1599602472ba5032988486cc465..0b7982ea76633e45b8d3073cd275ea74a757c0eb 100644 (file)
@@ -25,6 +25,10 @@ imposes the following rules on how references are named:
   grouping, but no slash-separated component can begin with a
   dot `.`.
 
+. They must contain at least one `/`. This enforces the presence of a
+  category like `heads/`, `tags/` etc. but the actual names are not
+  restricted.
+
 . They cannot have two consecutive dots `..` anywhere.
 
 . They cannot have ASCII control characters (i.e. bytes whose
@@ -38,6 +42,8 @@ imposes the following rules on how references are named:
 
 . They cannot contain a sequence `@{`.
 
+- They cannot contain a `\\`.
+
 These rules make it easy for shell script based tools to parse
 reference names, pathname expansion by the shell when a reference name is used
 unquoted (by mistake), and also avoids ambiguities in certain
index 4072f40d7ae5417c51d1cddcf587b674aa1dc0e5..b14de6c407b8bd0bc001c608ca4f26fc619abf3e 100644 (file)
@@ -149,7 +149,7 @@ then the cloned repository will become corrupt.
        part of the source repository is used if no directory is
        explicitly given ("repo" for "/path/to/repo.git" and "foo"
        for "host.xz:foo/.git").  Cloning into an existing directory
-       is not allowed.
+       is only allowed if the directory is empty.
 
 :git-clone: 1
 include::urls.txt[]
index 7131ee3c66951de5981a82e304f4619de88064c5..f68b198205d3a4d808ce58e6b0ac03e70bb160a4 100644 (file)
@@ -69,7 +69,8 @@ OPTIONS
 
 --add::
        Adds a new line to the option without altering any existing
-       values.  This is the same as providing '^$' as the value_regex.
+       values.  This is the same as providing '^$' as the value_regex
+       in `--replace-all`.
 
 --get::
        Get the value for a given key (optionally filtered by a regex
@@ -155,7 +156,7 @@ See also <<FILES>>.
        When the color setting for `name` is undefined, the command uses
        `color.ui` as fallback.
 
---get-color name default::
+--get-color name [default]::
 
        Find the color configured for `name` (e.g. `color.diff.new`) and
        output it as the ANSI color escape sequence to the standard
index f68e5c5c1abd15350e679eebf976f0ac8516123b..c3fdccb4c2f66b8b3a3c6b60b21feac881b06cb4 100644 (file)
@@ -82,8 +82,10 @@ Output Format
 -------------
         <mode> SP <type> SP <object> TAB <file>
 
-When the `-z` option is not used, TAB, LF, and backslash characters
+Unless the `-z` option is used, TAB, LF, and backslash characters
 in pathnames are represented as `\t`, `\n`, and `\\`, respectively.
+This output format is compatible with what '--index-info --stdin' of
+'git update-index' expects.
 
 When the `-l` option is used, format changes to
 
index 3d5a066c31675e502eb027dde824d1966c9c0f09..26f3b7b2b0daad0affb36e6514156520a693b164 100644 (file)
@@ -231,8 +231,7 @@ OPTIONS
 
 -s <strategy>::
 --strategy=<strategy>::
-       Use the given merge strategy; can be supplied more than
-       once to specify them in the order they should be tried.
+       Use the given merge strategy.
        If there is no `-s` option, a built-in list of strategies
        is used instead ('git-merge-recursive' when merging a single
        head, 'git-merge-octopus' otherwise).  This implies --merge.
index 51a4e9d6d767f34205f418ec86a6281dbf4c7b2c..edd8f6463ebab38f950db634e28fe5f06cf3915a 100644 (file)
@@ -10,6 +10,7 @@ SYNOPSIS
 [verse]
 'git show-branch' [--all] [--remotes] [--topo-order] [--current]
                [--more=<n> | --list | --independent | --merge-base]
+               [--color | --no-color]
                [--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
 'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
 
@@ -107,6 +108,14 @@ OPTIONS
        When no explicit <ref> parameter is given, it defaults to the
        current branch (or `HEAD` if it is detached).
 
+--color::
+       Color the status sign (one of these: `*` `!` `+` `-`) of each commit
+       corresponding to the branch it's in.
+
+--no-color::
+       Turn off colored output, even when the configuration file gives the
+       default to color output.
+
 Note that --more, --list, --independent and --merge-base options
 are mutually exclusive.
 
index 3b8df4467377d73d613f76875c725cbf8544ee77..14256c695b3817014be8ba4f45a62a2cd588939c 100644 (file)
@@ -9,10 +9,12 @@ git-submodule - Initialize, update or inspect submodules
 SYNOPSIS
 --------
 [verse]
-'git submodule' [--quiet] add [-b branch] [--] <repository> <path>
+'git submodule' [--quiet] add [-b branch]
+             [--reference <repository>] [--] <repository> <path>
 'git submodule' [--quiet] status [--cached] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
-'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--] [<path>...]
+'git submodule' [--quiet] update [--init] [-N|--no-fetch]
+             [--reference <repository>] [--] [<path>...]
 'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
 'git submodule' [--quiet] foreach <command>
 'git submodule' [--quiet] sync [--] [<path>...]
@@ -177,6 +179,14 @@ OPTIONS
        This option is only valid for the update command.
        Don't fetch new objects from the remote site.
 
+--reference <repository>::
+       This option is only valid for add and update commands.  These
+       commands sometimes need to clone a remote repository. In this case,
+       this option will be passed to the linkgit:git-clone[1] command.
++
+*NOTE*: Do *not* use this option unless you have read the note
+for linkgit:git-clone[1]'s --reference and --shared options carefully.
+
 <path>...::
        Paths to submodule(s). When specified this will restrict the command
        to only operate on the submodules found at the specified paths.
index 1c40894669d6f86e7dbb97d86ef9ee6f2a76190d..ca3fc3de1fcfc3509a9d5d1ff268c9673bafc3c0 100644 (file)
@@ -398,6 +398,14 @@ after the authors-file is modified should continue operation.
 
 config key: svn.authorsfile
 
+--authors-prog=<filename>::
+
+If this option is specified, for each SVN committer name that does not
+exist in the authors file, the given file is executed with the committer
+name as the first argument.  The program is expected to return a single
+line of the form "Name <email>", which will be treated as if included in
+the authors file.
+
 -q::
 --quiet::
        Make 'git-svn' less verbose. Specify a second time to make it
index e66ca9f70c705841c864196a3a651e04d8156e01..b43458eae6787caab163fadab113dff61e577498 100644 (file)
@@ -137,6 +137,10 @@ There are some macros to easily define options:
        Introduce a boolean option.
        If used, `int_var` is bitwise-ored with `mask`.
 
+`OPT_NEGBIT(short, long, &int_var, description, mask)`::
+       Introduce a boolean option.
+       If used, `int_var` is bitwise-anded with the inverted `mask`.
+
 `OPT_SET_INT(short, long, &int_var, description, integer)`::
        Introduce a boolean option.
        If used, set `int_var` to `integer`.
@@ -166,6 +170,14 @@ There are some macros to easily define options:
 `OPT_ARGUMENT(long, description)`::
        Introduce a long-option argument that will be kept in `argv[]`.
 
+`OPT_NUMBER_CALLBACK(&var, description, func_ptr)`::
+       Recognize numerical options like -123 and feed the integer as
+       if it was an argument to the function given by `func_ptr`.
+       The result will be put into `var`.  There can be only one such
+       option definition.  It cannot be negated and it takes no
+       arguments.  Short options that happen to be digits take
+       precedence over it.
+
 
 The last element of the array must be `OPT_END()`.
 
@@ -198,7 +210,7 @@ The function must be defined in this form:
 
 The callback mechanism is as follows:
 
-* Inside `funct`, the only interesting member of the structure
+* Inside `func`, the only interesting member of the structure
   given by `opt` is the void pointer `opt->value`.
   `\*opt->value` will be the value that is saved into `var`, if you
   use `OPT_CALLBACK()`.
index 6e216436c36f4dcbe1121d02a291e9f568ca6071..26d180cc5422c968f5bde4ae4a300347b3f33e02 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -749,6 +749,7 @@ endif
 ifeq ($(uname_S),OpenBSD)
        NO_STRCASESTR = YesPlease
        NO_MEMMEM = YesPlease
+       USE_ST_TIMESPEC = YesPlease
        NEEDS_LIBICONV = YesPlease
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
index dd8bc4bb4ab75e1148cb9b7aaf8ff7384ebb19ec..f8e49a5070afc21fbd3db9320841300fe93c570f 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.3.txt
\ No newline at end of file
+Documentation/RelNotes-1.6.4.txt
\ No newline at end of file
diff --git a/alias.c b/alias.c
index e687fe54c1ce2a435e8f0d7806db231c06f998eb..372b7d809301f9e3e936459e405cd6f2627bd4a9 100644 (file)
--- a/alias.c
+++ b/alias.c
@@ -38,10 +38,7 @@ int split_cmdline(char *cmdline, const char ***argv)
                        while (cmdline[++src]
                                        && isspace(cmdline[src]))
                                ; /* skip */
-                       if (count >= size) {
-                               size += 16;
-                               *argv = xrealloc(*argv, sizeof(char *) * size);
-                       }
+                       ALLOC_GROW(*argv, count+1, size);
                        (*argv)[count++] = cmdline + dst;
                } else if (!quoted && (c == '\'' || c == '"')) {
                        quoted = c;
@@ -72,6 +69,9 @@ int split_cmdline(char *cmdline, const char ***argv)
                return error("unclosed quote");
        }
 
+       ALLOC_GROW(*argv, count+1, size);
+       (*argv)[count] = NULL;
+
        return count;
 }
 
index ba890ebdecd8672aeb32757605c8a2976fa21161..cee06ce3cbc1819008337633ed0753638c423ac5 100644 (file)
@@ -180,7 +180,7 @@ static int write_tar_entry(struct archiver_args *args,
 
        sprintf(header.mode, "%07o", mode & 07777);
        sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0);
-       sprintf(header.mtime, "%011lo", args->time);
+       sprintf(header.mtime, "%011lo", (unsigned long) args->time);
 
        sprintf(header.uid, "%07o", 0);
        sprintf(header.gid, "%07o", 0);
index cb67d2c17e4017e8deede61b30c0eb7c8c60ac1e..bee45f00de7d82e07b617716033f0d5605b2a368 100644 (file)
 #include "cache-tree.h"
 #include "run-command.h"
 #include "parse-options.h"
+#include "diff.h"
+#include "revision.h"
 
 static const char * const builtin_add_usage[] = {
        "git add [options] [--] <filepattern>...",
        NULL
 };
-static int patch_interactive, add_interactive;
+static int patch_interactive, add_interactive, edit_interactive;
 static int take_worktree_changes;
 
 static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
@@ -61,7 +63,7 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p
        fill_pathspec_matches(pathspec, seen, specs);
 
        for (i = 0; i < specs; i++) {
-               if (!seen[i] && !file_exists(pathspec[i]))
+               if (!seen[i] && pathspec[i][0] && !file_exists(pathspec[i]))
                        die("pathspec '%s' did not match any files",
                                        pathspec[i]);
        }
@@ -187,6 +189,51 @@ int interactive_add(int argc, const char **argv, const char *prefix)
        return status;
 }
 
+int edit_patch(int argc, const char **argv, const char *prefix)
+{
+       char *file = xstrdup(git_path("ADD_EDIT.patch"));
+       const char *apply_argv[] = { "apply", "--recount", "--cached",
+               file, NULL };
+       struct child_process child;
+       struct rev_info rev;
+       int out;
+       struct stat st;
+
+       git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
+
+       if (read_cache() < 0)
+               die ("Could not read the index");
+
+       init_revisions(&rev, prefix);
+       rev.diffopt.context = 7;
+
+       argc = setup_revisions(argc, argv, &rev, NULL);
+       rev.diffopt.output_format = DIFF_FORMAT_PATCH;
+       out = open(file, O_CREAT | O_WRONLY, 0644);
+       if (out < 0)
+               die ("Could not open '%s' for writing.", file);
+       rev.diffopt.file = fdopen(out, "w");
+       rev.diffopt.close_file = 1;
+       if (run_diff_files(&rev, 0))
+               die ("Could not write patch");
+
+       launch_editor(file, NULL, NULL);
+
+       if (stat(file, &st))
+               die("Could not stat '%s'", file);
+       if (!st.st_size)
+               die("Empty patch. Aborted.");
+
+       memset(&child, 0, sizeof(child));
+       child.git_cmd = 1;
+       child.argv = apply_argv;
+       if (run_command(&child))
+               die ("Could not apply '%s'", file);
+
+       unlink(file);
+       return 0;
+}
+
 static struct lock_file lock_file;
 
 static const char ignore_error[] =
@@ -201,6 +248,7 @@ static struct option builtin_add_options[] = {
        OPT_GROUP(""),
        OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
        OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
+       OPT_BOOLEAN('e', "edit", &edit_interactive, "edit current diff and apply"),
        OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
        OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
        OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, "record only the fact that the path will be added later"),
@@ -251,14 +299,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
        int require_pathspec;
 
        argc = parse_options(argc, argv, builtin_add_options,
-                         builtin_add_usage, 0);
+                         builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
        if (patch_interactive)
                add_interactive = 1;
        if (add_interactive)
-               exit(interactive_add(argc, argv, prefix));
+               exit(interactive_add(argc - 1, argv + 1, prefix));
 
        git_config(add_config, NULL);
 
+       if (edit_interactive)
+               return(edit_patch(argc, argv, prefix));
+       argc--;
+       argv++;
+
        if (addremove && take_worktree_changes)
                die("-A and -u are mutually incompatible");
        if ((addremove || take_worktree_changes) && !argc) {
index 7b404ef6601e5b7820e9b1b6812225639e3ea4b1..8a3771e87e1ef2ac7a1ee70133b8206f0f18cbb5 100644 (file)
@@ -2781,7 +2781,7 @@ static void remove_file(struct patch *patch, int rmdir_empty)
                        if (rmdir(patch->old_name))
                                warning("unable to remove submodule %s",
                                        patch->old_name);
-               } else if (!unlink(patch->old_name) && rmdir_empty) {
+               } else if (!unlink_or_warn(patch->old_name) && rmdir_empty) {
                        remove_path(patch->old_name);
                }
        }
@@ -2891,7 +2891,7 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
                        if (!try_create_file(newpath, mode, buf, size)) {
                                if (!rename(newpath, path))
                                        return;
-                               unlink(newpath);
+                               unlink_or_warn(newpath);
                                break;
                        }
                        if (errno != EEXIST)
index 91098ca9b106239916af000cb54a4bf09629e6b6..6aaa708473231848db8cba061f6048d41a6782af 100644 (file)
@@ -547,7 +547,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        struct option options[] = {
                OPT_GROUP("Generic options"),
                OPT__VERBOSE(&verbose),
-               OPT_SET_INT( 0 , "track",  &track, "set up tracking mode (see git-pull(1))",
+               OPT_SET_INT('t', "track",  &track, "set up tracking mode (see git-pull(1))",
                        BRANCH_TRACK_EXPLICIT),
                OPT_BOOLEAN( 0 , "color",  &branch_use_color, "use colored output"),
                OPT_SET_INT('r', NULL,     &kinds, "act on remote-tracking branches",
index 15f0c32c7a7ed62afe31e3bafb2d7306ba4a3402..f2d7ef01b0bbe667ae8042f7a806a634fa0aa46b 100644 (file)
@@ -365,17 +365,14 @@ static int merge_working_tree(struct checkout_opts *opts,
        int ret;
        struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
        int newfd = hold_locked_index(lock_file, 1);
-       int reprime_cache_tree = 0;
 
        if (read_cache() < 0)
                return error("corrupt index file");
 
-       cache_tree_free(&active_cache_tree);
        if (opts->force) {
                ret = reset_tree(new->commit->tree, opts, 1);
                if (ret)
                        return ret;
-               reprime_cache_tree = 1;
        } else {
                struct tree_desc trees[2];
                struct tree *tree;
@@ -411,9 +408,7 @@ static int merge_working_tree(struct checkout_opts *opts,
                init_tree_desc(&trees[1], tree->buffer, tree->size);
 
                ret = unpack_trees(2, trees, &topts);
-               if (ret != -1) {
-                       reprime_cache_tree = 1;
-               } else {
+               if (ret == -1) {
                        /*
                         * Unpack couldn't do a trivial merge; either
                         * give up or do a real merge, depending on
@@ -457,8 +452,6 @@ static int merge_working_tree(struct checkout_opts *opts,
                }
        }
 
-       if (reprime_cache_tree)
-               prime_cache_tree(&active_cache_tree, new->commit->tree);
        if (write_cache(newfd, active_cache, active_nr) ||
            commit_locked_index(lock_file))
                die("unable to write new index file");
@@ -548,14 +541,6 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
                parse_commit(new->commit);
        }
 
-       /*
-        * If we were on a detached HEAD, but we are now moving to
-        * a new commit, we want to mention the old commit once more
-        * to remind the user that it might be lost.
-        */
-       if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
-               describe_detached_head("Previous HEAD position was", old.commit);
-
        if (!old.commit && !opts->force) {
                if (!opts->quiet) {
                        warning("You appear to be on a branch yet to be born.");
@@ -568,6 +553,14 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
        if (ret)
                return ret;
 
+       /*
+        * If we were on a detached HEAD, but have now moved to
+        * a new commit, we want to mention the old commit once more
+        * to remind the user that it might be lost.
+        */
+       if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
+               describe_detached_head("Previous HEAD position was", old.commit);
+
        update_refs_for_switch(opts, &old, new);
 
        ret = post_checkout_hook(old.commit, new->commit, 1);
index 880373f279dd073ea7f0ae8564daca1cc687e529..c935833c6ce176caf47a14b5ad1f2848f0d1ab22 100644 (file)
@@ -104,11 +104,12 @@ static char *get_repo_path(const char *repo, int *is_bundle)
 static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
 {
        const char *end = repo + strlen(repo), *start;
+       char *dir;
 
        /*
-        * Strip trailing slashes and /.git
+        * Strip trailing spaces, slashes and /.git
         */
-       while (repo < end && is_dir_sep(end[-1]))
+       while (repo < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
                end--;
        if (end - repo > 5 && is_dir_sep(end[-5]) &&
            !strncmp(end - 4, ".git", 4)) {
@@ -140,10 +141,33 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
        if (is_bare) {
                struct strbuf result = STRBUF_INIT;
                strbuf_addf(&result, "%.*s.git", (int)(end - start), start);
-               return strbuf_detach(&result, 0);
+               dir = strbuf_detach(&result, 0);
+       } else
+               dir = xstrndup(start, end - start);
+       /*
+        * Replace sequences of 'control' characters and whitespace
+        * with one ascii space, remove leading and trailing spaces.
+        */
+       if (*dir) {
+               char *out = dir;
+               int prev_space = 1 /* strip leading whitespace */;
+               for (end = dir; *end; ++end) {
+                       char ch = *end;
+                       if ((unsigned char)ch < '\x20')
+                               ch = '\x20';
+                       if (isspace(ch)) {
+                               if (prev_space)
+                                       continue;
+                               prev_space = 1;
+                       } else
+                               prev_space = 0;
+                       *out++ = ch;
+               }
+               *out = '\0';
+               if (out > dir && prev_space)
+                       out[-1] = '\0';
        }
-
-       return xstrndup(start, end - start);
+       return dir;
 }
 
 static void strip_trailing_slashes(char *dir)
@@ -228,7 +252,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest)
                }
 
                if (unlink(dest->buf) && errno != ENOENT)
-                       die("failed to unlink %s", dest->buf);
+                       die("failed to unlink %s: %s",
+                           dest->buf, strerror(errno));
                if (!option_no_hardlinks) {
                        if (!link(src->buf, dest->buf))
                                continue;
index 87f46c6d07ccb0f82449b92e33cd4cda76a99da3..6202462216f3b8c3cbe924d4cc002616e69d75ab 100644 (file)
@@ -825,7 +825,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
                fd = hold_lock_file_for_update(&lock, shallow,
                                               LOCK_DIE_ON_ERROR);
                if (!write_shallow_commits(fd, 0)) {
-                       unlink(shallow);
+                       unlink_or_warn(shallow);
                        rollback_lock_file(&lock);
                } else {
                        commit_lock_file(&lock);
index 3c998ea740adf474ee980fc763bd7156b9ce81af..b944cac6e6546164ca41d66662e395de60ee4337 100644 (file)
@@ -289,7 +289,7 @@ static int update_local_ref(struct ref *ref,
        }
 }
 
-static int store_updated_refs(const char *url, const char *remote_name,
+static int store_updated_refs(const char *raw_url, const char *remote_name,
                struct ref *ref_map)
 {
        FILE *fp;
@@ -298,11 +298,13 @@ static int store_updated_refs(const char *url, const char *remote_name,
        char note[1024];
        const char *what, *kind;
        struct ref *rm;
-       char *filename = git_path("FETCH_HEAD");
+       char *url, *filename = git_path("FETCH_HEAD");
 
        fp = fopen(filename, "a");
        if (!fp)
                return error("cannot open %s: %s\n", filename, strerror(errno));
+
+       url = transport_anonymize_url(raw_url);
        for (rm = ref_map; rm; rm = rm->next) {
                struct ref *ref = NULL;
 
@@ -353,12 +355,18 @@ static int store_updated_refs(const char *url, const char *remote_name,
                                                    kind);
                        note_len += sprintf(note + note_len, "'%s' of ", what);
                }
-               note_len += sprintf(note + note_len, "%.*s", url_len, url);
-               fprintf(fp, "%s\t%s\t%s\n",
+               note[note_len] = '\0';
+               fprintf(fp, "%s\t%s\t%s",
                        sha1_to_hex(commit ? commit->object.sha1 :
                                    rm->old_sha1),
                        rm->merge ? "" : "not-for-merge",
                        note);
+               for (i = 0; i < url_len; ++i)
+                       if ('\n' == url[i])
+                               fputs("\\n", fp);
+                       else
+                               fputc(url[i], fp);
+               fputc('\n', fp);
 
                if (ref)
                        rc |= update_local_ref(ref, what, note);
@@ -376,6 +384,7 @@ static int store_updated_refs(const char *url, const char *remote_name,
                                fprintf(stderr, " %s\n", note);
                }
        }
+       free(url);
        fclose(fp);
        if (rc & 2)
                error("some local refs could not be updated; try running\n"
index 91e8f95fd20215cae72e206a691370c71dbc575e..d091e04af9549b70a1e15a4b845383056e71932e 100644 (file)
@@ -339,8 +339,11 @@ static const char *copy_name(const char *buf)
 static const char *copy_email(const char *buf)
 {
        const char *email = strchr(buf, '<');
-       const char *eoemail = strchr(email, '>');
-       if (!email || !eoemail)
+       const char *eoemail;
+       if (!email)
+               return "";
+       eoemail = strchr(email, '>');
+       if (!eoemail)
                return "";
        return xmemdupz(email, eoemail + 1 - email);
 }
index f88a912ace9195c387566770432a904e2d7adcb7..5308b346e69a50d7695b26f3b8e00bfdf71e1dd2 100644 (file)
@@ -10,6 +10,7 @@
 #include "tag.h"
 #include "tree-walk.h"
 #include "builtin.h"
+#include "parse-options.h"
 #include "grep.h"
 
 #ifndef NO_EXTERNAL_GREP
 #endif
 #endif
 
-static int builtin_grep;
+static char const * const grep_usage[] = {
+       "git grep [options] [-e] <pattern> [<rev>...] [[--] path...]",
+       NULL
+};
 
 static int grep_config(const char *var, const char *value, void *cb)
 {
@@ -432,7 +436,8 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
 }
 #endif
 
-static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
+static int grep_cache(struct grep_opt *opt, const char **paths, int cached,
+                     int external_grep_allowed)
 {
        int hit = 0;
        int nr;
@@ -444,7 +449,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
         * we grep through the checked-out files. It tends to
         * be a lot more optimized
         */
-       if (!cached && !builtin_grep) {
+       if (!cached && external_grep_allowed) {
                hit = external_grep(opt, paths, cached);
                if (hit >= 0)
                        return hit;
@@ -560,25 +565,182 @@ static int grep_object(struct grep_opt *opt, const char **paths,
        die("unable to grep from object of type %s", typename(obj->type));
 }
 
-static const char builtin_grep_usage[] =
-"git grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
+static int context_callback(const struct option *opt, const char *arg,
+                           int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       int value;
+       const char *endp;
+
+       if (unset) {
+               grep_opt->pre_context = grep_opt->post_context = 0;
+               return 0;
+       }
+       value = strtol(arg, (char **)&endp, 10);
+       if (*endp) {
+               return error("switch `%c' expects a numerical value",
+                            opt->short_name);
+       }
+       grep_opt->pre_context = grep_opt->post_context = value;
+       return 0;
+}
+
+static int file_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       FILE *patterns;
+       int lno = 0;
+       struct strbuf sb;
+
+       patterns = fopen(arg, "r");
+       if (!patterns)
+               die("'%s': %s", arg, strerror(errno));
+       while (strbuf_getline(&sb, patterns, '\n') == 0) {
+               /* ignore empty line like grep does */
+               if (sb.len == 0)
+                       continue;
+               append_grep_pattern(grep_opt, strbuf_detach(&sb, NULL), arg,
+                                   ++lno, GREP_PATTERN);
+       }
+       fclose(patterns);
+       strbuf_release(&sb);
+       return 0;
+}
+
+static int not_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT);
+       return 0;
+}
+
+static int and_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND);
+       return 0;
+}
+
+static int open_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN);
+       return 0;
+}
+
+static int close_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN);
+       return 0;
+}
 
-static const char emsg_invalid_context_len[] =
-"%s: invalid context length argument";
-static const char emsg_missing_context_len[] =
-"missing context length argument";
-static const char emsg_missing_argument[] =
-"option requires an argument -%s";
+static int pattern_callback(const struct option *opt, const char *arg,
+                           int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN);
+       return 0;
+}
+
+static int help_callback(const struct option *opt, const char *arg, int unset)
+{
+       return -1;
+}
 
 int cmd_grep(int argc, const char **argv, const char *prefix)
 {
        int hit = 0;
        int cached = 0;
+       int external_grep_allowed = 1;
        int seen_dashdash = 0;
        struct grep_opt opt;
        struct object_array list = { 0, 0, NULL };
        const char **paths = NULL;
        int i;
+       int dummy;
+       struct option options[] = {
+               OPT_BOOLEAN(0, "cached", &cached,
+                       "search in index instead of in the work tree"),
+               OPT_GROUP(""),
+               OPT_BOOLEAN('v', "invert-match", &opt.invert,
+                       "show non-matching lines"),
+               OPT_BIT('i', "ignore-case", &opt.regflags,
+                       "case insensitive matching", REG_ICASE),
+               OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
+                       "match patterns only at word boundaries"),
+               OPT_SET_INT('a', "text", &opt.binary,
+                       "process binary files as text", GREP_BINARY_TEXT),
+               OPT_SET_INT('I', NULL, &opt.binary,
+                       "don't match patterns in binary files",
+                       GREP_BINARY_NOMATCH),
+               OPT_GROUP(""),
+               OPT_BIT('E', "extended-regexp", &opt.regflags,
+                       "use extended POSIX regular expressions", REG_EXTENDED),
+               OPT_NEGBIT('G', "basic-regexp", &opt.regflags,
+                       "use basic POSIX regular expressions (default)",
+                       REG_EXTENDED),
+               OPT_BOOLEAN('F', "fixed-strings", &opt.fixed,
+                       "interpret patterns as fixed strings"),
+               OPT_GROUP(""),
+               OPT_BOOLEAN('n', NULL, &opt.linenum, "show line numbers"),
+               OPT_NEGBIT('h', NULL, &opt.pathname, "don't show filenames", 1),
+               OPT_BIT('H', NULL, &opt.pathname, "show filenames", 1),
+               OPT_NEGBIT(0, "full-name", &opt.relative,
+                       "show filenames relative to top directory", 1),
+               OPT_BOOLEAN('l', "files-with-matches", &opt.name_only,
+                       "show only filenames instead of matching lines"),
+               OPT_BOOLEAN(0, "name-only", &opt.name_only,
+                       "synonym for --files-with-matches"),
+               OPT_BOOLEAN('L', "files-without-match",
+                       &opt.unmatch_name_only,
+                       "show only the names of files without match"),
+               OPT_BOOLEAN('z', "null", &opt.null_following_name,
+                       "print NUL after filenames"),
+               OPT_BOOLEAN('c', "count", &opt.count,
+                       "show the number of matches instead of matching lines"),
+               OPT_SET_INT(0, "color", &opt.color, "highlight matches", 1),
+               OPT_GROUP(""),
+               OPT_CALLBACK('C', NULL, &opt, "n",
+                       "show <n> context lines before and after matches",
+                       context_callback),
+               OPT_INTEGER('B', NULL, &opt.pre_context,
+                       "show <n> context lines before matches"),
+               OPT_INTEGER('A', NULL, &opt.post_context,
+                       "show <n> context lines after matches"),
+               OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
+                       context_callback),
+               OPT_GROUP(""),
+               OPT_CALLBACK('f', NULL, &opt, "file",
+                       "read patterns from file", file_callback),
+               { OPTION_CALLBACK, 'e', NULL, &opt, "pattern",
+                       "match <pattern>", PARSE_OPT_NONEG, pattern_callback },
+               { OPTION_CALLBACK, 0, "and", &opt, NULL,
+                 "combine patterns specified with -e",
+                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
+               OPT_BOOLEAN(0, "or", &dummy, ""),
+               { OPTION_CALLBACK, 0, "not", &opt, NULL, "",
+                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
+               { OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
+                 PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
+                 open_callback },
+               { OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
+                 PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
+                 close_callback },
+               OPT_BOOLEAN(0, "all-match", &opt.all_match,
+                       "show only matches from files that match all patterns"),
+               OPT_GROUP(""),
+#if NO_EXTERNAL_GREP
+               OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
+                       "allow calling of grep(1) (ignored by this build)"),
+#else
+               OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
+                       "allow calling of grep(1) (default)"),
+#endif
+               { OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage",
+                 PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
+               OPT_END()
+       };
 
        memset(&opt, 0, sizeof(opt));
        opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
@@ -603,227 +765,21 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
         * unrecognized non option is the beginning of the refs list
         * that continues up to the -- (if exists), and then paths.
         */
-
-       while (1 < argc) {
-               const char *arg = argv[1];
-               argc--; argv++;
-               if (!strcmp("--cached", arg)) {
-                       cached = 1;
-                       continue;
-               }
-               if (!strcmp("--no-ext-grep", arg)) {
-                       builtin_grep = 1;
-                       continue;
-               }
-               if (!strcmp("-a", arg) ||
-                   !strcmp("--text", arg)) {
-                       opt.binary = GREP_BINARY_TEXT;
-                       continue;
-               }
-               if (!strcmp("-i", arg) ||
-                   !strcmp("--ignore-case", arg)) {
-                       opt.regflags |= REG_ICASE;
-                       continue;
-               }
-               if (!strcmp("-I", arg)) {
-                       opt.binary = GREP_BINARY_NOMATCH;
-                       continue;
-               }
-               if (!strcmp("-v", arg) ||
-                   !strcmp("--invert-match", arg)) {
-                       opt.invert = 1;
-                       continue;
-               }
-               if (!strcmp("-E", arg) ||
-                   !strcmp("--extended-regexp", arg)) {
-                       opt.regflags |= REG_EXTENDED;
-                       continue;
-               }
-               if (!strcmp("-F", arg) ||
-                   !strcmp("--fixed-strings", arg)) {
-                       opt.fixed = 1;
-                       continue;
-               }
-               if (!strcmp("-G", arg) ||
-                   !strcmp("--basic-regexp", arg)) {
-                       opt.regflags &= ~REG_EXTENDED;
-                       continue;
-               }
-               if (!strcmp("-n", arg)) {
-                       opt.linenum = 1;
-                       continue;
-               }
-               if (!strcmp("-h", arg)) {
-                       opt.pathname = 0;
-                       continue;
-               }
-               if (!strcmp("-H", arg)) {
-                       opt.pathname = 1;
-                       continue;
-               }
-               if (!strcmp("-l", arg) ||
-                   !strcmp("--name-only", arg) ||
-                   !strcmp("--files-with-matches", arg)) {
-                       opt.name_only = 1;
-                       continue;
-               }
-               if (!strcmp("-L", arg) ||
-                   !strcmp("--files-without-match", arg)) {
-                       opt.unmatch_name_only = 1;
-                       continue;
-               }
-               if (!strcmp("-z", arg) ||
-                   !strcmp("--null", arg)) {
-                       opt.null_following_name = 1;
-                       continue;
-               }
-               if (!strcmp("-c", arg) ||
-                   !strcmp("--count", arg)) {
-                       opt.count = 1;
-                       continue;
-               }
-               if (!strcmp("-w", arg) ||
-                   !strcmp("--word-regexp", arg)) {
-                       opt.word_regexp = 1;
-                       continue;
-               }
-               if (!prefixcmp(arg, "-A") ||
-                   !prefixcmp(arg, "-B") ||
-                   !prefixcmp(arg, "-C") ||
-                   (arg[0] == '-' && '1' <= arg[1] && arg[1] <= '9')) {
-                       unsigned num;
-                       const char *scan;
-                       switch (arg[1]) {
-                       case 'A': case 'B': case 'C':
-                               if (!arg[2]) {
-                                       if (argc <= 1)
-                                               die(emsg_missing_context_len);
-                                       scan = *++argv;
-                                       argc--;
-                               }
-                               else
-                                       scan = arg + 2;
-                               break;
-                       default:
-                               scan = arg + 1;
-                               break;
-                       }
-                       if (strtoul_ui(scan, 10, &num))
-                               die(emsg_invalid_context_len, scan);
-                       switch (arg[1]) {
-                       case 'A':
-                               opt.post_context = num;
-                               break;
-                       default:
-                       case 'C':
-                               opt.post_context = num;
-                       case 'B':
-                               opt.pre_context = num;
-                               break;
-                       }
-                       continue;
-               }
-               if (!strcmp("-f", arg)) {
-                       FILE *patterns;
-                       int lno = 0;
-                       char buf[1024];
-                       if (argc <= 1)
-                               die(emsg_missing_argument, arg);
-                       patterns = fopen(argv[1], "r");
-                       if (!patterns)
-                               die("'%s': %s", argv[1], strerror(errno));
-                       while (fgets(buf, sizeof(buf), patterns)) {
-                               int len = strlen(buf);
-                               if (len && buf[len-1] == '\n')
-                                       buf[len-1] = 0;
-                               /* ignore empty line like grep does */
-                               if (!buf[0])
-                                       continue;
-                               append_grep_pattern(&opt, xstrdup(buf),
-                                                   argv[1], ++lno,
-                                                   GREP_PATTERN);
-                       }
-                       fclose(patterns);
-                       argv++;
-                       argc--;
-                       continue;
-               }
-               if (!strcmp("--not", arg)) {
-                       append_grep_pattern(&opt, arg, "command line", 0,
-                                           GREP_NOT);
-                       continue;
-               }
-               if (!strcmp("--and", arg)) {
-                       append_grep_pattern(&opt, arg, "command line", 0,
-                                           GREP_AND);
-                       continue;
-               }
-               if (!strcmp("--or", arg))
-                       continue; /* no-op */
-               if (!strcmp("(", arg)) {
-                       append_grep_pattern(&opt, arg, "command line", 0,
-                                           GREP_OPEN_PAREN);
-                       continue;
-               }
-               if (!strcmp(")", arg)) {
-                       append_grep_pattern(&opt, arg, "command line", 0,
-                                           GREP_CLOSE_PAREN);
-                       continue;
-               }
-               if (!strcmp("--all-match", arg)) {
-                       opt.all_match = 1;
-                       continue;
-               }
-               if (!strcmp("-e", arg)) {
-                       if (1 < argc) {
-                               append_grep_pattern(&opt, argv[1],
-                                                   "-e option", 0,
-                                                   GREP_PATTERN);
-                               argv++;
-                               argc--;
-                               continue;
-                       }
-                       die(emsg_missing_argument, arg);
-               }
-               if (!strcmp("--full-name", arg)) {
-                       opt.relative = 0;
-                       continue;
-               }
-               if (!strcmp("--color", arg)) {
-                       opt.color = 1;
-                       continue;
-               }
-               if (!strcmp("--no-color", arg)) {
-                       opt.color = 0;
-                       continue;
-               }
-               if (!strcmp("--", arg)) {
-                       /* later processing wants to have this at argv[1] */
-                       argv--;
-                       argc++;
-                       break;
-               }
-               if (*arg == '-')
-                       usage(builtin_grep_usage);
-
-               /* First unrecognized non-option token */
-               if (!opt.pattern_list) {
-                       append_grep_pattern(&opt, arg, "command line", 0,
-                                           GREP_PATTERN);
-                       break;
-               }
-               else {
-                       /* We are looking at the first path or rev;
-                        * it is found at argv[1] after leaving the
-                        * loop.
-                        */
-                       argc++; argv--;
-                       break;
-               }
+       argc = parse_options(argc, argv, options, grep_usage,
+                            PARSE_OPT_KEEP_DASHDASH |
+                            PARSE_OPT_STOP_AT_NON_OPTION |
+                            PARSE_OPT_NO_INTERNAL_HELP);
+
+       /* First unrecognized non-option token */
+       if (argc > 0 && !opt.pattern_list) {
+               append_grep_pattern(&opt, argv[0], "command line", 0,
+                                   GREP_PATTERN);
+               argv++;
+               argc--;
        }
 
        if (opt.color && !opt.color_external)
-               builtin_grep = 1;
+               external_grep_allowed = 0;
        if (!opt.pattern_list)
                die("no pattern given.");
        if ((opt.regflags != REG_NEWLINE) && opt.fixed)
@@ -831,7 +787,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        compile_grep_patterns(&opt);
 
        /* Check revs and then paths */
-       for (i = 1; i < argc; i++) {
+       for (i = 0; i < argc; i++) {
                const char *arg = argv[i];
                unsigned char sha1[20];
                /* Is it a rev? */
@@ -874,7 +830,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        if (!list.nr) {
                if (!cached)
                        setup_work_tree();
-               return !grep_cache(&opt, paths, cached);
+               return !grep_cache(&opt, paths, cached, external_grep_allowed);
        }
 
        if (cached)
index da2daf45acd2154b7f00da34d41a5ab8acaf0c38..3d59b0e140ca199997704ffcf59fbc2138345168 100644 (file)
@@ -454,7 +454,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
                OPT_BIT(0, "directory", &dir.flags,
                        "show 'other' directories' name only",
                        DIR_SHOW_OTHER_DIRECTORIES),
-               OPT_BIT(0, "no-empty-directory", &dir.flags,
+               OPT_NEGBIT(0, "empty-directory", &dir.flags,
                        "don't show empty directories",
                        DIR_HIDE_EMPTY_DIRECTORIES),
                OPT_BOOLEAN('u', "unmerged", &show_unmerged,
index 4942892e9f83abc7beed6570d508cfe76da126a0..00590b1c3c2cceda7a75537c8680a96cd2ef84d4 100644 (file)
@@ -28,8 +28,8 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts)
                memcpy(pathname + len, de->d_name, 38);
                if (opts & DRY_RUN)
                        printf("rm -f %s\n", pathname);
-               else if (unlink(pathname) < 0)
-                       error("unable to unlink %s", pathname);
+               else
+                       unlink_or_warn(pathname);
                display_progress(progress, i + 1);
        }
        pathname[len] = 0;
index 545e9c1f9458ed936e2a99a208f75b70f368294c..145ba83651e9c8560e20d6ab449ce64783bc65f5 100644 (file)
@@ -27,7 +27,7 @@ static int prune_tmp_object(const char *path, const char *filename)
        }
        printf("Removing stale temporary file %s\n", fullpath);
        if (!show_only)
-               unlink(fullpath);
+               unlink_or_warn(fullpath);
        return 0;
 }
 
@@ -47,7 +47,7 @@ static int prune_object(char *path, const char *filename, const unsigned char *s
                       (type > 0) ? typename(type) : "unknown");
        }
        if (!show_only)
-               unlink(fullpath);
+               unlink_or_warn(fullpath);
        return 0;
 }
 
index a970b39505b5dda0bfa32a1a9c14ad676d28ec92..0b08da9b595432efa231eb59d88ecd2b422eb56a 100644 (file)
@@ -27,10 +27,9 @@ static int receive_unpack_limit = -1;
 static int transfer_unpack_limit = -1;
 static int unpack_limit = 100;
 static int report_status;
+static int prefer_ofs_delta = 1;
 static const char *head_name;
-
-static char capabilities[] = " report-status delete-refs ";
-static int capabilities_sent;
+static char *capabilities_to_send;
 
 static enum deny_action parse_deny_action(const char *var, const char *value)
 {
@@ -84,24 +83,29 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
+       if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
+               prefer_ofs_delta = git_config_bool(var, value);
+               return 0;
+       }
+
        return git_default_config(var, value, cb);
 }
 
 static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 {
-       if (capabilities_sent)
+       if (!capabilities_to_send)
                packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
        else
                packet_write(1, "%s %s%c%s\n",
-                            sha1_to_hex(sha1), path, 0, capabilities);
-       capabilities_sent = 1;
+                            sha1_to_hex(sha1), path, 0, capabilities_to_send);
+       capabilities_to_send = NULL;
        return 0;
 }
 
 static void write_head_info(void)
 {
        for_each_ref(show_ref, NULL);
-       if (!capabilities_sent)
+       if (capabilities_to_send)
                show_ref("capabilities^{}", null_sha1, 0, NULL);
 
 }
@@ -687,6 +691,10 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
        else if (0 <= receive_unpack_limit)
                unpack_limit = receive_unpack_limit;
 
+       capabilities_to_send = (prefer_ofs_delta) ?
+               " report-status delete-refs ofs-delta " :
+               " report-status delete-refs ";
+
        add_alternate_refs();
        write_head_info();
        clear_extra_refs();
@@ -702,7 +710,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
                        unpack_status = unpack();
                execute_commands(unpack_status);
                if (pack_lockfile)
-                       unlink(pack_lockfile);
+                       unlink_or_warn(pack_lockfile);
                if (report_status)
                        report(unpack_status);
                run_receive_hook(post_receive_hook);
index 2ed752cbf1803c243145ecc73d6abbf758a2203a..71abf68404f5b260ba96208717d89e50e778dd36 100644 (file)
@@ -525,8 +525,8 @@ static int migrate_file(struct remote *remote)
                path = git_path("remotes/%s", remote->name);
        else if (remote->origin == REMOTE_BRANCHES)
                path = git_path("branches/%s", remote->name);
-       if (path && unlink(path))
-               warning("failed to remove '%s'", path);
+       if (path)
+               unlink_or_warn(path);
        return 0;
 }
 
index 020af7377bb9aa1bced7489d40169e3cb2ff7682..adfb7b5f48597c19c23235b74cf1a0c779985dc6 100644 (file)
@@ -116,7 +116,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
                        if (!has_rerere_resolution(name))
                                unlink_rr_item(name);
                }
-               unlink(git_path("rr-cache/MERGE_RR"));
+               unlink_or_warn(git_path("rr-cache/MERGE_RR"));
        } else if (!strcmp(argv[1], "gc"))
                garbage_collect(&merge_rr);
        else if (!strcmp(argv[1], "status"))
index d5a1c48d0e2abab16c646ce86ac9670b95dddc07..473a3de40c4cc9aab5c1355d0602646234e7bc1c 100644 (file)
@@ -43,12 +43,16 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
                "--stdout",
                NULL,
                NULL,
+               NULL,
        };
        struct child_process po;
        int i;
 
+       i = 4;
        if (args->use_thin_pack)
-               argv[4] = "--thin";
+               argv[i++] = "--thin";
+       if (args->use_ofs_delta)
+               argv[i++] = "--delta-base-offset";
        memset(&po, 0, sizeof(po));
        po.argv = argv;
        po.in = -1;
@@ -315,6 +319,8 @@ int send_pack(struct send_pack_args *args,
                ask_for_status_report = 1;
        if (server_supports("delete-refs"))
                allow_deleting_refs = 1;
+       if (server_supports("ofs-delta"))
+               args->use_ofs_delta = 1;
 
        if (!remote_refs) {
                fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
index 828e6f86de22f8def68a49b702a27521c248a012..c8e9b3c723cb733e1d6b4cd2036f165f0a088970 100644 (file)
@@ -2,12 +2,25 @@
 #include "commit.h"
 #include "refs.h"
 #include "builtin.h"
+#include "color.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>";
 static const char show_branch_usage_reflog[] =
 "--reflog is incompatible with --all, --remotes, --independent or --merge-base";
 
+static int showbranch_use_color = -1;
+static char column_colors[][COLOR_MAXLEN] = {
+       GIT_COLOR_RED,
+       GIT_COLOR_GREEN,
+       GIT_COLOR_YELLOW,
+       GIT_COLOR_BLUE,
+       GIT_COLOR_MAGENTA,
+       GIT_COLOR_CYAN,
+};
+
+#define COLUMN_COLORS_MAX (ARRAY_SIZE(column_colors))
+
 static int default_num;
 static int default_alloc;
 static const char **default_arg;
@@ -19,6 +32,20 @@ static const char **default_arg;
 
 #define DEFAULT_REFLOG 4
 
+static const char *get_color_code(int idx)
+{
+       if (showbranch_use_color)
+               return column_colors[idx];
+       return "";
+}
+
+static const char *get_color_reset_code(void)
+{
+       if (showbranch_use_color)
+               return GIT_COLOR_RESET;
+       return "";
+}
+
 static struct commit *interesting(struct commit_list *list)
 {
        while (list) {
@@ -545,7 +572,12 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       return git_default_config(var, value, cb);
+       if (!strcmp(var, "color.showbranch")) {
+               showbranch_use_color = git_config_colorbool(var, value, -1);
+               return 0;
+       }
+
+       return git_color_default_config(var, value, cb);
 }
 
 static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
@@ -576,7 +608,7 @@ static void parse_reflog_param(const char *arg, int *cnt, const char **base)
        if (*ep == ',')
                *base = ep + 1;
        else if (*ep)
-               die("unrecognized reflog param '%s'", arg + 9);
+               die("unrecognized reflog param '%s'", arg);
        else
                *base = NULL;
        if (*cnt <= 0)
@@ -611,6 +643,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 
        git_config(git_show_branch_config, NULL);
 
+       if (showbranch_use_color == -1)
+               showbranch_use_color = git_use_color_default;
+
        /* If nothing is specified, try the default first */
        if (ac == 1 && default_num) {
                ac = default_num + 1;
@@ -658,6 +693,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                        parse_reflog_param(arg + 9, &reflog, &reflog_base);
                else if (!prefixcmp(arg, "-g="))
                        parse_reflog_param(arg + 3, &reflog, &reflog_base);
+               else if (!strcmp(arg, "--color"))
+                       showbranch_use_color = 1;
+               else if (!strcmp(arg, "--no-color"))
+                       showbranch_use_color = 0;
                else
                        usage(show_branch_usage);
                ac--; av++;
@@ -843,8 +882,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                        else {
                                for (j = 0; j < i; j++)
                                        putchar(' ');
-                               printf("%c [%s] ",
-                                      is_head ? '*' : '!', ref_name[i]);
+                               printf("%s%c%s [%s] ",
+                                      get_color_code(i % COLUMN_COLORS_MAX),
+                                      is_head ? '*' : '!',
+                                      get_color_reset_code(), ref_name[i]);
                        }
 
                        if (!reflog) {
@@ -903,7 +944,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                                        mark = '*';
                                else
                                        mark = '+';
-                               putchar(mark);
+                               printf("%s%c%s",
+                                      get_color_code(i % COLUMN_COLORS_MAX),
+                                      mark, get_color_reset_code());
                        }
                        putchar(' ');
                }
index 01e73747d02f384c5e31b846340a4b586c84aab3..e54443009420d98dc281285e997b32f2a263b996 100644 (file)
@@ -338,7 +338,7 @@ static void create_tag(const unsigned char *object, const char *tag,
                exit(128);
        }
        if (path) {
-               unlink(path);
+               unlink_or_warn(path);
                free(path);
        }
 }
index 729a1593e61d87ad4596f07e7faedac81de64e81..7f7fda42f9b7ab272ff2b3fa4ad1984a79f11ce0 100644 (file)
@@ -55,7 +55,7 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
        close(gpg.in);
        ret = finish_command(&gpg);
 
-       unlink(path);
+       unlink_or_warn(path);
 
        return ret;
 }
index d0dd818b31faa04caa4d418a39ad3020a919aa2d..e4b2aa9c4a2a7fb52121828343aa27ab47d17279 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -98,7 +98,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
         */
        struct ref_list *p = &header->prerequisites;
        struct rev_info revs;
-       const char *argv[] = {NULL, "--all"};
+       const char *argv[] = {NULL, "--all", NULL};
        struct object_array refs;
        struct commit *commit;
        int i, ret = 0, req_nr;
index 1683e6d7b8bc677469d52acf4d6ff187e084cf3a..0c8bb536c84f04627e78f251f51aea11b2048ce5 100755 (executable)
@@ -99,20 +99,32 @@ __git_ps1 ()
                elif [ -d "$g/rebase-merge" ]; then
                        r="|REBASE-m"
                        b="$(cat "$g/rebase-merge/head-name")"
-               elif [ -f "$g/MERGE_HEAD" ]; then
-                       r="|MERGING"
-                       b="$(git symbolic-ref HEAD 2>/dev/null)"
                else
+                       if [ -f "$g/MERGE_HEAD" ]; then
+                               r="|MERGING"
+                       fi
                        if [ -f "$g/BISECT_LOG" ]; then
                                r="|BISECTING"
                        fi
-                       if ! b="$(git symbolic-ref HEAD 2>/dev/null)"; then
-                               if ! b="$(git describe --exact-match HEAD 2>/dev/null)"; then
-                                       if [ -r "$g/HEAD" ]; then
-                                               b="$(cut -c1-7 "$g/HEAD")..."
-                                       fi
-                               fi
-                       fi
+
+                       b="$(git symbolic-ref HEAD 2>/dev/null)" || {
+
+                               b="$(
+                               case "${GIT_PS1_DESCRIBE_STYLE-}" in
+                               (contains)
+                                       git describe --contains HEAD ;;
+                               (branch)
+                                       git describe --contains --all HEAD ;;
+                               (describe)
+                                       git describe HEAD ;;
+                               (* | default)
+                                       git describe --exact-match HEAD ;;
+                               esac 2>/dev/null)" ||
+
+                               b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
+                               b="unknown"
+                               b="($b)"
+                       }
                fi
 
                local w
@@ -120,7 +132,7 @@ __git_ps1 ()
                local c
 
                if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
-                       if [ "true" = "$(git config --bool core.bare 2>/dev/null)" ]; then
+                       if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
                                c="BARE:"
                        else
                                b="GIT_DIR!"
@@ -1322,6 +1334,35 @@ _git_send_email ()
        COMPREPLY=()
 }
 
+__git_config_get_set_variables ()
+{
+       local prevword word config_file= c=$COMP_CWORD
+       while [ $c -gt 1 ]; do
+               word="${COMP_WORDS[c]}"
+               case "$word" in
+               --global|--system|--file=*)
+                       config_file="$word"
+                       break
+                       ;;
+               -f|--file)
+                       config_file="$word $prevword"
+                       break
+                       ;;
+               esac
+               prevword=$word
+               c=$((--c))
+       done
+
+       for i in $(git --git-dir="$(__gitdir)" config $config_file --list \
+                       2>/dev/null); do
+               case "$i" in
+               *.*)
+                       echo "${i/=*/}"
+                       ;;
+               esac
+       done
+}
+
 _git_config ()
 {
        local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -1353,7 +1394,8 @@ _git_config ()
                __gitcomp "$(__git_merge_strategies)"
                return
                ;;
-       color.branch|color.diff|color.interactive|color.status|color.ui)
+       color.branch|color.diff|color.interactive|\
+       color.showbranch|color.status|color.ui)
                __gitcomp "always never auto"
                return
                ;;
@@ -1388,6 +1430,10 @@ _git_config ()
                __gitcomp "$__git_send_email_suppresscc_options"
                return
                ;;
+       --get|--get-all|--unset|--unset-all)
+               __gitcomp "$(__git_config_get_set_variables)"
+               return
+               ;;
        *.*)
                COMPREPLY=()
                return
@@ -1498,6 +1544,7 @@ _git_config ()
                color.interactive.help
                color.interactive.prompt
                color.pager
+               color.showbranch
                color.status
                color.status.added
                color.status.changed
@@ -1792,7 +1839,7 @@ _git_show ()
                return
                ;;
        --*)
-               __gitcomp "--pretty= --format=
+               __gitcomp "--pretty= --format= --abbrev-commit --oneline
                        $__git_diff_common_options
                        "
                return
@@ -1809,7 +1856,8 @@ _git_show_branch ()
                __gitcomp "
                        --all --remotes --topo-order --current --more=
                        --list --independent --merge-base --no-name
-                       --sha1-name --topics --reflog
+                       --color --no-color
+                       --sha1-name --sparse --topics --reflog
                        "
                return
                ;;
index 82d9e221eabab53acc418d0db6327e480836a5ed..2f8a63e38881587fe29fcb72a5272ef54b9efa6e 100644 (file)
@@ -8,7 +8,9 @@
 
 static unsigned int hash_obj(const struct object *obj, unsigned int n)
 {
-       unsigned int hash = *(unsigned int *)obj->sha1;
+       unsigned int hash;
+
+       memcpy(&hash, obj->sha1, sizeof(unsigned int));
        return hash % n;
 }
 
@@ -16,7 +18,7 @@ static void *insert_decoration(struct decoration *n, const struct object *base,
 {
        int size = n->size;
        struct object_decoration *hash = n->hash;
-       int j = hash_obj(base, size);
+       unsigned int j = hash_obj(base, size);
 
        while (hash[j].base) {
                if (hash[j].base == base) {
@@ -68,7 +70,7 @@ void *add_decoration(struct decoration *n, const struct object *obj,
 /* Lookup a decoration pointer */
 void *lookup_decoration(struct decoration *n, const struct object *obj)
 {
-       int j;
+       unsigned int j;
 
        /* nothing to lookup */
        if (!n->size)
diff --git a/diff.c b/diff.c
index 363dcb9613f5f57a2ae31ea6f803caf44954475a..f06876be67245ab559b57168553cfd71b9d23feb 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -189,7 +189,7 @@ static void remove_tempfile(void)
        int i;
        for (i = 0; i < ARRAY_SIZE(diff_temp); i++) {
                if (diff_temp[i].name == diff_temp[i].tmp_path)
-                       unlink(diff_temp[i].name);
+                       unlink_or_warn(diff_temp[i].name);
                diff_temp[i].name = NULL;
        }
 }
@@ -839,10 +839,9 @@ static int scale_linear(int it, int width, int max_change)
 }
 
 static void show_name(FILE *file,
-                     const char *prefix, const char *name, int len,
-                     const char *reset, const char *set)
+                     const char *prefix, const char *name, int len)
 {
-       fprintf(file, " %s%s%-*s%s |", set, prefix, len, name, reset);
+       fprintf(file, " %s%-*s |", prefix, len, name);
 }
 
 static void show_graph(FILE *file, char ch, int cnt, const char *set, const char *reset)
@@ -956,7 +955,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                }
 
                if (data->files[i]->is_binary) {
-                       show_name(options->file, prefix, name, len, reset, set);
+                       show_name(options->file, prefix, name, len);
                        fprintf(options->file, "  Bin ");
                        fprintf(options->file, "%s%d%s", del_c, deleted, reset);
                        fprintf(options->file, " -> ");
@@ -966,7 +965,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                        continue;
                }
                else if (data->files[i]->is_unmerged) {
-                       show_name(options->file, prefix, name, len, reset, set);
+                       show_name(options->file, prefix, name, len);
                        fprintf(options->file, "  Unmerged\n");
                        continue;
                }
@@ -988,7 +987,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                        add = scale_linear(add, width, max_change);
                        del = scale_linear(del, width, max_change);
                }
-               show_name(options->file, prefix, name, len, reset, set);
+               show_name(options->file, prefix, name, len);
                fprintf(options->file, "%5d%s", added + deleted,
                                added + deleted ? " " : "");
                show_graph(options->file, '+', add, add_c, reset);
@@ -996,8 +995,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
                fprintf(options->file, "\n");
        }
        fprintf(options->file,
-              "%s %d files changed, %d insertions(+), %d deletions(-)%s\n",
-              set, total_files, adds, dels, reset);
+              " %d files changed, %d insertions(+), %d deletions(-)\n",
+              total_files, adds, dels);
 }
 
 static void show_shortstats(struct diffstat_t* data, struct diff_options *options)
diff --git a/dir.c b/dir.c
index 6aae09a22e54a7b9291ed1b6acf79529c6029a49..0e6b752cd5833bfb970619983b4efa880aaaf134 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -576,7 +576,7 @@ static int get_dtype(struct dirent *de, const char *path)
  */
 static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only, const struct path_simplify *simplify)
 {
-       DIR *fdir = opendir(path);
+       DIR *fdir = opendir(*path ? path : ".");
        int contents = 0;
 
        if (fdir) {
diff --git a/entry.c b/entry.c
index 915514aa5c43d3fd39f077a79f63ac27b841d255..cc841edf9051460b3a382ea25c0097f245ec8884 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -35,7 +35,7 @@ static void create_directories(const char *path, int path_len,
                 */
                if (mkdir(buf, 0777)) {
                        if (errno == EEXIST && state->force &&
-                           !unlink(buf) && !mkdir(buf, 0777))
+                           !unlink_or_warn(buf) && !mkdir(buf, 0777))
                                continue;
                        die("cannot create directory at %s", buf);
                }
index e9d23ffb2fb3f6df141944dca7ddab0edbd1e5ee..a2a24588a99957d5af759ca6d8858366430ab3a3 100644 (file)
@@ -931,7 +931,7 @@ static void unkeep_all_packs(void)
                struct packed_git *p = all_packs[k];
                snprintf(name, sizeof(name), "%s/pack/pack-%s.keep",
                         get_object_directory(), sha1_to_hex(p->sha1));
-               unlink(name);
+               unlink_or_warn(name);
        }
 }
 
@@ -981,7 +981,7 @@ static void end_packfile(void)
        }
        else {
                close(old_p->pack_fd);
-               unlink(old_p->pack_name);
+               unlink_or_warn(old_p->pack_name);
        }
        free(old_p);
 
index 1ac16bde5ab853098f857a64c6f0fea9f4c3437f..c7cf2d5d9cdbfd4ed20c8b8ea49a36af7c138a4e 100644 (file)
@@ -415,4 +415,10 @@ void git_qsort(void *base, size_t nmemb, size_t size,
 #define fstat_is_reliable() 1
 #endif
 
+/*
+ * Preserves errno, prints a message, but gives no warning for ENOENT.
+ * Always returns the return value of unlink(2).
+ */
+int unlink_or_warn(const char *path);
+
 #endif
index e1eb9632660146396a0b5f3f2a410d8cb027ff9d..9c2c1b7202462370509a7bdb391982ae32564bd6 100755 (executable)
@@ -113,6 +113,10 @@ case "${1:-.}${2:-.}${3:-.}" in
        src1=`git-unpack-file $2`
        git merge-file "$src1" "$orig" "$src2"
        ret=$?
+       msg=
+       if [ $ret -ne 0 ]; then
+               msg='content conflict'
+       fi
 
        # Create the working tree file, using "our tree" version from the
        # index, and then store the result of the merge.
@@ -120,7 +124,10 @@ case "${1:-.}${2:-.}${3:-.}" in
        rm -f -- "$orig" "$src1" "$src2"
 
        if [ "$6" != "$7" ]; then
-               echo "ERROR: Permissions conflict: $5->$6,$7."
+               if [ -n "$msg" ]; then
+                       msg="$msg, "
+               fi
+               msg="${msg}permissions conflict: $5->$6,$7"
                ret=1
        fi
        if [ "$1" = '' ]; then
@@ -128,7 +135,7 @@ case "${1:-.}${2:-.}${3:-.}" in
        fi
 
        if [ $ret -ne 0 ]; then
-               echo "ERROR: Merge conflict in $4"
+               echo "ERROR: $msg in $4"
                exit 1
        fi
        exec git update-index -- "$4"
index cccbf4517aa46d4d217a1ce25105f7c413301d2d..e3408d513fd5b3f504415021647351c7f9aeab91 100755 (executable)
@@ -409,7 +409,7 @@ my %parse_alias = (
        mailrc => sub { my $fh = shift; while (<$fh>) {
                if (/^alias\s+(\S+)\s+(.*)$/) {
                        # spaces delimit multiple addresses
-                       $aliases{$1} = [ split(/\s+/, $2) ];
+                       $aliases{$1} = [ quotewords('\s+', 0, $2) ];
                }}},
        pine => sub { my $fh = shift; my $f='\t[^\t]*';
                for (my $x = ''; defined($x); $x = $_) {
index 8e234a4028d22e11baedba11f871d33f56945716..ab1ed02a663b7e6252fe33f5224cb9653bcd50f2 100755 (executable)
@@ -15,6 +15,7 @@ require_work_tree
 command=
 branch=
 quiet=
+reference=
 cached=
 nofetch=
 
@@ -91,6 +92,7 @@ module_clone()
 {
        path=$1
        url=$2
+       reference="$3"
 
        # If there already is a directory at the submodule path,
        # expect it to be empty (since that is the default checkout
@@ -106,7 +108,12 @@ module_clone()
        test -e "$path" &&
        die "A file already exist at path '$path'"
 
-       git-clone -n "$url" "$path" ||
+       if test -n "$reference"
+       then
+               git-clone "$reference" -n "$url" "$path"
+       else
+               git-clone -n "$url" "$path"
+       fi ||
        die "Clone of '$url' into submodule path '$path' failed"
 }
 
@@ -131,6 +138,15 @@ cmd_add()
                -q|--quiet)
                        quiet=1
                        ;;
+               --reference)
+                       case "$2" in '') usage ;; esac
+                       reference="--reference=$2"
+                       shift
+                       ;;
+               --reference=*)
+                       reference="$1"
+                       shift
+                       ;;
                --)
                        shift
                        break
@@ -203,7 +219,7 @@ cmd_add()
                git config submodule."$path".url "$url"
        else
 
-               module_clone "$path" "$realrepo" || exit
+               module_clone "$path" "$realrepo" "$reference" || exit
                (
                        unset GIT_DIR
                        cd "$path" &&
@@ -314,13 +330,22 @@ cmd_update()
                        quiet=1
                        ;;
                -i|--init)
+                       init=1
                        shift
-                       cmd_init "$@" || return
                        ;;
                -N|--no-fetch)
                        shift
                        nofetch=1
                        ;;
+               --reference)
+                       case "$2" in '') usage ;; esac
+                       reference="--reference=$2"
+                       shift 2
+                       ;;
+               --reference=*)
+                       reference="$1"
+                       shift
+                       ;;
                --)
                        shift
                        break
@@ -334,6 +359,11 @@ cmd_update()
                esac
        done
 
+       if test -n "$init"
+       then
+               cmd_init "--" "$@" || return
+       fi
+
        module_list "$@" |
        while read mode sha1 stage path
        do
@@ -351,7 +381,7 @@ cmd_update()
 
                if ! test -d "$path"/.git -o -f "$path"/.git
                then
-                       module_clone "$path" "$url" || exit
+                       module_clone "$path" "$url" "$reference"|| exit
                        subsha1=
                else
                        subsha1=$(unset GIT_DIR; cd "$path" &&
index ef1d30db3889d0d33b43b1d15cd19281291f5aea..a70c7d7b2cc1e47d5293e1bd45e11d398e48c3f1 100755 (executable)
@@ -5,7 +5,7 @@ use warnings;
 use strict;
 use vars qw/   $AUTHOR $VERSION
                $sha1 $sha1_short $_revision $_repository
-               $_q $_authors %users/;
+               $_q $_authors $_authors_prog %users/;
 $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
 $VERSION = '@@GIT_VERSION@@';
 
@@ -39,6 +39,7 @@ use Digest::MD5;
 use IO::File qw//;
 use File::Basename qw/dirname basename/;
 use File::Path qw/mkpath/;
+use File::Spec;
 use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
 use IPC::Open3;
 use Git;
@@ -76,6 +77,7 @@ my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
                     'ignore-paths=s' => \$SVN::Git::Fetcher::_ignore_regex );
 my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
                'authors-file|A=s' => \$_authors,
+               'authors-prog=s' => \$_authors_prog,
                'repack:i' => \$Git::SVN::_repack,
                'noMetadata' => \$Git::SVN::_no_metadata,
                'useSvmProps' => \$Git::SVN::_use_svm_props,
@@ -263,6 +265,9 @@ usage(0) if $_help;
 version() if $_version;
 usage(1) unless defined $cmd;
 load_authors() if $_authors;
+if (defined $_authors_prog) {
+       $_authors_prog = "'" . File::Spec->rel2abs($_authors_prog) . "'";
+}
 
 unless ($cmd =~ /^(?:clone|init|multi-init|commit-diff)$/) {
        Git::SVN::Migration::migration_check();
@@ -361,6 +366,7 @@ sub cmd_clone {
        $path = basename($url) if !defined $path || !length $path;
        cmd_init($url, $path);
        Git::SVN::fetch_all($Git::SVN::default_repo_id);
+       command_oneline('config', 'svn.authorsfile', $_authors) if $_authors;
 }
 
 sub cmd_init {
@@ -2663,12 +2669,33 @@ sub other_gs {
        $gs
 }
 
+sub call_authors_prog {
+       my ($orig_author) = @_;
+       my $author = `$::_authors_prog $orig_author`;
+       if ($? != 0) {
+               die "$::_authors_prog failed with exit code $?\n"
+       }
+       if ($author =~ /^\s*(.+?)\s*<(.*)>\s*$/) {
+               my ($name, $email) = ($1, $2);
+               $email = undef if length $2 == 0;
+               return [$name, $email];
+       } else {
+               die "Author: $orig_author: $::_authors_prog returned "
+                       . "invalid author format: $author\n";
+       }
+}
+
 sub check_author {
        my ($author) = @_;
        if (!defined $author || length $author == 0) {
                $author = '(no author)';
-       } elsif (defined $::_authors && ! defined $::users{$author}) {
-               die "Author: $author not defined in $::_authors file\n";
+       }
+       if (!defined $::users{$author}) {
+               if (defined $::_authors_prog) {
+                       $::users{$author} = call_authors_prog($author);
+               } elsif (defined $::_authors) {
+                       die "Author: $author not defined in $::_authors file\n";
+               }
        }
        $author;
 }
@@ -4438,6 +4465,7 @@ sub gs_fetch_loop_common {
        my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc);
        my $longest_path = longest_common_path($gsv, $globs);
        my $ra_url = $self->{url};
+       my $find_trailing_edge;
        while (1) {
                my %revs;
                my $err;
@@ -4455,8 +4483,10 @@ sub gs_fetch_loop_common {
                               sub { $revs{$_[1]} = _cb(@_) });
                if ($err) {
                        print "Checked through r$max\r";
+               } else {
+                       $find_trailing_edge = 1;
                }
-               if ($err && $max >= $head) {
+               if ($err and $find_trailing_edge) {
                        print STDERR "Path '$longest_path' ",
                                     "was probably deleted:\n",
                                     $err->expanded_message,
@@ -4468,13 +4498,14 @@ sub gs_fetch_loop_common {
                                my $ok;
                                $self->get_log([$longest_path], $min, $hi,
                                               0, 1, 1, sub {
-                                              $ok ||= $_[1];
+                                              $ok = $_[1];
                                               $revs{$_[1]} = _cb(@_) });
                                if ($ok) {
                                        print STDERR "r$min .. r$ok OK\n";
                                        last;
                                }
                        }
+                       $find_trailing_edge = 0;
                }
                $SVN::Error::handler = $err_handler;
 
index 3f99361ed03b8d5202cb17e894c65678364fc1ed..d143829c5d69f2ceeab894b083b55b5ed3b90514 100755 (executable)
@@ -838,7 +838,7 @@ exit;
 ## ======================================================================
 ## action links
 
-sub href (%) {
+sub href {
        my %params = @_;
        # default is to use -absolute url() i.e. $my_uri
        my $href = $params{-full} ? $my_url : $my_uri;
@@ -1036,7 +1036,7 @@ sub esc_url {
 }
 
 # replace invalid utf8 character with SUBSTITUTION sequence
-sub esc_html ($;%) {
+sub esc_html {
        my $str = shift;
        my %opts = @_;
 
@@ -1235,7 +1235,7 @@ sub chop_and_escape_str {
        if ($chopped eq $str) {
                return esc_html($chopped);
        } else {
-               $str =~ s/([[:cntrl:]])/?/g;
+               $str =~ s/[[:cntrl:]]/?/g;
                return $cgi->span({-title=>$str}, esc_html($chopped));
        }
 }
@@ -1296,7 +1296,7 @@ use constant {
 };
 
 # submodule/subproject, a commit object reference
-sub S_ISGITLINK($) {
+sub S_ISGITLINK {
        my $mode = shift;
 
        return (($mode & S_IFMT) == S_IFGITLINK)
@@ -1458,6 +1458,7 @@ sub format_subject_html {
        $extra = '' unless defined($extra);
 
        if (length($short) < length($long)) {
+               $long =~ s/[[:cntrl:]]/?/g;
                return $cgi->a({-href => $href, -class => "list subject",
                                -title => to_utf8($long)},
                       esc_html($short) . $extra);
@@ -2615,7 +2616,7 @@ sub parsed_difftree_line {
 }
 
 # parse line of git-ls-tree output
-sub parse_ls_tree_line ($;%) {
+sub parse_ls_tree_line {
        my $line = shift;
        my %opts = @_;
        my %res;
@@ -3213,7 +3214,6 @@ sub git_print_header_div {
              "\n</div>\n";
 }
 
-#sub git_print_authorship (\%) {
 sub git_print_authorship {
        my $co = shift;
 
@@ -3269,8 +3269,7 @@ sub git_print_page_path {
        print "<br/></div>\n";
 }
 
-# sub git_print_log (\@;%) {
-sub git_print_log ($;%) {
+sub git_print_log {
        my $log = shift;
        my %opts = @_;
 
diff --git a/graph.c b/graph.c
index 06fbeb6c2416d0c1c5fd7df1a12924656592cdc3..f8d7a5c0f6d17538a72b75e8de9dd092829a0262 100644 (file)
--- a/graph.c
+++ b/graph.c
@@ -47,20 +47,6 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb);
  * - Limit the number of columns, similar to the way gitk does.
  *   If we reach more than a specified number of columns, omit
  *   sections of some columns.
- *
- * - The output during the GRAPH_PRE_COMMIT and GRAPH_COLLAPSING states
- *   could be made more compact by printing horizontal lines, instead of
- *   long diagonal lines.  For example, during collapsing, something like
- *   this:          instead of this:
- *   | | | | |      | | | | |
- *   | |_|_|/       | | | |/
- *   |/| | |        | | |/|
- *   | | | |        | |/| |
- *                  |/| | |
- *                  | | | |
- *
- *   If there are several parallel diagonal lines, they will need to be
- *   replaced with horizontal lines on subsequent rows.
  */
 
 struct column {
@@ -982,6 +968,9 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf
 {
        int i;
        int *tmp_mapping;
+       short used_horizontal = 0;
+       int horizontal_edge = -1;
+       int horizontal_edge_target = -1;
 
        /*
         * Clear out the new_mapping array
@@ -1019,6 +1008,23 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf
                         * Move to the left by one
                         */
                        graph->new_mapping[i - 1] = target;
+                       /*
+                        * If there isn't already an edge moving horizontally
+                        * select this one.
+                        */
+                       if (horizontal_edge == -1) {
+                               int j;
+                               horizontal_edge = i;
+                               horizontal_edge_target = target;
+                               /*
+                                * The variable target is the index of the graph
+                                * column, and therefore target*2+3 is the
+                                * actual screen column of the first horizontal
+                                * line.
+                                */
+                               for (j = (target * 2)+3; j < (i - 2); j += 2)
+                                       graph->new_mapping[j] = target;
+                       }
                } else if (graph->new_mapping[i - 1] == target) {
                        /*
                         * There is a branch line to our left
@@ -1039,10 +1045,21 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf
                         *
                         * The space just to the left of this
                         * branch should always be empty.
+                        *
+                        * The branch to the left of that space
+                        * should be our eventual target.
                         */
                        assert(graph->new_mapping[i - 1] > target);
                        assert(graph->new_mapping[i - 2] < 0);
+                       assert(graph->new_mapping[i - 3] == target);
                        graph->new_mapping[i - 2] = target;
+                       /*
+                        * Mark this branch as the horizontal edge to
+                        * prevent any other edges from moving
+                        * horizontally.
+                        */
+                       if (horizontal_edge == -1)
+                               horizontal_edge = i;
                }
        }
 
@@ -1061,8 +1078,23 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf
                        strbuf_addch(sb, ' ');
                else if (target * 2 == i)
                        strbuf_write_column(sb, &graph->new_columns[target], '|');
-               else
+               else if (target == horizontal_edge_target &&
+                        i != horizontal_edge - 1) {
+                               /*
+                                * Set the mappings for all but the
+                                * first segment to -1 so that they
+                                * won't continue into the next line.
+                                */
+                               if (i != (target * 2)+3)
+                                       graph->new_mapping[i] = -1;
+                               used_horizontal = 1;
+                       strbuf_write_column(sb, &graph->new_columns[target], '_');
+               } else {
+                       if (used_horizontal && i < horizontal_edge)
+                               graph->new_mapping[i] = -1;
                        strbuf_write_column(sb, &graph->new_columns[target], '/');
+
+               }
        }
 
        graph_pad_horizontally(graph, sb, graph->mapping_size);
diff --git a/grep.c b/grep.c
index 04c777a20c1a8c10417cc9d44e53e5b99dc32a27..a649f063cf28baa5b0ddce72d7d6e4d9fca6f360 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -305,6 +305,7 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
 {
        int hit = 0;
        int saved_ch = 0;
+       const char *start = bol;
 
        if ((p->token != GREP_PATTERN) &&
            ((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
@@ -365,6 +366,10 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
        }
        if (p->token == GREP_PATTERN_HEAD && saved_ch)
                *eol = saved_ch;
+       if (hit) {
+               pmatch[0].rm_so += bol - start;
+               pmatch[0].rm_eo += bol - start;
+       }
        return hit;
 }
 
diff --git a/grep.h b/grep.h
index a67005de62d1442e7ba6a8dc27320225a0d55819..464e272edf4594539915a89d68628fd3959b8ee3 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -61,23 +61,23 @@ struct grep_opt {
        struct grep_expr *pattern_expression;
        int prefix_length;
        regex_t regexp;
-       unsigned linenum:1;
-       unsigned invert:1;
-       unsigned status_only:1;
-       unsigned name_only:1;
-       unsigned unmatch_name_only:1;
-       unsigned count:1;
-       unsigned word_regexp:1;
-       unsigned fixed:1;
-       unsigned all_match:1;
+       int linenum;
+       int invert;
+       int status_only;
+       int name_only;
+       int unmatch_name_only;
+       int count;
+       int word_regexp;
+       int fixed;
+       int all_match;
 #define GREP_BINARY_DEFAULT    0
 #define GREP_BINARY_NOMATCH    1
 #define GREP_BINARY_TEXT       2
-       unsigned binary:2;
-       unsigned extended:1;
-       unsigned relative:1;
-       unsigned pathname:1;
-       unsigned null_following_name:1;
+       int binary;
+       int extended;
+       int relative;
+       int pathname;
+       int null_following_name;
        int color;
        char color_match[COLOR_MAXLEN];
        const char *color_external;
index 5138224cc372482fb60afd350fa40e37d019f367..dac2c6e0524e3051ca98bfb4d75fbc81efe91eef 100644 (file)
@@ -315,9 +315,9 @@ static void start_fetch_loose(struct transfer_request *request)
                 "%s.temp", filename);
 
        snprintf(prevfile, sizeof(prevfile), "%s.prev", request->filename);
-       unlink(prevfile);
+       unlink_or_warn(prevfile);
        rename(request->tmpfile, prevfile);
-       unlink(request->tmpfile);
+       unlink_or_warn(request->tmpfile);
 
        if (request->local_fileno != -1)
                error("fd leakage in start: %d", request->local_fileno);
@@ -372,7 +372,7 @@ static void start_fetch_loose(struct transfer_request *request)
                } while (prev_read > 0);
                close(prevlocal);
        }
-       unlink(prevfile);
+       unlink_or_warn(prevfile);
 
        /* Reset inflate/SHA1 if there was an error reading the previous temp
           file; also rewind to the beginning of the local file. */
@@ -784,7 +784,7 @@ static void finish_request(struct transfer_request *request)
                    request->http_code != 416) {
                        if (stat(request->tmpfile, &st) == 0) {
                                if (st.st_size == 0)
-                                       unlink(request->tmpfile);
+                                       unlink_or_warn(request->tmpfile);
                        }
                } else {
                        if (request->http_code == 416)
@@ -793,9 +793,9 @@ static void finish_request(struct transfer_request *request)
                        git_inflate_end(&request->stream);
                        git_SHA1_Final(request->real_sha1, &request->c);
                        if (request->zret != Z_STREAM_END) {
-                               unlink(request->tmpfile);
+                               unlink_or_warn(request->tmpfile);
                        } else if (hashcmp(request->obj->sha1, request->real_sha1)) {
-                               unlink(request->tmpfile);
+                               unlink_or_warn(request->tmpfile);
                        } else {
                                request->rename =
                                        move_temp_to_file(
@@ -2326,7 +2326,7 @@ int main(int argc, char **argv)
        new_refs = 0;
        for (ref = remote_refs; ref; ref = ref->next) {
                char old_hex[60], *new_hex;
-               const char *commit_argv[4];
+               const char *commit_argv[5];
                int commit_argc;
                char *new_sha1_hex, *old_sha1_hex;
 
@@ -2406,6 +2406,7 @@ int main(int argc, char **argv)
                        commit_argv[3] = old_sha1_hex;
                        commit_argc++;
                }
+               commit_argv[commit_argc] = NULL;
                init_revisions(&revs, setup_git_directory());
                setup_revisions(commit_argc, commit_argv, &revs, NULL);
                revs.edge_hint = 0; /* just in case */
index c5a3ea3b31045be9407579a9d1aba222ee3e9914..7321ccc9fe751a1e608c6620bcce401eac7ff98c 100644 (file)
@@ -111,9 +111,9 @@ static void start_object_request(struct walker *walker,
        struct walker_data *data = walker->data;
 
        snprintf(prevfile, sizeof(prevfile), "%s.prev", obj_req->filename);
-       unlink(prevfile);
+       unlink_or_warn(prevfile);
        rename(obj_req->tmpfile, prevfile);
-       unlink(obj_req->tmpfile);
+       unlink_or_warn(obj_req->tmpfile);
 
        if (obj_req->local != -1)
                error("fd leakage in start: %d", obj_req->local);
@@ -177,7 +177,7 @@ static void start_object_request(struct walker *walker,
                } while (prev_read > 0);
                close(prevlocal);
        }
-       unlink(prevfile);
+       unlink_or_warn(prevfile);
 
        /* Reset inflate/SHA1 if there was an error reading the previous temp
           file; also rewind to the beginning of the local file. */
@@ -238,18 +238,18 @@ static void finish_object_request(struct object_request *obj_req)
        } else if (obj_req->curl_result != CURLE_OK) {
                if (stat(obj_req->tmpfile, &st) == 0)
                        if (st.st_size == 0)
-                               unlink(obj_req->tmpfile);
+                               unlink_or_warn(obj_req->tmpfile);
                return;
        }
 
        git_inflate_end(&obj_req->stream);
        git_SHA1_Final(obj_req->real_sha1, &obj_req->c);
        if (obj_req->zret != Z_STREAM_END) {
-               unlink(obj_req->tmpfile);
+               unlink_or_warn(obj_req->tmpfile);
                return;
        }
        if (hashcmp(obj_req->sha1, obj_req->real_sha1)) {
-               unlink(obj_req->tmpfile);
+               unlink_or_warn(obj_req->tmpfile);
                return;
        }
        obj_req->rename =
@@ -809,7 +809,7 @@ static void abort_object_request(struct object_request *obj_req)
                close(obj_req->local);
                obj_req->local = -1;
        }
-       unlink(obj_req->tmpfile);
+       unlink_or_warn(obj_req->tmpfile);
        if (obj_req->slot) {
                release_active_slot(obj_req->slot);
                obj_req->slot = NULL;
index fa2ca5250c75a0d335570a3a3c71b20ebd0b42fa..81c02ad0531e98379d8cd11dc7c2d70214d67fb4 100644 (file)
@@ -219,7 +219,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
        close(fd);
  bad:
        for (i = 0; i < 3; i++)
-               unlink(temp[i]);
+               unlink_or_warn(temp[i]);
        strbuf_release(&cmd);
        return status;
 }
index 828d19f452a8bfffe2ee224a630e8246f4a1edab..eb931eded5a6ed20f1d80dadf08cbb8009d85767 100644 (file)
@@ -16,7 +16,7 @@ static void remove_lock_file(void)
                    lock_file_list->filename[0]) {
                        if (lock_file_list->fd >= 0)
                                close(lock_file_list->fd);
-                       unlink(lock_file_list->filename);
+                       unlink_or_warn(lock_file_list->filename);
                }
                lock_file_list = lock_file_list->next;
        }
@@ -259,7 +259,7 @@ void rollback_lock_file(struct lock_file *lk)
        if (lk->filename[0]) {
                if (lk->fd >= 0)
                        close(lk->fd);
-               unlink(lk->filename);
+               unlink_or_warn(lk->filename);
        }
        lk->filename[0] = 0;
 }
index a3721efcaf9458e5c735b45794d60bac670366d2..f5df9b961b2999e4824b900d61d28c254b2ef858 100644 (file)
@@ -933,11 +933,12 @@ static int process_renames(struct merge_options *o,
                                       ren1_src, ren1_dst, branch1,
                                       branch2);
                                update_file(o, 0, ren1->pair->two->sha1, ren1->pair->two->mode, ren1_dst);
-                               update_stages(ren1_dst, NULL,
-                                               branch1 == o->branch1 ?
-                                               ren1->pair->two : NULL,
-                                               branch1 == o->branch1 ?
-                                               NULL : ren1->pair->two, 1);
+                               if (!o->call_depth)
+                                       update_stages(ren1_dst, NULL,
+                                                       branch1 == o->branch1 ?
+                                                       ren1->pair->two : NULL,
+                                                       branch1 == o->branch1 ?
+                                                       NULL : ren1->pair->two, 1);
                        } else if (!sha_eq(dst_other.sha1, null_sha1)) {
                                const char *new_path;
                                clean_merge = 0;
index 7e6a92c88e7b139ec03e0ff26e97e1559a06a220..a6ef439192c1083e367f0a86cb10d93564fc9481 100644 (file)
--- a/object.c
+++ b/object.c
@@ -45,13 +45,14 @@ int type_from_string(const char *str)
 
 static unsigned int hash_obj(struct object *obj, unsigned int n)
 {
-       unsigned int hash = *(unsigned int *)obj->sha1;
+       unsigned int hash;
+       memcpy(&hash, obj->sha1, sizeof(unsigned int));
        return hash % n;
 }
 
 static void insert_obj_hash(struct object *obj, struct object **hash, unsigned int size)
 {
-       int j = hash_obj(obj, size);
+       unsigned int j = hash_obj(obj, size);
 
        while (hash[j]) {
                j++;
@@ -61,16 +62,16 @@ static void insert_obj_hash(struct object *obj, struct object **hash, unsigned i
        hash[j] = obj;
 }
 
-static int hashtable_index(const unsigned char *sha1)
+static unsigned int hashtable_index(const unsigned char *sha1)
 {
        unsigned int i;
        memcpy(&i, sha1, sizeof(unsigned int));
-       return (int)(i % obj_hash_size);
+       return i % obj_hash_size;
 }
 
 struct object *lookup_object(const unsigned char *sha1)
 {
-       int i;
+       unsigned int i;
        struct object *obj;
 
        if (!obj_hash)
index 2c76fb181f64e10c65517224b0c09cb648db81ac..301fc60eae1ad53721851a272a0fbd0192881801 100644 (file)
@@ -66,7 +66,7 @@ static void prune_ref(struct ref_to_prune *r)
        struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
 
        if (lock) {
-               unlink(git_path("%s", r->name));
+               unlink_or_warn(git_path("%s", r->name));
                unlock_ref(lock);
        }
 }
index cf71bcffd2e1e9aeacb44df488b0825f09d54255..c52b8ccf59a4848be6f3f810e01029f7c6625c78 100644 (file)
@@ -50,6 +50,7 @@ static int get_value(struct parse_opt_ctx_t *p,
                        /* FALLTHROUGH */
                case OPTION_BOOLEAN:
                case OPTION_BIT:
+               case OPTION_NEGBIT:
                case OPTION_SET_INT:
                case OPTION_SET_PTR:
                        return opterror(opt, "takes no value", flags);
@@ -66,6 +67,13 @@ static int get_value(struct parse_opt_ctx_t *p,
                        *(int *)opt->value |= opt->defval;
                return 0;
 
+       case OPTION_NEGBIT:
+               if (unset)
+                       *(int *)opt->value |= opt->defval;
+               else
+                       *(int *)opt->value &= ~opt->defval;
+               return 0;
+
        case OPTION_BOOLEAN:
                *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
                return 0;
@@ -121,11 +129,33 @@ static int get_value(struct parse_opt_ctx_t *p,
 
 static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
 {
+       const struct option *numopt = NULL;
+
        for (; options->type != OPTION_END; options++) {
                if (options->short_name == *p->opt) {
                        p->opt = p->opt[1] ? p->opt + 1 : NULL;
                        return get_value(p, options, OPT_SHORT);
                }
+
+               /*
+                * Handle the numerical option later, explicit one-digit
+                * options take precedence over it.
+                */
+               if (options->type == OPTION_NUMBER)
+                       numopt = options;
+       }
+       if (numopt && isdigit(*p->opt)) {
+               size_t len = 1;
+               char *arg;
+               int rc;
+
+               while (isdigit(p->opt[len]))
+                       len++;
+               arg = xmemdupz(p->opt, len);
+               p->opt = p->opt[len] ? p->opt + len : NULL;
+               rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0;
+               free(arg);
+               return rc;
        }
        return -2;
 }
@@ -215,6 +245,25 @@ is_abbreviated:
        return -2;
 }
 
+static int parse_nodash_opt(struct parse_opt_ctx_t *p, const char *arg,
+                           const struct option *options)
+{
+       for (; options->type != OPTION_END; options++) {
+               if (!(options->flags & PARSE_OPT_NODASH))
+                       continue;
+               if ((options->flags & PARSE_OPT_OPTARG) ||
+                   !(options->flags & PARSE_OPT_NOARG))
+                       die("BUG: dashless options don't support arguments");
+               if (!(options->flags & PARSE_OPT_NONEG))
+                       die("BUG: dashless options don't support negation");
+               if (options->long_name)
+                       die("BUG: dashless options can't be long");
+               if (options->short_name == arg[0] && arg[1] == '\0')
+                       return get_value(p, options, OPT_SHORT);
+       }
+       return -2;
+}
+
 static void check_typos(const char *arg, const struct option *options)
 {
        if (strlen(arg) < 3)
@@ -265,6 +314,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                const char *arg = ctx->argv[0];
 
                if (*arg != '-' || !arg[1]) {
+                       if (parse_nodash_opt(ctx, arg, options) == 0)
+                               continue;
                        if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
                                break;
                        ctx->out[ctx->cpidx++] = ctx->argv[0];
@@ -397,12 +448,18 @@ int usage_with_options_internal(const char * const *usagestr,
                        continue;
 
                pos = fprintf(stderr, "    ");
-               if (opts->short_name)
-                       pos += fprintf(stderr, "-%c", opts->short_name);
+               if (opts->short_name) {
+                       if (opts->flags & PARSE_OPT_NODASH)
+                               pos += fprintf(stderr, "%c", opts->short_name);
+                       else
+                               pos += fprintf(stderr, "-%c", opts->short_name);
+               }
                if (opts->long_name && opts->short_name)
                        pos += fprintf(stderr, ", ");
                if (opts->long_name)
                        pos += fprintf(stderr, "--%s", opts->long_name);
+               if (opts->type == OPTION_NUMBER)
+                       pos += fprintf(stderr, "-NUM");
 
                switch (opts->type) {
                case OPTION_ARGUMENT:
@@ -439,7 +496,7 @@ int usage_with_options_internal(const char * const *usagestr,
                                        pos += fprintf(stderr, " ...");
                        }
                        break;
-               default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
+               default: /* OPTION_{BIT,BOOLEAN,NUMBER,SET_INT,SET_PTR} */
                        break;
                }
 
index b54eec128bcda1a8b4c4a2c33f2ce799c506ac23..919b9b441f97511695308287a2fdc6f3a45e383d 100644 (file)
@@ -6,8 +6,10 @@ enum parse_opt_type {
        OPTION_END,
        OPTION_ARGUMENT,
        OPTION_GROUP,
+       OPTION_NUMBER,
        /* options with no arguments */
        OPTION_BIT,
+       OPTION_NEGBIT,
        OPTION_BOOLEAN, /* _INCR would have been a better name */
        OPTION_SET_INT,
        OPTION_SET_PTR,
@@ -31,6 +33,7 @@ enum parse_opt_option_flags {
        PARSE_OPT_NONEG   = 4,
        PARSE_OPT_HIDDEN  = 8,
        PARSE_OPT_LASTARG_DEFAULT = 16,
+       PARSE_OPT_NODASH = 32,
 };
 
 struct option;
@@ -64,8 +67,11 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
  *   PARSE_OPT_OPTARG: says that the argument is optional (not for BOOLEANs)
  *   PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
  *   PARSE_OPT_NONEG: says that this option cannot be negated
- *   PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in
- *                    the long one.
+ *   PARSE_OPT_HIDDEN: this option is skipped in the default usage, and
+ *                     shown only in the full usage.
+ *   PARSE_OPT_LASTARG_DEFAULT: if no argument is given, the default value
+ *                              is used.
+ *   PARSE_OPT_NODASH: this option doesn't start with a dash.
  *
  * `callback`::
  *   pointer to the callback to use for OPTION_CALLBACK.
@@ -93,6 +99,7 @@ struct option {
 #define OPT_ARGUMENT(l, h)          { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
 #define OPT_GROUP(h)                { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
 #define OPT_BIT(s, l, v, h, b)      { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
+#define OPT_NEGBIT(s, l, v, h, b)   { OPTION_NEGBIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
 #define OPT_BOOLEAN(s, l, v, h)     { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
 #define OPT_SET_INT(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) }
 #define OPT_SET_PTR(s, l, v, h, p)  { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) }
@@ -103,6 +110,9 @@ struct option {
          parse_opt_approxidate_cb }
 #define OPT_CALLBACK(s, l, v, a, h, f) \
        { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
+#define OPT_NUMBER_CALLBACK(v, h, f) \
+       { OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
+         PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
 
 /* parse_options() will filter out the processed options and leave the
  * non-option arguments in argv[].
index 291ff5b53c1883ee8fce67fbb7e2b32393ef0800..e8df55d2f290210ba4cf7ae8c91639f2a34c834e 100644 (file)
@@ -185,7 +185,7 @@ sub repository {
 
                if ($dir) {
                        $dir =~ m#^/# or $dir = $opts{Directory} . '/' . $dir;
-                       $opts{Repository} = $dir;
+                       $opts{Repository} = abs_path($dir);
 
                        # If --git-dir went ok, this shouldn't die either.
                        my $prefix = $search->command_oneline('rev-parse', '--show-prefix');
@@ -1280,6 +1280,8 @@ sub _cmd_exec {
        my ($self, @args) = @_;
        if ($self) {
                $self->repo_path() and $ENV{'GIT_DIR'} = $self->repo_path();
+               $self->repo_path() and $self->wc_path()
+                       and $ENV{'GIT_WORK_TREE'} = $self->wc_path();
                $self->wc_path() and chdir($self->wc_path());
                $self->wc_subdir() and chdir($self->wc_subdir());
        }
diff --git a/refs.c b/refs.c
index e65a3b4c4ef57863a1055108d2598777cabc2c8d..bb4bdc9eac9a3cb5a122437f14a0f175511b1493 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -682,12 +682,13 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
  * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
  * - it ends with a "/".
  * - it ends with ".lock"
+ * - it contains a "\" (backslash)
  */
 
 static inline int bad_ref_char(int ch)
 {
        if (((unsigned) ch) <= ' ' ||
-           ch == '~' || ch == '^' || ch == ':')
+           ch == '~' || ch == '^' || ch == ':' || ch == '\\')
                return 1;
        /* 2.13 Pattern Matching Notation */
        if (ch == '?' || ch == '[') /* Unsupported */
@@ -1002,12 +1003,10 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
                } else {
                        path = git_path("%s", refname);
                }
-               err = unlink(path);
-               if (err && errno != ENOENT) {
+               err = unlink_or_warn(path);
+               if (err && errno != ENOENT)
                        ret = 1;
-                       error("unlink(%s) failed: %s",
-                             path, strerror(errno));
-               }
+
                if (!(delopt & REF_NODEREF))
                        lock->lk->filename[i] = '.';
        }
@@ -1017,10 +1016,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
         */
        ret |= repack_without_ref(refname);
 
-       err = unlink(git_path("logs/%s", lock->ref_name));
-       if (err && errno != ENOENT)
-               warning("unlink(%s) failed: %s",
-                       git_path("logs/%s", lock->ref_name), strerror(errno));
+       unlink_or_warn(git_path("logs/%s", lock->ref_name));
        invalidate_cached_refs();
        unlock_ref(lock);
        return ret;
@@ -1381,7 +1377,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
        if (adjust_shared_perm(git_HEAD)) {
                error("Unable to fix permissions on %s", lockpath);
        error_unlink_return:
-               unlink(lockpath);
+               unlink_or_warn(lockpath);
        error_free_return:
                free(git_HEAD);
                return -1;
index 713c6e16ac536eaa667cc9f22768670be129483c..87360dc23e54aabf47b3bda160e58058507d4a2f 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -173,7 +173,7 @@ static int handle_file(const char *path,
                git_SHA1_Final(sha1, &ctx);
        if (hunk != RR_CONTEXT) {
                if (output)
-                       unlink(output);
+                       unlink_or_warn(output);
                return error("Could not parse conflict hunks in %s", path);
        }
        if (wrerror)
index 83d76c7e35183ded9eec5a56c59d4da549c0b584..1d7b1b3b4f41177dfd6637fcd98a0fc01f310c09 100644 (file)
@@ -6,6 +6,7 @@ struct send_pack_args {
                send_mirror:1,
                force_update:1,
                use_thin_pack:1,
+               use_ofs_delta:1,
                dry_run:1;
 };
 
index 906ce5b27242ca1e415a5410135d58f1c000e8b0..4098ca2b5c166c32cfe4aea9d1bff2e6593e9a60 100644 (file)
@@ -246,7 +246,7 @@ int update_server_info(int force)
        errs = errs | update_info_packs(force);
 
        /* remove leftover rev-cache file if there is any */
-       unlink(git_path("info/rev-cache"));
+       unlink_or_warn(git_path("info/rev-cache"));
 
        return errs;
 }
index 28bd9082fc9f4b79519f6bef8204600072c07027..e73cd4fc0ba2daac14f604f1973d1b0658212b26 100644 (file)
@@ -720,6 +720,8 @@ static int open_packed_git_1(struct packed_git *p)
                return error("packfile %s index unavailable", p->pack_name);
 
        p->pack_fd = open(p->pack_name, O_RDONLY);
+       while (p->pack_fd < 0 && errno == EMFILE && unuse_one_window(p, -1))
+               p->pack_fd = open(p->pack_name, O_RDONLY);
        if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
                return -1;
 
@@ -937,6 +939,8 @@ static void prepare_packed_git_one(char *objdir, int local)
        sprintf(path, "%s/pack", objdir);
        len = strlen(path);
        dir = opendir(path);
+       while (!dir && errno == EMFILE && unuse_one_window(packed_git, -1))
+               dir = opendir(path);
        if (!dir) {
                if (errno != ENOENT)
                        error("unable to open object pack directory: %s: %s",
@@ -2247,7 +2251,7 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
                        goto out;
                ret = errno;
        }
-       unlink(tmpfile);
+       unlink_or_warn(tmpfile);
        if (ret) {
                if (ret != EEXIST) {
                        return error("unable to write sha1 filename %s: %s\n", filename, strerror(ret));
@@ -2339,6 +2343,8 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
 
        filename = sha1_file_name(sha1);
        fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
+       while (fd < 0 && errno == EMFILE && unuse_one_window(packed_git, -1))
+               fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
        if (fd < 0) {
                if (errno == EACCES)
                        return error("insufficient permission for adding an object to repository database %s\n", get_object_directory());
index 773d47cf3cb704d7976185738a2b9840c159a33c..56549623430ca6bea2de35bbae7d2d211720da3b 100644 (file)
@@ -26,6 +26,8 @@ fi
 
 svnrepo=$PWD/svnrepo
 export svnrepo
+svnconf=$PWD/svnconf
+export svnconf
 
 perl -w -e "
 use SVN::Core;
@@ -54,6 +56,19 @@ poke() {
        test-chmtime +1 "$1"
 }
 
+# We need this, because we should pass empty configuration directory to
+# the 'svn commit' to avoid automated property changes and other stuff
+# that could be set from user's configuration files in ~/.subversion.
+svn_cmd () {
+       [ -d "$svnconf" ] || mkdir "$svnconf"
+       orig_svncmd="$1"; shift
+       if [ -z "$orig_svncmd" ]; then
+               svn
+               return
+       fi
+       svn "$orig_svncmd" --config-dir "$svnconf" "$@"
+}
+
 for d in \
        "$SVN_HTTPD_PATH" \
        /usr/sbin/apache2 \
index e38241c80a6625c9b5b89340b9d0c5a2667bf345..a40c1236c0862da4d77231bf9255b499ccddd99f 100755 (executable)
@@ -12,6 +12,7 @@ usage: test-parse-options <options>
 
     -b, --boolean         get a boolean
     -4, --or4             bitwise-or boolean with ...0100
+    --neg-or4             same as --no-or4
 
     -i, --integer <n>     get a integer
     -j <n>                get a integer, too
@@ -29,6 +30,8 @@ String options
 
 Magic arguments
     --quux                means --quux
+    -NUM                  set integer to NUM
+    +                     same as -b
 
 Standard options
     --abbrev[=<n>]        use <n> digits to display SHA-1s
@@ -245,7 +248,56 @@ test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
        test_cmp expect output
 '
 
-# --or4
-# --no-or4
+test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
+       test-parse-options --set23 -bbbbb --neg-or4 > output 2> output.err &&
+       test ! -s output.err &&
+       test_cmp expect output
+'
+
+cat > expect <<EOF
+boolean: 6
+integer: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+EOF
+
+test_expect_success 'OPT_BIT() works' '
+       test-parse-options -bb --or4 > output 2> output.err &&
+       test ! -s output.err &&
+       test_cmp expect output
+'
+
+test_expect_success 'OPT_NEGBIT() works' '
+       test-parse-options -bb --no-neg-or4 > output 2> output.err &&
+       test ! -s output.err &&
+       test_cmp expect output
+'
+
+test_expect_success 'OPT_BOOLEAN() with PARSE_OPT_NODASH works' '
+       test-parse-options + + + + + + > output 2> output.err &&
+       test ! -s output.err &&
+       test_cmp expect output
+'
+
+cat > expect <<EOF
+boolean: 0
+integer: 12345
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+EOF
+
+test_expect_success 'OPT_NUMBER_CALLBACK() works' '
+       test-parse-options -12345 > output 2> output.err &&
+       test ! -s output.err &&
+       test_cmp expect output
+'
 
 test_done
diff --git a/t/t2014-switch.sh b/t/t2014-switch.sh
new file mode 100755 (executable)
index 0000000..ccfb147
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+test_description='Peter MacMillan'
+. ./test-lib.sh
+
+test_expect_success setup '
+       echo Hello >file &&
+       git add file &&
+       test_tick &&
+       git commit -m V1 &&
+       echo Hello world >file &&
+       git add file &&
+       git checkout -b other
+'
+
+test_expect_success 'check all changes are staged' '
+       git diff --exit-code
+'
+
+test_expect_success 'second commit' '
+       git commit -m V2
+'
+
+test_expect_success 'check' '
+       git diff --cached --exit-code
+'
+
+test_done
diff --git a/t/t3031-merge-criscross.sh b/t/t3031-merge-criscross.sh
new file mode 100755 (executable)
index 0000000..7f41607
--- /dev/null
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+test_description='merge-recursive backend test'
+
+. ./test-lib.sh
+
+#         A      <- create some files
+#        / \
+#       B   C    <- cause rename/delete conflicts between B and C
+#      /     \
+#     |\     /|
+#     | D   E |
+#     |  \ /  |
+#     |   X   |
+#     |  / \  |
+#     | /   \ |
+#     |/     \|
+#     F       G  <- merge E into B, D into C
+#      \     /
+#       \   /
+#        \ /
+#         H      <- recursive merge crashes
+#
+
+# initialize
+test_expect_success 'setup repo with criss-cross history' '
+       mkdir data &&
+
+       # create a bunch of files
+       n=1 &&
+       while test $n -le 10
+       do
+               echo $n > data/$n &&
+               n=$(($n+1)) ||
+               break
+       done &&
+
+       # check them in
+       git add data &&
+       git commit -m A &&
+       git branch A &&
+
+       # a file in one branch
+       git checkout -b B A &&
+       git rm data/9 &&
+       git add data &&
+       git commit -m B &&
+
+       # with a branch off of it
+       git branch D &&
+
+       # put some commits on D
+       git checkout D &&
+       echo testD > data/testD &&
+       git add data &&
+       git commit -m D &&
+
+       # back up to the top, create another branch and cause
+       # a rename conflict with the file we deleted earlier
+       git checkout -b C A &&
+       git mv data/9 data/new-9 &&
+       git add data &&
+       git commit -m C &&
+
+       # with a branch off of it
+       git branch E &&
+
+       # put a commit on E
+       git checkout E &&
+       echo testE > data/testE &&
+       git add data &&
+       git commit -m E &&
+
+       # now, merge E into B
+       git checkout B &&
+       test_must_fail git merge E &&
+       # force-resolve
+       git add data &&
+       git commit -m F &&
+       git branch F &&
+
+       # and merge D into C
+       git checkout C &&
+       test_must_fail git merge D &&
+       # force-resolve
+       git add data &&
+       git commit -m G &&
+       git branch G
+'
+
+test_expect_success 'recursive merge between F and G, causes segfault' '
+       git merge F
+'
+
+test_done
diff --git a/t/t3702-add-edit.sh b/t/t3702-add-edit.sh
new file mode 100755 (executable)
index 0000000..4ee47cc
--- /dev/null
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='add -e basic tests'
+. ./test-lib.sh
+
+
+cat > file << EOF
+LO, praise of the prowess of people-kings
+of spear-armed Danes, in days long sped,
+we have heard, and what honor the athelings won!
+Oft Scyld the Scefing from squadroned foes,
+from many a tribe, the mead-bench tore,
+awing the earls. Since erst he lay
+friendless, a foundling, fate repaid him:
+for he waxed under welkin, in wealth he throve,
+till before him the folk, both far and near,
+who house by the whale-path, heard his mandate,
+gave him gifts:  a good king he!
+EOF
+
+cat > second-part << EOF
+To him an heir was afterward born,
+a son in his halls, whom heaven sent
+to favor the folk, feeling their woe
+that erst they had lacked an earl for leader
+so long a while; the Lord endowed him,
+the Wielder of Wonder, with world's renown.
+EOF
+
+test_expect_success 'setup' '
+
+       git add file &&
+       test_tick &&
+       git commit -m initial file
+
+'
+
+cat > expected-patch << EOF
+diff --git a/file b/file
+index b9834b5..9020acb 100644
+--- a/file
++++ b/file
+@@ -1,11 +1,6 @@
+-LO, praise of the prowess of people-kings
+-of spear-armed Danes, in days long sped,
+-we have heard, and what honor the athelings won!
+-Oft Scyld the Scefing from squadroned foes,
+-from many a tribe, the mead-bench tore,
+-awing the earls. Since erst he lay
+-friendless, a foundling, fate repaid him:
+-for he waxed under welkin, in wealth he throve,
+-till before him the folk, both far and near,
+-who house by the whale-path, heard his mandate,
+-gave him gifts:  a good king he!
++To him an heir was afterward born,
++a son in his halls, whom heaven sent
++to favor the folk, feeling their woe
++that erst they had lacked an earl for leader
++so long a while; the Lord endowed him,
++the Wielder of Wonder, with world's renown.
+EOF
+
+cat > patch << EOF
+diff --git a/file b/file
+index b9834b5..ef6e94c 100644
+--- a/file
++++ b/file
+@@ -3,1 +3,333 @@ of spear-armed Danes, in days long sped,
+ we have heard, and what honor the athelings won!
++
+ Oft Scyld the Scefing from squadroned foes,
+@@ -2,7 +1,5 @@ awing the earls. Since erst he lay
+ friendless, a foundling, fate repaid him:
++
+ for he waxed under welkin, in wealth he throve,
+EOF
+
+cat > expected << EOF
+diff --git a/file b/file
+index b9834b5..ef6e94c 100644
+--- a/file
++++ b/file
+@@ -1,10 +1,12 @@
+ LO, praise of the prowess of people-kings
+ of spear-armed Danes, in days long sped,
+ we have heard, and what honor the athelings won!
++
+ Oft Scyld the Scefing from squadroned foes,
+ from many a tribe, the mead-bench tore,
+ awing the earls. Since erst he lay
+ friendless, a foundling, fate repaid him:
++
+ for he waxed under welkin, in wealth he throve,
+ till before him the folk, both far and near,
+ who house by the whale-path, heard his mandate,
+EOF
+
+echo "#!$SHELL_PATH" >fake-editor.sh
+cat >> fake-editor.sh <<\EOF
+mv -f "$1" orig-patch &&
+mv -f patch "$1"
+EOF
+
+test_set_editor "$(pwd)/fake-editor.sh"
+chmod a+x fake-editor.sh
+
+test_expect_success 'add -e' '
+
+       cp second-part file &&
+       git add -e &&
+       test_cmp second-part file &&
+       test_cmp orig-patch expected-patch &&
+       git diff --cached > out &&
+       test_cmp out expected
+
+'
+
+test_done
index 784c31aec99d90b69186079ddb66350d9f4a8827..b4ec2b53de2662a5ba40602d4b7a4fde984c4013 100755 (executable)
@@ -9,7 +9,15 @@ test_description='commit and log output encodings'
 
 compare_with () {
        git show -s $1 | sed -e '1,/^$/d' -e 's/^    //' >current &&
-       test_cmp current "$2"
+       case "$3" in
+       '')
+               test_cmp "$2" current ;;
+       ?*)
+               iconv -f "$3" -t UTF-8 >current.utf8 <current &&
+               iconv -f "$3" -t UTF-8 >expect.utf8 <"$2" &&
+               test_cmp expect.utf8 current.utf8
+               ;;
+       esac
 }
 
 test_expect_success setup '
@@ -103,11 +111,17 @@ done
 
 for J in EUCJP ISO-2022-JP
 do
+       if test "$J" = ISO-2022-JP
+       then
+               ICONV=$J
+       else
+               ICONV=
+       fi
        git config i18n.logoutputencoding $J
        for H in EUCJP ISO-2022-JP
        do
                test_expect_success "$H should be shown in $J now" '
-                       compare_with '$H' "$TEST_DIRECTORY"/t3900/'$J'.txt
+                       compare_with '$H' "$TEST_DIRECTORY"/t3900/'$J'.txt $ICONV
                '
        done
 done
index 11061ddd5bd122a1e180509c018e1b8bea42ddc3..922a8941ed4720e2ad6dcd500a3759187aace969 100755 (executable)
@@ -505,4 +505,15 @@ test_expect_success 'format-patch from a subdirectory (3)' '
        test -f "$basename"
 '
 
+test_expect_success 'format-patch --in-reply-to' '
+       git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
+       grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
+       grep "^References: <baz@foo.bar>" patch8
+'
+
+test_expect_success 'format-patch --signoff' '
+       git format-patch -1 --signoff --stdout |
+       grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+'
+
 test_done
index 9b6e1be8b298f4675d77adeb84dc4c8dfb4d0c85..709b3231ca8d9da631727b4aadfb2f46049d37e9 100755 (executable)
@@ -115,4 +115,10 @@ test_expect_success 'format.numbered = auto && --no-numbered' '
 
 '
 
+test_expect_success '--start-number && --numbered' '
+
+       git format-patch --start-number 3 --numbered --stdout HEAD~1 > patch8 &&
+       grep "^Subject: \[PATCH 3/3\]" patch8
+'
+
 test_done
index 64502e2be762a82b65a72af6847d5a3b79303d45..aad3894ad4c542d4ab894c2d57a035a89eb88258 100755 (executable)
@@ -324,14 +324,12 @@ cat > expect <<\EOF
 * | | |   Merge branch 'side'
 |\ \ \ \
 | * | | | side-2
-| | | |/
-| | |/|
+| | |_|/
 | |/| |
 | * | | side-1
 * | | | Second
 * | | | sixth
-| | |/
-| |/|
+| |_|/
 |/| |
 * | | fifth
 * | | fourth
index bdb808af1aefae97c297f7845a8cd3b595404e89..ebfd34df36068f8808406a98d371731fb85012c4 100755 (executable)
@@ -534,4 +534,12 @@ test_expect_success 'failing checkout -b should not break working tree' '
 
 '
 
+test_expect_success 'switch out of non-branch' '
+       git reset --hard master &&
+       git checkout master^0 &&
+       echo modified >one &&
+       test_must_fail git checkout renamer 2>error.log &&
+       ! grep "^Previous HEAD" error.log
+'
+
 test_done
diff --git a/t/t7406-submodule-reference.sh b/t/t7406-submodule-reference.sh
new file mode 100755 (executable)
index 0000000..cc16d3f
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh
+#
+# Copyright (c) 2009, Red Hat Inc, Author: Michael S. Tsirkin (mst@redhat.com)
+#
+
+test_description='test clone --reference'
+. ./test-lib.sh
+
+base_dir=`pwd`
+
+U=$base_dir/UPLOAD_LOG
+
+test_expect_success 'preparing first repository' \
+'test_create_repo A && cd A &&
+echo first > file1 &&
+git add file1 &&
+git commit -m A-initial'
+
+cd "$base_dir"
+
+test_expect_success 'preparing second repository' \
+'git clone A B && cd B &&
+echo second > file2 &&
+git add file2 &&
+git commit -m B-addition &&
+git repack -a -d &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_success 'preparing supermodule' \
+'test_create_repo super && cd super &&
+echo file > file &&
+git add file &&
+git commit -m B-super-initial'
+
+cd "$base_dir"
+
+test_expect_success 'submodule add --reference' \
+'cd super && git submodule add --reference ../B "file://$base_dir/A" sub &&
+git commit -m B-super-added'
+
+cd "$base_dir"
+
+test_expect_success 'after add: existence of info/alternates' \
+'test `wc -l <super/sub/.git/objects/info/alternates` = 1'
+
+cd "$base_dir"
+
+test_expect_success 'that reference gets used with add' \
+'cd super/sub &&
+echo "0 objects, 0 kilobytes" > expected &&
+git count-objects > current &&
+diff expected current'
+
+cd "$base_dir"
+
+test_expect_success 'cloning supermodule' \
+'git clone super super-clone'
+
+cd "$base_dir"
+
+test_expect_success 'update with reference' \
+'cd super-clone && git submodule update --init --reference ../B'
+
+cd "$base_dir"
+
+test_expect_success 'after update: existence of info/alternates' \
+'test `wc -l <super-clone/sub/.git/objects/info/alternates` = 1'
+
+cd "$base_dir"
+
+test_expect_success 'that reference gets used with update' \
+'cd super-clone/sub &&
+echo "0 objects, 0 kilobytes" > expected &&
+git count-objects > current &&
+diff expected current'
+
+cd "$base_dir"
+
+test_done
index 4eee2e9fa6bacdc0d130a692f727885c5fa42e49..64aa7e2f104eba5f9f844c40d520163a8463cc8f 100755 (executable)
@@ -31,7 +31,7 @@ test_expect_success \
        echo "zzz" > bar/zzz &&
        echo "#!/bin/sh" > exec.sh &&
        chmod +x exec.sh &&
-       svn import -m "import for git svn" . "$svnrepo" >/dev/null &&
+       svn_cmd import -m "import for git svn" . "$svnrepo" >/dev/null &&
        cd .. &&
        rm -rf import &&
        git svn init "$svnrepo"'
@@ -51,7 +51,7 @@ test_expect_success "$name" '
        git commit -m "$name" &&
        git svn set-tree --find-copies-harder --rmdir \
                ${remotes_git_svn}..mybranch &&
-       svn up "$SVN_TREE" &&
+       svn_cmd up "$SVN_TREE" &&
        test -d "$SVN_TREE"/dir && test ! -d "$SVN_TREE"/dir/a'
 
 
@@ -118,7 +118,7 @@ test_expect_success "$name" '
        git commit -m "$name" &&
        git svn set-tree --find-copies-harder --rmdir \
                ${remotes_git_svn}..mybranch5 &&
-       svn up "$SVN_TREE" &&
+       svn_cmd up "$SVN_TREE" &&
        test ! -x "$SVN_TREE"/exec.sh'
 
 
@@ -129,7 +129,7 @@ test_expect_success "$name" '
        git commit -m "$name" &&
        git svn set-tree --find-copies-harder --rmdir \
                ${remotes_git_svn}..mybranch5 &&
-       svn up "$SVN_TREE" &&
+       svn_cmd up "$SVN_TREE" &&
        test -x "$SVN_TREE"/exec.sh'
 
 
@@ -141,7 +141,7 @@ test_expect_success "$name" '
        git commit -m "$name" &&
        git svn set-tree --find-copies-harder --rmdir \
                ${remotes_git_svn}..mybranch5 &&
-       svn up "$SVN_TREE" &&
+       svn_cmd up "$SVN_TREE" &&
        test -L "$SVN_TREE"/exec.sh'
 
 name='new symlink is added to a file that was also just made executable'
@@ -153,7 +153,7 @@ test_expect_success "$name" '
        git commit -m "$name" &&
        git svn set-tree --find-copies-harder --rmdir \
                ${remotes_git_svn}..mybranch5 &&
-       svn up "$SVN_TREE" &&
+       svn_cmd up "$SVN_TREE" &&
        test -x "$SVN_TREE"/bar/zzz &&
        test -L "$SVN_TREE"/exec-2.sh'
 
@@ -166,7 +166,7 @@ test_expect_success "$name" '
        git commit -m "$name" &&
        git svn set-tree --find-copies-harder --rmdir \
                ${remotes_git_svn}..mybranch5 &&
-       svn up "$SVN_TREE" &&
+       svn_cmd up "$SVN_TREE" &&
        test -f "$SVN_TREE"/exec-2.sh &&
        test ! -L "$SVN_TREE"/exec-2.sh &&
        test_cmp help "$SVN_TREE"/exec-2.sh'
index 1e31d6ea7253ee4216347fd707d1408f97af32fa..9da4178c94f4bde62f69f32701b16ab3d04524e0 100755 (executable)
@@ -48,7 +48,7 @@ EOF
        printf "\r\n" > empty_crlf
        a_empty_crlf=`git hash-object -w empty_crlf`
 
-       svn import --no-auto-props -m 'import for git svn' . "$svnrepo" >/dev/null
+       svn_cmd import --no-auto-props -m 'import for git svn' . "$svnrepo" >/dev/null
 cd ..
 
 rm -rf import
@@ -57,13 +57,13 @@ test_expect_success 'setup some commits to svn' \
        'cd test_wc &&
                echo Greetings >> kw.c &&
                poke kw.c &&
-               svn commit -m "Not yet an Id" &&
+               svn_cmd commit -m "Not yet an Id" &&
                echo Hello world >> kw.c &&
                poke kw.c &&
-               svn commit -m "Modified file, but still not yet an Id" &&
-               svn propset svn:keywords Id kw.c &&
+               svn_cmd commit -m "Modified file, but still not yet an Id" &&
+               svn_cmd propset svn:keywords Id kw.c &&
                poke kw.c &&
-               svn commit -m "Propset Id" &&
+               svn_cmd commit -m "Propset Id" &&
        cd ..'
 
 test_expect_success 'initialize git svn' 'git svn init "$svnrepo"'
@@ -83,16 +83,16 @@ test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'"
 
 test_expect_success "propset CR on crlf files" \
        'cd test_wc &&
-               svn propset svn:eol-style CR empty &&
-               svn propset svn:eol-style CR crlf &&
-               svn propset svn:eol-style CR ne_crlf &&
-               svn commit -m "propset CR on crlf files" &&
+               svn_cmd propset svn:eol-style CR empty &&
+               svn_cmd propset svn:eol-style CR crlf &&
+               svn_cmd propset svn:eol-style CR ne_crlf &&
+               svn_cmd commit -m "propset CR on crlf files" &&
         cd ..'
 
 test_expect_success 'fetch and pull latest from svn and checkout a new wc' \
        'git svn fetch &&
         git pull . ${remotes_git_svn} &&
-        svn co "$svnrepo" new_wc'
+        svn_cmd co "$svnrepo" new_wc'
 
 for i in crlf ne_crlf lf ne_lf cr ne_cr empty_cr empty_lf empty empty_crlf
 do
@@ -106,11 +106,11 @@ cd test_wc
        a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git hash-object --stdin`
        a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git hash-object --stdin`
        test_expect_success 'Set CRLF on cr files' \
-       'svn propset svn:eol-style CRLF cr &&
-        svn propset svn:eol-style CRLF ne_cr &&
-        svn propset svn:keywords Id cr &&
-        svn propset svn:keywords Id ne_cr &&
-        svn commit -m "propset CRLF on cr files"'
+       'svn_cmd propset svn:eol-style CRLF cr &&
+        svn_cmd propset svn:eol-style CRLF ne_cr &&
+        svn_cmd propset svn:keywords Id cr &&
+        svn_cmd propset svn:keywords Id ne_cr &&
+        svn_cmd commit -m "propset CRLF on cr files"'
 cd ..
 test_expect_success 'fetch and pull latest from svn' \
        'git svn fetch && git pull . ${remotes_git_svn}'
@@ -140,10 +140,10 @@ test_expect_success 'test show-ignore' "
        cd test_wc &&
        mkdir -p deeply/nested/directory &&
        touch deeply/nested/directory/.keep &&
-       svn add deeply &&
-       svn up &&
-       svn propset -R svn:ignore 'no-such-file*' .
-       svn commit -m 'propset svn:ignore'
+       svn_cmd add deeply &&
+       svn_cmd up &&
+       svn_cmd propset -R svn:ignore 'no-such-file*' .
+       svn_cmd commit -m 'propset svn:ignore'
        cd .. &&
        git svn show-ignore > show-ignore.got &&
        cmp show-ignore.expect show-ignore.got
index e2232180158cfb0e523c8ffdd3ac10bf61c8f4ee..028fb19e09bbb9e2720e95a5e0b4ddb221f4a0e1 100755 (executable)
@@ -9,7 +9,7 @@ test_expect_success 'initialize repo' '
        mkdir -p deeply/nested/directory/number/2 &&
        echo foo > deeply/nested/directory/number/1/file &&
        echo foo > deeply/nested/directory/number/2/another &&
-       svn import -m "import for git svn" . "$svnrepo" &&
+       svn_cmd import -m "import for git svn" . "$svnrepo" &&
        cd ..
        '
 
@@ -23,7 +23,7 @@ test_expect_success 'Try a commit on rmdir' '
        git rm -f deeply/nested/directory/number/2/another &&
        git commit -a -m "remove another" &&
        git svn set-tree --rmdir HEAD &&
-       svn ls -R "$svnrepo" | grep ^deeply/nested/directory/number/1
+       svn_cmd ls -R "$svnrepo" | grep ^deeply/nested/directory/number/1
        '
 
 
index 963dd95e4a71ccefa64b9500c490f44ea6d7c789..3413164cb127da9e8d601775769b3b049816173e 100755 (executable)
@@ -10,15 +10,15 @@ test_expect_success 'make history for tracking' '
        mkdir import &&
        mkdir import/trunk &&
        echo hello >> import/trunk/README &&
-       svn import -m initial import "$svnrepo" &&
+       svn_cmd import -m initial import "$svnrepo" &&
        rm -rf import &&
-       svn co "$svnrepo"/trunk trunk &&
+       svn_cmd co "$svnrepo"/trunk trunk &&
        echo bye bye >> trunk/README &&
-       svn rm -m "gone" "$svnrepo"/trunk &&
+       svn_cmd rm -m "gone" "$svnrepo"/trunk &&
        rm -rf trunk &&
        mkdir trunk &&
        echo "new" > trunk/FOLLOWME &&
-       svn import -m "new trunk" trunk "$svnrepo"/trunk
+       svn_cmd import -m "new trunk" trunk "$svnrepo"/trunk
 '
 
 test_expect_success 'clone repo with git' '
index ab9fa322200b333dd0222be6b712c6651f4419fb..78610b61e63596dad7e86a19a7e39deda3b19222 100755 (executable)
@@ -11,18 +11,18 @@ test_expect_success 'initialize repo' '
        cd import &&
        mkdir -p trunk &&
        echo hello > trunk/readme &&
-       svn import -m "initial" . "$svnrepo" &&
+       svn_cmd import -m "initial" . "$svnrepo" &&
        cd .. &&
-       svn co "$svnrepo" wc &&
+       svn_cmd co "$svnrepo" wc &&
        cd wc &&
        echo world >> trunk/readme &&
        poke trunk/readme &&
-       svn commit -m "another commit" &&
-       svn up &&
-       svn mv trunk thunk &&
+       svn_cmd commit -m "another commit" &&
+       svn_cmd up &&
+       svn_cmd mv trunk thunk &&
        echo goodbye >> thunk/readme &&
        poke thunk/readme &&
-       svn commit -m "bye now" &&
+       svn_cmd commit -m "bye now" &&
        cd ..
        '
 
@@ -51,7 +51,7 @@ test_expect_success 'init and fetch from one svn-remote' '
         '
 
 test_expect_success 'follow deleted parent' '
-        (svn cp -m "resurrecting trunk as junk" \
+        (svn_cmd cp -m "resurrecting trunk as junk" \
                "$svnrepo"/trunk@2 "$svnrepo"/junk ||
          svn cp -m "resurrecting trunk as junk" \
                -r2 "$svnrepo"/trunk "$svnrepo"/junk) &&
@@ -97,8 +97,8 @@ test_expect_success 'follow higher-level parent' '
         '
 
 test_expect_success 'follow deleted directory' '
-       svn mv -m "bye!" "$svnrepo"/glob/blob/hi "$svnrepo"/glob/blob/bye &&
-       svn rm -m "remove glob" "$svnrepo"/glob &&
+       svn_cmd mv -m "bye!" "$svnrepo"/glob/blob/hi "$svnrepo"/glob/blob/bye &&
+       svn_cmd rm -m "remove glob" "$svnrepo"/glob &&
        git svn init --minimize-url -i glob "$svnrepo"/glob &&
        git svn fetch -i glob &&
        test "`git cat-file blob refs/remotes/glob:blob/bye`" = hi &&
@@ -120,7 +120,7 @@ test_expect_success 'follow-parent avoids deleting relevant info' '
        cd import &&
          svn import -m "r9270 test" . "$svnrepo"/r9270 &&
        cd .. &&
-       svn co "$svnrepo"/r9270/trunk/subversion/bindings/swig/perl r9270 &&
+       svn_cmd co "$svnrepo"/r9270/trunk/subversion/bindings/swig/perl r9270 &&
        cd r9270 &&
          svn mkdir native &&
          svn mv t native/t &&
@@ -138,7 +138,7 @@ test_expect_success 'follow-parent avoids deleting relevant info' '
        '
 
 test_expect_success "track initial change if it was only made to parent" '
-       svn cp -m "wheee!" "$svnrepo"/r9270/trunk "$svnrepo"/r9270/drunk &&
+       svn_cmd cp -m "wheee!" "$svnrepo"/r9270/trunk "$svnrepo"/r9270/drunk &&
        git svn init --minimize-url -i r9270-d \
          "$svnrepo"/r9270/drunk/subversion/bindings/swig/perl/native/t &&
        git svn fetch -i r9270-d &&
@@ -152,20 +152,20 @@ test_expect_success "track initial change if it was only made to parent" '
 test_expect_success "follow-parent is atomic" '
        (
                cd wc &&
-               svn up &&
-               svn mkdir stunk &&
+               svn_cmd up &&
+               svn_cmd mkdir stunk &&
                echo "trunk stunk" > stunk/readme &&
-               svn add stunk/readme &&
-               svn ci -m "trunk stunk" &&
+               svn_cmd add stunk/readme &&
+               svn_cmd ci -m "trunk stunk" &&
                echo "stunk like junk" >> stunk/readme &&
-               svn ci -m "really stunk" &&
+               svn_cmd ci -m "really stunk" &&
                echo "stink stank stunk" >> stunk/readme &&
-               svn ci -m "even the grinch agrees"
+               svn_cmd ci -m "even the grinch agrees"
        ) &&
-       svn copy -m "stunk flunked" "$svnrepo"/stunk "$svnrepo"/flunk &&
+       svn_cmd copy -m "stunk flunked" "$svnrepo"/stunk "$svnrepo"/flunk &&
        { svn cp -m "early stunk flunked too" \
                "$svnrepo"/stunk@17 "$svnrepo"/flunked ||
-       svn cp -m "early stunk flunked too" \
+       svn_cmd cp -m "early stunk flunked too" \
                -r17 "$svnrepo"/stunk "$svnrepo"/flunked; } &&
        git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
        git svn fetch -i stunk &&
@@ -192,7 +192,7 @@ test_expect_success "follow-parent is atomic" '
        '
 
 test_expect_success "track multi-parent paths" '
-       svn cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob &&
+       svn_cmd cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob &&
        git svn multi-fetch &&
        test `git cat-file commit refs/remotes/glob | \
               grep "^parent " | wc -l` -eq 2
index ba99abb6d975351cf2725e757a588a26109a9723..dd48e9cba832a06a34fd1e2c895bb1b19792168f 100755 (executable)
@@ -8,7 +8,7 @@ test_expect_success 'initialize repo' '
        mkdir import &&
        cd import &&
        echo hello > readme &&
-       svn import -m "initial" . "$svnrepo" &&
+       svn_cmd import -m "initial" . "$svnrepo" &&
        cd .. &&
        echo hello > readme &&
        git update-index --add readme &&
@@ -27,16 +27,16 @@ prev=`git rev-parse --verify HEAD^1`
 test_expect_success 'test the commit-diff command' '
        test -n "$prev" && test -n "$head" &&
        git svn commit-diff -r1 "$prev" "$head" "$svnrepo" &&
-       svn co "$svnrepo" wc &&
+       svn_cmd co "$svnrepo" wc &&
        cmp readme wc/readme
        '
 
 test_expect_success 'commit-diff to a sub-directory (with git svn config)' '
-       svn import -m "sub-directory" import "$svnrepo"/subdir &&
+       svn_cmd import -m "sub-directory" import "$svnrepo"/subdir &&
        git svn init --minimize-url "$svnrepo"/subdir &&
        git svn fetch &&
        git svn commit-diff -r3 "$prev" "$head" &&
-       svn cat "$svnrepo"/subdir/readme > readme.2 &&
+       svn_cmd cat "$svnrepo"/subdir/readme > readme.2 &&
        cmp readme readme.2
        '
 
index 6eb0fd85c86ec194062af7da8c7002f0819bcc07..12f21b700ec5216b6aeaa886f862d3e3b1f6682f 100755 (executable)
@@ -8,18 +8,18 @@ test_expect_success 'initialize repo' '
        mkdir import &&
        cd import &&
        echo initial > file &&
-       svn import -m "initial" . "$svnrepo" &&
+       svn_cmd import -m "initial" . "$svnrepo" &&
        cd .. &&
        echo initial > file &&
        git update-index --add file &&
        git commit -a -m "initial"
        '
 test_expect_success 'commit change from svn side' '
-       svn co "$svnrepo" t.svn &&
+       svn_cmd co "$svnrepo" t.svn &&
        cd t.svn &&
        echo second line from svn >> file &&
        poke file &&
-       svn commit -m "second line from svn" &&
+       svn_cmd commit -m "second line from svn" &&
        cd .. &&
        rm -rf t.svn
        '
@@ -43,11 +43,11 @@ test_expect_success 'dcommit fails to commit because of conflict' '
        git svn init "$svnrepo" &&
        git svn fetch &&
        git reset --hard refs/${remotes_git_svn} &&
-       svn co "$svnrepo" t.svn &&
+       svn_cmd co "$svnrepo" t.svn &&
        cd t.svn &&
        echo fourth line from svn >> file &&
        poke file &&
-       svn commit -m "fourth line from svn" &&
+       svn_cmd commit -m "fourth line from svn" &&
        cd .. &&
        rm -rf t.svn &&
        echo "fourth line from git" >> file &&
@@ -67,11 +67,11 @@ test_expect_success 'dcommit does the svn equivalent of an index merge' "
        "
 
 test_expect_success 'commit another change from svn side' '
-       svn co "$svnrepo" t.svn &&
+       svn_cmd co "$svnrepo" t.svn &&
        cd t.svn &&
                echo third line from svn >> file &&
                poke file &&
-               svn commit -m "third line from svn" &&
+               svn_cmd commit -m "third line from svn" &&
        cd .. &&
        rm -rf t.svn
        '
index acad16a6f0f9b3b45b4766474e15ee5019ec2ce2..3a9e07768d8e6bebd7a4c4156ace6c5746d7d440 100755 (executable)
@@ -12,7 +12,7 @@ test_expect_success 'setup old-looking metadata' '
                        mkdir -p $i && \
                        echo hello >> $i/README || exit 1
                done && \
-               svn import -m test . "$svnrepo"
+               svn_cmd import -m test . "$svnrepo"
                cd .. &&
        git svn init "$svnrepo" &&
        git svn fetch &&
index d8582b1aa5d178778623bfb4386a66f58e165c17..d732d3130299e964359784949fc97805a2888e39 100755 (executable)
@@ -14,30 +14,30 @@ test_expect_success 'test refspec globbing' '
        mkdir -p trunk/src/a trunk/src/b trunk/doc &&
        echo "hello world" > trunk/src/a/readme &&
        echo "goodbye world" > trunk/src/b/readme &&
-       svn import -m "initial" trunk "$svnrepo"/trunk &&
-       svn co "$svnrepo" tmp &&
+       svn_cmd import -m "initial" trunk "$svnrepo"/trunk &&
+       svn_cmd co "$svnrepo" tmp &&
        (
                cd tmp &&
                mkdir branches tags &&
-               svn add branches tags &&
-               svn cp trunk branches/start &&
-               svn commit -m "start a new branch" &&
-               svn up &&
+               svn_cmd add branches tags &&
+               svn_cmd cp trunk branches/start &&
+               svn_cmd commit -m "start a new branch" &&
+               svn_cmd up &&
                echo "hi" >> branches/start/src/b/readme &&
                poke branches/start/src/b/readme &&
                echo "hey" >> branches/start/src/a/readme &&
                poke branches/start/src/a/readme &&
-               svn commit -m "hi" &&
-               svn up &&
-               svn cp branches/start tags/end &&
+               svn_cmd commit -m "hi" &&
+               svn_cmd up &&
+               svn_cmd cp branches/start tags/end &&
                echo "bye" >> tags/end/src/b/readme &&
                poke tags/end/src/b/readme &&
                echo "aye" >> tags/end/src/a/readme &&
                poke tags/end/src/a/readme &&
-               svn commit -m "the end" &&
+               svn_cmd commit -m "the end" &&
                echo "byebye" >> tags/end/src/b/readme &&
                poke tags/end/src/b/readme &&
-               svn commit -m "nothing to see here"
+               svn_cmd commit -m "nothing to see here"
        ) &&
        git config --add svn-remote.svn.url "$svnrepo" &&
        git config --add svn-remote.svn.fetch \
@@ -72,7 +72,7 @@ test_expect_success 'test left-hand-side only globbing' '
                cd tmp &&
                echo "try try" >> tags/end/src/b/readme &&
                poke tags/end/src/b/readme &&
-               svn commit -m "try to try"
+               svn_cmd commit -m "try to try"
        ) &&
        git svn fetch two &&
        test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
@@ -102,7 +102,7 @@ test_expect_success 'test disallow multi-globs' '
                cd tmp &&
                echo "try try" >> tags/end/src/b/readme &&
                poke tags/end/src/b/readme &&
-               svn commit -m "try to try"
+               svn_cmd commit -m "try to try"
        ) &&
        test_must_fail git svn fetch three 2> stderr.three &&
        test_cmp expect.three stderr.three
index 8f79c3f251aed240e0ba59244a8cfd91db2369d2..c318f9f946a35f0d13b90f67dd00a6817d77d989 100755 (executable)
@@ -14,30 +14,30 @@ test_expect_success 'test refspec globbing' '
        mkdir -p trunk/src/a trunk/src/b trunk/doc &&
        echo "hello world" > trunk/src/a/readme &&
        echo "goodbye world" > trunk/src/b/readme &&
-       svn import -m "initial" trunk "$svnrepo"/trunk &&
-       svn co "$svnrepo" tmp &&
+       svn_cmd import -m "initial" trunk "$svnrepo"/trunk &&
+       svn_cmd co "$svnrepo" tmp &&
        (
                cd tmp &&
                mkdir branches branches/v1 tags &&
-               svn add branches tags &&
-               svn cp trunk branches/v1/start &&
-               svn commit -m "start a new branch" &&
-               svn up &&
+               svn_cmd add branches tags &&
+               svn_cmd cp trunk branches/v1/start &&
+               svn_cmd commit -m "start a new branch" &&
+               svn_cmd up &&
                echo "hi" >> branches/v1/start/src/b/readme &&
                poke branches/v1/start/src/b/readme &&
                echo "hey" >> branches/v1/start/src/a/readme &&
                poke branches/v1/start/src/a/readme &&
-               svn commit -m "hi" &&
-               svn up &&
-               svn cp branches/v1/start tags/end &&
+               svn_cmd commit -m "hi" &&
+               svn_cmd up &&
+               svn_cmd cp branches/v1/start tags/end &&
                echo "bye" >> tags/end/src/b/readme &&
                poke tags/end/src/b/readme &&
                echo "aye" >> tags/end/src/a/readme &&
                poke tags/end/src/a/readme &&
-               svn commit -m "the end" &&
+               svn_cmd commit -m "the end" &&
                echo "byebye" >> tags/end/src/b/readme &&
                poke tags/end/src/b/readme &&
-               svn commit -m "nothing to see here"
+               svn_cmd commit -m "nothing to see here"
        ) &&
        git config --add svn-remote.svn.url "$svnrepo" &&
        git config --add svn-remote.svn.fetch \
@@ -72,7 +72,7 @@ test_expect_success 'test left-hand-side only globbing' '
                cd tmp &&
                echo "try try" >> tags/end/src/b/readme &&
                poke tags/end/src/b/readme &&
-               svn commit -m "try to try"
+               svn_cmd commit -m "try to try"
        ) &&
        git svn fetch two &&
        test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
@@ -97,25 +97,25 @@ test_expect_success 'test another branch' '
        (
                cd tmp &&
                mkdir branches/v2 &&
-               svn add branches/v2 &&
-               svn cp trunk branches/v2/start &&
-               svn commit -m "Another versioned branch" &&
-               svn up &&
+               svn_cmd add branches/v2 &&
+               svn_cmd cp trunk branches/v2/start &&
+               svn_cmd commit -m "Another versioned branch" &&
+               svn_cmd up &&
                echo "hello" >> branches/v2/start/src/b/readme &&
                poke branches/v2/start/src/b/readme &&
                echo "howdy" >> branches/v2/start/src/a/readme &&
                poke branches/v2/start/src/a/readme &&
-               svn commit -m "Changed 2 in v2/start" &&
-               svn up &&
-               svn cp branches/v2/start tags/next &&
+               svn_cmd commit -m "Changed 2 in v2/start" &&
+               svn_cmd up &&
+               svn_cmd cp branches/v2/start tags/next &&
                echo "bye" >> tags/next/src/b/readme &&
                poke tags/next/src/b/readme &&
                echo "aye" >> tags/next/src/a/readme &&
                poke tags/next/src/a/readme &&
-               svn commit -m "adding more" &&
+               svn_cmd commit -m "adding more" &&
                echo "byebye" >> tags/next/src/b/readme &&
                poke tags/next/src/b/readme &&
-               svn commit -m "adios"
+               svn_cmd commit -m "adios"
        ) &&
        git config --add svn-remote.four.url "$svnrepo" &&
        git config --add svn-remote.four.fetch trunk:refs/remotes/four/trunk &&
@@ -151,7 +151,7 @@ test_expect_success 'test disallow multiple globs' '
                cd tmp &&
                echo "try try" >> tags/end/src/b/readme &&
                poke tags/end/src/b/readme &&
-               svn commit -m "try to try"
+               svn_cmd commit -m "try to try"
        ) &&
        test_must_fail git svn fetch three 2> stderr.three &&
        test_cmp expect.three stderr.three
index e9b6128b3fa5c3d0cbbe5abb7f3e55267263449d..e8479cec7abade29aec91b22bba69d4ab9804f21 100755 (executable)
@@ -15,7 +15,7 @@ test_description='git svn dcommit new files over svn:// test'
 require_svnserve
 
 test_expect_success 'start tracking an empty repo' '
-       svn mkdir -m "empty dir" "$svnrepo"/empty-dir &&
+       svn_cmd mkdir -m "empty dir" "$svnrepo"/empty-dir &&
        echo "[general]" > "$rawsvnrepo"/conf/svnserve.conf &&
        echo anon-access = write >> "$rawsvnrepo"/conf/svnserve.conf &&
        start_svnserve &&
index 17b2855c4f308d463ea239f355549120dab4f80f..84f7c9b4bb00931b57740be32ce7ee29bbb26694 100755 (executable)
@@ -35,12 +35,12 @@ EOF
 }
 
 test_expect_success 'setup svn repository' '
-       svn co "$svnrepo" mysvnwork &&
+       svn_cmd co "$svnrepo" mysvnwork &&
        mkdir -p mysvnwork/trunk &&
        cd mysvnwork &&
                big_text_block >> trunk/README &&
-               svn add trunk &&
-               svn ci -m "first commit" trunk &&
+               svn_cmd add trunk &&
+               svn_cmd ci -m "first commit" trunk &&
                cd ..
        '
 
index fd6d1d20463f2a4de1bd8ed739c0e977921e037c..0374a7476bcc5b254aa1464d468434ae3205f114 100755 (executable)
@@ -14,7 +14,7 @@ test_expect_success 'setup repository and import' '
                        mkdir -p $i && \
                        echo hello >> $i/README || exit 1
                done && \
-               svn import -m test . "$svnrepo"
+               svn_cmd import -m test . "$svnrepo"
                cd .. &&
        git svn init "$svnrepo" -T trunk -b branches -t tags &&
        git svn fetch &&
index dde46cd92fba24221393b15233ed248997161caf..b7ef9e25895550e8749952e2ed54d7827737242e 100755 (executable)
@@ -16,7 +16,7 @@ cd tmp
 test_expect_success 'setup svnrepo' '
        mkdir project project/trunk project/branches project/tags &&
        echo foo > project/trunk/foo &&
-       svn import -m "$test_description" project "$svnrepo"/project &&
+       svn_cmd import -m "$test_description" project "$svnrepo"/project &&
        rm -rf project
        '
 
index 7a7c12868758d6e3bd9d1f8ec4fe32c0663115f4..ac52bff0ef540bce48e4ee02a53adbbec3662939 100755 (executable)
@@ -13,13 +13,13 @@ scary_ref='Abo-Uebernahme%20(Bug%20#994)'
 test_expect_success 'setup svnrepo' '
        mkdir project project/trunk project/branches project/tags &&
        echo foo > project/trunk/foo &&
-       svn import -m "$test_description" project "$svnrepo/pr ject" &&
+       svn_cmd import -m "$test_description" project "$svnrepo/pr ject" &&
        rm -rf project &&
-       svn cp -m "fun" "$svnrepo/pr ject/trunk" \
+       svn_cmd cp -m "fun" "$svnrepo/pr ject/trunk" \
                        "$svnrepo/pr ject/branches/fun plugin" &&
-       svn cp -m "more fun!" "$svnrepo/pr ject/branches/fun plugin" \
+       svn_cmd cp -m "more fun!" "$svnrepo/pr ject/branches/fun plugin" \
                              "$svnrepo/pr ject/branches/more fun plugin!" &&
-       svn cp -m "scary" "$svnrepo/pr ject/branches/fun plugin" \
+       svn_cmd cp -m "scary" "$svnrepo/pr ject/branches/fun plugin" \
                      "$svnrepo/pr ject/branches/$scary_uri" &&
        start_httpd
        '
index 27dd7c273a4a1ae77a8e48b2e4b4ce1a3ae19a56..95741cbbac6bf2e59531bbe1f9527ce4596fa904 100755 (executable)
@@ -7,7 +7,7 @@ test_description='git svn info'
 . ./lib-git-svn.sh
 
 # Tested with: svn, version 1.4.4 (r25188)
-v=`svn --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p'`
+v=`svn_cmd --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p'`
 case $v in
 1.[45].*)
        ;;
@@ -31,7 +31,7 @@ ptouch() {
                        my $atime = $mtime;
                        utime $atime, $mtime, $git_file;
                }
-       ' "`svn info $2 | grep '^Text Last Updated:'`" "$1"
+       ' "`svn_cmd info $2 | grep '^Text Last Updated:'`" "$1"
 }
 
 quoted_svnrepo="$(echo $svnrepo | sed 's/ /%20/')"
@@ -45,14 +45,14 @@ test_expect_success 'setup repository and import' '
                mkdir directory &&
                touch directory/.placeholder &&
                ln -s directory symlink-directory &&
-               svn import -m "initial" . "$svnrepo" &&
+               svn_cmd import -m "initial" . "$svnrepo" &&
        cd .. &&
-       svn co "$svnrepo" svnwc &&
+       svn_cmd co "$svnrepo" svnwc &&
        cd svnwc &&
                echo foo > foo &&
-               svn add foo &&
-               svn commit -m "change outside directory" &&
-               svn update &&
+               svn_cmd add foo &&
+               svn_cmd commit -m "change outside directory" &&
+               svn_cmd update &&
        cd .. &&
        mkdir gitwc &&
        cd gitwc &&
@@ -143,7 +143,7 @@ test_expect_success 'info added-file' "
        cp gitwc/added-file svnwc/added-file &&
        ptouch gitwc/added-file svnwc/added-file &&
        cd svnwc &&
-               svn add added-file > /dev/null &&
+               svn_cmd add added-file > /dev/null &&
        cd .. &&
        (cd svnwc; svn info added-file) > expected.info-added-file &&
        (cd gitwc; git svn info added-file) > actual.info-added-file &&
@@ -160,7 +160,7 @@ test_expect_success 'info added-directory' "
        ptouch gitwc/added-directory svnwc/added-directory &&
        touch gitwc/added-directory/.placeholder &&
        cd svnwc &&
-               svn add added-directory > /dev/null &&
+               svn_cmd add added-directory > /dev/null &&
        cd .. &&
        cd gitwc &&
                git add added-directory &&
@@ -184,7 +184,7 @@ test_expect_success 'info added-symlink-file' "
        cd .. &&
        cd svnwc &&
                ln -s added-file added-symlink-file &&
-               svn add added-symlink-file > /dev/null &&
+               svn_cmd add added-symlink-file > /dev/null &&
        cd .. &&
        ptouch gitwc/added-symlink-file svnwc/added-symlink-file &&
        (cd svnwc; svn info added-symlink-file) \
@@ -207,7 +207,7 @@ test_expect_success 'info added-symlink-directory' "
        cd .. &&
        cd svnwc &&
                ln -s added-directory added-symlink-directory &&
-               svn add added-symlink-directory > /dev/null &&
+               svn_cmd add added-symlink-directory > /dev/null &&
        cd .. &&
        ptouch gitwc/added-symlink-directory svnwc/added-symlink-directory &&
        (cd svnwc; svn info added-symlink-directory) \
@@ -233,7 +233,7 @@ test_expect_success 'info deleted-file' "
                git rm -f file > /dev/null &&
        cd .. &&
        cd svnwc &&
-               svn rm --force file > /dev/null &&
+               svn_cmd rm --force file > /dev/null &&
        cd .. &&
        (cd svnwc; svn info file) |
        sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
@@ -254,7 +254,7 @@ test_expect_success 'info deleted-directory' "
                git rm -r -f directory > /dev/null &&
        cd .. &&
        cd svnwc &&
-               svn rm --force directory > /dev/null &&
+               svn_cmd rm --force directory > /dev/null &&
        cd .. &&
        (cd svnwc; svn info directory) |
        sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
@@ -275,7 +275,7 @@ test_expect_success 'info deleted-symlink-file' "
                git rm -f symlink-file > /dev/null &&
        cd .. &&
        cd svnwc &&
-               svn rm --force symlink-file > /dev/null &&
+               svn_cmd rm --force symlink-file > /dev/null &&
        cd .. &&
        (cd svnwc; svn info symlink-file) |
        sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
@@ -297,7 +297,7 @@ test_expect_success 'info deleted-symlink-directory' "
                git rm -f symlink-directory > /dev/null &&
        cd .. &&
        cd svnwc &&
-               svn rm --force symlink-directory > /dev/null &&
+               svn_cmd rm --force symlink-directory > /dev/null &&
        cd .. &&
        (cd svnwc; svn info symlink-directory) |
        sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
index ef2c0523cd4566b3d1c4925ba608efc16524546a..555a0189a7bd6412829da88a3e615208117eaa90 100755 (executable)
@@ -9,7 +9,7 @@ test_description='git svn clone with percent escapes'
 test_expect_success 'setup svnrepo' '
        mkdir project project/trunk project/branches project/tags &&
        echo foo > project/trunk/foo &&
-       svn import -m "$test_description" project "$svnrepo/pr ject" &&
+       svn_cmd import -m "$test_description" project "$svnrepo/pr ject" &&
        rm -rf project &&
        start_httpd
 '
index 1b1cf47281d10c64ac57e96701c727f19f189948..30013b7bb948640869d5c5208b2feeb08c011b73 100755 (executable)
@@ -4,12 +4,12 @@ test_description='git svn authorship'
 . ./lib-git-svn.sh
 
 test_expect_success 'setup svn repository' '
-       svn checkout "$svnrepo" work.svn &&
+       svn_cmd checkout "$svnrepo" work.svn &&
        (
                cd work.svn &&
                echo >file
-               svn add file
-               svn commit -m "first commit" file
+               svn_cmd add file
+               svn_cmd commit -m "first commit" file
        )
 '
 
@@ -74,10 +74,10 @@ test_expect_success 'interact with it via git svn' '
        # Make sure there are no svn commit messages with excess blank lines
        (
                cd work.svn &&
-               svn up &&
+               svn_cmd up &&
                
-               test $(svn log -r2:2 | wc -l) = 5 &&
-               test $(svn log -r4:4 | wc -l) = 7
+               test $(svn_cmd log -r2:2 | wc -l) = 5 &&
+               test $(svn_cmd log -r4:4 | wc -l) = 7
        )
 '
 
index cf0415274c2d2abae7a6850818f4de8063cb61a7..045521615c64d1ae938524b0424e1e4260ca8c54 100755 (executable)
@@ -10,7 +10,7 @@ test_description='git svn respects rewriteRoot during rebuild'
 mkdir import
 cd import
        touch foo
-       svn import -m 'import for git svn' . "$svnrepo" >/dev/null
+       svn_cmd import -m 'import for git svn' . "$svnrepo" >/dev/null
 cd ..
 rm -rf import
 
index 263dbf5fc276ffa052096810f59565a851245b7f..d6b076f6b7de148c8d548c7a977e4f09b4be8e3b 100755 (executable)
@@ -21,7 +21,7 @@ test_expect_success 'initialize git svn' '
        (
                cd import &&
                echo foo >foo &&
-               svn import -m "import for git svn" . "$svnrepo"
+               svn_cmd import -m "import for git svn" . "$svnrepo"
        ) &&
        rm -rf import &&
        git svn init "$svnrepo"
@@ -61,23 +61,23 @@ test_expect_success 'check resulting svn repository' '
 (
        mkdir work &&
        cd work &&
-       svn co "$svnrepo" &&
+       svn_cmd co "$svnrepo" &&
        cd svnrepo &&
 
        # Check properties from first commit.
-       test "x$(svn propget svn:executable exec1.sh)" = "x*" &&
-       test "x$(svn propget svn:mime-type exec1.sh)" = \
+       test "x$(svn_cmd propget svn:executable exec1.sh)" = "x*" &&
+       test "x$(svn_cmd propget svn:mime-type exec1.sh)" = \
             "xapplication/x-shellscript" &&
-       test "x$(svn propget svn:mime-type hello.txt)" = "xtext/plain" &&
-       test "x$(svn propget svn:eol-style hello.txt)" = "xnative" &&
-       test "x$(svn propget svn:mime-type bar)" = "x" &&
+       test "x$(svn_cmd propget svn:mime-type hello.txt)" = "xtext/plain" &&
+       test "x$(svn_cmd propget svn:eol-style hello.txt)" = "xnative" &&
+       test "x$(svn_cmd propget svn:mime-type bar)" = "x" &&
 
        # Check properties from second commit.
-       test "x$(svn propget svn:executable exec2.sh)" = "x*" &&
-       test "x$(svn propget svn:mime-type exec2.sh)" = "x" &&
-       test "x$(svn propget svn:mime-type world.txt)" = "x" &&
-       test "x$(svn propget svn:eol-style world.txt)" = "x" &&
-       test "x$(svn propget svn:mime-type zot)" = "x"
+       test "x$(svn_cmd propget svn:executable exec2.sh)" = "x*" &&
+       test "x$(svn_cmd propget svn:mime-type exec2.sh)" = "x" &&
+       test "x$(svn_cmd propget svn:mime-type world.txt)" = "x" &&
+       test "x$(svn_cmd propget svn:eol-style world.txt)" = "x" &&
+       test "x$(svn_cmd propget svn:mime-type zot)" = "x"
 )
 '
 
@@ -89,12 +89,12 @@ test_expect_success 'check renamed file' '
        git svn dcommit --config-dir=user &&
        (
                cd work/svnrepo &&
-               svn up &&
+               svn_cmd up &&
                test ! -e foo &&
                test -e foo.sh &&
-               test "x$(svn propget svn:mime-type foo.sh)" = \
+               test "x$(svn_cmd propget svn:mime-type foo.sh)" = \
                     "xapplication/x-shellscript" &&
-               test "x$(svn propget svn:eol-style foo.sh)" = "xLF"
+               test "x$(svn_cmd propget svn:eol-style foo.sh)" = "xLF"
        )
 '
 
index 475c751c1cb88ce92a18beb2f9c7362a29ae4a5b..c19418614fc8946b5be5f0014559e53fcc15c060 100755 (executable)
@@ -8,11 +8,11 @@ test_expect_success 'setup svnrepo' '
        mkdir project project/trunk project/branches \
                        project/branches/v14.1 project/tags &&
        echo foo > project/trunk/foo &&
-       svn import -m "$test_description" project "$svnrepo/project" &&
+       svn_cmd import -m "$test_description" project "$svnrepo/project" &&
        rm -rf project &&
-       svn cp -m "fun" "$svnrepo/project/trunk" \
+       svn_cmd cp -m "fun" "$svnrepo/project/trunk" \
                        "$svnrepo/project/branches/v14.1/beta" &&
-       svn cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
+       svn_cmd cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
                              "$svnrepo/project/branches/v14.1/gold"
        '
 
index 87696a92dc82fad38e89a97af4a74ede84057241..4aab8ecc142d9719fd83b064445fa297cc10a520 100755 (executable)
@@ -14,21 +14,21 @@ test_expect_success 'initialize svnrepo' '
                cd trunk &&
                echo foo > foo &&
                cd .. &&
-               svn import -m "import for git-svn" . "$svnrepo" >/dev/null &&
-               svn copy "$svnrepo"/trunk "$svnrepo"/branches/a \
+               svn_cmd import -m "import for git-svn" . "$svnrepo" >/dev/null &&
+               svn_cmd copy "$svnrepo"/trunk "$svnrepo"/branches/a \
                        -m "created branch a" &&
                cd .. &&
                rm -rf import &&
-               svn co "$svnrepo"/trunk trunk &&
+               svn_cmd co "$svnrepo"/trunk trunk &&
                cd trunk &&
                echo bar >> foo &&
-               svn ci -m "updated trunk" &&
+               svn_cmd ci -m "updated trunk" &&
                cd .. &&
-               svn co "$svnrepo"/branches/a a &&
+               svn_cmd co "$svnrepo"/branches/a a &&
                cd a &&
                echo baz >> a &&
-               svn add a &&
-               svn ci -m "updated a" &&
+               svn_cmd add a &&
+               svn_cmd ci -m "updated a" &&
                cd .. &&
                git svn init --stdlayout "$svnrepo"
        )
index 252daa7e1aec3c40a31db9a12a9432fbb85ef1b0..807e494a3af4eb889711cbd7bb8d20c160557301 100755 (executable)
@@ -14,13 +14,13 @@ test_expect_success 'initialize svnrepo' '
                cd trunk &&
                echo foo > foo &&
                cd .. &&
-               svn import -m "import for git-svn" . "$svnrepo" >/dev/null &&
+               svn_cmd import -m "import for git-svn" . "$svnrepo" >/dev/null &&
                cd .. &&
                rm -rf import &&
-               svn co "$svnrepo"/trunk trunk &&
+               svn_cmd co "$svnrepo"/trunk trunk &&
                cd trunk &&
                echo bar >> foo &&
-               svn ci -m "updated trunk" &&
+               svn_cmd ci -m "updated trunk" &&
                cd .. &&
                rm -rf trunk
        )
@@ -57,14 +57,14 @@ test_expect_success 'git svn branch tests' '
 '
 
 test_expect_success 'branch uses correct svn-remote' '
-       (svn co "$svnrepo" svn &&
+       (svn_cmd co "$svnrepo" svn &&
        cd svn &&
        mkdir mirror &&
-       svn add mirror &&
-       svn copy trunk mirror/ &&
-       svn copy tags mirror/ &&
-       svn copy branches mirror/ &&
-       svn ci -m "made mirror" ) &&
+       svn_cmd add mirror &&
+       svn_cmd copy trunk mirror/ &&
+       svn_cmd copy tags mirror/ &&
+       svn_cmd copy branches mirror/ &&
+       svn_cmd ci -m "made mirror" ) &&
        rm -rf svn &&
        git svn init -s -R mirror --prefix=mirror/ "$svnrepo"/mirror &&
        git svn fetch -R mirror &&
index 3200ab38efa03076b81b94713e74205d740e38e8..d45fb73016362827e647118eec028c8b85e5aeff 100755 (executable)
@@ -33,7 +33,7 @@ for H in ISO-8859-1 EUCJP ISO-2022-JP
 do
        test_expect_success "$H setup" '
                mkdir $H &&
-               svn import -m "$H test" $H "$svnrepo"/$H &&
+               svn_cmd import -m "$H test" $H "$svnrepo"/$H &&
                git svn clone "$svnrepo"/$H $H
        '
 done
index b8fb277562e7782cf538ba7011214b4cf9136484..f5abdb3c7fd24033f1538db51c957345ab86e341 100755 (executable)
@@ -15,7 +15,7 @@ EOF
 test_expect_success 'setup svnrepo' '
        for i in aa bb cc dd
        do
-               svn mkdir -m $i --username $i "$svnrepo"/$i
+               svn_cmd mkdir -m $i --username $i "$svnrepo"/$i
        done
        '
 
@@ -52,13 +52,13 @@ test_expect_success 'continues to import once authors have been added' '
        '
 
 test_expect_success 'authors-file against globs' '
-       svn mkdir -m globs --username aa \
+       svn_cmd mkdir -m globs --username aa \
          "$svnrepo"/aa/trunk "$svnrepo"/aa/branches "$svnrepo"/aa/tags &&
        git svn clone --authors-file=svn-authors -s "$svnrepo"/aa aa-work &&
        for i in bb ee cc
        do
                branch="aa/branches/$i"
-               svn mkdir -m "$branch" --username $i "$svnrepo/$branch"
+               svn_cmd mkdir -m "$branch" --username $i "$svnrepo/$branch"
        done
        '
 
index 893f57ef7370a5078cce39ef7f4136342451f655..f3c30e63b7f584cddb91793b0170f004d866530d 100755 (executable)
@@ -7,19 +7,19 @@ test_description='git svn property tests'
 . ./lib-git-svn.sh
 
 test_expect_success 'setup repo with a git repo inside it' '
-       svn co "$svnrepo" s &&
+       svn_cmd co "$svnrepo" s &&
        (
                cd s &&
                git init &&
                test -f .git/HEAD &&
                > .git/a &&
                echo a > a &&
-               svn add .git a &&
-               svn commit -m "create a nested git repo" &&
-               svn up &&
+               svn_cmd add .git a &&
+               svn_cmd commit -m "create a nested git repo" &&
+               svn_cmd up &&
                echo hi >> .git/a &&
-               svn commit -m "modify .git/a" &&
-               svn up
+               svn_cmd commit -m "modify .git/a" &&
+               svn_cmd up
        )
 '
 
@@ -33,9 +33,9 @@ test_expect_success 'SVN-side change outside of .git' '
        (
                cd s &&
                echo b >> a &&
-               svn commit -m "SVN-side change outside of .git" &&
-               svn up &&
-               svn log -v | fgrep "SVN-side change outside of .git"
+               svn_cmd commit -m "SVN-side change outside of .git" &&
+               svn_cmd up &&
+               svn_cmd log -v | fgrep "SVN-side change outside of .git"
        )
 '
 
@@ -56,10 +56,10 @@ test_expect_success 'SVN-side change inside of .git' '
                git add a &&
                git commit -m "add a inside an SVN repo" &&
                git log &&
-               svn add --force .git &&
-               svn commit -m "SVN-side change inside of .git" &&
-               svn up &&
-               svn log -v | fgrep "SVN-side change inside of .git"
+               svn_cmd add --force .git &&
+               svn_cmd commit -m "SVN-side change inside of .git" &&
+               svn_cmd up &&
+               svn_cmd log -v | fgrep "SVN-side change inside of .git"
        )
 '
 
@@ -80,9 +80,9 @@ test_expect_success 'SVN-side change in and out of .git' '
                echo c >> a &&
                git add a &&
                git commit -m "add a inside an SVN repo" &&
-               svn commit -m "SVN-side change in and out of .git" &&
-               svn up &&
-               svn log -v | fgrep "SVN-side change in and out of .git"
+               svn_cmd commit -m "SVN-side change in and out of .git" &&
+               svn_cmd up &&
+               svn_cmd log -v | fgrep "SVN-side change in and out of .git"
        )
 '
 
index 71fdc4a69dde2ff0bfdb092d8e28aeba495a1dc0..09ff10cd9b0688522671cac9ee2c8886a8587947 100755 (executable)
@@ -8,19 +8,19 @@ test_description='git svn property tests'
 . ./lib-git-svn.sh
 
 test_expect_success 'setup test repository' '
-       svn co "$svnrepo" s &&
+       svn_cmd co "$svnrepo" s &&
        (
                cd s &&
                mkdir qqq www &&
                echo test_qqq > qqq/test_qqq.txt &&
                echo test_www > www/test_www.txt &&
-               svn add qqq &&
-               svn add www &&
-               svn commit -m "create some files" &&
-               svn up &&
+               svn_cmd add qqq &&
+               svn_cmd add www &&
+               svn_cmd commit -m "create some files" &&
+               svn_cmd up &&
                echo hi >> www/test_www.txt &&
-               svn commit -m "modify www/test_www.txt" &&
-               svn up
+               svn_cmd commit -m "modify www/test_www.txt" &&
+               svn_cmd up
        )
 '
 
@@ -51,9 +51,9 @@ test_expect_success 'SVN-side change outside of www' '
        (
                cd s &&
                echo b >> qqq/test_qqq.txt &&
-               svn commit -m "SVN-side change outside of www" &&
-               svn up &&
-               svn log -v | fgrep "SVN-side change outside of www"
+               svn_cmd commit -m "SVN-side change outside of www" &&
+               svn_cmd up &&
+               svn_cmd log -v | fgrep "SVN-side change outside of www"
        )
 '
 
@@ -83,9 +83,9 @@ test_expect_success 'SVN-side change inside of ignored www' '
        (
                cd s &&
                echo zaq >> www/test_www.txt
-               svn commit -m "SVN-side change inside of www/test_www.txt" &&
-               svn up &&
-               svn log -v | fgrep "SVN-side change inside of www/test_www.txt"
+               svn_cmd commit -m "SVN-side change inside of www/test_www.txt" &&
+               svn_cmd up &&
+               svn_cmd log -v | fgrep "SVN-side change inside of www/test_www.txt"
        )
 '
 
@@ -116,9 +116,9 @@ test_expect_success 'SVN-side change in and out of ignored www' '
                cd s &&
                echo cvf >> www/test_www.txt
                echo ygg >> qqq/test_qqq.txt
-               svn commit -m "SVN-side change in and out of ignored www" &&
-               svn up &&
-               svn log -v | fgrep "SVN-side change in and out of ignored www"
+               svn_cmd commit -m "SVN-side change in and out of ignored www" &&
+               svn_cmd up &&
+               svn_cmd log -v | fgrep "SVN-side change in and out of ignored www"
        )
 '
 
index fd185011b73a8e45b7863bc336f884dee8d4f980..636ca0abb965ad2462a2e1e1ebea2a4183aa19e6 100755 (executable)
@@ -8,7 +8,7 @@ test_expect_success 'initialize repo' '
        mkdir import &&
        cd import &&
        awk "BEGIN { for (i = 1; i < 64; i++) { print i } }" > file
-       svn import -m "initial" . "$svnrepo" &&
+       svn_cmd import -m "initial" . "$svnrepo" &&
        cd .. &&
        git svn init "$svnrepo" &&
        git svn fetch &&
@@ -18,14 +18,14 @@ test_expect_success 'initialize repo' '
 test_expect_success '(supposedly) non-conflicting change from SVN' '
        test x"`sed -n -e 58p < file`" = x58 &&
        test x"`sed -n -e 61p < file`" = x61 &&
-       svn co "$svnrepo" tmp &&
+       svn_cmd co "$svnrepo" tmp &&
        cd tmp &&
                perl -i.bak -p -e "s/^58$/5588/" file &&
                perl -i.bak -p -e "s/^61$/6611/" file &&
                poke file &&
                test x"`sed -n -e 58p < file`" = x5588 &&
                test x"`sed -n -e 61p < file`" = x6611 &&
-               svn commit -m "58 => 5588, 61 => 6611" &&
+               svn_cmd commit -m "58 => 5588, 61 => 6611" &&
                cd ..
        '
 
@@ -46,7 +46,7 @@ test_expect_success 'change file but in unrelated area' "
        test x\"\`sed -n -e 7p < file\`\" = x7777 &&
        git commit -m '4 => 4444, 7 => 7777' file &&
        git svn dcommit &&
-       svn up tmp &&
+       svn_cmd up tmp &&
        cd tmp &&
                test x\"\`sed -n -e 4p < file\`\" = x4444 &&
                test x\"\`sed -n -e 7p < file\`\" = x7777 &&
diff --git a/t/t9138-git-svn-authors-prog.sh b/t/t9138-git-svn-authors-prog.sh
new file mode 100755 (executable)
index 0000000..a4b00f2
--- /dev/null
@@ -0,0 +1,69 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong, Mark Lodato
+#
+
+test_description='git svn authors prog tests'
+
+. ./lib-git-svn.sh
+
+cat > svn-authors-prog <<'EOF'
+#!/usr/bin/perl
+$_ = shift;
+if (s/-sub$//)  {
+       print "$_ <$_\@sub.example.com>\n";
+}
+else {
+       print "$_ <$_\@example.com>\n";
+}
+EOF
+chmod +x svn-authors-prog
+
+cat > svn-authors <<'EOF'
+ff = FFFFFFF FFFFFFF <fFf@other.example.com>
+EOF
+
+test_expect_success 'setup svnrepo' '
+       for i in aa bb cc-sub dd-sub ee-foo ff
+       do
+               svn mkdir -m $i --username $i "$svnrepo"/$i
+       done
+       '
+
+test_expect_success 'import authors with prog and file' '
+       git svn clone --authors-prog=./svn-authors-prog \
+           --authors-file=svn-authors "$svnrepo" x
+       '
+
+test_expect_success 'imported 6 revisions successfully' '
+       (
+               cd x
+               test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 6
+       )
+       '
+
+test_expect_success 'authors-prog ran correctly' '
+       (
+               cd x
+               git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
+                 grep "^author ee-foo <ee-foo@example\.com> " &&
+               git rev-list -1 --pretty=raw refs/remotes/git-svn~2 | \
+                 grep "^author dd <dd@sub\.example\.com> " &&
+               git rev-list -1 --pretty=raw refs/remotes/git-svn~3 | \
+                 grep "^author cc <cc@sub\.example\.com> " &&
+               git rev-list -1 --pretty=raw refs/remotes/git-svn~4 | \
+                 grep "^author bb <bb@example\.com> " &&
+               git rev-list -1 --pretty=raw refs/remotes/git-svn~5 | \
+                 grep "^author aa <aa@example\.com> "
+       )
+       '
+
+test_expect_success 'authors-file overrode authors-prog' '
+       (
+               cd x
+               git rev-list -1 --pretty=raw refs/remotes/git-svn | \
+                 grep "^author FFFFFFF FFFFFFF <fFf@other\.example\.com> "
+       )
+       '
+
+test_done
index b4ca244626a6635faa2587722c26f4c17692af65..4eb7d3f7f042f896106f208a7f8bb91925352b2a 100755 (executable)
@@ -29,6 +29,10 @@ test_expect_success \
      git add . &&
      git commit -m "first commit" &&
 
+     echo "new file in subdir 2" > directory2/file2 &&
+     git add . &&
+     git commit -m "commit in directory2" &&
+
      echo "changed file 1" > file1 &&
      git commit -a -m "second commit" &&
 
index 697daf3ffd33c27654ce00f780acc2c6db5f9985..6c70aec020c9c6486ae984dc264edb1dd8b270cf 100755 (executable)
@@ -86,15 +86,22 @@ close TEMPFILE;
 unlink $tmpfile;
 
 # paths
-is($r->repo_path, "./.git", "repo_path");
+is($r->repo_path, $abs_repo_dir . "/.git", "repo_path");
 is($r->wc_path, $abs_repo_dir . "/", "wc_path");
 is($r->wc_subdir, "", "wc_subdir initial");
 $r->wc_chdir("directory1");
 is($r->wc_subdir, "directory1", "wc_subdir after wc_chdir");
-TODO: {
-       local $TODO = "commands do not work after wc_chdir";
-       # Failure output is active even in non-verbose mode and thus
-       # annoying.  Hence we skip these tests as long as they fail.
-       todo_skip 'config after wc_chdir', 1;
-       is($r->config("color.string"), "value", "config after wc_chdir");
-}
+is($r->config("test.string"), "value", "config after wc_chdir");
+
+# Object generation in sub directory
+chdir("directory2");
+my $r2 = Git->repository();
+is($r2->repo_path, $abs_repo_dir . "/.git", "repo_path (2)");
+is($r2->wc_path, $abs_repo_dir . "/", "wc_path (2)");
+is($r2->wc_subdir, "directory2/", "wc_subdir initial (2)");
+
+# commands in sub directory
+my $last_commit = $r2->command_oneline(qw(rev-parse --verify HEAD));
+like($last_commit, qr/^[0-9a-fA-F]{40}$/, 'rev-parse returned hash');
+my $dir_commit = $r2->command_oneline('log', '-n1', '--pretty=format:%H', '.');
+isnt($last_commit, $dir_commit, 'log . does not show last commit');
index 0e49279c7f7b805c78f1bc4760a0d1c70a84a0d9..b11ad6a6fbab9242a2dac157ee1a55875954b95a 100755 (executable)
@@ -7,7 +7,32 @@
 #
 # To enable this hook, rename this file to "pre-commit".
 
-if git-rev-parse --verify HEAD 2>/dev/null
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+       test "$(git diff --cached --name-only --diff-filter=A -z |
+         LC_ALL=C tr -d '[ -~]\0')"
+then
+       echo "Error: Attempt to add a non-ascii filename."
+       echo
+       echo "This can cause problems if you want to work together"
+       echo "with people on other platforms than you."
+       echo
+       echo "To be portable it is adviseable to rename the file ..."
+       echo
+       echo "If you know what you are doing you can disable this"
+       echo "check using:"
+       echo
+       echo "  git config hooks.allownonascii true"
+       echo
+       exit 1
+fi
+
+if git-rev-parse --verify HEAD >/dev/null 2>&1
 then
        against=HEAD
 else
index f8bf490cffa2d41d19ffc9a31839ca3c2686df16..fd63b2d662dbcf98ec622a1ab754d041a559e3be 100755 (executable)
@@ -13,6 +13,9 @@
 # hooks.allowdeletetag
 #   This boolean sets whether deleting tags will be allowed in the
 #   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
 # hooks.allowdeletebranch
 #   This boolean sets whether deleting branches will be allowed in the
 #   repository.  By default they won't be.
@@ -44,6 +47,7 @@ allowunannotated=$(git config --bool hooks.allowunannotated)
 allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
 denycreatebranch=$(git config --bool hooks.denycreatebranch)
 allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
 
 # check for no description
 projectdesc=$(sed -e '1q' "$GIT_DIR/description")
@@ -82,6 +86,12 @@ case "$refname","$newrev_type" in
                ;;
        refs/tags/*,tag)
                # annotated tag
+               if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+               then
+                       echo "*** Tag '$refname' already exists." >&2
+                       echo "*** Modifying a tag is not allowed in this repository." >&2
+                       exit 1
+               fi
                ;;
        refs/heads/*,commit)
                # branch
index 61d2c39814529bd0264e4c9e40241131d51d819c..e0669dcb41d1d779f274e1ff785352e284953b14 100644 (file)
@@ -19,6 +19,12 @@ int length_callback(const struct option *opt, const char *arg, int unset)
        return 0;
 }
 
+int number_callback(const struct option *opt, const char *arg, int unset)
+{
+       *(int *)opt->value = strtol(arg, NULL, 10);
+       return 0;
+}
+
 int main(int argc, const char **argv)
 {
        const char *usage[] = {
@@ -29,6 +35,7 @@ int main(int argc, const char **argv)
                OPT_BOOLEAN('b', "boolean", &boolean, "get a boolean"),
                OPT_BIT('4', "or4", &boolean,
                        "bitwise-or boolean with ...0100", 4),
+               OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4),
                OPT_GROUP(""),
                OPT_INTEGER('i', "integer", &integer, "get a integer"),
                OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
@@ -45,6 +52,10 @@ int main(int argc, const char **argv)
                        "set string to default", (unsigned long)"default"),
                OPT_GROUP("Magic arguments"),
                OPT_ARGUMENT("quux", "means --quux"),
+               OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
+                       number_callback),
+               { OPTION_BOOLEAN, '+', NULL, &boolean, NULL, "same as -b",
+                 PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH },
                OPT_GROUP("Standard options"),
                OPT__ABBREV(&abbrev),
                OPT__VERBOSE(&verbose),
index 3dfb03c06ed82102f60045d6889db97cf036651e..89d846e5c3d936739a13983728eaf97a1eb15932 100644 (file)
@@ -1069,7 +1069,7 @@ int transport_fetch_refs(struct transport *transport, const struct ref *refs)
 void transport_unlock_pack(struct transport *transport)
 {
        if (transport->pack_lockfile) {
-               unlink(transport->pack_lockfile);
+               unlink_or_warn(transport->pack_lockfile);
                free(transport->pack_lockfile);
                transport->pack_lockfile = NULL;
        }
@@ -1083,3 +1083,51 @@ int transport_disconnect(struct transport *transport)
        free(transport);
        return ret;
 }
+
+/*
+ * Strip username (and password) from an url and return
+ * it in a newly allocated string.
+ */
+char *transport_anonymize_url(const char *url)
+{
+       char *anon_url, *scheme_prefix, *anon_part;
+       size_t anon_len, prefix_len = 0;
+
+       anon_part = strchr(url, '@');
+       if (is_local(url) || !anon_part)
+               goto literal_copy;
+
+       anon_len = strlen(++anon_part);
+       scheme_prefix = strstr(url, "://");
+       if (!scheme_prefix) {
+               if (!strchr(anon_part, ':'))
+                       /* cannot be "me@there:/path/name" */
+                       goto literal_copy;
+       } else {
+               const char *cp;
+               /* make sure scheme is reasonable */
+               for (cp = url; cp < scheme_prefix; cp++) {
+                       switch (*cp) {
+                               /* RFC 1738 2.1 */
+                       case '+': case '.': case '-':
+                               break; /* ok */
+                       default:
+                               if (isalnum(*cp))
+                                       break;
+                               /* it isn't */
+                               goto literal_copy;
+                       }
+               }
+               /* @ past the first slash does not count */
+               cp = strchr(scheme_prefix + 3, '/');
+               if (cp && cp < anon_part)
+                       goto literal_copy;
+               prefix_len = scheme_prefix - url + 3;
+       }
+       anon_url = xcalloc(1, 1 + prefix_len + anon_len);
+       memcpy(anon_url, url, prefix_len);
+       memcpy(anon_url + prefix_len, anon_part, anon_len);
+       return anon_url;
+literal_copy:
+       return xstrdup(url);
+}
index b1c225276619c3bc4dda5dcd0469e242ab421ea0..27bfc528acb5b51006c7d61db0d1d7910adaf31c 100644 (file)
@@ -74,5 +74,6 @@ const struct ref *transport_get_remote_refs(struct transport *transport);
 int transport_fetch_refs(struct transport *transport, const struct ref *refs);
 void transport_unlock_pack(struct transport *transport);
 int transport_disconnect(struct transport *transport);
+char *transport_anonymize_url(const char *url);
 
 #endif
index e4eb8fa3afc7ad895ba925701ee3c6881b29bd91..aaacaf1015ccf1f353151982a3018ad349663d76 100644 (file)
@@ -61,7 +61,7 @@ static void unlink_entry(struct cache_entry *ce)
 {
        if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce)))
                return;
-       if (unlink(ce->name))
+       if (unlink_or_warn(ce->name))
                return;
        schedule_dir_for_removal(ce->name, ce_namelen(ce));
 }
index d8efb1365a01104db568633fa8f6aef0c67b4cd1..7eb3218ee995991881252e4bb599452d7214ae4f 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -289,3 +289,19 @@ int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1)
        safe_create_leading_directories(name);
        return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
 }
+
+int unlink_or_warn(const char *file)
+{
+       int rc = unlink(file);
+
+       if (rc < 0) {
+               int err = errno;
+               if (ENOENT != err) {
+                       warning("unable to unlink %s: %s",
+                               file, strerror(errno));
+                       errno = err;
+               }
+       }
+       return rc;
+}
+