Merge commit 'junio/master' into devel

Conflicts:
	t/t3700-add.sh
This commit is contained in:
Steffen Prohaska
2008-08-16 15:45:58 +02:00
52 changed files with 936 additions and 198 deletions

View File

@@ -5,7 +5,7 @@ User visible changes
--------------------
With the default Makefile settings, most of the programs are now
installed outside your $PATH, except for "git", "gitk", "git-gui" and
installed outside your $PATH, except for "git", "gitk" and
some server side programs that need to be accessible for technical
reasons. Invoking a git subcommand as "git-xyzzy" from the command
line has been deprecated since early 2006 (and officially announced in
@@ -28,6 +28,16 @@ introduced in v1.5.2 and v1.4.4.5. If you want to keep your repositories
backwards compatible past these versions, set repack.useDeltaBaseOffset
to false or pack.indexVersion to 1, respectively.
We used to prevent sample hook scripts shipped in templates/ from
triggering by default by relying on the fact that we install them as
unexecutable, but on some filesystems, this approach does not work.
They are now shipped with ".sample" suffix. If you want to activate
any of these samples as-is, rename them to drop the ".sample" suffix,
instead of running "chmod +x" on them. For example, you can rename
hooks/post-update.sample to hooks/post-update to enable the sample
hook that runs update-server-info, in order to make repositories
friendly to dumb protocols (i.e. HTTP).
GIT_CONFIG, which was only documented as affecting "git config", but
actually affected all git commands, now only affects "git config".
GIT_LOCAL_CONFIG, also only documented as affecting "git config" and
@@ -56,11 +66,7 @@ Updates since v1.5.6
gangs.
* Sample hook scripts shipped in templates/ are now suffixed with
*.sample. We used to prevent them from triggering by default by
relying on the fact that we install them as unexecutable, but on
some filesystems this approach does not work. Instead of running
"chmod +x" on them, the users who want to activate these samples
as-is can now rename them dropping *.sample suffix.
*.sample.
* perl's in-place edit (-i) does not work well without backup files on Windows;
some tests are rewritten to cope with this.
@@ -172,7 +178,7 @@ Updates since v1.5.6
* git-diff --check now checks leftover merge conflict markers.
* "git-diff -p" learned to grab a better hunk header lines in
Pascal/Delphi and Ruby source files, and also pays attention to
BibTex, Pascal/Delphi, and Ruby files and also pays attention to
chapter and part boundary in TeX documents.
* When remote side used to have branch 'foo' and git-fetch finds that now
@@ -186,7 +192,7 @@ Updates since v1.5.6
* fast-import and fast-export learned to export and import gitlinks.
* "gitk" left background process behind after begin asked to dig very deep
* "gitk" left background process behind after being asked to dig very deep
history and the user killed the UI; the process is killed when the UI goes
away now.
@@ -248,6 +254,6 @@ this release, unless otherwise noted.
---
exec >/var/tmp/1
O=v1.6.0-rc1-113-gf44bc33
O=v1.6.0-rc3
echo O=$(git describe refs/heads/master)
git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint

View File

@@ -978,6 +978,11 @@ pack.packSizeLimit::
can be overridden by the `\--max-pack-size` option of
linkgit:git-repack[1].
pager.<cmd>::
Allows to set your own pager preferences for each command, overriding
the default. If `\--pager` or `\--no-pager` is specified on the command
line, it takes precedence over this option.
pull.octopus::
The default merge strategy to use when pulling multiple branches
at once.

View File

@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git am' [--signoff] [--keep] [--utf8 | --no-utf8]
[--3way] [--interactive] [--binary]
[--3way] [--interactive]
[--whitespace=<option>] [-C<n>] [-p<n>]
[<mbox> | <Maildir>...]
'git am' (--skip | --resolved | --abort)
@@ -59,11 +59,6 @@ default. You could use `--no-utf8` to override this.
it is supposed to apply to, and we have those blobs
available locally.
-b::
--binary::
Pass `--allow-binary-replacement` flag to 'git-apply'
(see linkgit:git-apply[1]).
--whitespace=<option>::
This flag is passed to the 'git-apply' (see linkgit:git-apply[1])
program that applies

View File

@@ -16,12 +16,12 @@ This is usually not what an end user wants to run directly. See
linkgit:git-commit[1] instead.
Creates a new commit object based on the provided tree object and
emits the new commit object id on stdout. If no parent is given then
it is considered to be an initial tree.
emits the new commit object id on stdout.
A commit object usually has 1 parent (a commit after a change) or up
to 16 parents. More than one parent represents a merge of branches
that led to them.
A commit object may have any number of parents. With exactly one
parent, it is an ordinary commit. Having more than one parent makes
the commit a merge between several lines of history. Initial (root)
commits have no parents.
While a tree represents a particular directory state of a working
directory, a commit represents that state in "time", and explains how

View File

@@ -13,7 +13,7 @@ SYNOPSIS
[--msg-filter <command>] [--commit-filter <command>]
[--tag-name-filter <command>] [--subdirectory-filter <directory>]
[--original <namespace>] [-d <directory>] [-f | --force]
[<rev-list options>...]
[--] [<rev-list options>...]
DESCRIPTION
-----------
@@ -168,10 +168,10 @@ to other tags will be rewritten to point to the underlying commit.
'refs/original/', unless forced.
<rev-list options>...::
When options are given after the new branch name, they will
be passed to 'git-rev-list'. Only commits in the resulting
output will be filtered, although the filtered commits can still
reference parents which are outside of that set.
Arguments for 'git-rev-list'. All positive refs included by
these options are rewritten. You may also specify options
such as '--all', but you must use '--' to separate them from
the 'git-filter-branch' options.
Examples
@@ -196,6 +196,17 @@ git filter-branch --index-filter 'git rm --cached filename' HEAD
Now, you will get the rewritten history saved in HEAD.
To rewrite the repository to look as if `foodir/` had been its project
root, and discard all other history:
-------------------------------------------------------
git filter-branch --subdirectory-filter foodir -- --all
-------------------------------------------------------
Thus you can, e.g., turn a library subdirectory into a repository of
its own. Note the `\--` that separates 'filter-branch' options from
revision options, and the `\--all` to rewrite all branches and tags.
To set a commit (which typically is at the tip of another
history) to be the parent of the current initial commit, in
order to paste the other history behind the current history:

View File

@@ -147,9 +147,9 @@ include::diff-options.txt[]
to any configured headers, and may be used multiple times.
--cover-letter::
Generate a cover letter template. You still have to fill in
a description, but the shortlog and the diffstat will be
generated for you.
In addition to the patches, generate a cover letter file
containing the shortlog and the overall diffstat. You can
fill in a description in the file before sending it out.
--suffix=.<sfx>::
Instead of using `.patch` as the suffix for generated

View File

@@ -31,8 +31,8 @@ OPTIONS
operation. See the section <<URLS,GIT URLS>> below.
<refspec>...::
The canonical format of each <refspec> parameter is
`+?<src>:<dst>`; that is, an optional plus `+`, followed
The canonical format of a <refspec> parameter is
`+?<src>:<dst>`; that is, an optional plus `{plus}`, followed
by the source ref, followed by a colon `:`, followed by
the destination ref.
+

View File

@@ -90,15 +90,15 @@ One way to do it is to pull master into the topic branch:
The commits marked with `*` touch the same area in the same
file; you need to resolve the conflicts when creating the commit
marked with `+`. Then you can test the result to make sure your
marked with `{plus}`. Then you can test the result to make sure your
work-in-progress still works with what is in the latest master.
After this test merge, there are two ways to continue your work
on the topic. The easiest is to build on top of the test merge
commit `+`, and when your work in the topic branch is finally
commit `{plus}`, and when your work in the topic branch is finally
ready, pull the topic branch into master, and/or ask the
upstream to pull from you. By that time, however, the master or
the upstream might have been advanced since the test merge `+`,
the upstream might have been advanced since the test merge `{plus}`,
in which case the final commit graph would look like this:
------------

View File

@@ -7,7 +7,7 @@ git-rm - Remove files from the working tree and from the index
SYNOPSIS
--------
'git rm' [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
'git rm' [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
DESCRIPTION
-----------
@@ -36,6 +36,7 @@ OPTIONS
but this requires the `-r` option to be explicitly given.
-f::
--force::
Override the up-to-date check.
-n::

View File

@@ -8,11 +8,13 @@ git-stash - Stash the changes in a dirty working directory away
SYNOPSIS
--------
[verse]
'git stash' list
'git stash' (show | apply | drop | pop ) [<stash>]
'git stash' list [<options>]
'git stash' (show | drop | pop ) [<stash>]
'git stash' apply [--index] [<stash>]
'git stash' branch <branchname> [<stash>]
'git stash' [save [<message>]]
'git stash' [save [--keep-index] [<message>]]
'git stash' clear
'git stash' create
DESCRIPTION
-----------
@@ -116,6 +118,11 @@ pop [<stash>]::
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
object name, without storing it anywhere in the ref namespace.
DISCUSSION
----------

View File

@@ -138,6 +138,15 @@ and have no uncommitted changes.
+
--no-rebase;;
After committing, do not rebase or reset.
--commit-url <URL>;;
Commit to this SVN URL (the full path). This is intended to
allow existing git-svn repositories created with one transport
method (e.g. `svn://` or `http://` for anonymous read) to be
reused if a user is later given access to an alternate transport
method (e.g. `svn+ssh://` or `https://`) for commit.
Using this option for any other purpose (don't ask)
is very strongly discouraged.
--
'log'::

View File

@@ -307,9 +307,18 @@ backslash, and zero or more occurrences of `sub` followed by
There are a few built-in patterns to make this easier, and `tex`
is one of them, so you do not have to write the above in your
configuration file (you still need to enable this with the
attribute mechanism, via `.gitattributes`). Another built-in
pattern is defined for `java` that defines a pattern suitable
for program text in Java language.
attribute mechanism, via `.gitattributes`). The following built in
patterns are available:
- `bibtex` suitable for files with BibTeX coded references.
- `java` suitable for source code in the Java lanugage.
- `pascal` suitable for source code in the Pascal/Delphi language.
- `ruby` suitable for source code in the Ruby language.
- `tex` suitable for source code for LaTeX documents.
Performing a three-way merge

View File

@@ -1366,8 +1366,9 @@ your login shell is 'bash', only `.bashrc` is read and not
[NOTE]
If you plan to publish this repository to be accessed over http,
you should do `chmod +x my-git.git/hooks/post-update` at this
point. This makes sure that every time you push into this
you should do `mv my-git.git/hooks/post-update.sample
my-git.git/hooks/post-update` at this point.
This makes sure that every time you push into this
repository, `git update-server-info` is run.
Your "public repository" is now ready to accept your changes.
@@ -1486,11 +1487,11 @@ A recommended workflow for a "project lead" goes like this:
If other people are pulling from your repository over dumb
transport protocols (HTTP), you need to keep this repository
'dumb transport friendly'. After `git init`,
`$GIT_DIR/hooks/post-update` copied from the standard templates
would contain a call to 'git-update-server-info' but the
`post-update` hook itself is disabled by default -- enable it
with `chmod +x post-update`. This makes sure 'git-update-server-info'
keeps the necessary files up-to-date.
`$GIT_DIR/hooks/post-update.sample` copied from the standard templates
would contain a call to 'git-update-server-info'
but you need to manually enable the hook with
`mv post-update.sample post-update`. This makes sure
'git-update-server-info' keeps the necessary files up-to-date.
3. Push into the public repository from your primary
repository.

View File

@@ -6,7 +6,7 @@
<refspec>::
The canonical format of a <refspec> parameter is
`+?<src>:<dst>`; that is, an optional plus `+`, followed
`+?<src>:<dst>`; that is, an optional plus `{plus}`, followed
by the source ref, followed by a colon `:`, followed by
the destination ref.
+

View File

@@ -43,11 +43,13 @@ endif::git-rev-list[]
--parents::
Print the parents of the commit.
Print the parents of the commit. Also enables parent
rewriting, see 'History Simplification' below.
--children::
Print the children of the commit.
Print the children of the commit. Also enables parent
rewriting, see 'History Simplification' below.
ifdef::git-rev-list[]
--timestamp::
@@ -71,7 +73,7 @@ For example, if you have this topology:
o---x---a---a branch A
-----------------------------------------------------------------------
+
you would get an output line this:
you would get an output like this:
+
-----------------------------------------------------------------------
$ git rev-list --left-right --boundary --pretty=oneline A...B
@@ -94,6 +96,7 @@ you would get an output line this:
This implies the '--topo-order' option by default, but the
'--date-order' option may also be specified.
ifndef::git-rev-list[]
Diff Formatting
~~~~~~~~~~~~~~~
@@ -123,6 +126,7 @@ options may be given. See linkgit:git-diff-files[1] for more options.
-t::
Show the tree objects in the diff output. This implies '-r'.
endif::git-rev-list[]
Commit Limiting
~~~~~~~~~~~~~~~
@@ -191,14 +195,6 @@ endif::git-rev-list[]
Stop when a given path disappears from the tree.
--full-history::
Show also parts of history irrelevant to current state of a given
path. This turns off history simplification, which removed merges
which didn't change anything at all at some child. It will still actually
simplify away merges that didn't change anything at all into either
child.
--no-merges::
Do not print commits with more than one parent.
@@ -264,11 +260,10 @@ With '\--pretty' format other than oneline (for obvious reasons),
this causes the output to have two extra lines of information
taken from the reflog. By default, 'commit@\{Nth}' notation is
used in the output. When the starting commit is specified as
'commit@{now}', output also uses 'commit@\{timestamp}' notation
'commit@\{now}', output also uses 'commit@\{timestamp}' notation
instead. Under '\--pretty=oneline', the commit message is
prefixed with this information on the same line.
Cannot be combined with '\--reverse'.
This option cannot be combined with '\--reverse'.
See also linkgit:git-reflog[1].
--merge::
@@ -281,18 +276,144 @@ See also linkgit:git-reflog[1].
Output uninteresting commits at the boundary, which are usually
not shown.
--
History Simplification
~~~~~~~~~~~~~~~~~~~~~~
When optional paths are given, 'git-rev-list' simplifies commits with
various strategies, according to the options you have selected.
Suppose you specified `foo` as the <paths>. We shall call commits
that modify `foo` !TREESAME, and the rest TREESAME. (In a diff
filtered for `foo`, they look different and equal, respectively.)
In the following, we will always refer to the same example history to
illustrate the differences between simplification settings. We assume
that you are filtering for a file `foo` in this commit graph:
-----------------------------------------------------------------------
.-A---M---N---O---P
/ / / / /
I B C D E
\ / / / /
`-------------'
-----------------------------------------------------------------------
The horizontal line of history A--P is taken to be the first parent of
each merge. The commits are:
* `I` is the initial commit, in which `foo` exists with contents
"asdf", and a file `quux` exists with contents "quux". Initial
commits are compared to an empty tree, so `I` is !TREESAME.
* In `A`, `foo` contains just "foo".
* `B` contains the same change as `A`. Its merge `M` is trivial and
hence TREESAME to all parents.
* `C` does not change `foo`, but its merge `N` changes it to "foobar",
so it is not TREESAME to any parent.
* `D` sets `foo` to "baz". Its merge `O` combines the strings from
`N` and `D` to "foobarbaz"; i.e., it is not TREESAME to any parent.
* `E` changes `quux` to "xyzzy", and its merge `P` combines the
strings to "quux xyzzy". Despite appearing interesting, `P` is
TREESAME to all parents.
'rev-list' walks backwards through history, including or excluding
commits based on whether '\--full-history' and/or parent rewriting
(via '\--parents' or '\--children') are used. The following settings
are available.
Default mode::
Commits are included if they are not TREESAME to any parent
(though this can be changed, see '\--sparse' below). If the
commit was a merge, and it was TREESAME to one parent, follow
only that parent. (Even if there are several TREESAME
parents, follow only one of them.) Otherwise, follow all
parents.
+
This results in:
+
-----------------------------------------------------------------------
.-A---N---O
/ /
I---------D
-----------------------------------------------------------------------
+
Note how the rule to only follow the TREESAME parent, if one is
available, removed `B` from consideration entirely. `C` was
considered via `N`, but is TREESAME. Root commits are compared to an
empty tree, so `I` is !TREESAME.
+
Parent/child relations are only visible with --parents, but that does
not affect the commits selected in default mode, so we have shown the
parent lines.
--full-history without parent rewriting::
This mode differs from the default in one point: always follow
all parents of a merge, even if it is TREESAME to one of them.
Even if more than one side of the merge has commits that are
included, this does not imply that the merge itself is! In
the example, we get
+
-----------------------------------------------------------------------
I A B N D O
-----------------------------------------------------------------------
+
`P` and `M` were excluded because they are TREESAME to a parent. `E`,
`C` and `B` were all walked, but only `B` was !TREESAME, so the others
do not appear.
+
Note that without parent rewriting, it is not really possible to talk
about the parent/child relationships between the commits, so we show
them disconnected.
--full-history with parent rewriting::
Ordinary commits are only included if they are !TREESAME
(though this can be changed, see '\--sparse' below).
+
Merges are always included. However, their parent list is rewritten:
Along each parent, prune away commits that are not included
themselves. This results in
+
-----------------------------------------------------------------------
.-A---M---N---O---P
/ / / / /
I B / D /
\ / / / /
`-------------'
-----------------------------------------------------------------------
+
Compare to '\--full-history' without rewriting above. Note that `E`
was pruned away because it is TREESAME, but the parent list of P was
rewritten to contain `E`'s parent `I`. The same happened for `C` and
`N`. Note also that `P` was included despite being TREESAME.
In addition to the above settings, you can change whether TREESAME
affects inclusion:
--dense::
Commits that are walked are included if they are not TREESAME
to any parent.
--sparse::
When optional paths are given, the default behaviour ('--dense') is to
only output commits that changes at least one of them, and also ignore
merges that do not touch the given paths.
All commits that are walked are included.
+
Note that without '\--full-history', this still simplifies merges: if
one of the parents is TREESAME, we follow only that one, so the other
sides of the merge are never walked.
Use the '--sparse' flag to makes the command output all eligible commits
(still subject to count and age limitation), but apply merge
simplification nevertheless.
ifdef::git-rev-list[]
Bisection Helpers
~~~~~~~~~~~~~~~~~
--bisect::
Limit output to the one commit object which is roughly halfway between
@@ -342,7 +463,6 @@ after all the sorted commit objects, there will be the same text as if
`--bisect-vars` had been used alone.
endif::git-rev-list[]
--
Commit Ordering
~~~~~~~~~~~~~~~

View File

@@ -1128,8 +1128,8 @@ This typically includes files generated by a build process or temporary
backup files made by your editor. Of course, 'not' tracking files with git
is just a matter of 'not' calling "`git-add`" on them. But it quickly becomes
annoying to have these untracked files lying around; e.g. they make
"`git add .`" and "`git commit -a`" practically useless, and they keep
showing up in the output of "`git status`".
"`git add .`" practically useless, and they keep showing up in the output of
"`git status`".
You can tell git to ignore certain files by creating a file called .gitignore
in the top level of your working directory, with contents such as:
@@ -1890,7 +1890,7 @@ adjustments to give web clients some extra information they need:
$ mv proj.git /home/you/public_html/proj.git
$ cd proj.git
$ git --bare update-server-info
$ chmod a+x hooks/post-update
$ mv hooks/post-update.sample hooks/post-update
-------------------------------------------------
(For an explanation of the last two lines, see
@@ -2825,8 +2825,8 @@ You can also add a "+" to force the update each time:
$ git config remote.example.fetch +master:ref/remotes/example/master
-------------------------------------------------
Don't do this unless you're sure you won't mind "git-fetch" possibly
throwing away commits on mybranch.
Don't do this unless you're sure you won't mind "git fetch" possibly
throwing away commits on 'example/master'.
Also note that all of the above configuration can be performed by
directly editing the file .git/config instead of using

View File

@@ -16,6 +16,7 @@ elif test -d .git -o -f .git &&
case "$VN" in
*$LF*) (exit 1) ;;
v[0-9]*)
git update-index -q --refresh
test -z "$(git diff-index --name-only HEAD --)" ||
VN="$VN-dirty" ;;
esac

View File

@@ -1064,9 +1064,11 @@ export TAR INSTALL DESTDIR SHELL_PATH
### Build rules
all:: $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
SHELL = $(SHELL_PATH)
all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
ifneq (,$X)
$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$p';)
$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
endif
all::
@@ -1077,6 +1079,11 @@ endif
$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)
please_set_SHELL_PATH_to_a_more_modern_shell:
@$$(:)
shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
strip: $(PROGRAMS) git$X
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
@@ -1460,6 +1467,7 @@ endif
$(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS
.PHONY: all install clean strip
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
.PHONY: .FORCE-GIT-VERSION-FILE TAGS tags cscope .FORCE-GIT-CFLAGS
.PHONY: .FORCE-GIT-BUILD-OPTIONS

View File

@@ -330,7 +330,8 @@ static struct ref *write_remote_refs(const struct ref *refs,
struct ref *r;
get_fetch_map(refs, refspec, &tail, 0);
get_fetch_map(refs, tag_refspec, &tail, 0);
if (!option_mirror)
get_fetch_map(refs, tag_refspec, &tail, 0);
for (r = local_refs; r; r = r->next)
add_extra_ref(r->peer_ref->name, r->old_sha1, 0);

View File

@@ -203,7 +203,8 @@ static void handle_content_transfer_encoding(const struct strbuf *line)
static int is_multipart_boundary(const struct strbuf *line)
{
return !strbuf_cmp(line, *content_top);
return (((*content_top)->len <= line->len) &&
!memcmp(line->buf, (*content_top)->buf, (*content_top)->len));
}
static void cleanup_subject(struct strbuf *subject)
@@ -649,8 +650,11 @@ again:
check_header(&line, p_hdr_data, 0);
strbuf_release(&newline);
/* eat the blank line after section info */
return (strbuf_getline(&line, fin, '\n') == 0);
/* replenish line */
if (strbuf_getline(&line, fin, '\n'))
return 0;
strbuf_addch(&line, '\n');
return 1;
}
static inline int patchbreak(const struct strbuf *line)
@@ -757,9 +761,10 @@ static void handle_body(void)
/* process any boundary lines */
if (*content_top && is_multipart_boundary(&line)) {
/* flush any leftover */
if (line.len)
handle_filter(&line);
if (prev.len) {
handle_filter(&prev);
strbuf_reset(&prev);
}
if (!handle_boundary())
goto handle_body_out;
}

View File

@@ -604,8 +604,8 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
continue;
}
if (!dwim_ref(argv[i], spec - argv[i], sha1, &ref)) {
status |= error("%s points nowhere!", argv[i]);
if (!dwim_log(argv[i], spec - argv[i], sha1, &ref)) {
status |= error("no reflog for '%s'", argv[i]);
continue;
}

View File

@@ -131,7 +131,7 @@ static struct option builtin_rm_options[] = {
OPT__DRY_RUN(&show_only),
OPT__QUIET(&quiet),
OPT_BOOLEAN( 0 , "cached", &index_only, "only remove from the index"),
OPT_BOOLEAN('f', NULL, &force, "override the up-to-date check"),
OPT_BOOLEAN('f', "force", &force, "override the up-to-date check"),
OPT_BOOLEAN('r', NULL, &recursive, "allow recursive removal"),
OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
"exit with a zero status even if nothing matched"),

View File

@@ -501,7 +501,7 @@ __git_has_doubledash ()
return 1
}
__git_whitespacelist="nowarn warn error error-all strip"
__git_whitespacelist="nowarn warn error error-all fix"
_git_am ()
{
@@ -885,7 +885,11 @@ _git_help ()
return
;;
esac
__gitcomp "$(__git_all_commands)"
__gitcomp "$(__git_all_commands)
attributes cli core-tutorial cvs-migration
diffcore gitk glossary hooks ignore modules
repository-layout tutorial tutorial-2
"
}
_git_init ()
@@ -972,6 +976,7 @@ _git_log ()
--decorate --diff-filter=
--color-words --walk-reflogs
--parents --children --full-history
--merge
"
return
;;
@@ -1001,6 +1006,25 @@ _git_merge ()
__gitcomp "$(__git_refs)"
}
_git_mergetool ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
--tool=*)
__gitcomp "
kdiff3 tkdiff meld xxdiff emerge
vimdiff gvimdiff ecmerge opendiff
" "" "${cur##--tool=}"
return
;;
--*)
__gitcomp "--tool="
return
;;
esac
COMPREPLY=()
}
_git_merge_base ()
{
__gitcomp "$(__git_refs)"
@@ -1439,7 +1463,7 @@ _git_stash ()
apply,--*)
__gitcomp "--index"
;;
show,--*|apply,--*|drop,--*|pop,--*|branch,--*)
show,--*|drop,--*|pop,--*|branch,--*)
COMPREPLY=()
;;
show,*|apply,*|drop,*|pop,*|branch,*)
@@ -1650,6 +1674,7 @@ _git ()
ls-remote) _git_ls_remote ;;
ls-tree) _git_ls_tree ;;
merge) _git_merge;;
mergetool) _git_mergetool;;
merge-base) _git_merge_base ;;
mv) _git_mv ;;
name-rev) _git_name_rev ;;

View File

@@ -794,6 +794,7 @@ static void child_handler(int signo)
}
break;
}
signal(SIGCHLD, child_handler);
}
static int set_reuse_addr(int sockfd)

4
diff.c
View File

@@ -1387,6 +1387,7 @@ static struct builtin_funcname_pattern {
"\\|"
"^\\(.*=[ \t]*\\(class\\|record\\).*\\)$"
},
{ "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" },
{ "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" },
{ "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" },
};
@@ -1631,7 +1632,8 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
ecb.priv = &data;
xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
if (data.trailing_blanks_start) {
if ((data.ws_rule & WS_TRAILING_SPACE) &&
data.trailing_blanks_start) {
fprintf(o->file, "%s:%d: ends with blank lines.\n",
data.filename, data.trailing_blanks_start);
data.status = 1; /* report errors */

2
dir.c
View File

@@ -54,7 +54,7 @@ int common_prefix(const char **pathspec)
static inline int special_char(unsigned char c1)
{
return !c1 || c1 == '*' || c1 == '[' || c1 == '?';
return !c1 || c1 == '*' || c1 == '[' || c1 == '?' || c1 == '\\';
}
/*

View File

@@ -10,7 +10,7 @@ git am [options] (--resolved | --skip | --abort)
--
d,dotest= (removed -- do not use)
i,interactive run interactively
b,binary pass --allow-binary-replacement to git-apply
b,binary (historical option -- no-op)
3,3way allow fall back on 3way merging if needed
s,signoff add a Signed-off-by line to the commit message
u,utf8 recode into utf8 (default)
@@ -87,7 +87,7 @@ fall_back_3way () {
echo Using index info to reconstruct a base tree...
if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
git apply $binary --cached <"$dotest/patch"
git apply --cached <"$dotest/patch"
then
mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base"
mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index"
@@ -121,7 +121,7 @@ It does not apply to blobs recorded in its index."
prec=4
dotest="$GIT_DIR/rebase-apply"
sign= utf8=t keep= skip= interactive= resolved= binary= rebasing= abort=
sign= utf8=t keep= skip= interactive= resolved= rebasing= abort=
resolvemsg= resume=
git_apply_opt=
@@ -131,7 +131,7 @@ do
-i|--interactive)
interactive=t ;;
-b|--binary)
binary=t ;;
: ;;
-3|--3way)
threeway=t ;;
-s|--signoff)
@@ -149,7 +149,7 @@ do
--abort)
abort=t ;;
--rebasing)
rebasing=t threeway=t keep=t binary=t ;;
rebasing=t threeway=t keep=t ;;
-d|--dotest)
die "-d option is no longer supported. Do not use."
;;
@@ -247,10 +247,9 @@ else
exit 1
}
# -b, -s, -u, -k and --whitespace flags are kept for the
# -s, -u, -k and --whitespace flags are kept for the
# resuming session after a patch failure.
# -3 and -i can and must be given when resuming.
echo "$binary" >"$dotest/binary"
echo " $ws" >"$dotest/whitespace"
echo "$sign" >"$dotest/sign"
echo "$utf8" >"$dotest/utf8"
@@ -274,10 +273,6 @@ case "$resolved" in
fi
esac
if test "$(cat "$dotest/binary")" = t
then
binary=--allow-binary-replacement
fi
if test "$(cat "$dotest/utf8")" = t
then
utf8=-u
@@ -459,7 +454,7 @@ do
case "$resolved" in
'')
git apply $git_apply_opt $binary --index "$dotest/patch"
git apply $git_apply_opt --index "$dotest/patch"
apply_status=$?
;;
t)

View File

@@ -220,7 +220,8 @@ bisect_next_check() {
if test -t 0
then
printf >&2 'Are you sure [Y/n]? '
case "$(read yesno)" in [Nn]*) exit 1 ;; esac
read yesno
case "$yesno" in [Nn]*) exit 1 ;; esac
fi
: bisect without good...
;;

View File

@@ -361,9 +361,17 @@ do
;;
$_x40)
echo "Ref '$ref' was rewritten"
git update-ref -m "filter-branch: rewrite" \
"$ref" $rewritten $sha1 ||
die "Could not rewrite $ref"
if ! git update-ref -m "filter-branch: rewrite" \
"$ref" $rewritten $sha1 2>/dev/null; then
if test $(git cat-file -t "$ref") = tag; then
if test -z "$filter_tag_name"; then
warn "WARNING: You said to rewrite tagged commits, but not the corresponding tag."
warn "WARNING: Perhaps use '--tag-name-filter cat' to rewrite the tag."
fi
else
die "Could not rewrite $ref"
fi
fi
;;
*)
# NEEDSWORK: possibly add -Werror, making this an error

View File

@@ -145,7 +145,16 @@ pick_one () {
}
pick_one_preserving_merges () {
case "$1" in -n) sha1=$2 ;; *) sha1=$1 ;; esac
fast_forward=t
case "$1" in
-n)
fast_forward=f
sha1=$2
;;
*)
sha1=$1
;;
esac
sha1=$(git rev-parse $sha1)
if test -f "$DOTEST"/current-commit
@@ -156,15 +165,14 @@ pick_one_preserving_merges () {
die "Cannot write current commit's replacement sha1"
fi
echo $sha1 > "$DOTEST"/current-commit
# rewrite parents; if none were rewritten, we can fast-forward.
fast_forward=t
preserve=t
new_parents=
for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
do
if test -f "$REWRITTEN"/$p
then
preserve=f
new_p=$(cat "$REWRITTEN"/$p)
test $p != $new_p && fast_forward=f
case "$new_parents" in
@@ -181,7 +189,8 @@ pick_one_preserving_merges () {
case $fast_forward in
t)
output warn "Fast forward to $sha1"
test $preserve = f || echo $sha1 > "$REWRITTEN"/$sha1
output git reset --hard $sha1 ||
die "Cannot fast forward to $sha1"
;;
f)
test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
@@ -191,7 +200,6 @@ pick_one_preserving_merges () {
output git checkout $first_parent 2> /dev/null ||
die "Cannot move HEAD to $first_parent"
echo $sha1 > "$DOTEST"/current-commit
case "$new_parents" in
' '*' '*)
# redo merge

View File

@@ -1,7 +1,13 @@
#!/bin/sh
# Copyright (c) 2007, Nanako Shiraishi
USAGE='[ | save | list | show | apply | clear | drop | pop | create | branch ]'
dashless=$(basename "$0" | sed -e 's/-/ /')
USAGE="list [<options>]
or: $dashless (show | drop | pop ) [<stash>]
or: $dashless apply [--index] [<stash>]
or: $dashless branch <branchname> [<stash>]
or: $dashless [save [--keep-index] [<message>]]
or: $dashless clear"
SUBDIRECTORY_OK=Yes
OPTIONS_SPEC=

View File

@@ -66,7 +66,7 @@ my ($_stdin, $_help, $_edit,
$_version, $_fetch_all, $_no_rebase,
$_merge, $_strategy, $_dry_run, $_local,
$_prefix, $_no_checkout, $_url, $_verbose,
$_git_format);
$_git_format, $_commit_url);
$Git::SVN::_follow_parent = 1;
my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
'config-dir=s' => \$Git::SVN::Ra::config_dir,
@@ -127,6 +127,8 @@ my %cmd = (
'verbose|v' => \$_verbose,
'dry-run|n' => \$_dry_run,
'fetch-all|all' => \$_fetch_all,
'commit-url=s' => \$_commit_url,
'revision|r=i' => \$_revision,
'no-rebase' => \$_no_rebase,
%cmt_opts, %fc_opts } ],
'set-tree' => [ \&cmd_set_tree,
@@ -169,7 +171,8 @@ my %cmd = (
'color' => \$Git::SVN::Log::color,
'pager=s' => \$Git::SVN::Log::pager
} ],
'find-rev' => [ \&cmd_find_rev, "Translate between SVN revision numbers and tree-ish",
'find-rev' => [ \&cmd_find_rev,
"Translate between SVN revision numbers and tree-ish",
{} ],
'rebase' => [ \&cmd_rebase, "Fetch and rebase your working directory",
{ 'merge|m|M' => \$_merge,
@@ -229,7 +232,9 @@ unless ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
read_repo_config(\%opts);
Getopt::Long::Configure('pass_through') if ($cmd && ($cmd eq 'log' || $cmd eq 'blame'));
if ($cmd && ($cmd eq 'log' || $cmd eq 'blame')) {
Getopt::Long::Configure('pass_through');
}
my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
'minimize-connections' => \$Git::SVN::Migration::_minimize,
'id|i=s' => \$Git::SVN::default_ref_id,
@@ -416,6 +421,8 @@ sub cmd_dcommit {
$head ||= 'HEAD';
my @refs;
my ($url, $rev, $uuid, $gs) = working_head_info($head, \@refs);
$url = $_commit_url if defined $_commit_url;
my $last_rev = $_revision if defined $_revision;
if ($url) {
print "Committing to $url ...\n";
}
@@ -423,7 +430,6 @@ sub cmd_dcommit {
die "Unable to determine upstream SVN information from ",
"$head history.\nPerhaps the repository is empty.";
}
my $last_rev;
my ($linear_refs, $parents) = linearize_history($gs, \@refs);
if ($_no_rebase && scalar(@$linear_refs) > 1) {
warn "Attempting to commit more than one change while ",
@@ -446,7 +452,7 @@ sub cmd_dcommit {
my $cmt_rev;
my %ed_opts = ( r => $last_rev,
log => get_commit_entry($d)->{log},
ra => Git::SVN::Ra->new($gs->full_url),
ra => Git::SVN::Ra->new($url),
config => SVN::Core::config_get_config(
$Git::SVN::Ra::config_dir
),
@@ -984,8 +990,10 @@ sub complete_url_ls_init {
if (length $pfx && $pfx !~ m#/$#) {
die "--prefix='$pfx' must have a trailing slash '/'\n";
}
command_noisy('config', "svn-remote.$gs->{repo_id}.$n",
"$remote_path:refs/remotes/$pfx*");
command_noisy('config',
"svn-remote.$gs->{repo_id}.$n",
"$remote_path:refs/remotes/$pfx*" .
('/*' x (($remote_path =~ tr/*/*/) - 1)) );
}
sub verify_ref {
@@ -1257,7 +1265,7 @@ sub md5sum {
my $arg = shift;
my $ref = ref $arg;
my $md5 = Digest::MD5->new();
if ($ref eq 'GLOB' || $ref eq 'IO::File') {
if ($ref eq 'GLOB' || $ref eq 'IO::File' || $ref eq 'File::Temp') {
$md5->addfile($arg) or croak $!;
} elsif ($ref eq 'SCALAR') {
$md5->add($$arg) or croak $!;
@@ -1320,6 +1328,7 @@ BEGIN {
}
}
my (%LOCKFILES, %INDEX_FILES);
END {
unlink keys %LOCKFILES if %LOCKFILES;
@@ -3222,13 +3231,11 @@ sub change_file_prop {
sub apply_textdelta {
my ($self, $fb, $exp) = @_;
my $fh = IO::File->new_tmpfile;
$fh->autoflush(1);
my $fh = Git::temp_acquire('svn_delta');
# $fh gets auto-closed() by SVN::TxDelta::apply(),
# (but $base does not,) so dup() it for reading in close_file
open my $dup, '<&', $fh or croak $!;
my $base = IO::File->new_tmpfile;
$base->autoflush(1);
my $base = Git::temp_acquire('git_blob');
if ($fb->{blob}) {
print $base 'link ' if ($fb->{mode_a} == 120000);
my $size = $::_repository->cat_blob($fb->{blob}, $base);
@@ -3243,9 +3250,9 @@ sub apply_textdelta {
}
}
seek $base, 0, 0 or croak $!;
$fb->{fh} = $dup;
$fb->{fh} = $fh;
$fb->{base} = $base;
[ SVN::TxDelta::apply($base, $fh, undef, $fb->{path}, $fb->{pool}) ];
[ SVN::TxDelta::apply($base, $dup, undef, $fb->{path}, $fb->{pool}) ];
}
sub close_file {
@@ -3261,35 +3268,36 @@ sub close_file {
"expected: $exp\n got: $got\n";
}
}
sysseek($fh, 0, 0) or croak $!;
if ($fb->{mode_b} == 120000) {
eval {
sysread($fh, my $buf, 5) == 5 or croak $!;
$buf eq 'link ' or die "$path has mode 120000",
" but is not a link";
};
if ($@) {
warn "$@\n";
sysseek($fh, 0, 0) or croak $!;
sysseek($fh, 0, 0) or croak $!;
sysread($fh, my $buf, 5) == 5 or croak $!;
unless ($buf eq 'link ') {
warn "$path has mode 120000",
" but is not a link\n";
} else {
my $tmp_fh = Git::temp_acquire('svn_hash');
my $res;
while ($res = sysread($fh, my $str, 1024)) {
my $out = syswrite($tmp_fh, $str, $res);
defined($out) && $out == $res
or croak("write ",
$tmp_fh->filename,
": $!\n");
}
defined $res or croak $!;
($fh, $tmp_fh) = ($tmp_fh, $fh);
Git::temp_release($tmp_fh, 1);
}
}
my ($tmp_fh, $tmp_filename) = File::Temp::tempfile(UNLINK => 1);
my $result;
while ($result = sysread($fh, my $string, 1024)) {
my $wrote = syswrite($tmp_fh, $string, $result);
defined($wrote) && $wrote == $result
or croak("write $tmp_filename: $!\n");
}
defined $result or croak $!;
close $tmp_fh or croak $!;
close $fh or croak $!;
$hash = $::_repository->hash_and_insert_object($tmp_filename);
unlink($tmp_filename);
$hash = $::_repository->hash_and_insert_object(
$fh->filename);
$hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
close $fb->{base} or croak $!;
Git::temp_release($fb->{base}, 1);
Git::temp_release($fh, 1);
} else {
$hash = $fb->{blob} or die "no blob information\n";
}
@@ -3659,7 +3667,7 @@ sub chg_file {
} elsif ($m->{mode_b} !~ /755$/ && $m->{mode_a} =~ /755$/) {
$self->change_file_prop($fbat,'svn:executable',undef);
}
my $fh = IO::File->new_tmpfile or croak $!;
my $fh = Git::temp_acquire('git_blob');
if ($m->{mode_b} =~ /^120/) {
print $fh 'link ' or croak $!;
$self->change_file_prop($fbat,'svn:special','*');
@@ -3678,9 +3686,8 @@ sub chg_file {
my $atd = $self->apply_textdelta($fbat, undef, $pool);
my $got = SVN::TxDelta::send_stream($fh, @$atd, $pool);
die "Checksum mismatch\nexpected: $exp\ngot: $got\n" if ($got ne $exp);
Git::temp_release($fh, 1);
$pool->clear;
close $fh or croak $!;
}
sub D {
@@ -4121,16 +4128,38 @@ sub gs_fetch_loop_common {
Git::SVN::gc();
}
sub get_dir_globbed {
my ($self, $left, $depth, $r) = @_;
my @x = eval { $self->get_dir($left, $r) };
return unless scalar @x == 3;
my $dirents = $x[0];
my @finalents;
foreach my $de (keys %$dirents) {
next if $dirents->{$de}->{kind} != $SVN::Node::dir;
if ($depth > 1) {
my @args = ("$left/$de", $depth - 1, $r);
foreach my $dir ($self->get_dir_globbed(@args)) {
push @finalents, "$de/$dir";
}
} else {
push @finalents, $de;
}
}
@finalents;
}
sub match_globs {
my ($self, $exists, $paths, $globs, $r) = @_;
sub get_dir_check {
my ($self, $exists, $g, $r) = @_;
my @x = eval { $self->get_dir($g->{path}->{left}, $r) };
return unless scalar @x == 3;
my $dirents = $x[0];
foreach my $de (keys %$dirents) {
next if $dirents->{$de}->{kind} != $SVN::Node::dir;
my @dirs = $self->get_dir_globbed($g->{path}->{left},
$g->{path}->{depth},
$r);
foreach my $de (@dirs) {
my $p = $g->{path}->full_path($de);
next if $exists->{$p};
next if (length $g->{path}->{right} &&
@@ -4912,15 +4941,20 @@ sub new {
my ($class, $glob) = @_;
my $re = $glob;
$re =~ s!/+$!!g; # no need for trailing slashes
my $nr = ($re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g);
my ($left, $right) = ($1, $2);
if ($nr > 1) {
die "Only one '*' wildcard expansion ",
"is supported (got $nr): '$glob'\n";
} elsif ($nr == 0) {
$re =~ m!^([^*]*)(\*(?:/\*)*)([^*]*)$!;
my $temp = $re;
my ($left, $right) = ($1, $3);
$re = $2;
my $depth = $re =~ tr/*/*/;
if ($depth != $temp =~ tr/*/*/) {
die "Only one set of wildcard directories " .
"(e.g. '*' or '*/*/*') is supported: '$glob'\n";
}
if ($depth == 0) {
die "One '*' is needed for glob: '$glob'\n";
}
$re = quotemeta($left) . $re . quotemeta($right);
$re =~ s!\*!\[^/\]*!g;
$re = quotemeta($left) . "($re)" . quotemeta($right);
if (length $left && !($left =~ s!/+$!!g)) {
die "Missing trailing '/' on left side of: '$glob' ($left)\n";
}
@@ -4929,7 +4963,7 @@ sub new {
}
my $left_re = qr/^\/\Q$left\E(\/|$)/;
bless { left => $left, right => $right, left_regex => $left_re,
regex => qr/$re/, glob => $glob }, $class;
regex => qr/$re/, glob => $glob, depth => $depth }, $class;
}
sub full_path {

2
path.c
View File

@@ -365,7 +365,7 @@ int normalize_absolute_path(char *buf, const char *path)
* path = Canonical absolute path
* prefix_list = Colon-separated list of absolute paths
*
* Determines, for each path in parent_list, whether the "prefix" really
* Determines, for each path in prefix_list, whether the "prefix" really
* is an ancestor directory of path. Returns the length of the longest
* ancestor directory, excluding any trailing slashes, or -1 if no prefix
* is an ancestor. (Note that this means 0 is returned if prefix_list is

View File

@@ -57,7 +57,8 @@ require Exporter;
command_output_pipe command_input_pipe command_close_pipe
command_bidi_pipe command_close_bidi_pipe
version exec_path hash_object git_cmd_try
remote_refs);
remote_refs
temp_acquire temp_release temp_reset);
=head1 DESCRIPTION
@@ -99,7 +100,7 @@ use Carp qw(carp croak); # but croak is bad - throw instead
use Error qw(:try);
use Cwd qw(abs_path);
use IPC::Open2 qw(open2);
use Fcntl qw(SEEK_SET SEEK_CUR);
}
@@ -933,6 +934,131 @@ sub _close_cat_blob {
delete @$self{@vars};
}
{ # %TEMP_* Lexical Context
my (%TEMP_LOCKS, %TEMP_FILES);
=item temp_acquire ( NAME )
Attempts to retreive the temporary file mapped to the string C<NAME>. If an
associated temp file has not been created this session or was closed, it is
created, cached, and set for autoflush and binmode.
Internally locks the file mapped to C<NAME>. This lock must be released with
C<temp_release()> when the temp file is no longer needed. Subsequent attempts
to retrieve temporary files mapped to the same C<NAME> while still locked will
cause an error. This locking mechanism provides a weak guarantee and is not
threadsafe. It does provide some error checking to help prevent temp file refs
writing over one another.
In general, the L<File::Handle> returned should not be closed by consumers as
it defeats the purpose of this caching mechanism. If you need to close the temp
file handle, then you should use L<File::Temp> or another temp file faculty
directly. If a handle is closed and then requested again, then a warning will
issue.
=cut
sub temp_acquire {
my ($self, $name) = _maybe_self(@_);
my $temp_fd = _temp_cache($name);
$TEMP_LOCKS{$temp_fd} = 1;
$temp_fd;
}
=item temp_release ( NAME )
=item temp_release ( FILEHANDLE )
Releases a lock acquired through C<temp_acquire()>. Can be called either with
the C<NAME> mapping used when acquiring the temp file or with the C<FILEHANDLE>
referencing a locked temp file.
Warns if an attempt is made to release a file that is not locked.
The temp file will be truncated before being released. This can help to reduce
disk I/O where the system is smart enough to detect the truncation while data
is in the output buffers. Beware that after the temp file is released and
truncated, any operations on that file may fail miserably until it is
re-acquired. All contents are lost between each release and acquire mapped to
the same string.
=cut
sub temp_release {
my ($self, $temp_fd, $trunc) = _maybe_self(@_);
if (ref($temp_fd) ne 'File::Temp') {
$temp_fd = $TEMP_FILES{$temp_fd};
}
unless ($TEMP_LOCKS{$temp_fd}) {
carp "Attempt to release temp file '",
$temp_fd, "' that has not been locked";
}
temp_reset($temp_fd) if $trunc and $temp_fd->opened;
$TEMP_LOCKS{$temp_fd} = 0;
undef;
}
sub _temp_cache {
my ($name) = @_;
_verify_require();
my $temp_fd = \$TEMP_FILES{$name};
if (defined $$temp_fd and $$temp_fd->opened) {
if ($TEMP_LOCKS{$$temp_fd}) {
throw Error::Simple("Temp file with moniker '",
$name, "' already in use");
}
} else {
if (defined $$temp_fd) {
# then we're here because of a closed handle.
carp "Temp file '", $name,
"' was closed. Opening replacement.";
}
$$temp_fd = File::Temp->new(
TEMPLATE => 'Git_XXXXXX',
DIR => File::Spec->tmpdir
) or throw Error::Simple("couldn't open new temp file");
$$temp_fd->autoflush;
binmode $$temp_fd;
}
$$temp_fd;
}
sub _verify_require {
eval { require File::Temp; require File::Spec; };
$@ and throw Error::Simple($@);
}
=item temp_reset ( FILEHANDLE )
Truncates and resets the position of the C<FILEHANDLE>.
=cut
sub temp_reset {
my ($self, $temp_fd) = _maybe_self(@_);
truncate $temp_fd, 0
or throw Error::Simple("couldn't truncate file");
sysseek($temp_fd, 0, SEEK_SET) and seek($temp_fd, 0, SEEK_SET)
or throw Error::Simple("couldn't seek to beginning of file");
sysseek($temp_fd, 0, SEEK_CUR) == 0 and tell($temp_fd) == 0
or throw Error::Simple("expected file position to be reset");
}
sub END {
unlink values %TEMP_FILES if %TEMP_FILES;
}
} # %TEMP_* Lexical Context
=back
=head1 ERROR HANDLING

View File

@@ -36,7 +36,7 @@ test_expect_success 'setup' '
test_expect_success 'am' '
git am --binary -3 <patchfile &&
git am -3 <patchfile &&
git diff-files --name-status --exit-code
'

View File

@@ -188,16 +188,30 @@ test_expect_success 'delete' '
test_tick &&
git commit -m tiger C &&
test 5 = $(git reflog | wc -l) &&
HEAD_entry_count=$(git reflog | wc -l)
master_entry_count=$(git reflog show master | wc -l)
test $HEAD_entry_count = 5 &&
test $master_entry_count = 5 &&
git reflog delete master@{1} &&
git reflog show master > output &&
test 4 = $(wc -l < output) &&
test $(($master_entry_count - 1)) = $(wc -l < output) &&
test $HEAD_entry_count = $(git reflog | wc -l) &&
! grep ox < output &&
master_entry_count=$(wc -l < output)
git reflog delete HEAD@{1} &&
test $(($HEAD_entry_count -1)) = $(git reflog | wc -l) &&
test $master_entry_count = $(git reflog show master | wc -l) &&
HEAD_entry_count=$(git reflog | wc -l)
git reflog delete master@{07.04.2005.15:15:00.-0700} &&
git reflog show master > output &&
test 3 = $(wc -l < output) &&
test $(($master_entry_count - 1)) = $(wc -l < output) &&
! grep dragon < output
'

View File

@@ -202,6 +202,9 @@ test_expect_success 'retain authorship when squashing' '
test_expect_success '-p handles "no changes" gracefully' '
HEAD=$(git rev-parse HEAD) &&
git rebase -i -p HEAD^ &&
git update-index --refresh &&
git diff-files --quiet &&
git diff-index --quiet --cached HEAD -- &&
test $HEAD = $(git rev-parse HEAD)
'
@@ -235,6 +238,9 @@ test_expect_success 'preserve merges with -p' '
git checkout -b to-be-rebased &&
test_tick &&
git rebase -i -p --onto branch1 master &&
git update-index --refresh &&
git diff-files --quiet &&
git diff-index --quiet --cached HEAD -- &&
test $(git rev-parse HEAD~6) = $(git rev-parse branch1) &&
test $(git rev-parse HEAD~4^2) = $(git rev-parse to-be-preserved) &&
test $(git rev-parse HEAD^^2^) = $(git rev-parse HEAD^^^) &&
@@ -244,6 +250,18 @@ test_expect_success 'preserve merges with -p' '
test $(git show HEAD:unrelated-file) = 1
'
test_expect_success 'edit ancestor with -p' '
FAKE_LINES="1 edit 2 3 4" git rebase -i -p HEAD~3 &&
echo 2 > unrelated-file &&
test_tick &&
git commit -m L2-modified --amend unrelated-file &&
git rebase --continue &&
git update-index --refresh &&
git diff-files --quiet &&
git diff-index --quiet --cached HEAD -- &&
test $(git show HEAD:unrelated-file) = 2
'
test_expect_success '--continue tries to commit' '
test_tick &&
test_must_fail git rebase -i --onto new-branch1 HEAD^ &&

View File

@@ -232,4 +232,12 @@ test_expect_success 'git add (add.ignore-errors = false)' '
fi # skip chmod 0 tests
test_expect_success 'git add '\''fo\[ou\]bar'\'' ignores foobar' '
git reset --hard &&
touch fo\[ou\]bar foobar &&
git add '\''fo\[ou\]bar'\'' &&
git ls-files fo\[ou\]bar | grep -F fo\[ou\]bar &&
! ( git ls-files foobar | grep foobar )
'
test_done

View File

@@ -13,7 +13,8 @@ test_expect_success setup '
echo " HT and SP indent" >>F &&
echo "With trailing SP " >>F &&
echo "Carriage ReturnQ" | tr Q "\015" >>F &&
echo "No problem" >>F
echo "No problem" >>F &&
echo >>F
'
@@ -160,4 +161,21 @@ test_expect_success 'with cr-at-eol (attribute)' '
'
test_expect_success 'trailing empty lines (1)' '
rm -f .gitattributes &&
test_must_fail git diff --check >output &&
grep "ends with blank lines." output &&
grep "trailing whitespace" output
'
test_expect_success 'trailing empty lines (2)' '
echo "F -whitespace" >.gitattributes &&
git diff --check >output &&
! test -s output
'
test_done

View File

@@ -11,7 +11,7 @@ test_expect_success 'split sample box' \
'git mailsplit -o. ../t5100/sample.mbox >last &&
last=`cat last` &&
echo total is $last &&
test `cat last` = 10'
test `cat last` = 11'
for mail in `echo 00*`
do

5
t/t5100/info0011 Normal file
View File

@@ -0,0 +1,5 @@
Author: A U Thor
Email: a.u.thor@example.com
Subject: Xyzzy
Date: Fri, 8 Aug 2008 13:08:37 +0200 (CEST)

2
t/t5100/msg0011 Normal file
View File

@@ -0,0 +1,2 @@
Here comes a commit log message, and
its second line is here.

22
t/t5100/patch0011 Normal file
View File

@@ -0,0 +1,22 @@
---
builtin-mailinfo.c | 4 ++--
diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index 3e5fe51..aabfe5c 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -758,8 +758,8 @@ static void handle_body(void)
/* process any boundary lines */
if (*content_top && is_multipart_boundary(&line)) {
/* flush any leftover */
- if (line.len)
- handle_filter(&line);
+ if (prev.len)
+ handle_filter(&prev);
if (!handle_boundary())
goto handle_body_out;
--
1.6.0.rc2

View File

@@ -465,3 +465,38 @@ index 962aa34..2d1520f 100644
--
1.5.6.2.455.g1efb2
From nobody Fri Aug 8 22:24:03 2008
Date: Fri, 8 Aug 2008 13:08:37 +0200 (CEST)
From: A U Thor <a.u.thor@example.com>
Subject: [PATCH 3/3 v2] Xyzzy
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
--=-=-=
Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: quoted-printable
Here comes a commit log message, and
its second line is here.
---
builtin-mailinfo.c | 4 ++--
diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index 3e5fe51..aabfe5c 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -758,8 +758,8 @@ static void handle_body(void)
/* process any boundary lines */
if (*content_top && is_multipart_boundary(&line)) {
/* flush any leftover */
- if (line.len)
- handle_filter(&line);
+ if (prev.len)
+ handle_filter(&prev);
=20
if (!handle_boundary())
goto handle_body_out;
--=20
1.6.0.rc2
--=-=-=--

View File

@@ -21,7 +21,7 @@ test_expect_success 'prune stale packs' '
orig_pack=$(echo .git/objects/pack/*.pack) &&
: > .git/objects/tmp_1.pack &&
: > .git/objects/tmp_2.pack &&
test-chmtime -86501 .git/objects/tmp_1.pack &&
test-chmtime =-86501 .git/objects/tmp_1.pack &&
git prune --expire 1.day &&
test -f $orig_pack &&
test -f .git/objects/tmp_2.pack &&
@@ -39,7 +39,7 @@ test_expect_success 'prune --expire' '
git prune --expire=1.hour.ago &&
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test -f $BLOB_FILE &&
test-chmtime -86500 $BLOB_FILE &&
test-chmtime =-86500 $BLOB_FILE &&
git prune --expire 1.day &&
test $before = $(git count-objects | sed "s/ .*//") &&
! test -f $BLOB_FILE
@@ -53,11 +53,11 @@ test_expect_success 'gc: implicit prune --expire' '
BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test -f $BLOB_FILE &&
test-chmtime -$((86400*14-30)) $BLOB_FILE &&
test-chmtime =-$((86400*14-30)) $BLOB_FILE &&
git gc &&
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test -f $BLOB_FILE &&
test-chmtime -$((86400*14+1)) $BLOB_FILE &&
test-chmtime =-$((86400*14+1)) $BLOB_FILE &&
git gc &&
test $before = $(git count-objects | sed "s/ .*//") &&
! test -f $BLOB_FILE

View File

@@ -41,7 +41,7 @@ test_expect_success 'setup remote repository' '
git clone --bare test_repo test_repo.git &&
cd test_repo.git &&
git --bare update-server-info &&
chmod +x hooks/post-update &&
mv hooks/post-update.sample hooks/post-update &&
cd - &&
mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
'

View File

@@ -95,4 +95,16 @@ test_expect_success 'clone --bare names the local repository <name>.git' '
'
test_expect_success 'clone --mirror does not repeat tags' '
(cd src &&
git tag some-tag HEAD) &&
git clone --mirror src mirror2 &&
(cd mirror2 &&
git show-ref 2> clone.err > clone.out) &&
test_must_fail grep Duplicate mirror2/clone.err &&
grep some-tag mirror2/clone.out
'
test_done

View File

@@ -16,7 +16,8 @@ test_expect_success 'test refspec globbing' '
echo "goodbye world" > trunk/src/b/readme &&
svn import -m "initial" trunk "$svnrepo"/trunk &&
svn co "$svnrepo" tmp &&
cd tmp &&
(
cd tmp &&
mkdir branches tags &&
svn add branches tags &&
svn cp trunk branches/start &&
@@ -37,7 +38,7 @@ test_expect_success 'test refspec globbing' '
echo "byebye" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
svn commit -m "nothing to see here"
cd .. &&
) &&
git config --add svn-remote.svn.url "$svnrepo" &&
git config --add svn-remote.svn.fetch \
"trunk/src/a:refs/remotes/trunk" &&
@@ -48,11 +49,12 @@ test_expect_success 'test refspec globbing' '
git-svn multi-fetch &&
git log --pretty=oneline refs/remotes/tags/end | \
sed -e "s/^.\{41\}//" > output.end &&
cmp expect.end output.end &&
test_cmp expect.end output.end &&
test "`git rev-parse refs/remotes/tags/end~1`" = \
"`git rev-parse refs/remotes/branches/start`" &&
test "`git rev-parse refs/remotes/branches/start~2`" = \
"`git rev-parse refs/remotes/trunk`"
"`git rev-parse refs/remotes/trunk`" &&
test_must_fail git rev-parse refs/remotes/tags/end@3
'
echo try to try > expect.two
@@ -66,11 +68,12 @@ test_expect_success 'test left-hand-side only globbing' '
"branches/*:refs/remotes/two/branches/*" &&
git config --add svn-remote.two.tags \
"tags/*:refs/remotes/two/tags/*" &&
cd tmp &&
(
cd tmp &&
echo "try try" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
svn commit -m "try to try"
cd .. &&
) &&
git-svn fetch two &&
test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
test `git rev-list refs/remotes/two/branches/start | wc -l` -eq 3 &&
@@ -80,7 +83,29 @@ test_expect_success 'test left-hand-side only globbing' '
`git rev-parse refs/remotes/two/branches/start` &&
git log --pretty=oneline refs/remotes/two/tags/end | \
sed -e "s/^.\{41\}//" > output.two &&
cmp expect.two output.two
test_cmp expect.two output.two
'
echo "Only one set of wildcard directories" \
"(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
echo "" >> expect.three
test_expect_success 'test disallow multi-globs' '
git config --add svn-remote.three.url "$svnrepo" &&
git config --add svn-remote.three.fetch \
trunk:refs/remotes/three/trunk &&
git config --add svn-remote.three.branches \
"branches/*/t/*:refs/remotes/three/branches/*" &&
git config --add svn-remote.three.tags \
"tags/*/*:refs/remotes/three/tags/*" &&
(
cd tmp &&
echo "try try" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
svn commit -m "try to try"
) &&
test_must_fail git-svn fetch three 2> stderr.three &&
test_cmp expect.three stderr.three
'
test_done

160
t/t9108-git-svn-multi-glob.sh Executable file
View File

@@ -0,0 +1,160 @@
#!/bin/sh
# Copyright (c) 2007 Eric Wong
test_description='git-svn globbing refspecs'
. ./lib-git-svn.sh
cat > expect.end <<EOF
the end
hi
start a new branch
initial
EOF
test_expect_success 'test refspec globbing' '
mkdir -p trunk/src/a trunk/src/b trunk/doc &&
echo "hello world" > trunk/src/a/readme &&
echo "goodbye world" > trunk/src/b/readme &&
svn import -m "initial" trunk "$svnrepo"/trunk &&
svn co "$svnrepo" tmp &&
(
cd tmp &&
mkdir branches branches/v1 tags &&
svn add branches tags &&
svn cp trunk branches/v1/start &&
svn commit -m "start a new branch" &&
svn up &&
echo "hi" >> branches/v1/start/src/b/readme &&
poke branches/v1/start/src/b/readme &&
echo "hey" >> branches/v1/start/src/a/readme &&
poke branches/v1/start/src/a/readme &&
svn commit -m "hi" &&
svn up &&
svn cp branches/v1/start tags/end &&
echo "bye" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
echo "aye" >> tags/end/src/a/readme &&
poke tags/end/src/a/readme &&
svn commit -m "the end" &&
echo "byebye" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
svn commit -m "nothing to see here"
) &&
git config --add svn-remote.svn.url "$svnrepo" &&
git config --add svn-remote.svn.fetch \
"trunk/src/a:refs/remotes/trunk" &&
git config --add svn-remote.svn.branches \
"branches/*/*/src/a:refs/remotes/branches/*/*" &&
git config --add svn-remote.svn.tags\
"tags/*/src/a:refs/remotes/tags/*" &&
git-svn multi-fetch &&
git log --pretty=oneline refs/remotes/tags/end | \
sed -e "s/^.\{41\}//" > output.end &&
test_cmp expect.end output.end &&
test "`git rev-parse refs/remotes/tags/end~1`" = \
"`git rev-parse refs/remotes/branches/v1/start`" &&
test "`git rev-parse refs/remotes/branches/v1/start~2`" = \
"`git rev-parse refs/remotes/trunk`" &&
test_must_fail git rev-parse refs/remotes/tags/end@3
'
echo try to try > expect.two
echo nothing to see here >> expect.two
cat expect.end >> expect.two
test_expect_success 'test left-hand-side only globbing' '
git config --add svn-remote.two.url "$svnrepo" &&
git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk &&
git config --add svn-remote.two.branches \
"branches/*/*:refs/remotes/two/branches/*/*" &&
git config --add svn-remote.two.tags \
"tags/*:refs/remotes/two/tags/*" &&
(
cd tmp &&
echo "try try" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
svn commit -m "try to try"
) &&
git-svn fetch two &&
test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 &&
test `git rev-parse refs/remotes/two/branches/v1/start~2` = \
`git rev-parse refs/remotes/two/trunk` &&
test `git rev-parse refs/remotes/two/tags/end~3` = \
`git rev-parse refs/remotes/two/branches/v1/start` &&
git log --pretty=oneline refs/remotes/two/tags/end | \
sed -e "s/^.\{41\}//" > output.two &&
test_cmp expect.two output.two
'
cat > expect.four <<EOF
adios
adding more
Changed 2 in v2/start
Another versioned branch
initial
EOF
test_expect_success 'test another branch' '
(
cd tmp &&
mkdir branches/v2 &&
svn add branches/v2 &&
svn cp trunk branches/v2/start &&
svn commit -m "Another versioned branch" &&
svn up &&
echo "hello" >> branches/v2/start/src/b/readme &&
poke branches/v2/start/src/b/readme &&
echo "howdy" >> branches/v2/start/src/a/readme &&
poke branches/v2/start/src/a/readme &&
svn commit -m "Changed 2 in v2/start" &&
svn up &&
svn cp branches/v2/start tags/next &&
echo "bye" >> tags/next/src/b/readme &&
poke tags/next/src/b/readme &&
echo "aye" >> tags/next/src/a/readme &&
poke tags/next/src/a/readme &&
svn commit -m "adding more" &&
echo "byebye" >> tags/next/src/b/readme &&
poke tags/next/src/b/readme &&
svn commit -m "adios"
) &&
git config --add svn-remote.four.url "$svnrepo" &&
git config --add svn-remote.four.fetch trunk:refs/remotes/four/trunk &&
git config --add svn-remote.four.branches \
"branches/*/*:refs/remotes/four/branches/*/*" &&
git config --add svn-remote.four.tags \
"tags/*:refs/remotes/four/tags/*" &&
git-svn fetch four &&
test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 &&
test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 &&
test `git rev-parse refs/remotes/four/branches/v2/start~2` = \
`git rev-parse refs/remotes/four/trunk` &&
test `git rev-parse refs/remotes/four/tags/next~2` = \
`git rev-parse refs/remotes/four/branches/v2/start` &&
git log --pretty=oneline refs/remotes/four/tags/next | \
sed -e "s/^.\{41\}//" > output.four &&
test_cmp expect.four output.four
'
echo "Only one set of wildcard directories" \
"(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
echo "" >> expect.three
test_expect_success 'test disallow multiple globs' '
git config --add svn-remote.three.url "$svnrepo" &&
git config --add svn-remote.three.fetch \
trunk:refs/remotes/three/trunk &&
git config --add svn-remote.three.branches \
"branches/*/t/*:refs/remotes/three/branches/*/*" &&
git config --add svn-remote.three.tags \
"tags/*:refs/remotes/three/tags/*" &&
(
cd tmp &&
echo "try try" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
svn commit -m "try to try"
) &&
test_must_fail git-svn fetch three 2> stderr.three &&
test_cmp expect.three stderr.three
'
test_done

View File

@@ -0,0 +1,37 @@
#!/bin/sh
# Copyright (c) 2008 Marcus Griep
test_description='git-svn multi-glob branch names'
. ./lib-git-svn.sh
test_expect_success 'setup svnrepo' '
mkdir project project/trunk project/branches \
project/branches/v14.1 project/tags &&
echo foo > project/trunk/foo &&
svn import -m "$test_description" project "$svnrepo/project" &&
rm -rf project &&
svn cp -m "fun" "$svnrepo/project/trunk" \
"$svnrepo/project/branches/v14.1/beta" &&
svn cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
"$svnrepo/project/branches/v14.1/gold"
'
test_expect_success 'test clone with multi-glob in branch names' '
git svn clone -T trunk -b branches/*/* -t tags \
"$svnrepo/project" project &&
cd project &&
git rev-parse "refs/remotes/v14.1/beta" &&
git rev-parse "refs/remotes/v14.1/gold" &&
cd ..
'
test_expect_success 'test dcommit to multi-globbed branch' "
cd project &&
git reset --hard 'refs/remotes/v14.1/gold' &&
echo hello >> foo &&
git commit -m 'hello' -- foo &&
git svn dcommit &&
cd ..
"
test_done

View File

@@ -15,7 +15,7 @@ int length_callback(const struct option *opt, const char *arg, int unset)
if (unset)
return 1; /* do not support unset */
*(unsigned long *)opt->value = strlen(arg);
*(int *)opt->value = strlen(arg);
return 0;
}

View File

@@ -463,17 +463,14 @@ static struct ref *get_refs_via_curl(struct transport *transport)
run_active_slot(slot);
if (results.curl_result != CURLE_OK) {
strbuf_release(&buffer);
if (missing_target(&results)) {
return NULL;
} else {
error("%s", curl_errorstr);
return NULL;
}
if (missing_target(&results))
die("%s not found: did you run git update-server-info on the server?", refs_url);
else
die("%s download error - %s", refs_url, curl_errorstr);
}
} else {
strbuf_release(&buffer);
error("Unable to start request");
return NULL;
die("Unable to start HTTP request");
}
data = buffer.buf;