Merge commit 'mingw/master' into work/merge-mingw

This commit is contained in:
Steffen Prohaska
2007-12-28 10:10:45 +01:00
44 changed files with 993 additions and 230 deletions

6
.gitignore vendored
View File

@@ -41,7 +41,6 @@ git-fetch
git-fetch--tool
git-fetch-pack
git-filter-branch
git-findtags
git-fmt-merge-msg
git-for-each-ref
git-format-patch
@@ -59,7 +58,6 @@ git-index-pack
git-init
git-init-db
git-instaweb
git-local-fetch
git-log
git-lost-found
git-ls-files
@@ -120,10 +118,6 @@ git-show
git-show-branch
git-show-index
git-show-ref
git-ssh-fetch
git-ssh-pull
git-ssh-push
git-ssh-upload
git-stash
git-status
git-stripspace

View File

@@ -2,7 +2,7 @@ MAN1_TXT= \
$(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \
$(wildcard git-*.txt)) \
gitk.txt
MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt
MAN5_TXT=gitattributes.txt gitignore.txt gitcli.txt gitmodules.txt
MAN7_TXT=git.txt
MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)

View File

@@ -14,28 +14,28 @@ Removal
Deprecation notices
-------------------
* Next feature release of git (this change is scheduled for v1.6.0)
* The next feature release of git (this change is scheduled for v1.6.0)
will by default install dashed form of commands (e.g. "git-commit")
outside of users' normal $PATH, and will install only selected
commands ("git" itself, and "gitk") in $PATH. This implies:
- Using dashed form of git commands (e.g. "git-commit") from the
- Using dashed forms of git commands (e.g. "git-commit") from the
command line has been informally deprecated since early 2006, but
now it officially is, and will be removed in the future. Use
dashless form (e.g. "git commit") instead.
dashless forms (e.g. "git commit") instead.
- Using dashed from from your scripts, without first prepending the
- Using dashed forms from your scripts, without first prepending the
return value from "git --exec-path" to the scripts' PATH, has been
informally deprecated since early 2006, but now it officially is.
- Use of dashed form with "PATH=$(git --exec-path):$PATH; export
- Use of dashed forms with "PATH=$(git --exec-path):$PATH; export
PATH" early in your script is not deprecated with this change.
Users are strongly encouraged to adjust their habits and scripts now
to prepare for this.
* The post-receive hook was introduced in March 2007 to supersede
post-update hook, primarily to overcome the command line length
the post-update hook, primarily to overcome the command line length
limitation of the latter. Use of post-update hook will be deprecated
in future versions of git, starting from v1.6.0.
@@ -43,10 +43,11 @@ Deprecation notices
option, and will be removed in the future.
* "git peek-remote" is deprecated, as "git ls-remote" was written in C
and works for all transports, and will be removed in the future.
and works for all transports; "git peek-remote" will be removed in
the future.
* From v1.6.0, the repack.usedeltabaseoffset config option will default
to true, which will give denser packfile (i.e. more efficient storage).
to true, which will give denser packfiles (i.e. more efficient storage).
The downside is that git older than version 1.4.4 will not be able
to directly use a repository packed using this setting.
@@ -67,7 +68,7 @@ Updates since v1.5.3
* gitk is now merged as a subdirectory of git.git project, in
preparation for its i18n.
* progress display from many commands are a lot nicer to the eye.
* progress displays from many commands are a lot nicer to the eye.
Transfer commands show throughput data.
* many commands that pay attention to per-directory .gitignore now do
@@ -76,12 +77,12 @@ Updates since v1.5.3
* Output processing for '--pretty=format:<user format>' has been
optimized.
* Rename detection of diff family, while detecting exact matches, has
* Rename detection of diff family while detecting exact matches has
been greatly optimized.
* Rename detection of diff family tries to make more naturally looking
pairing. Earlier if more than one identical rename sources were
found in the preimage, they were picked pretty much at random.
* Rename detection of diff family tries to make more natural looking
pairing. Earlier, if multiple identical rename sources were
found in the preimage, the source used was picked pretty much at random.
* Value "true" for color.diff and color.status configuration used to
mean "always" (even when the output is not going to a terminal).
@@ -90,6 +91,16 @@ Updates since v1.5.3
* "git diff" Porcelain now respects diff.external configuration, which
is another way to specify GIT_EXTERNAL_DIFF.
* "git diff" can be told to use different prefixes other than
"a/" and "b/" e.g. "git diff --src-prefix=l/ --dst-prefix=k/".
* "git diff" sometimes did not quote paths with funny
characters properly.
* "git log" (and any revision traversal commands) misbehaved
when --diff-filter is given but was not asked to actually
produce diff.
* HTTP proxy can be specified per remote repository using
remote.*.httpproxy configuration, or global http.proxy configuration
variable.
@@ -114,7 +125,7 @@ Updates since v1.5.3
* "git rebase --interactive" mode can now work on detached HEAD.
* Other minor to serious bugs in "git rebase -i" has been fixed.
* Other minor to serious bugs in "git rebase -i" have been fixed.
* "git rebase" now detaches head during its operation, so after a
successful "git rebase" operation, the reflog entry branch@{1} for
@@ -175,7 +186,9 @@ Updates since v1.5.3
* "git remote" learned "rm" subcommand.
* "git cvsserver" can be run via "git shell".
* "git cvsserver" can be run via "git shell". Also, "cvs" is
recognized as a synonym for "git cvsserver", so that CVS users
can be switched to git just by changing their login shell.
* "git cvsserver" acts more like receive-pack by running post-receive
and post-update hooks.
@@ -205,6 +218,10 @@ Updates since v1.5.3
* "git commit --amend" can amend a merge that does not change the tree
from its first parent.
* "git commit" used to unconditionally strip comment lines that
began with '#' and removed excess blank lines. This
behaviour has been made configurable.
* "git commit" has been rewritten in C.
* "git stash random-text" does not create a new stash anymore. It was
@@ -245,9 +262,12 @@ Updates since v1.5.3
* The format "git show" outputs an annotated tag has been updated to
include "Tagger: " and "Date: " lines from the tag itself. Strictly
speaking this is a backward incompatible change, but this is a
reasonable usability fix and people's script shouldn't have been
reasonable usability fix and people's scripts shouldn't have been
relying on the exact output from "git show" Porcelain anyway.
* "git cvsimport" did not notice errors from underlying "cvsps"
and produced a corrupt import silently.
* "git cvsexportcommit" learned -w option to specify and switch to the
CVS working directory.
@@ -281,7 +301,7 @@ Updates since v1.5.3
makes copy-and-pasting for git-checkout/git-add/git-rm easier. The
traditional behaviour to show the full path relative to the top of
the work tree can be had by setting status.relativepaths
configuration variable to true.
configuration variable to false.
* "git blame" kept text for each annotated revision in core needlessly;
this has been corrected.
@@ -324,6 +344,6 @@ series.
--
exec >/var/tmp/1
O=v1.5.4-rc0-85-gdbedf97
O=v1.5.4-rc1-36-g49e6be5
echo O=`git describe refs/heads/master`
git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint

View File

@@ -211,5 +211,14 @@ endif::git-format-patch[]
--no-ext-diff::
Disallow external diff drivers.
--src-prefix=<prefix>::
Show the given source prefix instead of "a/".
--dst-prefix=<prefix>::
Show the given destination prefix instead of "b/".
--no-prefix::
Do not show any source or destination prefix.
For more detailed explanation on these common options, see also
link:diffcore.html[diffcore documentation].

View File

@@ -30,10 +30,6 @@ Everybody uses these commands to maintain git repositories.
* gitlink:git-fsck[1] to check the repository for errors.
* gitlink:git-prune[1] to remove unused objects in the repository.
* gitlink:git-repack[1] to pack loose objects for efficiency.
* gitlink:git-gc[1] to do common housekeeping tasks such as
repack and prune.
@@ -45,24 +41,21 @@ Check health and remove cruft.::
------------
$ git fsck <1>
$ git count-objects <2>
$ git repack <3>
$ git gc <4>
$ git gc <3>
------------
+
<1> running without `\--full` is usually cheap and assures the
repository health reasonably well.
<2> check how many loose objects there are and how much
disk space is wasted by not repacking.
<3> without `-a` repacks incrementally. repacking every 4-5MB
of loose objects accumulation may be a good rule of thumb.
<4> it is easier to use `git gc` than individual housekeeping commands
such as `prune` and `repack`. This runs `repack -a -d`.
<3> repacks the local repository and performs other housekeeping tasks. Running
without `--prune` is a safe operation even while other ones are in progress.
Repack a small project into single pack.::
+
------------
$ git repack -a -d <1>
$ git prune
$ git gc <1>
$ git gc --prune
------------
+
<1> pack all the objects reachable from the refs into one pack,
@@ -189,7 +182,7 @@ $ git pull <3>
$ git log -p ORIG_HEAD.. arch/i386 include/asm-i386 <4>
$ git pull git://git.kernel.org/pub/.../jgarzik/libata-dev.git ALL <5>
$ git reset --hard ORIG_HEAD <6>
$ git prune <7>
$ git gc --prune <7>
$ git fetch --tags <8>
------------
+

View File

@@ -23,6 +23,11 @@ OPTIONS
be treated as an attribute.
SEE ALSO
--------
gitlink:gitattributes[5].
Author
------
Written by Junio C Hamano <junkio@cox.net>

View File

@@ -11,7 +11,7 @@ SYNOPSIS
'git-commit' [-a | --interactive] [-s] [-v] [-u]
[(-c | -C) <commit> | -F <file> | -m <msg> | --amend]
[--allow-empty] [--no-verify] [-e] [--author <author>]
[--] [[-i | -o ]<file>...]
[--cleanup=<mode>] [--] [[-i | -o ]<file>...]
DESCRIPTION
-----------
@@ -95,6 +95,16 @@ OPTIONS
from making such a commit. This option bypasses the safety, and
is primarily for use by foreign scm interface scripts.
--cleanup=<mode>::
This option sets how the commit message is cleaned up.
The '<mode>' can be one of 'verbatim', 'whitespace', 'strip',
and 'default'. The 'default' mode will strip leading and
trailing empty lines and #commentary from the commit message
only if the message is to be edited. Otherwise only whitespace
removed. The 'verbatim' mode does not change message at all,
'whitespace' removes just leading/trailing whitespace lines
and 'strip' removes both whitespace and commentary.
-e|--edit::
The message taken from file with `-F`, command line with
`-m`, and from file with `-C` are usually used as the

View File

@@ -43,8 +43,12 @@ include::diff-options.txt[]
--first-parent::
Follow only the first parent commit upon seeing a merge
commit. This option gives a better overview of the
evolution of a particular branch.
commit. This option can give a better overview when
viewing the evolution of a particular topic branch,
because merges into a topic branch tend to be only about
adjusting to updated upstream from time to time, and
this option allows you to ignore the individual commits
brought in to your history by such a merge.
-g, \--walk-reflogs::
Show commits as they were recorded in the reflog. The log contains

View File

@@ -105,7 +105,8 @@ OPTIONS
-v::
Similar to `-t`, but use lowercase letters for files
that are marked as 'always matching index'.
that are marked as 'assume unchanged' (see
gitlink:git-update-index[1]).
--full-name::
When run from a subdirectory, the command usually

View File

@@ -163,7 +163,8 @@ After seeing a conflict, you can do two things:
SEE ALSO
--------
gitlink:git-fmt-merge-msg[1], gitlink:git-pull[1]
gitlink:git-fmt-merge-msg[1], gitlink:git-pull[1],
gitlink:gitattributes[5]
Author

View File

@@ -15,6 +15,7 @@ SYNOPSIS
[ \--min-age=timestamp ]
[ \--sparse ]
[ \--no-merges ]
[ \--first-parent ]
[ \--remove-empty ]
[ \--full-history ]
[ \--not ]
@@ -256,6 +257,15 @@ limiting may be applied.
Do not print commits with more than one parent.
--first-parent::
Follow only the first parent commit upon seeing a merge
commit. This option can give a better overview when
viewing the evolution of a particular topic branch,
because merges into a topic branch tend to be only about
adjusting to updated upstream from time to time, and
this option allows you to ignore the individual commits
brought in to your history by such a merge.
--not::
Reverses the meaning of the '{caret}' prefix (or lack thereof)

View File

@@ -38,15 +38,16 @@ OPTIONS
FILES
-----
.mailmap::
If this file exists, it will be used for mapping author email
addresses to a real author name. One mapping per line, first
the author name followed by the email address enclosed by
'<' and '>'. Use hash '#' for comments. Example:
If the file `.mailmap` exists, it will be used for mapping author
email addresses to a real author name. One mapping per line, first
the author name followed by the email address enclosed by
'<' and '>'. Use hash '#' for comments. Example:
# Keep alphabetized
Adam Morrow <adam@localhost.localdomain>
Eve Jones <eve@laptop.(none)>
------------
# Keep alphabetized
Adam Morrow <adam@localhost.localdomain>
Eve Jones <eve@laptop.(none)>
------------
Author
------

View File

@@ -322,12 +322,43 @@ String::
requested with "binary".
Built-in merge drivers
^^^^^^^^^^^^^^^^^^^^^^
There are a few built-in low-level merge drivers defined that
can be asked for via the `merge` attribute.
text::
Usual 3-way file level merge for text files. Conflicted
regions are marked with conflict markers `<<<<<<<`,
`=======` and `>>>>>>>`. The version from your branch
appears before the `=======` marker, and the version
from the merged branch appears after the `=======`
marker.
binary::
Keep the version from your branch in the work tree, but
leave the path in the conflicted state for the user to
sort out.
union::
Run 3-way file level merge for text files, but take
lines from both versions, instead of leaving conflict
markers. This tends to leave the added lines in the
resulting file in random order and the user should
verify the result. Do not use this if you do not
understand the implications.
Defining a custom merge driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The definition of a merge driver is done in `gitconfig` not
`gitattributes` file, so strictly speaking this manual page is a
wrong place to talk about it. However...
The definition of a merge driver is done in the `.git/config`
file, not in the `gitattributes` file, so strictly speaking this
manual page is a wrong place to talk about it. However...
To define a custom merge driver `filfre`, add a section to your
`$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this:

113
Documentation/gitcli.txt Normal file
View File

@@ -0,0 +1,113 @@
gitcli(5)
=========
NAME
----
gitcli - git command line interface and conventions
SYNOPSIS
--------
gitcli
DESCRIPTION
-----------
This manual describes best practice in how to use git CLI. Here are
the rules that you should follow when you are scripting git:
* it's preferred to use the non dashed form of git commands, which means that
you should prefer `"git foo"` to `"git-foo"`.
* splitting short options to separate words (prefer `"git foo -a -b"`
to `"git foo -ab"`, the latter may not even work).
* when a command line option takes an argument, use the 'sticked' form. In
other words, write `"git foo -oArg"` instead of `"git foo -o Arg"` for short
options, and `"git foo --long-opt=Arg"` instead of `"git foo --long-opt Arg"`
for long options. An option that takes optional option-argument must be
written in the 'sticked' form.
* when you give a revision parameter to a command, make sure the parameter is
not ambiguous with a name of a file in the work tree. E.g. do not write
`"git log -1 HEAD"` but write `"git log -1 HEAD --"`; the former will not work
if you happen to have a file called `HEAD` in the work tree.
ENHANCED CLI
------------
From the git 1.5.4 series and further, many git commands (not all of them at the
time of the writing though) come with an enhanced option parser.
Here is an exhaustive list of the facilities provided by this option parser.
Magic Options
~~~~~~~~~~~~~
Commands which have the enhanced option parser activated all understand a
couple of magic command line options:
-h::
gives a pretty printed usage of the command.
+
---------------------------------------------
$ git describe -h
usage: git-describe [options] <committish>*
--contains find the tag that comes after the commit
--debug debug search strategy on stderr
--all use any ref in .git/refs
--tags use any tag in .git/refs/tags
--abbrev [<n>] use <n> digits to display SHA-1s
--candidates <n> consider <n> most recent tags (default: 10)
---------------------------------------------
--help-all::
Some git commands take options that are only used for plumbing or that
are deprecated, and such options are hidden from the default usage. This
option gives the full list of options.
Negating options
~~~~~~~~~~~~~~~~
Options with long option names can be negated by prefixing `"--no-"`. For
example, `"git branch"` has the option `"--track"` which is 'on' by default. You
can use `"--no-track"` to override that behaviour. The same goes for `"--color"`
and `"--no-color"`.
Aggregating short options
~~~~~~~~~~~~~~~~~~~~~~~~~
Commands that support the enhanced option parser allow you to aggregate short
options. This means that you can for example use `"git rm -rf"` or
`"git clean -fdx"`.
Separating argument from the option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can write the mandatory option parameter to an option as a separate
word on the command line. That means that all the following uses work:
----------------------------
$ git foo --long-opt=Arg
$ git foo --long-opt Arg
$ git foo -oArg
$ git foo -o Arg
----------------------------
However, this is *NOT* allowed for switches with an optionnal value, where the
'sticked' form must be used:
----------------------------
$ git describe --abbrev HEAD # correct
$ git describe --abbrev=10 HEAD # correct
$ git describe --abbrev 10 HEAD # NOT WHAT YOU MEANT
----------------------------
Documentation
-------------
Documentation by Pierre Habouzit.
GIT
---
Part of the gitlink:git[7] suite

View File

@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=v1.5.4-rc1.GIT
DEF_VER=v1.5.4-rc2.GIT
LF='
'

View File

@@ -1219,6 +1219,7 @@ check-docs::
documented,gitattributes | \
documented,gitignore | \
documented,gitmodules | \
documented,gitcli | \
documented,git-tools | \
sentinel,not,matching,is,ok ) continue ;; \
esac; \

View File

@@ -47,8 +47,21 @@ static char *logfile, *force_author, *template_file;
static char *edit_message, *use_message;
static int all, edit_flag, also, interactive, only, amend, signoff;
static int quiet, verbose, untracked_files, no_verify, allow_empty;
/*
* The default commit message cleanup mode will remove the lines
* beginning with # (shell comments) and leading and trailing
* whitespaces (empty lines or containing only whitespaces)
* if editor is used, and only the whitespaces if the message
* is specified explicitly.
*/
static enum {
CLEANUP_SPACE,
CLEANUP_NONE,
CLEANUP_ALL,
} cleanup_mode;
static char *cleanup_arg;
static int no_edit, initial_commit, in_merge;
static int use_editor = 1, initial_commit, in_merge;
const char *only_include_assumed;
struct strbuf message;
@@ -88,6 +101,7 @@ static struct option builtin_commit_options[] = {
OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
OPT_BOOLEAN(0, "untracked-files", &untracked_files, "show all untracked files"),
OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
OPT_END()
};
@@ -346,7 +360,8 @@ static int prepare_log_message(const char *index_file, const char *prefix)
if (fp == NULL)
die("could not open %s", git_path(commit_editmsg));
stripspace(&sb, 0);
if (cleanup_mode != CLEANUP_NONE)
stripspace(&sb, 0);
if (signoff) {
struct strbuf sob;
@@ -372,21 +387,25 @@ static int prepare_log_message(const char *index_file, const char *prefix)
strbuf_release(&sb);
if (no_edit) {
if (!use_editor) {
struct rev_info rev;
unsigned char sha1[40];
unsigned char sha1[20];
const char *parent = "HEAD";
fclose(fp);
if (!active_nr && read_cache() < 0)
die("Cannot read index");
if (get_sha1("HEAD", sha1) != 0)
if (amend)
parent = "HEAD^1";
if (get_sha1(parent, sha1))
return !!active_nr;
init_revisions(&rev, "");
rev.abbrev = 0;
setup_revisions(0, NULL, &rev, "HEAD");
setup_revisions(0, NULL, &rev, parent);
DIFF_OPT_SET(&rev.diffopt, QUIET);
DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
run_diff_index(&rev, 1 /* cached */);
@@ -394,7 +413,7 @@ static int prepare_log_message(const char *index_file, const char *prefix)
return !!DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES);
}
if (in_merge && !no_edit)
if (in_merge)
fprintf(fp,
"#\n"
"# It looks like you may be committing a MERGE.\n"
@@ -407,7 +426,12 @@ static int prepare_log_message(const char *index_file, const char *prefix)
fprintf(fp,
"\n"
"# Please enter the commit message for your changes.\n"
"# (Comment lines starting with '#' will not be included)\n");
"# (Comment lines starting with '#' will ");
if (cleanup_mode == CLEANUP_ALL)
fprintf(fp, "not be included)\n");
else /* CLEANUP_SPACE, that is. */
fprintf(fp, "be kept.\n"
"# You can remove them yourself if you want to)\n");
if (only_include_assumed)
fprintf(fp, "# %s\n", only_include_assumed);
@@ -431,10 +455,13 @@ static int message_is_empty(struct strbuf *sb, int start)
const char *nl;
int eol, i;
if (cleanup_mode == CLEANUP_NONE && sb->len)
return 0;
/* See if the template is just a prefix of the message. */
strbuf_init(&tmpl, 0);
if (template_file && strbuf_read_file(&tmpl, template_file, 0) > 0) {
stripspace(&tmpl, 1);
stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
if (start + tmpl.len <= sb->len &&
memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0)
start += tmpl.len;
@@ -509,9 +536,9 @@ static int parse_and_validate_options(int argc, const char *argv[],
argc = parse_options(argc, argv, builtin_commit_options, usage, 0);
if (logfile || message.len || use_message)
no_edit = 1;
use_editor = 0;
if (edit_flag)
no_edit = 0;
use_editor = 1;
if (get_sha1("HEAD", head_sha1))
initial_commit = 1;
@@ -587,6 +614,16 @@ static int parse_and_validate_options(int argc, const char *argv[],
only_include_assumed = "Explicit paths specified without -i nor -o; assuming --only paths...";
also = 0;
}
if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;
else if (!strcmp(cleanup_arg, "verbatim"))
cleanup_mode = CLEANUP_NONE;
else if (!strcmp(cleanup_arg, "whitespace"))
cleanup_mode = CLEANUP_SPACE;
else if (!strcmp(cleanup_arg, "strip"))
cleanup_mode = CLEANUP_ALL;
else
die("Invalid cleanup mode %s", cleanup_arg);
if (all && argc > 0)
die("Paths with -a does not make sense.");
@@ -792,7 +829,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
/* Get the commit message and validate it */
header_len = sb.len;
if (!no_edit) {
if (use_editor) {
char index[PATH_MAX];
const char *env[2] = { index, NULL };
snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
@@ -813,7 +850,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
if (p != NULL)
strbuf_setlen(&sb, p - sb.buf + 1);
stripspace(&sb, 1);
if (cleanup_mode != CLEANUP_NONE)
stripspace(&sb, cleanup_mode == CLEANUP_ALL);
if (sb.len < header_len || message_is_empty(&sb, header_len)) {
rollback_index_files();
die("no commit message? aborting commit.");

View File

@@ -95,8 +95,6 @@ static int handle_line(char *line)
return 3;
if (line[len - 1] == '\n')
line[len - 1] = 0, --len;
if (line[len - 1] == '\r')
line[len - 1] = 0;
line += 42;

View File

@@ -16,7 +16,7 @@
static const char * const git_tag_usage[] = {
"git-tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
"git-tag -d <tagname>...",
"git-tag [-n [<num>]] -l [<pattern>]",
"git-tag -l [-n [<num>]] [<pattern>]",
"git-tag -v <tagname>...",
NULL
};
@@ -47,7 +47,19 @@ void launch_editor(const char *path, struct strbuf *buffer, const char *const *e
editor = "vi";
if (strcmp(editor, ":")) {
const char *args[] = { editor, path, NULL };
size_t len = strlen(editor);
int i = 0;
const char *args[6];
if (strcspn(editor, "$ \t'") != len) {
/* there are specials */
args[i++] = "sh";
args[i++] = "-c";
args[i++] = "$0 \"$@\"";
}
args[i++] = editor;
args[i++] = path;
args[i] = NULL;
if (run_command_v_opt_cd_env(args, 0, NULL, env))
die("There was a problem with the editor %s.", editor);
@@ -384,13 +396,11 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
struct ref_lock *lock;
int annotate = 0, sign = 0, force = 0, lines = 0,
delete = 0, verify = 0;
char *list = NULL, *msgfile = NULL, *keyid = NULL;
const char *no_pattern = "NO_PATTERN";
list = 0, delete = 0, verify = 0;
char *msgfile = NULL, *keyid = NULL;
struct msg_arg msg = { 0, STRBUF_INIT };
struct option options[] = {
{ OPTION_STRING, 'l', NULL, &list, "pattern", "list tag names",
PARSE_OPT_OPTARG, NULL, (intptr_t) no_pattern },
OPT_BOOLEAN('l', NULL, &list, "list tag names"),
{ OPTION_INTEGER, 'n', NULL, &lines, NULL,
"print n lines of each tag message",
PARSE_OPT_OPTARG, NULL, 1 },
@@ -422,7 +432,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
annotate = 1;
if (list)
return list_tags(list == no_pattern ? NULL : list, lines);
return list_tags(argv[0], lines);
if (delete)
return for_each_tag_name(argv, delete_tag);
if (verify)

View File

@@ -646,12 +646,19 @@ static void reuse_combine_diff(struct sline *sline, unsigned long cnt,
sline->p_lno[i] = sline->p_lno[j];
}
static void dump_quoted_path(const char *prefix, const char *path,
static void dump_quoted_path(const char *head,
const char *prefix,
const char *path,
const char *c_meta, const char *c_reset)
{
printf("%s%s", c_meta, prefix);
quote_c_style(path, NULL, stdout, 0);
printf("%s\n", c_reset);
static struct strbuf buf = STRBUF_INIT;
strbuf_reset(&buf);
strbuf_addstr(&buf, c_meta);
strbuf_addstr(&buf, head);
quote_two_c_style(&buf, prefix, path, 0);
strbuf_addstr(&buf, c_reset);
puts(buf.buf);
}
static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
@@ -793,7 +800,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
if (rev->loginfo && !rev->no_commit_id)
show_log(rev, opt->msg_sep);
dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
elem->path, c_meta, c_reset);
"", elem->path, c_meta, c_reset);
printf("%sindex ", c_meta);
for (i = 0; i < num_parent; i++) {
abb = find_unique_abbrev(elem->parent[i].sha1,
@@ -829,14 +836,19 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
printf("%s\n", c_reset);
}
if (added)
dump_quoted_path("--- /dev/", "null", c_meta, c_reset);
dump_quoted_path("--- ", "", "/dev/null",
c_meta, c_reset);
else
dump_quoted_path("--- a/", elem->path, c_meta, c_reset);
dump_quoted_path("--- ", opt->a_prefix, elem->path,
c_meta, c_reset);
if (deleted)
dump_quoted_path("+++ /dev/", "null", c_meta, c_reset);
dump_quoted_path("+++ ", "", "/dev/null",
c_meta, c_reset);
else
dump_quoted_path("+++ b/", elem->path, c_meta, c_reset);
dump_sline(sline, cnt, num_parent, DIFF_OPT_TST(opt, COLOR_DIFF));
dump_quoted_path("+++ ", opt->b_prefix, elem->path,
c_meta, c_reset);
dump_sline(sline, cnt, num_parent,
DIFF_OPT_TST(opt, COLOR_DIFF));
}
free(result);

View File

@@ -234,17 +234,23 @@ static int git_parse_file(config_fn_t fn)
die("bad config file line %d in %s", config_linenr, config_file_name);
}
static unsigned long get_unit_factor(const char *end)
static int parse_unit_factor(const char *end, unsigned long *val)
{
if (!*end)
return 1;
else if (!strcasecmp(end, "k"))
return 1024;
else if (!strcasecmp(end, "m"))
return 1024 * 1024;
else if (!strcasecmp(end, "g"))
return 1024 * 1024 * 1024;
die("unknown unit: '%s'", end);
else if (!strcasecmp(end, "k")) {
*val *= 1024;
return 1;
}
else if (!strcasecmp(end, "m")) {
*val *= 1024 * 1024;
return 1;
}
else if (!strcasecmp(end, "g")) {
*val *= 1024 * 1024 * 1024;
return 1;
}
return 0;
}
int git_parse_long(const char *value, long *ret)
@@ -252,7 +258,10 @@ int git_parse_long(const char *value, long *ret)
if (value && *value) {
char *end;
long val = strtol(value, &end, 0);
*ret = val * get_unit_factor(end);
unsigned long factor = 1;
if (!parse_unit_factor(end, &factor))
return 0;
*ret = val * factor;
return 1;
}
return 0;
@@ -263,7 +272,9 @@ int git_parse_ulong(const char *value, unsigned long *ret)
if (value && *value) {
char *end;
unsigned long val = strtoul(value, &end, 0);
*ret = val * get_unit_factor(end);
if (!parse_unit_factor(end, &val))
return 0;
*ret = val;
return 1;
}
return 0;

197
contrib/examples/git-revert.sh Executable file
View File

@@ -0,0 +1,197 @@
#!/bin/sh
#
# Copyright (c) 2005 Linus Torvalds
# Copyright (c) 2005 Junio C Hamano
#
case "$0" in
*-revert* )
test -t 0 && edit=-e
replay=
me=revert
USAGE='[--edit | --no-edit] [-n] <commit-ish>' ;;
*-cherry-pick* )
replay=t
edit=
me=cherry-pick
USAGE='[--edit] [-n] [-r] [-x] <commit-ish>' ;;
* )
echo >&2 "What are you talking about?"
exit 1 ;;
esac
SUBDIRECTORY_OK=Yes ;# we will cd up
. git-sh-setup
require_work_tree
cd_to_toplevel
no_commit=
while case "$#" in 0) break ;; esac
do
case "$1" in
-n|--n|--no|--no-|--no-c|--no-co|--no-com|--no-comm|\
--no-commi|--no-commit)
no_commit=t
;;
-e|--e|--ed|--edi|--edit)
edit=-e
;;
--n|--no|--no-|--no-e|--no-ed|--no-edi|--no-edit)
edit=
;;
-r)
: no-op ;;
-x|--i-really-want-to-expose-my-private-commit-object-name)
replay=
;;
-*)
usage
;;
*)
break
;;
esac
shift
done
set_reflog_action "$me"
test "$me,$replay" = "revert,t" && usage
case "$no_commit" in
t)
# We do not intend to commit immediately. We just want to
# merge the differences in.
head=$(git-write-tree) ||
die "Your index file is unmerged."
;;
*)
head=$(git-rev-parse --verify HEAD) ||
die "You do not have a valid HEAD"
files=$(git-diff-index --cached --name-only $head) || exit
if [ "$files" ]; then
die "Dirty index: cannot $me (dirty: $files)"
fi
;;
esac
rev=$(git-rev-parse --verify "$@") &&
commit=$(git-rev-parse --verify "$rev^0") ||
die "Not a single commit $@"
prev=$(git-rev-parse --verify "$commit^1" 2>/dev/null) ||
die "Cannot run $me a root commit"
git-rev-parse --verify "$commit^2" >/dev/null 2>&1 &&
die "Cannot run $me a multi-parent commit."
encoding=$(git config i18n.commitencoding || echo UTF-8)
# "commit" is an existing commit. We would want to apply
# the difference it introduces since its first parent "prev"
# on top of the current HEAD if we are cherry-pick. Or the
# reverse of it if we are revert.
case "$me" in
revert)
git show -s --pretty=oneline --encoding="$encoding" $commit |
sed -e '
s/^[^ ]* /Revert "/
s/$/"/
'
echo
echo "This reverts commit $commit."
test "$rev" = "$commit" ||
echo "(original 'git revert' arguments: $@)"
base=$commit next=$prev
;;
cherry-pick)
pick_author_script='
/^author /{
s/'\''/'\''\\'\'\''/g
h
s/^author \([^<]*\) <[^>]*> .*$/\1/
s/'\''/'\''\'\'\''/g
s/.*/GIT_AUTHOR_NAME='\''&'\''/p
g
s/^author [^<]* <\([^>]*\)> .*$/\1/
s/'\''/'\''\'\'\''/g
s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
g
s/^author [^<]* <[^>]*> \(.*\)$/\1/
s/'\''/'\''\'\'\''/g
s/.*/GIT_AUTHOR_DATE='\''&'\''/p
q
}'
logmsg=`git show -s --pretty=raw --encoding="$encoding" "$commit"`
set_author_env=`echo "$logmsg" |
LANG=C LC_ALL=C sed -ne "$pick_author_script"`
eval "$set_author_env"
export GIT_AUTHOR_NAME
export GIT_AUTHOR_EMAIL
export GIT_AUTHOR_DATE
echo "$logmsg" |
sed -e '1,/^$/d' -e 's/^ //'
case "$replay" in
'')
echo "(cherry picked from commit $commit)"
test "$rev" = "$commit" ||
echo "(original 'git cherry-pick' arguments: $@)"
;;
esac
base=$prev next=$commit
;;
esac >.msg
eval GITHEAD_$head=HEAD
eval GITHEAD_$next='`git show -s \
--pretty=oneline --encoding="$encoding" "$commit" |
sed -e "s/^[^ ]* //"`'
export GITHEAD_$head GITHEAD_$next
# This three way merge is an interesting one. We are at
# $head, and would want to apply the change between $commit
# and $prev on top of us (when reverting), or the change between
# $prev and $commit on top of us (when cherry-picking or replaying).
git-merge-recursive $base -- $head $next &&
result=$(git-write-tree 2>/dev/null) || {
mv -f .msg "$GIT_DIR/MERGE_MSG"
{
echo '
Conflicts:
'
git ls-files --unmerged |
sed -e 's/^[^ ]* / /' |
uniq
} >>"$GIT_DIR/MERGE_MSG"
echo >&2 "Automatic $me failed. After resolving the conflicts,"
echo >&2 "mark the corrected paths with 'git-add <paths>'"
echo >&2 "and commit the result."
case "$me" in
cherry-pick)
echo >&2 "You may choose to use the following when making"
echo >&2 "the commit:"
echo >&2 "$set_author_env"
esac
exit 1
}
echo >&2 "Finished one $me."
# If we are cherry-pick, and if the merge did not result in
# hand-editing, we will hit this commit and inherit the original
# author date and name.
# If we are revert, or if our cherry-pick results in a hand merge,
# we had better say that the current user is responsible for that.
case "$no_commit" in
'')
git-commit -n -F .msg $edit
rm -f .msg
;;
esac

31
diff.c
View File

@@ -290,28 +290,35 @@ static void emit_rewrite_diff(const char *name_a,
const char *name_b,
struct diff_filespec *one,
struct diff_filespec *two,
int color_diff)
struct diff_options *o)
{
int lc_a, lc_b;
int color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
const char *name_a_tab, *name_b_tab;
const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);
const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);
const char *old = diff_get_color(color_diff, DIFF_FILE_OLD);
const char *new = diff_get_color(color_diff, DIFF_FILE_NEW);
const char *reset = diff_get_color(color_diff, DIFF_RESET);
static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;
name_a += (*name_a == '/');
name_b += (*name_b == '/');
name_a_tab = strchr(name_a, ' ') ? "\t" : "";
name_b_tab = strchr(name_b, ' ') ? "\t" : "";
strbuf_reset(&a_name);
strbuf_reset(&b_name);
quote_two_c_style(&a_name, o->a_prefix, name_a, 0);
quote_two_c_style(&b_name, o->b_prefix, name_b, 0);
diff_populate_filespec(one, 0);
diff_populate_filespec(two, 0);
lc_a = count_lines(one->data, one->size);
lc_b = count_lines(two->data, two->size);
printf("%s--- a/%s%s%s\n%s+++ b/%s%s%s\n%s@@ -",
metainfo, name_a, name_a_tab, reset,
metainfo, name_b, name_b_tab, reset, fraginfo);
printf("%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -",
metainfo, a_name.buf, name_a_tab, reset,
metainfo, b_name.buf, name_b_tab, reset, fraginfo);
print_line_count(lc_a);
printf(" +");
print_line_count(lc_b);
@@ -1212,8 +1219,8 @@ static void builtin_diff(const char *name_a,
const char *set = diff_get_color_opt(o, DIFF_METAINFO);
const char *reset = diff_get_color_opt(o, DIFF_RESET);
a_one = quote_two("a/", name_a + (*name_a == '/'));
b_two = quote_two("b/", name_b + (*name_b == '/'));
a_one = quote_two(o->a_prefix, name_a + (*name_a == '/'));
b_two = quote_two(o->b_prefix, name_b + (*name_b == '/'));
lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset);
@@ -1242,8 +1249,7 @@ static void builtin_diff(const char *name_a,
if ((one->mode ^ two->mode) & S_IFMT)
goto free_ab_and_return;
if (complete_rewrite) {
emit_rewrite_diff(name_a, name_b, one, two,
DIFF_OPT_TST(o, COLOR_DIFF));
emit_rewrite_diff(name_a, name_b, one, two, o);
o->found_changes = 1;
goto free_ab_and_return;
}
@@ -2020,6 +2026,9 @@ void diff_setup(struct diff_options *options)
else
DIFF_OPT_CLR(options, COLOR_DIFF);
options->detect_rename = diff_detect_rename_default;
options->a_prefix = "a/";
options->b_prefix = "b/";
}
int diff_setup_done(struct diff_options *options)
@@ -2291,6 +2300,12 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
else if (40 < options->abbrev)
options->abbrev = 40;
}
else if (!prefixcmp(arg, "--src-prefix="))
options->a_prefix = arg + 13;
else if (!prefixcmp(arg, "--dst-prefix="))
options->b_prefix = arg + 13;
else if (!strcmp(arg, "--no-prefix"))
options->a_prefix = options->b_prefix = "";
else
return 0;
return 1;

1
diff.h
View File

@@ -69,6 +69,7 @@ struct diff_options {
const char *orderfile;
const char *pickaxe;
const char *single_follow;
const char *a_prefix, *b_prefix;
unsigned flags;
int context;
int break_opt;

View File

@@ -66,6 +66,19 @@ case $(uname -s) in
xargs --no-run-if-empty \
cp $cp_arg --target-directory="$2" --parents
}
# pwd must return a path with a drive letter
bin_pwd() {
# there are no symlinks to resolve: /bin/pwd is not needed
builtin pwd -W
}
pwd() {
builtin pwd -W
}
;;
*)
bin_pwd() {
/bin/pwd
}
;;
esac
@@ -77,11 +90,11 @@ eval "$(echo "$OPTIONS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)
get_repo_base() {
(
cd "`/bin/pwd -W`" &&
cd "$(bin_pwd)" &&
cd "$1" || cd "$1.git" &&
{
cd .git
pwd -W
pwd
}
) 2>/dev/null
}

View File

@@ -632,6 +632,7 @@ unless ($opt_P) {
print $cvspsfh $_;
}
close CVSPS;
$? == 0 or die "git-cvsimport: fatal: cvsps reported error\n";
close $cvspsfh;
} else {
$cvspsfile = $opt_P;
@@ -848,7 +849,7 @@ while (<CVS>) {
}
if (!$opt_a && $starttime - 300 - (defined $opt_z ? $opt_z : 300) <= $date) {
# skip if the commit is too recent
# that the cvsps default fuzz is 300s, we give ourselves another
# given that the cvsps default fuzz is 300s, we give ourselves another
# 300s just in case -- this also prevents skipping commits
# due to server clock drift
print "skip patchset $patchset: $date too recent\n" if $opt_v;

View File

@@ -372,8 +372,10 @@ do
test ! -f "$DOTEST"/amend || git reset --soft HEAD^
} &&
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE &&
git commit --no-verify -F "$DOTEST"/message -e ||
if ! git commit --no-verify -F "$DOTEST"/message -e
then
die "Could not commit staged changes."
fi
require_clean_work_tree
do_rest

View File

@@ -400,7 +400,7 @@ EOT
close(C);
my $editor = $ENV{GIT_EDITOR} || $repo->config("core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
system($editor, $compose_filename);
system('sh', '-c', '$0 $@', $editor, $compose_filename);
open(C2,">",$compose_filename . ".final")
or die "Failed to open $compose_filename.final : " . $!;

View File

@@ -18,7 +18,8 @@ die() {
if test -n "$OPTIONS_SPEC"; then
usage() {
exec "$0" -h
"$0" -h
exit 1
}
parseopt_extra=

View File

@@ -99,7 +99,7 @@ save_stash () {
git update-ref -m "$stash_msg" $ref_stash $w_commit ||
die "Cannot save the current status"
printf >&2 'Saved "%s"\n' "$stash_msg"
printf >&2 'Saved working directory and index state "%s"\n' "$stash_msg"
}
have_stash () {
@@ -228,7 +228,9 @@ create)
*)
if test $# -eq 0
then
save_stash && git-reset --hard
save_stash &&
echo >&2 '(To restore them type "git stash apply")' &&
git-reset --hard
else
usage
fi

View File

@@ -1511,7 +1511,7 @@ sub config_to_int {
sub config_to_multi {
my $val = shift;
return ref($val) ? $val : (defined($val) ? [ $val ] : []);
return ref($val) ? $val : (defined($val) ? [ $val ] : []);
}
sub git_get_project_config {

View File

@@ -136,29 +136,38 @@ struct object *parse_object_buffer(const unsigned char *sha1, enum object_type t
struct object *obj;
int eaten = 0;
obj = NULL;
if (type == OBJ_BLOB) {
struct blob *blob = lookup_blob(sha1);
parse_blob_buffer(blob, buffer, size);
obj = &blob->object;
if (blob) {
parse_blob_buffer(blob, buffer, size);
obj = &blob->object;
}
} else if (type == OBJ_TREE) {
struct tree *tree = lookup_tree(sha1);
obj = &tree->object;
if (!tree->object.parsed) {
parse_tree_buffer(tree, buffer, size);
eaten = 1;
if (tree) {
obj = &tree->object;
if (!tree->object.parsed) {
parse_tree_buffer(tree, buffer, size);
eaten = 1;
}
}
} else if (type == OBJ_COMMIT) {
struct commit *commit = lookup_commit(sha1);
parse_commit_buffer(commit, buffer, size);
if (!commit->buffer) {
commit->buffer = buffer;
eaten = 1;
if (commit) {
parse_commit_buffer(commit, buffer, size);
if (!commit->buffer) {
commit->buffer = buffer;
eaten = 1;
}
obj = &commit->object;
}
obj = &commit->object;
} else if (type == OBJ_TAG) {
struct tag *tag = lookup_tag(sha1);
parse_tag_buffer(tag, buffer, size);
obj = &tag->object;
if (tag) {
parse_tag_buffer(tag, buffer, size);
obj = &tag->object;
}
} else {
warning("object %s has unknown type id %d\n", sha1_to_hex(sha1), type);
obj = NULL;

View File

@@ -89,7 +89,7 @@ static int get_value(struct optparse_t *p,
*(const char **)opt->value = NULL;
return 0;
}
if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-')) {
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
*(const char **)opt->value = (const char *)opt->defval;
return 0;
}
@@ -103,7 +103,7 @@ static int get_value(struct optparse_t *p,
return (*opt->callback)(opt, NULL, 1);
if (opt->flags & PARSE_OPT_NOARG)
return (*opt->callback)(opt, NULL, 0);
if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-'))
if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
return (*opt->callback)(opt, NULL, 0);
if (!arg)
return opterror(opt, "requires a value", flags);
@@ -114,7 +114,7 @@ static int get_value(struct optparse_t *p,
*(int *)opt->value = 0;
return 0;
}
if (opt->flags & PARSE_OPT_OPTARG && (!arg || !isdigit(*arg))) {
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
*(int *)opt->value = opt->defval;
return 0;
}

View File

@@ -412,7 +412,7 @@ static void parse_commit_header(struct format_commit_context *context)
if (i == eol) {
state++;
/* strip empty lines */
while (msg[eol + 1] == '\n')
while (msg[eol] == '\n' && msg[eol + 1] == '\n')
eol++;
} else if (!prefixcmp(msg + i, "author ")) {
context->author.off = i + 7;
@@ -425,6 +425,8 @@ static void parse_commit_header(struct format_commit_context *context)
context->encoding.len = eol - i - 9;
}
i = eol;
if (!msg[i])
break;
}
context->body_off = i;
context->commit_header_parsed = 1;

16
quote.c
View File

@@ -213,6 +213,22 @@ size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq)
return quote_c_style_counted(name, -1, sb, fp, nodq);
}
void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq)
{
if (quote_c_style(prefix, NULL, NULL, 0) ||
quote_c_style(path, NULL, NULL, 0)) {
if (!nodq)
strbuf_addch(sb, '"');
quote_c_style(prefix, sb, NULL, 1);
quote_c_style(path, sb, NULL, 1);
if (!nodq)
strbuf_addch(sb, '"');
} else {
strbuf_addstr(sb, prefix);
strbuf_addstr(sb, path);
}
}
void write_name_quoted(const char *name, FILE *fp, int terminator)
{
if (terminator) {

View File

@@ -41,6 +41,7 @@ extern char *sq_dequote(char *);
extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
extern void write_name_quoted(const char *name, FILE *, int terminator);
extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,

View File

@@ -1290,8 +1290,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
if (revs->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT)
revs->diff = 1;
/* Pickaxe and rename following needs diffs */
if (revs->diffopt.pickaxe || DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
/* Pickaxe, diff-filter and rename following need diffs */
if (revs->diffopt.pickaxe ||
revs->diffopt.filter ||
DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
revs->diff = 1;
if (revs->topo_order)

View File

@@ -448,6 +448,23 @@ test_expect_success numbers '
test z1048576 = "z$m"
'
cat > expect <<EOF
fatal: bad config value for 'aninvalid.unit' in .git/config
EOF
test_expect_success 'invalid unit' '
git config aninvalid.unit "1auto" &&
s=$(git config aninvalid.unit) &&
test "z1auto" = "z$s" &&
if git config --int --get aninvalid.unit 2>actual
then
echo config should have failed
false
fi &&
cmp actual expect
'
cat > expect << EOF
true
false

View File

@@ -10,58 +10,146 @@ z="$z$z$z$z$z$z$z$z" ;# 512
z="$z$z$z$z" ;# 2048
z2047=$(expr "$z" : '.\(.*\)') ; #2047
test_expect_success setup '
x=zzzzzzzzzz ;# 10
y="$x$x$x$x$x$x$x$x$x$x" ;# 100
z="$y$y$y$y$y$y$y$y$y$y" ;# 1000
z1000=$z
z100=$y
z10=$x
echo "a$z2047" >file-a &&
echo "b" >file-b &&
echo "$z2047" >>file-b &&
echo "c$z2047" | tr -d "\012" >file-c &&
echo "d" >file-d &&
echo "$z2047" | tr -d "\012" >>file-d &&
zs() {
count="$1"
while test "$count" -ge 1000
do
count=$(($count - 1000))
printf "%s" $z1000
done
while test "$count" -ge 100
do
count=$(($count - 100))
printf "%s" $z100
done
while test "$count" -ge 10
do
count=$(($count - 10))
printf "%s" $z10
done
while test "$count" -ge 1
do
count=$(($count - 1))
printf "z"
done
}
git add file-a file-b file-c file-d &&
zc () {
sed -e "/^index/d" \
-e "s/$z1000/Q/g" \
-e "s/QQQQQQQQQ/Z9000/g" \
-e "s/QQQQQQQQ/Z8000/g" \
-e "s/QQQQQQQ/Z7000/g" \
-e "s/QQQQQQ/Z6000/g" \
-e "s/QQQQQ/Z5000/g" \
-e "s/QQQQ/Z4000/g" \
-e "s/QQQ/Z3000/g" \
-e "s/QQ/Z2000/g" \
-e "s/Q/Z1000/g" \
-e "s/$z100/Q/g" \
-e "s/QQQQQQQQQ/Z900/g" \
-e "s/QQQQQQQQ/Z800/g" \
-e "s/QQQQQQQ/Z700/g" \
-e "s/QQQQQQ/Z600/g" \
-e "s/QQQQQ/Z500/g" \
-e "s/QQQQ/Z400/g" \
-e "s/QQQ/Z300/g" \
-e "s/QQ/Z200/g" \
-e "s/Q/Z100/g" \
-e "s/000Z//g" \
-e "s/$z10/Q/g" \
-e "s/QQQQQQQQQ/Z90/g" \
-e "s/QQQQQQQQ/Z80/g" \
-e "s/QQQQQQQ/Z70/g" \
-e "s/QQQQQQ/Z60/g" \
-e "s/QQQQQ/Z50/g" \
-e "s/QQQQ/Z40/g" \
-e "s/QQQ/Z30/g" \
-e "s/QQ/Z20/g" \
-e "s/Q/Z10/g" \
-e "s/00Z//g" \
-e "s/z/Q/g" \
-e "s/QQQQQQQQQ/Z9/g" \
-e "s/QQQQQQQQ/Z8/g" \
-e "s/QQQQQQQ/Z7/g" \
-e "s/QQQQQQ/Z6/g" \
-e "s/QQQQQ/Z5/g" \
-e "s/QQQQ/Z4/g" \
-e "s/QQQ/Z3/g" \
-e "s/QQ/Z2/g" \
-e "s/Q/Z1/g" \
-e "s/0Z//g" \
;
}
echo "A$z2047" >file-a &&
echo "B" >file-b &&
echo "$z2047" >>file-b &&
echo "C$z2047" | tr -d "\012" >file-c &&
echo "D" >file-d &&
echo "$z2047" | tr -d "\012" >>file-d
'
cat >expect <<\EOF
diff --git a/file-a b/file-a
--- a/file-a
+++ b/file-a
expect_pattern () {
cnt="$1"
cat <<EOF
diff --git a/file-a$cnt b/file-a$cnt
--- a/file-a$cnt
+++ b/file-a$cnt
@@ -1 +1 @@
-aZ
+AZ
diff --git a/file-b b/file-b
--- a/file-b
+++ b/file-b
-Z${cnt}a
+Z${cnt}A
diff --git a/file-b$cnt b/file-b$cnt
--- a/file-b$cnt
+++ b/file-b$cnt
@@ -1 +1 @@
-b
+B
diff --git a/file-c b/file-c
--- a/file-c
+++ b/file-c
diff --git a/file-c$cnt b/file-c$cnt
--- a/file-c$cnt
+++ b/file-c$cnt
@@ -1 +1 @@
-cZ
-cZ$cnt
\ No newline at end of file
+CZ
+CZ$cnt
\ No newline at end of file
diff --git a/file-d b/file-d
--- a/file-d
+++ b/file-d
diff --git a/file-d$cnt b/file-d$cnt
--- a/file-d$cnt
+++ b/file-d$cnt
@@ -1 +1 @@
-d
+D
EOF
}
sample='1023 1024 1025 2047 4095'
test_expect_success setup '
for n in $sample
do
( zs $n ; echo a ) >file-a$n &&
( echo b; zs $n; echo ) >file-b$n &&
( printf c; zs $n ) >file-c$n &&
( echo d; zs $n ) >file-d$n &&
git add file-a$n file-b$n file-c$n file-d$n &&
( zs $n ; echo A ) >file-a$n &&
( echo B; zs $n; echo ) >file-b$n &&
( printf C; zs $n ) >file-c$n &&
( echo D; zs $n ) >file-d$n &&
expect_pattern $n || break
done >expect
'
test_expect_success 'diff -U0' '
git diff -U0 | sed -e "/^index/d" -e "s/$z2047/Z/g" >actual &&
for n in $sample
do
git diff -U0 file-?$n
done | zc >actual &&
diff -u expect actual
'

74
t/t4202-log.sh Executable file
View File

@@ -0,0 +1,74 @@
#!/bin/sh
test_description='git log'
. ./test-lib.sh
test_expect_success setup '
echo one >one &&
git add one &&
test_tick &&
git commit -m initial &&
echo ichi >one &&
git add one &&
test_tick &&
git commit -m second &&
mkdir a &&
echo ni >a/two &&
git add a/two &&
test_tick &&
git commit -m third &&
echo san >a/three &&
git add a/three &&
test_tick &&
git commit -m fourth &&
git rm a/three &&
test_tick &&
git commit -m fifth
'
test_expect_success 'diff-filter=A' '
actual=$(git log --pretty="format:%s" --diff-filter=A HEAD) &&
expect=$(echo fourth ; echo third ; echo initial) &&
test "$actual" = "$expect" || {
echo Oops
echo "Actual: $actual"
false
}
'
test_expect_success 'diff-filter=M' '
actual=$(git log --pretty="format:%s" --diff-filter=M HEAD) &&
expect=$(echo second) &&
test "$actual" = "$expect" || {
echo Oops
echo "Actual: $actual"
false
}
'
test_expect_success 'diff-filter=D' '
actual=$(git log --pretty="format:%s" --diff-filter=D HEAD) &&
expect=$(echo fifth) &&
test "$actual" = "$expect" || {
echo Oops
echo "Actual: $actual"
false
}
'
test_done

View File

@@ -492,25 +492,21 @@ test_expect_success \
echo "tag-one-line" >expect &&
git-tag -l | grep "^tag-one-line" >actual &&
git diff expect actual &&
git-tag -n 0 -l | grep "^tag-one-line" >actual &&
git-tag -n0 -l | grep "^tag-one-line" >actual &&
git diff expect actual &&
git-tag -n 0 -l tag-one-line >actual &&
git-tag -n0 -l tag-one-line >actual &&
git diff expect actual &&
echo "tag-one-line A msg" >expect &&
git-tag -n xxx -l | grep "^tag-one-line" >actual &&
git diff expect actual &&
git-tag -n "" -l | grep "^tag-one-line" >actual &&
git diff expect actual &&
git-tag -n 1 -l | grep "^tag-one-line" >actual &&
git-tag -n1 -l | grep "^tag-one-line" >actual &&
git diff expect actual &&
git-tag -n -l | grep "^tag-one-line" >actual &&
git diff expect actual &&
git-tag -n 1 -l tag-one-line >actual &&
git-tag -n1 -l tag-one-line >actual &&
git diff expect actual &&
git-tag -n 2 -l tag-one-line >actual &&
git-tag -n2 -l tag-one-line >actual &&
git diff expect actual &&
git-tag -n 999 -l tag-one-line >actual &&
git-tag -n999 -l tag-one-line >actual &&
git diff expect actual
'
@@ -521,21 +517,21 @@ test_expect_success \
echo "tag-zero-lines" >expect &&
git-tag -l | grep "^tag-zero-lines" >actual &&
git diff expect actual &&
git-tag -n 0 -l | grep "^tag-zero-lines" >actual &&
git-tag -n0 -l | grep "^tag-zero-lines" >actual &&
git diff expect actual &&
git-tag -n 0 -l tag-zero-lines >actual &&
git-tag -n0 -l tag-zero-lines >actual &&
git diff expect actual &&
echo "tag-zero-lines " >expect &&
git-tag -n 1 -l | grep "^tag-zero-lines" >actual &&
git-tag -n1 -l | grep "^tag-zero-lines" >actual &&
git diff expect actual &&
git-tag -n -l | grep "^tag-zero-lines" >actual &&
git diff expect actual &&
git-tag -n 1 -l tag-zero-lines >actual &&
git-tag -n1 -l tag-zero-lines >actual &&
git diff expect actual &&
git-tag -n 2 -l tag-zero-lines >actual &&
git-tag -n2 -l tag-zero-lines >actual &&
git diff expect actual &&
git-tag -n 999 -l tag-zero-lines >actual &&
git-tag -n999 -l tag-zero-lines >actual &&
git diff expect actual
'
@@ -549,37 +545,37 @@ test_expect_success \
echo "tag-lines" >expect &&
git-tag -l | grep "^tag-lines" >actual &&
git diff expect actual &&
git-tag -n 0 -l | grep "^tag-lines" >actual &&
git-tag -n0 -l | grep "^tag-lines" >actual &&
git diff expect actual &&
git-tag -n 0 -l tag-lines >actual &&
git-tag -n0 -l tag-lines >actual &&
git diff expect actual &&
echo "tag-lines tag line one" >expect &&
git-tag -n 1 -l | grep "^tag-lines" >actual &&
git-tag -n1 -l | grep "^tag-lines" >actual &&
git diff expect actual &&
git-tag -n -l | grep "^tag-lines" >actual &&
git diff expect actual &&
git-tag -n 1 -l tag-lines >actual &&
git-tag -n1 -l tag-lines >actual &&
git diff expect actual &&
echo " tag line two" >>expect &&
git-tag -n 2 -l | grep "^ *tag.line" >actual &&
git-tag -n2 -l | grep "^ *tag.line" >actual &&
git diff expect actual &&
git-tag -n 2 -l tag-lines >actual &&
git-tag -n2 -l tag-lines >actual &&
git diff expect actual &&
echo " tag line three" >>expect &&
git-tag -n 3 -l | grep "^ *tag.line" >actual &&
git-tag -n3 -l | grep "^ *tag.line" >actual &&
git diff expect actual &&
git-tag -n 3 -l tag-lines >actual &&
git-tag -n3 -l tag-lines >actual &&
git diff expect actual &&
git-tag -n 4 -l | grep "^ *tag.line" >actual &&
git-tag -n4 -l | grep "^ *tag.line" >actual &&
git diff expect actual &&
git-tag -n 4 -l tag-lines >actual &&
git-tag -n4 -l tag-lines >actual &&
git diff expect actual &&
git-tag -n 99 -l | grep "^ *tag.line" >actual &&
git-tag -n99 -l | grep "^ *tag.line" >actual &&
git diff expect actual &&
git-tag -n 99 -l tag-lines >actual &&
git-tag -n99 -l tag-lines >actual &&
git diff expect actual
'
@@ -907,25 +903,21 @@ test_expect_success \
echo "stag-one-line" >expect &&
git-tag -l | grep "^stag-one-line" >actual &&
git diff expect actual &&
git-tag -n 0 -l | grep "^stag-one-line" >actual &&
git-tag -n0 -l | grep "^stag-one-line" >actual &&
git diff expect actual &&
git-tag -n 0 -l stag-one-line >actual &&
git-tag -n0 -l stag-one-line >actual &&
git diff expect actual &&
echo "stag-one-line A message line signed" >expect &&
git-tag -n xxx -l | grep "^stag-one-line" >actual &&
git diff expect actual &&
git-tag -n "" -l | grep "^stag-one-line" >actual &&
git diff expect actual &&
git-tag -n 1 -l | grep "^stag-one-line" >actual &&
git-tag -n1 -l | grep "^stag-one-line" >actual &&
git diff expect actual &&
git-tag -n -l | grep "^stag-one-line" >actual &&
git diff expect actual &&
git-tag -n 1 -l stag-one-line >actual &&
git-tag -n1 -l stag-one-line >actual &&
git diff expect actual &&
git-tag -n 2 -l stag-one-line >actual &&
git-tag -n2 -l stag-one-line >actual &&
git diff expect actual &&
git-tag -n 999 -l stag-one-line >actual &&
git-tag -n999 -l stag-one-line >actual &&
git diff expect actual
'
@@ -936,21 +928,21 @@ test_expect_success \
echo "stag-zero-lines" >expect &&
git-tag -l | grep "^stag-zero-lines" >actual &&
git diff expect actual &&
git-tag -n 0 -l | grep "^stag-zero-lines" >actual &&
git-tag -n0 -l | grep "^stag-zero-lines" >actual &&
git diff expect actual &&
git-tag -n 0 -l stag-zero-lines >actual &&
git-tag -n0 -l stag-zero-lines >actual &&
git diff expect actual &&
echo "stag-zero-lines " >expect &&
git-tag -n 1 -l | grep "^stag-zero-lines" >actual &&
git-tag -n1 -l | grep "^stag-zero-lines" >actual &&
git diff expect actual &&
git-tag -n -l | grep "^stag-zero-lines" >actual &&
git diff expect actual &&
git-tag -n 1 -l stag-zero-lines >actual &&
git-tag -n1 -l stag-zero-lines >actual &&
git diff expect actual &&
git-tag -n 2 -l stag-zero-lines >actual &&
git-tag -n2 -l stag-zero-lines >actual &&
git diff expect actual &&
git-tag -n 999 -l stag-zero-lines >actual &&
git-tag -n999 -l stag-zero-lines >actual &&
git diff expect actual
'
@@ -964,37 +956,37 @@ test_expect_success \
echo "stag-lines" >expect &&
git-tag -l | grep "^stag-lines" >actual &&
git diff expect actual &&
git-tag -n 0 -l | grep "^stag-lines" >actual &&
git-tag -n0 -l | grep "^stag-lines" >actual &&
git diff expect actual &&
git-tag -n 0 -l stag-lines >actual &&
git-tag -n0 -l stag-lines >actual &&
git diff expect actual &&
echo "stag-lines stag line one" >expect &&
git-tag -n 1 -l | grep "^stag-lines" >actual &&
git-tag -n1 -l | grep "^stag-lines" >actual &&
git diff expect actual &&
git-tag -n -l | grep "^stag-lines" >actual &&
git diff expect actual &&
git-tag -n 1 -l stag-lines >actual &&
git-tag -n1 -l stag-lines >actual &&
git diff expect actual &&
echo " stag line two" >>expect &&
git-tag -n 2 -l | grep "^ *stag.line" >actual &&
git-tag -n2 -l | grep "^ *stag.line" >actual &&
git diff expect actual &&
git-tag -n 2 -l stag-lines >actual &&
git-tag -n2 -l stag-lines >actual &&
git diff expect actual &&
echo " stag line three" >>expect &&
git-tag -n 3 -l | grep "^ *stag.line" >actual &&
git-tag -n3 -l | grep "^ *stag.line" >actual &&
git diff expect actual &&
git-tag -n 3 -l stag-lines >actual &&
git-tag -n3 -l stag-lines >actual &&
git diff expect actual &&
git-tag -n 4 -l | grep "^ *stag.line" >actual &&
git-tag -n4 -l | grep "^ *stag.line" >actual &&
git diff expect actual &&
git-tag -n 4 -l stag-lines >actual &&
git-tag -n4 -l stag-lines >actual &&
git diff expect actual &&
git-tag -n 99 -l | grep "^ *stag.line" >actual &&
git-tag -n99 -l | grep "^ *stag.line" >actual &&
git diff expect actual &&
git-tag -n 99 -l stag-lines >actual &&
git-tag -n99 -l stag-lines >actual &&
git diff expect actual
'

View File

@@ -38,7 +38,7 @@ test_expect_success 'dumb should error out when falling back on vi' '
if git commit --amend
then
echo "Oops?"
exit 1
false
else
: happy
fi

View File

@@ -89,4 +89,69 @@ test_expect_success 'verbose' '
'
test_expect_success 'cleanup commit messages (verbatim,-t)' '
echo >>negative &&
{ echo;echo "# text";echo; } >expect &&
git commit --cleanup=verbatim -t expect -a &&
git cat-file -p HEAD |sed -e "1,/^\$/d" |head -n 3 >actual &&
diff -u expect actual
'
test_expect_success 'cleanup commit messages (verbatim,-F)' '
echo >>negative &&
git commit --cleanup=verbatim -F expect -a &&
git cat-file -p HEAD |sed -e "1,/^\$/d">actual &&
diff -u expect actual
'
test_expect_success 'cleanup commit messages (verbatim,-m)' '
echo >>negative &&
git commit --cleanup=verbatim -m "$(cat expect)" -a &&
git cat-file -p HEAD |sed -e "1,/^\$/d">actual &&
diff -u expect actual
'
test_expect_success 'cleanup commit messages (whitespace,-F)' '
echo >>negative &&
{ echo;echo "# text";echo; } >text &&
echo "# text" >expect &&
git commit --cleanup=whitespace -F text -a &&
git cat-file -p HEAD |sed -e "1,/^\$/d">actual &&
diff -u expect actual
'
test_expect_success 'cleanup commit messages (strip,-F)' '
echo >>negative &&
{ echo;echo "# text";echo sample;echo; } >text &&
echo sample >expect &&
git commit --cleanup=strip -F text -a &&
git cat-file -p HEAD |sed -e "1,/^\$/d">actual &&
diff -u expect actual
'
echo "sample
# Please enter the commit message for your changes.
# (Comment lines starting with '#' will not be included)" >expect
test_expect_success 'cleanup commit messages (strip,-F,-e)' '
echo >>negative &&
{ echo;echo sample;echo; } >text &&
git commit -e -F text -a &&
head -n 4 .git/COMMIT_EDITMSG >actual &&
diff -u expect actual
'
test_done

View File

@@ -115,17 +115,20 @@ static void trim_common_tail(mmfile_t *a, mmfile_t *b, long ctx)
char *bp = b->ptr + b->size;
long smaller = (a->size < b->size) ? a->size : b->size;
if (ctx)
return;
while (blk + trimmed <= smaller && !memcmp(ap - blk, bp - blk, blk)) {
trimmed += blk;
ap -= blk;
bp -= blk;
}
while (recovered < trimmed && 0 <= ctx)
while (recovered < trimmed)
if (ap[recovered++] == '\n')
ctx--;
a->size -= (trimmed - recovered);
b->size -= (trimmed - recovered);
break;
a->size -= trimmed - recovered;
b->size -= trimmed - recovered;
}
int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *xecb)