diff options
-rw-r--r-- | Documentation/Makefile | 9 | ||||
-rw-r--r-- | Documentation/SubmittingPatches | 2 | ||||
-rw-r--r-- | Documentation/config.txt | 26 | ||||
-rw-r--r-- | Documentation/diff-format.txt | 159 | ||||
-rw-r--r-- | Documentation/diff-generate-patch.txt | 161 | ||||
-rw-r--r-- | Documentation/diff-options.txt | 2 | ||||
-rw-r--r-- | Documentation/git-add.txt | 2 | ||||
-rw-r--r-- | Documentation/git-config.txt | 10 | ||||
-rw-r--r-- | Documentation/git-log.txt | 7 | ||||
-rw-r--r-- | Documentation/git-status.txt | 4 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | builtin-branch.c | 2 | ||||
-rw-r--r-- | builtin-clean.c | 52 | ||||
-rw-r--r-- | builtin-config.c | 58 | ||||
-rw-r--r-- | builtin-for-each-ref.c | 6 | ||||
-rw-r--r-- | builtin-grep.c | 12 | ||||
-rw-r--r-- | color.c | 6 | ||||
-rw-r--r-- | color.h | 2 | ||||
-rw-r--r-- | config.mak.in | 1 | ||||
-rw-r--r-- | configure.ac | 22 | ||||
-rwxr-xr-x | contrib/hg-to-git/hg-to-git.py | 2 | ||||
-rw-r--r-- | diff.c | 2 | ||||
-rwxr-xr-x | git-add--interactive.perl | 119 | ||||
-rwxr-xr-x | git-am.sh | 9 | ||||
-rw-r--r-- | ident.c | 2 | ||||
-rw-r--r-- | perl/Git.pm | 35 | ||||
-rw-r--r-- | setup.c | 36 | ||||
-rwxr-xr-x | t/t1302-repo-version.sh | 46 | ||||
-rwxr-xr-x | t/t6300-for-each-ref.sh | 39 | ||||
-rwxr-xr-x | t/t7300-clean.sh | 14 | ||||
-rw-r--r-- | transport.c | 2 | ||||
-rw-r--r-- | wt-status.c | 2 |
32 files changed, 610 insertions, 245 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile index 16ee0d3972..1b5802456d 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -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+ diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 83bf54c7ac..de08d094e3 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -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 diff --git a/Documentation/config.txt b/Documentation/config.txt index 72a33e98b2..736fcd71cc 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -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>:: diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index 9709c35c98..2c3a4c433b 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -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 index 0000000000..029c5f2b82 --- /dev/null +++ b/Documentation/diff-generate-patch.txt @@ -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"). diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index e4af393515..d0154bbc0a 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -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[] diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index e74f83b47a..bf94cd43bd 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -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 diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 7640450787..98509b4f44 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -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 diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 5ec547cc0c..5920d1799a 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -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 -------- diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index 8fd0fc6236..b0cb6bc8b7 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -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 ------------- @@ -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 diff --git a/builtin-branch.c b/builtin-branch.c index c64768beb2..089cae5929 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -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.")) { diff --git a/builtin-clean.c b/builtin-clean.c index 56ae4eb9bb..ae30d4e76c 100644 --- a/builtin-clean.c +++ b/builtin-clean.c @@ -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; diff --git a/builtin-config.c b/builtin-config.c index 4c9ded3b1a..e4a12e3166 100644 --- a/builtin-config.c +++ b/builtin-config.c @@ -3,7 +3,7 @@ #include "color.h" static const char git_config_set_usage[] = -"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int ] [ -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--; diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index daf3a08165..f36a43c264 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -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)) diff --git a/builtin-grep.c b/builtin-grep.c index bbf747fc7b..f1ff8dc556 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -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++; @@ -116,7 +116,7 @@ bad: 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; @@ -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, ...); diff --git a/config.mak.in b/config.mak.in index 11d256e9cf..7d5df9bf3c 100644 --- a/config.mak.in +++ b/config.mak.in @@ -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@ diff --git a/configure.ac b/configure.ac index 5f8a15b9f9..dd4b4eb982 100644 --- a/configure.ac +++ b/configure.ac @@ -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. diff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py index 7a1c3e497f..9befb92c41 100755 --- a/contrib/hg-to-git/hg-to-git.py +++ b/contrib/hg-to-git/hg-to-git.py @@ -211,7 +211,7 @@ for cset in range(int(tip) + 1): 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 @@ -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")) { diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 335c2c6b56..1019a72d6c 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -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 @@ EOF } 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 @@ -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" ;; @@ -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" diff --git a/perl/Git.pm b/perl/Git.pm index 7468460f9a..a2812ea612 100644 --- a/perl/Git.pm +++ b/perl/Git.pm @@ -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 ) @@ -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 index 0000000000..37fc1c8d36 --- /dev/null +++ b/t/t1302-repo-version.sh @@ -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 diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index c722635050..8a23aaf21b 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -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 diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index f013c176ed..dfd118878f 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -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 && diff --git a/transport.c b/transport.c index 3eb93b4875..58e66f6c11 100644 --- a/transport.c +++ b/transport.c @@ -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) diff --git a/wt-status.c b/wt-status.c index d35386dae1..02dbb751db 100644 --- a/wt-status.c +++ b/wt-status.c @@ -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.")) { |