Code

Merge branch 'bw/diff-metainfo-color' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 21 Jun 2010 12:40:10 +0000 (05:40 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 21 Jun 2010 12:40:10 +0000 (05:40 -0700)
* bw/diff-metainfo-color:
  diff: fix coloring of extended diff headers

112 files changed:
.gitignore
Documentation/RelNotes-1.7.1.1.txt [new file with mode: 0644]
Documentation/SubmittingPatches
Documentation/blame-options.txt
Documentation/config.txt
Documentation/git-add.txt
Documentation/git-checkout.txt
Documentation/git-commit.txt
Documentation/git-log.txt
Documentation/git-mailinfo.txt
Documentation/git-notes.txt
Documentation/git-rebase.txt
Documentation/git-send-email.txt
Documentation/git-shortlog.txt
Documentation/git-update-index.txt
Documentation/gitdiffcore.txt
Documentation/pretty-formats.txt
Documentation/pretty-options.txt
GIT-VERSION-GEN
Makefile
RelNotes
attr.c
builtin/apply.c
builtin/blame.c
builtin/clone.c
builtin/commit.c
builtin/describe.c
builtin/for-each-ref.c
builtin/grep.c
builtin/index-pack.c
builtin/init-db.c
builtin/merge-file.c
builtin/merge-tree.c
builtin/notes.c
builtin/pack-objects.c
builtin/rerere.c
builtin/revert.c
builtin/shortlog.c
builtin/show-branch.c
cache.h
combine-diff.c
compat/mingw.c
compat/mingw.h
compat/win32/pthread.h
compat/win32mmap.c
config.mak.in
configure.ac
contrib/completion/git-completion.bash
contrib/hooks/post-receive-email
diff-no-index.c
diff.c
dir.c
exec_cmd.c
git-add--interactive.perl
git-am.sh
git-compat-util.h
git-send-email.perl
git-stash.sh
git-submodule.sh
gitweb/Makefile
http-walker.c
http.c
http.h
merge-file.c
object.c
pack-check.c
pack.h
pretty.c
remote-curl.c
remote.c
run-command.c
setup.c
sha1_file.c
shortlog.h
t/README
t/lib-t6000.sh [new file with mode: 0644]
t/t0000-basic.sh
t/t0001-init.sh
t/t0003-attributes.sh
t/t1501-worktree.sh
t/t2007-checkout-symlink.sh
t/t2106-update-index-assume-unchanged.sh [new file with mode: 0755]
t/t3307-notes-man.sh [new file with mode: 0755]
t/t3903-stash.sh
t/t4124-apply-ws-rule.sh
t/t4201-shortlog.sh
t/t5516-fetch-push.sh
t/t5541-http-push.sh
t/t5550-http-fetch.sh
t/t5601-clone.sh
t/t5704-bundle.sh
t/t5705-clone-2gb.sh
t/t6000lib.sh [deleted file]
t/t6002-rev-list-bisect.sh
t/t6003-rev-list-topo-order.sh
t/t6006-rev-list-format.sh
t/t6101-rev-parse-parents.sh
t/t6120-describe.sh
t/t7006-pager.sh
t/t7502-commit.sh
t/t7508-status.sh
t/test-lib.sh
tag.c
tag.h
thread-utils.c
thread-utils.h
unpack-trees.c
wrapper.c
wt-status.c
xdiff-interface.c
xdiff-interface.h
xdiff/xmerge.c

index 561401b2b5cab632afad901c3b886545a3ddd405..dbf1b90c63573b08efc894ed8c1e02de58fd53e4 100644 (file)
 /git-write-tree
 /git-core-*/?*
 /gitk-git/gitk-wish
+/gitweb/GITWEB-BUILD-OPTIONS
 /gitweb/gitweb.cgi
 /gitweb/gitweb.min.*
 /test-chmtime
diff --git a/Documentation/RelNotes-1.7.1.1.txt b/Documentation/RelNotes-1.7.1.1.txt
new file mode 100644 (file)
index 0000000..2eef038
--- /dev/null
@@ -0,0 +1,46 @@
+Git v1.7.1.1 Release Notes (draft)
+==================================
+
+Fixes since v1.7.1
+------------------
+
+ * Authentication over http transport can now be made lazily, in that the
+   request can first go to a URL without username, get a 401 response and
+   then the client will ask for the username to use.
+
+ * We used to mistakenly think "../work" is a subdirectory of the current
+   directory when we are in "../work-xyz".
+
+ * The attribute mechanism now allows an entry that uses an attribute
+   macro that set/unset one attribute, immediately followed by an
+   overriding setting; this makes attribute macros much easier to use.
+
+ * "git am -3" did not show diagnosis when the patch in the message was corrupt.
+
+ * "git bundle --stdin" segfaulted.
+
+ * "git describe" did not tie-break tags that point at the same commit
+   correctly; newer ones are preferred by paying attention to the
+   tagger date now.
+
+ * "git fetch" over HTTP verifies the downloaded packfiles more robustly.
+
+ * The memory usage by "git index-pack" (run during "git fetch" and "git
+   push") got leaner.
+
+ * "GIT_DIR=foo.git git init --bare bar.git" created foo.git instead of bar.git.
+
+ * "git log --abbrev=$num --format='%h' ignored --abbrev=$num.
+
+ * "git send-email" lacked a way to specify the domainname used in the
+   EHLO/HELO exchange, causing rejected connection from picky servers.
+   It learned --smtp-domain option to solve this issue.
+
+ * "git stash" incorrectly lost paths in the working tree that were
+   previously removed from the index.
+
+ * "git status" stopped refreshing the index by mistake in 1.7.1.
+
+ * "git status" showed excess "hints" even when advice.statusHints is set to false.
+
+And other minor fixes and documentation updates.
index abc65de9464144a7bac38756c01ab315ab6922eb..eb53e0636e3c3bab06e88ce3371945f5602c5756 100644 (file)
@@ -41,6 +41,7 @@ Checklist (and a short version for the impatient):
          maintainer (gitster@pobox.com) if (and only if) the patch
          is ready for inclusion. If you use git-send-email(1),
          please test it first by sending email to yourself.
+       - see below for instructions specific to your mailer
 
 Long version:
 
@@ -53,6 +54,34 @@ But the patch submission requirements are a lot more relaxed
 here on the technical/contents front, because the core GIT is
 thousand times smaller ;-).  So here is only the relevant bits.
 
+(0) Decide what to base your work on.
+
+In general, always base your work on the oldest branch that your
+change is relevant to.
+
+ - A bugfix should be based on 'maint' in general. If the bug is not
+   present in 'maint', base it on 'master'. For a bug that's not yet
+   in 'master', find the topic that introduces the regression, and
+   base your work on the tip of the topic.
+
+ - A new feature should be based on 'master' in general. If the new
+   feature depends on a topic that is in 'pu', but not in 'master',
+   base your work on the tip of that topic.
+
+ - Corrections and enhancements to a topic not yet in 'master' should
+   be based on the tip of that topic. If the topic has not been merged
+   to 'next', it's alright to add a note to squash minor corrections
+   into the series.
+
+ - In the exceptional case that a new feature depends on several topics
+   not in 'master', start working on 'next' or 'pu' privately and send
+   out patches for discussion. Before the final merge, you may have to
+   wait until some of the dependent topics graduate to 'master', and
+   rebase your work.
+
+To find the tip of a topic branch, run "git log --first-parent
+master..pu" and look for the merge commit. The second parent of this
+commit is the tip of the topic branch.
 
 (1) Make separate commits for logically separate changes.
 
@@ -170,17 +199,16 @@ patch, format it as "multipart/signed", not a text/plain message
 that starts with '-----BEGIN PGP SIGNED MESSAGE-----'.  That is
 not a text/plain, it's something else.
 
-Note that your maintainer does not necessarily read everything
-on the git mailing list.  If your patch is for discussion first,
-send it "To:" the mailing list, and optionally "cc:" him.  If it
-is trivially correct or after the list reached a consensus, send
-it "To:" the maintainer and optionally "cc:" the list for
-inclusion.
-
-Also note that your maintainer does not actively involve himself in
-maintaining what are in contrib/ hierarchy.  When you send fixes and
-enhancements to them, do not forget to "cc: " the person who primarily
-worked on that hierarchy in contrib/.
+Unless your patch is a very trivial and an obviously correct one,
+first send it with "To:" set to the mailing list, with "cc:" listing
+people who are involved in the area you are touching (the output from
+"git blame $path" and "git shortlog --no-merges $path" would help to
+identify them), to solicit comments and reviews.  After the list
+reached a consensus that it is a good idea to apply the patch, re-send
+it with "To:" set to the maintainer and optionally "cc:" the list for
+inclusion.  Do not forget to add trailers such as "Acked-by:",
+"Reviewed-by:" and "Tested-by:" after your "Signed-off-by:" line as
+necessary.
 
 
 (4) Sign your work
@@ -519,9 +547,27 @@ Gmail
 
 GMail does not appear to have any way to turn off line wrapping in the web
 interface, so this will mangle any emails that you send.  You can however
-use any IMAP email client to connect to the google imap server, and forward
+use "git send-email" and send your patches through the GMail SMTP server, or
+use any IMAP email client to connect to the google IMAP server and forward
 the emails through that.
 
+To use "git send-email" and send your patches through the GMail SMTP server,
+edit ~/.gitconfig to specify your account settings:
+
+[sendemail]
+       smtpencryption = tls
+       smtpserver = smtp.gmail.com
+       smtpuser = user@gmail.com
+       smtppass = p4ssw0rd
+       smtpserverport = 587
+
+Once your commits are ready to be sent to the mailing list, run the
+following commands:
+
+  $ git format-patch --cover-letter -M origin/master -o outgoing/
+  $ edit outgoing/0000-*
+  $ git send-email outgoing/*
+
 To submit using the IMAP interface, first, edit your ~/.gitconfig to specify your
 account settings:
 
@@ -537,8 +583,7 @@ You might need to instead use: folder = "[Google Mail]/Drafts" if you get an err
 that the "Folder doesn't exist".
 
 Once your commits are ready to be sent to the mailing list, run the
-following command to send the patch emails to your Gmail Drafts
-folder.
+following commands:
 
   $ git format-patch --cover-letter -M --stdout origin/master | git imap-send
 
@@ -546,19 +591,3 @@ Just make sure to disable line wrapping in the email client (GMail web
 interface will line wrap no matter what, so you need to use a real
 IMAP client).
 
-Alternatively, you can use "git send-email" and send your patches
-through the GMail SMTP server.  edit ~/.gitconfig to specify your
-account settings:
-
-[sendemail]
-       smtpencryption = tls
-       smtpserver = smtp.gmail.com
-       smtpuser = user@gmail.com
-       smtppass = p4ssw0rd
-       smtpserverport = 587
-
-Once your commits are ready to be sent to the mailing list, run the
-following commands:
-
-  $ git format-patch --cover-letter -M origin/master -o outgoing/
-  $ git send-email outgoing/*
index d8205691c6ff85dcbbe5f064463d4671ec10125e..16e3c685762a311eda1bbc39adb8ab19e000ec97 100644 (file)
@@ -90,9 +90,9 @@ of lines before or after the line given by <start>.
        running extra passes of inspection.
 +
 <num> is optional but it is the lower bound on the number of
-alphanumeric characters that git must detect as moving
+alphanumeric characters that git must detect as moving/copying
 within a file for it to associate those lines with the parent
-commit.
+commit. The default value is 20.
 
 -C|<num>|::
        In addition to `-M`, detect lines moved or copied from other
@@ -105,9 +105,11 @@ commit.
        looks for copies from other files in any commit.
 +
 <num> is optional but it is the lower bound on the number of
-alphanumeric characters that git must detect as moving
+alphanumeric characters that git must detect as moving/copying
 between files for it to associate those lines with the parent
-commit.
+commit. And the default value is 40. If there are more than one
+`-C` options given, the <num> argument of the last `-C` will
+take effect.
 
 -h::
 --help::
index 92f851e797ca820f6f6126391eafee0d4eec7e26..ae174c99dba1d398eef66f13ec15b257eabb7034 100644 (file)
@@ -518,18 +518,12 @@ check that makes sure that existing object files will not get overwritten.
 
 core.notesRef::
        When showing commit messages, also show notes which are stored in
-       the given ref.  This ref is expected to contain files named
-       after the full SHA-1 of the commit they annotate.  The ref
-       must be fully qualified.
+       the given ref.  The ref must be fully qualified.  If the given
+       ref does not exist, it is not an error but means that no
+       notes should be printed.
 +
-If such a file exists in the given ref, the referenced blob is read, and
-appended to the commit message, separated by a "Notes (<refname>):"
-line (shortened to "Notes:" in the case of "refs/notes/commits").  If the
-given ref itself does not exist, it is not an error, but means that no
-notes should be printed.
-+
-This setting defaults to "refs/notes/commits", and can be overridden by
-the `GIT_NOTES_REF` environment variable.
+This setting defaults to "refs/notes/commits", and it can be overridden by
+the 'GIT_NOTES_REF' environment variable.  See linkgit:git-notes[1].
 
 core.sparseCheckout::
        Enable "sparse checkout" feature. See section "Sparse checkout" in
@@ -1359,10 +1353,6 @@ notes.rewrite.<command>::
        automatically copies your notes from the original to the
        rewritten commit.  Defaults to `true`, but see
        "notes.rewriteRef" below.
-+
-This setting can be overridden with the `GIT_NOTES_REWRITE_REF`
-environment variable, which must be a colon separated list of refs or
-globs.
 
 notes.rewriteMode::
        When copying notes during a rewrite (see the
@@ -1382,6 +1372,10 @@ notes.rewriteRef::
 +
 Does not have a default value; you must configure this variable to
 enable note rewriting.
++
+This setting can be overridden with the `GIT_NOTES_REWRITE_REF`
+environment variable, which must be a colon separated list of refs or
+globs.
 
 pack.window::
        The size of the window used by linkgit:git-pack-objects[1] when no
@@ -1516,7 +1510,7 @@ receive.denyDeletes::
        the ref. Use this to prevent such a ref deletion via a push.
 
 receive.denyCurrentBranch::
-       If set to true or "refuse", receive-pack will deny a ref update
+       If set to true or "refuse", git-receive-pack will deny a ref update
        to the currently checked out branch of a non-bare repository.
        Such a push is potentially dangerous because it brings the HEAD
        out of sync with the index and working tree. If set to "warn",
@@ -1642,6 +1636,7 @@ sendemail.smtppass::
 sendemail.suppresscc::
 sendemail.suppressfrom::
 sendemail.to::
+sendemail.smtpdomain::
 sendemail.smtpserver::
 sendemail.smtpserverport::
 sendemail.smtpuser::
@@ -1681,6 +1676,13 @@ If this variable is not specified, it defaults to 'normal'.
 This variable can be overridden with the -u|--untracked-files option
 of linkgit:git-status[1] and linkgit:git-commit[1].
 
+status.submodulesummary::
+       Defaults to false.
+       If this is set to a non zero number or true (identical to -1 or an
+       unlimited number), the submodule summary will be enabled and a
+       summary of commits for modified submodules will be shown (see
+       --summary-limit option of linkgit:git-submodule[1]).
+
 tar.umask::
        This variable can be used to restrict the permission bits of
        tar archive entries.  The default is 0002, which turns off the
index 51cbeb7032865599317fd9d7d36a9c9e2f8cc0c5..74741a42f409a7af5c60584a0d3b7a0be851811c 100644 (file)
@@ -266,9 +266,9 @@ patch::
 
        y - stage this hunk
        n - do not stage this hunk
-       q - quit, do not stage this hunk nor any of the remaining ones
-       a - stage this and all the remaining hunks in the file
-       d - do not stage this hunk nor any of the remaining hunks in the file
+       q - quit; do not stage this hunk nor any of the remaining ones
+       a - stage this hunk and all later hunks in the file
+       d - do not stage this hunk nor any of the later hunks in the file
        g - select a hunk to go to
        / - search for a hunk matching the given regex
        j - leave this hunk undecided, see next undecided hunk
index 37c1810e3fc8424868333a22094107e99764fc37..a3a87fa7fd29973e15afb93382646ae6f89d0f61 100644 (file)
@@ -136,6 +136,10 @@ edits from your current working tree.
 As a special case, the `"@\{-N\}"` syntax for the N-th last branch
 checks out the branch (instead of detaching).  You may also specify
 `-` which is synonymous with `"@\{-1\}"`.
++
+As a further special case, you may use `"A...B"` as a shortcut for the
+merge base of `A` and `B` if there is exactly one merge base. You can
+leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.
 
 <new_branch>::
        Name for the new branch.
index 64fb458b4533eeda9c583ac926025495b260cf9b..69eb86e4506411b0d8029f849fd4ebff47166d05 100644 (file)
@@ -95,10 +95,11 @@ OPTIONS
        read the message from the standard input.
 
 --author=<author>::
-       Override the author name used in the commit.  You can use the
-       standard `A U Thor <author@example.com>` format.  Otherwise,
-       an existing commit that matches the given string and its author
-       name is used.
+       Override the commit author. Specify an explicit author using the
+       standard `A U Thor <author@example.com>` format. Otherwise <author>
+       is assumed to be a pattern and is used to search for an existing
+       commit by that author (i.e. rev-list --all -i --author=<author>);
+       the commit author is then copied from the first such commit found.
 
 --date=<date>::
        Override the author date used in the commit.
index fb184ba1863845797a5f296581ec74a1b31bef1a..d7f6a9cc3ee335c5437e27dd362ef47c8753ff43 100644 (file)
@@ -132,6 +132,48 @@ Discussion
 
 include::i18n.txt[]
 
+Configuration
+-------------
+
+See linkgit:git-config[1] for core variables and linkgit:git-diff[1]
+for settings related to diff generation.
+
+format.pretty::
+       Default for the `--format` option.  (See "PRETTY FORMATS" above.)
+       Defaults to "medium".
+
+i18n.logOutputEncoding::
+       Encoding to use when displaying logs.  (See "Discussion", above.)
+       Defaults to the value of `i18n.commitEncoding` if set, UTF-8
+       otherwise.
+
+log.date::
+       Default format for human-readable dates.  (Compare the
+       `--date` option.)  Defaults to "default", which means to write
+       dates like `Sat May 8 19:35:34 2010 -0500`.
+
+log.showroot::
+       If `false`, 'git log' and related commands will not treat the
+       initial commit as a big creation event.  Any root commits in
+       `git log -p` output would be shown without a diff attached.
+       The default is `true`.
+
+mailmap.file::
+       See linkgit:git-shortlog[1].
+
+notes.displayRef::
+       Which refs, in addition to the default set by `core.notesRef`
+       or 'GIT_NOTES_REF', to read notes from when showing commit
+       messages with the 'log' family of commands.  See
+       linkgit:git-notes[1].
++
+May be an unabbreviated ref name or a glob and may be specified
+multiple times.  A warning will be issued for refs that do not exist,
+but a glob that does not match any refs is silently ignored.
++
+This setting can be disabled by the `--no-standard-notes` option,
+overridden by the 'GIT_NOTES_DISPLAY_REF' environment variable,
+and supplemented by the `--show-notes` option.
 
 Author
 ------
index e3d58cbac3f162cc01d8731485f220fd70fed17b..3ea5aad56c5e1cec7fc2ca01ba9b5ea6badebe2f 100644 (file)
@@ -40,16 +40,16 @@ OPTIONS
 -u::
        The commit log message, author name and author email are
        taken from the e-mail, and after minimally decoding MIME
-       transfer encoding, re-coded in UTF-8 by transliterating
+       transfer encoding, re-coded in the charset specified by
+       i18n.commitencoding (defaulting to UTF-8) by transliterating
        them.  This used to be optional but now it is the default.
 +
 Note that the patch is always used as-is without charset
 conversion, even with this flag.
 
 --encoding=<encoding>::
-       Similar to -u but if the local convention is different
-       from what is specified by i18n.commitencoding, this flag
-       can be used to override it.
+       Similar to -u.  But when re-coding, the charset specified here is
+       used instead of the one specified by i18n.commitencoding or UTF-8.
 
 -n::
        Disable all charset re-coding of the metadata.
index 4e5113b837230c8f050cf4bbe10e8de4b3271bd0..de63ef0745a82136eeee6a2f0993984f2ed2f4ec 100644 (file)
@@ -3,7 +3,7 @@ git-notes(1)
 
 NAME
 ----
-git-notes - Add/inspect object notes
+git-notes - Add or inspect object notes
 
 SYNOPSIS
 --------
@@ -20,24 +20,26 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-This command allows you to add/remove notes to/from objects, without
-changing the objects themselves.
+Adds, removes, or reads notes attached to objects, without touching
+the objects themselves.
 
-A typical use of notes is to extend a commit message without having
-to change the commit itself. Such commit notes can be shown by `git log`
-along with the original commit message. To discern these notes from the
+By default, notes are saved to and read from `refs/notes/commits`, but
+this default can be overridden.  See the OPTIONS, CONFIGURATION, and
+ENVIRONMENT sections below.  If this ref does not exist, it will be
+quietly created when it is first needed to store a note.
+
+A typical use of notes is to supplement a commit message without
+changing the commit itself. Notes can be shown by 'git log' along with
+the original commit message. To distinguish these notes from the
 message stored in the commit object, the notes are indented like the
 message, after an unindented line saying "Notes (<refname>):" (or
-"Notes:" for the default setting).
+"Notes:" for `refs/notes/commits`).
 
-This command always manipulates the notes specified in "core.notesRef"
-(see linkgit:git-config[1]), which can be overridden by GIT_NOTES_REF.
-To change which notes are shown by 'git-log', see the
-"notes.displayRef" configuration.
+To change which notes are shown by 'git log', see the
+"notes.displayRef" configuration in linkgit:git-log[1].
 
-See the description of "notes.rewrite.<command>" in
-linkgit:git-config[1] for a way of carrying your notes across commands
-that rewrite commits.
+See the "notes.rewrite.<command>" configuration for a way to carry
+notes across commands that rewrite commits.
 
 
 SUBCOMMANDS
@@ -101,15 +103,20 @@ OPTIONS
        Use the given note message (instead of prompting).
        If multiple `-m` options are given, their values
        are concatenated as separate paragraphs.
+       Lines starting with `#` and empty lines other than a
+       single line between paragraphs will be stripped out.
 
 -F <file>::
 --file=<file>::
        Take the note message from the given file.  Use '-' to
        read the note message from the standard input.
+       Lines starting with `#` and empty lines other than a
+       single line between paragraphs will be stripped out.
 
 -C <object>::
 --reuse-message=<object>::
-       Reuse the note message from the given note object.
+       Take the note message from the given blob object (for
+       example, another note).
 
 -c <object>::
 --reedit-message=<object>::
@@ -117,22 +124,144 @@ OPTIONS
        the user can further edit the note message.
 
 --ref <ref>::
-       Manipulate the notes tree in <ref>.  This overrides both
-       GIT_NOTES_REF and the "core.notesRef" configuration.  The ref
+       Manipulate the notes tree in <ref>.  This overrides
+       'GIT_NOTES_REF' and the "core.notesRef" configuration.  The ref
        is taken to be in `refs/notes/` if it is not qualified.
 
 
-NOTES
------
+DISCUSSION
+----------
+
+Commit notes are blobs containing extra information about an object
+(usually information to supplement a commit's message).  These blobs
+are taken from notes refs.  A notes ref is usually a branch which
+contains "files" whose paths are the object names for the objects
+they describe, with some directory separators included for performance
+reasons footnote:[Permitted pathnames have the form
+'ab'`/`'cd'`/`'ef'`/`'...'`/`'abcdef...': a sequence of directory
+names of two hexadecimal digits each followed by a filename with the
+rest of the object ID.].
 
 Every notes change creates a new commit at the specified notes ref.
 You can therefore inspect the history of the notes by invoking, e.g.,
-`git log -p notes/commits`.
+`git log -p notes/commits`.  Currently the commit message only records
+which operation triggered the update, and the commit authorship is
+determined according to the usual rules (see linkgit:git-commit[1]).
+These details may change in the future.
+
+It is also permitted for a notes ref to point directly to a tree
+object, in which case the history of the notes can be read with
+`git log -p -g <refname>`.
+
+
+EXAMPLES
+--------
+
+You can use notes to add annotations with information that was not
+available at the time a commit was written.
+
+------------
+$ git notes add -m 'Tested-by: Johannes Sixt <j6t@kdbg.org>' 72a144e2
+$ git show -s 72a144e
+[...]
+    Signed-off-by: Junio C Hamano <gitster@pobox.com>
+
+Notes:
+    Tested-by: Johannes Sixt <j6t@kdbg.org>
+------------
+
+In principle, a note is a regular Git blob, and any kind of
+(non-)format is accepted.  You can binary-safely create notes from
+arbitrary files using 'git hash-object':
+
+------------
+$ cc *.c
+$ blob=$(git hash-object -w a.out)
+$ git notes --ref=built add -C "$blob" HEAD
+------------
+
+Of course, it doesn't make much sense to display non-text-format notes
+with 'git log', so if you use such notes, you'll probably need to write
+some special-purpose tools to do something useful with them.
+
+
+CONFIGURATION
+-------------
+
+core.notesRef::
+       Notes ref to read and manipulate instead of
+       `refs/notes/commits`.  Must be an unabbreviated ref name.
+       This setting can be overridden through the environment and
+       command line.
 
-Currently the commit message only records which operation triggered
-the update, and the commit authorship is determined according to the
-usual rules (see linkgit:git-commit[1]).  These details may change in
-the future.
+notes.displayRef::
+       Which ref (or refs, if a glob or specified more than once), in
+       addition to the default set by `core.notesRef` or
+       'GIT_NOTES_REF', to read notes from when showing commit
+       messages with the 'git log' family of commands.
+       This setting can be overridden on the command line or by the
+       'GIT_NOTES_DISPLAY_REF' environment variable.
+       See linkgit:git-log[1].
+
+notes.rewrite.<command>::
+       When rewriting commits with <command> (currently `amend` or
+       `rebase`), if this variable is `false`, git will not copy
+       notes from the original to the rewritten commit.  Defaults to
+       `true`.  See also "`notes.rewriteRef`" below.
++
+This setting can be overridden by the 'GIT_NOTES_REWRITE_REF'
+environment variable.
+
+notes.rewriteMode::
+       When copying notes during a rewrite, what to do if the target
+       commit already has a note.  Must be one of `overwrite`,
+       `concatenate`, and `ignore`.  Defaults to `concatenate`.
++
+This setting can be overridden with the `GIT_NOTES_REWRITE_MODE`
+environment variable.
+
+notes.rewriteRef::
+       When copying notes during a rewrite, specifies the (fully
+       qualified) ref whose notes should be copied.  May be a glob,
+       in which case notes in all matching refs will be copied.  You
+       may also specify this configuration several times.
++
+Does not have a default value; you must configure this variable to
+enable note rewriting.
++
+Can be overridden with the 'GIT_NOTES_REWRITE_REF' environment variable.
+
+
+ENVIRONMENT
+-----------
+
+'GIT_NOTES_REF'::
+       Which ref to manipulate notes from, instead of `refs/notes/commits`.
+       This overrides the `core.notesRef` setting.
+
+'GIT_NOTES_DISPLAY_REF'::
+       Colon-delimited list of refs or globs indicating which refs,
+       in addition to the default from `core.notesRef` or
+       'GIT_NOTES_REF', to read notes from when showing commit
+       messages.
+       This overrides the `notes.displayRef` setting.
++
+A warning will be issued for refs that do not exist, but a glob that
+does not match any refs is silently ignored.
+
+'GIT_NOTES_REWRITE_MODE'::
+       When copying notes during a rewrite, what to do if the target
+       commit already has a note.
+       Must be one of `overwrite`, `concatenate`, and `ignore`.
+       This overrides the `core.rewriteMode` setting.
+
+'GIT_NOTES_REWRITE_REF'::
+       When rewriting commits, which notes to copy from the original
+       to the rewritten commit.  Must be a colon-delimited list of
+       refs or globs.
++
+If not set in the environment, the list of notes to copy depends
+on the `notes.rewrite.<command>` and `notes.rewriteRef` settings.
 
 
 Author
index 0d07b1b2077c62f1199c5ee96790e5a7121b4f00..50ba2e469f48f1bc16c3f6e3b6f6451a9e29637a 100644 (file)
@@ -206,6 +206,10 @@ OPTIONS
        --onto option is not specified, the starting point is
        <upstream>.  May be any valid commit, and not just an
        existing branch name.
++
+As a special case, you may use "A...B" as a shortcut for the
+merge base of A and B if there is exactly one merge base. You can
+leave out at most one of A and B, in which case it defaults to HEAD.
 
 <upstream>::
        Upstream branch to compare against.  May be any valid commit,
@@ -295,6 +299,7 @@ link:howto/revert-a-faulty-merge.txt[revert-a-faulty-merge How-To] for details).
 --ignore-date::
        These flags are passed to 'git am' to easily change the dates
        of the rebased commits (see linkgit:git-am[1]).
+       Incompatible with the --interactive option.
 
 -i::
 --interactive::
index ced35b2f532dde3580f162a0c23b642002a0e508..12622fc49a0825fa8423c46ddddc06ff89f292d4 100644 (file)
@@ -119,6 +119,13 @@ Sending
        value reverts to plain SMTP.  Default is the value of
        'sendemail.smtpencryption'.
 
+--smtp-domain=<FQDN>::
+       Specifies the Fully Qualified Domain Name (FQDN) used in the
+       HELO/EHLO command to the SMTP server.  Some servers require the
+       FQDN to match your IP address.  If not set, git send-email attempts
+       to determine your FQDN automatically.  Default is the value of
+       'sendemail.smtpdomain'.
+
 --smtp-pass[=<password>]::
        Password for SMTP-AUTH. The argument is optional: If no
        argument is specified, then the empty string is used as
@@ -300,6 +307,21 @@ sendemail.confirm::
        in the previous section for the meaning of these values.
 
 
+Use gmail as the smtp server
+----------------------------
+
+Add the following section to the config file:
+
+       [sendemail]
+               smtpencryption = tls
+               smtpserver = smtp.gmail.com
+               smtpuser = yourname@gmail.com
+               smtpserverport = 587
+
+Note: the following perl modules are required
+      Net::SMTP::SSL, MIME::Base64 and Authen::SASL
+
+
 Author
 ------
 Written by Ryan Anderson <ryan@michonline.com>
index dfd4d0c2233df09b64a10d1ad31a36afaa01ec7c..bc1ac77495347967c941298e2da38f76d5d124c6 100644 (file)
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 git log --pretty=short | 'git shortlog' [-h] [-n] [-s] [-e] [-w]
-'git shortlog' [-n|--numbered] [-s|--summary] [-e|--email] [-w[<width>[,<indent1>[,<indent2>]]]] [<committish>...]
+'git shortlog' [-n|--numbered] [-s|--summary] [-e|--email] [-w[<width>[,<indent1>[,<indent2>]]]] <commit>...
 
 DESCRIPTION
 -----------
@@ -19,6 +19,11 @@ the first line of the commit message will be shown.
 
 Additionally, "[PATCH]" will be stripped from the commit description.
 
+If no revisions are passed on the command line and either standard input
+is not a terminal or there is no current branch, 'git shortlog' will
+output a summary of the log read from standard input, without
+reference to the current repository.
+
 OPTIONS
 -------
 
@@ -39,6 +44,14 @@ OPTIONS
 --email::
        Show the email address of each author.
 
+--format[='<format>']::
+       Instead of the commit subject, use some other information to
+       describe each commit.  '<format>' can be any string accepted
+       by the `--format` option of 'git log', such as '{asterisk} [%h] %s'.
+       (See the "PRETTY FORMATS" section of linkgit:git-log[1].)
+
+       Each pretty-printed commit will be rewrapped before it is shown.
+
 -w[<width>[,<indent1>[,<indent2>]]]::
        Linewrap the output by wrapping each line at `width`.  The first
        line of each entry is indented by `indent1` spaces, and the second
index 68dc1879fe912b1a01b3caa6b1c0168f6a7b8072..765d4b312ed6f062180e83fa0d931e6bd2eef24f 100644 (file)
@@ -93,8 +93,6 @@ OPTIONS
 This option can be also used as a coarse file-level mechanism
 to ignore uncommitted changes in tracked files (akin to what
 `.gitignore` does for untracked files).
-You should remember that an explicit 'git add' operation will
-still cause the file to be refreshed from the working tree.
 Git will fail (gracefully) in case it needs to modify this file
 in the index e.g. when merging in a commit;
 thus, in case the assumed-untracked file is changed upstream,
index 9de8caf5d11445f6db7193f7b7a4151c97befb29..5d91a7e5b3a40cbf41f03a81799c162775c36607 100644 (file)
@@ -227,8 +227,8 @@ changes that touch a specified string, and is controlled by the
 commands.
 
 When diffcore-pickaxe is in use, it checks if there are
-filepairs whose "original" side has the specified string and
-whose "result" side does not.  Such a filepair represents "the
+filepairs whose "result" side has the specified string and
+whose "origin" side does not.  Such a filepair represents "the
 string appeared in this changeset".  It also checks for the
 opposite case that loses the specified string.
 
index 1686a54d22a746036b997d6eb8d5b85ca1d79c5d..c85a52c0cc27a187abbdea17cd25cec51b808064 100644 (file)
@@ -76,9 +76,9 @@ displayed in full, regardless of whether --abbrev or
 true parent commits, without taking grafts nor history
 simplification into account.
 
-* 'format:'
+* 'format:<string>'
 +
-The 'format:' format allows you to specify which information
+The 'format:<string>' format allows you to specify which information
 you want to show. It works a little bit like printf format,
 with the notable exception that you get a newline with '%n'
 instead of '\n'.
index af6d2b995a050007ae088dec8e2c3474e9f06ad5..d78e121c76ef12b2d72fbdf1558fa967dfdba85b 100644 (file)
@@ -3,8 +3,9 @@
 
        Pretty-print the contents of the commit logs in a given format,
        where '<format>' can be one of 'oneline', 'short', 'medium',
-       'full', 'fuller', 'email', 'raw' and 'format:<string>'.
-       When omitted, the format defaults to 'medium'.
+       'full', 'fuller', 'email', 'raw' and 'format:<string>'.  See
+       the "PRETTY FORMATS" section for some additional details for each
+       format.  When omitted, the format defaults to 'medium'.
 +
 Note: you can specify the default pretty format in the repository
 configuration (see linkgit:git-config[1]).
index 0ad39484eceab30360e1f46c6057a873ca2c26f1..82fd72652b6d35837b8786005024263ac61630dd 100755 (executable)
@@ -12,7 +12,7 @@ if test -f version
 then
        VN=$(cat version) || VN="$DEF_VER"
 elif test -d .git -o -f .git &&
-       VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
+       VN=$(git describe --match "v[0-9]*" --abbrev=4 HEAD 2>/dev/null) &&
        case "$VN" in
        *$LF*) (exit 1) ;;
        v[0-9]*)
index 910f4713ef1491278500573bab2d00ee1925abb8..b18768e0aedfbf246173293f74049456070deec3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -31,6 +31,9 @@ all::
 # Define EXPATDIR=/foo/bar if your expat header and library files are in
 # /foo/bar/include and /foo/bar/lib directories.
 #
+# Define HAVE_PATHS_H if you have paths.h and want to use the default PATH
+# it specifies.
+#
 # Define NO_D_INO_IN_DIRENT if you don't have d_ino in your struct dirent.
 #
 # Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
@@ -735,10 +738,12 @@ EXTLIBS =
 ifeq ($(uname_S),Linux)
        NO_STRLCPY = YesPlease
        NO_MKSTEMPS = YesPlease
+       HAVE_PATHS_H = YesPlease
 endif
 ifeq ($(uname_S),GNU/kFreeBSD)
        NO_STRLCPY = YesPlease
        NO_MKSTEMPS = YesPlease
+       HAVE_PATHS_H = YesPlease
 endif
 ifeq ($(uname_S),UnixWare)
        CC = cc
@@ -867,6 +872,7 @@ ifeq ($(uname_S),FreeBSD)
                NO_STRTOUMAX = YesPlease
        endif
        PYTHON_PATH = /usr/local/bin/python
+       HAVE_PATHS_H = YesPlease
 endif
 ifeq ($(uname_S),OpenBSD)
        NO_STRCASESTR = YesPlease
@@ -875,6 +881,7 @@ ifeq ($(uname_S),OpenBSD)
        NEEDS_LIBICONV = YesPlease
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
+       HAVE_PATHS_H = YesPlease
 endif
 ifeq ($(uname_S),NetBSD)
        ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2)
@@ -884,8 +891,10 @@ ifeq ($(uname_S),NetBSD)
        BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
        USE_ST_TIMESPEC = YesPlease
        NO_MKSTEMPS = YesPlease
+       HAVE_PATHS_H = YesPlease
 endif
 ifeq ($(uname_S),AIX)
+       DEFAULT_PAGER = more
        NO_STRCASESTR=YesPlease
        NO_MEMMEM = YesPlease
        NO_MKDTEMP = YesPlease
@@ -904,6 +913,7 @@ ifeq ($(uname_S),GNU)
        # GNU/Hurd
        NO_STRLCPY=YesPlease
        NO_MKSTEMPS = YesPlease
+       HAVE_PATHS_H = YesPlease
 endif
 ifeq ($(uname_S),IRIX)
        NO_SETENV = YesPlease
@@ -1353,6 +1363,10 @@ else
        LIB_OBJS += thread-utils.o
 endif
 
+ifdef HAVE_PATHS_H
+       BASIC_CFLAGS += -DHAVE_PATHS_H
+endif
+
 ifdef DIR_HAS_BSD_GROUP_SEMANTICS
        COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS
 endif
@@ -1996,12 +2010,13 @@ endif
                ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
                cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
          done; } && \
-       { for p in $(REMOTE_CURL_ALIASES); do \
+       { test x"$(REMOTE_CURL_ALIASES)" = x || \
+               { for p in $(REMOTE_CURL_ALIASES); do \
                $(RM) "$$execdir/$$p" && \
                ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
                ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
                cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; \
-         done; } && \
+         done; } ; } && \
        ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
 
 install-doc:
@@ -2098,7 +2113,7 @@ clean:
        $(RM) $(htmldocs).tar.gz $(manpages).tar.gz
        $(MAKE) -C Documentation/ clean
 ifndef NO_PERL
-       $(RM) gitweb/gitweb.cgi gitweb/gitweb.min.*
+       $(MAKE) -C gitweb clean
        $(MAKE) -C perl clean
 endif
 ifndef NO_PYTHON
index 00e77229ddadcb8a13b10b693a96bd76a4cb9f33..136c1b6afa6bc9cee85b018cd5df66c639c3fc91 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.7.1.txt
\ No newline at end of file
+Documentation/RelNotes-1.7.1.1.txt
\ No newline at end of file
diff --git a/attr.c b/attr.c
index f5346ed32a1b5caf908021805214fd97e033eb27..7467baf2d6c81f94a7d043dcde13d463b3b46272 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -594,20 +594,25 @@ static int path_matches(const char *pathname, int pathlen,
        return fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;
 }
 
+static int macroexpand_one(int attr_nr, int rem);
+
 static int fill_one(const char *what, struct match_attr *a, int rem)
 {
        struct git_attr_check *check = check_all_attr;
        int i;
 
-       for (i = 0; 0 < rem && i < a->num_attr; i++) {
+       for (i = a->num_attr - 1; 0 < rem && 0 <= i; i--) {
                struct git_attr *attr = a->state[i].attr;
                const char **n = &(check[attr->attr_nr].value);
                const char *v = a->state[i].setto;
 
                if (*n == ATTR__UNKNOWN) {
-                       debug_set(what, a->u.pattern, attr, v);
+                       debug_set(what,
+                                 a->is_macro ? a->u.attr->name : a->u.pattern,
+                                 attr, v);
                        *n = v;
                        rem--;
+                       rem = macroexpand_one(attr->attr_nr, rem);
                }
        }
        return rem;
@@ -629,19 +634,27 @@ static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
        return rem;
 }
 
-static int macroexpand(struct attr_stack *stk, int rem)
+static int macroexpand_one(int attr_nr, int rem)
 {
+       struct attr_stack *stk;
+       struct match_attr *a = NULL;
        int i;
-       struct git_attr_check *check = check_all_attr;
 
-       for (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) {
-               struct match_attr *a = stk->attrs[i];
-               if (!a->is_macro)
-                       continue;
-               if (check[a->u.attr->attr_nr].value != ATTR__TRUE)
-                       continue;
+       if (check_all_attr[attr_nr].value != ATTR__TRUE)
+               return rem;
+
+       for (stk = attr_stack; !a && stk; stk = stk->prev)
+               for (i = stk->num_matches - 1; !a && 0 <= i; i--) {
+                       struct match_attr *ma = stk->attrs[i];
+                       if (!ma->is_macro)
+                               continue;
+                       if (ma->u.attr->attr_nr == attr_nr)
+                               a = ma;
+               }
+
+       if (a)
                rem = fill_one("expand", a, rem);
-       }
+
        return rem;
 }
 
@@ -666,9 +679,6 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
        for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
                rem = fill(path, pathlen, stk, rem);
 
-       for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
-               rem = macroexpand(stk, rem);
-
        for (i = 0; i < num; i++) {
                const char *value = check_all_attr[check[i].attr->attr_nr].value;
                if (value == ATTR__UNKNOWN)
index 771c972c5506db4848e2c214fb617525bafdf335..f669157b42e658b3769ec775f7aa4dafea634db8 100644 (file)
@@ -1864,13 +1864,13 @@ static int match_fragment(struct image *img,
                if (match_end && (preimage->nr + try_lno != img->nr))
                        return 0;
        } else if (ws_error_action == correct_ws_error &&
-                  (ws_rule & WS_BLANK_AT_EOF) && match_end) {
+                  (ws_rule & WS_BLANK_AT_EOF)) {
                /*
-                * This hunk that matches at the end extends beyond
-                * the end of img, and we are removing blank lines
-                * at the end of the file.  This many lines from the
-                * beginning of the preimage must match with img, and
-                * the remainder of the preimage must be blank.
+                * This hunk extends beyond the end of img, and we are
+                * removing blank lines at the end of the file.  This
+                * many lines from the beginning of the preimage must
+                * match with img, and the remainder of the preimage
+                * must be blank.
                 */
                preimage_limit = img->nr - try_lno;
        } else {
index fc1586350f94ae48e7e48a51818517b465e7a40d..8506286dd271d4e92369d81ec2cce9240a559d64 100644 (file)
@@ -39,7 +39,7 @@ static int show_root;
 static int reverse;
 static int blank_boundary;
 static int incremental;
-static int xdl_opts = XDF_NEED_MINIMAL;
+static int xdl_opts;
 
 static enum date_mode blame_date_mode = DATE_ISO8601;
 static size_t blame_date_width;
@@ -1589,7 +1589,7 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent)
        strcpy(hex, sha1_to_hex(suspect->commit->object.sha1));
        printf("%s%c%d %d %d\n",
               hex,
-              ent->guilty ? ' ' : '*', // purely for debugging
+              ent->guilty ? ' ' : '*', /* purely for debugging */
               ent->s_lno + 1,
               ent->lno + 1,
               ent->num_lines);
index 05f8fb4771b1ef07030338a6fd38dc7cb3bc1d1d..0bedde41f077f7c6e6106b144854c208ed4f6076 100644 (file)
@@ -302,6 +302,8 @@ static const struct ref *clone_local(const char *src_repo,
        transport = transport_get(remote, src_repo);
        ret = transport_get_remote_refs(transport);
        transport_disconnect(transport);
+       if (0 <= option_verbosity)
+               printf("done.\n");
        return ret;
 }
 
@@ -461,7 +463,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                die("could not create leading directories of '%s'", git_dir);
        set_git_dir(make_absolute_path(git_dir));
 
-       init_db(option_template, (option_verbosity < 0) ? INIT_DB_QUIET : 0);
+       if (0 <= option_verbosity)
+               printf("Cloning into %s...\n", get_git_dir());
+       init_db(option_template, INIT_DB_QUIET);
 
        /*
         * At this point, the config exists, so we do not need the
index c5ab683d5b66d5ad85f53d13d6df71e29cd9234d..3c14ade9dddd06001d9c6d5fab23a9a6b7ca2580 100644 (file)
@@ -1017,6 +1017,7 @@ static int git_status_config(const char *k, const char *v, void *cb)
 int cmd_status(int argc, const char **argv, const char *prefix)
 {
        struct wt_status s;
+       int fd;
        unsigned char sha1[20];
        static struct option builtin_status_options[] = {
                OPT__VERBOSE(&verbose),
@@ -1050,6 +1051,14 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 
        read_cache_preload(s.pathspec);
        refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL);
+
+       fd = hold_locked_index(&index_lock, 0);
+       if (0 <= fd) {
+               if (!write_cache(fd, active_cache, active_nr))
+                       commit_locked_index(&index_lock);
+               rollback_lock_file(&index_lock);
+       }
+
        s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
        s.in_merge = in_merge;
        wt_status_collect(&s);
index 71be2a9364748668996696f6c74057dba43315b5..43caff2ffe185df6ab224b93b4fd9ce3d82de2d0 100644 (file)
@@ -35,7 +35,8 @@ static const char *diff_index_args[] = {
 
 struct commit_name {
        struct tag *tag;
-       int prio; /* annotated tag = 2, tag = 1, head = 0 */
+       unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
+       unsigned name_checked:1;
        unsigned char sha1[20];
        char path[FLEX_ARRAY]; /* more */
 };
@@ -43,18 +44,53 @@ static const char *prio_names[] = {
        "head", "lightweight", "annotated",
 };
 
+static int replace_name(struct commit_name *e,
+                              int prio,
+                              const unsigned char *sha1,
+                              struct tag **tag)
+{
+       if (!e || e->prio < prio)
+               return 1;
+
+       if (e->prio == 2 && prio == 2) {
+               /* Multiple annotated tags point to the same commit.
+                * Select one to keep based upon their tagger date.
+                */
+               struct tag *t;
+
+               if (!e->tag) {
+                       t = lookup_tag(e->sha1);
+                       if (!t || parse_tag(t))
+                               return 1;
+                       e->tag = t;
+               }
+
+               t = lookup_tag(sha1);
+               if (!t || parse_tag(t))
+                       return 0;
+               *tag = t;
+
+               if (e->tag->date < t->date)
+                       return 1;
+       }
+
+       return 0;
+}
+
 static void add_to_known_names(const char *path,
                               struct commit *commit,
                               int prio,
                               const unsigned char *sha1)
 {
        struct commit_name *e = commit->util;
-       if (!e || e->prio < prio) {
+       struct tag *tag = NULL;
+       if (replace_name(e, prio, sha1, &tag)) {
                size_t len = strlen(path)+1;
                free(e);
                e = xmalloc(sizeof(struct commit_name) + len);
-               e->tag = NULL;
+               e->tag = tag;
                e->prio = prio;
+               e->name_checked = 0;
                hashcpy(e->sha1, sha1);
                memcpy(e->path, path, len);
                commit->util = e;
@@ -165,10 +201,15 @@ static void display_name(struct commit_name *n)
 {
        if (n->prio == 2 && !n->tag) {
                n->tag = lookup_tag(n->sha1);
-               if (!n->tag || parse_tag(n->tag) || !n->tag->tag)
+               if (!n->tag || parse_tag(n->tag))
                        die("annotated tag %s not available", n->path);
+       }
+       if (n->tag && !n->name_checked) {
+               if (!n->tag->tag)
+                       die("annotated tag %s has no embedded name", n->path);
                if (strcmp(n->tag->tag, all ? n->path + 5 : n->path))
                        warning("tag '%s' is really '%s' here", n->tag->tag, n->path);
+               n->name_checked = 1;
        }
 
        if (n->tag)
index 62be1bbfd6659f9dfac73a17acd1e2d5322dac66..7f5011f75ef9eb549b33861d9546f3d18a94c256 100644 (file)
@@ -549,10 +549,10 @@ static void grab_values(struct atom_value *val, int deref, struct object *obj, v
                grab_person("committer", val, deref, obj, buf, sz);
                break;
        case OBJ_TREE:
-               // grab_tree_values(val, deref, obj, buf, sz);
+               /* grab_tree_values(val, deref, obj, buf, sz); */
                break;
        case OBJ_BLOB:
-               // grab_blob_values(val, deref, obj, buf, sz);
+               /* grab_blob_values(val, deref, obj, buf, sz); */
                break;
        default:
                die("Eh?  Object of type %d?", obj->type);
index 8e928e217041a159f4a962f0883d740aa84536d7..b194ea3cea531f3a6c81d6d27b5b3028641ba9ce 100644 (file)
@@ -17,8 +17,8 @@
 #include "dir.h"
 
 #ifndef NO_PTHREADS
-#include "thread-utils.h"
 #include <pthread.h>
+#include "thread-utils.h"
 #endif
 
 static char const * const grep_usage[] = {
index b4cf8c53e0ebbee65a0e4bc0ac1afd1173d1b8e8..a89ae831dd6251d7332e06470273d30fd9cb31eb 100644 (file)
@@ -11,7 +11,7 @@
 #include "exec_cmd.h"
 
 static const char index_pack_usage[] =
-"git index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
+"git index-pack [-v] [-o <index-file>] [{ --keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
 
 struct object_entry
 {
@@ -266,26 +266,23 @@ static void unlink_base_data(struct base_data *c)
 
 static void *unpack_entry_data(unsigned long offset, unsigned long size)
 {
+       int status;
        z_stream stream;
        void *buf = xmalloc(size);
 
        memset(&stream, 0, sizeof(stream));
+       git_inflate_init(&stream);
        stream.next_out = buf;
        stream.avail_out = size;
-       stream.next_in = fill(1);
-       stream.avail_in = input_len;
-       git_inflate_init(&stream);
 
-       for (;;) {
-               int ret = git_inflate(&stream, 0);
-               use(input_len - stream.avail_in);
-               if (stream.total_out == size && ret == Z_STREAM_END)
-                       break;
-               if (ret != Z_OK)
-                       bad_object(offset, "inflate returned %d", ret);
+       do {
                stream.next_in = fill(1);
                stream.avail_in = input_len;
-       }
+               status = git_inflate(&stream, 0);
+               use(input_len - stream.avail_in);
+       } while (status == Z_OK);
+       if (stream.total_out != size || status != Z_STREAM_END)
+               bad_object(offset, "inflate returned %d", status);
        git_inflate_end(&stream);
        return buf;
 }
@@ -359,34 +356,38 @@ static void *get_data_from_pack(struct object_entry *obj)
 {
        off_t from = obj[0].idx.offset + obj[0].hdr_size;
        unsigned long len = obj[1].idx.offset - from;
-       unsigned long rdy = 0;
-       unsigned char *src, *data;
+       unsigned char *data, *inbuf;
        z_stream stream;
-       int st;
+       int status;
 
-       src = xmalloc(len);
-       data = src;
-       do {
-               ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
-               if (n < 0)
-                       die_errno("cannot pread pack file");
-               if (!n)
-                       die("premature end of pack file, %lu bytes missing",
-                           len - rdy);
-               rdy += n;
-       } while (rdy < len);
        data = xmalloc(obj->size);
+       inbuf = xmalloc((len < 64*1024) ? len : 64*1024);
+
        memset(&stream, 0, sizeof(stream));
+       git_inflate_init(&stream);
        stream.next_out = data;
        stream.avail_out = obj->size;
-       stream.next_in = src;
-       stream.avail_in = len;
-       git_inflate_init(&stream);
-       while ((st = git_inflate(&stream, Z_FINISH)) == Z_OK);
-       git_inflate_end(&stream);
-       if (st != Z_STREAM_END || stream.total_out != obj->size)
+
+       do {
+               ssize_t n = (len < 64*1024) ? len : 64*1024;
+               n = pread(pack_fd, inbuf, n, from);
+               if (n < 0)
+                       die_errno("cannot pread pack file");
+               if (!n)
+                       die("premature end of pack file, %lu bytes missing", len);
+               from += n;
+               len -= n;
+               stream.next_in = inbuf;
+               stream.avail_in = n;
+               status = git_inflate(&stream, 0);
+       } while (len && status == Z_OK && !stream.avail_in);
+
+       /* This has been inflated OK when first encountered, so... */
+       if (status != Z_STREAM_END || stream.total_out != obj->size)
                die("serious inflate inconsistency");
-       free(src);
+
+       git_inflate_end(&stream);
+       free(inbuf);
        return data;
 }
 
@@ -668,25 +669,25 @@ static void parse_pack_objects(unsigned char *sha1)
 static int write_compressed(struct sha1file *f, void *in, unsigned int size)
 {
        z_stream stream;
-       unsigned long maxsize;
-       void *out;
+       int status;
+       unsigned char outbuf[4096];
 
        memset(&stream, 0, sizeof(stream));
        deflateInit(&stream, zlib_compression_level);
-       maxsize = deflateBound(&stream, size);
-       out = xmalloc(maxsize);
-
-       /* Compress it */
        stream.next_in = in;
        stream.avail_in = size;
-       stream.next_out = out;
-       stream.avail_out = maxsize;
-       while (deflate(&stream, Z_FINISH) == Z_OK);
-       deflateEnd(&stream);
 
+       do {
+               stream.next_out = outbuf;
+               stream.avail_out = sizeof(outbuf);
+               status = deflate(&stream, Z_FINISH);
+               sha1write(f, outbuf, sizeof(outbuf) - stream.avail_out);
+       } while (status == Z_OK);
+
+       if (status != Z_STREAM_END)
+               die("unable to deflate appended object (%d)", status);
        size = stream.total_out;
-       sha1write(f, out, size);
-       free(out);
+       deflateEnd(&stream);
        return size;
 }
 
index edc40ff5748fbd68b64f382c251c6b030cf88803..0271285fad6ad532a6133838f7188498476fd77b 100644 (file)
@@ -463,7 +463,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
                static char git_dir[PATH_MAX+1];
 
                setenv(GIT_DIR_ENVIRONMENT,
-                       getcwd(git_dir, sizeof(git_dir)), 0);
+                       getcwd(git_dir, sizeof(git_dir)), argc > 0);
        }
 
        if (init_shared_repository != -1)
index 610849a6533c6fd2d3d2e8d3f8d233757174aabd..b8e9e5ba01658bbdd6e9d712b00da902b6f33fbe 100644 (file)
@@ -25,7 +25,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
        const char *names[3] = { NULL, NULL, NULL };
        mmfile_t mmfs[3];
        mmbuffer_t result = {NULL, 0};
-       xmparam_t xmp = {{XDF_NEED_MINIMAL}};
+       xmparam_t xmp = {{0}};
        int ret = 0, i = 0, to_stdout = 0;
        int quiet = 0;
        int nongit;
index a4a4f2ce4c3f147062070c2acc08eaf9f4d40be8..fc00d794d641c146023a78d7d8e4143f0fdac302 100644 (file)
@@ -106,7 +106,7 @@ static void show_diff(struct merge_list *entry)
        xdemitconf_t xecfg;
        xdemitcb_t ecb;
 
-       xpp.flags = XDF_NEED_MINIMAL;
+       xpp.flags = 0;
        memset(&xecfg, 0, sizeof(xecfg));
        xecfg.ctxlen = 3;
        ecb.outf = show_outf;
index 52b72fca687d42dc09d1d79a8e76584a55c0c546..26617546c8cadac493f06473d02f27f320713b28 100644 (file)
@@ -416,7 +416,7 @@ int notes_copy_from_stdin(int force, const char *rewrite_cmd)
 {
        struct strbuf buf = STRBUF_INIT;
        struct notes_rewrite_cfg *c = NULL;
-       struct notes_tree *t;
+       struct notes_tree *t = NULL;
        int ret = 0;
 
        if (rewrite_cmd) {
index 97802585ea3ac69ac6ed2e7995605bdcae84558e..214d7ef2b12d41e8d70539fe4a4b16fde71a780a 100644 (file)
@@ -18,8 +18,8 @@
 #include "refs.h"
 
 #ifndef NO_PTHREADS
-#include "thread-utils.h"
 #include <pthread.h>
+#include "thread-utils.h"
 #endif
 
 static const char pack_usage[] =
@@ -1522,6 +1522,13 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
 
 #ifndef NO_PTHREADS
 
+static void try_to_free_from_threads(size_t size)
+{
+       read_lock();
+       release_pack_memory(size, -1);
+       read_unlock();
+}
+
 /*
  * The main thread waits on the condition that (at least) one of the workers
  * has stopped working (which is indicated in the .working member of
@@ -1552,14 +1559,16 @@ static pthread_cond_t progress_cond;
  */
 static void init_threaded_search(void)
 {
-       pthread_mutex_init(&read_mutex, NULL);
+       init_recursive_mutex(&read_mutex);
        pthread_mutex_init(&cache_mutex, NULL);
        pthread_mutex_init(&progress_mutex, NULL);
        pthread_cond_init(&progress_cond, NULL);
+       set_try_to_free_routine(try_to_free_from_threads);
 }
 
 static void cleanup_threaded_search(void)
 {
+       set_try_to_free_routine(NULL);
        pthread_cond_destroy(&progress_cond);
        pthread_mutex_destroy(&read_mutex);
        pthread_mutex_destroy(&cache_mutex);
index 34f9acee910406c7ba0bf9eed76267a0cf8f46c2..0048f9ef7fee24e5e058ef226f3b0fc93703fcf1 100644 (file)
@@ -89,7 +89,7 @@ static int diff_two(const char *file1, const char *label1,
        printf("--- a/%s\n+++ b/%s\n", label1, label2);
        fflush(stdout);
        memset(&xpp, 0, sizeof(xpp));
-       xpp.flags = XDF_NEED_MINIMAL;
+       xpp.flags = 0;
        memset(&xecfg, 0, sizeof(xecfg));
        xecfg.ctxlen = 3;
        ecb.outf = outf;
index 778a56eb512edde3aac6c2a4d668cc73ab3d8460..7d68ef714eee5011d82952ca1829016c90827f61 100644 (file)
@@ -109,8 +109,13 @@ static int get_message(const char *raw_message, struct commit_message *out)
                encoding = "UTF-8";
        if (!git_commit_encoding)
                git_commit_encoding = "UTF-8";
-       if ((out->reencoded_message = reencode_string(raw_message,
-                                       git_commit_encoding, encoding)))
+
+       out->reencoded_message = NULL;
+       out->message = raw_message;
+       if (strcmp(encoding, git_commit_encoding))
+               out->reencoded_message = reencode_string(raw_message,
+                                       git_commit_encoding, encoding);
+       if (out->reencoded_message)
                out->message = out->reencoded_message;
 
        abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
index 06320f5285988365b8340e110427866e68536b47..5089502800d5f477f47b6cd6499d278097f11e67 100644 (file)
@@ -162,7 +162,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
                    sha1_to_hex(commit->object.sha1));
        if (log->user_format) {
                struct pretty_print_context ctx = {0};
-               ctx.abbrev = DEFAULT_ABBREV;
+               ctx.abbrev = log->abbrev;
                ctx.subject = "";
                ctx.after_subject = "";
                ctx.date_mode = DATE_NORMAL;
@@ -290,6 +290,7 @@ parse_done:
        }
 
        log.user_format = rev.commit_format == CMIT_FMT_USERFORMAT;
+       log.abbrev = rev.abbrev;
 
        /* assume HEAD if from a tty */
        if (!nongit && !rev.pending.nr && isatty(0))
index e20fcf3e935dfafb4e30f24990aa974c8b2f5927..e8719aa9e9f47c30b697332925fcdd206fdfd55c 100644 (file)
@@ -313,7 +313,8 @@ static void show_one_commit(struct commit *commit, int no_name)
                }
                else
                        printf("[%s] ",
-                              find_unique_abbrev(commit->object.sha1, 7));
+                              find_unique_abbrev(commit->object.sha1,
+                                                 DEFAULT_ABBREV));
        }
        puts(pretty_str);
        strbuf_release(&pretty);
diff --git a/cache.h b/cache.h
index 5eb0573bcc81050cc06a304f346fe5f41ebe242e..0d101e4913f380a0eda0b3bf9e1d8b76e34c6fd8 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -905,7 +905,7 @@ struct extra_have_objects {
 extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags, struct extra_have_objects *);
 extern int server_supports(const char *feature);
 
-extern struct packed_git *parse_pack_index(unsigned char *sha1);
+extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
 
 extern void prepare_packed_git(void);
 extern void reprepare_packed_git(void);
@@ -916,6 +916,7 @@ extern struct packed_git *find_sha1_pack(const unsigned char *sha1,
 
 extern void pack_report(void);
 extern int open_pack_index(struct packed_git *);
+extern void close_pack_index(struct packed_git *);
 extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
 extern void close_pack_windows(struct packed_git *);
 extern void unuse_pack(struct pack_window **);
index 3480dae82416bda357dee2f0d545ac6dadc6a26f..655fa89d8a7ffe3c3823080f5af3e5e385e95440 100644 (file)
@@ -211,7 +211,6 @@ static void combine_diff(const unsigned char *parent, unsigned int mode,
        xpparam_t xpp;
        xdemitconf_t xecfg;
        mmfile_t parent_file;
-       xdemitcb_t ecb;
        struct combine_diff_state state;
        unsigned long sz;
 
@@ -221,7 +220,7 @@ static void combine_diff(const unsigned char *parent, unsigned int mode,
        parent_file.ptr = grab_blob(parent, mode, &sz);
        parent_file.size = sz;
        memset(&xpp, 0, sizeof(xpp));
-       xpp.flags = XDF_NEED_MINIMAL;
+       xpp.flags = 0;
        memset(&xecfg, 0, sizeof(xecfg));
        memset(&state, 0, sizeof(state));
        state.nmask = nmask;
@@ -231,7 +230,7 @@ static void combine_diff(const unsigned char *parent, unsigned int mode,
        state.n = n;
 
        xdi_diff_outf(&parent_file, result_file, consume_line, &state,
-                     &xpp, &xecfg, &ecb);
+                     &xpp, &xecfg);
        free(parent_file.ptr);
 
        /* Assign line numbers for this parent.
index f90a114b021d32c2ee1976bf51a82e87a81ea1cb..9a8e3365827d303c6513475726113a3952fe0040 100644 (file)
@@ -140,6 +140,23 @@ int mingw_open (const char *filename, int oflags, ...)
        return fd;
 }
 
+#undef write
+ssize_t mingw_write(int fd, const void *buf, size_t count)
+{
+       /*
+        * While write() calls to a file on a local disk are translated
+        * into WriteFile() calls with a maximum size of 64KB on Windows
+        * XP and 256KB on Vista, no such cap is placed on writes to
+        * files over the network on Windows XP.  Unfortunately, there
+        * seems to be a limit of 32MB-28KB on X64 and 64MB-32KB on x86;
+        * bigger writes fail on Windows XP.
+        * So we cap to a nice 31MB here to avoid write failures over
+        * the net without changing the number of WriteFile() calls in
+        * the local case.
+        */
+       return write(fd, buf, min(count, 31 * 1024 * 1024));
+}
+
 #undef fopen
 FILE *mingw_fopen (const char *filename, const char *otype)
 {
index 7c2ab64cb4eb7532c2495383ab0e7eefb329bcf9..0e3e74304138ab2f279c74599ee934ade72ae37d 100644 (file)
@@ -170,6 +170,9 @@ int link(const char *oldpath, const char *newpath);
 int mingw_open (const char *filename, int oflags, ...);
 #define open mingw_open
 
+ssize_t mingw_write(int fd, const void *buf, size_t count);
+#define write mingw_write
+
 FILE *mingw_fopen (const char *filename, const char *otype);
 #define fopen mingw_fopen
 
index c72f100f40ce2ab9ae7abead730ed00c2a461fbf..a45f8d66df8d1e452d9392945bf12a74c32bbca9 100644 (file)
  */
 #define pthread_mutex_t CRITICAL_SECTION
 
-#define pthread_mutex_init(a,b) InitializeCriticalSection((a))
+#define pthread_mutex_init(a,b) (InitializeCriticalSection((a)), 0)
 #define pthread_mutex_destroy(a) DeleteCriticalSection((a))
 #define pthread_mutex_lock EnterCriticalSection
 #define pthread_mutex_unlock LeaveCriticalSection
 
+typedef int pthread_mutexattr_t;
+#define pthread_mutexattr_init(a) (*(a) = 0)
+#define pthread_mutexattr_destroy(a) do {} while (0)
+#define pthread_mutexattr_settype(a, t) 0
+#define PTHREAD_MUTEX_RECURSIVE 0
+
 /*
  * Implement simple condition variable for Windows threads, based on ACE
  * implementation.
index 1c5a14922f255af2c3b0e75e06925b748d3d7684..b58aa69fa0609dad7f591024f9da31dfa58496fb 100644 (file)
@@ -4,19 +4,19 @@ void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t of
 {
        HANDLE hmap;
        void *temp;
-       size_t len;
+       off_t len;
        struct stat st;
        uint64_t o = offset;
        uint32_t l = o & 0xFFFFFFFF;
        uint32_t h = (o >> 32) & 0xFFFFFFFF;
 
        if (!fstat(fd, &st))
-               len = xsize_t(st.st_size);
+               len = st.st_size;
        else
                die("mmap: could not determine filesize");
 
        if ((length + offset) > len)
-               length = len - offset;
+               length = xsize_t(len - offset);
 
        if (!(flags & MAP_PRIVATE))
                die("Invalid usage of mmap when built with USE_WIN32_MMAP");
index 6008ac9f1b8d056e522d5fe83c8d56bff314ca92..0d4b64d076b8041a3701715a83ca46a4675ac9d6 100644 (file)
@@ -31,6 +31,7 @@ NO_OPENSSL=@NO_OPENSSL@
 NO_CURL=@NO_CURL@
 NO_EXPAT=@NO_EXPAT@
 NO_LIBGEN_H=@NO_LIBGEN_H@
+HAVE_PATHS_H=@HAVE_PATHS_H@
 NEEDS_LIBICONV=@NEEDS_LIBICONV@
 NEEDS_SOCKET=@NEEDS_SOCKET@
 NEEDS_RESOLV=@NEEDS_RESOLV@
index f4d7372ef8d7b45f9810d5f8bc191c71622a71f2..71038fcf1cd04fdfa3bcd133b6fc82974a135141 100644 (file)
@@ -724,6 +724,12 @@ AC_CHECK_HEADER([libgen.h],
 [NO_LIBGEN_H=YesPlease])
 AC_SUBST(NO_LIBGEN_H)
 #
+# Define HAVE_PATHS_H if you have paths.h.
+AC_CHECK_HEADER([paths.h],
+[HAVE_PATHS_H=YesPlease],
+[HAVE_PATHS_H=])
+AC_SUBST(HAVE_PATHS_H)
+#
 # Define NO_STRCASESTR if you don't have strcasestr.
 GIT_CHECK_FUNC(strcasestr,
 [NO_STRCASESTR=],
index 545bd4b38368e3c2a3958133bbeef6a19e831fff..57245a8c01fa3aba4f9e3f2bc258b40f38f446c0 100755 (executable)
@@ -797,6 +797,7 @@ _git_branch ()
                __gitcomp "
                        --color --no-color --verbose --abbrev= --no-abbrev
                        --track --no-track --contains --merged --no-merged
+                       --set-upstream
                        "
                ;;
        *)
index 58a35c82870c54f844fd1154a82237891655f38f..30ae63d74da065a31cced0b161708680f39c04c0 100755 (executable)
 # possible for the email to be from someone other than the person doing the
 # push.
 #
+# To help with debugging and use on pre-v1.5.1 git servers, this script will
+# also obey the interface of hooks/update, taking its arguments on the
+# command line.  Unfortunately, hooks/update is called once for each ref.
+# To avoid firing one email per ref, this script just prints its output to
+# the screen when used in this mode.  The output can then be redirected if
+# wanted.
+#
 # Config
 # ------
 # hooks.mailinglist
index aae8e7accc1ff955bd76c62b379b37f343f61cc4..4cd9dacbe8e98d1420ebe1a217b0f927d24d125a 100644 (file)
@@ -150,16 +150,14 @@ static int queue_diff(struct diff_options *o,
 
 static int path_outside_repo(const char *path)
 {
-       /*
-        * We have already done setup_git_directory_gently() so we
-        * know we are inside a git work tree already.
-        */
        const char *work_tree;
        size_t len;
 
        if (!is_absolute_path(path))
                return 0;
        work_tree = get_git_work_tree();
+       if (!work_tree)
+               return 1;
        len = strlen(work_tree);
        if (strncmp(path, work_tree, len) ||
            (path[len] != '\0' && path[len] != '/'))
diff --git a/diff.c b/diff.c
index 7e508dd064b849ba3c42b97b59a88d63304da8c7..230c310952f0296d195c32fbe18b26b279b3fd54 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -700,7 +700,6 @@ static void diff_words_show(struct diff_words_data *diff_words)
 {
        xpparam_t xpp;
        xdemitconf_t xecfg;
-       xdemitcb_t ecb;
        mmfile_t minus, plus;
 
        /* special case: only removal */
@@ -718,11 +717,11 @@ static void diff_words_show(struct diff_words_data *diff_words)
        memset(&xecfg, 0, sizeof(xecfg));
        diff_words_fill(&diff_words->minus, &minus, diff_words->word_regex);
        diff_words_fill(&diff_words->plus, &plus, diff_words->word_regex);
-       xpp.flags = XDF_NEED_MINIMAL;
+       xpp.flags = 0;
        /* as only the hunk header will be parsed, we need a 0-context */
        xecfg.ctxlen = 0;
        xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
-                     &xpp, &xecfg, &ecb);
+                     &xpp, &xecfg);
        free(minus.ptr);
        free(plus.ptr);
        if (diff_words->current_plus != diff_words->plus.text.ptr +
@@ -1708,7 +1707,6 @@ static void builtin_diff(const char *name_a,
                const char *diffopts = getenv("GIT_DIFF_OPTS");
                xpparam_t xpp;
                xdemitconf_t xecfg;
-               xdemitcb_t ecb;
                struct emit_callback ecbdata;
                const struct userdiff_funcname *pe;
 
@@ -1747,7 +1745,7 @@ static void builtin_diff(const char *name_a,
                        check_blank_at_eof(&mf1, &mf2, &ecbdata);
                ecbdata.file = o->file;
                ecbdata.header = header.len ? &header : NULL;
-               xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
+               xpp.flags = o->xdl_opts;
                xecfg.ctxlen = o->context;
                xecfg.interhunkctxlen = o->interhunkcontext;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
@@ -1780,7 +1778,7 @@ static void builtin_diff(const char *name_a,
                        }
                }
                xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
-                             &xpp, &xecfg, &ecb);
+                             &xpp, &xecfg);
                if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS))
                        free_diff_words_data(&ecbdata);
                if (textconv_one)
@@ -1833,13 +1831,12 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
                /* Crazy xdl interfaces.. */
                xpparam_t xpp;
                xdemitconf_t xecfg;
-               xdemitcb_t ecb;
 
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
-               xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
+               xpp.flags = o->xdl_opts;
                xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
-                             &xpp, &xecfg, &ecb);
+                             &xpp, &xecfg);
        }
 
  free_and_return:
@@ -1881,14 +1878,13 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
                /* Crazy xdl interfaces.. */
                xpparam_t xpp;
                xdemitconf_t xecfg;
-               xdemitcb_t ecb;
 
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                xecfg.ctxlen = 1; /* at least one context line */
-               xpp.flags = XDF_NEED_MINIMAL;
+               xpp.flags = 0;
                xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
-                             &xpp, &xecfg, &ecb);
+                             &xpp, &xecfg);
 
                if (data.ws_rule & WS_BLANK_AT_EOF) {
                        struct emit_callback ecbdata;
@@ -3392,7 +3388,6 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
        for (i = 0; i < q->nr; i++) {
                xpparam_t xpp;
                xdemitconf_t xecfg;
-               xdemitcb_t ecb;
                mmfile_t mf1, mf2;
                struct diff_filepair *p = q->queue[i];
                int len1, len2;
@@ -3450,11 +3445,11 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
                                        len2, p->two->path);
                git_SHA1_Update(&ctx, buffer, len1);
 
-               xpp.flags = XDF_NEED_MINIMAL;
+               xpp.flags = 0;
                xecfg.ctxlen = 3;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
                xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
-                             &xpp, &xecfg, &ecb);
+                             &xpp, &xecfg);
        }
 
        git_SHA1_Final(sha1, &ctx);
diff --git a/dir.c b/dir.c
index cb83332a261f97026f9c6273afb162245944dec7..5615f33af187f381f8c2dfe7ab53910fe165fd59 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -958,9 +958,14 @@ char *get_relative_cwd(char *buffer, int size, const char *dir)
        }
        if (*dir)
                return NULL;
-       if (*cwd == '/')
+       switch (*cwd) {
+       case '\0':
+               return cwd;
+       case '/':
                return cwd + 1;
-       return cwd;
+       default:
+               return NULL;
+       }
 }
 
 int is_inside_dir(const char *dir)
index b2c07c70ce26312d81f499d3acf90dab919f1d24..bf225706ee377b89035eb21f76f9957cfaf6363b 100644 (file)
@@ -107,7 +107,7 @@ void setup_path(void)
        if (old_path)
                strbuf_addstr(&new_path, old_path);
        else
-               strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
+               strbuf_addstr(&new_path, _PATH_DEFPATH);
 
        setenv("PATH", new_path.buf, 1);
 
index 21f1330a5bf26c955051ce9cf263289d90c7667b..27fc79347af428dd39daa5b550814cc6cf980510 100755 (executable)
@@ -1111,9 +1111,9 @@ sub help_patch_cmd {
        print colored $help_color, <<EOF ;
 y - $verb this hunk$target
 n - do not $verb this hunk$target
-q - quit, do not $verb this hunk nor any of the remaining ones
-a - $verb this and all the remaining hunks in the file
-d - do not $verb this hunk nor any of the remaining hunks in the file
+q - quit; do not $verb this hunk nor any of the remaining ones
+a - $verb this hunk and all later hunks in the file
+d - do not $verb this hunk nor any of the later hunks in the file
 g - select a hunk to go to
 / - search for a hunk matching the given regex
 j - leave this hunk undecided, see next undecided hunk
index 1056075545ad3e5e42626d167c91c1deada6186b..87ffae252b3f2ff88646d142ea9c2dfb38a28953 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -740,7 +740,7 @@ do
                ;;
        esac
 
-       if test $apply_status = 1 && test "$threeway" = t
+       if test $apply_status != 0 && test "$threeway" = t
        then
                if (fall_back_3way)
                then
index 7e62b552700a580646dbb6a8921c40761d6b57a2..c9e711872f1a2380d273f7149b4795a4a9852c06 100644 (file)
@@ -56,7 +56,7 @@
 # define _XOPEN_SOURCE 500
 # endif
 #elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
-      !defined(_M_UNIX) && !defined(sgi) && !defined(__DragonFly__)
+      !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__)
 #define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
 #define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
 #endif
@@ -164,6 +164,13 @@ extern char *gitbasename(char *);
 #define PATH_SEP ':'
 #endif
 
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifndef _PATH_DEFPATH
+#define _PATH_DEFPATH "/usr/local/bin:/usr/bin:/bin"
+#endif
+
 #ifndef STRIP_EXTENSION
 #define STRIP_EXTENSION ""
 #endif
@@ -356,6 +363,8 @@ static inline void *gitmempcpy(void *dest, const void *src, size_t n)
 
 extern void release_pack_memory(size_t, int);
 
+extern void set_try_to_free_routine(void (*routine)(size_t));
+
 extern char *xstrdup(const char *str);
 extern void *xmalloc(size_t size);
 extern void *xmallocz(size_t size);
index ce569a9c8f964b3cdc8920325bc817141035c2c3..111c981229bf2c0bc6afa4a22db011b68d93fdfa 100755 (executable)
@@ -132,8 +132,6 @@ my $have_email_valid = eval { require Email::Valid; 1 };
 my $have_mail_address = eval { require Mail::Address; 1 };
 my $smtp;
 my $auth;
-my $mail_domain_default = "localhost.localdomain";
-my $mail_domain;
 
 sub unique_email_list(@);
 sub cleanup_compose_files();
@@ -190,7 +188,7 @@ sub do_edit {
 # Variables with corresponding config settings
 my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd);
 my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption);
-my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
+my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts, $smtp_domain);
 my ($validate, $confirm);
 my (@suppress_cc);
 
@@ -212,6 +210,7 @@ my %config_settings = (
     "smtpserverport" => \$smtp_server_port,
     "smtpuser" => \$smtp_authuser,
     "smtppass" => \$smtp_authpass,
+       "smtpdomain" => \$smtp_domain,
     "to" => \@to,
     "cc" => \@initial_cc,
     "cccmd" => \$cc_cmd,
@@ -283,7 +282,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,
                    "smtp-ssl" => sub { $smtp_encryption = 'ssl' },
                    "smtp-encryption=s" => \$smtp_encryption,
                    "smtp-debug:i" => \$debug_net_smtp,
-                   "smtp-domain:s" => \$mail_domain,
+                   "smtp-domain:s" => \$smtp_domain,
                    "identity=s" => \$identity,
                    "annotate" => \$annotate,
                    "compose" => \$compose,
@@ -761,8 +760,7 @@ sub extract_valid_address {
 # We'll setup a template for the message id, using the "from" address:
 
 my ($message_id_stamp, $message_id_serial);
-sub make_message_id
-{
+sub make_message_id {
        my $uniq;
        if (!defined $message_id_stamp) {
                $message_id_stamp = sprintf("%s-%s", time, $$);
@@ -817,8 +815,7 @@ sub is_rfc2047_quoted {
 }
 
 # use the simplest quoting being able to handle the recipient
-sub sanitize_address
-{
+sub sanitize_address {
        my ($recipient) = @_;
        my ($recipient_name, $recipient_addr) = ($recipient =~ /^(.*?)\s*(<.*)/);
 
@@ -863,21 +860,23 @@ sub sanitize_address
 # This maildomain*() code is based on ideas in Perl library Test::Reporter
 # /usr/share/perl5/Test/Reporter/Mail/Util.pm ==> sub _maildomain ()
 
-sub maildomain_net
-{
+sub valid_fqdn {
+       my $domain = shift;
+       return !($^O eq 'darwin' && $domain =~ /\.local$/) && $domain =~ /\./;
+}
+
+sub maildomain_net {
        my $maildomain;
 
        if (eval { require Net::Domain; 1 }) {
                my $domain = Net::Domain::domainname();
-               $maildomain = $domain
-                       unless $^O eq 'darwin' && $domain =~ /\.local$/;
+               $maildomain = $domain if valid_fqdn($domain);
        }
 
        return $maildomain;
 }
 
-sub maildomain_mta
-{
+sub maildomain_mta {
        my $maildomain;
 
        if (eval { require Net::SMTP; 1 }) {
@@ -887,8 +886,7 @@ sub maildomain_mta
                                my $domain = $smtp->domain;
                                $smtp->quit;
 
-                               $maildomain = $domain
-                                       unless $^O eq 'darwin' && $domain =~ /\.local$/;
+                               $maildomain = $domain if valid_fqdn($domain);
 
                                last if $maildomain;
                        }
@@ -898,17 +896,15 @@ sub maildomain_mta
        return $maildomain;
 }
 
-sub maildomain
-{
-       return maildomain_net() || maildomain_mta() || $mail_domain_default;
+sub maildomain {
+       return maildomain_net() || maildomain_mta() || 'localhost.localdomain';
 }
 
 # Returns 1 if the message was sent, and 0 otherwise.
 # In actuality, the whole program dies when there
 # is an error sending a message.
 
-sub send_message
-{
+sub send_message {
        my @recipients = unique_email_list(@to);
        @cc = (grep { my $cc = extract_valid_address($_);
                      not grep { $cc eq $_ } @recipients
@@ -1005,18 +1001,18 @@ X-Mailer: git-send-email $gitversion
                if ($smtp_encryption eq 'ssl') {
                        $smtp_server_port ||= 465; # ssmtp
                        require Net::SMTP::SSL;
-                       $mail_domain ||= maildomain();
+                       $smtp_domain ||= maildomain();
                        $smtp ||= Net::SMTP::SSL->new($smtp_server,
-                                                     Hello => $mail_domain,
+                                                     Hello => $smtp_domain,
                                                      Port => $smtp_server_port);
                }
                else {
                        require Net::SMTP;
-                       $mail_domain ||= maildomain();
+                       $smtp_domain ||= maildomain();
                        $smtp ||= Net::SMTP->new((defined $smtp_server_port)
                                                 ? "$smtp_server:$smtp_server_port"
                                                 : $smtp_server,
-                                                Hello => $mail_domain,
+                                                Hello => $smtp_domain,
                                                 Debug => $debug_net_smtp);
                        if ($smtp_encryption eq 'tls' && $smtp) {
                                require Net::SMTP::SSL;
@@ -1039,7 +1035,7 @@ X-Mailer: git-send-email $gitversion
                        die "Unable to initialize SMTP properly. Check config and use --smtp-debug. ",
                            "VALUES: server=$smtp_server ",
                            "encryption=$smtp_encryption ",
-                           "maildomain=$mail_domain",
+                           "hello=$smtp_domain",
                            defined $smtp_server_port ? "port=$smtp_server_port" : "";
                }
 
index 59db3dc38e72fda88d521171a174c08b919677a9..0f858d334c756f9cd4028b4950a3912d0f6182dd 100755 (executable)
@@ -86,7 +86,7 @@ create_stash () {
                        GIT_INDEX_FILE="$TMP-index" &&
                        export GIT_INDEX_FILE &&
                        git read-tree -m $i_tree &&
-                       git add -u &&
+                       git diff --name-only -z HEAD | git update-index -z --add --remove --stdin &&
                        git write-tree &&
                        rm -f "$TMP-index"
                ) ) ||
index 2dd372a21d82a109774e80e014f9959485202b3e..3319b836b217a26b4ac55ae5ced328ffafa0a015 100755 (executable)
@@ -21,6 +21,8 @@ command=
 branch=
 reference=
 cached=
+recursive=
+init=
 files=
 nofetch=
 update=
index f2e1d92fbb965893b14adf2e9acb904bab953812..e7dd2527736ddc6e47f864916115f9cc5c9e7dd9 100644 (file)
@@ -91,7 +91,7 @@ ifdef CSSMIN
 GITWEB_CSS = gitweb.min.css
 all:: gitweb.min.css
 gitweb.min.css: gitweb.css GITWEB-BUILD-OPTIONS
-       $(QUIET_GEN)$(CSSMIN) <$ >$@
+       $(QUIET_GEN)$(CSSMIN) <$< >$@
 endif
 
 GITWEB_REPLACE = \
index ef99ae647ae02995495c71455eef785bdeca1789..8ca76d0507bdc1d95283e1f5fee3f88180cdce26 100644 (file)
@@ -510,7 +510,7 @@ static int fetch_object(struct walker *walker, struct alt_base *repo, unsigned c
                ret = error("File %s has bad hash", hex);
        } else if (req->rename < 0) {
                ret = error("unable to write sha1 filename %s",
-                           req->filename);
+                           sha1_file_name(req->sha1));
        }
 
        release_http_object_request(req);
diff --git a/http.c b/http.c
index 4814217c6401faa1fd8f13f0288758f57b5e3755..1320c50e32eb7b8715b263bc2af089c3dbce39fa 100644 (file)
--- a/http.c
+++ b/http.c
@@ -1,6 +1,7 @@
 #include "http.h"
 #include "pack.h"
 #include "sideband.h"
+#include "run-command.h"
 
 int data_received;
 int active_requests;
@@ -720,7 +721,7 @@ static inline int hex(int v)
                return 'A' + v - 10;
 }
 
-static void end_url_with_slash(struct strbuf *buf, const char *url)
+void end_url_with_slash(struct strbuf *buf, const char *url)
 {
        strbuf_addstr(buf, url);
        if (buf->len && buf->buf[buf->len - 1] != '/')
@@ -815,7 +816,21 @@ static int http_request(const char *url, void *result, int target, int options)
                        ret = HTTP_OK;
                else if (missing_target(&results))
                        ret = HTTP_MISSING_TARGET;
-               else
+               else if (results.http_code == 401) {
+                       if (user_name) {
+                               ret = HTTP_NOAUTH;
+                       } else {
+                               /*
+                                * git_getpass is needed here because its very likely stdin/stdout are
+                                * pipes to our parent process.  So we instead need to use /dev/tty,
+                                * but that is non-portable.  Using git_getpass() can at least be stubbed
+                                * on other platforms with a different implementation if/when necessary.
+                                */
+                               user_name = xstrdup(git_getpass("Username: "));
+                               init_curl_http_auth(slot->curl);
+                               ret = HTTP_REAUTH;
+                       }
+               } else
                        ret = HTTP_ERROR;
        } else {
                error("Unable to start HTTP request for %s", url);
@@ -831,7 +846,11 @@ static int http_request(const char *url, void *result, int target, int options)
 
 int http_get_strbuf(const char *url, struct strbuf *result, int options)
 {
-       return http_request(url, result, HTTP_REQUEST_STRBUF, options);
+       int http_ret = http_request(url, result, HTTP_REQUEST_STRBUF, options);
+       if (http_ret == HTTP_REAUTH) {
+               http_ret = http_request(url, result, HTTP_REQUEST_STRBUF, options);
+       }
+       return http_ret;
 }
 
 /*
@@ -896,47 +915,67 @@ int http_fetch_ref(const char *base, struct ref *ref)
 }
 
 /* Helpers for fetching packs */
-static int fetch_pack_index(unsigned char *sha1, const char *base_url)
+static char *fetch_pack_index(unsigned char *sha1, const char *base_url)
 {
-       int ret = 0;
-       char *hex = xstrdup(sha1_to_hex(sha1));
-       char *filename;
-       char *url = NULL;
+       char *url, *tmp;
        struct strbuf buf = STRBUF_INIT;
 
-       if (has_pack_index(sha1)) {
-               ret = 0;
-               goto cleanup;
-       }
-
        if (http_is_verbose)
-               fprintf(stderr, "Getting index for pack %s\n", hex);
+               fprintf(stderr, "Getting index for pack %s\n", sha1_to_hex(sha1));
 
        end_url_with_slash(&buf, base_url);
-       strbuf_addf(&buf, "objects/pack/pack-%s.idx", hex);
+       strbuf_addf(&buf, "objects/pack/pack-%s.idx", sha1_to_hex(sha1));
        url = strbuf_detach(&buf, NULL);
 
-       filename = sha1_pack_index_name(sha1);
-       if (http_get_file(url, filename, 0) != HTTP_OK)
-               ret = error("Unable to get pack index %s\n", url);
+       strbuf_addf(&buf, "%s.temp", sha1_pack_index_name(sha1));
+       tmp = strbuf_detach(&buf, NULL);
+
+       if (http_get_file(url, tmp, 0) != HTTP_OK) {
+               error("Unable to get pack index %s\n", url);
+               free(tmp);
+               tmp = NULL;
+       }
 
-cleanup:
-       free(hex);
        free(url);
-       return ret;
+       return tmp;
 }
 
 static int fetch_and_setup_pack_index(struct packed_git **packs_head,
        unsigned char *sha1, const char *base_url)
 {
        struct packed_git *new_pack;
+       char *tmp_idx = NULL;
+       int ret;
 
-       if (fetch_pack_index(sha1, base_url))
+       if (has_pack_index(sha1)) {
+               new_pack = parse_pack_index(sha1, NULL);
+               if (!new_pack)
+                       return -1; /* parse_pack_index() already issued error message */
+               goto add_pack;
+       }
+
+       tmp_idx = fetch_pack_index(sha1, base_url);
+       if (!tmp_idx)
                return -1;
 
-       new_pack = parse_pack_index(sha1);
-       if (!new_pack)
+       new_pack = parse_pack_index(sha1, tmp_idx);
+       if (!new_pack) {
+               unlink(tmp_idx);
+               free(tmp_idx);
+
                return -1; /* parse_pack_index() already issued error message */
+       }
+
+       ret = verify_pack_index(new_pack);
+       if (!ret) {
+               close_pack_index(new_pack);
+               ret = move_temp_to_file(tmp_idx, sha1_pack_index_name(sha1));
+       }
+       free(tmp_idx);
+       if (ret)
+               return -1;
+
+add_pack:
        new_pack->next = *packs_head;
        *packs_head = new_pack;
        return 0;
@@ -1000,37 +1039,62 @@ void release_http_pack_request(struct http_pack_request *preq)
 
 int finish_http_pack_request(struct http_pack_request *preq)
 {
-       int ret;
        struct packed_git **lst;
+       struct packed_git *p = preq->target;
+       char *tmp_idx;
+       struct child_process ip;
+       const char *ip_argv[8];
 
-       preq->target->pack_size = ftell(preq->packfile);
-
-       if (preq->packfile != NULL) {
-               fclose(preq->packfile);
-               preq->packfile = NULL;
-               preq->slot->local = NULL;
-       }
+       close_pack_index(p);
 
-       ret = move_temp_to_file(preq->tmpfile, preq->filename);
-       if (ret)
-               return ret;
+       fclose(preq->packfile);
+       preq->packfile = NULL;
+       preq->slot->local = NULL;
 
        lst = preq->lst;
-       while (*lst != preq->target)
+       while (*lst != p)
                lst = &((*lst)->next);
        *lst = (*lst)->next;
 
-       if (verify_pack(preq->target))
+       tmp_idx = xstrdup(preq->tmpfile);
+       strcpy(tmp_idx + strlen(tmp_idx) - strlen(".pack.temp"),
+              ".idx.temp");
+
+       ip_argv[0] = "index-pack";
+       ip_argv[1] = "-o";
+       ip_argv[2] = tmp_idx;
+       ip_argv[3] = preq->tmpfile;
+       ip_argv[4] = NULL;
+
+       memset(&ip, 0, sizeof(ip));
+       ip.argv = ip_argv;
+       ip.git_cmd = 1;
+       ip.no_stdin = 1;
+       ip.no_stdout = 1;
+
+       if (run_command(&ip)) {
+               unlink(preq->tmpfile);
+               unlink(tmp_idx);
+               free(tmp_idx);
+               return -1;
+       }
+
+       unlink(sha1_pack_index_name(p->sha1));
+
+       if (move_temp_to_file(preq->tmpfile, sha1_pack_name(p->sha1))
+        || move_temp_to_file(tmp_idx, sha1_pack_index_name(p->sha1))) {
+               free(tmp_idx);
                return -1;
-       install_packed_git(preq->target);
+       }
 
+       install_packed_git(p);
+       free(tmp_idx);
        return 0;
 }
 
 struct http_pack_request *new_http_pack_request(
        struct packed_git *target, const char *base_url)
 {
-       char *filename;
        long prev_posn = 0;
        char range[RANGE_HEADER_SIZE];
        struct strbuf buf = STRBUF_INIT;
@@ -1045,9 +1109,8 @@ struct http_pack_request *new_http_pack_request(
                sha1_to_hex(target->sha1));
        preq->url = strbuf_detach(&buf, NULL);
 
-       filename = sha1_pack_name(target->sha1);
-       snprintf(preq->filename, sizeof(preq->filename), "%s", filename);
-       snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp", filename);
+       snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp",
+               sha1_pack_name(target->sha1));
        preq->packfile = fopen(preq->tmpfile, "a");
        if (!preq->packfile) {
                error("Unable to open local file %s for pack",
@@ -1082,7 +1145,6 @@ struct http_pack_request *new_http_pack_request(
        return preq;
 
 abort:
-       free(filename);
        free(preq->url);
        free(preq);
        return NULL;
@@ -1137,7 +1199,6 @@ struct http_object_request *new_http_object_request(const char *base_url,
        freq->localfile = -1;
 
        filename = sha1_file_name(sha1);
-       snprintf(freq->filename, sizeof(freq->filename), "%s", filename);
        snprintf(freq->tmpfile, sizeof(freq->tmpfile),
                 "%s.temp", filename);
 
@@ -1166,8 +1227,8 @@ struct http_object_request *new_http_object_request(const char *base_url,
        }
 
        if (freq->localfile < 0) {
-               error("Couldn't create temporary file %s for %s: %s",
-                     freq->tmpfile, freq->filename, strerror(errno));
+               error("Couldn't create temporary file %s: %s",
+                     freq->tmpfile, strerror(errno));
                goto abort;
        }
 
@@ -1214,8 +1275,8 @@ struct http_object_request *new_http_object_request(const char *base_url,
                        prev_posn = 0;
                        lseek(freq->localfile, 0, SEEK_SET);
                        if (ftruncate(freq->localfile, 0) < 0) {
-                               error("Couldn't truncate temporary file %s for %s: %s",
-                                         freq->tmpfile, freq->filename, strerror(errno));
+                               error("Couldn't truncate temporary file %s: %s",
+                                         freq->tmpfile, strerror(errno));
                                goto abort;
                        }
                }
@@ -1291,7 +1352,7 @@ int finish_http_object_request(struct http_object_request *freq)
                return -1;
        }
        freq->rename =
-               move_temp_to_file(freq->tmpfile, freq->filename);
+               move_temp_to_file(freq->tmpfile, sha1_file_name(freq->sha1));
 
        return freq->rename;
 }
diff --git a/http.h b/http.h
index 5c9441c10ce708be426afe7424d63dcbb68a49e2..a0b59015948c3b9736dd6c09fd9137f7ecd4f59a 100644 (file)
--- a/http.h
+++ b/http.h
@@ -117,6 +117,7 @@ extern void append_remote_object_url(struct strbuf *buf, const char *url,
                                     int only_two_digit_prefix);
 extern char *get_remote_object_url(const char *url, const char *hex,
                                   int only_two_digit_prefix);
+extern void end_url_with_slash(struct strbuf *buf, const char *url);
 
 /* Options for http_request_*() */
 #define HTTP_NO_CACHE          1
@@ -126,6 +127,8 @@ extern char *get_remote_object_url(const char *url, const char *hex,
 #define HTTP_MISSING_TARGET    1
 #define HTTP_ERROR             2
 #define HTTP_START_FAILED      3
+#define HTTP_REAUTH    4
+#define HTTP_NOAUTH    5
 
 /*
  * Requests an url and stores the result in a strbuf.
@@ -152,7 +155,6 @@ struct http_pack_request
        struct packed_git *target;
        struct packed_git **lst;
        FILE *packfile;
-       char filename[PATH_MAX];
        char tmpfile[PATH_MAX];
        struct curl_slist *range_header;
        struct active_request_slot *slot;
@@ -167,7 +169,6 @@ extern void release_http_pack_request(struct http_pack_request *preq);
 struct http_object_request
 {
        char *url;
-       char filename[PATH_MAX];
        char tmpfile[PATH_MAX];
        int localfile;
        CURLcode curl_result;
index c336c93c01c0bad76d6189065f0e6630d0b7f5af..db4d0d50d32d8852d1cb5173125e4173c3badb49 100644 (file)
@@ -66,7 +66,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2)
        xdemitcb_t ecb;
 
        memset(&xpp, 0, sizeof(xpp));
-       xpp.flags = XDF_NEED_MINIMAL;
+       xpp.flags = 0;
        memset(&xecfg, 0, sizeof(xecfg));
        xecfg.ctxlen = 3;
        xecfg.flags = XDL_EMIT_COMMON;
index 3ca92c4c4def46af10556dbe9b3f48774b9a4a35..277b3ddba7dc5387cd97cb35c23d3358727898be 100644 (file)
--- a/object.c
+++ b/object.c
@@ -252,10 +252,10 @@ void add_object_array_with_mode(struct object *obj, const char *name, struct obj
 
 void object_array_remove_duplicates(struct object_array *array)
 {
-       int ref, src, dst;
+       unsigned int ref, src, dst;
        struct object_array_entry *objects = array->objects;
 
-       for (ref = 0; ref < array->nr - 1; ref++) {
+       for (ref = 0; ref + 1 < array->nr; ref++) {
                for (src = ref + 1, dst = src;
                     src < array->nr;
                     src++) {
index 166ca703c10face0d4961da6ceee7a149ebcfac4..395fb9527a3bc6dd8ca648233911a1c35604440d 100644 (file)
@@ -133,14 +133,13 @@ static int verify_packfile(struct packed_git *p,
        return err;
 }
 
-int verify_pack(struct packed_git *p)
+int verify_pack_index(struct packed_git *p)
 {
        off_t index_size;
        const unsigned char *index_base;
        git_SHA_CTX ctx;
        unsigned char sha1[20];
        int err = 0;
-       struct pack_window *w_curs = NULL;
 
        if (open_pack_index(p))
                return error("packfile %s index not opened", p->pack_name);
@@ -154,8 +153,18 @@ int verify_pack(struct packed_git *p)
        if (hashcmp(sha1, index_base + index_size - 20))
                err = error("Packfile index for %s SHA1 mismatch",
                            p->pack_name);
+       return err;
+}
+
+int verify_pack(struct packed_git *p)
+{
+       int err = 0;
+       struct pack_window *w_curs = NULL;
+
+       err |= verify_pack_index(p);
+       if (!p->index_data)
+               return -1;
 
-       /* Verify pack file */
        err |= verify_packfile(p, &w_curs);
        unuse_pack(&w_curs);
 
diff --git a/pack.h b/pack.h
index d268c014c9eb7040bd65125b13d68edce670274b..bb275762b7eb6f473f333ae40780821e383db20b 100644 (file)
--- a/pack.h
+++ b/pack.h
@@ -57,6 +57,7 @@ struct pack_idx_entry {
 
 extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1);
 extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
+extern int verify_pack_index(struct packed_git *);
 extern int verify_pack(struct packed_git *);
 extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);
 extern char *index_pack_lockfile(int fd);
index 7cb3a2af508bb5667cd74304f72b50766c749990..2777d30224618fb0ec823961c3c35ede1ac4e2e5 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -716,7 +716,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
                if (add_again(sb, &c->abbrev_commit_hash))
                        return 1;
                strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1,
-                                                    DEFAULT_ABBREV));
+                                                    c->pretty_ctx->abbrev));
                c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
                return 1;
        case 'T':               /* tree hash */
@@ -726,7 +726,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
                if (add_again(sb, &c->abbrev_tree_hash))
                        return 1;
                strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.sha1,
-                                                    DEFAULT_ABBREV));
+                                                    c->pretty_ctx->abbrev));
                c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off;
                return 1;
        case 'P':               /* parent hashes */
@@ -743,7 +743,8 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
                        if (p != commit->parents)
                                strbuf_addch(sb, ' ');
                        strbuf_addstr(sb, find_unique_abbrev(
-                                       p->item->object.sha1, DEFAULT_ABBREV));
+                                       p->item->object.sha1,
+                                       c->pretty_ctx->abbrev));
                }
                c->abbrev_parent_hashes.len = sb->len -
                                              c->abbrev_parent_hashes.off;
index b76bfcb3d3cdbbee2e3279a6696c7d6b526176d7..24fbb9a9b972c1078b3688b2d0683c9704e09ee6 100644 (file)
@@ -9,7 +9,7 @@
 #include "sideband.h"
 
 static struct remote *remote;
-static const char *url;
+static const char *url; /* always ends with a trailing slash */
 
 struct options {
        int verbosity;
@@ -101,7 +101,7 @@ static struct discovery* discover_refs(const char *service)
                return last;
        free_discovery(last);
 
-       strbuf_addf(&buffer, "%s/info/refs", url);
+       strbuf_addf(&buffer, "%sinfo/refs", url);
        if (!prefixcmp(url, "http://") || !prefixcmp(url, "https://")) {
                is_http = 1;
                if (!strchr(url, '?'))
@@ -120,7 +120,7 @@ static struct discovery* discover_refs(const char *service)
                strbuf_reset(&buffer);
 
                proto_git_candidate = 0;
-               strbuf_addf(&buffer, "%s/info/refs", url);
+               strbuf_addf(&buffer, "%sinfo/refs", url);
                refs_url = strbuf_detach(&buffer, NULL);
 
                http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
@@ -132,6 +132,8 @@ static struct discovery* discover_refs(const char *service)
        case HTTP_MISSING_TARGET:
                die("%s not found: did you run git update-server-info on the"
                    " server?", refs_url);
+       case HTTP_NOAUTH:
+               die("Authentication failed");
        default:
                http_error(refs_url, http_ret);
                die("HTTP request failed");
@@ -509,7 +511,7 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
        rpc->out = client.out;
        strbuf_init(&rpc->result, 0);
 
-       strbuf_addf(&buf, "%s/%s", url, svc);
+       strbuf_addf(&buf, "%s%s", url, svc);
        rpc->service_url = strbuf_detach(&buf, NULL);
 
        strbuf_addf(&buf, "Content-Type: application/x-%s-request", svc);
@@ -798,11 +800,13 @@ int main(int argc, const char **argv)
        remote = remote_get(argv[1]);
 
        if (argc > 2) {
-               url = argv[2];
+               end_url_with_slash(&buf, argv[2]);
        } else {
-               url = remote->url[0];
+               end_url_with_slash(&buf, remote->url[0]);
        }
 
+       url = strbuf_detach(&buf, NULL);
+
        http_init(remote);
 
        do {
index c70181cdc621b27ed02aba17b3e4f7ab64518e9f..26ce56046dd14fec4ae59c7e7df3c2072178c51d 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -476,7 +476,7 @@ static void read_config(void)
        unsigned char sha1[20];
        const char *head_ref;
        int flag;
-       if (default_remote_name) // did this already
+       if (default_remote_name) /* did this already */
                return;
        default_remote_name = xstrdup("origin");
        current_branch = NULL;
index eb5c57562909c1e505c2a7688bad6dbeea4b96a0..c7793f50fbe0a43495c2b2d36a47c0b5aac37483 100644 (file)
@@ -383,6 +383,8 @@ fail_pipe:
                        close(cmd->out);
                if (need_err)
                        close_pair(fderr);
+               else if (cmd->err)
+                       close(cmd->err);
                errno = failed_errno;
                return -1;
        }
diff --git a/setup.c b/setup.c
index 5716d90b57574d045114f4aaad1bdf36fd79ed89..0e4cfe603f1afe515365c9daf1ad8406de8e7fa8 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -519,6 +519,12 @@ int check_repository_format(void)
        return check_repository_format_gently(NULL);
 }
 
+/*
+ * Returns the "prefix", a path to the current working directory
+ * relative to the work tree root, or NULL, if the current working
+ * directory is not a strict subdirectory of the work tree root. The
+ * prefix always ends with a '/' character.
+ */
 const char *setup_git_directory(void)
 {
        const char *retval = setup_git_directory_gently(NULL);
index ff65328006404fd0d113f2cd4c4d52377b4cc8cf..1efa9154eda4e1ec064d627dfb21c876c914f4d7 100644 (file)
@@ -599,6 +599,14 @@ void unuse_pack(struct pack_window **w_cursor)
        }
 }
 
+void close_pack_index(struct packed_git *p)
+{
+       if (p->index_data) {
+               munmap((void *)p->index_data, p->index_size);
+               p->index_data = NULL;
+       }
+}
+
 /*
  * This is used by git-repack in case a newly created pack happens to
  * contain the same set of objects as an existing one.  In that case
@@ -620,8 +628,7 @@ void free_pack_by_name(const char *pack_name)
                        close_pack_windows(p);
                        if (p->pack_fd != -1)
                                close(p->pack_fd);
-                       if (p->index_data)
-                               munmap((void *)p->index_data, p->index_size);
+                       close_pack_index(p);
                        free(p->bad_object_sha1);
                        *pp = p->next;
                        free(p);
@@ -831,9 +838,8 @@ struct packed_git *add_packed_git(const char *path, int path_len, int local)
        return p;
 }
 
-struct packed_git *parse_pack_index(unsigned char *sha1)
+struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
 {
-       const char *idx_path = sha1_pack_index_name(sha1);
        const char *path = sha1_pack_name(sha1);
        struct packed_git *p = alloc_packed_git(strlen(path) + 1);
 
@@ -2448,6 +2454,8 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
                else
                        ret = -1;
                strbuf_release(&sbuf);
+       } else if (!size) {
+               ret = index_mem(sha1, NULL, size, write_object, type, path);
        } else if (size <= SMALL_FILE_SIZE) {
                char *buf = xmalloc(size);
                if (size == read_in_full(fd, buf, size))
@@ -2456,12 +2464,11 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
                else
                        ret = error("short read %s", strerror(errno));
                free(buf);
-       } else if (size) {
+       } else {
                void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
                ret = index_mem(sha1, buf, size, write_object, type, path);
                munmap(buf, size);
-       } else
-               ret = index_mem(sha1, NULL, size, write_object, type, path);
+       }
        close(fd);
        return ret;
 }
index bc02cc29ef0d5f640ab390614def995f30fe4691..de4f86fb970e15491f44dfe38b7d7d6fdc3be9ad 100644 (file)
@@ -12,6 +12,7 @@ struct shortlog {
        int in1;
        int in2;
        int user_format;
+       int abbrev;
 
        char *common_repo_prefix;
        int email;
index dcd3ebb5f2dcdbf15ca0e4a043b45cd2fc36cbb5..0e4e8d8862c96383a6f6f22a1b6bb01044925620 100644 (file)
--- a/t/README
+++ b/t/README
@@ -84,6 +84,12 @@ appropriately before running "make".
        implied by other options like --valgrind and
        GIT_TEST_INSTALLED.
 
+--root=<directory>::
+       Create "trash" directories used to store all temporary data during
+       testing under <directory>, instead of the t/ directory.
+       Using this option with a RAM-based filesystem (such as tmpfs)
+       can massively speed up the test suite.
+
 You can also set the GIT_TEST_INSTALLED environment variable to
 the bindir of an existing git installation to test that installation.
 You still need to have built this git sandbox, from which various
diff --git a/t/lib-t6000.sh b/t/lib-t6000.sh
new file mode 100644 (file)
index 0000000..985d517
--- /dev/null
@@ -0,0 +1,127 @@
+: included from 6002 and others
+
+[ -d .git/refs/tags ] || mkdir -p .git/refs/tags
+
+:> sed.script
+
+# Answer the sha1 has associated with the tag. The tag must exist in .git or .git/refs/tags
+tag()
+{
+       _tag=$1
+       [ -f .git/refs/tags/$_tag ] || error "tag: \"$_tag\" does not exist"
+       cat .git/refs/tags/$_tag
+}
+
+# Generate a commit using the text specified to make it unique and the tree
+# named by the tag specified.
+unique_commit()
+{
+       _text=$1
+        _tree=$2
+       shift 2
+       echo $_text | git commit-tree $(tag $_tree) "$@"
+}
+
+# Save the output of a command into the tag specified. Prepend
+# a substitution script for the tag onto the front of sed.script
+save_tag()
+{
+       _tag=$1
+       [ -n "$_tag" ] || error "usage: save_tag tag commit-args ..."
+       shift 1
+       "$@" >.git/refs/tags/$_tag
+
+        echo "s/$(tag $_tag)/$_tag/g" > sed.script.tmp
+       cat sed.script >> sed.script.tmp
+       rm sed.script
+       mv sed.script.tmp sed.script
+}
+
+# Replace unhelpful sha1 hashses with their symbolic equivalents
+entag()
+{
+       sed -f sed.script
+}
+
+# Execute a command after first saving, then setting the GIT_AUTHOR_EMAIL
+# tag to a specified value. Restore the original value on return.
+as_author()
+{
+       _author=$1
+       shift 1
+        _save=$GIT_AUTHOR_EMAIL
+
+       GIT_AUTHOR_EMAIL="$_author"
+       export GIT_AUTHOR_EMAIL
+       "$@"
+       if test -z "$_save"
+       then
+               unset GIT_AUTHOR_EMAIL
+       else
+               GIT_AUTHOR_EMAIL="$_save"
+               export GIT_AUTHOR_EMAIL
+       fi
+}
+
+commit_date()
+{
+        _commit=$1
+       git cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p"
+}
+
+on_committer_date()
+{
+    _date=$1
+    shift 1
+    GIT_COMMITTER_DATE="$_date"
+    export GIT_COMMITTER_DATE
+    "$@"
+    unset GIT_COMMITTER_DATE
+}
+
+# Execute a command and suppress any error output.
+hide_error()
+{
+       "$@" 2>/dev/null
+}
+
+check_output()
+{
+       _name=$1
+       shift 1
+       if eval "$*" | entag > $_name.actual
+       then
+               diff $_name.expected $_name.actual
+       else
+               return 1;
+       fi
+}
+
+# Turn a reasonable test description into a reasonable test name.
+# All alphanums translated into -'s which are then compressed and stripped
+# from front and back.
+name_from_description()
+{
+       perl -pe '
+               s/[^A-Za-z0-9.]/-/g;
+               s/-+/-/g;
+               s/-$//;
+               s/^-//;
+               y/A-Z/a-z/;
+       '
+}
+
+
+# Execute the test described by the first argument, by eval'ing
+# command line specified in the 2nd argument. Check the status code
+# is zero and that the output matches the stream read from
+# stdin.
+test_output_expect_success()
+{
+       _description=$1
+        _test=$2
+        [ $# -eq 2 ] || error "usage: test_output_expect_success description test <<EOF ... EOF"
+        _name=$(echo $_description | name_from_description)
+       cat > $_name.expected
+       test_expect_success "$_description" "check_output $_name \"$_test\""
+}
index f4ca4fc85c6b52a2ba919528284f2b668e6bd3d2..3ec9cbef2c88f65e5fb254d10cc551c6c4062c88 100755 (executable)
@@ -73,6 +73,27 @@ then
        exit 1
 fi
 
+clean=no
+test_expect_success 'tests clean up after themselves' '
+    test_when_finished clean=yes
+'
+
+cleaner=no
+test_expect_code 1 'tests clean up even after a failure' '
+    test_when_finished cleaner=yes &&
+    (exit 1)
+'
+
+if test $clean$cleaner != yesyes
+then
+       say "bug in test framework: cleanup commands do not work reliably"
+       exit 1
+fi
+
+test_expect_code 2 'failure to clean up causes the test to fail' '
+    test_when_finished "(exit 2)"
+'
+
 ################################################################
 # Basics of the basics
 
index 675773479a8c6a1791ae01eb47654f4433c30ee3..7c0a698b92696ff2bbb91e65e0a42e87f9163a1d 100755 (executable)
@@ -310,4 +310,18 @@ test_expect_success POSIXPERM 'init notices EPERM' '
        )
 '
 
+test_expect_success 'init creates a new bare directory with global --bare' '
+       rm -rf newdir &&
+       git --bare init newdir &&
+       test -d newdir/refs
+'
+
+test_expect_success 'init prefers command line to GIT_DIR' '
+       rm -rf newdir &&
+       mkdir otherdir &&
+       GIT_DIR=otherdir git --bare init newdir &&
+       test -d newdir/refs &&
+       ! test -d otherdir/refs
+'
+
 test_done
index 1c77192eb318d007689089eaf42f4f939c2f9ee4..53bd7fcc4abbf6cb7db73b43d5dde477f5115f90 100755 (executable)
@@ -20,8 +20,12 @@ test_expect_success 'setup' '
 
        mkdir -p a/b/d a/c &&
        (
+               echo "[attr]notest !test"
                echo "f test=f"
                echo "a/i test=a/i"
+               echo "onoff test -test"
+               echo "offon -test test"
+               echo "no notest"
        ) >.gitattributes &&
        (
                echo "g test=a/g" &&
@@ -30,6 +34,7 @@ test_expect_success 'setup' '
        (
                echo "h test=a/b/h" &&
                echo "d/* test=a/b/d/*"
+               echo "d/yes notest"
        ) >a/b/.gitattributes
 
 '
@@ -44,6 +49,11 @@ test_expect_success 'attribute test' '
        attr_check b/g unspecified &&
        attr_check a/b/h a/b/h &&
        attr_check a/b/d/g "a/b/d/*"
+       attr_check onoff unset
+       attr_check offon set
+       attr_check no unspecified
+       attr_check a/b/d/no "a/b/d/*"
+       attr_check a/b/d/yes unspecified
 
 '
 
@@ -58,6 +68,11 @@ a/b/g: test: a/b/g
 b/g: test: unspecified
 a/b/h: test: a/b/h
 a/b/d/g: test: a/b/d/*
+onoff: test: unset
+offon: test: set
+no: test: unspecified
+a/b/d/no: test: a/b/d/*
+a/b/d/yes: test: unspecified
 EOF
 
        sed -e "s/:.*//" < expect | git check-attr --stdin test > actual &&
index 9df301211c7f03e4a9edb0ccb9b1a7a648f97d8c..bd8b60732b06365fa22585eb8e97a3b1e64fdd05 100755 (executable)
@@ -30,6 +30,7 @@ test_rev_parse() {
 
 EMPTY_TREE=$(git write-tree)
 mkdir -p work/sub/dir || exit 1
+mkdir -p work2 || exit 1
 mv .git repo.git || exit 1
 
 say "core.worktree = relative path"
@@ -54,7 +55,9 @@ GIT_DIR=$(pwd)/repo.git
 GIT_CONFIG=$GIT_DIR/config
 git config core.worktree "$(pwd)/work"
 test_rev_parse 'outside'      false false false
-cd work || exit 1
+cd work2
+test_rev_parse 'outside2'     false false false
+cd ../work || exit 1
 test_rev_parse 'inside'       false false true ''
 cd sub/dir || exit 1
 test_rev_parse 'subdirectory' false false true sub/dir/
@@ -67,7 +70,9 @@ git config core.worktree non-existent
 GIT_WORK_TREE=work
 export GIT_WORK_TREE
 test_rev_parse 'outside'      false false false
-cd work || exit 1
+cd work2
+test_rev_parse 'outside'      false false false
+cd ../work || exit 1
 GIT_WORK_TREE=.
 test_rev_parse 'inside'       false false true ''
 cd sub/dir || exit 1
@@ -76,6 +81,7 @@ test_rev_parse 'subdirectory' false false true sub/dir/
 cd ../../.. || exit 1
 
 mv work repo.git/work
+mv work2 repo.git/work2
 
 say "GIT_WORK_TREE=absolute path, work tree below git dir"
 GIT_DIR=$(pwd)/repo.git
@@ -86,6 +92,8 @@ cd repo.git || exit 1
 test_rev_parse 'in repo.git'              false true  false
 cd objects || exit 1
 test_rev_parse 'in repo.git/objects'      false true  false
+cd ../work2 || exit 1
+test_rev_parse 'in repo.git/work2'      false true  false
 cd ../work || exit 1
 test_rev_parse 'in repo.git/work'         false true true ''
 cd sub/dir || exit 1
index 20f33436d00077b64dcc855fc263cd5d0efcca38..27e2127afeeb0dd462a686254e60be74e9dd9c28 100755 (executable)
@@ -44,8 +44,10 @@ test_expect_success 'switch from symlink to dir' '
 
 '
 
-rm -fr frotz xyzzy nitfol &&
-git checkout -f master || exit
+test_expect_success 'Remove temporary directories & switch to master' '
+       rm -fr frotz xyzzy nitfol &&
+       git checkout -f master
+'
 
 test_expect_success 'switch from dir to symlink' '
 
diff --git a/t/t2106-update-index-assume-unchanged.sh b/t/t2106-update-index-assume-unchanged.sh
new file mode 100755 (executable)
index 0000000..99d858c
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+test_description='git update-index --assume-unchanged test.
+'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' \
+       ': >file &&
+        git add file &&
+        git commit -m initial &&
+        git branch other &&
+        echo upstream >file &&
+        git add file &&
+        git commit -m upstream'
+
+test_expect_success 'do not switch branches with dirty file' \
+       'git reset --hard &&
+        git checkout other &&
+        echo dirt >file &&
+        git update-index --assume-unchanged file &&
+        test_must_fail git checkout master'
+
+test_done
diff --git a/t/t3307-notes-man.sh b/t/t3307-notes-man.sh
new file mode 100755 (executable)
index 0000000..3269f2e
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+test_description='Examples from the git-notes man page
+
+Make sure the manual is not full of lies.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       test_commit A &&
+       test_commit B &&
+       test_commit C
+'
+
+test_expect_success 'example 1: notes to add an Acked-by line' '
+       cat <<-\EOF >expect &&
+           B
+
+       Notes:
+           Acked-by: A C Ker <acker@example.com>
+       EOF
+       git notes add -m "Acked-by: A C Ker <acker@example.com>" B &&
+       git show -s B^{commit} >log &&
+       tail -n 4 log >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'example 2: binary notes' '
+       cp "$TEST_DIRECTORY"/test4012.png .
+       git checkout B &&
+       blob=$(git hash-object -w test4012.png) &&
+       git notes --ref=logo add -C "$blob" &&
+       git notes --ref=logo copy B C &&
+       git notes --ref=logo show C >actual &&
+       test_cmp test4012.png actual
+'
+
+test_done
index 476e5ec038f3c9fd2cad4607c3819f54dabd04ad..8fe14ccc5444df95960bee88e5b79eb68156572b 100755 (executable)
@@ -228,4 +228,154 @@ test_expect_success 'stash --invalid-option' '
        test bar,bar2 = $(cat file),$(cat file2)
 '
 
+test_expect_success 'stash an added file' '
+       git reset --hard &&
+       echo new >file3 &&
+       git add file3 &&
+       git stash save "added file" &&
+       ! test -r file3 &&
+       git stash apply &&
+       test new = "$(cat file3)"
+'
+
+test_expect_success 'stash rm then recreate' '
+       git reset --hard &&
+       git rm file &&
+       echo bar7 >file &&
+       git stash save "rm then recreate" &&
+       test bar = "$(cat file)" &&
+       git stash apply &&
+       test bar7 = "$(cat file)"
+'
+
+test_expect_success 'stash rm and ignore' '
+       git reset --hard &&
+       git rm file &&
+       echo file >.gitignore &&
+       git stash save "rm and ignore" &&
+       test bar = "$(cat file)" &&
+       test file = "$(cat .gitignore)"
+       git stash apply &&
+       ! test -r file &&
+       test file = "$(cat .gitignore)"
+'
+
+test_expect_success 'stash rm and ignore (stage .gitignore)' '
+       git reset --hard &&
+       git rm file &&
+       echo file >.gitignore &&
+       git add .gitignore &&
+       git stash save "rm and ignore (stage .gitignore)" &&
+       test bar = "$(cat file)" &&
+       ! test -r .gitignore
+       git stash apply &&
+       ! test -r file &&
+       test file = "$(cat .gitignore)"
+'
+
+test_expect_success SYMLINKS 'stash file to symlink' '
+       git reset --hard &&
+       rm file &&
+       ln -s file2 file &&
+       git stash save "file to symlink" &&
+       test -f file &&
+       test bar = "$(cat file)" &&
+       git stash apply &&
+       case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
+'
+
+test_expect_success SYMLINKS 'stash file to symlink (stage rm)' '
+       git reset --hard &&
+       git rm file &&
+       ln -s file2 file &&
+       git stash save "file to symlink (stage rm)" &&
+       test -f file &&
+       test bar = "$(cat file)" &&
+       git stash apply &&
+       case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
+'
+
+test_expect_success SYMLINKS 'stash file to symlink (full stage)' '
+       git reset --hard &&
+       rm file &&
+       ln -s file2 file &&
+       git add file &&
+       git stash save "file to symlink (full stage)" &&
+       test -f file &&
+       test bar = "$(cat file)" &&
+       git stash apply &&
+       case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
+'
+
+# This test creates a commit with a symlink used for the following tests
+
+test_expect_success SYMLINKS 'stash symlink to file' '
+       git reset --hard &&
+       ln -s file filelink &&
+       git add filelink &&
+       git commit -m "Add symlink" &&
+       rm filelink &&
+       cp file filelink &&
+       git stash save "symlink to file" &&
+       test -h filelink &&
+       case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac &&
+       git stash apply &&
+       ! test -h filelink &&
+       test bar = "$(cat file)"
+'
+
+test_expect_success SYMLINKS 'stash symlink to file (stage rm)' '
+       git reset --hard &&
+       git rm filelink &&
+       cp file filelink &&
+       git stash save "symlink to file (stage rm)" &&
+       test -h filelink &&
+       case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac &&
+       git stash apply &&
+       ! test -h filelink &&
+       test bar = "$(cat file)"
+'
+
+test_expect_success SYMLINKS 'stash symlink to file (full stage)' '
+       git reset --hard &&
+       rm filelink &&
+       cp file filelink &&
+       git add filelink &&
+       git stash save "symlink to file (full stage)" &&
+       test -h filelink &&
+       case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac &&
+       git stash apply &&
+       ! test -h filelink &&
+       test bar = "$(cat file)"
+'
+
+test_expect_failure 'stash directory to file' '
+       git reset --hard &&
+       mkdir dir &&
+       echo foo >dir/file &&
+       git add dir/file &&
+       git commit -m "Add file in dir" &&
+       rm -fr dir &&
+       echo bar >dir &&
+       git stash save "directory to file" &&
+       test -d dir &&
+       test foo = "$(cat dir/file)" &&
+       test_must_fail git stash apply &&
+       test bar = "$(cat dir)" &&
+       git reset --soft HEAD^
+'
+
+test_expect_failure 'stash file to directory' '
+       git reset --hard &&
+       rm file &&
+       mkdir file &&
+       echo foo >file/file &&
+       git stash save "file to directory" &&
+       test -f file &&
+       test bar = "$(cat file)" &&
+       git stash apply &&
+       test -f file/file &&
+       test foo = "$(cat file/file)"
+'
+
 test_done
index fb9ad247bf76c07a8b6dbbb0d6bf1ab830041770..451d75e3fb2ea3efb17825f6af92fa3213c620aa 100755 (executable)
@@ -325,6 +325,18 @@ test_expect_success 'two missing blank lines at end with --whitespace=fix' '
        test_cmp one expect
 '
 
+test_expect_success 'missing blank line at end, insert before end, --whitespace=fix' '
+       { echo a; echo; } >one &&
+       git add one &&
+       { echo b; echo a; echo; } >one &&
+       cp one expect &&
+       git diff -- one >patch &&
+       echo a >one &&
+       test_must_fail git apply patch &&
+       git apply --whitespace=fix patch &&
+       test_cmp one expect
+'
+
 test_expect_success 'shrink file with tons of missing blanks at end of file' '
        { echo a; echo b; echo c; } >one &&
        cp one no-blank-lines &&
index a01e55bf6b96246c33332e5112bcb3d6583402ac..cdb70b4b3356eeb45bb6e5ac62d1f82eb6b3ccdc 100755 (executable)
@@ -8,30 +8,93 @@ test_description='git shortlog
 
 . ./test-lib.sh
 
-echo 1 > a1
-git add a1
-tree=$(git write-tree)
-commit=$( (echo "Test"; echo) | git commit-tree $tree )
-git update-ref HEAD $commit
+test_expect_success 'setup' '
+       echo 1 >a1 &&
+       git add a1 &&
+       tree=$(git write-tree) &&
+       commit=$(printf "%s\n" "Test" "" | git commit-tree "$tree") &&
+       git update-ref HEAD "$commit" &&
+
+       echo 2 >a1 &&
+       git commit --quiet -m "This is a very, very long first line for the commit message to see if it is wrapped correctly" a1 &&
+
+       # test if the wrapping is still valid
+       # when replacing all is by treble clefs.
+       echo 3 >a1 &&
+       git commit --quiet -m "$(
+               echo "This is a very, very long first line for the commit message to see if it is wrapped correctly" |
+               sed "s/i/1234/g" |
+               tr 1234 "\360\235\204\236")" a1 &&
+
+       # now fsck up the utf8
+       git config i18n.commitencoding non-utf-8 &&
+       echo 4 >a1 &&
+       git commit --quiet -m "$(
+               echo "This is a very, very long first line for the commit message to see if it is wrapped correctly" |
+               sed "s/i/1234/g" |
+               tr 1234 "\370\235\204\236")" a1 &&
+
+       echo 5 >a1 &&
+       git commit --quiet -m "a                                                                12      34      56      78" a1
+
+       echo 6 >a1 &&
+       git commit --quiet -m "Commit by someone else" \
+               --author="Someone else <not!me>" a1 &&
+
+       cat >expect.template <<-\EOF
+       A U Thor (5):
+             SUBJECT
+             SUBJECT
+             SUBJECT
+             SUBJECT
+             SUBJECT
+
+       Someone else (1):
+             SUBJECT
+
+       EOF
+'
 
-echo 2 > a1
-git commit --quiet -m "This is a very, very long first line for the commit message to see if it is wrapped correctly" a1
+fuzz() {
+       file=$1 &&
+       sed "
+                       s/$_x40/OBJECT_NAME/g
+                       s/$_x05/OBJID/g
+                       s/^ \{6\}[CTa].*/      SUBJECT/g
+                       s/^ \{8\}[^ ].*/        CONTINUATION/g
+               " <"$file" >"$file.fuzzy" &&
+       sed "/CONTINUATION/ d" <"$file.fuzzy"
+}
 
-# test if the wrapping is still valid when replacing all i's by treble clefs.
-echo 3 > a1
-git commit --quiet -m "$(echo "This is a very, very long first line for the commit message to see if it is wrapped correctly" | sed "s/i/1234/g" | tr 1234 '\360\235\204\236')" a1
+test_expect_success 'default output format' '
+       git shortlog HEAD >log &&
+       fuzz log >log.predictable &&
+       test_cmp expect.template log.predictable
+'
 
-# now fsck up the utf8
-git config i18n.commitencoding non-utf-8
-echo 4 > a1
-git commit --quiet -m "$(echo "This is a very, very long first line for the commit message to see if it is wrapped correctly" | sed "s/i/1234/g" | tr 1234 '\370\235\204\236')" a1
+test_expect_success 'pretty format' '
+       sed s/SUBJECT/OBJECT_NAME/ expect.template >expect &&
+       git shortlog --format="%H" HEAD >log &&
+       fuzz log >log.predictable &&
+       test_cmp expect log.predictable
+'
 
-echo 5 > a1
-git commit --quiet -m "a                                                               12      34      56      78" a1
+test_expect_success '--abbrev' '
+       sed s/SUBJECT/OBJID/ expect.template >expect &&
+       git shortlog --format="%h" --abbrev=5 HEAD >log &&
+       fuzz log >log.predictable &&
+       test_cmp expect log.predictable
+'
 
-git shortlog -w HEAD > out
+test_expect_success 'output from user-defined format is re-wrapped' '
+       sed "s/SUBJECT/two lines/" expect.template >expect &&
+       git shortlog --format="two%nlines" HEAD >log &&
+       fuzz log >log.predictable &&
+       test_cmp expect log.predictable
+'
 
-cat > expect << EOF
+test_expect_success 'shortlog wrapping' '
+       cat >expect <<\EOF &&
 A U Thor (5):
       Test
       This is a very, very long first line for the commit message to see if
@@ -43,14 +106,19 @@ A U Thor (5):
       a                                                                12      34
          56    78
 
-EOF
-
-test_expect_success 'shortlog wrapping' 'test_cmp expect out'
+Someone else (1):
+      Commit by someone else
 
-git log HEAD > log
-GIT_DIR=non-existing git shortlog -w < log > out
+EOF
+       git shortlog -w HEAD >out &&
+       test_cmp expect out
+'
 
-test_expect_success 'shortlog from non-git directory' 'test_cmp expect out'
+test_expect_success 'shortlog from non-git directory' '
+       git log HEAD >log &&
+       GIT_DIR=non-existing git shortlog -w <log >out &&
+       test_cmp expect out
+'
 
 iconvfromutf8toiso88591() {
        printf "%s" "$*" | iconv -f UTF-8 -t ISO8859-1
index 2de98e6561607b87bceef66c20ad9055d04878c3..6a37a4d993df3fa4958a719fdfdb82f0dd2de623 100755 (executable)
@@ -528,7 +528,7 @@ test_expect_success 'push does not update local refs on failure' '
        mk_test heads/master &&
        mk_child child &&
        mkdir testrepo/.git/hooks &&
-       echo exit 1 >testrepo/.git/hooks/pre-receive &&
+       echo "#!/no/frobnication/today" >testrepo/.git/hooks/pre-receive &&
        chmod +x testrepo/.git/hooks/pre-receive &&
        (cd child &&
                git pull .. master
index 795dc2bcdf98e582dd2f05d901b791ab4225ce3b..17e1bdc5a81ce4802f5074ddb9c1996c68fc97be 100755 (executable)
@@ -34,8 +34,34 @@ test_expect_success 'setup remote repository' '
        mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
 '
 
-test_expect_success 'clone remote repository' '
+cat >exp <<EOF
+GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
+EOF
+test_expect_success 'no empty path components' '
+       # In the URL, add a trailing slash, and see if git appends yet another
+       # slash.
        cd "$ROOT_PATH" &&
+       git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone &&
+
+       sed -e "
+               s/^.* \"//
+               s/\"//
+               s/ [1-9][0-9]*\$//
+               s/^GET /GET  /
+       " >act <"$HTTPD_ROOT_PATH"/access.log &&
+
+       # Clear the log, so that it does not affect the "used receive-pack
+       # service" test which reads the log too.
+       #
+       # We do this before the actual comparison to ensure the log is cleared.
+       echo > "$HTTPD_ROOT_PATH"/access.log &&
+
+       test_cmp exp act
+'
+
+test_expect_success 'clone remote repository' '
+       rm -rf test_repo_clone &&
        git clone $HTTPD_URL/smart/test_repo.git test_repo_clone
 '
 
@@ -68,6 +94,7 @@ test_expect_success 'create and delete remote branch' '
 '
 
 cat >exp <<EOF
+
 GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
 POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
 GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
index 8cfce969bcdac6e2091e635dad9c58ca616e5c3b..fc675b50adfa945724cd7d17dbb6034df53426d3 100755 (executable)
@@ -55,12 +55,43 @@ test_expect_success 'http remote detects correct HEAD' '
 
 test_expect_success 'fetch packed objects' '
        cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
-       cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
-       git --bare repack &&
-       git --bare prune-packed &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
+        git --bare repack &&
+        git --bare prune-packed
+       ) &&
        git clone $HTTPD_URL/dumb/repo_pack.git
 '
 
+test_expect_success 'fetch notices corrupt pack' '
+       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
+        p=`ls objects/pack/pack-*.pack` &&
+        chmod u+w $p &&
+        printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
+       ) &&
+       mkdir repo_bad1.git &&
+       (cd repo_bad1.git &&
+        git --bare init &&
+        test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad1.git &&
+        test 0 = `ls objects/pack/pack-*.pack | wc -l`
+       )
+'
+
+test_expect_success 'fetch notices corrupt idx' '
+       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
+        p=`ls objects/pack/pack-*.idx` &&
+        chmod u+w $p &&
+        printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
+       ) &&
+       mkdir repo_bad2.git &&
+       (cd repo_bad2.git &&
+        git --bare init &&
+        test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad2.git &&
+        test 0 = `ls objects/pack | wc -l`
+       )
+'
+
 test_expect_success 'did not use upload-pack service' '
        grep '/git-upload-pack' <"$HTTPD_ROOT_PATH"/access.log >act
        : >exp
index 214756731baf199e6a50f9ab2380a8b4bfc0fb18..678cee502de54e5a9c18a43f114446d3392ec7f3 100755 (executable)
@@ -34,7 +34,7 @@ test_expect_success 'clone with excess parameters (2)' '
 test_expect_success 'output from clone' '
        rm -fr dst &&
        git clone -n "file://$(pwd)/src" dst >output &&
-       test $(grep Initialized output | wc -l) = 1
+       test $(grep Clon output | wc -l) = 1
 '
 
 test_expect_success 'clone does not keep pack' '
index a8f4419e610c4329cefc556684a7212f1405e104..ddc3dc52f497d05e20cf4034d544df6d08632935 100755 (executable)
@@ -30,4 +30,20 @@ test_expect_success 'tags can be excluded by rev-list options' '
 
 '
 
+test_expect_failure 'bundle --stdin' '
+
+       echo master | git bundle create stdin-bundle.bdl --stdin &&
+       git ls-remote stdin-bundle.bdl >output &&
+       grep master output
+
+'
+
+test_expect_failure 'bundle --stdin <rev-list options>' '
+
+       echo master | git bundle create hybrid-bundle.bdl --stdin tag &&
+       git ls-remote hybrid-bundle.bdl >output &&
+       grep master output
+
+'
+
 test_done
index adfaae8c5b453835eeeac3e3794950971e6dd6d8..8afbdd4de2146be763f7454af66a15986490fe60 100755 (executable)
@@ -12,7 +12,7 @@ test_expect_success 'setup' '
 
        git config pack.compression 0 &&
        git config pack.depth 0 &&
-       blobsize=$((20*1024*1024)) &&
+       blobsize=$((100*1024*1024)) &&
        blobcount=$((2*1024*1024*1024/$blobsize+1)) &&
        i=1 &&
        (while test $i -le $blobcount
@@ -36,9 +36,15 @@ test_expect_success 'setup' '
 
 '
 
-test_expect_success 'clone' '
+test_expect_success 'clone - bare' '
 
-       git clone --bare --no-hardlinks . clone
+       git clone --bare --no-hardlinks . clone-bare
+
+'
+
+test_expect_success 'clone - with worktree, file:// protocol' '
+
+       git clone file://. clone-wt
 
 '
 
diff --git a/t/t6000lib.sh b/t/t6000lib.sh
deleted file mode 100644 (file)
index 985d517..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-: included from 6002 and others
-
-[ -d .git/refs/tags ] || mkdir -p .git/refs/tags
-
-:> sed.script
-
-# Answer the sha1 has associated with the tag. The tag must exist in .git or .git/refs/tags
-tag()
-{
-       _tag=$1
-       [ -f .git/refs/tags/$_tag ] || error "tag: \"$_tag\" does not exist"
-       cat .git/refs/tags/$_tag
-}
-
-# Generate a commit using the text specified to make it unique and the tree
-# named by the tag specified.
-unique_commit()
-{
-       _text=$1
-        _tree=$2
-       shift 2
-       echo $_text | git commit-tree $(tag $_tree) "$@"
-}
-
-# Save the output of a command into the tag specified. Prepend
-# a substitution script for the tag onto the front of sed.script
-save_tag()
-{
-       _tag=$1
-       [ -n "$_tag" ] || error "usage: save_tag tag commit-args ..."
-       shift 1
-       "$@" >.git/refs/tags/$_tag
-
-        echo "s/$(tag $_tag)/$_tag/g" > sed.script.tmp
-       cat sed.script >> sed.script.tmp
-       rm sed.script
-       mv sed.script.tmp sed.script
-}
-
-# Replace unhelpful sha1 hashses with their symbolic equivalents
-entag()
-{
-       sed -f sed.script
-}
-
-# Execute a command after first saving, then setting the GIT_AUTHOR_EMAIL
-# tag to a specified value. Restore the original value on return.
-as_author()
-{
-       _author=$1
-       shift 1
-        _save=$GIT_AUTHOR_EMAIL
-
-       GIT_AUTHOR_EMAIL="$_author"
-       export GIT_AUTHOR_EMAIL
-       "$@"
-       if test -z "$_save"
-       then
-               unset GIT_AUTHOR_EMAIL
-       else
-               GIT_AUTHOR_EMAIL="$_save"
-               export GIT_AUTHOR_EMAIL
-       fi
-}
-
-commit_date()
-{
-        _commit=$1
-       git cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p"
-}
-
-on_committer_date()
-{
-    _date=$1
-    shift 1
-    GIT_COMMITTER_DATE="$_date"
-    export GIT_COMMITTER_DATE
-    "$@"
-    unset GIT_COMMITTER_DATE
-}
-
-# Execute a command and suppress any error output.
-hide_error()
-{
-       "$@" 2>/dev/null
-}
-
-check_output()
-{
-       _name=$1
-       shift 1
-       if eval "$*" | entag > $_name.actual
-       then
-               diff $_name.expected $_name.actual
-       else
-               return 1;
-       fi
-}
-
-# Turn a reasonable test description into a reasonable test name.
-# All alphanums translated into -'s which are then compressed and stripped
-# from front and back.
-name_from_description()
-{
-       perl -pe '
-               s/[^A-Za-z0-9.]/-/g;
-               s/-+/-/g;
-               s/-$//;
-               s/^-//;
-               y/A-Z/a-z/;
-       '
-}
-
-
-# Execute the test described by the first argument, by eval'ing
-# command line specified in the 2nd argument. Check the status code
-# is zero and that the output matches the stream read from
-# stdin.
-test_output_expect_success()
-{
-       _description=$1
-        _test=$2
-        [ $# -eq 2 ] || error "usage: test_output_expect_success description test <<EOF ... EOF"
-        _name=$(echo $_description | name_from_description)
-       cat > $_name.expected
-       test_expect_success "$_description" "check_output $_name \"$_test\""
-}
index b4e8fbaa5e6f2a56094c05ca505630669a51e101..fb07536a0f5b7e1000cf4945f55be3305df88e90 100755 (executable)
@@ -5,7 +5,7 @@
 test_description='Tests git rev-list --bisect functionality'
 
 . ./test-lib.sh
-. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions
+. "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions
 
 # usage: test_bisection max-diff bisect-option head ^prune...
 #
index 2c73f2da7b0a1f560bfd41376b587d1c91b18615..e4c52b0214b5028e8c3db035dc96ca3285e61506 100755 (executable)
@@ -6,7 +6,7 @@
 test_description='Tests git rev-list --topo-order functionality'
 
 . ./test-lib.sh
-. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions
+. "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions
 
 list_duplicates()
 {
index a49b7c5722e6cb675f771c31e4eec87262388548..e8fde5c19c16f3fa2305ed319edb3289f4f758b9 100755 (executable)
@@ -191,6 +191,31 @@ test_expect_success 'add LF before non-empty (2)' '
        grep "^$" actual
 '
 
+test_expect_success '--abbrev' '
+       echo SHORT SHORT SHORT >expect2 &&
+       echo LONG LONG LONG >expect3 &&
+       git log -1 --format="%h %h %h" HEAD >actual1 &&
+       git log -1 --abbrev=5 --format="%h %h %h" HEAD >actual2 &&
+       git log -1 --abbrev=5 --format="%H %H %H" HEAD >actual3 &&
+       sed -e "s/$_x40/LONG/g" -e "s/$_x05/SHORT/g" <actual2 >fuzzy2 &&
+       sed -e "s/$_x40/LONG/g" -e "s/$_x05/SHORT/g" <actual3 >fuzzy3 &&
+       test_cmp expect2 fuzzy2 &&
+       test_cmp expect3 fuzzy3 &&
+       ! test_cmp actual1 actual2
+'
+
+test_expect_success '%H is not affected by --abbrev-commit' '
+       git log -1 --format=%H --abbrev-commit --abbrev=20 HEAD >actual &&
+       len=$(wc -c <actual) &&
+       test $len = 41
+'
+
+test_expect_success '%h is not affected by --abbrev-commit' '
+       git log -1 --format=%h --abbrev-commit --abbrev=20 HEAD >actual &&
+       len=$(wc -c <actual) &&
+       test $len = 21
+'
+
 test_expect_success '"%h %gD: %gs" is same as git-reflog' '
        git reflog >expect &&
        git log -g --format="%h %gD: %gs" >actual &&
@@ -203,6 +228,12 @@ test_expect_success '"%h %gD: %gs" is same as git-reflog (with date)' '
        test_cmp expect actual
 '
 
+test_expect_success '"%h %gD: %gs" is same as git-reflog (with --abbrev)' '
+       git reflog --abbrev=13 --date=raw >expect &&
+       git log -g --abbrev=13 --format="%h %gD: %gs" --date=raw >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success '%gd shortens ref name' '
        echo "master@{0}" >expect.gd-short &&
        git log -g -1 --format=%gd refs/heads/master >actual.gd-short &&
index f105fab98e2d493ab489d345676101fc13096c22..e673c25e943f77430d7f61b0ab9e0b21e38e6915 100755 (executable)
@@ -6,7 +6,7 @@
 test_description='Test git rev-parse with different parent options'
 
 . ./test-lib.sh
-. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions
+. "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions
 
 date >path0
 git update-index --add path0
index 065deadc29eb3838f391ce758c4b188249dc87f9..876d1ab7430c2054ddc69bd3712ff769de52e774 100755 (executable)
@@ -8,7 +8,7 @@ test_description='test describe
  o----o----o----o----o----.    /
        \        A    c        /
         .------------o---o---o
-                     D   e
+                   D,R   e
 '
 . ./test-lib.sh
 
@@ -68,6 +68,8 @@ test_expect_success setup '
        echo D >another && git add another && git commit -m D &&
        test_tick &&
        git tag -a -m D D &&
+       test_tick &&
+       git tag -a -m R R &&
 
        test_tick &&
        echo DD >another && git commit -a -m another &&
@@ -89,10 +91,10 @@ test_expect_success setup '
 
 check_describe A-* HEAD
 check_describe A-* HEAD^
-check_describe D-* HEAD^^
+check_describe R-* HEAD^^
 check_describe A-* HEAD^^2
 check_describe B HEAD^^2^
-check_describe D-* HEAD^^^
+check_describe R-* HEAD^^^
 
 check_describe c-* --tags HEAD
 check_describe c-* --tags HEAD^
index d9202d5af5a179ca0b77d6509e05cbe6bf092ccc..3bc7a2a796bdb97702eaaf92e26b189cc4204c90 100755 (executable)
@@ -4,17 +4,24 @@ test_description='Test automatic use of a pager.'
 
 . ./test-lib.sh
 
-rm -f stdout_is_tty
+cleanup_fail() {
+       echo >&2 cleanup failed
+       (exit 1)
+}
+
 test_expect_success 'set up terminal for tests' '
+       rm -f stdout_is_tty ||
+       cleanup_fail &&
+
        if test -t 1
        then
-               : > stdout_is_tty
+               >stdout_is_tty
        elif
                test_have_prereq PERL &&
                "$PERL_PATH" "$TEST_DIRECTORY"/t7006/test-terminal.perl \
                        sh -c "test -t 1"
        then
-               : > test_terminal_works
+               >test_terminal_works
        fi
 '
 
@@ -32,53 +39,68 @@ else
        say no usable terminal, so skipping some tests
 fi
 
-unset GIT_PAGER GIT_PAGER_IN_USE
-git config --unset core.pager
-PAGER='cat > paginated.out'
-export PAGER
-
 test_expect_success 'setup' '
+       unset GIT_PAGER GIT_PAGER_IN_USE &&
+       test_might_fail git config --unset core.pager &&
+
+       PAGER="cat >paginated.out" &&
+       export PAGER &&
+
        test_commit initial
 '
 
-rm -f paginated.out
 test_expect_success TTY 'some commands use a pager' '
+       rm -f paginated.out ||
+       cleanup_fail &&
+
        test_terminal git log &&
        test -e paginated.out
 '
 
-rm -f paginated.out
 test_expect_success TTY 'some commands do not use a pager' '
+       rm -f paginated.out ||
+       cleanup_fail &&
+
        test_terminal git rev-list HEAD &&
        ! test -e paginated.out
 '
 
-rm -f paginated.out
 test_expect_success 'no pager when stdout is a pipe' '
+       rm -f paginated.out ||
+       cleanup_fail &&
+
        git log | cat &&
        ! test -e paginated.out
 '
 
-rm -f paginated.out
 test_expect_success 'no pager when stdout is a regular file' '
-       git log > file &&
+       rm -f paginated.out ||
+       cleanup_fail &&
+
+       git log >file &&
        ! test -e paginated.out
 '
 
-rm -f paginated.out
 test_expect_success TTY 'git --paginate rev-list uses a pager' '
+       rm -f paginated.out ||
+       cleanup_fail &&
+
        test_terminal git --paginate rev-list HEAD &&
        test -e paginated.out
 '
 
-rm -f file paginated.out
 test_expect_success 'no pager even with --paginate when stdout is a pipe' '
+       rm -f file paginated.out ||
+       cleanup_fail &&
+
        git --paginate log | cat &&
        ! test -e paginated.out
 '
 
-rm -f paginated.out
 test_expect_success TTY 'no pager with --no-pager' '
+       rm -f paginated.out ||
+       cleanup_fail &&
+
        test_terminal git --no-pager log &&
        ! test -e paginated.out
 '
@@ -86,88 +108,119 @@ test_expect_success TTY 'no pager with --no-pager' '
 # A colored commit log will begin with an appropriate ANSI escape
 # for the first color; the text "commit" comes later.
 colorful() {
-       read firstline < $1
+       read firstline <$1
        ! expr "$firstline" : "^[a-zA-Z]" >/dev/null
 }
 
-rm -f colorful.log colorless.log
 test_expect_success 'tests can detect color' '
-       git log --no-color > colorless.log &&
-       git log --color > colorful.log &&
+       rm -f colorful.log colorless.log ||
+       cleanup_fail &&
+
+       git log --no-color >colorless.log &&
+       git log --color >colorful.log &&
        ! colorful colorless.log &&
        colorful colorful.log
 '
 
-rm -f colorless.log
-git config color.ui auto
 test_expect_success 'no color when stdout is a regular file' '
-       git log > colorless.log &&
+       rm -f colorless.log &&
+       git config color.ui auto ||
+       cleanup_fail &&
+
+       git log >colorless.log &&
        ! colorful colorless.log
 '
 
-rm -f paginated.out
-git config color.ui auto
 test_expect_success TTY 'color when writing to a pager' '
-       TERM=vt100 test_terminal git log &&
+       rm -f paginated.out &&
+       git config color.ui auto ||
+       cleanup_fail &&
+
+       (
+               TERM=vt100 &&
+               export TERM &&
+               test_terminal git log
+       ) &&
        colorful paginated.out
 '
 
-rm -f colorful.log
-git config color.ui auto
 test_expect_success 'color when writing to a file intended for a pager' '
-       TERM=vt100 GIT_PAGER_IN_USE=true git log > colorful.log &&
+       rm -f colorful.log &&
+       git config color.ui auto ||
+       cleanup_fail &&
+
+       (
+               TERM=vt100 &&
+               GIT_PAGER_IN_USE=true &&
+               export TERM GIT_PAGER_IN_USE &&
+               git log >colorful.log
+       ) &&
        colorful colorful.log
 '
 
-unset PAGER GIT_PAGER
-git config --unset core.pager
 test_expect_success 'determine default pager' '
+       unset PAGER GIT_PAGER &&
+       test_might_fail git config --unset core.pager ||
+       cleanup_fail &&
+
        less=$(git var GIT_PAGER) &&
        test -n "$less"
 '
 
-if expr "$less" : '^[a-z]*$' > /dev/null && test_have_prereq TTY
+if expr "$less" : '^[a-z][a-z]*$' >/dev/null && test_have_prereq TTY
 then
        test_set_prereq SIMPLEPAGER
 fi
 
-unset PAGER GIT_PAGER
-git config --unset core.pager
-rm -f default_pager_used
 test_expect_success SIMPLEPAGER 'default pager is used by default' '
-       cat > $less <<-EOF &&
-       #!$SHELL_PATH
-       wc > default_pager_used
+       unset PAGER GIT_PAGER &&
+       test_might_fail git config --unset core.pager &&
+       rm -f default_pager_used ||
+       cleanup_fail &&
+
+       cat >$less <<-\EOF &&
+       #!/bin/sh
+       wc >default_pager_used
        EOF
        chmod +x $less &&
-       PATH=.:$PATH test_terminal git log &&
+       (
+               PATH=.:$PATH &&
+               export PATH &&
+               test_terminal git log
+       ) &&
        test -e default_pager_used
 '
 
-unset GIT_PAGER
-git config --unset core.pager
-rm -f PAGER_used
 test_expect_success TTY 'PAGER overrides default pager' '
-       PAGER="wc > PAGER_used" &&
+       unset GIT_PAGER &&
+       test_might_fail git config --unset core.pager &&
+       rm -f PAGER_used ||
+       cleanup_fail &&
+
+       PAGER="wc >PAGER_used" &&
        export PAGER &&
        test_terminal git log &&
        test -e PAGER_used
 '
 
-unset GIT_PAGER
-rm -f core.pager_used
 test_expect_success TTY 'core.pager overrides PAGER' '
+       unset GIT_PAGER &&
+       rm -f core.pager_used ||
+       cleanup_fail &&
+
        PAGER=wc &&
        export PAGER &&
-       git config core.pager "wc > core.pager_used" &&
+       git config core.pager "wc >core.pager_used" &&
        test_terminal git log &&
        test -e core.pager_used
 '
 
-rm -f GIT_PAGER_used
 test_expect_success TTY 'GIT_PAGER overrides core.pager' '
+       rm -f GIT_PAGER_used ||
+       cleanup_fail &&
+
        git config core.pager wc &&
-       GIT_PAGER="wc > GIT_PAGER_used" &&
+       GIT_PAGER="wc >GIT_PAGER_used" &&
        export GIT_PAGER &&
        test_terminal git log &&
        test -e GIT_PAGER_used
index 844fb43c6db1ae4e9b8a3cda6156af359e9f639e..95044668ee182fc2c1091fba7680e0576f7854bd 100755 (executable)
@@ -35,7 +35,7 @@ test_expect_success 'partial' '
 
 '
 
-test_expect_success 'partial modification in a subdirecotry' '
+test_expect_success 'partial modification in a subdirectory' '
 
        test_tick &&
        git commit -m "partial commit to subdirectory" not &&
index 556d0faa77e027c8a18e213088fa6bbc5d7e7af5..008d5711b818a315136290c141c830cdf5af80a0 100755 (executable)
@@ -68,6 +68,34 @@ test_expect_success 'status (2)' '
 
 '
 
+cat >expect <<\EOF
+# On branch master
+# Changes to be committed:
+#      new file:   dir2/added
+#
+# Changed but not updated:
+#      modified:   dir1/modified
+#
+# Untracked files:
+#      dir1/untracked
+#      dir2/modified
+#      dir2/untracked
+#      expect
+#      output
+#      untracked
+EOF
+
+git config advice.statusHints false
+
+test_expect_success 'status (advice.statusHints false)' '
+
+       git status >output &&
+       test_cmp expect output
+
+'
+
+git config --unset advice.statusHints
+
 cat >expect <<\EOF
  M dir1/modified
 A  dir2/added
@@ -115,6 +143,23 @@ test_expect_success 'status (status.showUntrackedFiles no)' '
        test_cmp expect output
 '
 
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+#      new file:   dir2/added
+#
+# Changed but not updated:
+#      modified:   dir1/modified
+#
+# Untracked files not listed
+EOF
+git config advice.statusHints false
+test_expect_success 'status -uno (advice.statusHints false)' '
+       git status -uno >output &&
+       test_cmp expect output
+'
+git config --unset advice.statusHints
+
 cat >expect << EOF
  M dir1/modified
 A  dir2/added
@@ -496,6 +541,16 @@ test_expect_success 'dry-run of partial commit excluding new file in index' '
        test_cmp expect output
 '
 
+cat >expect <<EOF
+:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M     dir1/modified
+EOF
+test_expect_success 'status refreshes the index' '
+       touch dir2/added &&
+       git status &&
+       git diff-files >output &&
+       test_cmp expect output
+'
+
 test_expect_success 'setup status submodule summary' '
        test_create_repo sm && (
                cd sm &&
@@ -693,4 +748,19 @@ test_expect_success 'commit --dry-run submodule summary (--amend)' '
        test_cmp expect output
 '
 
+test_expect_success POSIXPERM 'status succeeds in a read-only repository' '
+       (
+               chmod a-w .git &&
+               # make dir1/tracked stat-dirty
+               >dir1/tracked1 && mv -f dir1/tracked1 dir1/tracked &&
+               git status -s >output &&
+               ! grep dir1/tracked output &&
+               # make sure "status" succeeded without writing index out
+               git diff-files | grep dir1/tracked
+       )
+       status=$?
+       chmod 775 .git
+       (exit $status)
+'
+
 test_done
index c582964b0d26bedcc69b4f7cc787c4deccfab6b9..9bfa14be7f1c3935013d04318eeaecc68b4ef88c 100644 (file)
@@ -2,6 +2,18 @@
 #
 # Copyright (c) 2005 Junio C Hamano
 #
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see http://www.gnu.org/licenses/ .
 
 # if --tee was passed, write the output not only to the terminal, but
 # additionally to the file test-results/$BASENAME.out, too.
@@ -354,8 +366,10 @@ test_debug () {
 }
 
 test_run_ () {
+       test_cleanup=:
        eval >&3 2>&4 "$1"
-       eval_ret="$?"
+       eval_ret=$?
+       eval >&3 2>&4 "$test_cleanup"
        return 0
 }
 
@@ -516,6 +530,22 @@ test_must_fail () {
        test $? -gt 0 -a $? -le 129 -o $? -gt 192
 }
 
+# Similar to test_must_fail, but tolerates success, too.  This is
+# meant to be used in contexts like:
+#
+#      test_expect_success 'some command works without configuration' '
+#              test_might_fail git config --unset all.configuration &&
+#              do something
+#      '
+#
+# Writing "git config --unset all.configuration || :" would be wrong,
+# because we want to notice if it fails due to segv.
+
+test_might_fail () {
+       "$@"
+       test $? -ge 0 -a $? -le 129 -o $? -gt 192
+}
+
 # test_cmp is a helper function to compare actual and expected output.
 # You can use it like:
 #
@@ -533,6 +563,31 @@ test_cmp() {
        $GIT_TEST_CMP "$@"
 }
 
+# This function can be used to schedule some commands to be run
+# unconditionally at the end of the test to restore sanity:
+#
+#      test_expect_success 'test core.capslock' '
+#              git config core.capslock true &&
+#              test_when_finished "git config --unset core.capslock" &&
+#              hello world
+#      '
+#
+# That would be roughly equivalent to
+#
+#      test_expect_success 'test core.capslock' '
+#              git config core.capslock true &&
+#              hello world
+#              git config --unset core.capslock
+#      '
+#
+# except that the greeting and config --unset must both succeed for
+# the test to pass.
+
+test_when_finished () {
+       test_cleanup="{ $*
+               } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup"
+}
+
 # Most tests can use the created repository, but some may need to create more.
 # Usage: test_create_repo <directory>
 test_create_repo () {
diff --git a/tag.c b/tag.c
index 4470d2bf78e1fbb00d00e487f41daa4373cf48e1..85607c219e25d63b0d1f3344649104c60f5b96e2 100644 (file)
--- a/tag.c
+++ b/tag.c
@@ -36,43 +36,50 @@ struct tag *lookup_tag(const unsigned char *sha1)
         return (struct tag *) obj;
 }
 
+static unsigned long parse_tag_date(const char *buf, const char *tail)
+{
+       const char *dateptr;
+
+       while (buf < tail && *buf++ != '>')
+               /* nada */;
+       if (buf >= tail)
+               return 0;
+       dateptr = buf;
+       while (buf < tail && *buf++ != '\n')
+               /* nada */;
+       if (buf >= tail)
+               return 0;
+       /* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */
+       return strtoul(dateptr, NULL, 10);
+}
+
 int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
 {
-       int typelen, taglen;
        unsigned char sha1[20];
-       const char *type_line, *tag_line, *sig_line;
        char type[20];
-       const char *start = data;
+       const char *bufptr = data;
+       const char *tail = bufptr + size;
+       const char *nl;
 
-        if (item->object.parsed)
-                return 0;
-        item->object.parsed = 1;
+       if (item->object.parsed)
+               return 0;
+       item->object.parsed = 1;
 
        if (size < 64)
                return -1;
-       if (memcmp("object ", data, 7) || get_sha1_hex((char *) data + 7, sha1))
+       if (memcmp("object ", bufptr, 7) || get_sha1_hex(bufptr + 7, sha1) || bufptr[47] != '\n')
                return -1;
+       bufptr += 48; /* "object " + sha1 + "\n" */
 
-       type_line = (char *) data + 48;
-       if (memcmp("\ntype ", type_line-1, 6))
+       if (prefixcmp(bufptr, "type "))
                return -1;
-
-       tag_line = memchr(type_line, '\n', size - (type_line - start));
-       if (!tag_line || memcmp("tag ", ++tag_line, 4))
+       bufptr += 5;
+       nl = memchr(bufptr, '\n', tail - bufptr);
+       if (!nl || sizeof(type) <= (nl - bufptr))
                return -1;
-
-       sig_line = memchr(tag_line, '\n', size - (tag_line - start));
-       if (!sig_line)
-               return -1;
-       sig_line++;
-
-       typelen = tag_line - type_line - strlen("type \n");
-       if (typelen >= 20)
-               return -1;
-       memcpy(type, type_line + 5, typelen);
-       type[typelen] = '\0';
-       taglen = sig_line - tag_line - strlen("tag \n");
-       item->tag = xmemdupz(tag_line + 4, taglen);
+       strncpy(type, bufptr, nl - bufptr);
+       type[nl - bufptr] = '\0';
+       bufptr = nl + 1;
 
        if (!strcmp(type, blob_type)) {
                item->tagged = &lookup_blob(sha1)->object;
@@ -87,6 +94,20 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
                item->tagged = NULL;
        }
 
+       if (prefixcmp(bufptr, "tag "))
+               return -1;
+       bufptr += 4;
+       nl = memchr(bufptr, '\n', tail - bufptr);
+       if (!nl)
+               return -1;
+       item->tag = xmemdupz(bufptr, nl - bufptr);
+       bufptr = nl + 1;
+
+       if (!prefixcmp(bufptr, "tagger "))
+               item->date = parse_tag_date(bufptr, tail);
+       else
+               item->date = 0;
+
        return 0;
 }
 
diff --git a/tag.h b/tag.h
index 7a0cb0070d46ba8c49d71029dc0704188805ea62..47662724a6d7d07eeeacd5c8528d94d750ecf878 100644 (file)
--- a/tag.h
+++ b/tag.h
@@ -9,7 +9,7 @@ struct tag {
        struct object object;
        struct object *tagged;
        char *tag;
-       char *signature; /* not actually implemented */
+       unsigned long date;
 };
 
 extern struct tag *lookup_tag(const unsigned char *sha1);
index 4f9c829c2df319e386b6b5d4f5c23818cc21c979..589f838f82b568195232ea81346d0049261b86b1 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include <pthread.h>
 
 #if defined(hpux) || defined(__hpux) || defined(_hpux)
 #  include <sys/pstat.h>
@@ -43,3 +44,18 @@ int online_cpus(void)
 
        return 1;
 }
+
+int init_recursive_mutex(pthread_mutex_t *m)
+{
+       pthread_mutexattr_t a;
+       int ret;
+
+       ret = pthread_mutexattr_init(&a);
+       if (!ret) {
+               ret = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE);
+               if (!ret)
+                       ret = pthread_mutex_init(m, &a);
+               pthread_mutexattr_destroy(&a);
+       }
+       return ret;
+}
index cce4b77bd6452e2ec589d8c0dc0e8156352dd67b..1727a03333b80f2a01ca029162a4b511480a86e8 100644 (file)
@@ -2,5 +2,6 @@
 #define THREAD_COMPAT_H
 
 extern int online_cpus(void);
+extern int init_recursive_mutex(pthread_mutex_t*);
 
 #endif /* THREAD_COMPAT_H */
index 75f54cac97f62ddaad736c2cd582cc6cdeaaebfa..1a8030ced0b7923d44d6b891133458e98ce969c7 100644 (file)
@@ -862,7 +862,7 @@ static int verify_uptodate_1(struct cache_entry *ce,
 {
        struct stat st;
 
-       if (o->index_only || (!ce_skip_worktree(ce) && (o->reset || ce_uptodate(ce))))
+       if (o->index_only || (!((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) && (o->reset || ce_uptodate(ce))))
                return 0;
 
        if (!lstat(ce->name, &st)) {
index 9c71b21242773f52ca560d7e5e5e52123674d334..62edb57338ccd1ae56b86649ec07d88c251576da 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -3,11 +3,23 @@
  */
 #include "cache.h"
 
+static void try_to_free_builtin(size_t size)
+{
+       release_pack_memory(size, -1);
+}
+
+static void (*try_to_free_routine)(size_t size) = try_to_free_builtin;
+
+void set_try_to_free_routine(void (*routine)(size_t))
+{
+       try_to_free_routine = (routine) ? routine : try_to_free_builtin;
+}
+
 char *xstrdup(const char *str)
 {
        char *ret = strdup(str);
        if (!ret) {
-               release_pack_memory(strlen(str) + 1, -1);
+               try_to_free_routine(strlen(str) + 1);
                ret = strdup(str);
                if (!ret)
                        die("Out of memory, strdup failed");
@@ -21,7 +33,7 @@ void *xmalloc(size_t size)
        if (!ret && !size)
                ret = malloc(1);
        if (!ret) {
-               release_pack_memory(size, -1);
+               try_to_free_routine(size);
                ret = malloc(size);
                if (!ret && !size)
                        ret = malloc(1);
@@ -67,7 +79,7 @@ void *xrealloc(void *ptr, size_t size)
        if (!ret && !size)
                ret = realloc(ptr, 1);
        if (!ret) {
-               release_pack_memory(size, -1);
+               try_to_free_routine(size);
                ret = realloc(ptr, size);
                if (!ret && !size)
                        ret = realloc(ptr, 1);
@@ -83,7 +95,7 @@ void *xcalloc(size_t nmemb, size_t size)
        if (!ret && (!nmemb || !size))
                ret = calloc(1, 1);
        if (!ret) {
-               release_pack_memory(nmemb * size, -1);
+               try_to_free_routine(nmemb * size);
                ret = calloc(nmemb, size);
                if (!ret && (!nmemb || !size))
                        ret = calloc(1, 1);
index 8ca59a2d2abec0c9c4629cd4ae7340fcd79a0c7e..d44486c826ee46d258e88c5013d038243aad2756 100644 (file)
@@ -625,7 +625,9 @@ void wt_status_print(struct wt_status *s)
        if (s->show_untracked_files)
                wt_status_print_untracked(s);
        else if (s->commitable)
-                fprintf(s->fp, "# Untracked files not listed (use -u option to show untracked files)\n");
+               fprintf(s->fp, "# Untracked files not listed%s\n",
+                       advice_status_hints
+                       ? " (use -u option to show untracked files)" : "");
 
        if (s->verbose)
                wt_status_print_verbose(s);
@@ -635,15 +637,22 @@ void wt_status_print(struct wt_status *s)
                else if (s->nowarn)
                        ; /* nothing */
                else if (s->workdir_dirty)
-                       printf("no changes added to commit (use \"git add\" and/or \"git commit -a\")\n");
+                       printf("no changes added to commit%s\n",
+                               advice_status_hints
+                               ? " (use \"git add\" and/or \"git commit -a\")" : "");
                else if (s->untracked.nr)
-                       printf("nothing added to commit but untracked files present (use \"git add\" to track)\n");
+                       printf("nothing added to commit but untracked files present%s\n",
+                               advice_status_hints
+                               ? " (use \"git add\" to track)" : "");
                else if (s->is_initial)
-                       printf("nothing to commit (create/copy files and use \"git add\" to track)\n");
+                       printf("nothing to commit%s\n", advice_status_hints
+                               ? " (create/copy files and use \"git add\" to track)" : "");
                else if (!s->show_untracked_files)
-                       printf("nothing to commit (use -u to show untracked files)\n");
+                       printf("nothing to commit%s\n", advice_status_hints
+                               ? " (use -u to show untracked files)" : "");
                else
-                       printf("nothing to commit (working directory clean)\n");
+                       printf("nothing to commit%s\n", advice_status_hints
+                               ? " (working directory clean)" : "");
        }
 }
 
index ca5e3fbae8184e7114413ec65fe815e01ad6b2a8..cd2285de1cb1faa9f7c6c97dd22210f20bb046a3 100644 (file)
@@ -138,19 +138,20 @@ int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t co
 
 int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
                  xdiff_emit_consume_fn fn, void *consume_callback_data,
-                 xpparam_t const *xpp,
-                 xdemitconf_t const *xecfg, xdemitcb_t *xecb)
+                 xpparam_t const *xpp, xdemitconf_t const *xecfg)
 {
        int ret;
        struct xdiff_emit_state state;
+       xdemitcb_t ecb;
 
        memset(&state, 0, sizeof(state));
        state.consume = fn;
        state.consume_callback_data = consume_callback_data;
-       xecb->outf = xdiff_outf;
-       xecb->priv = &state;
+       memset(&ecb, 0, sizeof(ecb));
+       ecb.outf = xdiff_outf;
+       ecb.priv = &state;
        strbuf_init(&state.remainder, 0);
-       ret = xdi_diff(mf1, mf2, xpp, xecfg, xecb);
+       ret = xdi_diff(mf1, mf2, xpp, xecfg, &ecb);
        strbuf_release(&state.remainder);
        return ret;
 }
index abba70c16bb31fae0df999241830d0c8df8bfbb3..49d1116fc34f536ab9358313522a25564dd1f6c3 100644 (file)
@@ -9,8 +9,7 @@ typedef void (*xdiff_emit_hunk_consume_fn)(void *, long, long, long);
 int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb);
 int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
                  xdiff_emit_consume_fn fn, void *consume_callback_data,
-                 xpparam_t const *xpp,
-                 xdemitconf_t const *xecfg, xdemitcb_t *xecb);
+                 xpparam_t const *xpp, xdemitconf_t const *xecfg);
 int xdi_diff_hunks(mmfile_t *mf1, mmfile_t *mf2,
                   xdiff_emit_hunk_consume_fn fn, void *consume_callback_data,
                   xpparam_t const *xpp, xdemitconf_t *xecfg);
index 16dd9acd37b431f1e439d9ab051fe2436c54b45c..6d6fc1bc5e01be7305ec5101f43645a1dce69bd3 100644 (file)
@@ -152,7 +152,6 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
        int marker1_size = (name1 ? strlen(name1) + 1 : 0);
        int marker2_size = (name2 ? strlen(name2) + 1 : 0);
        int marker3_size = (name3 ? strlen(name3) + 1 : 0);
-       int j;
 
        if (marker_size <= 0)
                marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
@@ -164,8 +163,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
        if (!dest) {
                size += marker_size + 1 + marker1_size;
        } else {
-               for (j = 0; j < marker_size; j++)
-                       dest[size++] = '<';
+               memset(dest + size, '<', marker_size);
+               size += marker_size;
                if (marker1_size) {
                        dest[size] = ' ';
                        memcpy(dest + size + 1, name1, marker1_size - 1);
@@ -183,8 +182,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
                if (!dest) {
                        size += marker_size + 1 + marker3_size;
                } else {
-                       for (j = 0; j < marker_size; j++)
-                               dest[size++] = '|';
+                       memset(dest + size, '|', marker_size);
+                       size += marker_size;
                        if (marker3_size) {
                                dest[size] = ' ';
                                memcpy(dest + size + 1, name3, marker3_size - 1);
@@ -199,8 +198,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
        if (!dest) {
                size += marker_size + 1;
        } else {
-               for (j = 0; j < marker_size; j++)
-                       dest[size++] = '=';
+               memset(dest + size, '=', marker_size);
+               size += marker_size;
                dest[size++] = '\n';
        }
 
@@ -210,8 +209,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
        if (!dest) {
                size += marker_size + 1 + marker2_size;
        } else {
-               for (j = 0; j < marker_size; j++)
-                       dest[size++] = '>';
+               memset(dest + size, '>', marker_size);
+               size += marker_size;
                if (marker2_size) {
                        dest[size] = ' ';
                        memcpy(dest + size + 1, name2, marker2_size - 1);