Merge branch 'mw/cvsserver'
authorJunio C Hamano <gitster@pobox.com>
Fri, 7 Dec 2007 07:44:49 +0000 (23:44 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 7 Dec 2007 07:44:49 +0000 (23:44 -0800)
* mw/cvsserver:
git-cvsserver runs hooks/post-update
git-cvsserver runs hooks/post-receive

33 files changed:
Documentation/Makefile
Documentation/SubmittingPatches
Documentation/config.txt
Documentation/diff-format.txt
Documentation/diff-generate-patch.txt [new file with mode: 0644]
Documentation/diff-options.txt
Documentation/git-add.txt
Documentation/git-config.txt
Documentation/git-log.txt
Documentation/git-status.txt
Makefile
builtin-branch.c
builtin-clean.c
builtin-config.c
builtin-fetch.c
builtin-for-each-ref.c
builtin-grep.c
color.c
color.h
config.mak.in
configure.ac
contrib/hg-to-git/hg-to-git.py
diff.c
git-add--interactive.perl
git-am.sh
ident.c
perl/Git.pm
setup.c
t/t1302-repo-version.sh [new file with mode: 0755]
t/t6300-for-each-ref.sh
t/t7300-clean.sh
transport.c
wt-status.c
index 16ee0d39724578b947dee8e1afee6c828e8ed591..1b5802456dea9dec329cba19eddb6ef6ea45a090 100644 (file)
@@ -45,6 +45,9 @@ infodir?=$(prefix)/share/info
 MAKEINFO=makeinfo
 INSTALL_INFO=install-info
 DOCBOOK2X_TEXI=docbook2x-texi
+ifndef PERL_PATH
+       PERL_PATH = /usr/bin/perl
+endif
 
 -include ../config.mak.autogen
 -include ../config.mak
@@ -105,7 +108,7 @@ install-info: info
 #
 doc.dep : $(wildcard *.txt) build-docdep.perl
        $(RM) $@+ $@
-       perl ./build-docdep.perl >$@+
+       $(PERL_PATH) ./build-docdep.perl >$@+
        mv $@+ $@
 
 -include doc.dep
@@ -124,7 +127,7 @@ $(cmds_txt): cmd-list.made
 
 cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
        $(RM) $@
-       perl ./cmd-list.perl ../command-list.txt
+       $(PERL_PATH) ./cmd-list.perl ../command-list.txt
        date >$@
 
 git.7 git.html: git.txt
@@ -161,7 +164,7 @@ user-manual.html: user-manual.xml
 git.info: user-manual.xml
        $(RM) $@ $*.texi $*.texi+
        $(DOCBOOK2X_TEXI) user-manual.xml --to-stdout >$*.texi+
-       perl fix-texi.perl <$*.texi+ >$*.texi
+       $(PERL_PATH) fix-texi.perl <$*.texi+ >$*.texi
        $(MAKEINFO) --no-split $*.texi
        $(RM) $*.texi $*.texi+
 
index 83bf54c7ac153b7010dcecc34d28c05dc68c10b6..de08d094e3e3683913bac49f643bb6b49fbec04d 100644 (file)
@@ -10,7 +10,7 @@ Checklist (and a short version for the impatient):
        - the first line of the commit message should be a short
          description and should skip the full stop
        - if you want your work included in git.git, add a
-         "Signed-off-by: Your Name <your@email.com>" line to the
+         "Signed-off-by: Your Name <you@example.com>" line to the
          commit message (or just use the option "-s" when
          committing) to confirm that you agree to the Developer's
          Certificate of Origin
index 72a33e98b2e0d7a24087b80c3e28f62a05aab439..736fcd71cce107969c93cbd06490b3956be72a1b 100644 (file)
@@ -359,8 +359,8 @@ clean.requireForce::
 
 color.branch::
        A boolean to enable/disable color in the output of
-       gitlink:git-branch[1]. May be set to `true` (or `always`),
-       `false` (or `never`) or `auto`, in which case colors are used
+       gitlink:git-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.branch.<slot>::
@@ -378,9 +378,9 @@ second is the background.  The position of the attribute, if any,
 doesn't matter.
 
 color.diff::
-       When true (or `always`), always use colors in patch.
-       When false (or `never`), never.  When set to `auto`, use
-       colors only when the output is to the terminal.
+       When set to `always`, always use colors in patch.
+       When false (or `never`), never.  When set to `true` or `auto`, use
+       colors only when the output is to the terminal. Defaults to false.
 
 color.diff.<slot>::
        Use customized color for diff colorization.  `<slot>` specifies
@@ -391,14 +391,26 @@ color.diff.<slot>::
        whitespace).  The values of these variables may be specified as
        in color.branch.<slot>.
 
+color.interactive::
+       When set to `always`, always use colors in `git add --interactive`.
+       When false (or `never`), never.  When set to `true` or `auto`, use
+       colors only when the output is to the terminal. Defaults to false.
+
+color.interactive.<slot>::
+       Use customized color for `git add --interactive`
+       output. `<slot>` may be `prompt`, `header`, or `help`, for
+       three distinct types of normal output from interactive
+       programs.  The values of these variables may be specified as
+       in color.branch.<slot>.
+
 color.pager::
        A boolean to enable/disable colored output when the pager is in
        use (default is true).
 
 color.status::
        A boolean to enable/disable color in the output of
-       gitlink:git-status[1]. May be set to `true` (or `always`),
-       `false` (or `never`) or `auto`, in which case colors are used
+       gitlink:git-status[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.<slot>::
index 9709c35c98bc678d1f2e339c8e2d4bbcd7e6231f..2c3a4c433b2a6d2b0846243a4f1dbebeed45236e 100644 (file)
@@ -83,161 +83,4 @@ Note that 'combined diff' lists only files which were modified from
 all parents.
 
 
-Generating patches with -p
---------------------------
-
-When "git-diff-index", "git-diff-tree", or "git-diff-files" are run
-with a '-p' option, or "git diff" without the '--raw' option, they
-do not produce the output described above; instead they produce a
-patch file.  You can customize the creation of such patches via the
-GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables.
-
-What the -p option produces is slightly different from the traditional
-diff format.
-
-1.   It is preceded with a "git diff" header, that looks like
-     this:
-
-       diff --git a/file1 b/file2
-+
-The `a/` and `b/` filenames are the same unless rename/copy is
-involved.  Especially, even for a creation or a deletion,
-`/dev/null` is _not_ used in place of `a/` or `b/` filenames.
-+
-When rename/copy is involved, `file1` and `file2` show the
-name of the source file of the rename/copy and the name of
-the file that rename/copy produces, respectively.
-
-2.   It is followed by one or more extended header lines:
-
-       old mode <mode>
-       new mode <mode>
-       deleted file mode <mode>
-       new file mode <mode>
-       copy from <path>
-       copy to <path>
-       rename from <path>
-       rename to <path>
-       similarity index <number>
-       dissimilarity index <number>
-       index <hash>..<hash> <mode>
-
-3.  TAB, LF, double quote and backslash characters in pathnames
-    are represented as `\t`, `\n`, `\"` and `\\`, respectively.
-    If there is need for such substitution then the whole
-    pathname is put in double quotes.
-
-The similarity index is the percentage of unchanged lines, and
-the dissimilarity index is the percentage of changed lines.  It
-is a rounded down integer, followed by a percent sign.  The
-similarity index value of 100% is thus reserved for two equal
-files, while 100% dissimilarity means that no line from the old
-file made it into the new one.
-
-
-combined diff format
---------------------
-
-"git-diff-tree", "git-diff-files" and "git-diff" can take '-c' or
-'--cc' option to produce 'combined diff', which looks like this:
-
-------------
-diff --combined describe.c
-index fabadb8,cc95eb0..4866510
---- a/describe.c
-+++ b/describe.c
-@@@ -98,20 -98,12 +98,20 @@@
-       return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
-  }
-
-- static void describe(char *arg)
- -static void describe(struct commit *cmit, int last_one)
-++static void describe(char *arg, int last_one)
-  {
- +     unsigned char sha1[20];
- +     struct commit *cmit;
-       struct commit_list *list;
-       static int initialized = 0;
-       struct commit_name *n;
-
- +     if (get_sha1(arg, sha1) < 0)
- +             usage(describe_usage);
- +     cmit = lookup_commit_reference(sha1);
- +     if (!cmit)
- +             usage(describe_usage);
- +
-       if (!initialized) {
-               initialized = 1;
-               for_each_ref(get_name);
-------------
-
-1.   It is preceded with a "git diff" header, that looks like
-     this (when '-c' option is used):
-
-       diff --combined file
-+
-or like this (when '--cc' option is used):
-
-       diff --c file
-
-2.   It is followed by one or more extended header lines
-     (this example shows a merge with two parents):
-
-       index <hash>,<hash>..<hash>
-       mode <mode>,<mode>..<mode>
-       new file mode <mode>
-       deleted file mode <mode>,<mode>
-+
-The `mode <mode>,<mode>..<mode>` line appears only if at least one of
-the <mode> is different from the rest. Extended headers with
-information about detected contents movement (renames and
-copying detection) are designed to work with diff of two
-<tree-ish> and are not used by combined diff format.
-
-3.   It is followed by two-line from-file/to-file header
-
-       --- a/file
-       +++ b/file
-+
-Similar to two-line header for traditional 'unified' diff
-format, `/dev/null` is used to signal created or deleted
-files.
-
-4.   Chunk header format is modified to prevent people from
-     accidentally feeding it to `patch -p1`. Combined diff format
-     was created for review of merge commit changes, and was not
-     meant for apply. The change is similar to the change in the
-     extended 'index' header:
-
-       @@@ <from-file-range> <from-file-range> <to-file-range> @@@
-+
-There are (number of parents + 1) `@` characters in the chunk
-header for combined diff format.
-
-Unlike the traditional 'unified' diff format, which shows two
-files A and B with a single column that has `-` (minus --
-appears in A but removed in B), `+` (plus -- missing in A but
-added to B), or `" "` (space -- unchanged) prefix, this format
-compares two or more files file1, file2,... with one file X, and
-shows how X differs from each of fileN.  One column for each of
-fileN is prepended to the output line to note how X's line is
-different from it.
-
-A `-` character in the column N means that the line appears in
-fileN but it does not appear in the result.  A `+` character
-in the column N means that the line appears in the last file,
-and fileN does not have that line (in other words, the line was
-added, from the point of view of that parent).
-
-In the above example output, the function signature was changed
-from both files (hence two `-` removals from both file1 and
-file2, plus `++` to mean one line that was added does not appear
-in either file1 nor file2).  Also two other lines are the same
-from file1 but do not appear in file2 (hence prefixed with ` +`).
-
-When shown by `git diff-tree -c`, it compares the parents of a
-merge commit with the merge result (i.e. file1..fileN are the
-parents).  When shown by `git diff-files -c`, it compares the
-two unresolved merge parents with the working tree file
-(i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka
-"their version").
+include::diff-generate-patch.txt[]
diff --git a/Documentation/diff-generate-patch.txt b/Documentation/diff-generate-patch.txt
new file mode 100644 (file)
index 0000000..029c5f2
--- /dev/null
@@ -0,0 +1,161 @@
+Generating patches with -p
+--------------------------
+
+When "git-diff-index", "git-diff-tree", or "git-diff-files" are run
+with a '-p' option, "git diff" without the '--raw' option, or
+"git log" with the "-p" option, they
+do not produce the output described above; instead they produce a
+patch file.  You can customize the creation of such patches via the
+GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables.
+
+What the -p option produces is slightly different from the traditional
+diff format.
+
+1.   It is preceded with a "git diff" header, that looks like
+     this:
+
+       diff --git a/file1 b/file2
++
+The `a/` and `b/` filenames are the same unless rename/copy is
+involved.  Especially, even for a creation or a deletion,
+`/dev/null` is _not_ used in place of `a/` or `b/` filenames.
++
+When rename/copy is involved, `file1` and `file2` show the
+name of the source file of the rename/copy and the name of
+the file that rename/copy produces, respectively.
+
+2.   It is followed by one or more extended header lines:
+
+       old mode <mode>
+       new mode <mode>
+       deleted file mode <mode>
+       new file mode <mode>
+       copy from <path>
+       copy to <path>
+       rename from <path>
+       rename to <path>
+       similarity index <number>
+       dissimilarity index <number>
+       index <hash>..<hash> <mode>
+
+3.  TAB, LF, double quote and backslash characters in pathnames
+    are represented as `\t`, `\n`, `\"` and `\\`, respectively.
+    If there is need for such substitution then the whole
+    pathname is put in double quotes.
+
+The similarity index is the percentage of unchanged lines, and
+the dissimilarity index is the percentage of changed lines.  It
+is a rounded down integer, followed by a percent sign.  The
+similarity index value of 100% is thus reserved for two equal
+files, while 100% dissimilarity means that no line from the old
+file made it into the new one.
+
+
+combined diff format
+--------------------
+
+"git-diff-tree", "git-diff-files" and "git-diff" can take '-c' or
+'--cc' option to produce 'combined diff'.  For showing a merge commit
+with "git log -p", this is the default format.
+A 'combined diff' format looks like this:
+
+------------
+diff --combined describe.c
+index fabadb8,cc95eb0..4866510
+--- a/describe.c
++++ b/describe.c
+@@@ -98,20 -98,12 +98,20 @@@
+       return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
+  }
+
+- static void describe(char *arg)
+ -static void describe(struct commit *cmit, int last_one)
+++static void describe(char *arg, int last_one)
+  {
+ +     unsigned char sha1[20];
+ +     struct commit *cmit;
+       struct commit_list *list;
+       static int initialized = 0;
+       struct commit_name *n;
+
+ +     if (get_sha1(arg, sha1) < 0)
+ +             usage(describe_usage);
+ +     cmit = lookup_commit_reference(sha1);
+ +     if (!cmit)
+ +             usage(describe_usage);
+ +
+       if (!initialized) {
+               initialized = 1;
+               for_each_ref(get_name);
+------------
+
+1.   It is preceded with a "git diff" header, that looks like
+     this (when '-c' option is used):
+
+       diff --combined file
++
+or like this (when '--cc' option is used):
+
+       diff --c file
+
+2.   It is followed by one or more extended header lines
+     (this example shows a merge with two parents):
+
+       index <hash>,<hash>..<hash>
+       mode <mode>,<mode>..<mode>
+       new file mode <mode>
+       deleted file mode <mode>,<mode>
++
+The `mode <mode>,<mode>..<mode>` line appears only if at least one of
+the <mode> is different from the rest. Extended headers with
+information about detected contents movement (renames and
+copying detection) are designed to work with diff of two
+<tree-ish> and are not used by combined diff format.
+
+3.   It is followed by two-line from-file/to-file header
+
+       --- a/file
+       +++ b/file
++
+Similar to two-line header for traditional 'unified' diff
+format, `/dev/null` is used to signal created or deleted
+files.
+
+4.   Chunk header format is modified to prevent people from
+     accidentally feeding it to `patch -p1`. Combined diff format
+     was created for review of merge commit changes, and was not
+     meant for apply. The change is similar to the change in the
+     extended 'index' header:
+
+       @@@ <from-file-range> <from-file-range> <to-file-range> @@@
++
+There are (number of parents + 1) `@` characters in the chunk
+header for combined diff format.
+
+Unlike the traditional 'unified' diff format, which shows two
+files A and B with a single column that has `-` (minus --
+appears in A but removed in B), `+` (plus -- missing in A but
+added to B), or `" "` (space -- unchanged) prefix, this format
+compares two or more files file1, file2,... with one file X, and
+shows how X differs from each of fileN.  One column for each of
+fileN is prepended to the output line to note how X's line is
+different from it.
+
+A `-` character in the column N means that the line appears in
+fileN but it does not appear in the result.  A `+` character
+in the column N means that the line appears in the last file,
+and fileN does not have that line (in other words, the line was
+added, from the point of view of that parent).
+
+In the above example output, the function signature was changed
+from both files (hence two `-` removals from both file1 and
+file2, plus `++` to mean one line that was added does not appear
+in either file1 nor file2).  Also two other lines are the same
+from file1 but do not appear in file2 (hence prefixed with ` +`).
+
+When shown by `git diff-tree -c`, it compares the parents of a
+merge commit with the merge result (i.e. file1..fileN are the
+parents).  When shown by `git diff-files -c`, it compares the
+two unresolved merge parents with the working tree file
+(i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka
+"their version").
index e4af393515c346528bccb7a4f2d3823aebddddfc..d0154bbc0a2f868b3f5f1c63dcffd1fc9355ebc3 100644 (file)
@@ -6,7 +6,9 @@
 
 ifndef::git-format-patch[]
 ifndef::git-diff[]
+ifndef::git-log[]
 :git-diff-core: 1
+endif::git-log[]
 endif::git-diff[]
 endif::git-format-patch[]
 
index e74f83b47ad7453ea3fda994f067de81f04baa9d..bf94cd43bdd8a9e113af37bec5acd568dd1b3930 100644 (file)
@@ -8,7 +8,7 @@ git-add - Add file contents to the index
 SYNOPSIS
 --------
 [verse]
-'git-add' [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh]
+'git-add' [-n] [-v] [-f] [--interactive | -i] [--patch | -p] [-u] [--refresh]
           [--] <filepattern>...
 
 DESCRIPTION
index 7640450787064aac7211b5a3d5504275b62119ff..98509b4f441abc7671645ece78c9ba83a8dac4c0 100644 (file)
@@ -21,6 +21,7 @@ SYNOPSIS
 'git-config' [<file-option>] --remove-section name
 'git-config' [<file-option>] [-z|--null] -l | --list
 'git-config' [<file-option>] --get-color name [default]
+'git-config' [<file-option>] --get-colorbool name [stdout-is-tty]
 
 DESCRIPTION
 -----------
@@ -135,6 +136,15 @@ See also <<FILES>>.
        output without getting confused e.g. by values that
        contain line breaks.
 
+--get-colorbool name [stdout-is-tty]::
+
+       Find the color setting for `name` (e.g. `color.diff`) and output
+       "true" or "false".  `stdout-is-tty` should be either "true" or
+       "false", and is taken into account when configuration says
+       "auto".  If `stdout-is-tty` is missing, then checks the standard
+       output of the command itself, and exits with status 0 if color
+       is to be used, or exits with status 1 otherwise.
+
 --get-color name default::
 
        Find the color configured for `name` (e.g. `color.diff.new`) and
index 5ec547cc0c10fb940b1bd2481940997cd375e830..5920d1799acd2fe84e302b005695e2c795ecad36 100644 (file)
@@ -27,6 +27,9 @@ OPTIONS
 
 include::pretty-options.txt[]
 
+:git-log: 1
+include::diff-options.txt[]
+
 -<n>::
        Limits the number of commits to show.
 
@@ -43,9 +46,6 @@ include::pretty-options.txt[]
        commit.  This  option gives a better overview of the
        evolution of a particular branch.
 
--p::
-       Show the change the commit introduces in a patch form.
-
 -g, \--walk-reflogs::
        Show commits as they were recorded in the reflog. The log contains
        a record about how the tip of a reference was changed.
@@ -78,6 +78,7 @@ include::pretty-options.txt[]
 
 include::pretty-formats.txt[]
 
+include::diff-generate-patch.txt[]
 
 Examples
 --------
index 8fd0fc62368611bee25b4bbc3becef853937ff2c..b0cb6bc8b74158f3c9012b6f2d0f10f8f9e5bae9 100644 (file)
@@ -40,6 +40,10 @@ OUTPUT
 The output from this command is designed to be used as a commit
 template comments, and all the output lines are prefixed with '#'.
 
+The paths mentioned in the output, unlike many other git commands, are
+made relative to the current directory, if you are working in a
+subdirectory (this is on purpose, to help cutting and pasting).
+
 
 CONFIGURATION
 -------------
index 999391e10b9949ea9c4cb0e71d98bf6d72ee47af..4dda3405bb6d456e8f4910e834affc6a82827f77 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -406,7 +406,9 @@ endif
 ifeq ($(uname_S),Darwin)
        NEEDS_SSL_WITH_CRYPTO = YesPlease
        NEEDS_LIBICONV = YesPlease
-       OLD_ICONV = UnfortunatelyYes
+       ifneq ($(shell expr "$(uname_R)" : '9\.'),2)
+               OLD_ICONV = UnfortunatelyYes
+       endif
        NO_STRLCPY = YesPlease
        NO_MEMMEM = YesPlease
 endif
index c64768beb2c112fc32a65fb4070f01331ebf1540..089cae59299659b20359b7249e57ddc3a43ded06 100644 (file)
@@ -65,7 +65,7 @@ static int parse_branch_color_slot(const char *var, int ofs)
 static int git_branch_config(const char *var, const char *value)
 {
        if (!strcmp(var, "color.branch")) {
-               branch_use_color = git_config_colorbool(var, value);
+               branch_use_color = git_config_colorbool(var, value, -1);
                return 0;
        }
        if (!prefixcmp(var, "color.branch.")) {
index 56ae4eb9bb4efad179f7d664880457535bd6048f..ae30d4e76c3e758689464f41a63dda0605d60e9f 100644 (file)
@@ -27,13 +27,14 @@ static int git_clean_config(const char *var, const char *value)
 
 int cmd_clean(int argc, const char **argv, const char *prefix)
 {
-       int j;
+       int i;
        int show_only = 0, remove_directories = 0, quiet = 0, ignored = 0;
        int ignored_only = 0, baselen = 0, config_set = 0;
        struct strbuf directory;
        struct dir_struct dir;
        const char *path, *base;
        static const char **pathspec;
+       char *seen = NULL;
        struct option options[] = {
                OPT__QUIET(&quiet),
                OPT__DRY_RUN(&show_only),
@@ -85,12 +86,14 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
        read_directory(&dir, path, base, baselen, pathspec);
        strbuf_init(&directory, 0);
 
-       for (j = 0; j < dir.nr; ++j) {
-               struct dir_entry *ent = dir.entries[j];
-               int len, pos, specs;
+       if (pathspec)
+               seen = xmalloc(argc);
+
+       for (i = 0; i < dir.nr; i++) {
+               struct dir_entry *ent = dir.entries[i];
+               int len, pos, matches;
                struct cache_entry *ce;
                struct stat st;
-               char *seen;
 
                /*
                 * Remove the '/' at the end that directory
@@ -110,25 +113,29 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
                                continue; /* Yup, this one exists unmerged */
                }
 
-               if (!lstat(ent->name, &st) && (S_ISDIR(st.st_mode))) {
-                       int matched_path = 0;
+               /*
+                * we might have removed this as part of earlier
+                * recursive directory removal, so lstat() here could
+                * fail with ENOENT.
+                */
+               if (lstat(ent->name, &st))
+                       continue;
+
+               if (pathspec) {
+                       memset(seen, 0, argc);
+                       matches = match_pathspec(pathspec, ent->name, ent->len,
+                                                baselen, seen);
+               } else {
+                       matches = 0;
+               }
+
+               if (S_ISDIR(st.st_mode)) {
                        strbuf_addstr(&directory, ent->name);
-                       if (pathspec) {
-                               for (specs =0; pathspec[specs]; ++specs)
-                                       /* nothing */;
-                               seen = xcalloc(specs, 1);
-                               /* Check if directory was explictly passed as
-                                * pathspec.  If so we want to remove it */
-                               if (match_pathspec(pathspec, ent->name, ent->len,
-                                                  baselen, seen))
-                                       matched_path = 1;
-                               free(seen);
-                       }
-                       if (show_only && (remove_directories || matched_path)) {
+                       if (show_only && (remove_directories || matches)) {
                                printf("Would remove %s\n", directory.buf);
-                       } else if (quiet && (remove_directories || matched_path)) {
+                       } else if (quiet && (remove_directories || matches)) {
                                remove_dir_recursively(&directory, 0);
-                       } else if (remove_directories || matched_path) {
+                       } else if (remove_directories || matches) {
                                printf("Removing %s\n", directory.buf);
                                remove_dir_recursively(&directory, 0);
                        } else if (show_only) {
@@ -138,6 +145,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
                        }
                        strbuf_reset(&directory);
                } else {
+                       if (pathspec && !matches)
+                               continue;
                        if (show_only) {
                                printf("Would remove %s\n", ent->name);
                                continue;
@@ -147,6 +156,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
                        unlink(ent->name);
                }
        }
+       free(seen);
 
        strbuf_release(&directory);
        return 0;
index 4c9ded3b1a146c20d24559bbbee267e9be743fd2..e4a12e316648e6b0ab1ee0b424773f3c672c751e 100644 (file)
@@ -3,7 +3,7 @@
 #include "color.h"
 
 static const char git_config_set_usage[] =
-"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default]";
+"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
 
 static char *key;
 static regex_t *key_regexp;
@@ -38,8 +38,7 @@ static int show_config(const char* key_, const char* value_)
        if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0))
                return 0;
        if (regexp != NULL &&
-                        (do_not_match ^
-                         regexec(regexp, (value_?value_:""), 0, NULL, 0)))
+           (do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0)))
                return 0;
 
        if (show_keys) {
@@ -209,6 +208,57 @@ static int get_color(int argc, const char **argv)
        return 0;
 }
 
+static int stdout_is_tty;
+static int get_colorbool_found;
+static int get_diff_color_found;
+static int git_get_colorbool_config(const char *var, const char *value)
+{
+       if (!strcmp(var, get_color_slot)) {
+               get_colorbool_found =
+                       git_config_colorbool(var, value, stdout_is_tty);
+       }
+       if (!strcmp(var, "diff.color")) {
+               get_diff_color_found =
+                       git_config_colorbool(var, value, stdout_is_tty);
+       }
+       return 0;
+}
+
+static int get_colorbool(int argc, const char **argv)
+{
+       /*
+        * git config --get-colorbool <slot> [<stdout-is-tty>]
+        *
+        * returns "true" or "false" depending on how <slot>
+        * is configured.
+        */
+
+       if (argc == 2)
+               stdout_is_tty = git_config_bool("command line", argv[1]);
+       else if (argc == 1)
+               stdout_is_tty = isatty(1);
+       else
+               usage(git_config_set_usage);
+       get_colorbool_found = -1;
+       get_diff_color_found = -1;
+       get_color_slot = argv[0];
+       git_config(git_get_colorbool_config);
+
+       if (get_colorbool_found < 0) {
+               if (!strcmp(get_color_slot, "color.diff"))
+                       get_colorbool_found = get_diff_color_found;
+               if (get_colorbool_found < 0)
+                       get_colorbool_found = 0;
+       }
+
+       if (argc == 1) {
+               return get_colorbool_found ? 0 : 1;
+       } else {
+               printf("%s\n", get_colorbool_found ? "true" : "false");
+               return 0;
+       }
+}
+
 int cmd_config(int argc, const char **argv, const char *prefix)
 {
        int nongit = 0;
@@ -284,6 +334,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                        return 0;
                } else if (!strcmp(argv[1], "--get-color")) {
                        return get_color(argc-2, argv+2);
+               } else if (!strcmp(argv[1], "--get-colorbool")) {
+                       return get_colorbool(argc-2, argv+2);
                } else
                        break;
                argc--;
index f6d16fe9662c01f44795837606d48ddf7c9d414e..320e235682340f07cb28b0a4de0c39b6bd9da383 100644 (file)
@@ -9,14 +9,45 @@
 #include "remote.h"
 #include "transport.h"
 #include "run-command.h"
+#include "parse-options.h"
 
-static const char fetch_usage[] = "git-fetch [-a | --append] [--upload-pack <upload-pack>] [-f | --force] [--no-tags] [-t | --tags] [-k | --keep] [-u | --update-head-ok] [--depth <depth>] [-v | --verbose] [<repository> <refspec>...]";
+static const char * const builtin_fetch_usage[] = {
+       "git-fetch [options] [<repository> <refspec>...]",
+       NULL
+};
 
-static int append, force, tags, no_tags, update_head_ok, verbose, quiet;
+enum {
+       TAGS_UNSET = 0,
+       TAGS_DEFAULT = 1,
+       TAGS_SET = 2
+};
+
+static int append, force, keep, update_head_ok, verbose, quiet;
+static int tags = TAGS_DEFAULT;
 static const char *depth;
+static const char *upload_pack;
 static struct strbuf default_rla = STRBUF_INIT;
 static struct transport *transport;
 
+static struct option builtin_fetch_options[] = {
+       OPT__QUIET(&quiet),
+       OPT__VERBOSE(&verbose),
+       OPT_BOOLEAN('a', "append", &append,
+                   "append to .git/FETCH_HEAD instead of overwriting"),
+       OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
+                  "path to upload pack on remote end"),
+       OPT_BOOLEAN('f', "force", &force,
+                   "force overwrite of local branch"),
+       OPT_SET_INT('t', "tags", &tags,
+                   "fetch all tags and associated objects", TAGS_SET),
+       OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
+       OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
+                   "allow updating of HEAD ref"),
+       OPT_STRING(0, "depth", &depth, "DEPTH",
+                  "deepen history of shallow clone"),
+       OPT_END()
+};
+
 static void unlock_pack(void)
 {
        if (transport)
@@ -81,7 +112,7 @@ static struct ref *get_ref_map(struct transport *transport,
 
        const struct ref *remote_refs = transport_get_remote_refs(transport);
 
-       if (ref_count || tags) {
+       if (ref_count || tags == TAGS_SET) {
                for (i = 0; i < ref_count; i++) {
                        get_fetch_map(remote_refs, &refs[i], &tail, 0);
                        if (refs[i].dst && refs[i].dst[0])
@@ -90,7 +121,7 @@ static struct ref *get_ref_map(struct transport *transport,
                /* Merge everything on the command line, but not --tags */
                for (rm = ref_map; rm; rm = rm->next)
                        rm->merge = 1;
-               if (tags) {
+               if (tags == TAGS_SET) {
                        struct refspec refspec;
                        refspec.src = "refs/tags/";
                        refspec.dst = "refs/tags/";
@@ -482,10 +513,10 @@ static int do_fetch(struct transport *transport,
        struct ref *ref_map, *fetch_map;
        struct ref *rm;
        int autotags = (transport->remote->fetch_tags == 1);
-       if (transport->remote->fetch_tags == 2 && !no_tags)
-               tags = 1;
+       if (transport->remote->fetch_tags == 2 && tags != TAGS_UNSET)
+               tags = TAGS_SET;
        if (transport->remote->fetch_tags == -1)
-               no_tags = 1;
+               tags = TAGS_UNSET;
 
        if (!transport->get_refs_list || !transport->fetch)
                die("Don't know how to fetch from %s", transport->url);
@@ -515,7 +546,7 @@ static int do_fetch(struct transport *transport,
 
        /* if neither --no-tags nor --tags was specified, do automated tag
         * following ... */
-       if (!(tags || no_tags) && autotags) {
+       if (tags == TAGS_DEFAULT && autotags) {
                ref_map = find_non_local_tags(transport, fetch_map);
                if (ref_map) {
                        transport_set_option(transport, TRANS_OPT_DEPTH, "0");
@@ -546,80 +577,19 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        int i;
        static const char **refs = NULL;
        int ref_nr = 0;
-       const char *upload_pack = NULL;
-       int keep = 0;
 
        /* Record the command line for the reflog */
        strbuf_addstr(&default_rla, "fetch");
        for (i = 1; i < argc; i++)
                strbuf_addf(&default_rla, " %s", argv[i]);
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-
-               if (arg[0] != '-')
-                       break;
-               if (!strcmp(arg, "--append") || !strcmp(arg, "-a")) {
-                       append = 1;
-                       continue;
-               }
-               if (!prefixcmp(arg, "--upload-pack=")) {
-                       upload_pack = arg + 14;
-                       continue;
-               }
-               if (!strcmp(arg, "--upload-pack")) {
-                       i++;
-                       if (i == argc)
-                               usage(fetch_usage);
-                       upload_pack = argv[i];
-                       continue;
-               }
-               if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
-                       force = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--no-tags")) {
-                       no_tags = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--tags") || !strcmp(arg, "-t")) {
-                       tags = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--keep") || !strcmp(arg, "-k")) {
-                       keep = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--update-head-ok") || !strcmp(arg, "-u")) {
-                       update_head_ok = 1;
-                       continue;
-               }
-               if (!prefixcmp(arg, "--depth=")) {
-                       depth = arg + 8;
-                       continue;
-               }
-               if (!strcmp(arg, "--depth")) {
-                       i++;
-                       if (i == argc)
-                               usage(fetch_usage);
-                       depth = argv[i];
-                       continue;
-               }
-               if (!strcmp(arg, "--quiet") || !strcmp(arg, "-q")) {
-                       quiet = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) {
-                       verbose++;
-                       continue;
-               }
-               usage(fetch_usage);
-       }
+       argc = parse_options(argc, argv,
+                            builtin_fetch_options, builtin_fetch_usage, 0);
 
-       if (i == argc)
+       if (argc == 0)
                remote = remote_get(NULL);
        else
-               remote = remote_get(argv[i++]);
+               remote = remote_get(argv[0]);
 
        transport = transport_get(remote, remote->url[0]);
        if (verbose >= 2)
@@ -636,10 +606,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        if (!transport->url)
                die("Where do you want to fetch from today?");
 
-       if (i < argc) {
+       if (argc > 1) {
                int j = 0;
-               refs = xcalloc(argc - i + 1, sizeof(const char *));
-               while (i < argc) {
+               refs = xcalloc(argc + 1, sizeof(const char *));
+               for (i = 1; i < argc; i++) {
                        if (!strcmp(argv[i], "tag")) {
                                char *ref;
                                i++;
@@ -651,7 +621,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                                refs[j++] = ref;
                        } else
                                refs[j++] = argv[i];
-                       i++;
                }
                refs[j] = NULL;
                ref_nr = j;
index daf3a081650b6b39fe18f0fab61fa8b3f6c8be0f..f36a43c26459bd386618e551e2e93743cd8030aa 100644 (file)
@@ -13,8 +13,8 @@
 #define QUOTE_NONE 0
 #define QUOTE_SHELL 1
 #define QUOTE_PERL 2
-#define QUOTE_PYTHON 3
-#define QUOTE_TCL 4
+#define QUOTE_PYTHON 4
+#define QUOTE_TCL 8
 
 typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
 
@@ -861,7 +861,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
                usage_with_options(for_each_ref_usage, opts);
        }
        if (HAS_MULTI_BITS(quote_style)) {
-               error("more than one quoting style ?");
+               error("more than one quoting style?");
                usage_with_options(for_each_ref_usage, opts);
        }
        if (verify_format(format))
index bbf747fc7b66f6b4f19d9dc62a9ba10965199917..f1ff8dc556ce6caa1cafe77be41396dd9b7c9ee6 100644 (file)
@@ -343,12 +343,12 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
                        memcpy(name + 2, ce->name, len + 1);
                }
                argv[argc++] = name;
-               if (argc < MAXARGS)
-                       continue;
-               status = flush_grep(opt, argc, nr, argv, &kept);
-               if (0 < status)
-                       hit = 1;
-               argc = nr + kept;
+               if (MAXARGS <= argc) {
+                       status = flush_grep(opt, argc, nr, argv, &kept);
+                       if (0 < status)
+                               hit = 1;
+                       argc = nr + kept;
+               }
                if (ce_stage(ce)) {
                        do {
                                i++;
diff --git a/color.c b/color.c
index 97cfbda31ac02b7e4fe747052c28821a34ee0165..7bd424a8f6012859f40f2aa6210e7d4ce7686dc0 100644 (file)
--- a/color.c
+++ b/color.c
@@ -116,7 +116,7 @@ void color_parse(const char *value, const char *var, char *dst)
        die("bad config value '%s' for variable '%s'", value, var);
 }
 
-int git_config_colorbool(const char *var, const char *value)
+int git_config_colorbool(const char *var, const char *value, int stdout_is_tty)
 {
        if (value) {
                if (!strcasecmp(value, "never"))
@@ -133,7 +133,9 @@ int git_config_colorbool(const char *var, const char *value)
 
        /* any normal truth value defaults to 'auto' */
  auto_color:
-       if (isatty(1) || (pager_in_use && pager_use_color)) {
+       if (stdout_is_tty < 0)
+               stdout_is_tty = isatty(1);
+       if (stdout_is_tty || (pager_in_use && pager_use_color)) {
                char *term = getenv("TERM");
                if (term && strcmp(term, "dumb"))
                        return 1;
diff --git a/color.h b/color.h
index 68098006ed057552370ec27359eb776e139bec5e..ff63513d39b1553e65230ef98583549506670950 100644 (file)
--- a/color.h
+++ b/color.h
@@ -4,7 +4,7 @@
 /* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
 #define COLOR_MAXLEN 24
 
-int git_config_colorbool(const char *var, const char *value);
+int git_config_colorbool(const char *var, const char *value, int stdout_is_tty);
 void color_parse(const char *var, const char *value, char *dst);
 int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
 int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
index 11d256e9cf5b51154a3bf0084f9e3bcea5702352..7d5df9bf3c5dc898a68b538bae55f3d44dbc01ff 100644 (file)
@@ -41,4 +41,5 @@ NO_STRTOUMAX=@NO_STRTOUMAX@
 NO_SETENV=@NO_SETENV@
 NO_MKDTEMP=@NO_MKDTEMP@
 NO_ICONV=@NO_ICONV@
+OLD_ICONV=@OLD_ICONV@
 NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
index 5f8a15b9f9580bea6f350e8af468f81cf2535c9e..dd4b4eb9822f131f0efc746013a803c4adba02d2 100644 (file)
@@ -212,6 +212,28 @@ test -n "$NEEDS_SOCKET" && LIBS="$LIBS -lsocket"
 
 
 ## Checks for header files.
+AC_MSG_NOTICE([CHECKS for header files])
+#
+# Define OLD_ICONV if your library has an old iconv(), where the second
+# (input buffer pointer) parameter is declared with type (const char **).
+AC_DEFUN([OLDICONVTEST_SRC], [[
+#include <iconv.h>
+
+extern size_t iconv(iconv_t cd,
+                   char **inbuf, size_t *inbytesleft,
+                   char **outbuf, size_t *outbytesleft);
+
+int main(void)
+{
+       return 0;
+}
+]])
+AC_MSG_CHECKING([for old iconv()])
+AC_COMPILE_IFELSE(OLDICONVTEST_SRC,
+       [AC_MSG_RESULT([no])],
+       [AC_MSG_RESULT([yes])
+       OLD_ICONV=UnfortunatelyYes])
+AC_SUBST(OLD_ICONV)
 
 
 ## Checks for typedefs, structures, and compiler characteristics.
index 7a1c3e497f00fd886a0602551bfa933931a995be..9befb92c410794a3e81cc571b82f9f35e0def091 100755 (executable)
@@ -211,7 +211,7 @@ def getgitenv(user, date):
     os.system('git-ls-files -x .hg --deleted | git-update-index --remove --stdin')
 
     # commit
-    os.system(getgitenv(user, date) + 'git-commit -a -F %s' % filecomment)
+    os.system(getgitenv(user, date) + 'git commit --allow-empty -a -F %s' % filecomment)
     os.unlink(filecomment)
 
     # tag
diff --git a/diff.c b/diff.c
index 6b54959610db604bfabc15e6edd2b212f16d0c62..be6cf687a4421acdc127df73aafef4aa9cf4daac 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -146,7 +146,7 @@ int git_diff_ui_config(const char *var, const char *value)
                return 0;
        }
        if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
-               diff_use_color_default = git_config_colorbool(var, value);
+               diff_use_color_default = git_config_colorbool(var, value, -1);
                return 0;
        }
        if (!strcmp(var, "diff.renames")) {
index 335c2c6b56875b97ad6cf8f4406218833afc53ef..1019a72d6c5840a3a30a8435ac7e425080c0f594 100755 (executable)
@@ -1,6 +1,55 @@
 #!/usr/bin/perl -w
 
 use strict;
+use Git;
+
+# Prompt colors:
+my ($prompt_color, $header_color, $help_color, $normal_color);
+# Diff colors:
+my ($new_color, $old_color, $fraginfo_color, $metainfo_color, $whitespace_color);
+
+my ($use_color, $diff_use_color);
+my $repo = Git->repository();
+
+$use_color = $repo->get_colorbool('color.interactive');
+
+if ($use_color) {
+       # Set interactive colors:
+
+       # Grab the 3 main colors in git color string format, with sane
+       # (visible) defaults:
+       $prompt_color = $repo->get_color("color.interactive.prompt", "bold blue");
+       $header_color = $repo->get_color("color.interactive.header", "bold");
+       $help_color = $repo->get_color("color.interactive.help", "red bold");
+       $normal_color = $repo->get_color("", "reset");
+
+       # Do we also set diff colors?
+       $diff_use_color = $repo->get_colorbool('color.diff');
+       if ($diff_use_color) {
+               $new_color = $repo->get_color("color.diff.new", "green");
+               $old_color = $repo->get_color("color.diff.old", "red");
+               $fraginfo_color = $repo->get_color("color.diff.frag", "cyan");
+               $metainfo_color = $repo->get_color("color.diff.meta", "bold");
+               $whitespace_color = $repo->get_color("color.diff.whitespace", "normal red");
+       }
+}
+
+sub colored {
+       my $color = shift;
+       my $string = join("", @_);
+
+       if ($use_color) {
+               # Put a color code at the beginning of each line, a reset at the end
+               # color after newlines that are not at the end of the string
+               $string =~ s/(\n+)(.)/$1$color$2/g;
+               # reset before newlines
+               $string =~ s/(\n+)/$normal_color$1/g;
+               # codes at beginning and end (if necessary):
+               $string =~ s/^/$color/;
+               $string =~ s/$/$normal_color/ unless $string =~ /\n$/;
+       }
+       return $string;
+}
 
 # command line options
 my $patch_mode;
@@ -246,10 +295,20 @@ sub is_valid_prefix {
 sub highlight_prefix {
        my $prefix = shift;
        my $remainder = shift;
-       return $remainder unless defined $prefix;
-       return is_valid_prefix($prefix) ?
-           "[$prefix]$remainder" :
-           "$prefix$remainder";
+
+       if (!defined $prefix) {
+               return $remainder;
+       }
+
+       if (!is_valid_prefix($prefix)) {
+               return "$prefix$remainder";
+       }
+
+       if (!$use_color) {
+               return "[$prefix]$remainder";
+       }
+
+       return "$prompt_color$prefix$normal_color$remainder";
 }
 
 sub list_and_choose {
@@ -266,7 +325,7 @@ sub list_and_choose {
                        if (!$opts->{LIST_FLAT}) {
                                print "     ";
                        }
-                       print "$opts->{HEADER}\n";
+                       print colored $header_color, "$opts->{HEADER}\n";
                }
                for ($i = 0; $i < @stuff; $i++) {
                        my $chosen = $chosen[$i] ? '*' : ' ';
@@ -304,7 +363,7 @@ sub list_and_choose {
 
                return if ($opts->{LIST_ONLY});
 
-               print $opts->{PROMPT};
+               print colored $prompt_color, $opts->{PROMPT};
                if ($opts->{SINGLETON}) {
                        print "> ";
                }
@@ -371,7 +430,7 @@ sub list_and_choose {
 }
 
 sub singleton_prompt_help_cmd {
-       print <<\EOF ;
+       print colored $help_color, <<\EOF ;
 Prompt help:
 1          - select a numbered item
 foo        - select item based on unique prefix
@@ -380,7 +439,7 @@ sub singleton_prompt_help_cmd {
 }
 
 sub prompt_help_cmd {
-       print <<\EOF ;
+       print colored $help_color, <<\EOF ;
 Prompt help:
 1          - select a single item
 3-5        - select a range of items
@@ -477,6 +536,31 @@ sub parse_diff {
        return @hunk;
 }
 
+sub colored_diff_hunk {
+       my ($text) = @_;
+       # return the text, so that it can be passed to print()
+       my @ret;
+       for (@$text) {
+               if (!$diff_use_color) {
+                       push @ret, $_;
+                       next;
+               }
+
+               if (/^\+/) {
+                       push @ret, colored($new_color, $_);
+               } elsif (/^\-/) {
+                       push @ret, colored($old_color, $_);
+               } elsif (/^\@/) {
+                       push @ret, colored($fraginfo_color, $_);
+               } elsif (/^ /) {
+                       push @ret, colored($normal_color, $_);
+               } else {
+                       push @ret, colored($metainfo_color, $_);
+               }
+       }
+       return @ret;
+}
+
 sub hunk_splittable {
        my ($text) = @_;
 
@@ -671,7 +755,7 @@ sub coalesce_overlapping_hunks {
 }
 
 sub help_patch_cmd {
-       print <<\EOF ;
+       print colored $help_color, <<\EOF ;
 y - stage this hunk
 n - do not stage this hunk
 a - stage this and all the remaining hunks in the file
@@ -710,9 +794,7 @@ sub patch_update_file {
        my ($ix, $num);
        my $path = shift;
        my ($head, @hunk) = parse_diff($path);
-       for (@{$head->{TEXT}}) {
-               print;
-       }
+       print colored_diff_hunk($head->{TEXT});
        $num = scalar @hunk;
        $ix = 0;
 
@@ -754,10 +836,8 @@ sub patch_update_file {
                if (hunk_splittable($hunk[$ix]{TEXT})) {
                        $other .= '/s';
                }
-               for (@{$hunk[$ix]{TEXT}}) {
-                       print;
-               }
-               print "Stage this hunk [y/n/a/d$other/?]? ";
+               print colored_diff_hunk($hunk[$ix]{TEXT});
+               print colored $prompt_color, "Stage this hunk [y/n/a/d$other/?]? ";
                my $line = <STDIN>;
                if ($line) {
                        if ($line =~ /^y/i) {
@@ -811,7 +891,7 @@ sub patch_update_file {
                        elsif ($other =~ /s/ && $line =~ /^s/) {
                                my @split = split_hunk($hunk[$ix]{TEXT});
                                if (1 < @split) {
-                                       print "Split into ",
+                                       print colored $header_color, "Split into ",
                                        scalar(@split), " hunks.\n";
                                }
                                splice(@hunk, $ix, 1,
@@ -894,8 +974,7 @@ sub diff_cmd {
                                     HEADER => $status_head, },
                                   @mods);
        return if (!@them);
-       system(qw(git diff-index -p --cached HEAD --),
-              map { $_->{VALUE} } @them);
+       system(qw(git diff -p --cached HEAD --), map { $_->{VALUE} } @them);
 }
 
 sub quit_cmd {
@@ -904,7 +983,7 @@ sub quit_cmd {
 }
 
 sub help_cmd {
-       print <<\EOF ;
+       print colored $help_color, <<\EOF ;
 status        - show paths with changes
 update        - add working tree state to the staged set of changes
 revert        - revert staged set of changes back to the HEAD version
index 2e407084260350e7fa56987a7603afdcd00acfb5..65c634f77af98b3598bfb50583de05f0cf5d6eb4 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -117,6 +117,10 @@ It does not apply to blobs recorded in its index."
     unset GITHEAD_$his_tree
 }
 
+reread_subject () {
+       git stripspace <"$1" | sed -e 1q
+}
+
 prec=4
 dotest=.dotest sign= utf8=t keep= skip= interactive= resolved= binary=
 resolvemsg= resume=
@@ -307,9 +311,9 @@ do
        GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$dotest/info")"
        GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$dotest/info")"
 
-       if test -z "$GIT_AUTHOR_EMAIL" || test -z "$GIT_AUTHOR_DATE"
+       if test -z "$GIT_AUTHOR_EMAIL"
        then
-               echo "Patch does not have valid authorship information."
+               echo "Patch does not have a valid e-mail address."
                stop_here $this
        fi
 
@@ -376,6 +380,7 @@ do
                [aA]*) action=yes interactive= ;;
                [nN]*) action=skip ;;
                [eE]*) git_editor "$dotest/final-commit"
+                      SUBJECT=$(reread_subject "$dotest/final-commit")
                       action=again ;;
                [vV]*) action=again
                       LESS=-S ${PAGER:-less} "$dotest/patch" ;;
diff --git a/ident.c b/ident.c
index 07b4998f71670f17d4972f8e7940d18091f56921..7631698f27a8e1685614c233037eb067eef65168 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -175,7 +175,7 @@ static const char *env_hint =
 "\n"
 "Run\n"
 "\n"
-"  git config --global user.email \"you@email.com\"\n"
+"  git config --global user.email \"you@example.com\"\n"
 "  git config --global user.name \"Your Name\"\n"
 "\n"
 "to set your account\'s default identity.\n"
index 7468460f9a6d29d5c4bf14db4921bf28e23b6814..a2812ea612b997c1a76d89075dd1263a3af4fd37 100644 (file)
@@ -581,6 +581,41 @@ sub config_int {
        };
 }
 
+=item get_colorbool ( NAME )
+
+Finds if color should be used for NAMEd operation from the configuration,
+and returns boolean (true for "use color", false for "do not use color").
+
+=cut
+
+sub get_colorbool {
+       my ($self, $var) = @_;
+       my $stdout_to_tty = (-t STDOUT) ? "true" : "false";
+       my $use_color = $self->command_oneline('config', '--get-colorbool',
+                                              $var, $stdout_to_tty);
+       return ($use_color eq 'true');
+}
+
+=item get_color ( SLOT, COLOR )
+
+Finds color for SLOT from the configuration, while defaulting to COLOR,
+and returns the ANSI color escape sequence:
+
+       print $repo->get_color("color.interactive.prompt", "underline blue white");
+       print "some text";
+       print $repo->get_color("", "normal");
+
+=cut
+
+sub get_color {
+       my ($self, $slot, $default) = @_;
+       my $color = $self->command_oneline('config', '--get-color', $slot, $default);
+       if (!defined $color) {
+               $color = "";
+       }
+       return $color;
+}
+
 =item ident ( TYPE | IDENTSTR )
 
 =item ident_person ( TYPE | IDENTSTR | IDENTARRAY )
diff --git a/setup.c b/setup.c
index 2c7b5cb200414a0fa3f2727c68ea60e51b39c261..e96a316452197ed4b224f0c6839f036a01082bc2 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -222,6 +222,22 @@ void setup_work_tree(void)
        initialized = 1;
 }
 
+static int check_repository_format_gently(int *nongit_ok)
+{
+       git_config(check_repository_format_version);
+       if (GIT_REPO_VERSION < repository_format_version) {
+               if (!nongit_ok)
+                       die ("Expected git repo version <= %d, found %d",
+                            GIT_REPO_VERSION, repository_format_version);
+               warning("Expected git repo version <= %d, found %d",
+                       GIT_REPO_VERSION, repository_format_version);
+               warning("Please upgrade Git");
+               *nongit_ok = -1;
+               return -1;
+       }
+       return 0;
+}
+
 /*
  * We cannot decide in this function whether we are in the work tree or
  * not, since the config can only be read _after_ this function was called.
@@ -246,8 +262,15 @@ const char *setup_git_directory_gently(int *nongit_ok)
                        static char buffer[1024 + 1];
                        const char *retval;
 
-                       if (!work_tree_env)
-                               return set_work_tree(gitdirenv);
+                       if (!work_tree_env) {
+                               retval = set_work_tree(gitdirenv);
+                               /* config may override worktree */
+                               if (check_repository_format_gently(nongit_ok))
+                                       return NULL;
+                               return retval;
+                       }
+                       if (check_repository_format_gently(nongit_ok))
+                               return NULL;
                        retval = get_relative_cwd(buffer, sizeof(buffer) - 1,
                                        get_git_work_tree());
                        if (!retval || !*retval)
@@ -286,6 +309,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
                        if (!work_tree_env)
                                inside_work_tree = 0;
                        setenv(GIT_DIR_ENVIRONMENT, ".", 1);
+                       check_repository_format_gently(nongit_ok);
                        return NULL;
                }
                chdir("..");
@@ -306,6 +330,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
        if (!work_tree_env)
                inside_work_tree = 1;
        git_work_tree_cfg = xstrndup(cwd, offset);
+       if (check_repository_format_gently(nongit_ok))
+               return NULL;
        if (offset == len)
                return NULL;
 
@@ -356,11 +382,7 @@ int check_repository_format_version(const char *var, const char *value)
 
 int check_repository_format(void)
 {
-       git_config(check_repository_format_version);
-       if (GIT_REPO_VERSION < repository_format_version)
-               die ("Expected git repo version <= %d, found %d",
-                    GIT_REPO_VERSION, repository_format_version);
-       return 0;
+       return check_repository_format_gently(NULL);
 }
 
 const char *setup_git_directory(void)
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
new file mode 100755 (executable)
index 0000000..37fc1c8
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Nguyễn Thái Ngọc Duy
+#
+
+test_description='Test repository version check'
+
+. ./test-lib.sh
+
+cat >test.patch <<EOF
+diff --git a/test.txt b/test.txt
+new file mode 100644
+--- /dev/null
++++ b/test.txt
+@@ -0,0 +1 @@
++123
+EOF
+
+test_create_repo "test"
+test_create_repo "test2"
+
+GIT_CONFIG=test2/.git/config git config core.repositoryformatversion 99 || exit 1
+
+test_expect_success 'gitdir selection on normal repos' '
+       (test "$(git config core.repositoryformatversion)" = 0 &&
+       cd test &&
+       test "$(git config core.repositoryformatversion)" = 0)'
+
+# Make sure it would stop at test2, not trash
+test_expect_success 'gitdir selection on unsupported repo' '
+       (cd test2 &&
+       test "$(git config core.repositoryformatversion)" = 99)'
+
+test_expect_success 'gitdir not required mode' '
+       (git apply --stat test.patch &&
+       cd test && git apply --stat ../test.patch &&
+       cd ../test2 && git apply --stat ../test.patch)'
+
+test_expect_success 'gitdir required mode on normal repos' '
+       (git apply --check --index test.patch &&
+       cd test && git apply --check --index ../test.patch)'
+
+test_expect_failure 'gitdir required mode on unsupported repo' '
+       (cd test2 && git apply --check --index ../test.patch)'
+
+test_done
index c722635050fed8011c04177dc5a8220cae12a843..8a23aaf21b1977fab66aa2989cac56635251ecb6 100755 (executable)
@@ -169,5 +169,44 @@ test_expect_success 'Verify descending sort' '
        git diff expected actual
 '
 
+cat >expected <<\EOF
+'refs/heads/master'
+'refs/tags/testtag'
+EOF
+
+test_expect_success 'Quoting style: shell' '
+       git for-each-ref --shell --format="%(refname)" >actual &&
+       git diff expected actual
+'
+
+test_expect_success 'Quoting style: perl' '
+       git for-each-ref --perl --format="%(refname)" >actual &&
+       git diff expected actual
+'
+
+test_expect_success 'Quoting style: python' '
+       git for-each-ref --python --format="%(refname)" >actual &&
+       git diff expected actual
+'
+
+cat >expected <<\EOF
+"refs/heads/master"
+"refs/tags/testtag"
+EOF
+
+test_expect_success 'Quoting style: tcl' '
+       git for-each-ref --tcl --format="%(refname)" >actual &&
+       git diff expected actual
+'
+
+for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
+       test_expect_success "more than one quoting style: $i" "
+               git for-each-ref $i 2>&1 | (read line &&
+               case \$line in
+               \"error: more than one quoting style\"*) : happy;;
+               *) false
+               esac)
+       "
+done
 
 test_done
index f013c176ed910d278cbb886004429869f288ebc7..dfd118878fd37c096ccd426aa01fa2ac36581367 100755 (executable)
@@ -126,6 +126,20 @@ test_expect_success 'git-clean symbolic link' '
 
 '
 
+test_expect_success 'git-clean with wildcard' '
+
+       touch a.clean b.clean other.c &&
+       git-clean "*.clean" &&
+       test -f Makefile &&
+       test -f README &&
+       test -f src/part1.c &&
+       test -f src/part2.c &&
+       test ! -f a.clean &&
+       test ! -f b.clean &&
+       test -f other.c
+
+'
+
 test_expect_success 'git-clean -n' '
 
        mkdir -p build docs &&
index 3eb93b4875ed0e4884088565a0faa45cc3d287e3..58e66f6c11798dac416941ce5ad3dbae91c31a06 100644 (file)
@@ -659,7 +659,7 @@ static int fetch_refs_via_pack(struct transport *transport,
        free(heads);
        free_refs(refs);
        free(dest);
-       return 0;
+       return (refs ? 0 : -1);
 }
 
 static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
index d35386dae19287a28ef7086d886bdfb3941d18b1..02dbb751db86b1c10a018cfb234f267e22d73894 100644 (file)
@@ -391,7 +391,7 @@ void wt_status_print(struct wt_status *s)
 int git_status_config(const char *k, const char *v)
 {
        if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
-               wt_status_use_color = git_config_colorbool(k, v);
+               wt_status_use_color = git_config_colorbool(k, v, -1);
                return 0;
        }
        if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) {