Merge branch 'master' of git://repo.or.cz/alt-git

This commit is contained in:
Johannes Sixt
2009-06-10 08:09:10 +02:00
132 changed files with 1918 additions and 927 deletions

View File

@@ -0,0 +1,61 @@
GIT v1.6.3.2 Release Notes
==========================
Fixes since v1.6.3.1
--------------------
* A few codepaths picked up the first few bytes from an sha1[] by
casting the (char *) pointer to (int *); GCC 4.4 did not like this,
and aborted compilation.
* Some unlink(2) failures went undiagnosed.
* The "recursive" merge strategy misbehaved when faced rename/delete
conflicts while coming up with an intermediate merge base.
* The low-level merge algorithm did not handle a degenerate case of
merging a file with itself using itself as the common ancestor
gracefully. It should produce the file itself, but instead
produced an empty result.
* GIT_TRACE mechanism segfaulted when tracing a shell-quoted aliases.
* OpenBSD also uses st_ctimspec in "struct stat", instead of "st_ctim".
* With NO_CROSS_DIRECTORY_HARDLINKS, "make install" can be told not to
create hardlinks between $(gitexecdir)/git-$builtin_commands and
$(bindir)/git.
* command completion code in bash did not reliably detect that we are
in a bare repository.
* "git add ." in an empty directory complained that pathspec "." did not
match anything, which may be technically correct, but not useful. We
silently make it a no-op now.
* "git add -p" (and "patch" action in "git add -i") was broken when
the first hunk that adds a line at the top was split into two and
both halves are marked to be used.
* "git blame path" misbehaved at the commit where path became file
from a directory with some files in it.
* "git for-each-ref" had a segfaulting bug when dealing with a tag object
created by an ancient git.
* "git format-patch -k" still added patch numbers if format.numbered
configuration was set.
* "git grep --color ''" did not terminate. The command also had
subtle bugs with its -w option.
* http-push had a small use-after-free bug.
* "git push" was converting OFS_DELTA pack representation into less
efficient REF_DELTA representation unconditionally upon transfer,
making the transferred data unnecessarily larger.
* "git remote show origin" segfaulted when origin was still empty.
Many other general usability updates around help text, diagnostic messages
and documentation are included as well.

View File

@@ -35,12 +35,43 @@ Updates since v1.6.3
(subsystems)
* gitweb Perl style clean-up.
* git-svn updates, including a new --authors-prog option to map author
names by invoking an external program.
(portability)
* We feed iconv with "UTF-8" instead of "utf8"; the former is
understood more widely.
(performance)
(usability, bells and whistles)
* "git add --edit" lets users edit the whole patch text to fine-tune what
is added to the index.
* "git log --graph" draws graphs more compactly by using horizonal lines
when able.
* "git log --decorate" shows shorter refnames by stripping well-known
refs/* prefix.
* "git send-email" understands quoted aliases in .mailrc files (might
have to be backported to 1.6.3.X).
* "git send-email" can fetch the sender address from the configuration
variable "sendmail.from" (and "sendmail.<identity>.from").
* "git show-branch" can color its output.
* "add" and "update" subcommands to "git submodule" learned --reference
option to use local clone with references.
(developers)
* A major part of the "git bisect" wrapper has moved to C.
Fixes since v1.6.3
------------------
@@ -51,9 +82,12 @@ release, unless otherwise noted.
Here are fixes that this release has, but have not been backported to
v1.6.3.X series.
* The way Git.pm sets up a Repository object was not friendly to callers
that chdir around. It now internally records the repository location
as an absolute path when autodetected.
---
exec >/var/tmp/1
echo O=$(git describe master)
O=v1.6.3
O=v1.6.3.1-168-g23807fa
git shortlog --no-merges $O..master ^maint

View File

@@ -438,6 +438,11 @@ On some file system/operating system combinations, this is unreliable.
Set this config setting to 'rename' there; However, This will remove the
check that makes sure that existing object files will not get overwritten.
add.ignore-errors::
Tells 'git-add' to continue adding files when some files cannot be
added due to indexing errors. Equivalent to the '--ignore-errors'
option of linkgit:git-add[1].
alias.*::
Command aliases for the linkgit:git[1] command wrapper - e.g.
after defining "alias.last = cat-file commit HEAD", the invocation

View File

@@ -3,7 +3,7 @@ git-apply(1)
NAME
----
git-apply - Apply a patch on a git index file and a working tree
git-apply - Apply a patch on a git index file and/or a working tree
SYNOPSIS

View File

@@ -9,8 +9,8 @@ git-cat-file - Provide content or type and size information for repository objec
SYNOPSIS
--------
[verse]
'git cat-file' [-t | -s | -e | -p | <type>] <object>
'git cat-file' [--batch | --batch-check] < <list-of-objects>
'git cat-file' (-t | -s | -e | -p | <type>) <object>
'git cat-file' (--batch | --batch-check) < <list-of-objects>
DESCRIPTION
-----------

View File

@@ -8,12 +8,13 @@ git-mktree - Build a tree-object from ls-tree formatted text
SYNOPSIS
--------
'git mktree' [-z]
'git mktree' [-z] [--missing] [--batch]
DESCRIPTION
-----------
Reads standard input in non-recursive `ls-tree` output format,
and creates a tree object. The object name of the tree object
Reads standard input in non-recursive `ls-tree` output format, and creates
a tree object. The order of the tree entries is normalised by mktree so
pre-sorting the input is not required. The object name of the tree object
built is written to the standard output.
OPTIONS
@@ -21,6 +22,18 @@ OPTIONS
-z::
Read the NUL-terminated `ls-tree -z` output instead.
--missing::
Allow missing objects. The default behaviour (without this option)
is to verify that each tree entry's sha1 identifies an existing
object. This option has no effect on the treatment of gitlink entries
(aka "submodules") which are always allowed to be missing.
--batch::
Allow building of more than one tree object before exiting. Each
tree is separated by as single blank line. The final new-line is
optional. Note - if the '-z' option is used, lines are terminated
with NUL.
Author
------
Written by Junio C Hamano <gitster@pobox.com>

View File

@@ -39,6 +39,10 @@ OPTIONS
Composing
~~~~~~~~~
--annotate::
Review and edit each patch you're about to send. See the
CONFIGURATION section for 'sendemail.multiedit'.
--bcc=<address>::
Specify a "Bcc:" value for each email. Default is the value of
'sendemail.bcc'.
@@ -51,11 +55,6 @@ The --bcc option must be repeated for each user you want on the bcc list.
+
The --cc option must be repeated for each user you want on the cc list.
--annotate::
Review each patch you're about to send in an editor. The setting
'sendemail.multiedit' defines if this will spawn one editor per patch
or one for all of them at once.
--compose::
Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an
introductory message for the patch series.
@@ -67,6 +66,8 @@ In-Reply-To headers specified in the message. If the body of the message
and In-Reply-To headers will be used unless they are removed.
+
Missing From or In-Reply-To headers will be prompted for.
+
See the CONFIGURATION section for 'sendemail.multiedit'.
--from=<address>::
Specify the sender of the emails. If not specified on the command line,
@@ -138,7 +139,9 @@ user is prompted for a password while the input is masked for privacy.
--smtp-server-port=<port>::
Specifies a port different from the default port (SMTP
servers typically listen to smtp port 25 and ssmtp port
465). This can be set with 'sendemail.smtpserverport'.
465); symbolic port names (e.g. "submission" instead of 465)
are also accepted. The port can also be set with the
'sendemail.smtpserverport' configuration variable.
--smtp-ssl::
Legacy alias for '--smtp-encryption ssl'.
@@ -233,6 +236,12 @@ have been specified, in which case default to 'compose'.
--dry-run::
Do everything except actually send the emails.
--[no-]format-patch::
When an argument may be understood either as a reference or as a file name,
choose to understand it as a format-patch argument ('--format-patch')
or as a file name ('--no-format-patch'). By default, when such a conflict
occurs, git send-email will fail.
--quiet::
Make git-send-email less verbose. One line per email should be
all that is output.
@@ -249,12 +258,6 @@ have been specified, in which case default to 'compose'.
Default is the value of 'sendemail.validate'; if this is not set,
default to '--validate'.
--[no-]format-patch::
When an argument may be understood either as a reference or as a file name,
choose to understand it as a format-patch argument ('--format-patch')
or as a file name ('--no-format-patch'). By default, when such a conflict
occurs, git send-email will fail.
CONFIGURATION
-------------

View File

@@ -8,10 +8,11 @@ git-show-branch - Show branches and their commits
SYNOPSIS
--------
[verse]
'git show-branch' [--all] [--remotes] [--topo-order] [--current]
'git show-branch' [--all] [--remotes] [--topo-order | --date-order]
[--current] [--color | --no-color]
[--more=<n> | --list | --independent | --merge-base]
[--color | --no-color]
[--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
[--no-name | --sha1-name] [--topics]
[<rev> | <glob>]...
'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
DESCRIPTION
@@ -58,6 +59,11 @@ OPTIONS
appear in topological order (i.e., descendant commits
are shown before their parents).
--date-order::
This option is similar to '--topo-order' in the sense that no
parent comes before all of its children, but otherwise commits
are ordered according to their commit date.
--sparse::
By default, the output omits merges that are reachable
from only one tip being shown. This option makes them

View File

@@ -9,8 +9,8 @@ SYNOPSIS
--------
[verse]
'git stash' list [<options>]
'git stash' (show | drop | pop ) [<stash>]
'git stash' apply [--index] [<stash>]
'git stash' ( show | drop ) [<stash>]
'git stash' ( pop | apply ) [--index] [<stash>]
'git stash' branch <branchname> [<stash>]
'git stash' [save [--keep-index] [<message>]]
'git stash' clear
@@ -75,19 +75,27 @@ show [<stash>]::
it will accept any format known to 'git-diff' (e.g., `git stash show
-p stash@\{1}` to view the second most recent stash in patch form).
apply [--index] [<stash>]::
pop [<stash>]::
Restore the changes recorded in the stash on top of the current
working tree state. When no `<stash>` is given, applies the latest
one. The working directory must match the index.
Remove a single stashed state from the stash list and apply it
on top of the current working tree state, i.e., do the inverse
operation of `git stash save`. The working directory must
match the index.
+
This operation can fail with conflicts; you need to resolve them
by hand in the working tree.
Applying the state can fail with conflicts; in this case, it is not
removed from the stash list. You need to resolve the conflicts by hand
and call `git stash drop` manually afterwards.
+
If the `--index` option is used, then tries to reinstate not only the working
tree's changes, but also the index's ones. However, this can fail, when you
have conflicts (which are stored in the index, where you therefore can no
longer apply the changes as they were originally).
+
When no `<stash>` is given, `stash@\{0}` is assumed.
apply [--index] [<stash>]::
Like `pop`, but do not remove the state from the stash list.
branch <branchname> [<stash>]::
@@ -112,12 +120,6 @@ drop [<stash>]::
Remove a single stashed state from the stash list. When no `<stash>`
is given, it removes the latest one. i.e. `stash@\{0}`
pop [<stash>]::
Remove a single stashed state from the stash list and apply on top
of the current working tree state. When no `<stash>` is given,
`stash@\{0}` is assumed. See also `apply`.
create::
Create a stash (which is a regular commit object) and return its
@@ -163,7 +165,7 @@ $ git pull
file foobar not up to date, cannot merge.
$ git stash
$ git pull
$ git stash apply
$ git stash pop
----------------------------------------------------------------
Interrupted workflow::
@@ -192,7 +194,7 @@ You can use 'git-stash' to simplify the above, like this:
$ git stash
$ edit emergency fix
$ git commit -a -m "Fix in a hurry"
$ git stash apply
$ git stash pop
# ... continue hacking ...
----------------------------------------------------------------

View File

@@ -43,7 +43,12 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
* link:v1.6.3/git.html[documentation for release 1.6.3]
* link:v1.6.3.2/git.html[documentation for release 1.6.3.2]
* release notes for
link:RelNotes-1.6.3.2.txt[1.6.3.2],
link:RelNotes-1.6.3.1.txt[1.6.3.1],
link:RelNotes-1.6.3.txt[1.6.3].
* release notes for
link:RelNotes-1.6.2.5.txt[1.6.2.5],
@@ -227,6 +232,8 @@ The link:user-manual.html#git-concepts[git concepts chapter of the
user-manual] and linkgit:gitcore-tutorial[7] both provide
introductions to the underlying git architecture.
See linkgit:gitworkflows[7] for an overview of recommended workflows.
See also the link:howto-index.html[howto] documents for some useful
examples.
@@ -644,7 +651,8 @@ SEE ALSO
linkgit:gittutorial[7], linkgit:gittutorial-2[7],
link:everyday.html[Everyday Git], linkgit:gitcvs-migration[7],
linkgit:gitglossary[7], linkgit:gitcore-tutorial[7],
linkgit:gitcli[7], link:user-manual.html[The Git User's Manual]
linkgit:gitcli[7], link:user-manual.html[The Git User's Manual],
linkgit:gitworkflows[7]
GIT
---

View File

@@ -650,6 +650,9 @@ digressions that may be interesting at this point are:
smart enough to perform a close-to-optimal search even in the
case of complex non-linear history with lots of merged branches.
* linkgit:gitworkflows[7]: Gives an overview of recommended
workflows.
* link:everyday.html[Everyday GIT with 20 Commands Or So]
* linkgit:gitcvs-migration[7]: Git for CVS users.
@@ -661,6 +664,7 @@ linkgit:gitcvs-migration[7],
linkgit:gitcore-tutorial[7],
linkgit:gitglossary[7],
linkgit:git-help[1],
linkgit:gitworkflows[7],
link:everyday.html[Everyday git],
link:user-manual.html[The Git User's Manual]

View File

@@ -39,7 +39,8 @@
--squash::
Produce the working tree and index state as if a real
merge happened, but do not actually make a commit or
merge happened (except for the merge information),
but do not actually make a commit or
move the `HEAD`, nor record `$GIT_DIR/MERGE_HEAD` to
cause the next `git commit` command to create a merge
commit. This allows you to create a single commit on

View File

@@ -60,13 +60,13 @@ Steps to parse options
. in `cmd_foo(int argc, const char **argv, const char *prefix)`
call
argc = parse_options(argc, argv, builtin_foo_options, builtin_foo_usage, flags);
argc = parse_options(argc, argv, prefix, builtin_foo_options, builtin_foo_usage, flags);
+
`parse_options()` will filter out the processed options of `argv[]` and leave the
non-option arguments in `argv[]`.
`argc` is updated appropriately because of the assignment.
+
You can also pass NULL instead of a usage array as fourth parameter of
You can also pass NULL instead of a usage array as the fifth parameter of
parse_options(), to avoid displaying a help screen with usage info and
option list. This should only be done if necessary, e.g. to implement
a limited parser for only a subset of the options that needs to be run
@@ -167,6 +167,11 @@ There are some macros to easily define options:
and the result will be put into `var`.
See 'Option Callbacks' below for a more elaborate description.
`OPT_FILENAME(short, long, &var, description)`::
Introduce an option with a filename argument.
The filename will be prefixed by passing the filename along with
the prefix argument of `parse_options()` to `prefix_filename()`.
`OPT_ARGUMENT(long, description)`::
Introduce a long-option argument that will be kept in `argv[]`.

View File

@@ -1520,10 +1520,10 @@ $ git commit -a -m "blorpl: typofix"
------------------------------------------------
After that, you can go back to what you were working on with
`git stash apply`:
`git stash pop`:
------------------------------------------------
$ git stash apply
$ git stash pop
------------------------------------------------

View File

@@ -52,6 +52,10 @@ all::
#
# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
#
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
#
# Define NO_LIBGEN_H if you don't have libgen.h.
#
# Define NO_SYS_SELECT_H if you don't have sys/select.h.
#
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
@@ -336,7 +340,6 @@ PROGRAMS += git-index-pack$X
PROGRAMS += git-merge-index$X
PROGRAMS += git-merge-tree$X
PROGRAMS += git-mktag$X
PROGRAMS += git-mktree$X
PROGRAMS += git-pack-redundant$X
PROGRAMS += git-patch-id$X
PROGRAMS += git-shell$X
@@ -590,6 +593,7 @@ BUILTIN_OBJS += builtin-merge-base.o
BUILTIN_OBJS += builtin-merge-file.o
BUILTIN_OBJS += builtin-merge-ours.o
BUILTIN_OBJS += builtin-merge-recursive.o
BUILTIN_OBJS += builtin-mktree.o
BUILTIN_OBJS += builtin-mv.o
BUILTIN_OBJS += builtin-name-rev.o
BUILTIN_OBJS += builtin-pack-objects.o
@@ -636,10 +640,12 @@ EXTLIBS =
ifeq ($(uname_S),Linux)
NO_STRLCPY = YesPlease
NO_MKSTEMPS = YesPlease
THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),GNU/kFreeBSD)
NO_STRLCPY = YesPlease
NO_MKSTEMPS = YesPlease
THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),UnixWare)
@@ -651,6 +657,7 @@ ifeq ($(uname_S),UnixWare)
SHELL_PATH = /usr/local/bin/bash
NO_IPV6 = YesPlease
NO_HSTRERROR = YesPlease
NO_MKSTEMPS = YesPlease
BASIC_CFLAGS += -Kthread
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
@@ -674,6 +681,7 @@ ifeq ($(uname_S),SCO_SV)
SHELL_PATH = /usr/bin/bash
NO_IPV6 = YesPlease
NO_HSTRERROR = YesPlease
NO_MKSTEMPS = YesPlease
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
NO_STRCASESTR = YesPlease
@@ -702,7 +710,10 @@ ifeq ($(uname_S),SunOS)
NO_MEMMEM = YesPlease
NO_HSTRERROR = YesPlease
NO_MKDTEMP = YesPlease
OLD_ICONV = UnfortunatelyYes
NO_MKSTEMPS = YesPlease
ifneq ($(uname_R),5.11)
OLD_ICONV = UnfortunatelyYes
endif
ifeq ($(uname_R),5.8)
NO_UNSETENV = YesPlease
NO_SETENV = YesPlease
@@ -724,6 +735,7 @@ ifeq ($(uname_O),Cygwin)
NO_D_INO_IN_DIRENT = YesPlease
NO_STRCASESTR = YesPlease
NO_MEMMEM = YesPlease
NO_MKSTEMPS = YesPlease
NO_SYMLINK_HEAD = YesPlease
NEEDS_LIBICONV = YesPlease
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@@ -767,11 +779,13 @@ ifeq ($(uname_S),NetBSD)
BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
THREADED_DELTA_SEARCH = YesPlease
USE_ST_TIMESPEC = YesPlease
NO_MKSTEMPS = YesPlease
endif
ifeq ($(uname_S),AIX)
NO_STRCASESTR=YesPlease
NO_MEMMEM = YesPlease
NO_MKDTEMP = YesPlease
NO_MKSTEMPS = YesPlease
NO_STRLCPY = YesPlease
NO_NSEC = YesPlease
FREAD_READS_DIRECTORIES = UnfortunatelyYes
@@ -787,12 +801,14 @@ endif
ifeq ($(uname_S),GNU)
# GNU/Hurd
NO_STRLCPY=YesPlease
NO_MKSTEMPS = YesPlease
endif
ifeq ($(uname_S),IRIX64)
NO_IPV6=YesPlease
NO_SETENV=YesPlease
NO_STRCASESTR=YesPlease
NO_MEMMEM = YesPlease
NO_MKSTEMPS = YesPlease
NO_STRLCPY = YesPlease
NO_SOCKADDR_STORAGE=YesPlease
SHELL_PATH=/usr/gnu/bin/bash
@@ -805,6 +821,7 @@ ifeq ($(uname_S),HP-UX)
NO_SETENV=YesPlease
NO_STRCASESTR=YesPlease
NO_MEMMEM = YesPlease
NO_MKSTEMPS = YesPlease
NO_STRLCPY = YesPlease
NO_MKDTEMP = YesPlease
NO_UNSETENV = YesPlease
@@ -821,6 +838,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_PREAD = YesPlease
NO_OPENSSL = YesPlease
NO_CURL = YesPlease
NO_LIBGEN_H = YesPlease
NO_SYMLINK_HEAD = YesPlease
NO_IPV6 = YesPlease
NO_SETENV = YesPlease
@@ -834,6 +852,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_C99_FORMAT = YesPlease
NO_STRTOUMAX = YesPlease
NO_MKDTEMP = YesPlease
NO_MKSTEMPS = YesPlease
SNPRINTF_RETURNS_BOGUS = YesPlease
NO_SVN_TESTS = YesPlease
NO_PERL_MAKEMAKER = YesPlease
@@ -853,6 +872,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
endif
ifneq (,$(findstring arm,$(uname_M)))
ARM_SHA1 = YesPlease
NO_MKSTEMPS = YesPlease
endif
-include config.mak.autogen
@@ -884,6 +904,11 @@ ifndef CC_LD_DYNPATH
endif
endif
ifdef NO_LIBGEN_H
COMPAT_CFLAGS += -DNO_LIBGEN_H
COMPAT_OBJS += compat/basename.o
endif
ifdef NO_CURL
BASIC_CFLAGS += -DNO_CURL
else
@@ -1011,6 +1036,10 @@ ifdef NO_MKDTEMP
COMPAT_CFLAGS += -DNO_MKDTEMP
COMPAT_OBJS += compat/mkdtemp.o
endif
ifdef NO_MKSTEMPS
COMPAT_CFLAGS += -DNO_MKSTEMPS
COMPAT_OBJS += compat/mkstemps.o
endif
ifdef NO_UNSETENV
COMPAT_CFLAGS += -DNO_UNSETENV
COMPAT_OBJS += compat/unsetenv.o
@@ -1495,6 +1524,8 @@ test-delta$X: diff-delta.o patch-delta.o
test-parse-options$X: parse-options.o
test-parse-options.o: parse-options.h
.PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
test-%$X: test-%.o $(GITLIBS)

View File

@@ -309,7 +309,7 @@ static int parse_archive_args(int argc, const char **argv,
OPT_END()
};
argc = parse_options(argc, argv, opts, archive_usage, 0);
argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
if (remote)
die("Unexpected option --remote");

View File

@@ -553,7 +553,9 @@ struct commit_list *filter_skipped(struct commit_list *list,
return filtered;
}
static void bisect_rev_setup(struct rev_info *revs, const char *prefix)
static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
const char *bad_format, const char *good_format,
int read_paths)
{
struct argv_array rev_argv = { NULL, 0, 0 };
int i;
@@ -564,26 +566,24 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix)
/* rev_argv.argv[0] will be ignored by setup_revisions */
argv_array_push(&rev_argv, xstrdup("bisect_rev_setup"));
argv_array_push_sha1(&rev_argv, current_bad_sha1, "%s");
argv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format);
for (i = 0; i < good_revs.sha1_nr; i++)
argv_array_push_sha1(&rev_argv, good_revs.sha1[i], "^%s");
argv_array_push_sha1(&rev_argv, good_revs.sha1[i],
good_format);
argv_array_push(&rev_argv, xstrdup("--"));
read_bisect_paths(&rev_argv);
if (read_paths)
read_bisect_paths(&rev_argv);
argv_array_push(&rev_argv, NULL);
setup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL);
revs->limited = 1;
}
static void bisect_common(struct rev_info *revs, int *reaches, int *all)
static void bisect_common(struct rev_info *revs)
{
if (prepare_revision_walk(revs))
die("revision walk setup failed");
if (revs->tree_objects)
mark_edges_uninteresting(revs->commits, revs, NULL);
revs->commits = find_bisection(revs->commits, reaches, all,
!!skipped_revs.sha1_nr);
}
static void exit_if_skipped_commits(struct commit_list *tried,
@@ -750,42 +750,31 @@ static void check_merge_bases(void)
free_commit_list(result);
}
/*
* This function runs the command "git rev-list $_good ^$_bad"
* and returns 1 if it produces some output, 0 otherwise.
*/
static int check_ancestors(void)
static int check_ancestors(const char *prefix)
{
struct argv_array rev_argv = { NULL, 0, 0 };
struct strbuf str = STRBUF_INIT;
int i, result = 0;
struct child_process rls;
FILE *rls_fout;
struct rev_info revs;
struct object_array pending_copy;
int i, res;
argv_array_push(&rev_argv, xstrdup("rev-list"));
argv_array_push_sha1(&rev_argv, current_bad_sha1, "^%s");
for (i = 0; i < good_revs.sha1_nr; i++)
argv_array_push_sha1(&rev_argv, good_revs.sha1[i], "%s");
argv_array_push(&rev_argv, NULL);
bisect_rev_setup(&revs, prefix, "^%s", "%s", 0);
memset(&rls, 0, sizeof(rls));
rls.argv = rev_argv.argv;
rls.out = -1;
rls.git_cmd = 1;
if (start_command(&rls))
die("Could not launch 'git rev-list' command.");
rls_fout = fdopen(rls.out, "r");
while (strbuf_getline(&str, rls_fout, '\n') != EOF) {
strbuf_trim(&str);
if (*str.buf) {
result = 1;
break;
}
/* Save pending objects, so they can be cleaned up later. */
memset(&pending_copy, 0, sizeof(pending_copy));
for (i = 0; i < revs.pending.nr; i++)
add_object_array(revs.pending.objects[i].item,
revs.pending.objects[i].name,
&pending_copy);
bisect_common(&revs);
res = (revs.commits != NULL);
/* Clean up objects used, as they will be reused. */
for (i = 0; i < pending_copy.nr; i++) {
struct object *o = pending_copy.objects[i].item;
unparse_commit((struct commit *)o);
}
fclose(rls_fout);
finish_command(&rls);
return result;
return res;
}
/*
@@ -813,7 +802,8 @@ static void check_good_are_ancestors_of_bad(const char *prefix)
if (good_revs.sha1_nr == 0)
return;
if (check_ancestors())
/* Check if all good revs are ancestor of the bad rev. */
if (check_ancestors(prefix))
check_merge_bases();
/* Create file BISECT_ANCESTORS_OK. */
@@ -843,10 +833,13 @@ int bisect_next_all(const char *prefix)
check_good_are_ancestors_of_bad(prefix);
bisect_rev_setup(&revs, prefix);
bisect_rev_setup(&revs, prefix, "%s", "^%s", 1);
revs.limited = 1;
bisect_common(&revs, &reaches, &all);
bisect_common(&revs);
revs.commits = find_bisection(revs.commits, &reaches, &all,
!!skipped_revs.sha1_nr);
revs.commits = filter_skipped(revs.commits, &tried, 0);
if (!revs.commits) {

View File

@@ -298,7 +298,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
int add_new_files;
int require_pathspec;
argc = parse_options(argc, argv, builtin_add_options,
argc = parse_options(argc, argv, prefix, builtin_add_options,
builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
if (patch_interactive)
add_interactive = 1;

View File

@@ -320,6 +320,20 @@ static int name_terminate(const char *name, int namelen, int c, int terminate)
return 1;
}
/* remove double slashes to make --index work with such filenames */
static char *squash_slash(char *name)
{
int i = 0, j = 0;
while (name[i]) {
if ((name[j++] = name[i++]) == '/')
while (name[i] == '/')
i++;
}
name[j] = '\0';
return name;
}
static char *find_name(const char *line, char *def, int p_value, int terminate)
{
int len;
@@ -349,7 +363,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
free(def);
if (root)
strbuf_insert(&name, 0, root, root_len);
return strbuf_detach(&name, NULL);
return squash_slash(strbuf_detach(&name, NULL));
}
}
strbuf_release(&name);
@@ -369,10 +383,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
start = line;
}
if (!start)
return def;
return squash_slash(def);
len = line - start;
if (!len)
return def;
return squash_slash(def);
/*
* Generally we prefer the shorter name, especially
@@ -383,7 +397,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
if (def) {
int deflen = strlen(def);
if (deflen < len && !strncmp(start, def, deflen))
return def;
return squash_slash(def);
free(def);
}
@@ -392,10 +406,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
strcpy(ret, root);
memcpy(ret + root_len, start, len);
ret[root_len + len] = '\0';
return ret;
return squash_slash(ret);
}
return xmemdupz(start, len);
return squash_slash(xmemdupz(start, len));
}
static int count_slashes(const char *cp)
@@ -3278,7 +3292,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
"apply a patch without touching the working tree"),
OPT_BOOLEAN(0, "apply", &force_apply,
"also apply the patch (use with --stat/--summary/--check)"),
OPT_STRING(0, "build-fake-ancestor", &fake_ancestor, "file",
OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor,
"build a temporary index based on embedded index information"),
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
"paths are separated with NUL character",
@@ -3313,8 +3327,9 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
if (apply_default_whitespace)
parse_whitespace_option(apply_default_whitespace);
argc = parse_options(argc, argv, builtin_apply_options,
argc = parse_options(argc, argv, prefix, builtin_apply_options,
apply_usage, 0);
if (apply_with_reject)
apply = apply_verbosely = 1;
if (!force_apply && (diffstat || numstat || summary || check || fake_ancestor))

View File

@@ -80,7 +80,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
OPT_END()
};
argc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);
argc = parse_options(argc, argv, prefix, local_opts, NULL,
PARSE_OPT_KEEP_ALL);
if (output)
create_output_file(output);

View File

@@ -17,7 +17,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
OPT_END()
};
argc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);
argc = parse_options(argc, argv, prefix, options,
git_bisect_helper_usage, 0);
if (!next_all)
usage_with_options(git_bisect_helper_usage, options);

View File

@@ -362,18 +362,28 @@ static struct origin *find_origin(struct scoreboard *sb,
"", &diff_opts);
diffcore_std(&diff_opts);
/* It is either one entry that says "modified", or "created",
* or nothing.
*/
if (!diff_queued_diff.nr) {
/* The path is the same as parent */
porigin = get_origin(sb, parent, origin->path);
hashcpy(porigin->blob_sha1, origin->blob_sha1);
}
else if (diff_queued_diff.nr != 1)
die("internal error in blame::find_origin");
else {
struct diff_filepair *p = diff_queued_diff.queue[0];
} else {
/*
* Since origin->path is a pathspec, if the parent
* commit had it as a directory, we will see a whole
* bunch of deletion of files in the directory that we
* do not care about.
*/
int i;
struct diff_filepair *p = NULL;
for (i = 0; i < diff_queued_diff.nr; i++) {
const char *name;
p = diff_queued_diff.queue[i];
name = p->one->path ? p->one->path : p->two->path;
if (!strcmp(name, origin->path))
break;
}
if (!p)
die("internal error in blame::find_origin");
switch (p->status) {
default:
die("internal error in blame::find_origin (%c)",
@@ -2229,7 +2239,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
save_commit_buffer = 0;
dashdash_pos = 0;
parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
PARSE_OPT_KEEP_ARGV0);
for (;;) {
switch (parse_options_step(&ctx, options, blame_opt_usage)) {

View File

@@ -610,7 +610,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
}
hashcpy(merge_filter_ref, head_sha1);
argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
0);
if (!!delete + !!rename + !!force_create > 1)
usage_with_options(builtin_branch_usage, options);

View File

@@ -201,8 +201,8 @@ static int batch_objects(int print_contents)
}
static const char * const cat_file_usage[] = {
"git cat-file [-t|-s|-e|-p|<type>] <sha1>",
"git cat-file [--batch|--batch-check] < <list_of_sha1s>",
"git cat-file (-t|-s|-e|-p|<type>) <object>",
"git cat-file (--batch|--batch-check) < <list_of_objects>",
NULL
};
@@ -231,7 +231,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
if (argc != 3 && argc != 2)
usage_with_options(cat_file_usage, options);
argc = parse_options(argc, argv, options, cat_file_usage, 0);
argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);
if (opt) {
if (argc == 1)

View File

@@ -69,8 +69,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
int cnt, i, doubledash;
const char *errstr = NULL;
argc = parse_options(argc, argv, check_attr_options, check_attr_usage,
PARSE_OPT_KEEP_DASHDASH);
argc = parse_options(argc, argv, prefix, check_attr_options,
check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
if (!argc)
usage_with_options(check_attr_usage, check_attr_options);

View File

@@ -249,7 +249,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
die("invalid cache");
}
argc = parse_options(argc, argv, builtin_checkout_index_options,
argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
builtin_checkout_index_usage, 0);
state.force = force;
state.quiet = quiet;

View File

@@ -605,7 +605,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
opts.track = BRANCH_TRACK_UNSPECIFIED;
argc = parse_options(argc, argv, options, checkout_usage,
argc = parse_options(argc, argv, prefix, options, checkout_usage,
PARSE_OPT_KEEP_DASHDASH);
/* --track without -b should DWIM */

View File

@@ -56,7 +56,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
else
config_set = 1;
argc = parse_options(argc, argv, options, builtin_clean_usage, 0);
argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
0);
memset(&dir, 0, sizeof(dir));
if (ignored_only)

View File

@@ -360,7 +360,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
junk_pid = getpid();
argc = parse_options(argc, argv, builtin_clone_options,
argc = parse_options(argc, argv, prefix, builtin_clone_options,
builtin_clone_usage, 0);
if (argc == 0)

View File

@@ -88,13 +88,13 @@ static struct option builtin_commit_options[] = {
OPT__VERBOSE(&verbose),
OPT_GROUP("Commit message options"),
OPT_STRING('F', "file", &logfile, "FILE", "read log from file"),
OPT_FILENAME('F', "file", &logfile, "read log from file"),
OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit "),
OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
OPT_STRING('t', "template", &template_file, "FILE", "use specified template file"),
OPT_FILENAME('t', "template", &template_file, "use specified template file"),
OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
OPT_GROUP("Commit contents options"),
@@ -697,9 +697,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
{
int f = 0;
argc = parse_options(argc, argv, builtin_commit_options, usage, 0);
logfile = parse_options_fix_filename(prefix, logfile);
template_file = parse_options_fix_filename(prefix, template_file);
argc = parse_options(argc, argv, prefix, builtin_commit_options, usage,
0);
if (force_author && !strchr(force_author, '>'))
force_author = find_author_by_nickname(force_author);

View File

@@ -316,7 +316,8 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix)
config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
argc = parse_options(argc, argv, builtin_config_options, builtin_config_usage,
argc = parse_options(argc, argv, prefix, builtin_config_options,
builtin_config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (use_global_config + use_system_config + !!given_config_file > 1) {

View File

@@ -83,7 +83,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
OPT_END(),
};
argc = parse_options(argc, argv, opts, count_objects_usage, 0);
argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);
/* we do not take arguments other than flags for now */
if (argc)
usage_with_options(count_objects_usage, opts);

View File

@@ -322,7 +322,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
OPT_END(),
};
argc = parse_options(argc, argv, options, describe_usage, 0);
argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
if (max_candidates < 0)
max_candidates = 0;
else if (max_candidates > MAX_TAGS)

View File

@@ -515,7 +515,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
init_revisions(&revs, prefix);
argc = setup_revisions(argc, argv, &revs, NULL);
argc = parse_options(argc, argv, options, fast_export_usage, 0);
argc = parse_options(argc, argv, prefix, options, fast_export_usage, 0);
if (argc > 1)
usage_with_options (fast_export_usage, options);

View File

@@ -483,7 +483,9 @@ static int sideband_demux(int fd, void *data)
{
int *xd = data;
return recv_sideband("fetch-pack", xd[0], fd);
int ret = recv_sideband("fetch-pack", xd[0], fd);
close(fd);
return ret;
}
static int get_pack(int xd[2], char **pack_lockfile)

View File

@@ -167,6 +167,9 @@ static struct ref *get_ref_map(struct transport *transport,
return ref_map;
}
#define STORE_REF_ERROR_OTHER 1
#define STORE_REF_ERROR_DF_CONFLICT 2
static int s_update_ref(const char *action,
struct ref *ref,
int check_old)
@@ -181,9 +184,11 @@ static int s_update_ref(const char *action,
lock = lock_any_ref_for_update(ref->name,
check_old ? ref->old_sha1 : NULL, 0);
if (!lock)
return 2;
return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
STORE_REF_ERROR_OTHER;
if (write_ref_sha1(lock, ref->new_sha1, msg) < 0)
return 2;
return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
STORE_REF_ERROR_OTHER;
return 0;
}
@@ -386,7 +391,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
}
free(url);
fclose(fp);
if (rc & 2)
if (rc & STORE_REF_ERROR_DF_CONFLICT)
error("some local refs could not be updated; try running\n"
" 'git remote prune %s' to remove any old, conflicting "
"branches", remote_name);
@@ -634,7 +639,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc; i++)
strbuf_addf(&default_rla, " %s", argv[i]);
argc = parse_options(argc, argv,
argc = parse_options(argc, argv, prefix,
builtin_fetch_options, builtin_fetch_usage, 0);
if (argc == 0)

View File

@@ -351,7 +351,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT_BOOLEAN(0, "log", &merge_summary, "populate log with the shortlog"),
OPT_BOOLEAN(0, "summary", &merge_summary, "alias for --log"),
OPT_STRING('F', "file", &inpath, "file", "file to read from"),
OPT_FILENAME('F', "file", &inpath, "file to read from"),
OPT_END()
};
@@ -360,7 +360,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
int ret;
git_config(fmt_merge_msg_config, NULL);
argc = parse_options(argc, argv, options, fmt_merge_msg_usage, 0);
argc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,
0);
if (argc > 0)
usage_with_options(fmt_merge_msg_usage, options);

View File

@@ -905,7 +905,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
OPT_END(),
};
parse_options(argc, argv, opts, for_each_ref_usage, 0);
parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
if (maxcount < 0) {
error("invalid --count argument: `%d'", maxcount);
usage_with_options(for_each_ref_usage, opts);

View File

@@ -590,7 +590,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
errors_found = 0;
argc = parse_options(argc, argv, fsck_opts, fsck_usage, 0);
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
if (write_lost_and_found) {
check_full = 1;
include_reflogs = 0;

View File

@@ -194,7 +194,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
if (pack_refs < 0)
pack_refs = !is_bare_repository();
argc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0);
argc = parse_options(argc, argv, prefix, builtin_gc_options,
builtin_gc_usage, 0);
if (argc > 0)
usage_with_options(builtin_gc_usage, builtin_gc_options);

View File

@@ -765,7 +765,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
* unrecognized non option is the beginning of the refs list
* that continues up to the -- (if exists), and then paths.
*/
argc = parse_options(argc, argv, options, grep_usage,
argc = parse_options(argc, argv, prefix, options, grep_usage,
PARSE_OPT_KEEP_DASHDASH |
PARSE_OPT_STOP_AT_NON_OPTION |
PARSE_OPT_NO_INTERNAL_HELP);

View File

@@ -80,10 +80,9 @@ static int check_emacsclient_version(void)
ec_process.argv = argv_ec;
ec_process.err = -1;
ec_process.stdout_to_stderr = 1;
if (start_command(&ec_process)) {
fprintf(stderr, "Failed to start emacsclient.\n");
return -1;
}
if (start_command(&ec_process))
return error("Failed to start emacsclient.");
strbuf_read(&buffer, ec_process.err, 20);
close(ec_process.err);
@@ -94,20 +93,17 @@ static int check_emacsclient_version(void)
finish_command(&ec_process);
if (prefixcmp(buffer.buf, "emacsclient")) {
fprintf(stderr, "Failed to parse emacsclient version.\n");
strbuf_release(&buffer);
return -1;
return error("Failed to parse emacsclient version.");
}
strbuf_remove(&buffer, 0, strlen("emacsclient"));
version = atoi(buffer.buf);
if (version < 22) {
fprintf(stderr,
"emacsclient version '%d' too old (< 22).\n",
version);
strbuf_release(&buffer);
return -1;
return error("emacsclient version '%d' too old (< 22).",
version);
}
strbuf_release(&buffer);
@@ -423,7 +419,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
setup_git_directory_gently(&nongit);
git_config(git_help_config, NULL);
argc = parse_options(argc, argv, builtin_help_options,
argc = parse_options(argc, argv, prefix, builtin_help_options,
builtin_help_usage, 0);
if (show_all) {

View File

@@ -18,6 +18,7 @@
#include "shortlog.h"
#include "remote.h"
#include "string-list.h"
#include "parse-options.h"
/* Set a default date-time format for git log ("log.date" config variable) */
static const char *default_date_mode = NULL;
@@ -619,7 +620,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
struct shortlog log;
struct strbuf sb = STRBUF_INIT;
int i;
const char *encoding = "utf-8";
const char *encoding = "UTF-8";
struct diff_options opts;
int need_8bit_cte = 0;
struct commit *commit = NULL;
@@ -740,27 +741,179 @@ static const char *set_outdir(const char *prefix, const char *output_directory)
output_directory));
}
static const char * const builtin_format_patch_usage[] = {
"git format-patch [options] [<since> | <revision range>]",
NULL
};
static int keep_subject = 0;
static int keep_callback(const struct option *opt, const char *arg, int unset)
{
((struct rev_info *)opt->value)->total = -1;
keep_subject = 1;
return 0;
}
static int subject_prefix = 0;
static int subject_prefix_callback(const struct option *opt, const char *arg,
int unset)
{
subject_prefix = 1;
((struct rev_info *)opt->value)->subject_prefix = arg;
return 0;
}
static int numbered_cmdline_opt = 0;
static int numbered_callback(const struct option *opt, const char *arg,
int unset)
{
*(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1;
if (unset)
auto_number = 0;
return 0;
}
static int no_numbered_callback(const struct option *opt, const char *arg,
int unset)
{
return numbered_callback(opt, arg, 1);
}
static int output_directory_callback(const struct option *opt, const char *arg,
int unset)
{
const char **dir = (const char **)opt->value;
if (*dir)
die("Two output directories?");
*dir = arg;
return 0;
}
static int thread_callback(const struct option *opt, const char *arg, int unset)
{
int *thread = (int *)opt->value;
if (unset)
*thread = 0;
else if (!arg || !strcmp(arg, "shallow"))
*thread = THREAD_SHALLOW;
else if (!strcmp(arg, "deep"))
*thread = THREAD_DEEP;
else
return 1;
return 0;
}
static int attach_callback(const struct option *opt, const char *arg, int unset)
{
struct rev_info *rev = (struct rev_info *)opt->value;
if (unset)
rev->mime_boundary = NULL;
else if (arg)
rev->mime_boundary = arg;
else
rev->mime_boundary = git_version_string;
rev->no_inline = unset ? 0 : 1;
return 0;
}
static int inline_callback(const struct option *opt, const char *arg, int unset)
{
struct rev_info *rev = (struct rev_info *)opt->value;
if (unset)
rev->mime_boundary = NULL;
else if (arg)
rev->mime_boundary = arg;
else
rev->mime_boundary = git_version_string;
rev->no_inline = 0;
return 0;
}
static int header_callback(const struct option *opt, const char *arg, int unset)
{
add_header(arg);
return 0;
}
static int cc_callback(const struct option *opt, const char *arg, int unset)
{
ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
extra_cc[extra_cc_nr++] = xstrdup(arg);
return 0;
}
int cmd_format_patch(int argc, const char **argv, const char *prefix)
{
struct commit *commit;
struct commit **list = NULL;
struct rev_info rev;
int nr = 0, total, i, j;
int nr = 0, total, i;
int use_stdout = 0;
int start_number = -1;
int keep_subject = 0;
int numbered_files = 0; /* _just_ numbers */
int subject_prefix = 0;
int ignore_if_in_upstream = 0;
int cover_letter = 0;
int boundary_count = 0;
int no_binary_diff = 0;
int numbered_cmdline_opt = 0;
struct commit *origin = NULL, *head = NULL;
const char *in_reply_to = NULL;
struct patch_ids ids;
char *add_signoff = NULL;
struct strbuf buf = STRBUF_INIT;
const struct option builtin_format_patch_options[] = {
{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
"use [PATCH n/m] even with a single patch",
PARSE_OPT_NOARG, numbered_callback },
{ OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
"use [PATCH] even with multiple patches",
PARSE_OPT_NOARG, no_numbered_callback },
OPT_BOOLEAN('s', "signoff", &do_signoff, "add Signed-off-by:"),
OPT_BOOLEAN(0, "stdout", &use_stdout,
"print patches to standard out"),
OPT_BOOLEAN(0, "cover-letter", &cover_letter,
"generate a cover letter"),
OPT_BOOLEAN(0, "numbered-files", &numbered_files,
"use simple number sequence for output file names"),
OPT_STRING(0, "suffix", &fmt_patch_suffix, "sfx",
"use <sfx> instead of '.patch'"),
OPT_INTEGER(0, "start-number", &start_number,
"start numbering patches at <n> instead of 1"),
{ OPTION_CALLBACK, 0, "subject-prefix", &rev, "prefix",
"Use [<prefix>] instead of [PATCH]",
PARSE_OPT_NONEG, subject_prefix_callback },
{ OPTION_CALLBACK, 'o', "output-directory", &output_directory,
"dir", "store resulting files in <dir>",
PARSE_OPT_NONEG, output_directory_callback },
{ OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
"don't strip/add [PATCH]",
PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
"don't output binary diffs"),
OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
"don't include a patch matching a commit upstream"),
OPT_GROUP("Messaging"),
{ OPTION_CALLBACK, 0, "add-header", NULL, "header",
"add email header", PARSE_OPT_NONEG,
header_callback },
{ OPTION_CALLBACK, 0, "cc", NULL, "email", "add Cc: header",
PARSE_OPT_NONEG, cc_callback },
OPT_STRING(0, "in-reply-to", &in_reply_to, "message-id",
"make first mail a reply to <message-id>"),
{ OPTION_CALLBACK, 0, "attach", &rev, "boundary",
"attach the patch", PARSE_OPT_OPTARG,
attach_callback },
{ OPTION_CALLBACK, 0, "inline", &rev, "boundary",
"inline the patch",
PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
inline_callback },
{ OPTION_CALLBACK, 0, "thread", &thread, "style",
"enable message threading, styles: shallow, deep",
PARSE_OPT_OPTARG, thread_callback },
OPT_END()
};
git_config(git_format_config, NULL);
init_revisions(&rev, prefix);
@@ -783,102 +936,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
* like "git format-patch -o a123 HEAD^.." may fail; a123 is
* possibly a valid SHA1.
*/
for (i = 1, j = 1; i < argc; i++) {
if (!strcmp(argv[i], "--stdout"))
use_stdout = 1;
else if (!strcmp(argv[i], "-n") ||
!strcmp(argv[i], "--numbered")) {
numbered = 1;
numbered_cmdline_opt = 1;
}
else if (!strcmp(argv[i], "-N") ||
!strcmp(argv[i], "--no-numbered")) {
numbered = 0;
auto_number = 0;
}
else if (!prefixcmp(argv[i], "--start-number="))
start_number = strtol(argv[i] + 15, NULL, 10);
else if (!strcmp(argv[i], "--numbered-files"))
numbered_files = 1;
else if (!strcmp(argv[i], "--start-number")) {
i++;
if (i == argc)
die("Need a number for --start-number");
start_number = strtol(argv[i], NULL, 10);
}
else if (!prefixcmp(argv[i], "--cc=")) {
ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
extra_cc[extra_cc_nr++] = xstrdup(argv[i] + 5);
}
else if (!strcmp(argv[i], "-k") ||
!strcmp(argv[i], "--keep-subject")) {
keep_subject = 1;
rev.total = -1;
}
else if (!strcmp(argv[i], "--output-directory") ||
!strcmp(argv[i], "-o")) {
i++;
if (argc <= i)
die("Which directory?");
if (output_directory)
die("Two output directories?");
output_directory = argv[i];
}
else if (!strcmp(argv[i], "--signoff") ||
!strcmp(argv[i], "-s")) {
do_signoff = 1;
}
else if (!strcmp(argv[i], "--attach")) {
rev.mime_boundary = git_version_string;
rev.no_inline = 1;
}
else if (!prefixcmp(argv[i], "--attach=")) {
rev.mime_boundary = argv[i] + 9;
rev.no_inline = 1;
}
else if (!strcmp(argv[i], "--no-attach")) {
rev.mime_boundary = NULL;
rev.no_inline = 0;
}
else if (!strcmp(argv[i], "--inline")) {
rev.mime_boundary = git_version_string;
rev.no_inline = 0;
}
else if (!prefixcmp(argv[i], "--inline=")) {
rev.mime_boundary = argv[i] + 9;
rev.no_inline = 0;
}
else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
ignore_if_in_upstream = 1;
else if (!strcmp(argv[i], "--thread")
|| !strcmp(argv[i], "--thread=shallow"))
thread = THREAD_SHALLOW;
else if (!strcmp(argv[i], "--thread=deep"))
thread = THREAD_DEEP;
else if (!strcmp(argv[i], "--no-thread"))
thread = 0;
else if (!prefixcmp(argv[i], "--in-reply-to="))
in_reply_to = argv[i] + 14;
else if (!strcmp(argv[i], "--in-reply-to")) {
i++;
if (i == argc)
die("Need a Message-Id for --in-reply-to");
in_reply_to = argv[i];
} else if (!prefixcmp(argv[i], "--subject-prefix=")) {
subject_prefix = 1;
rev.subject_prefix = argv[i] + 17;
} else if (!prefixcmp(argv[i], "--suffix="))
fmt_patch_suffix = argv[i] + 9;
else if (!strcmp(argv[i], "--cover-letter"))
cover_letter = 1;
else if (!strcmp(argv[i], "--no-binary"))
no_binary_diff = 1;
else if (!prefixcmp(argv[i], "--add-header="))
add_header(argv[i] + 13);
else
argv[j++] = argv[i];
}
argc = j;
argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
builtin_format_patch_usage,
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
if (do_signoff) {
const char *committer;

View File

@@ -486,7 +486,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
prefix_offset = strlen(prefix);
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, builtin_ls_files_options,
argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
ls_files_usage, 0);
if (show_tag || show_valid_bit) {
tag_cached = "H ";

View File

@@ -193,8 +193,7 @@ static void handle_content_type(struct strbuf *line)
*content_top = boundary;
boundary = NULL;
}
if (slurp_attr(line->buf, "charset=", &charset))
strbuf_tolower(&charset);
slurp_attr(line->buf, "charset=", &charset);
if (boundary) {
strbuf_release(boundary);
@@ -481,7 +480,7 @@ static const char *guess_charset(const struct strbuf *line, const char *target_c
if (is_utf8(line->buf))
return NULL;
}
return "latin1";
return "ISO8859-1";
}
static void convert_to_utf8(struct strbuf *line, const char *charset)
@@ -494,7 +493,7 @@ static void convert_to_utf8(struct strbuf *line, const char *charset)
return;
}
if (!strcmp(metainfo_charset, charset))
if (!strcasecmp(metainfo_charset, charset))
return;
out = reencode_string(line->buf, metainfo_charset, charset);
if (!out)
@@ -550,7 +549,6 @@ static int decode_header_bq(struct strbuf *it)
if (cp + 3 - it->buf > it->len)
goto decode_header_bq_out;
strbuf_add(&charset_q, ep, cp - ep);
strbuf_tolower(&charset_q);
encoding = cp[1];
if (!encoding || cp[2] != '?')
@@ -944,7 +942,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
*/
git_config(git_default_config, NULL);
def_charset = (git_commit_encoding ? git_commit_encoding : "utf-8");
def_charset = (git_commit_encoding ? git_commit_encoding : "UTF-8");
metainfo_charset = def_charset;
while (1 < argc && argv[1][0] == '-') {

View File

@@ -53,7 +53,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, options, merge_base_usage, 0);
argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
if (argc < 2)
usage_with_options(merge_base_usage, options);
rev = xmalloc(argc * sizeof(*rev));

View File

@@ -48,7 +48,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
merge_style = git_xmerge_style;
}
argc = parse_options(argc, argv, options, merge_file_usage, 0);
argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
if (argc != 3)
usage_with_options(merge_file_usage, options);
if (quiet) {

View File

@@ -462,7 +462,7 @@ static int git_merge_config(const char *k, const char *v, void *cb)
argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
argc++;
parse_options(argc, argv, builtin_merge_options,
parse_options(argc, argv, NULL, builtin_merge_options,
builtin_merge_usage, 0);
free(buf);
}
@@ -855,7 +855,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (diff_use_color_default == -1)
diff_use_color_default = git_use_color_default;
argc = parse_options(argc, argv, builtin_merge_options,
argc = parse_options(argc, argv, prefix, builtin_merge_options,
builtin_merge_usage, 0);
if (verbosity < 0)
show_diffstat = 0;

190
builtin-mktree.c Normal file
View File

@@ -0,0 +1,190 @@
/*
* GIT - the stupid content tracker
*
* Copyright (c) Junio C Hamano, 2006, 2009
*/
#include "builtin.h"
#include "quote.h"
#include "tree.h"
#include "parse-options.h"
static struct treeent {
unsigned mode;
unsigned char sha1[20];
int len;
char name[FLEX_ARRAY];
} **entries;
static int alloc, used;
static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
{
struct treeent *ent;
int len = strlen(path);
if (strchr(path, '/'))
die("path %s contains slash", path);
if (alloc <= used) {
alloc = alloc_nr(used);
entries = xrealloc(entries, sizeof(*entries) * alloc);
}
ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
ent->mode = mode;
ent->len = len;
hashcpy(ent->sha1, sha1);
memcpy(ent->name, path, len+1);
}
static int ent_compare(const void *a_, const void *b_)
{
struct treeent *a = *(struct treeent **)a_;
struct treeent *b = *(struct treeent **)b_;
return base_name_compare(a->name, a->len, a->mode,
b->name, b->len, b->mode);
}
static void write_tree(unsigned char *sha1)
{
struct strbuf buf;
size_t size;
int i;
qsort(entries, used, sizeof(*entries), ent_compare);
for (size = i = 0; i < used; i++)
size += 32 + entries[i]->len;
strbuf_init(&buf, size);
for (i = 0; i < used; i++) {
struct treeent *ent = entries[i];
strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
strbuf_add(&buf, ent->sha1, 20);
}
write_sha1_file(buf.buf, buf.len, tree_type, sha1);
}
static const char *mktree_usage[] = {
"git mktree [-z] [--missing] [--batch]",
NULL
};
static void mktree_line(char *buf, size_t len, int line_termination, int allow_missing)
{
char *ptr, *ntr;
unsigned mode;
enum object_type mode_type; /* object type derived from mode */
enum object_type obj_type; /* object type derived from sha */
char *path;
unsigned char sha1[20];
ptr = buf;
/*
* Read non-recursive ls-tree output format:
* mode SP type SP sha1 TAB name
*/
mode = strtoul(ptr, &ntr, 8);
if (ptr == ntr || !ntr || *ntr != ' ')
die("input format error: %s", buf);
ptr = ntr + 1; /* type */
ntr = strchr(ptr, ' ');
if (!ntr || buf + len <= ntr + 40 ||
ntr[41] != '\t' ||
get_sha1_hex(ntr + 1, sha1))
die("input format error: %s", buf);
/* It is perfectly normal if we do not have a commit from a submodule */
if (S_ISGITLINK(mode))
allow_missing = 1;
*ntr++ = 0; /* now at the beginning of SHA1 */
path = ntr + 41; /* at the beginning of name */
if (line_termination && path[0] == '"') {
struct strbuf p_uq = STRBUF_INIT;
if (unquote_c_style(&p_uq, path, NULL))
die("invalid quoting");
path = strbuf_detach(&p_uq, NULL);
}
/*
* Object type is redundantly derivable three ways.
* These should all agree.
*/
mode_type = object_type(mode);
if (mode_type != type_from_string(ptr)) {
die("entry '%s' object type (%s) doesn't match mode type (%s)",
path, ptr, typename(mode_type));
}
/* Check the type of object identified by sha1 */
obj_type = sha1_object_info(sha1, NULL);
if (obj_type < 0) {
if (allow_missing) {
; /* no problem - missing objects are presumed to be of the right type */
} else {
die("entry '%s' object %s is unavailable", path, sha1_to_hex(sha1));
}
} else {
if (obj_type != mode_type) {
/*
* The object exists but is of the wrong type.
* This is a problem regardless of allow_missing
* because the new tree entry will never be correct.
*/
die("entry '%s' object %s is a %s but specified type was (%s)",
path, sha1_to_hex(sha1), typename(obj_type), typename(mode_type));
}
}
append_to_tree(mode, sha1, path);
}
int cmd_mktree(int ac, const char **av, const char *prefix)
{
struct strbuf sb = STRBUF_INIT;
unsigned char sha1[20];
int line_termination = '\n';
int allow_missing = 0;
int is_batch_mode = 0;
int got_eof = 0;
const struct option option[] = {
OPT_SET_INT('z', NULL, &line_termination, "input is NUL terminated", '\0'),
OPT_SET_INT( 0 , "missing", &allow_missing, "allow missing objects", 1),
OPT_SET_INT( 0 , "batch", &is_batch_mode, "allow creation of more than one tree", 1),
OPT_END()
};
ac = parse_options(ac, av, prefix, option, mktree_usage, 0);
while (!got_eof) {
while (1) {
if (strbuf_getline(&sb, stdin, line_termination) == EOF) {
got_eof = 1;
break;
}
if (sb.buf[0] == '\0') {
/* empty lines denote tree boundaries in batch mode */
if (is_batch_mode)
break;
die("input format error: (blank line only valid in batch mode)");
}
mktree_line(sb.buf, sb.len, line_termination, allow_missing);
}
if (is_batch_mode && got_eof && used < 1) {
/*
* Execution gets here if the last tree entry is terminated with a
* new-line. The final new-line has been made optional to be
* consistent with the original non-batch behaviour of mktree.
*/
; /* skip creating an empty tree */
} else {
write_tree(sha1);
puts(sha1_to_hex(sha1));
fflush(stdout);
}
used=0; /* reset tree entry buffer for re-use in batch mode */
}
strbuf_release(&sb);
exit(0);
}

View File

@@ -72,7 +72,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (read_cache() < 0)
die("index file corrupt");
argc = parse_options(argc, argv, builtin_mv_options, builtin_mv_usage, 0);
argc = parse_options(argc, argv, prefix, builtin_mv_options,
builtin_mv_usage, 0);
if (--argc < 1)
usage_with_options(builtin_mv_usage, builtin_mv_options);

View File

@@ -238,7 +238,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, opts, name_rev_usage, 0);
argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
if (!!all + !!transform_stdin + !!argc > 1) {
error("Specify either a list, or --all, not both!");
usage_with_options(name_rev_usage, opts);

View File

@@ -15,7 +15,7 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
OPT_BIT(0, "prune", &flags, "prune loose refs (default)", PACK_REFS_PRUNE),
OPT_END(),
};
if (parse_options(argc, argv, opts, pack_refs_usage, 0))
if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
usage_with_options(pack_refs_usage, opts);
return pack_refs(flags);
}

View File

@@ -142,7 +142,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
save_commit_buffer = 0;
init_revisions(&revs, prefix);
argc = parse_options(argc, argv, options, prune_usage, 0);
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
while (argc--) {
unsigned char sha1[20];
const char *name = *argv++;

View File

@@ -198,7 +198,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
OPT_END()
};
argc = parse_options(argc, argv, options, push_usage, 0);
argc = parse_options(argc, argv, prefix, options, push_usage, 0);
if (tags)
add_refspec("refs/tags/*");

View File

@@ -192,7 +192,6 @@ static int run_receive_hook(const char *hook_name)
static int run_update_hook(struct command *cmd)
{
static const char update_hook[] = "hooks/update";
struct child_process proc;
const char *argv[5];
if (access(update_hook, X_OK) < 0)
@@ -204,12 +203,9 @@ static int run_update_hook(struct command *cmd)
argv[3] = sha1_to_hex(cmd->new_sha1);
argv[4] = NULL;
memset(&proc, 0, sizeof(proc));
proc.argv = argv;
proc.no_stdin = 1;
proc.stdout_to_stderr = 1;
return hook_status(run_command(&proc), update_hook);
return hook_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
RUN_COMMAND_STDOUT_TO_STDERR),
update_hook);
}
static int is_ref_checked_out(const char *ref)

View File

@@ -79,7 +79,8 @@ static int add(int argc, const char **argv)
OPT_END()
};
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
0);
if (argc < 2)
usage_with_options(builtin_remote_usage, options);
@@ -299,11 +300,11 @@ static int get_push_ref_states(const struct ref *remote_refs,
return 0;
local_refs = get_local_heads();
ref = push_map = copy_ref_list(remote_refs);
while (ref->next)
ref = ref->next;
push_tail = &ref->next;
push_map = copy_ref_list(remote_refs);
push_tail = &push_map;
while (*push_tail)
push_tail = &((*push_tail)->next);
match_refs(local_refs, push_map, &push_tail, remote->push_refspec_nr,
remote->push_refspec, MATCH_REFS_NONE);
@@ -986,7 +987,8 @@ static int show(int argc, const char **argv)
struct string_list info_list = { NULL, 0, 0, 0 };
struct show_info info;
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
0);
if (argc < 1)
return show_all();
@@ -1003,9 +1005,12 @@ static int show(int argc, const char **argv)
get_remote_ref_states(*argv, &states, query_flag);
printf("* remote %s\n URL: %s\n", *argv,
states.remote->url_nr > 0 ?
states.remote->url[0] : "(no URL)");
printf("* remote %s\n", *argv);
if (states.remote->url_nr) {
for (i=0; i < states.remote->url_nr; i++)
printf(" URL: %s\n", states.remote->url[i]);
} else
printf(" URL: %s\n", "(no URL)");
if (no_query)
printf(" HEAD branch: (not queried)\n");
else if (!states.heads.nr)
@@ -1076,7 +1081,8 @@ static int set_head(int argc, const char **argv)
"delete refs/remotes/<name>/HEAD"),
OPT_END()
};
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
0);
if (argc)
strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
@@ -1130,7 +1136,8 @@ static int prune(int argc, const char **argv)
OPT_END()
};
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
0);
if (argc < 1)
usage_with_options(builtin_remote_usage, options);
@@ -1220,7 +1227,7 @@ static int update(int argc, const char **argv)
OPT_END()
};
argc = parse_options(argc, argv, options, builtin_remote_usage,
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
PARSE_OPT_KEEP_ARGV0);
if (argc < 2) {
argc = 2;
@@ -1306,7 +1313,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
};
int result;
argc = parse_options(argc, argv, options, builtin_remote_usage,
argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (argc < 1)

View File

@@ -203,7 +203,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, options, git_reset_usage,
argc = parse_options(argc, argv, prefix, options, git_reset_usage,
PARSE_OPT_KEEP_DASHDASH);
reflog_action = args_to_str(argv);
setenv("GIT_REFLOG_ACTION", reflog_action, 0);

View File

@@ -318,7 +318,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
int onb = 0, osz = 0, unb = 0, usz = 0;
strbuf_addstr(&parsed, "set --");
argc = parse_options(argc, argv, parseopt_opts, parseopt_usage,
argc = parse_options(argc, argv, prefix, parseopt_opts, parseopt_usage,
PARSE_OPT_KEEP_DASHDASH);
if (argc < 1 || strcmp(argv[0], "--"))
usage_with_options(parseopt_usage, parseopt_opts);
@@ -393,7 +393,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
/* put an OPT_END() */
ALLOC_GROW(opts, onb + 1, osz);
memset(opts + onb, 0, sizeof(opts[onb]));
argc = parse_options(argc, argv, opts, usage,
argc = parse_options(argc, argv, prefix, opts, usage,
keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0);
strbuf_addf(&parsed, " --");

View File

@@ -60,7 +60,7 @@ static void parse_args(int argc, const char **argv)
OPT_END(),
};
if (parse_options(argc, argv, options, usage_str, 0) != 1)
if (parse_options(argc, argv, NULL, options, usage_str, 0) != 1)
usage_with_options(usage_str, options);
arg = argv[0];
@@ -323,9 +323,9 @@ static int revert_or_cherry_pick(int argc, const char **argv)
encoding = get_encoding(message);
if (!encoding)
encoding = "utf-8";
encoding = "UTF-8";
if (!git_commit_encoding)
git_commit_encoding = "utf-8";
git_commit_encoding = "UTF-8";
if ((reencoded_message = reencode_string(message,
git_commit_encoding, encoding)))
message = reencoded_message;

View File

@@ -157,7 +157,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0);
argc = parse_options(argc, argv, prefix, builtin_rm_options,
builtin_rm_usage, 0);
if (!argc)
usage_with_options(builtin_rm_usage, builtin_rm_options);

View File

@@ -263,7 +263,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
shortlog_init(&log);
init_revisions(&rev, prefix);
parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
PARSE_OPT_KEEP_ARGV0);
for (;;) {

View File

@@ -3,11 +3,13 @@
#include "refs.h"
#include "builtin.h"
#include "color.h"
#include "parse-options.h"
static const char show_branch_usage[] =
"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
static const char show_branch_usage_reflog[] =
"--reflog is incompatible with --all, --remotes, --independent or --merge-base";
static const char* show_branch_usage[] = {
"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base] [--topics] [--color] [<refs>...]",
"--reflog[=n[,b]] [--list] [--color] <branch>",
NULL
};
static int showbranch_use_color = -1;
static char column_colors[][COLOR_MAXLEN] = {
@@ -601,18 +603,25 @@ static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
return 0;
}
static void parse_reflog_param(const char *arg, int *cnt, const char **base)
static int reflog = 0;
static int parse_reflog_param(const struct option *opt, const char *arg,
int unset)
{
char *ep;
*cnt = strtoul(arg, &ep, 10);
const char **base = (const char **)opt->value;
if (!arg)
arg = "";
reflog = strtoul(arg, &ep, 10);
if (*ep == ',')
*base = ep + 1;
else if (*ep)
die("unrecognized reflog param '%s'", arg);
return error("unrecognized reflog param '%s'", arg);
else
*base = NULL;
if (*cnt <= 0)
*cnt = DEFAULT_REFLOG;
if (reflog <= 0)
reflog = DEFAULT_REFLOG;
return 0;
}
int cmd_show_branch(int ac, const char **av, const char *prefix)
@@ -638,8 +647,43 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
int head_at = -1;
int topics = 0;
int dense = 1;
int reflog = 0;
const char *reflog_base = NULL;
struct option builtin_show_branch_options[] = {
OPT_BOOLEAN('a', "all", &all_heads,
"show remote-tracking and local branches"),
OPT_BOOLEAN('r', "remotes", &all_remotes,
"show remote-tracking branches"),
OPT_BOOLEAN(0, "color", &showbranch_use_color,
"color '*!+-' corresponding to the branch"),
{ OPTION_INTEGER, 0, "more", &extra, "n",
"show <n> more commits after the common ancestor",
PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
OPT_SET_INT(0, "list", &extra, "synonym to more=-1", -1),
OPT_BOOLEAN(0, "no-name", &no_name, "suppress naming strings"),
OPT_BOOLEAN(0, "current", &with_current_branch,
"include the current branch"),
OPT_BOOLEAN(0, "sha1-name", &sha1_name,
"name commits with their object names"),
OPT_BOOLEAN(0, "merge-base", &merge_base,
"act like git merge-base -a"),
OPT_BOOLEAN(0, "independent", &independent,
"show refs unreachable from any other ref"),
OPT_BOOLEAN(0, "topo-order", &lifo,
"show commits in topological order"),
OPT_BOOLEAN(0, "topics", &topics,
"show only commits not on the first branch"),
OPT_SET_INT(0, "sparse", &dense,
"show merges reachable from only one tip", 0),
OPT_SET_INT(0, "date-order", &lifo,
"show commits where no parent comes before its "
"children", 0),
{ OPTION_CALLBACK, 'g', "reflog", &reflog_base, "<n>[,<base>]",
"show <n> most recent ref-log entries starting at "
"base",
PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP,
parse_reflog_param },
OPT_END()
};
git_config(git_show_branch_config, NULL);
@@ -652,63 +696,18 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
av = default_arg - 1; /* ick; we would not address av[0] */
}
while (1 < ac && av[1][0] == '-') {
const char *arg = av[1];
if (!strcmp(arg, "--")) {
ac--; av++;
break;
}
else if (!strcmp(arg, "--all") || !strcmp(arg, "-a"))
all_heads = all_remotes = 1;
else if (!strcmp(arg, "--remotes") || !strcmp(arg, "-r"))
all_remotes = 1;
else if (!strcmp(arg, "--more"))
extra = 1;
else if (!strcmp(arg, "--list"))
extra = -1;
else if (!strcmp(arg, "--no-name"))
no_name = 1;
else if (!strcmp(arg, "--current"))
with_current_branch = 1;
else if (!strcmp(arg, "--sha1-name"))
sha1_name = 1;
else if (!prefixcmp(arg, "--more="))
extra = atoi(arg + 7);
else if (!strcmp(arg, "--merge-base"))
merge_base = 1;
else if (!strcmp(arg, "--independent"))
independent = 1;
else if (!strcmp(arg, "--topo-order"))
lifo = 1;
else if (!strcmp(arg, "--topics"))
topics = 1;
else if (!strcmp(arg, "--sparse"))
dense = 0;
else if (!strcmp(arg, "--date-order"))
lifo = 0;
else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) {
reflog = DEFAULT_REFLOG;
}
else if (!prefixcmp(arg, "--reflog="))
parse_reflog_param(arg + 9, &reflog, &reflog_base);
else if (!prefixcmp(arg, "-g="))
parse_reflog_param(arg + 3, &reflog, &reflog_base);
else if (!strcmp(arg, "--color"))
showbranch_use_color = 1;
else if (!strcmp(arg, "--no-color"))
showbranch_use_color = 0;
else
usage(show_branch_usage);
ac--; av++;
}
ac--; av++;
ac = parse_options(ac, av, prefix, builtin_show_branch_options,
show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION);
if (all_heads)
all_remotes = 1;
if (extra || reflog) {
/* "listing" mode is incompatible with
* independent nor merge-base modes.
*/
if (independent || merge_base)
usage(show_branch_usage);
usage_with_options(show_branch_usage,
builtin_show_branch_options);
if (reflog && ((0 < extra) || all_heads || all_remotes))
/*
* Asking for --more in reflog mode does not
@@ -716,7 +715,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
*
* Also --all and --remotes do not make sense either.
*/
usage(show_branch_usage_reflog);
die("--reflog is incompatible with --all, --remotes, "
"--independent or --merge-base");
}
/* If nothing is specified, show all branches by default */

View File

@@ -36,7 +36,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0);
argc = parse_options(argc, argv, prefix, options,
git_symbolic_ref_usage, 0);
if (msg &&!*msg)
die("Refusing to perform update with empty message");
switch (argc) {

View File

@@ -387,7 +387,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
"annotated tag, needs a message"),
OPT_CALLBACK('m', NULL, &msg, "msg",
"message for the tag", parse_msg_arg),
OPT_STRING('F', NULL, &msgfile, "file", "message in a file"),
OPT_FILENAME('F', NULL, &msgfile, "message in a file"),
OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
OPT_STRING('u', NULL, &keyid, "key-id",
"use another key to sign the tag"),
@@ -405,8 +405,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
git_config(git_tag_config, NULL);
argc = parse_options(argc, argv, options, git_tag_usage, 0);
msgfile = parse_options_fix_filename(prefix, msgfile);
argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
if (keyid) {
sign = 1;

View File

@@ -23,7 +23,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, options, git_update_ref_usage, 0);
argc = parse_options(argc, argv, prefix, options, git_update_ref_usage,
0);
if (msg && !*msg)
die("Refusing to perform update with empty message.");

View File

@@ -72,6 +72,7 @@ extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
extern int cmd_merge_ours(int argc, const char **argv, const char *prefix);
extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
extern int cmd_merge_recursive(int argc, const char **argv, const char *prefix);
extern int cmd_mktree(int argc, const char **argv, const char *prefix);
extern int cmd_mv(int argc, const char **argv, const char *prefix);
extern int cmd_name_rev(int argc, const char **argv, const char *prefix);
extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);

View File

@@ -614,6 +614,8 @@ extern int is_empty_blob_sha1(const unsigned char *sha1);
int git_mkstemp(char *path, size_t n, const char *template);
int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);
/*
* NOTE NOTE NOTE!!
*

View File

@@ -316,6 +316,26 @@ int parse_commit(struct commit *item)
return ret;
}
static void unparse_commit_list(struct commit_list *list)
{
for (; list; list = list->next)
unparse_commit(list->item);
}
void unparse_commit(struct commit *item)
{
item->object.flags = 0;
item->object.used = 0;
if (item->object.parsed) {
item->object.parsed = 0;
if (item->parents) {
unparse_commit_list(item->parents);
free_commit_list(item->parents);
item->parents = NULL;
}
}
}
struct commit_list *commit_list_insert(struct commit *item, struct commit_list **list_p)
{
struct commit_list *new_list = xmalloc(sizeof(struct commit_list));

View File

@@ -40,6 +40,8 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);
int parse_commit(struct commit *item);
void unparse_commit(struct commit *item);
struct commit_list * commit_list_insert(struct commit *item, struct commit_list **list_p);
unsigned commit_list_count(const struct commit_list *l);
struct commit_list * insert_by_date(struct commit *item, struct commit_list **list);

15
compat/basename.c Normal file
View File

@@ -0,0 +1,15 @@
#include "../git-compat-util.h"
/* Adapted from libiberty's basename.c. */
char *gitbasename (char *path)
{
const char *base;
/* Skip over the disk name in MSDOS pathnames. */
if (has_dos_drive_prefix(path))
path += 2;
for (base = path; *path; path++) {
if (is_dir_sep(*path))
base = path + 1;
}
return (char *)base;
}

70
compat/mkstemps.c Normal file
View File

@@ -0,0 +1,70 @@
#include "../git-compat-util.h"
/* Adapted from libiberty's mkstemp.c. */
#undef TMP_MAX
#define TMP_MAX 16384
int gitmkstemps(char *pattern, int suffix_len)
{
static const char letters[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
static const int num_letters = 62;
uint64_t value;
struct timeval tv;
char *template;
size_t len;
int fd, count;
len = strlen(pattern);
if (len < 6 + suffix_len) {
errno = EINVAL;
return -1;
}
if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) {
errno = EINVAL;
return -1;
}
/*
* Replace pattern's XXXXXX characters with randomness.
* Try TMP_MAX different filenames.
*/
gettimeofday(&tv, NULL);
value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();
template = &pattern[len - 6 - suffix_len];
for (count = 0; count < TMP_MAX; ++count) {
uint64_t v = value;
/* Fill in the random bits. */
template[0] = letters[v % num_letters]; v /= num_letters;
template[1] = letters[v % num_letters]; v /= num_letters;
template[2] = letters[v % num_letters]; v /= num_letters;
template[3] = letters[v % num_letters]; v /= num_letters;
template[4] = letters[v % num_letters]; v /= num_letters;
template[5] = letters[v % num_letters]; v /= num_letters;
fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);
if (fd > 0)
return fd;
/*
* Fatal error (EPERM, ENOSPC etc).
* It doesn't make sense to loop.
*/
if (errno != EEXIST)
break;
/*
* This is a random value. It is only necessary that
* the next TMP_MAX values generated by adding 7777 to
* VALUE are different with (module 2^32).
*/
value += 7777;
}
/* We return the null string if we can't find a unique file name. */
pattern[0] = '\0';
errno = EINVAL;
return -1;
}

View File

@@ -30,6 +30,7 @@ NEEDS_SSL_WITH_CRYPTO=@NEEDS_SSL_WITH_CRYPTO@
NO_OPENSSL=@NO_OPENSSL@
NO_CURL=@NO_CURL@
NO_EXPAT=@NO_EXPAT@
NO_LIBGEN_H=@NO_LIBGEN_H@
NEEDS_LIBICONV=@NEEDS_LIBICONV@
NEEDS_SOCKET=@NEEDS_SOCKET@
NO_SYS_SELECT_H=@NO_SYS_SELECT_H@
@@ -46,6 +47,7 @@ NO_STRTOUMAX=@NO_STRTOUMAX@
NO_SETENV=@NO_SETENV@
NO_UNSETENV=@NO_UNSETENV@
NO_MKDTEMP=@NO_MKDTEMP@
NO_MKSTEMPS=@NO_MKSTEMPS@
NO_ICONV=@NO_ICONV@
OLD_ICONV=@OLD_ICONV@
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@

View File

@@ -627,6 +627,12 @@ AC_SUBST(SNPRINTF_RETURNS_BOGUS)
## (in default C library and libraries checked by AC_CHECK_LIB)
AC_MSG_NOTICE([CHECKS for library functions])
#
# Define NO_LIBGEN_H if you don't have libgen.h.
AC_CHECK_HEADER([libgen.h],
[NO_LIBGEN_H=],
[NO_LIBGEN_H=YesPlease])
AC_SUBST(NO_LIBGEN_H)
#
# Define NO_STRCASESTR if you don't have strcasestr.
GIT_CHECK_FUNC(strcasestr,
[NO_STRCASESTR=],
@@ -677,6 +683,13 @@ GIT_CHECK_FUNC(mkdtemp,
[NO_MKDTEMP=YesPlease])
AC_SUBST(NO_MKDTEMP)
#
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
GIT_CHECK_FUNC(mkstemps,
[NO_MKSTEMPS=],
[NO_MKSTEMPS=YesPlease])
AC_SUBST(NO_MKSTEMPS)
#
#
# Define NO_MMAP if you want to avoid mmap.
#
# Define NO_ICONV if your libc does not properly support iconv.

View File

@@ -579,7 +579,10 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
git_tcp_connect(fd, host, flags);
/*
* Separate original protocol components prog and path
* from extended components with a NUL byte.
* from extended host header with a NUL byte.
*
* Note: Do not add any other headers here! Doing so
* will cause older git-daemon servers to crash.
*/
packet_write(fd[1],
"%s %s%chost=%s%c",

View File

@@ -40,6 +40,10 @@
# with the bash.showDirtyState variable, which defaults to true
# once GIT_PS1_SHOWDIRTYSTATE is enabled.
#
# You can also see if currently something is stashed, by setting
# GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
# then a '$' will be shown next to the branch name.
#
# To submit patches:
#
# *) Read Documentation/SubmittingPatches
@@ -84,26 +88,24 @@ __git_ps1 ()
if [ -n "$g" ]; then
local r
local b
if [ -d "$g/rebase-apply" ]; then
if [ -f "$g/rebase-apply/rebasing" ]; then
r="|REBASE"
elif [ -f "$g/rebase-apply/applying" ]; then
r="|AM"
else
r="|AM/REBASE"
fi
b="$(git symbolic-ref HEAD 2>/dev/null)"
elif [ -f "$g/rebase-merge/interactive" ]; then
if [ -f "$g/rebase-merge/interactive" ]; then
r="|REBASE-i"
b="$(cat "$g/rebase-merge/head-name")"
elif [ -d "$g/rebase-merge" ]; then
r="|REBASE-m"
b="$(cat "$g/rebase-merge/head-name")"
else
if [ -f "$g/MERGE_HEAD" ]; then
if [ -d "$g/rebase-apply" ]; then
if [ -f "$g/rebase-apply/rebasing" ]; then
r="|REBASE"
elif [ -f "$g/rebase-apply/applying" ]; then
r="|AM"
else
r="|AM/REBASE"
fi
elif [ -f "$g/MERGE_HEAD" ]; then
r="|MERGING"
fi
if [ -f "$g/BISECT_LOG" ]; then
elif [ -f "$g/BISECT_LOG" ]; then
r="|BISECTING"
fi
@@ -129,6 +131,7 @@ __git_ps1 ()
local w
local i
local s
local c
if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
@@ -150,14 +153,15 @@ __git_ps1 ()
fi
fi
fi
if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
fi
fi
if [ -n "$b" ]; then
if [ -n "${1-}" ]; then
printf "$1" "$c${b##refs/heads/}$w$i$r"
else
printf " (%s)" "$c${b##refs/heads/}$w$i$r"
fi
if [ -n "${1-}" ]; then
printf "$1" "$c${b##refs/heads/}$w$i$s$r"
else
printf " (%s)" "$c${b##refs/heads/}$w$i$s$r"
fi
fi
}
@@ -1877,10 +1881,10 @@ _git_stash ()
save,--*)
__gitcomp "--keep-index"
;;
apply,--*)
apply,--*|pop,--*)
__gitcomp "--index"
;;
show,--*|drop,--*|pop,--*|branch,--*)
show,--*|drop,--*|branch,--*)
COMPREPLY=()
;;
show,*|apply,*|drop,*|pop,*|branch,*)

View File

@@ -406,15 +406,15 @@ static char *xstrdup_tolower(const char *str)
}
/*
* Separate the "extra args" information as supplied by the client connection.
* Read the host as supplied by the client connection.
*/
static void parse_extra_args(char *extra_args, int buflen)
static void parse_host_arg(char *extra_args, int buflen)
{
char *val;
int vallen;
char *end = extra_args + buflen;
while (extra_args < end && *extra_args) {
if (extra_args < end && *extra_args) {
saw_extended_args = 1;
if (strncasecmp("host=", extra_args, 5) == 0) {
val = extra_args + 5;
@@ -436,6 +436,8 @@ static void parse_extra_args(char *extra_args, int buflen)
/* On to the next one */
extra_args = val + vallen;
}
if (extra_args < end && *extra_args)
die("Invalid request");
}
/*
@@ -545,7 +547,7 @@ static int execute(struct sockaddr *addr)
hostname = canon_hostname = ip_address = tcp_port = NULL;
if (len != pktlen)
parse_extra_args(line + len + 1, pktlen - len - 1);
parse_host_arg(line + len + 1, pktlen - len - 1);
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
struct daemon_service *s = &(daemon_service[i]);

24
diff.c
View File

@@ -1964,8 +1964,16 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
{
int fd;
struct strbuf buf = STRBUF_INIT;
struct strbuf template = STRBUF_INIT;
char *path_dup = xstrdup(path);
const char *base = basename(path_dup);
fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
/* Generate "XXXXXX_basename.ext" */
strbuf_addstr(&template, "XXXXXX_");
strbuf_addstr(&template, base);
fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf,
strlen(base) + 1);
if (fd < 0)
die("unable to create temp-file: %s", strerror(errno));
if (convert_to_working_tree(path,
@@ -1981,6 +1989,8 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
temp->hex[40] = 0;
sprintf(temp->mode, "%06o", mode);
strbuf_release(&buf);
strbuf_release(&template);
free(path_dup);
}
static struct diff_tempfile *prepare_temp_file(const char *name,
@@ -2014,18 +2024,15 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
die("stat(%s): %s", name, strerror(errno));
}
if (S_ISLNK(st.st_mode)) {
int ret;
char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
ret = readlink(name, buf, sizeof(buf));
if (ret < 0)
struct strbuf sb = STRBUF_INIT;
if (strbuf_readlink(&sb, name, st.st_size) < 0)
die("readlink(%s)", name);
if (ret == sizeof(buf))
die("symlink too long: %s", name);
prep_temp_blob(name, temp, buf, ret,
prep_temp_blob(name, temp, sb.buf, sb.len,
(one->sha1_valid ?
one->sha1 : null_sha1),
(one->sha1_valid ?
one->mode : S_IFLNK));
strbuf_release(&sb);
}
else {
/* we can borrow from the file in the work tree */
@@ -3589,6 +3596,7 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
if (start_command(&child) != 0 ||
strbuf_read(&buf, child.out, 0) < 0 ||
finish_command(&child) != 0) {
strbuf_release(&buf);
remove_tempfile();
error("error running textconv command '%s'", pgm);
return NULL;

2
dir.c
View File

@@ -396,7 +396,7 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
{
if (cache_name_pos(pathname, len) >= 0)
if (!cache_name_is_other(pathname, len))
return NULL;
ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc);

View File

@@ -767,6 +767,96 @@ sub split_hunk {
return @split;
}
sub find_last_o_ctx {
my ($it) = @_;
my $text = $it->{TEXT};
my ($o_ofs, $o_cnt) = parse_hunk_header($text->[0]);
my $i = @{$text};
my $last_o_ctx = $o_ofs + $o_cnt;
while (0 < --$i) {
my $line = $text->[$i];
if ($line =~ /^ /) {
$last_o_ctx--;
next;
}
last;
}
return $last_o_ctx;
}
sub merge_hunk {
my ($prev, $this) = @_;
my ($o0_ofs, $o0_cnt, $n0_ofs, $n0_cnt) =
parse_hunk_header($prev->{TEXT}[0]);
my ($o1_ofs, $o1_cnt, $n1_ofs, $n1_cnt) =
parse_hunk_header($this->{TEXT}[0]);
my (@line, $i, $ofs, $o_cnt, $n_cnt);
$ofs = $o0_ofs;
$o_cnt = $n_cnt = 0;
for ($i = 1; $i < @{$prev->{TEXT}}; $i++) {
my $line = $prev->{TEXT}[$i];
if ($line =~ /^\+/) {
$n_cnt++;
push @line, $line;
next;
}
last if ($o1_ofs <= $ofs);
$o_cnt++;
$ofs++;
if ($line =~ /^ /) {
$n_cnt++;
}
push @line, $line;
}
for ($i = 1; $i < @{$this->{TEXT}}; $i++) {
my $line = $this->{TEXT}[$i];
if ($line =~ /^\+/) {
$n_cnt++;
push @line, $line;
next;
}
$ofs++;
$o_cnt++;
if ($line =~ /^ /) {
$n_cnt++;
}
push @line, $line;
}
my $head = ("@@ -$o0_ofs" .
(($o_cnt != 1) ? ",$o_cnt" : '') .
" +$n0_ofs" .
(($n_cnt != 1) ? ",$n_cnt" : '') .
" @@\n");
@{$prev->{TEXT}} = ($head, @line);
}
sub coalesce_overlapping_hunks {
my (@in) = @_;
my @out = ();
my ($last_o_ctx, $last_was_dirty);
for (grep { $_->{USE} } @in) {
my $text = $_->{TEXT};
my ($o_ofs) = parse_hunk_header($text->[0]);
if (defined $last_o_ctx &&
$o_ofs <= $last_o_ctx &&
!$_->{DIRTY} &&
!$last_was_dirty) {
merge_hunk($out[-1], $_);
}
else {
push @out, $_;
}
$last_o_ctx = find_last_o_ctx($out[-1]);
$last_was_dirty = $_->{DIRTY};
}
return @out;
}
sub color_diff {
return map {
@@ -878,7 +968,8 @@ sub edit_hunk_loop {
my $newhunk = {
TEXT => $text,
TYPE => $hunk->[$ix]->{TYPE},
USE => 1
USE => 1,
DIRTY => 1,
};
if (diff_applies($head,
@{$hunk}[0..$ix-1],
@@ -1210,6 +1301,8 @@ sub patch_update_file {
}
}
@hunk = coalesce_overlapping_hunks(@hunk);
my $n_lofs = 0;
my @result = ();
for (@hunk) {

View File

@@ -41,8 +41,10 @@
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && !defined(_M_UNIX)
#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
#ifndef __sun__
#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
#endif
#endif
#define _ALL_SOURCE 1
#define _GNU_SOURCE 1
#define _BSD_SOURCE 1
@@ -97,6 +99,13 @@
#include "compat/mingw.h"
#endif /* __MINGW32__ */
#ifndef NO_LIBGEN_H
#include <libgen.h>
#else
#define basename gitbasename
extern char *gitbasename(char *);
#endif
#ifndef NO_ICONV
#include <iconv.h>
#endif
@@ -232,6 +241,11 @@ extern int gitsetenv(const char *, const char *, int);
extern char *gitmkdtemp(char *);
#endif
#ifdef NO_MKSTEMPS
#define mkstemps gitmkstemps
extern int gitmkstemps(char *, int);
#endif
#ifdef NO_UNSETENV
#define unsetenv gitunsetenv
extern void gitunsetenv(const char *);

View File

@@ -538,7 +538,7 @@ if ($compose) {
print C <<EOT;
From $tpl_sender # This line is ignored.
GIT: Lines beginning in "GIT: " will be removed.
GIT: Lines beginning in "GIT:" will be removed.
GIT: Consider including an overall diffstat or table of contents
GIT: for the patch you are writing.
GIT:
@@ -553,8 +553,6 @@ EOT
}
close(C);
my $editor = $ENV{GIT_EDITOR} || Git::config(@repo, "core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
if ($annotate) {
do_edit($compose_filename, @files);
} else {
@@ -571,7 +569,7 @@ EOT
my $in_body = 0;
my $summary_empty = 1;
while(<C>) {
next if m/^GIT: /;
next if m/^GIT:/;
if ($in_body) {
$summary_empty = 0 unless (/^\n$/);
} elsif (/^\n$/) {
@@ -579,7 +577,7 @@ EOT
if ($need_8bit_cte) {
print C2 "MIME-Version: 1.0\n",
"Content-Type: text/plain; ",
"charset=utf-8\n",
"charset=UTF-8\n",
"Content-Transfer-Encoding: 8bit\n";
}
} elsif (/^MIME-Version:/i) {
@@ -768,12 +766,20 @@ sub unquote_rfc2047 {
sub quote_rfc2047 {
local $_ = shift;
my $encoding = shift || 'utf-8';
my $encoding = shift || 'UTF-8';
s/([^-a-zA-Z0-9!*+\/])/sprintf("=%02X", ord($1))/eg;
s/(.*)/=\?$encoding\?q\?$1\?=/;
return $_;
}
sub is_rfc2047_quoted {
my $s = shift;
my $token = '[^][()<>@,;:"\/?.= \000-\037\177-\377]+';
my $encoded_text = '[!->@-~]+';
length($s) <= 75 &&
$s =~ m/^(?:"[[:ascii:]]*"|=\?$token\?$token\?$encoded_text\?=)$/o;
}
# use the simplest quoting being able to handle the recipient
sub sanitize_address
{
@@ -785,7 +791,7 @@ sub sanitize_address
}
# if recipient_name is already quoted, do nothing
if ($recipient_name =~ /^("[[:ascii:]]*"|=\?utf-8\?q\?.*\?=)$/) {
if (is_rfc2047_quoted($recipient_name)) {
return $recipient;
}
@@ -805,6 +811,10 @@ sub sanitize_address
}
# Returns 1 if the message was sent, and 0 otherwise.
# In actuality, the whole program dies when a there
# is an error sending a message.
sub send_message
{
my @recipients = unique_email_list(@to);
@@ -873,7 +883,7 @@ X-Mailer: git-send-email $gitversion
default => $ask_default);
die "Send this email reply required" unless defined $_;
if (/^n/i) {
return;
return 0;
} elsif (/^q/i) {
cleanup_compose_files();
exit(0);
@@ -954,7 +964,7 @@ X-Mailer: git-send-email $gitversion
$smtp->data or die $smtp->message;
$smtp->datasend("$header\n$message") or die $smtp->message;
$smtp->dataend() or die $smtp->message;
$smtp->ok or die "Failed to send $subject\n".$smtp->message;
$smtp->code =~ /250|200/ or die "Failed to send $subject\n".$smtp->message;
}
if ($quiet) {
printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject);
@@ -975,6 +985,8 @@ X-Mailer: git-send-email $gitversion
print "Result: OK\n";
}
}
return 1;
}
$reply_to = $initial_reply_to;
@@ -1135,10 +1147,10 @@ foreach my $t (@files) {
@cc = (@initial_cc, @cc);
send_message();
my $message_was_sent = send_message();
# set up for the next message
if ($chain_reply_to || !defined $reply_to || length($reply_to) == 0) {
if ($message_was_sent and $chain_reply_to || not defined $reply_to || length($reply_to) == 0) {
$reply_to = $message_id;
if (length $references > 0) {
$references .= "\n $message_id";

View File

@@ -3,8 +3,8 @@
dashless=$(basename "$0" | sed -e 's/-/ /')
USAGE="list [<options>]
or: $dashless (show | drop | pop ) [<stash>]
or: $dashless apply [--index] [<stash>]
or: $dashless ( show | drop ) [<stash>]
or: $dashless ( pop | apply ) [--index] [<stash>]
or: $dashless branch <branchname> [<stash>]
or: $dashless [save [--keep-index] [<message>]]
or: $dashless clear"

View File

@@ -1178,16 +1178,27 @@ sub get_commit_entry {
}
rename $commit_editmsg, $commit_msg or croak $!;
{
require Encode;
# SVN requires messages to be UTF-8 when entering the repo
local $/;
open $log_fh, '<', $commit_msg or croak $!;
binmode $log_fh;
chomp($log_entry{log} = <$log_fh>);
if (my $enc = Git::config('i18n.commitencoding')) {
require Encode;
Encode::from_to($log_entry{log}, $enc, 'UTF-8');
my $enc = Git::config('i18n.commitencoding') || 'UTF-8';
my $msg = $log_entry{log};
eval { $msg = Encode::decode($enc, $msg, 1) };
if ($@) {
die "Could not decode as $enc:\n", $msg,
"\nPerhaps you need to set i18n.commitencoding\n";
}
eval { $msg = Encode::encode('UTF-8', $msg, 1) };
die "Could not encode as UTF-8:\n$msg\n" if $@;
$log_entry{log} = $msg;
close $log_fh or croak $!;
}
unlink $commit_msg;

1
git.c
View File

@@ -327,6 +327,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "merge-ours", cmd_merge_ours, RUN_SETUP },
{ "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
{ "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
{ "mktree", cmd_mktree, RUN_SETUP },
{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
{ "name-rev", cmd_name_rev, RUN_SETUP },
{ "pack-objects", cmd_pack_objects, RUN_SETUP },

9
grep.c
View File

@@ -331,7 +331,7 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
if (hit && p->word_regexp) {
if ((pmatch[0].rm_so < 0) ||
(eol - bol) <= pmatch[0].rm_so ||
(eol - bol) < pmatch[0].rm_so ||
(pmatch[0].rm_eo < 0) ||
(eol - bol) < pmatch[0].rm_eo)
die("regexp returned nonsense");
@@ -350,6 +350,10 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
else
hit = 0;
/* Words consist of at least one character. */
if (pmatch->rm_so == pmatch->rm_eo)
hit = 0;
if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
/* There could be more than one match on the
* line, and the first match might not be
@@ -360,6 +364,7 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
bol = pmatch[0].rm_so + bol + 1;
while (word_char(bol[-1]) && bol < eol)
bol++;
eflags |= REG_NOTBOL;
if (bol < eol)
goto again;
}
@@ -499,6 +504,8 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
*eol = '\0';
while (next_match(opt, bol, eol, ctx, &match, eflags)) {
if (match.rm_so == match.rm_eo)
break;
printf("%.*s%s%.*s%s",
(int)match.rm_so, bol,
opt->color_match,

View File

@@ -84,7 +84,8 @@ int main(int argc, const char **argv)
git_extract_argv0_path(argv[0]);
argc = parse_options(argc, argv, hash_object_options, hash_object_usage, 0);
argc = parse_options(argc, argv, NULL, hash_object_options,
hash_object_usage, 0);
if (write_object) {
prefix = setup_git_directory();

View File

@@ -1884,17 +1884,6 @@ static void get_dav_remote_heads(void)
remote_ls("refs/", (PROCESS_FILES | PROCESS_DIRS | RECURSIVE), process_ls_ref, NULL);
}
static int is_zero_sha1(const unsigned char *sha1)
{
int i;
for (i = 0; i < 20; i++) {
if (*sha1++)
return 0;
}
return 1;
}
static void add_remote_info_ref(struct remote_ls_ctx *ls)
{
struct strbuf *buf = (struct strbuf *)ls->userData;
@@ -2120,13 +2109,13 @@ static int delete_remote_branch(char *pattern, int force)
/* Remote HEAD must resolve to a known object */
if (symref)
return error("Remote HEAD symrefs too deep");
if (is_zero_sha1(head_sha1))
if (is_null_sha1(head_sha1))
return error("Unable to resolve remote HEAD");
if (!has_sha1_file(head_sha1))
return error("Remote HEAD resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", sha1_to_hex(head_sha1));
/* Remote branch must resolve to a known object */
if (is_zero_sha1(remote_ref->old_sha1))
if (is_null_sha1(remote_ref->old_sha1))
return error("Unable to resolve remote branch %s",
remote_ref->name);
if (!has_sha1_file(remote_ref->old_sha1))
@@ -2334,7 +2323,7 @@ int main(int argc, char **argv)
if (!ref->peer_ref)
continue;
if (is_zero_sha1(ref->peer_ref->new_sha1)) {
if (is_null_sha1(ref->peer_ref->new_sha1)) {
if (delete_remote_branch(ref->name, 1) == -1) {
error("Could not remove %s", ref->name);
rc = -4;
@@ -2350,7 +2339,7 @@ int main(int argc, char **argv)
}
if (!force_all &&
!is_zero_sha1(ref->old_sha1) &&
!is_null_sha1(ref->old_sha1) &&
!ref->force) {
if (!has_sha1_file(ref->old_sha1) ||
!ref_newer(ref->peer_ref->new_sha1,
@@ -2400,7 +2389,7 @@ int main(int argc, char **argv)
old_sha1_hex = NULL;
commit_argv[1] = "--objects";
commit_argv[2] = new_sha1_hex;
if (!push_all && !is_zero_sha1(ref->old_sha1)) {
if (!push_all && !is_null_sha1(ref->old_sha1)) {
old_sha1_hex = xmalloc(42);
sprintf(old_sha1_hex, "^%s",
sha1_to_hex(ref->old_sha1));

View File

@@ -982,9 +982,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
struct imap_store *ctx;
struct imap *imap;
char *arg, *rsp;
struct hostent *he;
struct sockaddr_in addr;
int s, a[2], preauth;
int s = -1, a[2], preauth;
pid_t pid;
ctx = xcalloc(sizeof(*ctx), 1);
@@ -1021,6 +1019,51 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
imap_info("ok\n");
} else {
#ifndef NO_IPV6
struct addrinfo hints, *ai0, *ai;
int gai;
char portstr[6];
snprintf(portstr, sizeof(portstr), "%hu", srvc->port);
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
imap_info("Resolving %s... ", srvc->host);
gai = getaddrinfo(srvc->host, portstr, &hints, &ai);
if (gai) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(gai));
goto bail;
}
imap_info("ok\n");
for (ai0 = ai; ai; ai = ai->ai_next) {
char addr[NI_MAXHOST];
s = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (s < 0)
continue;
getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
sizeof(addr), NULL, 0, NI_NUMERICHOST);
imap_info("Connecting to [%s]:%s... ", addr, portstr);
if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
close(s);
s = -1;
perror("connect");
continue;
}
break;
}
freeaddrinfo(ai0);
#else /* NO_IPV6 */
struct hostent *he;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_port = htons(srvc->port);
addr.sin_family = AF_INET;
@@ -1040,7 +1083,12 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
imap_info("Connecting to %s:%hu... ", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
if (connect(s, (struct sockaddr *)&addr, sizeof(addr))) {
close(s);
s = -1;
perror("connect");
}
#endif
if (s < 0) {
fputs("Error: unable to connect to server.\n", stderr);
goto bail;
}

View File

@@ -175,8 +175,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
{ "B", temp[2] },
{ NULL }
};
struct child_process child;
const char *args[20];
const char *args[] = { "sh", "-c", NULL, NULL };
int status, fd, i;
struct stat st;
@@ -191,14 +190,8 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
memset(&child, 0, sizeof(child));
child.argv = args;
args[0] = "sh";
args[1] = "-c";
args[2] = cmd.buf;
args[3] = NULL;
status = run_command(&child);
status = run_command_v_opt(args, 0);
if (status < -ERR_RUN_COMMAND_FORK)
; /* failure in run-command */
else

View File

@@ -3,45 +3,20 @@
#include "exec_cmd.h"
static const char *pgm;
static const char *arguments[9];
static int one_shot, quiet;
static int err;
static void run_program(void)
{
struct child_process child;
memset(&child, 0, sizeof(child));
child.argv = arguments;
if (run_command(&child)) {
if (one_shot) {
err++;
} else {
if (!quiet)
die("merge program failed");
exit(1);
}
}
}
static int merge_entry(int pos, const char *path)
{
int found;
const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
char hexbuf[4][60];
char ownbuf[4][60];
if (pos >= active_nr)
die("git merge-index: %s not in the cache", path);
arguments[0] = pgm;
arguments[1] = "";
arguments[2] = "";
arguments[3] = "";
arguments[4] = path;
arguments[5] = "";
arguments[6] = "";
arguments[7] = "";
arguments[8] = NULL;
found = 0;
do {
static char hexbuf[4][60];
static char ownbuf[4][60];
struct cache_entry *ce = active_cache[pos];
int stage = ce_stage(ce);
@@ -55,7 +30,16 @@ static int merge_entry(int pos, const char *path)
} while (++pos < active_nr);
if (!found)
die("git merge-index: %s not in the cache", path);
run_program();
if (run_command_v_opt(arguments, 0)) {
if (one_shot)
err++;
else {
if (!quiet)
die("merge program failed");
exit(1);
}
}
return found;
}

131
mktree.c
View File

@@ -1,131 +0,0 @@
/*
* GIT - the stupid content tracker
*
* Copyright (c) Junio C Hamano, 2006
*/
#include "cache.h"
#include "quote.h"
#include "tree.h"
#include "exec_cmd.h"
static struct treeent {
unsigned mode;
unsigned char sha1[20];
int len;
char name[FLEX_ARRAY];
} **entries;
static int alloc, used;
static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
{
struct treeent *ent;
int len = strlen(path);
if (strchr(path, '/'))
die("path %s contains slash", path);
if (alloc <= used) {
alloc = alloc_nr(used);
entries = xrealloc(entries, sizeof(*entries) * alloc);
}
ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
ent->mode = mode;
ent->len = len;
hashcpy(ent->sha1, sha1);
memcpy(ent->name, path, len+1);
}
static int ent_compare(const void *a_, const void *b_)
{
struct treeent *a = *(struct treeent **)a_;
struct treeent *b = *(struct treeent **)b_;
return base_name_compare(a->name, a->len, a->mode,
b->name, b->len, b->mode);
}
static void write_tree(unsigned char *sha1)
{
struct strbuf buf;
size_t size;
int i;
qsort(entries, used, sizeof(*entries), ent_compare);
for (size = i = 0; i < used; i++)
size += 32 + entries[i]->len;
strbuf_init(&buf, size);
for (i = 0; i < used; i++) {
struct treeent *ent = entries[i];
strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
strbuf_add(&buf, ent->sha1, 20);
}
write_sha1_file(buf.buf, buf.len, tree_type, sha1);
}
static const char mktree_usage[] = "git mktree [-z]";
int main(int ac, char **av)
{
struct strbuf sb = STRBUF_INIT;
struct strbuf p_uq = STRBUF_INIT;
unsigned char sha1[20];
int line_termination = '\n';
git_extract_argv0_path(av[0]);
setup_git_directory();
while ((1 < ac) && av[1][0] == '-') {
char *arg = av[1];
if (!strcmp("-z", arg))
line_termination = 0;
else
usage(mktree_usage);
ac--;
av++;
}
while (strbuf_getline(&sb, stdin, line_termination) != EOF) {
char *ptr, *ntr;
unsigned mode;
enum object_type type;
char *path;
ptr = sb.buf;
/* Input is non-recursive ls-tree output format
* mode SP type SP sha1 TAB name
*/
mode = strtoul(ptr, &ntr, 8);
if (ptr == ntr || !ntr || *ntr != ' ')
die("input format error: %s", sb.buf);
ptr = ntr + 1; /* type */
ntr = strchr(ptr, ' ');
if (!ntr || sb.buf + sb.len <= ntr + 40 ||
ntr[41] != '\t' ||
get_sha1_hex(ntr + 1, sha1))
die("input format error: %s", sb.buf);
type = sha1_object_info(sha1, NULL);
if (type < 0)
die("object %s unavailable", sha1_to_hex(sha1));
*ntr++ = 0; /* now at the beginning of SHA1 */
if (type != type_from_string(ptr))
die("object type %s mismatch (%s)", ptr, typename(type));
path = ntr + 41; /* at the beginning of name */
if (line_termination && path[0] == '"') {
strbuf_reset(&p_uq);
if (unquote_c_style(&p_uq, path, NULL)) {
die("invalid quoting");
}
path = p_uq.buf;
}
append_to_tree(mode, sha1, path);
}
strbuf_release(&p_uq);
strbuf_release(&sb);
write_tree(sha1);
puts(sha1_to_hex(sha1));
exit(0);
}

View File

@@ -31,11 +31,20 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
return 0;
}
static void fix_filename(const char *prefix, const char **file)
{
if (!file || !*file || !prefix || is_absolute_path(*file)
|| !strcmp("-", *file))
return;
*file = xstrdup(prefix_filename(prefix, strlen(prefix), *file));
}
static int get_value(struct parse_opt_ctx_t *p,
const struct option *opt, int flags)
{
const char *s, *arg;
const int unset = flags & OPT_UNSET;
int err;
if (unset && p->opt)
return opterror(opt, "takes no value", flags);
@@ -95,6 +104,19 @@ static int get_value(struct parse_opt_ctx_t *p,
return get_arg(p, opt, flags, (const char **)opt->value);
return 0;
case OPTION_FILENAME:
err = 0;
if (unset)
*(const char **)opt->value = NULL;
else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
*(const char **)opt->value = (const char *)opt->defval;
else
err = get_arg(p, opt, flags, (const char **)opt->value);
if (!err)
fix_filename(p->prefix, (const char **)opt->value);
return err;
case OPTION_CALLBACK:
if (unset)
return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
@@ -285,12 +307,14 @@ static void check_typos(const char *arg, const struct option *options)
}
void parse_options_start(struct parse_opt_ctx_t *ctx,
int argc, const char **argv, int flags)
int argc, const char **argv, const char *prefix,
int flags)
{
memset(ctx, 0, sizeof(*ctx));
ctx->argc = argc - 1;
ctx->argv = argv + 1;
ctx->out = argv;
ctx->prefix = prefix;
ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
ctx->flags = flags;
if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
@@ -389,12 +413,13 @@ int parse_options_end(struct parse_opt_ctx_t *ctx)
return ctx->cpidx + ctx->argc;
}
int parse_options(int argc, const char **argv, const struct option *options,
const char * const usagestr[], int flags)
int parse_options(int argc, const char **argv, const char *prefix,
const struct option *options, const char * const usagestr[],
int flags)
{
struct parse_opt_ctx_t ctx;
parse_options_start(&ctx, argc, argv, flags);
parse_options_start(&ctx, argc, argv, prefix, flags);
switch (parse_options_step(&ctx, options, usagestr)) {
case PARSE_OPT_HELP:
exit(129);
@@ -412,6 +437,20 @@ int parse_options(int argc, const char **argv, const struct option *options,
return parse_options_end(&ctx);
}
static int usage_argh(const struct option *opts)
{
const char *s;
int literal = opts->flags & PARSE_OPT_LITERAL_ARGHELP;
if (opts->flags & PARSE_OPT_OPTARG)
if (opts->long_name)
s = literal ? "[=%s]" : "[=<%s>]";
else
s = literal ? "[%s]" : "[<%s>]";
else
s = literal ? " %s" : " <%s>";
return fprintf(stderr, s, opts->argh);
}
#define USAGE_OPTS_WIDTH 24
#define USAGE_GAP 2
@@ -477,16 +516,12 @@ int usage_with_options_internal(const char * const *usagestr,
if (opts->flags & PARSE_OPT_NOARG)
break;
/* FALLTHROUGH */
case OPTION_FILENAME:
/* FALLTHROUGH */
case OPTION_STRING:
if (opts->argh) {
if (opts->flags & PARSE_OPT_OPTARG)
if (opts->long_name)
pos += fprintf(stderr, "[=<%s>]", opts->argh);
else
pos += fprintf(stderr, "[<%s>]", opts->argh);
else
pos += fprintf(stderr, " <%s>", opts->argh);
} else {
if (opts->argh)
pos += usage_argh(opts);
else {
if (opts->flags & PARSE_OPT_OPTARG)
if (opts->long_name)
pos += fprintf(stderr, "[=...]");
@@ -593,15 +628,3 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
commit_list_insert(commit, opt->value);
return 0;
}
/*
* This should really be OPTION_FILENAME type as a part of
* parse_options that take prefix to do this while parsing.
*/
extern const char *parse_options_fix_filename(const char *prefix, const char *file)
{
if (!file || !prefix || is_absolute_path(file) || !strcmp("-", file))
return file;
return prefix_filename(prefix, strlen(prefix), file);
}

View File

@@ -17,6 +17,7 @@ enum parse_opt_type {
OPTION_STRING,
OPTION_INTEGER,
OPTION_CALLBACK,
OPTION_FILENAME
};
enum parse_opt_flags {
@@ -34,6 +35,7 @@ enum parse_opt_option_flags {
PARSE_OPT_HIDDEN = 8,
PARSE_OPT_LASTARG_DEFAULT = 16,
PARSE_OPT_NODASH = 32,
PARSE_OPT_LITERAL_ARGHELP = 64,
};
struct option;
@@ -69,9 +71,15 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
* PARSE_OPT_NONEG: says that this option cannot be negated
* PARSE_OPT_HIDDEN: this option is skipped in the default usage, and
* shown only in the full usage.
* PARSE_OPT_LASTARG_DEFAULT: if no argument is given, the default value
* is used.
* PARSE_OPT_LASTARG_DEFAULT: says that this option will take the default
* value if no argument is given when the option
* is last on the command line. If the option is
* not last it will require an argument.
* Should not be used with PARSE_OPT_OPTARG.
* PARSE_OPT_NODASH: this option doesn't start with a dash.
* PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
* (i.e. '<argh>') in the help message.
* Useful for options with multiple parameters.
*
* `callback`::
* pointer to the callback to use for OPTION_CALLBACK.
@@ -113,12 +121,14 @@ struct option {
#define OPT_NUMBER_CALLBACK(v, h, f) \
{ OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
#define OPT_FILENAME(s, l, v, h) { OPTION_FILENAME, (s), (l), (v), \
"FILE", (h) }
/* parse_options() will filter out the processed options and leave the
* non-option arguments in argv[].
* Returns the number of arguments left in argv[].
*/
extern int parse_options(int argc, const char **argv,
extern int parse_options(int argc, const char **argv, const char *prefix,
const struct option *options,
const char * const usagestr[], int flags);
@@ -144,13 +154,15 @@ struct parse_opt_ctx_t {
int argc, cpidx;
const char *opt;
int flags;
const char *prefix;
};
extern int parse_options_usage(const char * const *usagestr,
const struct option *opts);
extern void parse_options_start(struct parse_opt_ctx_t *ctx,
int argc, const char **argv, int flags);
int argc, const char **argv, const char *prefix,
int flags);
extern int parse_options_step(struct parse_opt_ctx_t *ctx,
const struct option *options,
@@ -178,6 +190,4 @@ extern int parse_opt_with_commit(const struct option *, const char *, int);
"use <n> digits to display SHA-1s", \
PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
extern const char *parse_options_fix_filename(const char *prefix, const char *file);
#endif

16
path.c
View File

@@ -139,6 +139,22 @@ int git_mkstemp(char *path, size_t len, const char *template)
return mkstemp(path);
}
/* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */
int git_mkstemps(char *path, size_t len, const char *template, int suffix_len)
{
const char *tmp;
size_t n;
tmp = getenv("TMPDIR");
if (!tmp)
tmp = "/tmp";
n = snprintf(path, len, "%s/%s", tmp, template);
if (len <= n) {
errno = ENAMETOOLONG;
return -1;
}
return mkstemps(path, suffix_len);
}
int validate_headref(const char *path)
{

View File

@@ -284,7 +284,7 @@ static char *replace_encoding_header(char *buf, const char *encoding)
static char *logmsg_reencode(const struct commit *commit,
const char *output_encoding)
{
static const char *utf8 = "utf-8";
static const char *utf8 = "UTF-8";
const char *use_encoding;
char *encoding;
char *out;
@@ -881,7 +881,7 @@ char *reencode_commit_message(const struct commit *commit, const char **encoding
? git_log_output_encoding
: git_commit_encoding);
if (!encoding)
encoding = "utf-8";
encoding = "UTF-8";
if (encoding_p)
*encoding_p = encoding;
return logmsg_reencode(commit, encoding);

4
refs.c
View File

@@ -893,8 +893,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
* name is a proper prefix of our refname.
*/
if (missing &&
!is_refname_available(ref, NULL, get_packed_refs(), 0))
!is_refname_available(ref, NULL, get_packed_refs(), 0)) {
last_errno = ENOTDIR;
goto error_return;
}
lock->lk = xcalloc(1, sizeof(struct lock_file));

View File

@@ -256,10 +256,12 @@ static int everybody_uninteresting(struct commit_list *orig)
/*
* The goal is to get REV_TREE_NEW as the result only if the
* diff consists of all '+' (and no other changes), and
* REV_TREE_DIFFERENT otherwise (of course if the trees are
* the same we want REV_TREE_SAME). That means that once we
* get to REV_TREE_DIFFERENT, we do not have to look any further.
* diff consists of all '+' (and no other changes), REV_TREE_OLD
* if the whole diff is removal of old data, and otherwise
* REV_TREE_DIFFERENT (of course if the trees are the same we
* want REV_TREE_SAME).
* That means that once we get to REV_TREE_DIFFERENT, we do not
* have to look any further.
*/
static int tree_difference = REV_TREE_SAME;
@@ -268,22 +270,9 @@ static void file_add_remove(struct diff_options *options,
const unsigned char *sha1,
const char *fullpath)
{
int diff = REV_TREE_DIFFERENT;
int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD;
/*
* Is it an add of a new file? It means that the old tree
* didn't have it at all, so we will turn "REV_TREE_SAME" ->
* "REV_TREE_NEW", but leave any "REV_TREE_DIFFERENT" alone
* (and if it already was "REV_TREE_NEW", we'll keep it
* "REV_TREE_NEW" of course).
*/
if (addremove == '+') {
diff = tree_difference;
if (diff != REV_TREE_SAME)
return;
diff = REV_TREE_NEW;
}
tree_difference = diff;
tree_difference |= diff;
if (tree_difference == REV_TREE_DIFFERENT)
DIFF_OPT_SET(options, HAS_CHANGES);
}
@@ -305,6 +294,8 @@ static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct
if (!t1)
return REV_TREE_NEW;
if (!t2)
return REV_TREE_OLD;
if (revs->simplify_by_decoration) {
/*
@@ -323,8 +314,7 @@ static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct
if (!revs->prune_data)
return REV_TREE_SAME;
}
if (!t2)
return REV_TREE_DIFFERENT;
tree_difference = REV_TREE_SAME;
DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
@@ -429,6 +419,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
p->parents = NULL;
}
/* fallthrough */
case REV_TREE_OLD:
case REV_TREE_DIFFERENT:
tree_changed = 1;
pp = &parent->next;

View File

@@ -118,8 +118,9 @@ struct rev_info {
};
#define REV_TREE_SAME 0
#define REV_TREE_NEW 1
#define REV_TREE_DIFFERENT 2
#define REV_TREE_NEW 1 /* Only new files */
#define REV_TREE_OLD 2 /* Only files removed */
#define REV_TREE_DIFFERENT 3 /* Mixed changes */
/* revision.c */
void read_revisions_from_stdin(struct rev_info *revs);

View File

@@ -196,8 +196,9 @@ void invalidate_lstat_cache(const char *name, int len)
cache.path[previous_slash] = '\0';
cache.len = previous_slash;
cache.flags = FL_DIR;
} else
} else {
reset_lstat_cache();
}
}
}
@@ -263,7 +264,6 @@ static void do_remove_scheduled_dirs(int new_len)
removal.path[removal.len] != '/');
}
removal.len = new_len;
return;
}
void schedule_dir_for_removal(const char *name, int len)
@@ -296,11 +296,9 @@ void schedule_dir_for_removal(const char *name, int len)
last_slash - match_len);
removal.len = last_slash;
}
return;
}
void remove_scheduled_dirs(void)
{
do_remove_scheduled_dirs(0);
return;
}

View File

@@ -93,14 +93,16 @@ prepare_httpd() {
start_httpd() {
prepare_httpd >&3 2>&4
trap 'stop_httpd; die' EXIT
trap 'code=$?; stop_httpd; (exit $code); die' EXIT
"$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \
-f "$TEST_PATH/apache.conf" $HTTPD_PARA \
-c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start \
>&3 2>&4
if ! test $? = 0; then
if test $? -ne 0
then
say "skipping test, web server setup failed"
trap 'die' EXIT
test_done
fi
}

Some files were not shown because too many files have changed in this diff Show More