Merge branch 'fk/relink-upon-ldflags-update' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 16 Aug 2011 18:23:26 +0000 (11:23 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Aug 2011 18:23:26 +0000 (11:23 -0700)
* fk/relink-upon-ldflags-update:
Makefile: Track changes to LDFLAGS and relink when necessary

50 files changed:
Documentation/.gitignore
Documentation/Makefile
Documentation/RelNotes/1.7.6.txt
Documentation/diff-options.txt
Documentation/git-check-ref-format.txt
Documentation/git-fast-import.txt
Documentation/git-filter-branch.txt
Documentation/git-remote.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/glossary-content.txt
Documentation/rev-list-options.txt
Documentation/technical/api-builtin.txt
Documentation/technical/index-format.txt
Documentation/technical/pack-protocol.txt
GIT-VERSION-GEN
builtin/branch.c
builtin/checkout.c
combine-diff.c
compat/cygwin.c
config.c
connect.c
contrib/completion/git-completion.bash
diff-lib.c
diff.c
git-am.sh
git-filter-branch.sh
git-rebase--interactive.sh
git-submodule.sh
git-svn.perl
refs.c
refs.h
remote-curl.c
sha1_file.c
submodule.c
t/aggregate-results.sh
t/t2018-checkout-branch.sh
t/t3404-rebase-interactive.sh
t/t3409-rebase-preserve-merges.sh
t/t3411-rebase-preserve-around-merges.sh
t/t4048-diff-combined-binary.sh [new file with mode: 0755]
t/t5526-fetch-submodules.sh
t/t7400-submodule-basic.sh
t/t7407-submodule-foreach.sh
t/t9159-git-svn-no-parent-mergeinfo.sh [new file with mode: 0755]
t/test-lib.sh
unpack-trees.c
unpack-trees.h
userdiff.c
userdiff.h
index 1c3a9fead579a9b52037f1bbe245998db8a2f40b..d62aebd848b2a44f977ad4d7c4b75b6ff72b2163 100644 (file)
@@ -3,6 +3,7 @@
 *.[1-8]
 *.made
 *.texi
+*.pdf
 git.info
 gitman.info
 howto-index.txt
index 36989b7f6541cb8444385b64d2c955ae2a1f6d1b..18c71d763f472b1a98ad162626a0bc3d39d7e975 100644 (file)
@@ -232,6 +232,7 @@ cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
 clean:
        $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7
        $(RM) *.texi *.texi+ *.texi++ git.info gitman.info
+       $(RM) *.pdf
        $(RM) howto-index.txt howto/*.html doc.dep
        $(RM) technical/api-*.html technical/api-index.txt
        $(RM) $(cmds_txt) *.made
index 9fd85f5362fef82059ffcf2d158572fb87506ce4..9ec498ea39d969a60c74192bf0863ef9fabe4bc1 100644 (file)
@@ -1,4 +1,4 @@
-Git v1.7.6 Release Notes (draft)
+Git v1.7.6 Release Notes
 ========================
 
 Updates since v1.7.5
@@ -134,9 +134,3 @@ included in this release.
 
  * "git status -z" did not default to --porcelain output format.
    (merge bc/maint-status-z-to-use-porcelain later)
-
----
-exec >/var/tmp/1
-echo O=$(git describe master)
-O=v1.7.6-rc2
-git shortlog --no-merges ^maint ^$O master
index c7ed94635786789baca1de41d482cd6334d1181a..659de6f12384239f58dc688797db8dbb10420143 100644 (file)
@@ -224,10 +224,14 @@ endif::git-format-patch[]
 
 ifndef::git-format-patch[]
 --check::
-       Warn if changes introduce trailing whitespace
-       or an indent that uses a space before a tab. Exits with
-       non-zero status if problems are found. Not compatible with
-       --exit-code.
+       Warn if changes introduce whitespace errors.  What are
+       considered whitespace errors is controlled by `core.whitespace`
+       configuration.  By default, trailing whitespaces (including
+       lines that solely consist of whitespaces) and a space character
+       that is immediately followed by a tab character inside the
+       initial indent of the line are considered whitespace errors.
+       Exits with non-zero status if problems are found. Not compatible
+       with --exit-code.
 endif::git-format-patch[]
 
 --full-index::
@@ -412,6 +416,17 @@ endif::git-format-patch[]
 --no-ext-diff::
        Disallow external diff drivers.
 
+--textconv::
+--no-textconv::
+       Allow (or disallow) external text conversion filters to be run
+       when comparing binary files. See linkgit:gitattributes[5] for
+       details. Because textconv filters are typically a one-way
+       conversion, the resulting diff is suitable for human
+       consumption, but cannot be applied. For this reason, textconv
+       filters are enabled by default only for linkgit:git-diff[1] and
+       linkgit:git-log[1], but not for linkgit:git-format-patch[1] or
+       diff plumbing commands.
+
 --ignore-submodules[=<when>]::
        Ignore changes to submodules in the diff generation. <when> can be
        either "none", "untracked", "dirty" or "all", which is the default
index 205d83dd0b281d59e0f53284d29846c8eb58a246..c9fdf84a08847bd8cb8c9ce1e2f50241975e267c 100644 (file)
@@ -18,9 +18,12 @@ Checks if a given 'refname' is acceptable, and exits with a non-zero
 status if it is not.
 
 A reference is used in git to specify branches and tags.  A
-branch head is stored under the `$GIT_DIR/refs/heads` directory, and
-a tag is stored under the `$GIT_DIR/refs/tags` directory (or, if refs
-are packed by `git gc`, as entries in the `$GIT_DIR/packed-refs` file).
+branch head is stored in the `refs/heads` hierarchy, while
+a tag is stored in the `refs/tags` hierarchy of the ref namespace
+(typically in `$GIT_DIR/refs/heads` and `$GIT_DIR/refs/tags`
+directories or, as entries in file `$GIT_DIR/packed-refs`
+if refs are packed by `git gc`).
+
 git imposes the following rules on how references are named:
 
 . They can include slash `/` for hierarchical (directory)
index 249249aac7b2b9def824794b2bf71e2c7fe497ce..3f5b9126b1581d955a31fe5647834e9a8f61c666 100644 (file)
@@ -648,9 +648,14 @@ paths for a commit are encouraged to do so.
 
 `notemodify`
 ^^^^^^^^^^^^
-Included in a `commit` command to add a new note (annotating a given
-commit) or change the content of an existing note.  This command has
-two different means of specifying the content of the note.
+Included in a `commit` `<notes_ref>` command to add a new note
+annotating a `<committish>` or change this annotation contents.
+Internally it is similar to filemodify 100644 on `<committish>`
+path (maybe split into subdirectories). It's not advised to
+use any other commands to write to the `<notes_ref>` tree except
+`filedeleteall` to delete all existing notes in this tree.
+This command has two different means of specifying the content
+of the note.
 
 External data format::
        The data content for the note was already supplied by a prior
index 9dc1f2a94708d40daf428a427dd2ea4256cc172a..0f2f1173834bdee77bd1d8d77e070af07a7b3580 100644 (file)
@@ -32,8 +32,9 @@ changes, which would normally have no effect.  Nevertheless, this may be
 useful in the future for compensating for some git bugs or such,
 therefore such a usage is permitted.
 
-*NOTE*: This command honors `.git/info/grafts`. If you have any grafts
-defined, running this command will make them permanent.
+*NOTE*: This command honors `.git/info/grafts` and `.git/refs/replace/`.
+If you have any grafts or replacement refs defined, running this command
+will make them permanent.
 
 *WARNING*! The rewritten history will have different object names for all
 the objects and will not converge with the original branch.  You will not
index 528f34a13106836c1eace8c5d8972543b6fcc121..5a8c5061f3701c57bab75b2b4c70ad620f7e536f 100644 (file)
@@ -60,11 +60,11 @@ the remote repository.
 +
 With `-t <branch>` option, instead of the default glob
 refspec for the remote to track all branches under
-`$GIT_DIR/remotes/<name>/`, a refspec to track only `<branch>`
+the `refs/remotes/<name>/` namespace, a refspec to track only `<branch>`
 is created.  You can give more than one `-t <branch>` to track
 multiple branches without grabbing all branches.
 +
-With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
+With `-m <master>` option, a symbolic-ref `refs/remotes/<name>/HEAD` is set
 up to point at remote's `<master>` branch. See also the set-head command.
 +
 When a fetch mirror is created with `\--mirror=fetch`, the refs will not
@@ -92,24 +92,25 @@ configuration settings for the remote are removed.
 
 'set-head'::
 
-Sets or deletes the default branch (`$GIT_DIR/remotes/<name>/HEAD`) for
+Sets or deletes the default branch (i.e. the target of the
+symbolic-ref `refs/remotes/<name>/HEAD`) for
 the named remote. Having a default branch for a remote is not required,
 but allows the name of the remote to be specified in lieu of a specific
 branch. For example, if the default branch for `origin` is set to
 `master`, then `origin` may be specified wherever you would normally
 specify `origin/master`.
 +
-With `-d`, `$GIT_DIR/remotes/<name>/HEAD` is deleted.
+With `-d`, the symbolic ref `refs/remotes/<name>/HEAD` is deleted.
 +
-With `-a`, the remote is queried to determine its `HEAD`, then
-`$GIT_DIR/remotes/<name>/HEAD` is set to the same branch. e.g., if the remote
+With `-a`, the remote is queried to determine its `HEAD`, then the
+symbolic-ref `refs/remotes/<name>/HEAD` is set to the same branch. e.g., if the remote
 `HEAD` is pointed at `next`, "`git remote set-head origin -a`" will set
-`$GIT_DIR/refs/remotes/origin/HEAD` to `refs/remotes/origin/next`. This will
+the symbolic-ref `refs/remotes/origin/HEAD` to `refs/remotes/origin/next`. This will
 only work if `refs/remotes/origin/next` already exists; if not it must be
 fetched first.
 +
-Use `<branch>` to set `$GIT_DIR/remotes/<name>/HEAD` explicitly. e.g., "git
-remote set-head origin master" will set `$GIT_DIR/refs/remotes/origin/HEAD` to
+Use `<branch>` to set the symbolic-ref `refs/remotes/<name>/HEAD` explicitly. e.g., "git
+remote set-head origin master" will set the symbolic-ref `refs/remotes/origin/HEAD` to
 `refs/remotes/origin/master`. This will only work if
 `refs/remotes/origin/master` already exists; if not it must be fetched first.
 +
index 5c45446a4ac955630c8709e2184e52163185b8d4..0172cd70149914897862fbf0f3f221c7ef31ea5c 100644 (file)
@@ -44,6 +44,11 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
+* link:v1.7.6/git.html[documentation for release 1.7.6]
+
+* release notes for
+  link:RelNotes/1.7.6.txt[1.7.6].
+
 * link:v1.7.5.4/git.html[documentation for release 1.7.5.4]
 
 * release notes for
@@ -518,16 +523,15 @@ Any git command accepting any <object> can also use the following
 symbolic notation:
 
 HEAD::
-       indicates the head of the current branch (i.e. the
-       contents of `$GIT_DIR/HEAD`).
+       indicates the head of the current branch.
 
 <tag>::
        a valid tag 'name'
-       (i.e. the contents of `$GIT_DIR/refs/tags/<tag>`).
+       (i.e. a `refs/tags/<tag>` reference).
 
 <head>::
        a valid head 'name'
-       (i.e. the contents of `$GIT_DIR/refs/heads/<head>`).
+       (i.e. a `refs/heads/<head>` reference).
 
 For a more complete list of ways to spell object names, see
 "SPECIFYING REVISIONS" section in linkgit:gitrevisions[7].
index 412c55b549354471a56a4e56ca5533277c83bc54..2bbe76b5d88e4a38f22bdaef8612a48ddf1fe8ba 100644 (file)
@@ -79,7 +79,7 @@ Attributes for all users on a system should be placed in the
 `$(prefix)/etc/gitattributes` file.
 
 Sometimes you would need to override an setting of an attribute
-for a path to `unspecified` state.  This can be done by listing
+for a path to `Unspecified` state.  This can be done by listing
 the name of the attribute prefixed with an exclamation point `!`.
 
 
@@ -868,7 +868,7 @@ If this attribute is not set or has an invalid value, the value of the
 (See linkgit:git-config[1]).
 
 
-USING ATTRIBUTE MACROS
+USING MACRO ATTRIBUTES
 ----------------------
 
 You do not want any end-of-line conversions applied to, nor textual diffs
@@ -879,24 +879,27 @@ produced for, any binary file you track.  You would need to specify e.g.
 ------------
 
 but that may become cumbersome, when you have many attributes.  Using
-attribute macros, you can specify groups of attributes set or unset at
-the same time.  The system knows a built-in attribute macro, `binary`:
+macro attributes, you can define an attribute that, when set, also
+sets or unsets a number of other attributes at the same time.  The
+system knows a built-in macro attribute, `binary`:
 
 ------------
 *.jpg binary
 ------------
 
-which is equivalent to the above.  Note that the attribute macros can only
-be "Set" (see the above example that sets "binary" macro as if it were an
-ordinary attribute --- setting it in turn unsets "text" and "diff").
+Setting the "binary" attribute also unsets the "text" and "diff"
+attributes as above.  Note that macro attributes can only be "Set",
+though setting one might have the effect of setting or unsetting other
+attributes or even returning other attributes to the "Unspecified"
+state.
 
 
-DEFINING ATTRIBUTE MACROS
+DEFINING MACRO ATTRIBUTES
 -------------------------
 
-Custom attribute macros can be defined only in the `.gitattributes` file
-at the toplevel (i.e. not in any subdirectory).  The built-in attribute
-macro "binary" is equivalent to:
+Custom macro attributes can be defined only in the `.gitattributes`
+file at the toplevel (i.e. not in any subdirectory).  The built-in
+macro attribute "binary" is equivalent to:
 
 ------------
 [attr]binary -diff -text
index 8f62d1abeeb9b80fd36aa8ea12120c640a98414e..3595b586bc35d865a08ab538a1908cb2abe8e1a8 100644 (file)
@@ -161,8 +161,8 @@ to point at the new commit.
 
 [[def_head]]head::
        A <<def_ref,named reference>> to the <<def_commit,commit>> at the tip of a
-       <<def_branch,branch>>.  Heads are stored in
-       `$GIT_DIR/refs/heads/`, except when using packed refs. (See
+       <<def_branch,branch>>.  Heads are stored in a file in
+       `$GIT_DIR/refs/heads/` directory, except when using packed refs. (See
        linkgit:git-pack-refs[1].)
 
 [[def_HEAD]]HEAD::
@@ -170,8 +170,8 @@ to point at the new commit.
        working tree>> is normally derived from the state of the tree
        referred to by HEAD.  HEAD is a reference to one of the
        <<def_head,heads>> in your repository, except when using a
-       <<def_detached_HEAD,detached HEAD>>, in which case it may
-       reference an arbitrary commit.
+       <<def_detached_HEAD,detached HEAD>>, in which case it directly
+       references an arbitrary commit.
 
 [[def_head_ref]]head ref::
        A synonym for <<def_head,head>>.
@@ -382,8 +382,9 @@ should not be combined with other pathspec.
 
 [[def_ref]]ref::
        A 40-byte hex representation of a <<def_SHA1,SHA1>> or a name that
-       denotes a particular <<def_object,object>>. These may be stored in
-       `$GIT_DIR/refs/`.
+       denotes a particular <<def_object,object>>. They may be stored in
+       a file under `$GIT_DIR/refs/` directory, or
+       in the `$GIT_DIR/packed-refs` file.
 
 [[def_reflog]]reflog::
        A reflog shows the local "history" of a ref.  In other words,
@@ -459,14 +460,14 @@ should not be combined with other pathspec.
        command.
 
 [[def_tag]]tag::
-       A <<def_ref,ref>> pointing to a <<def_tag_object,tag>> or
-       <<def_commit_object,commit object>>. In contrast to a <<def_head,head>>,
-       a tag is not changed by a <<def_commit,commit>>. Tags (not
-       <<def_tag_object,tag objects>>) are stored in `$GIT_DIR/refs/tags/`. A
-       git tag has nothing to do with a Lisp tag (which would be
-       called an <<def_object_type,object type>> in git's context). A
-       tag is most typically used to mark a particular point in the
-       commit ancestry <<def_chain,chain>>.
+       A <<def_ref,ref>> under `refs/tags/` namespace that points to an
+       object of an arbitrary type (typically a tag points to either a
+       <<def_tag_object,tag>> or a <<def_commit_object,commit object>>).
+       In contrast to a <<def_head,head>>, a tag is not updated by
+       the `commit` command. A git tag has nothing to do with a Lisp
+       tag (which would be called an <<def_object_type,object type>>
+       in git's context). A tag is most typically used to mark a particular
+       point in the commit ancestry <<def_chain,chain>>.
 
 [[def_tag_object]]tag object::
        An <<def_object,object>> containing a <<def_ref,ref>> pointing to
index 7e7ba68781f98b55f4189fe0fb4dd6e96c47c0af..62340a5e4c3751000208cee289c0e4341f5c046c 100644 (file)
@@ -272,7 +272,7 @@ Default mode::
 
 --full-history::
 
-       As the default mode but does not prune some history.
+       Same as the default mode, but does not prune some history.
 
 --dense::
 
index 5cb2b0590abb1fc4e4685097ba3cdd3d0683a95f..b0cafe87bee046dc9b2d4e61e0d057e787a6f1f6 100644 (file)
@@ -49,6 +49,8 @@ Additionally, if `foo` is a new command, there are 3 more things to do:
 
 . Add an entry for `git-foo` to `command-list.txt`.
 
+. Add an entry for `/git-foo` to `.gitignore`.
+
 
 How a built-in is called
 ------------------------
index 7b233ca19676c2f89b1fb0231d7085e70c7eaaf6..8930b3fabceebfc7e03ddabdf5f7bfb228babf6b 100644 (file)
@@ -147,8 +147,9 @@ GIT index format
   - 160-bit object name for the object that would result from writing
     this span of index as a tree.
 
-  An entry can be in an invalidated state and is represented by having -1
-  in the entry_count field.
+  An entry can be in an invalidated state and is represented by having
+  -1 in the entry_count field. In this case, there is no object name
+  and the next entry starts immediately after the newline.
 
   The entries are written out in the top-down, depth-first order.  The
   first entry represents the root level of the repository, followed by the
index 369f91d3b949b23682c4deda8234f13513f15732..a7004c63e7ff5a4fe237267121a5b7c76a4c5496 100644 (file)
@@ -179,34 +179,36 @@ and descriptions.
 
 Packfile Negotiation
 --------------------
-After reference and capabilities discovery, the client can decide
-to terminate the connection by sending a flush-pkt, telling the
-server it can now gracefully terminate (as happens with the ls-remote
-command) or it can enter the negotiation phase, where the client and
-server determine what the minimal packfile necessary for transport is.
-
-Once the client has the initial list of references that the server
-has, as well as the list of capabilities, it will begin telling the
-server what objects it wants and what objects it has, so the server
-can make a packfile that only contains the objects that the client needs.
-The client will also send a list of the capabilities it wants to be in
-effect, out of what the server said it could do with the first 'want' line.
+After reference and capabilities discovery, the client can decide to
+terminate the connection by sending a flush-pkt, telling the server it can
+now gracefully terminate, and disconnect, when it does not need any pack
+data. This can happen with the ls-remote command, and also can happen when
+the client already is up-to-date.
+
+Otherwise, it enters the negotiation phase, where the client and
+server determine what the minimal packfile necessary for transport is,
+by telling the server what objects it wants, its shallow objects
+(if any), and the maximum commit depth it wants (if any).  The client
+will also send a list of the capabilities it wants to be in effect,
+out of what the server said it could do with the first 'want' line.
 
 ----
   upload-request    =  want-list
-                      have-list
-                      compute-end
+                      *shallow-line
+                      *1depth-request
+                      flush-pkt
 
   want-list         =  first-want
                       *additional-want
-                      flush-pkt
+
+  shallow-line      =  PKT_LINE("shallow" SP obj-id)
+
+  depth-request     =  PKT_LINE("deepen" SP depth)
 
   first-want        =  PKT-LINE("want" SP obj-id SP capability-list LF)
   additional-want   =  PKT-LINE("want" SP obj-id LF)
 
-  have-list         =  *have-line
-  have-line         =  PKT-LINE("have" SP obj-id LF)
-  compute-end       =  flush-pkt / PKT-LINE("done")
+  depth             =  1*DIGIT
 ----
 
 Clients MUST send all the obj-ids it wants from the reference
@@ -215,21 +217,64 @@ discovery phase as 'want' lines. Clients MUST send at least one
 obj-id in a 'want' command which did not appear in the response
 obtained through ref discovery.
 
-If client is requesting a shallow clone, it will now send a 'deepen'
-line with the depth it is requesting.
+The client MUST write all obj-ids which it only has shallow copies
+of (meaning that it does not have the parents of a commit) as
+'shallow' lines so that the server is aware of the limitations of
+the client's history. Clients MUST NOT mention an obj-id which
+it does not know exists on the server.
+
+The client now sends the maximum commit history depth it wants for
+this transaction, which is the number of commits it wants from the
+tip of the history, if any, as a 'deepen' line.  A depth of 0 is the
+same as not making a depth request. The client does not want to receive
+any commits beyond this depth, nor objects needed only to complete
+those commits. Commits whose parents are not received as a result are
+defined as shallow and marked as such in the server. This information
+is sent back to the client in the next step.
+
+Once all the 'want's and 'shallow's (and optional 'deepen') are
+transferred, clients MUST send a flush-pkt, to tell the server side
+that it is done sending the list.
+
+Otherwise, if the client sent a positive depth request, the server
+will determine which commits will and will not be shallow and
+send this information to the client. If the client did not request
+a positive depth, this step is skipped.
 
-Once all the "want"s (and optional 'deepen') are transferred,
-clients MUST send a flush-pkt. If the client has all the references
-on the server, client flushes and disconnects.
+----
+  shallow-update   =  *shallow-line
+                     *unshallow-line
+                     flush-pkt
 
-TODO: shallow/unshallow response and document the deepen command in the ABNF.
+  shallow-line     =  PKT-LINE("shallow" SP obj-id)
+
+  unshallow-line   =  PKT-LINE("unshallow" SP obj-id)
+----
+
+If the client has requested a positive depth, the server will compute
+the set of commits which are no deeper than the desired depth, starting
+at the client's wants. The server writes 'shallow' lines for each
+commit whose parents will not be sent as a result. The server writes
+an 'unshallow' line for each commit which the client has indicated is
+shallow, but is no longer shallow at the currently requested depth
+(that is, its parents will now be sent). The server MUST NOT mark
+as unshallow anything which the client has not indicated was shallow.
 
 Now the client will send a list of the obj-ids it has using 'have'
-lines.  In multi_ack mode, the canonical implementation will send up
-to 32 of these at a time, then will send a flush-pkt.  The canonical
-implementation will skip ahead and send the next 32 immediately,
-so that there is always a block of 32 "in-flight on the wire" at a
-time.
+lines, so the server can make a packfile that only contains the objects
+that the client needs. In multi_ack mode, the canonical implementation
+will send up to 32 of these at a time, then will send a flush-pkt. The
+canonical implementation will skip ahead and send the next 32 immediately,
+so that there is always a block of 32 "in-flight on the wire" at a time.
+
+----
+  upload-haves      =  have-list
+                      compute-end
+
+  have-list         =  *have-line
+  have-line         =  PKT-LINE("have" SP obj-id LF)
+  compute-end       =  flush-pkt / PKT-LINE("done")
+----
 
 If the server reads 'have' lines, it then will respond by ACKing any
 of the obj-ids the client said it had that the server also has. The
index 08e864869bdc70a5afe63d7d99de5c30e725a4a9..f04e4b138d344155b767a0538321dda34552906e 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.6-rc2
+DEF_VER=v1.7.6
 
 LF='
 '
index d6ab93bfbb369965e76e384e6984a29b667cdfbe..3142daa57a6fa1c8a7d21095946bf5d26443d0e0 100644 (file)
@@ -19,7 +19,7 @@
 static const char * const builtin_branch_usage[] = {
        "git branch [options] [-r | -a] [--merged | --no-merged]",
        "git branch [options] [-l] [-f] <branchname> [<start-point>]",
-       "git branch [options] [-r] (-d | -D) <branchname>",
+       "git branch [options] [-r] (-d | -D) <branchname>...",
        "git branch [options] (-m | -M) [<oldbranch>] <newbranch>",
        NULL
 };
index 28cdc51b85e7d433dca085c0080f964d19a391b4..af1e7b579a83aef15e11c0c5dfa29447e485654c 100644 (file)
@@ -1071,7 +1071,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                if (strbuf_check_branch_ref(&buf, opts.new_branch))
                        die(_("git checkout: we do not like '%s' as a branch name."),
                            opts.new_branch);
-               if (!get_sha1(buf.buf, rev)) {
+               if (ref_exists(buf.buf)) {
                        opts.branch_exists = 1;
                        if (!opts.new_branch_force)
                                die(_("git checkout: branch %s already exists"),
index 655fa89d8a7ffe3c3823080f5af3e5e385e95440..be67cfcd45469497f81e0c36ed87a11fd409daee 100644 (file)
@@ -7,6 +7,7 @@
 #include "xdiff-interface.h"
 #include "log-tree.h"
 #include "refs.h"
+#include "userdiff.h"
 
 static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
 {
@@ -92,7 +93,9 @@ struct sline {
        unsigned long *p_lno;
 };
 
-static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned long *size)
+static char *grab_blob(const unsigned char *sha1, unsigned int mode,
+                      unsigned long *size, struct userdiff_driver *textconv,
+                      const char *path)
 {
        char *blob;
        enum object_type type;
@@ -105,6 +108,11 @@ static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned lo
                /* deleted blob */
                *size = 0;
                return xcalloc(1, 1);
+       } else if (textconv) {
+               struct diff_filespec *df = alloc_filespec(path);
+               fill_filespec(df, sha1, mode);
+               *size = fill_textconv(textconv, df, &blob);
+               free_filespec(df);
        } else {
                blob = read_sha1_file(sha1, &type, size);
                if (type != OBJ_BLOB)
@@ -204,7 +212,9 @@ static void consume_line(void *state_, char *line, unsigned long len)
 static void combine_diff(const unsigned char *parent, unsigned int mode,
                         mmfile_t *result_file,
                         struct sline *sline, unsigned int cnt, int n,
-                        int num_parent, int result_deleted)
+                        int num_parent, int result_deleted,
+                        struct userdiff_driver *textconv,
+                        const char *path)
 {
        unsigned int p_lno, lno;
        unsigned long nmask = (1UL << n);
@@ -217,7 +227,7 @@ static void combine_diff(const unsigned char *parent, unsigned int mode,
        if (result_deleted)
                return; /* result deleted */
 
-       parent_file.ptr = grab_blob(parent, mode, &sz);
+       parent_file.ptr = grab_blob(parent, mode, &sz, textconv, path);
        parent_file.size = sz;
        memset(&xpp, 0, sizeof(xpp));
        xpp.flags = 0;
@@ -681,6 +691,82 @@ static void dump_quoted_path(const char *head,
        puts(buf.buf);
 }
 
+static void show_combined_header(struct combine_diff_path *elem,
+                                int num_parent,
+                                int dense,
+                                struct rev_info *rev,
+                                int mode_differs,
+                                int show_file_header)
+{
+       struct diff_options *opt = &rev->diffopt;
+       int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
+       const char *a_prefix = opt->a_prefix ? opt->a_prefix : "a/";
+       const char *b_prefix = opt->b_prefix ? opt->b_prefix : "b/";
+       int use_color = DIFF_OPT_TST(opt, COLOR_DIFF);
+       const char *c_meta = diff_get_color(use_color, DIFF_METAINFO);
+       const char *c_reset = diff_get_color(use_color, DIFF_RESET);
+       const char *abb;
+       int added = 0;
+       int deleted = 0;
+       int i;
+
+       if (rev->loginfo && !rev->no_commit_id)
+               show_log(rev);
+
+       dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
+                        "", elem->path, c_meta, c_reset);
+       printf("%sindex ", c_meta);
+       for (i = 0; i < num_parent; i++) {
+               abb = find_unique_abbrev(elem->parent[i].sha1,
+                                        abbrev);
+               printf("%s%s", i ? "," : "", abb);
+       }
+       abb = find_unique_abbrev(elem->sha1, abbrev);
+       printf("..%s%s\n", abb, c_reset);
+
+       if (mode_differs) {
+               deleted = !elem->mode;
+
+               /* We say it was added if nobody had it */
+               added = !deleted;
+               for (i = 0; added && i < num_parent; i++)
+                       if (elem->parent[i].status !=
+                           DIFF_STATUS_ADDED)
+                               added = 0;
+               if (added)
+                       printf("%snew file mode %06o",
+                              c_meta, elem->mode);
+               else {
+                       if (deleted)
+                               printf("%sdeleted file ", c_meta);
+                       printf("mode ");
+                       for (i = 0; i < num_parent; i++) {
+                               printf("%s%06o", i ? "," : "",
+                                      elem->parent[i].mode);
+                       }
+                       if (elem->mode)
+                               printf("..%06o", elem->mode);
+               }
+               printf("%s\n", c_reset);
+       }
+
+       if (!show_file_header)
+               return;
+
+       if (added)
+               dump_quoted_path("--- ", "", "/dev/null",
+                                c_meta, c_reset);
+       else
+               dump_quoted_path("--- ", a_prefix, elem->path,
+                                c_meta, c_reset);
+       if (deleted)
+               dump_quoted_path("+++ ", "", "/dev/null",
+                                c_meta, c_reset);
+       else
+               dump_quoted_path("+++ ", b_prefix, elem->path,
+                                c_meta, c_reset);
+}
+
 static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
                            int dense, struct rev_info *rev)
 {
@@ -692,17 +778,22 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
        int mode_differs = 0;
        int i, show_hunks;
        int working_tree_file = is_null_sha1(elem->sha1);
-       int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
-       const char *a_prefix, *b_prefix;
        mmfile_t result_file;
+       struct userdiff_driver *userdiff;
+       struct userdiff_driver *textconv = NULL;
+       int is_binary;
 
        context = opt->context;
-       a_prefix = opt->a_prefix ? opt->a_prefix : "a/";
-       b_prefix = opt->b_prefix ? opt->b_prefix : "b/";
+       userdiff = userdiff_find_by_path(elem->path);
+       if (!userdiff)
+               userdiff = userdiff_find_by_name("default");
+       if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV))
+               textconv = userdiff_get_textconv(userdiff);
 
        /* Read the result of merge first */
        if (!working_tree_file)
-               result = grab_blob(elem->sha1, elem->mode, &result_size);
+               result = grab_blob(elem->sha1, elem->mode, &result_size,
+                                  textconv, elem->path);
        else {
                /* Used by diff-tree to read from the working tree */
                struct stat st;
@@ -725,9 +816,16 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
                } else if (S_ISDIR(st.st_mode)) {
                        unsigned char sha1[20];
                        if (resolve_gitlink_ref(elem->path, "HEAD", sha1) < 0)
-                               result = grab_blob(elem->sha1, elem->mode, &result_size);
+                               result = grab_blob(elem->sha1, elem->mode,
+                                                  &result_size, NULL, NULL);
                        else
-                               result = grab_blob(sha1, elem->mode, &result_size);
+                               result = grab_blob(sha1, elem->mode,
+                                                  &result_size, NULL, NULL);
+               } else if (textconv) {
+                       struct diff_filespec *df = alloc_filespec(elem->path);
+                       fill_filespec(df, null_sha1, st.st_mode);
+                       result_size = fill_textconv(textconv, df, &result);
+                       free_filespec(df);
                } else if (0 <= (fd = open(elem->path, O_RDONLY))) {
                        size_t len = xsize_t(st.st_size);
                        ssize_t done;
@@ -777,6 +875,38 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
                        close(fd);
        }
 
+       for (i = 0; i < num_parent; i++) {
+               if (elem->parent[i].mode != elem->mode) {
+                       mode_differs = 1;
+                       break;
+               }
+       }
+
+       if (textconv)
+               is_binary = 0;
+       else if (userdiff->binary != -1)
+               is_binary = userdiff->binary;
+       else {
+               is_binary = buffer_is_binary(result, result_size);
+               for (i = 0; !is_binary && i < num_parent; i++) {
+                       char *buf;
+                       unsigned long size;
+                       buf = grab_blob(elem->parent[i].sha1,
+                                       elem->parent[i].mode,
+                                       &size, NULL, NULL);
+                       if (buffer_is_binary(buf, size))
+                               is_binary = 1;
+                       free(buf);
+               }
+       }
+       if (is_binary) {
+               show_combined_header(elem, num_parent, dense, rev,
+                                    mode_differs, 0);
+               printf("Binary files differ\n");
+               free(result);
+               return;
+       }
+
        for (cnt = 0, cp = result; cp < result + result_size; cp++) {
                if (*cp == '\n')
                        cnt++;
@@ -824,71 +954,15 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
                        combine_diff(elem->parent[i].sha1,
                                     elem->parent[i].mode,
                                     &result_file, sline,
-                                    cnt, i, num_parent, result_deleted);
-               if (elem->parent[i].mode != elem->mode)
-                       mode_differs = 1;
+                                    cnt, i, num_parent, result_deleted,
+                                    textconv, elem->path);
        }
 
        show_hunks = make_hunks(sline, cnt, num_parent, dense);
 
        if (show_hunks || mode_differs || working_tree_file) {
-               const char *abb;
-               int use_color = DIFF_OPT_TST(opt, COLOR_DIFF);
-               const char *c_meta = diff_get_color(use_color, DIFF_METAINFO);
-               const char *c_reset = diff_get_color(use_color, DIFF_RESET);
-               int added = 0;
-               int deleted = 0;
-
-               if (rev->loginfo && !rev->no_commit_id)
-                       show_log(rev);
-               dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
-                                "", elem->path, c_meta, c_reset);
-               printf("%sindex ", c_meta);
-               for (i = 0; i < num_parent; i++) {
-                       abb = find_unique_abbrev(elem->parent[i].sha1,
-                                                abbrev);
-                       printf("%s%s", i ? "," : "", abb);
-               }
-               abb = find_unique_abbrev(elem->sha1, abbrev);
-               printf("..%s%s\n", abb, c_reset);
-
-               if (mode_differs) {
-                       deleted = !elem->mode;
-
-                       /* We say it was added if nobody had it */
-                       added = !deleted;
-                       for (i = 0; added && i < num_parent; i++)
-                               if (elem->parent[i].status !=
-                                   DIFF_STATUS_ADDED)
-                                       added = 0;
-                       if (added)
-                               printf("%snew file mode %06o",
-                                      c_meta, elem->mode);
-                       else {
-                               if (deleted)
-                                       printf("%sdeleted file ", c_meta);
-                               printf("mode ");
-                               for (i = 0; i < num_parent; i++) {
-                                       printf("%s%06o", i ? "," : "",
-                                              elem->parent[i].mode);
-                               }
-                               if (elem->mode)
-                                       printf("..%06o", elem->mode);
-                       }
-                       printf("%s\n", c_reset);
-               }
-               if (added)
-                       dump_quoted_path("--- ", "", "/dev/null",
-                                        c_meta, c_reset);
-               else
-                       dump_quoted_path("--- ", a_prefix, elem->path,
-                                        c_meta, c_reset);
-               if (deleted)
-                       dump_quoted_path("+++ ", "", "/dev/null",
-                                        c_meta, c_reset);
-               else
-                       dump_quoted_path("+++ ", b_prefix, elem->path,
-                                        c_meta, c_reset);
+               show_combined_header(elem, num_parent, dense, rev,
+                                    mode_differs, 1);
                dump_sline(sline, cnt, num_parent,
                           DIFF_OPT_TST(opt, COLOR_DIFF), result_deleted);
        }
index b4a51b958c5651d3b509013aaef0c4e30b68a816..ba3327f1f96922c91a4e3f0094c0fa10cde0301e 100644 (file)
@@ -101,7 +101,7 @@ static int cygwin_stat(const char *path, struct stat *buf)
  * and calling git_default_config() from here would break such variables.
  */
 static int native_stat = 1;
-static int core_filemode;
+static int core_filemode = 1; /* matches trust_executable_bit default */
 
 static int git_cygwin_config(const char *var, const char *value, void *cb)
 {
index e0b3b80d92ece9f37e0e76292bd61ce97271fcce..113723bf3b069ed907cd71831ddff91a0ed113da 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1479,10 +1479,10 @@ int git_config_rename_section(const char *old_name, const char *new_name)
                }
        }
        fclose(config_file);
- unlock_and_out:
+unlock_and_out:
        if (commit_lock_file(lock) < 0)
                ret = error("could not commit config file %s", config_filename);
- out:
+out:
        free(config_filename);
        return ret;
 }
index 2119c3f74edcd2a976ff0e375c5d8d60d40da2ec..b3585aba22bcbd72c9697fd256ef95f691aa384f 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -216,7 +216,7 @@ static int git_tcp_connect_sock(char *host, int flags)
        if (flags & CONNECT_VERBOSE)
                fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);
 
-       for (ai0 = ai; ai; ai = ai->ai_next) {
+       for (ai0 = ai; ai; ai = ai->ai_next, cnt++) {
                sockfd = socket(ai->ai_family,
                                ai->ai_socktype, ai->ai_protocol);
                if (sockfd < 0) {
index b36290fa6015d9b66dc6a5891ff12f85f279a1c3..5a8309076dc633f431797c4bd59876490b0d7408 100755 (executable)
@@ -2058,7 +2058,7 @@ _git_config ()
                color.ui
                commit.status
                commit.template
-               core.abbrevguard
+               core.abbrev
                core.askpass
                core.attributesfile
                core.autocrlf
index 9c29293bbc05d175ba13338813e8532c7ad677cf..2e09500c8210e22d6c81484aa198f1d811a9933d 100644 (file)
@@ -433,8 +433,13 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
        if (tree == o->df_conflict_entry)
                tree = NULL;
 
-       if (ce_path_match(idx ? idx : tree, &revs->prune_data))
+       if (ce_path_match(idx ? idx : tree, &revs->prune_data)) {
                do_oneway_diff(o, idx, tree);
+               if (diff_can_quit_early(&revs->diffopt)) {
+                       o->exiting_early = 1;
+                       return -1;
+               }
+       }
 
        return 0;
 }
diff --git a/diff.c b/diff.c
index 61bedaed57216cadaf2716ef7aa0d63889571f8a..5dd9049c7d354110534b2770fbf6cbc8e74e359e 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1984,19 +1984,7 @@ struct userdiff_driver *get_textconv(struct diff_filespec *one)
                return NULL;
 
        diff_filespec_load_driver(one);
-       if (!one->driver->textconv)
-               return NULL;
-
-       if (one->driver->textconv_want_cache && !one->driver->textconv_cache) {
-               struct notes_cache *c = xmalloc(sizeof(*c));
-               struct strbuf name = STRBUF_INIT;
-
-               strbuf_addf(&name, "textconv/%s", one->driver->name);
-               notes_cache_init(c, name.buf, one->driver->textconv);
-               one->driver->textconv_cache = c;
-       }
-
-       return one->driver;
+       return userdiff_get_textconv(one->driver);
 }
 
 static void builtin_diff(const char *name_a,
index 6cdd5910db50c96df3d149fba172750cb10c09cb..f1a03c912824a264cbe29905d53e2fe58c2c9dd6 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -507,6 +507,8 @@ else
        fi
 fi
 
+git update-index -q --refresh
+
 case "$resolved" in
 '')
        case "$HAS_HEAD" in
index 962a93b586571eb6fc60aae53c77f6e6b9fb281f..6b5f2251b6b5f0b9a43e16296c390e991c6fa13a 100755 (executable)
@@ -363,7 +363,7 @@ while read commit parents; do
        sed -e '1,/^$/d' <../commit | \
                eval "$filter_msg" > ../message ||
                        die "msg filter failed: $filter_msg"
-       @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \
+       workdir=$workdir @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \
                $(git write-tree) $parentstr < ../message > ../map/$commit ||
                        die "could not write rewritten commit"
 done <../revs
index 65690af89307abd72749123caddce9e6c4692383..c6ba7c15510935353bd17b2b8d8188fe16052907 100644 (file)
@@ -713,7 +713,6 @@ then
        # parents to rewrite and skipping dropped commits would
        # prematurely end our probe
        merges_option=
-       first_after_upstream="$(git rev-list --reverse --first-parent $upstream..$orig_head | head -n 1)"
 else
        merges_option="--no-merges --cherry-pick"
 fi
@@ -746,7 +745,7 @@ do
                        preserve=t
                        for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
                        do
-                               if test -f "$rewritten"/$p -a \( $p != $onto -o $sha1 = $first_after_upstream \)
+                               if test -f "$rewritten"/$p
                                then
                                        preserve=f
                                fi
index d189a24c71c44806a9c1381e2a8e5993269e568a..9c6dca5a1590a22ec7478e46b7d4660c7d1beb01 100755 (executable)
@@ -300,6 +300,10 @@ cmd_foreach()
 
        toplevel=$(pwd)
 
+       # dup stdin so that it can be restored when running the external
+       # command in the subshell (and a recursive call to this function)
+       exec 3<&0
+
        module_list |
        while read mode sha1 stage path
        do
@@ -316,7 +320,7 @@ cmd_foreach()
                                then
                                        cmd_foreach "--recursive" "$@"
                                fi
-                       ) ||
+                       ) <&3 3<&- ||
                        die "Stopping at '$path'; script returned non-zero status."
                fi
        done
index 7849cfc141d384bc28479c2f37fd128c77fe0fbe..89f83fd27abe315804173a809b3c7ef00ead6527 100755 (executable)
@@ -3124,8 +3124,12 @@ sub lookup_svn_merge {
                        next;
                }
 
-               push @merged_commit_ranges,
-                       "$bottom_commit^..$top_commit";
+               if (scalar(command('rev-parse', "$bottom_commit^@"))) {
+                       push @merged_commit_ranges,
+                            "$bottom_commit^..$top_commit";
+               } else {
+                       push @merged_commit_ranges, "$top_commit";
+               }
 
                if ( !defined $tip or $top > $tip ) {
                        $tip = $top;
@@ -3154,9 +3158,9 @@ sub check_cherry_pick {
        my $parents = shift;
        my @ranges = @_;
        my %commits = map { $_ => 1 }
-               _rev_list("--no-merges", $tip, "--not", $base, @$parents);
+               _rev_list("--no-merges", $tip, "--not", $base, @$parents, "--");
        for my $range ( @ranges ) {
-               delete @commits{_rev_list($range)};
+               delete @commits{_rev_list($range, "--")};
        }
        for my $commit (keys %commits) {
                if (has_no_changes($commit)) {
diff --git a/refs.c b/refs.c
index b10419a69815ef1c005915f3606c992659e60c77..3a8789d3857d17a3a0a94ba2750e9f22857b8667 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1826,6 +1826,12 @@ int update_ref(const char *action, const char *refname,
        return 0;
 }
 
+int ref_exists(char *refname)
+{
+       unsigned char sha1[20];
+       return !!resolve_ref(refname, sha1, 1, NULL);
+}
+
 struct ref *find_ref_by_name(const struct ref *list, const char *name)
 {
        for ( ; list; list = list->next)
diff --git a/refs.h b/refs.h
index 5e7a9a59f5f6b687d15eb37a11696433bdc8f15c..5de06e57e7a9644a7dd51832552e9d1afa53c8cd 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -54,6 +54,7 @@ extern void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refn
  */
 extern void add_extra_ref(const char *refname, const unsigned char *sha1, int flags);
 extern void clear_extra_refs(void);
+extern int ref_exists(char *);
 
 extern int peel_ref(const char *, unsigned char *);
 
index b5be25ce9623936e42566ca52b9e4d1d33153111..8ac5028343320b44b75c6945318fe5b328af81fd 100644 (file)
@@ -227,6 +227,8 @@ static struct ref *parse_info_refs(struct discovery *heads)
                if (data[i] == '\t')
                        mid = &data[i];
                if (data[i] == '\n') {
+                       if (mid - start != 40)
+                               die("%sinfo/refs not valid: is this a git repository?", url);
                        data[i] = 0;
                        ref_name = mid + 1;
                        ref = xmalloc(sizeof(struct ref) +
index 064a33040812ba8782bf602c693abf08613d6ec7..697f4a43c5ef0bdc220a15545d94bc31ad1f248e 100644 (file)
@@ -1205,20 +1205,29 @@ static void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
        return map;
 }
 
-static int legacy_loose_object(unsigned char *map)
+/*
+ * There used to be a second loose object header format which
+ * was meant to mimic the in-pack format, allowing for direct
+ * copy of the object data.  This format turned up not to be
+ * really worth it and we no longer write loose objects in that
+ * format.
+ */
+static int experimental_loose_object(unsigned char *map)
 {
        unsigned int word;
 
        /*
         * Is it a zlib-compressed buffer? If so, the first byte
         * must be 0x78 (15-bit window size, deflated), and the
-        * first 16-bit word is evenly divisible by 31
+        * first 16-bit word is evenly divisible by 31. If so,
+        * we are looking at the official format, not the experimental
+        * one.
         */
        word = (map[0] << 8) + map[1];
        if (map[0] == 0x78 && !(word % 31))
-               return 1;
-       else
                return 0;
+       else
+               return 1;
 }
 
 unsigned long unpack_object_header_buffer(const unsigned char *buf,
@@ -1262,34 +1271,29 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
        stream->next_out = buffer;
        stream->avail_out = bufsiz;
 
-       if (legacy_loose_object(map)) {
-               git_inflate_init(stream);
-               return git_inflate(stream, 0);
-       }
-
+       if (experimental_loose_object(map)) {
+               /*
+                * The old experimental format we no longer produce;
+                * we can still read it.
+                */
+               used = unpack_object_header_buffer(map, mapsize, &type, &size);
+               if (!used || !valid_loose_object_type[type])
+                       return -1;
+               map += used;
+               mapsize -= used;
 
-       /*
-        * There used to be a second loose object header format which
-        * was meant to mimic the in-pack format, allowing for direct
-        * copy of the object data.  This format turned up not to be
-        * really worth it and we don't write it any longer.  But we
-        * can still read it.
-        */
-       used = unpack_object_header_buffer(map, mapsize, &type, &size);
-       if (!used || !valid_loose_object_type[type])
-               return -1;
-       map += used;
-       mapsize -= used;
+               /* Set up the stream for the rest.. */
+               stream->next_in = map;
+               stream->avail_in = mapsize;
+               git_inflate_init(stream);
 
-       /* Set up the stream for the rest.. */
-       stream->next_in = map;
-       stream->avail_in = mapsize;
+               /* And generate the fake traditional header */
+               stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu",
+                                                typename(type), size);
+               return 0;
+       }
        git_inflate_init(stream);
-
-       /* And generate the fake traditional header */
-       stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu",
-                                        typename(type), size);
-       return 0;
+       return git_inflate(stream, 0);
 }
 
 static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size, const unsigned char *sha1)
index b6dec70bd1a6b35c8ecc6a1a9953d64bfe6c4510..1ba9646d3484fe2a11c1faba339c4e333186085e 100644 (file)
@@ -388,6 +388,7 @@ void check_for_new_submodule_commits(unsigned char new_sha1[20])
                while (parent) {
                        struct diff_options diff_opts;
                        diff_setup(&diff_opts);
+                       DIFF_OPT_SET(&diff_opts, RECURSIVE);
                        diff_opts.output_format |= DIFF_FORMAT_CALLBACK;
                        diff_opts.format_callback = submodule_collect_changed_cb;
                        if (diff_setup_done(&diff_opts) < 0)
index d206b7c4cfa4f7d61d151cebc35a0f296fbe4c6b..7913e206ed6b73d16779e91d6a9197e602626c57 100755 (executable)
@@ -1,5 +1,6 @@
 #!/bin/sh
 
+failed_tests=
 fixed=0
 success=0
 failed=0
@@ -18,7 +19,13 @@ do
                success)
                        success=$(($success + $value)) ;;
                failed)
-                       failed=$(($failed + $value)) ;;
+                       failed=$(($failed + $value))
+                       if test $value != 0
+                       then
+                               testnum=$(expr "$file" : 'test-results/\(t[0-9]*\)-')
+                               failed_tests="$failed_tests $testnum"
+                       fi
+                       ;;
                broken)
                        broken=$(($broken + $value)) ;;
                total)
@@ -27,6 +34,11 @@ do
        done <"$file"
 done
 
+if test -n "$failed_tests"
+then
+       printf "\nfailed test(s):$failed_tests\n\n"
+fi
+
 printf "%-8s%d\n" fixed $fixed
 printf "%-8s%d\n" success $success
 printf "%-8s%d\n" failed $failed
index fa69016381b0196c49472af51e36948ec7c5a2a9..a42e03967b1df3001df24089f2c50008c092ac51 100755 (executable)
@@ -169,4 +169,15 @@ test_expect_success 'checkout -f -B to an existing branch with mergeable changes
        test_must_fail test_dirty_mergeable
 '
 
+test_expect_success 'checkout -b <describe>' '
+       git tag -f -m "First commit" initial initial &&
+       git checkout -f change1 &&
+       name=$(git describe) &&
+       git checkout -b $name &&
+       git diff --exit-code change1 &&
+       echo "refs/heads/$name" >expect &&
+       git symbolic-ref HEAD >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 47c8371c7edfe7945ded380bb6f96a00d26c04eb..8538813d1d0dfa72008da1d711cf2c042796a6ee 100755 (executable)
@@ -295,7 +295,7 @@ test_expect_success 'preserve merges with -p' '
 '
 
 test_expect_success 'edit ancestor with -p' '
-       FAKE_LINES="1 edit 2 3 4" git rebase -i -p HEAD~3 &&
+       FAKE_LINES="1 2 edit 3 4" git rebase -i -p HEAD~3 &&
        echo 2 > unrelated-file &&
        test_tick &&
        git commit -m L2-modified --amend unrelated-file &&
index 08201e2331d36af769d832e3d9551c48331b7033..6de4e2263f9ec65d2de2e28af6a12d5c1065f686 100755 (executable)
@@ -37,7 +37,15 @@ export GIT_AUTHOR_EMAIL
 #      \
 #       B2     <-- origin/topic
 #
-# In all cases, 'topic' is rebased onto 'origin/topic'.
+# Clone 4 (merge using second parent as base):
+#
+# A1--A2--B3   <-- origin/master
+#  \
+#   B1--A3--M  <-- topic
+#    \     /
+#     \--A4    <-- topic2
+#      \
+#       B2     <-- origin/topic
 
 test_expect_success 'setup for merge-preserving rebase' \
        'echo First > A &&
@@ -57,6 +65,13 @@ test_expect_success 'setup for merge-preserving rebase' \
        git merge origin/master
        ) &&
 
+       git clone ./. clone4 &&
+       (
+               cd clone4 &&
+               git checkout -b topic origin/topic &&
+               git merge origin/master
+       ) &&
+
        echo Fifth > B &&
        git add B &&
        git commit -m "Add different B" &&
@@ -123,4 +138,15 @@ test_expect_success 'rebase -p preserves no-ff merges' '
        )
 '
 
+test_expect_success 'rebase -p works when base inside second parent' '
+       (
+       cd clone4 &&
+       git fetch &&
+       git rebase -p HEAD^2 &&
+       test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
+       test 1 = $(git rev-list --all --pretty=oneline | grep "Modify B" | wc -l) &&
+       test 1 = $(git rev-list --all --pretty=oneline | grep "Merge remote-tracking branch " | wc -l)
+       )
+'
+
 test_done
index 14a23cd8726fbb33df480133ed0466177916b7fb..ace8e54e9b374688751cc470eeb9003ca7f5c48f 100755 (executable)
@@ -37,7 +37,7 @@ test_expect_success 'setup' '
 #        -- C1 --
 #
 test_expect_success 'squash F1 into D1' '
-       FAKE_LINES="1 squash 3 2" git rebase -i -p B1 &&
+       FAKE_LINES="1 squash 4 2 3" git rebase -i -p B1 &&
        test "$(git rev-parse HEAD^2)" = "$(git rev-parse C1)" &&
        test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" &&
        git tag E2
diff --git a/t/t4048-diff-combined-binary.sh b/t/t4048-diff-combined-binary.sh
new file mode 100755 (executable)
index 0000000..87a8949
--- /dev/null
@@ -0,0 +1,212 @@
+#!/bin/sh
+
+test_description='combined and merge diff handle binary files and textconv'
+. ./test-lib.sh
+
+test_expect_success 'setup binary merge conflict' '
+       echo oneQ1 | q_to_nul >binary &&
+       git add binary &&
+       git commit -m one &&
+       echo twoQ2 | q_to_nul >binary &&
+       git commit -a -m two &&
+       git checkout -b branch-binary HEAD^ &&
+       echo threeQ3 | q_to_nul >binary &&
+       git commit -a -m three &&
+       test_must_fail git merge master &&
+       echo resolvedQhooray | q_to_nul >binary &&
+       git commit -a -m resolved
+'
+
+cat >expect <<'EOF'
+resolved
+
+diff --git a/binary b/binary
+index 7ea6ded..9563691 100644
+Binary files a/binary and b/binary differ
+resolved
+
+diff --git a/binary b/binary
+index 6197570..9563691 100644
+Binary files a/binary and b/binary differ
+EOF
+test_expect_success 'diff -m indicates binary-ness' '
+       git show --format=%s -m >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+resolved
+
+diff --combined binary
+index 7ea6ded,6197570..9563691
+Binary files differ
+EOF
+test_expect_success 'diff -c indicates binary-ness' '
+       git show --format=%s -c >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+resolved
+
+diff --cc binary
+index 7ea6ded,6197570..9563691
+Binary files differ
+EOF
+test_expect_success 'diff --cc indicates binary-ness' '
+       git show --format=%s --cc >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'setup non-binary with binary attribute' '
+       git checkout master &&
+       test_commit one text &&
+       test_commit two text &&
+       git checkout -b branch-text HEAD^ &&
+       test_commit three text &&
+       test_must_fail git merge master &&
+       test_commit resolved text &&
+       echo text -diff >.gitattributes
+'
+
+cat >expect <<'EOF'
+resolved
+
+diff --git a/text b/text
+index 2bdf67a..2ab19ae 100644
+Binary files a/text and b/text differ
+resolved
+
+diff --git a/text b/text
+index f719efd..2ab19ae 100644
+Binary files a/text and b/text differ
+EOF
+test_expect_success 'diff -m respects binary attribute' '
+       git show --format=%s -m >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+resolved
+
+diff --combined text
+index 2bdf67a,f719efd..2ab19ae
+Binary files differ
+EOF
+test_expect_success 'diff -c respects binary attribute' '
+       git show --format=%s -c >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+resolved
+
+diff --cc text
+index 2bdf67a,f719efd..2ab19ae
+Binary files differ
+EOF
+test_expect_success 'diff --cc respects binary attribute' '
+       git show --format=%s --cc >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'setup textconv attribute' '
+       echo "text diff=upcase" >.gitattributes &&
+       git config diff.upcase.textconv "tr a-z A-Z <"
+'
+
+cat >expect <<'EOF'
+resolved
+
+diff --git a/text b/text
+index 2bdf67a..2ab19ae 100644
+--- a/text
++++ b/text
+@@ -1 +1 @@
+-THREE
++RESOLVED
+resolved
+
+diff --git a/text b/text
+index f719efd..2ab19ae 100644
+--- a/text
++++ b/text
+@@ -1 +1 @@
+-TWO
++RESOLVED
+EOF
+test_expect_success 'diff -m respects textconv attribute' '
+       git show --format=%s -m >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+resolved
+
+diff --combined text
+index 2bdf67a,f719efd..2ab19ae
+--- a/text
++++ b/text
+@@@ -1,1 -1,1 +1,1 @@@
+- THREE
+ -TWO
+++RESOLVED
+EOF
+test_expect_success 'diff -c respects textconv attribute' '
+       git show --format=%s -c >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+resolved
+
+diff --cc text
+index 2bdf67a,f719efd..2ab19ae
+--- a/text
++++ b/text
+@@@ -1,1 -1,1 +1,1 @@@
+- THREE
+ -TWO
+++RESOLVED
+EOF
+test_expect_success 'diff --cc respects textconv attribute' '
+       git show --format=%s --cc >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+diff --combined text
+index 2bdf67a,f719efd..2ab19ae
+--- a/text
++++ b/text
+@@@ -1,1 -1,1 +1,1 @@@
+- three
+ -two
+++resolved
+EOF
+test_expect_success 'diff-tree plumbing does not respect textconv' '
+       git diff-tree HEAD -c -p >full &&
+       tail -n +2 full >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+diff --cc text
+index 2bdf67a,f719efd..0000000
+--- a/text
++++ b/text
+@@@ -1,1 -1,1 +1,5 @@@
+++<<<<<<< HEAD
+ +THREE
+++=======
++ TWO
+++>>>>>>> MASTER
+EOF
+test_expect_success 'diff --cc respects textconv on worktree file' '
+       git reset --hard HEAD^ &&
+       test_must_fail git merge master &&
+       git diff >actual &&
+       test_cmp expect actual
+'
+
+test_done
index a1fddd4d15fb2c3cb5d0ab6e09a461314fb4b1f1..ca5b027c557014cff85ca4ba7d118db578a57256 100755 (executable)
@@ -47,7 +47,7 @@ test_expect_success setup '
                git init &&
                echo subcontent > subfile &&
                git add subfile &&
-               git submodule add "$pwd/deepsubmodule" deepsubmodule &&
+               git submodule add "$pwd/deepsubmodule" subdir/deepsubmodule &&
                git commit -a -m new
        ) &&
        git submodule add "$pwd/submodule" submodule &&
@@ -58,7 +58,7 @@ test_expect_success setup '
                git submodule update --init --recursive
        ) &&
        echo "Fetching submodule submodule" > expect.out &&
-       echo "Fetching submodule submodule/deepsubmodule" >> expect.out
+       echo "Fetching submodule submodule/subdir/deepsubmodule" >> expect.out
 '
 
 test_expect_success "fetch --recurse-submodules recurses into submodules" '
@@ -277,12 +277,12 @@ test_expect_success "Recursion picks up all submodules when necessary" '
        (
                cd submodule &&
                (
-                       cd deepsubmodule &&
+                       cd subdir/deepsubmodule &&
                        git fetch &&
                        git checkout -q FETCH_HEAD
                ) &&
                head1=$(git rev-parse --short HEAD^) &&
-               git add deepsubmodule &&
+               git add subdir/deepsubmodule &&
                git commit -m "new deepsubmodule"
                head2=$(git rev-parse --short HEAD) &&
                echo "From $pwd/submodule" > ../expect.err.sub &&
@@ -309,12 +309,12 @@ test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no ne
        (
                cd submodule &&
                (
-                       cd deepsubmodule &&
+                       cd subdir/deepsubmodule &&
                        git fetch &&
                        git checkout -q FETCH_HEAD
                ) &&
                head1=$(git rev-parse --short HEAD^) &&
-               git add deepsubmodule &&
+               git add subdir/deepsubmodule &&
                git commit -m "new deepsubmodule"
                head2=$(git rev-parse --short HEAD) &&
                echo "From $pwd/submodule" > ../expect.err.sub &&
@@ -345,13 +345,13 @@ test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necess
                git config fetch.recurseSubmodules false &&
                (
                        cd submodule &&
-                       git config -f .gitmodules submodule.deepsubmodule.fetchRecursive false
+                       git config -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive false
                ) &&
                git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err &&
                git config --unset fetch.recurseSubmodules
                (
                        cd submodule &&
-                       git config --unset -f .gitmodules submodule.deepsubmodule.fetchRecursive
+                       git config --unset -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive
                )
        ) &&
        test_i18ncmp expect.out actual.out &&
index 874279e32da98ac2c20137a207a0d115f073e444..3f115d9ca966879ccd7d587911d7d54bc88c08c2 100755 (executable)
@@ -47,8 +47,10 @@ test_expect_success 'setup - repository to add submodules to' '
 '
 
 # The 'submodule add' tests need some repository to add as a submodule.
-# The trash directory is a good one as any.
-submodurl=$TRASH_DIRECTORY
+# The trash directory is a good one as any. We need to canonicalize
+# the name, though, as some tests compare it to the absolute path git
+# generates, which will expand symbolic links.
+submodurl=$(pwd -P)
 
 listbranches() {
        git for-each-ref --format='%(refname)' 'refs/heads/*'
index e5be13c271c92ce7c51601ee1eaf966d849d8ae4..835a50624114253b634896e1cceae43578a279bf 100755 (executable)
@@ -292,4 +292,22 @@ test_expect_success 'use "update --recursive nested1" to checkout all submodules
        )
 '
 
+test_expect_success 'command passed to foreach retains notion of stdin' '
+       (
+               cd super &&
+               git submodule foreach echo success >../expected &&
+               yes | git submodule foreach "read y && test \"x\$y\" = xy && echo success" >../actual
+       ) &&
+       test_cmp expected actual
+'
+
+test_expect_success 'command passed to foreach --recursive retains notion of stdin' '
+       (
+               cd clone2 &&
+               git submodule foreach --recursive echo success >../expected &&
+               yes | git submodule foreach --recursive "read y && test \"x\$y\" = xy && echo success" >../actual
+       ) &&
+       test_cmp expected actual
+'
+
 test_done
diff --git a/t/t9159-git-svn-no-parent-mergeinfo.sh b/t/t9159-git-svn-no-parent-mergeinfo.sh
new file mode 100755 (executable)
index 0000000..85120b7
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+test_description='git svn handling of root commits in merge ranges'
+. ./lib-git-svn.sh
+
+test_expect_success 'test handling of root commits in merge ranges' '
+       mkdir -p init/trunk init/branches init/tags &&
+       echo "r1" > init/trunk/file.txt &&
+       svn_cmd import -m "initial import" init "$svnrepo" &&
+       svn_cmd co "$svnrepo" tmp &&
+       (
+               cd tmp &&
+               echo "r2" > trunk/file.txt &&
+               svn_cmd commit -m "Modify file.txt on trunk" &&
+               svn_cmd cp trunk@1 branches/a &&
+               svn_cmd commit -m "Create branch a from trunk r1" &&
+               svn_cmd propset svn:mergeinfo /trunk:1-2 branches/a &&
+               svn_cmd commit -m "Fake merge of trunk r2 into branch a" &&
+               mkdir branches/b &&
+               echo "r5" > branches/b/file2.txt &&
+               svn_cmd add branches/b &&
+               svn_cmd commit -m "Create branch b from thin air" &&
+               echo "r6" > branches/b/file2.txt &&
+               svn_cmd commit -m "Modify file2.txt on branch b" &&
+               svn_cmd cp branches/b@5 branches/c &&
+               svn_cmd commit -m "Create branch c from branch b r5" &&
+               svn_cmd propset svn:mergeinfo /branches/b:5-6 branches/c &&
+               svn_cmd commit -m "Fake merge of branch b r6 into branch c"
+       ) &&
+       git svn init -s "$svnrepo" &&
+       git svn fetch
+       '
+
+test_done
index 8c57a0059574ff78626ad0e26d3f75da9204b23d..df25f1792923a65aab2c4ce88e7b528effb381f5 100644 (file)
@@ -446,9 +446,14 @@ test_debug () {
 
 test_run_ () {
        test_cleanup=:
+       expecting_failure=$2
        eval >&3 2>&4 "$1"
        eval_ret=$?
-       eval >&3 2>&4 "$test_cleanup"
+
+       if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure"
+       then
+               eval >&3 2>&4 "$test_cleanup"
+       fi
        if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then
                echo ""
        fi
@@ -497,7 +502,7 @@ test_expect_failure () {
        if ! test_skip "$@"
        then
                say >&3 "checking known breakage: $2"
-               test_run_ "$2"
+               test_run_ "$2" expecting_failure
                if [ "$?" = 0 -a "$eval_ret" = 0 ]
                then
                        test_known_broken_ok_ "$1"
@@ -774,6 +779,9 @@ test_cmp() {
 #
 # except that the greeting and config --unset must both succeed for
 # the test to pass.
+#
+# Note that under --immediate mode, no clean-up is done to help diagnose
+# what went wrong.
 
 test_when_finished () {
        test_cleanup="{ $*
index 07f83642443601d107e0a2425407b3250c022dcd..cc616c3f991a655d10fcac15055fcdfafa8620fd 100644 (file)
@@ -593,7 +593,7 @@ static int unpack_nondirectories(int n, unsigned long mask,
 static int unpack_failed(struct unpack_trees_options *o, const char *message)
 {
        discard_index(&o->result);
-       if (!o->gently) {
+       if (!o->gently && !o->exiting_early) {
                if (message)
                        return error("%s", message);
                return -1;
@@ -1133,6 +1133,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
                display_error_msgs(o);
        mark_all_ce_unused(o->src_index);
        ret = unpack_failed(o, NULL);
+       if (o->exiting_early)
+               ret = 0;
        goto done;
 }
 
@@ -1166,11 +1168,22 @@ static int verify_uptodate_1(struct cache_entry *ce,
 {
        struct stat st;
 
-       if (o->index_only || (!((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) && (o->reset || ce_uptodate(ce))))
+       if (o->index_only)
+               return 0;
+
+       /*
+        * CE_VALID and CE_SKIP_WORKTREE cheat, we better check again
+        * if this entry is truly up-to-date because this file may be
+        * overwritten.
+        */
+       if ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce))
+               ; /* keep checking */
+       else if (o->reset || ce_uptodate(ce))
                return 0;
 
        if (!lstat(ce->name, &st)) {
-               unsigned changed = ie_match_stat(o->src_index, ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
+               int flags = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE;
+               unsigned changed = ie_match_stat(o->src_index, ce, &st, flags);
                if (!changed)
                        return 0;
                /*
index 64f02cb03ab242ac08ea0f1afbb24e71cf6664aa..79989483079970e9dad42512e522eef8ea2a75a4 100644 (file)
@@ -46,6 +46,7 @@ struct unpack_trees_options {
                     debug_unpack,
                     skip_sparse_checkout,
                     gently,
+                    exiting_early,
                     show_all_errors,
                     dry_run;
        const char *prefix;
index e55310cd02c8e7d1f0404b2fee9539e7340993d9..01d3a8b81e628b0a088e3e9fc0ca59acf7d9c58d 100644 (file)
@@ -281,3 +281,20 @@ struct userdiff_driver *userdiff_find_by_path(const char *path)
                return NULL;
        return userdiff_find_by_name(check.value);
 }
+
+struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver)
+{
+       if (!driver->textconv)
+               return NULL;
+
+       if (driver->textconv_want_cache && !driver->textconv_cache) {
+               struct notes_cache *c = xmalloc(sizeof(*c));
+               struct strbuf name = STRBUF_INIT;
+
+               strbuf_addf(&name, "textconv/%s", driver->name);
+               notes_cache_init(c, name.buf, driver->textconv);
+               driver->textconv_cache = c;
+       }
+
+       return driver;
+}
index 942d5949501027fb5d30e0d59629aab38fd2669a..4a7e78ffbcc6d552a39dcccd9008d6c11919e432 100644 (file)
@@ -23,4 +23,6 @@ int userdiff_config(const char *k, const char *v);
 struct userdiff_driver *userdiff_find_by_name(const char *name);
 struct userdiff_driver *userdiff_find_by_path(const char *path);
 
+struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver);
+
 #endif /* USERDIFF */