Merge branch 'eb/core-eol'
authorJunio C Hamano <gitster@pobox.com>
Mon, 21 Jun 2010 13:02:49 +0000 (06:02 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 21 Jun 2010 13:02:49 +0000 (06:02 -0700)
* eb/core-eol:
Add "core.eol" config variable
Rename the "crlf" attribute "text"
Add per-repository eol normalization
Add tests for per-repository eol normalization

Conflicts:
Documentation/config.txt
Makefile

1  2 
Documentation/config.txt
Documentation/git-cvsserver.txt
Documentation/gitattributes.txt
Makefile
attr.c
cache.h
config.c
convert.c
environment.c
git-cvsserver.perl
diff --combined Documentation/config.txt
index 7afd0a333f5e67fcfcc5c5277c3a871f6825ea83,5cb334c2b9bd2e164345e4e80790526ae908982d..9f1c785b7e5e5fdebeaf6fa0425659697c51c19b
@@@ -138,11 -138,6 +138,11 @@@ advice.*:
                Advice on how to set your identity configuration when
                your information is guessed from the system username and
                domain name. Default: true.
 +
 +      detachedHead::
 +              Advice shown when you used linkgit::git-checkout[1] to
 +              move to the detach HEAD state, to instruct how to create
 +              a local branch after the fact.  Default: true.
  --
  
  core.fileMode::
@@@ -196,20 -191,17 +196,17 @@@ core.quotepath:
        quoted without `-z` regardless of the setting of this
        variable.
  
- core.autocrlf::
-       If true, makes git convert `CRLF` at the end of lines in text files to
-       `LF` when reading from the work tree, and convert in reverse when
-       writing to the work tree.  The variable can be set to
-       'input', in which case the conversion happens only while
-       reading from the work tree but files are written out to the work
-       tree with `LF` at the end of lines.  A file is considered
-       "text" (i.e. be subjected to the autocrlf mechanism) based on
-       the file's `crlf` attribute, or if `crlf` is unspecified,
-       based on the file's contents.  See linkgit:gitattributes[5].
+ core.eol::
+       Sets the line ending type to use in the working directory for
+       files that have the `text` property set.  Alternatives are
+       'lf', 'crlf' and 'native', which uses the platform's native
+       line ending.  The default value is `native`.  See
+       linkgit:gitattributes[5] for more information on end-of-line
+       conversion.
  
  core.safecrlf::
-       If true, makes git check if converting `CRLF` as controlled by
-       `core.autocrlf` is reversible.  Git will verify if a command
+       If true, makes git check if converting `CRLF` is reversible when
+       end-of-line conversion is active.  Git will verify if a command
        modifies a file in the work tree either directly or indirectly.
        For example, committing a file followed by checking out the
        same file should yield the original file in the work tree.  If
        irreversible conversion but continue the operation.
  +
  CRLF conversion bears a slight chance of corrupting data.
autocrlf=true will convert CRLF to LF during commit and LF to
When it is enabled, git will convert CRLF to LF during commit and LF to
  CRLF during checkout.  A file that contains a mixture of LF and
  CRLF before the commit cannot be recreated by git.  For text
  files this is the right thing to do: it corrects line endings
@@@ -243,15 -235,25 +240,25 @@@ converting CRLFs corrupts data
  +
  Note, this safety check does not mean that a checkout will generate a
  file identical to the original file for a different setting of
- `core.autocrlf`, but only for the current one.  For example, a text
- file with `LF` would be accepted with `core.autocrlf=input` and could
later be checked out with `core.autocrlf=true`, in which case the
+ `core.eol` and `core.autocrlf`, but only for the current one.  For
+ example, a text file with `LF` would be accepted with `core.eol=lf`
and could later be checked out with `core.eol=crlf`, in which case the
  resulting file would contain `CRLF`, although the original file
  contained `LF`.  However, in both work trees the line endings would be
  consistent, that is either all `LF` or all `CRLF`, but never mixed.  A
  file with mixed line endings would be reported by the `core.safecrlf`
  mechanism.
  
+ core.autocrlf::
+       Setting this variable to "true" is almost the same as setting
+       the `text` attribute to "auto" on all files except that text
+       files are not guaranteed to be normalized: files that contain
+       `CRLF` in the repository will not be touched.  Use this
+       setting if you want to have `CRLF` line endings in your
+       working directory even though the repository does not have
+       normalized line endings.  This variable can be set to 'input',
+       in which case no output conversion is performed.
  core.symlinks::
        If false, symbolic links are checked out as small plain files that
        contain the link text. linkgit:git-update-index[1] and
@@@ -481,8 -483,6 +488,8 @@@ core.whitespace:
    error (enabled by default).
  * `indent-with-non-tab` treats a line that is indented with 8 or more
    space characters as an error (not enabled by default).
 +* `tab-in-indent` treats a tab character in the initial indent part of
 +  the line as an error (not enabled by default).
  * `blank-at-eof` treats blank lines added at the end of file as an error
    (enabled by default).
  * `trailing-space` is a short-hand to cover both `blank-at-eol` and
@@@ -520,12 -520,16 +527,12 @@@ check that makes sure that existing obj
  
  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.
 -+
 -If such a file exists in the given ref, the referenced blob is read, and
 -appended to the commit message, separated by a "Notes:" line.  If the
 -given ref itself does not exist, it is not an error, but means that no
 -notes should be printed.
 +      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.
  +
 -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
@@@ -553,13 -557,6 +560,13 @@@ it will be treated as a shell command
  executed from the top-level directory of a repository, which may
  not necessarily be the current directory.
  
 +am.keepcr::
 +      If true, git-am will call git-mailsplit for patches in mbox format
 +      with parameter '--keep-cr'. In this case git-mailsplit will
 +      not remove `\r` from lines ending with `\r\n`. Can be overrriden
 +      by giving '--no-keep-cr' from the command line.
 +      See linkgit:git-am[1], linkgit:git-mailsplit[1].
 +
  apply.ignorewhitespace::
        When set to 'change', tells 'git apply' to ignore changes in
        whitespace, in the same way as the '--ignore-space-change'
@@@ -688,29 -685,11 +695,29 @@@ color.grep:
        `never`), never.  When set to `true` or `auto`, use color only
        when the output is written to the terminal.  Defaults to `false`.
  
 -color.grep.match::
 -      Use customized color for matches.  The value of this variable
 -      may be specified as in color.branch.<slot>.  It is passed using
 -      the environment variables 'GREP_COLOR' and 'GREP_COLORS' when
 -      calling an external 'grep'.
 +color.grep.<slot>::
 +      Use customized color for grep colorization.  `<slot>` specifies which
 +      part of the line to use the specified color, and is one of
 ++
 +--
 +`context`;;
 +      non-matching text in context lines (when using `-A`, `-B`, or `-C`)
 +`filename`;;
 +      filename prefix (when not using `-h`)
 +`function`;;
 +      function name lines (when using `-p`)
 +`linenumber`;;
 +      line number prefix (when using `-n`)
 +`match`;;
 +      matching text
 +`selected`;;
 +      non-matching text in selected lines
 +`separator`;;
 +      separators between fields on a line (`:`, `-`, and `=`)
 +      and between hunks (`--`)
 +--
 ++
 +The values of these variables may be specified as in color.branch.<slot>.
  
  color.interactive::
        When set to `always`, always use colors for interactive prompts
@@@ -792,8 -771,6 +799,8 @@@ diff.mnemonicprefix:
        standard "a/" and "b/" depending on what is being compared.  When
        this configuration is in effect, reverse diff output also swaps
        the order of the prefixes:
 +diff.noprefix::
 +      If set, 'git diff' does not show any source or destination prefix.
  `git diff`;;
        compares the (i)ndex and the (w)ork tree;
  `git diff HEAD`;;
@@@ -912,7 -889,7 +919,7 @@@ format.signoff:
  gc.aggressiveWindow::
        The window size parameter used in the delta compression
        algorithm used by 'git gc --aggressive'.  This defaults
 -      to 10.
 +      to 250.
  
  gc.auto::
        When there are approximately more than this many loose
@@@ -942,19 -919,13 +949,19 @@@ gc.pruneexpire:
        unreachable objects immediately.
  
  gc.reflogexpire::
 +gc.<pattern>.reflogexpire::
        'git reflog expire' removes reflog entries older than
 -      this time; defaults to 90 days.
 +      this time; defaults to 90 days.  With "<pattern>" (e.g.
 +      "refs/stash") in the middle the setting applies only to
 +      the refs that match the <pattern>.
  
  gc.reflogexpireunreachable::
 +gc.<ref>.reflogexpireunreachable::
        'git reflog expire' removes reflog entries older than
        this time and are not reachable from the current tip;
 -      defaults to 30 days.
 +      defaults to 30 days.  With "<pattern>" (e.g. "refs/stash")
 +      in the middle, the setting applies only to the refs that
 +      match the <pattern>.
  
  gc.rerereresolved::
        Records of conflicted merge you resolved earlier are
@@@ -979,13 -950,15 +986,15 @@@ gitcvs.logfile:
        various stuff. See linkgit:git-cvsserver[1].
  
  gitcvs.usecrlfattr::
-       If true, the server will look up the `crlf` attribute for
-       files to determine the '-k' modes to use. If `crlf` is set,
-       the '-k' mode will be left blank, so cvs clients will
-       treat it as text. If `crlf` is explicitly unset, the file
+       If true, the server will look up the end-of-line conversion
+       attributes for files to determine the '-k' modes to use. If
+       the attributes force git to treat a file as text,
+       the '-k' mode will be left blank so cvs clients will
+       treat it as text. If they suppress text conversion, the file
        will be set with '-kb' mode, which suppresses any newline munging
-       the client might otherwise do. If `crlf` is not specified,
-       then 'gitcvs.allbinary' is used. See linkgit:gitattributes[5].
+       the client might otherwise do. If the attributes do not allow
+       the file type to be determined, then 'gitcvs.allbinary' is
+       used. See linkgit:gitattributes[5].
  
  gitcvs.allbinary::
        This is used if 'gitcvs.usecrlfattr' does not resolve
@@@ -1236,10 -1209,6 +1245,10 @@@ imap:
        The configuration variables in the 'imap' section are described
        in linkgit:git-imap-send[1].
  
 +init.templatedir::
 +      Specify the directory from which templates will be copied.
 +      (See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
 +
  instaweb.browser::
        Specify the program that will be used to browse your working
        repository in gitweb. See linkgit:git-instaweb[1].
@@@ -1272,13 -1241,6 +1281,13 @@@ log.date:
        following alternatives: {relative,local,default,iso,rfc,short}.
        See linkgit:git-log[1].
  
 +log.decorate::
 +      Print out the ref names of any commits that are shown by the log
 +      command. If 'short' is specified, the ref name prefixes 'refs/heads/',
 +      'refs/tags/' and 'refs/remotes/' will not be printed. If 'full' is
 +      specified, the full ref name (including prefix) will be printed.
 +      This is the same as the log commands '--decorate' option.
 +
  log.showroot::
        If true, the initial commit will be shown as a big creation event.
        This is equivalent to a diff against an empty tree.
@@@ -1347,53 -1309,6 +1356,53 @@@ mergetool.keepTemporaries:
  mergetool.prompt::
        Prompt before each invocation of the merge resolution program.
  
 +notes.displayRef::
 +      The (fully qualified) refname from which to show notes when
 +      showing commit messages.  The value of this variable can be set
 +      to a glob, in which case notes from all matching refs will be
 +      shown.  You may also specify this configuration variable
 +      several 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 overridden with the `GIT_NOTES_DISPLAY_REF`
 +environment variable, which must be a colon separated list of refs or
 +globs.
 ++
 +The effective value of "core.notesRef" (possibly overridden by
 +GIT_NOTES_REF) is also implicitly added to the list of refs to be
 +displayed.
 +
 +notes.rewrite.<command>::
 +      When rewriting commits with <command> (currently `amend` or
 +      `rebase`) and this variable is set to `true`, git
 +      automatically copies your notes from the original to the
 +      rewritten commit.  Defaults to `true`, but see
 +      "notes.rewriteRef" below.
 +
 +notes.rewriteMode::
 +      When copying notes during a rewrite (see the
 +      "notes.rewrite.<command>" option), determines what to do if
 +      the target commit already has a note.  Must be one of
 +      `overwrite`, `concatenate`, or `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.  The ref 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.
 ++
 +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
        window size is given on the command line. Defaults to 10.
@@@ -1477,16 -1392,6 +1486,16 @@@ pager.<cmd>:
        it takes precedence over this option.  To disable pagination for
        all commands, set `core.pager` or `GIT_PAGER` to `cat`.
  
 +pretty.<name>::
 +      Alias for a --pretty= format string, as specified in
 +      linkgit:git-log[1]. Any aliases defined here can be used just
 +      as the built-in pretty formats could. For example,
 +      running `git config pretty.changelog "format:{asterisk} %H %s"`
 +      would cause the invocation `git log --pretty=changelog`
 +      to be equivalent to running `git log "--pretty=format:{asterisk} %H %s"`.
 +      Note that an alias with the same name as a built-in format
 +      will be silently ignored.
 +
  pull.octopus::
        The default merge strategy to use when pulling multiple branches
        at once.
@@@ -1537,13 -1442,13 +1546,13 @@@ 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",
        print a warning of such a push to stderr, but allow the push to
        proceed. If set to false or "ignore", allow such pushes with no
 -      message. Defaults to "warn".
 +      message. Defaults to "refuse".
  
  receive.denyNonFastForwards::
        If set to true, git-receive-pack will deny a ref update which is
@@@ -1599,9 -1504,7 +1608,9 @@@ remote.<name>.uploadpack:
  
  remote.<name>.tagopt::
        Setting this value to \--no-tags disables automatic tag following when
 -      fetching from remote <name>
 +      fetching from remote <name>. Setting it to \--tags will fetch every
 +      tag from remote <name>, even if they are not reachable from remote
 +      branch heads.
  
  remote.<name>.vcs::
        Setting this to a value <vcs> will cause git to interact with
@@@ -1665,7 -1568,6 +1674,7 @@@ sendemail.smtppass:
  sendemail.suppresscc::
  sendemail.suppressfrom::
  sendemail.to::
 +sendemail.smtpdomain::
  sendemail.smtpserver::
  sendemail.smtpserverport::
  sendemail.smtpuser::
@@@ -1705,13 -1607,6 +1714,13 @@@ If this variable is not specified, it d
  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 c27ca4350e675e396c72e30022b26f8efff53a7f,086485763c40761dc9136f48127ce6f0e24f7212..7004dd2decfb2a9cf82b248aae1f848beaf885cb
@@@ -72,6 -72,9 +72,6 @@@ plugin. Most functionality works fine w
  LIMITATIONS
  -----------
  
 -Currently cvsserver works over SSH connections for read/write clients, and
 -over pserver for anonymous CVS access.
 -
  CVS clients cannot tag, branch or perform GIT merges.
  
  'git-cvsserver' maps GIT branches to CVS modules. This is very different
@@@ -81,7 -84,7 +81,7 @@@ one or more directories
  INSTALLATION
  ------------
  
 -1. If you are going to offer anonymous CVS access via pserver, add a line in
 +1. If you are going to offer CVS access via pserver, add a line in
     /etc/inetd.conf like
  +
  --
@@@ -98,38 -101,6 +98,38 @@@ looks lik
     cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver
  
  ------
 +
 +Only anonymous access is provided by pserve by default. To commit you
 +will have to create pserver accounts, simply add a gitcvs.authdb
 +setting in the config file of the repositories you want the cvsserver
 +to allow writes to, for example:
 +
 +------
 +
 +   [gitcvs]
 +      authdb = /etc/cvsserver/passwd
 +
 +------
 +The format of these files is username followed by the crypted password,
 +for example:
 +
 +------
 +   myuser:$1Oyx5r9mdGZ2
 +   myuser:$1$BA)@$vbnMJMDym7tA32AamXrm./
 +------
 +You can use the 'htpasswd' facility that comes with Apache to make these
 +files, but Apache's MD5 crypt method differs from the one used by most C
 +library's crypt() function, so don't use the -m option.
 +
 +Alternatively you can produce the password with perl's crypt() operator:
 +-----
 +   perl -e 'my ($user, $pass) = @ARGV; printf "%s:%s\n", $user, crypt($user, $pass)' $USER password
 +-----
 +
 +Then provide your password via the pserver method, for example:
 +------
 +   cvs -d:pserver:someuser:somepassword <at> server/path/repo.git co <HEAD_name>
 +------
  No special setup is needed for SSH access, other than having GIT tools
  in the PATH. If you have clients that do not accept the CVS_SERVER
  environment variable, you can rename 'git-cvsserver' to `cvs`.
@@@ -369,16 -340,13 +369,13 @@@ By default the server leaves the '-k' m
  which causes the cvs client to treat them as a text files, subject
  to crlf conversion on some platforms.
  
- You can make the server use `crlf` attributes to set the '-k' modes
- for files by setting the `gitcvs.usecrlfattr` config variable.
- In this case, if `crlf` is explicitly unset ('-crlf'), then the
- server will set '-kb' mode for binary files. If `crlf` is set,
- then the '-k' mode will explicitly be left blank.  See
- also linkgit:gitattributes[5] for more information about the `crlf`
- attribute.
+ You can make the server use the end-of-line conversion attributes to
+ set the '-k' modes for files by setting the `gitcvs.usecrlfattr`
+ config variable.  See linkgit:gitattributes[5] for more information
+ about end-of-line conversion.
  
  Alternatively, if `gitcvs.usecrlfattr` config is not enabled
- or if the `crlf` attribute is unspecified for a filename, then
+ or the attributes do not allow automatic detection for a filename, then
  the server uses the `gitcvs.allbinary` config for the default setting.
  If `gitcvs.allbinary` is set, then file not otherwise
  specified will default to '-kb' mode. Otherwise the '-k' mode
index 0523a576989dfb717be06af04c4be22a5a8eafd6,c2efe4c07957daf680ea5fba55c327ec4ea9bcdc..564586b943f439cb5ae04c4e76bc19d093c625da
@@@ -92,53 -92,154 +92,154 @@@ such as 'git checkout' and 'git merge' 
  git stores the contents you prepare in the working tree in the
  repository upon 'git add' and 'git commit'.
  
- `crlf`
+ `text`
  ^^^^^^
  
- This attribute controls the line-ending convention.
+ This attribute enables and controls end-of-line normalization.  When a
+ text file is normalized, its line endings are converted to LF in the
+ repository.  To control what line ending style is used in the working
+ directory, use the `eol` attribute for a single file and the
+ `core.eol` configuration variable for all text files.
  
  Set::
  
-       Setting the `crlf` attribute on a path is meant to mark
-       the path as a "text" file.  'core.autocrlf' conversion
-       takes place without guessing the content type by
-       inspection.
+       Setting the `text` attribute on a path enables end-of-line
+       normalization and marks the path as a text file.  End-of-line
+       conversion takes place without guessing the content type.
  
  Unset::
  
-       Unsetting the `crlf` attribute on a path tells git not to
+       Unsetting the `text` attribute on a path tells git not to
        attempt any end-of-line conversion upon checkin or checkout.
  
+ Set to string value "auto"::
+       When `text` is set to "auto", the path is marked for automatic
+       end-of-line normalization.  If git decides that the content is
+       text, its line endings are normalized to LF on checkin.
  Unspecified::
  
-       Unspecified `crlf` attribute tells git to apply the
-       `core.autocrlf` conversion when the file content looks
-       like text.
+       If the `text` attribute is unspecified, git uses the
+       `core.autocrlf` configuration variable to determine if the
+       file should be converted.
  
- Set to string value "input"::
+ Any other value causes git to act as if `text` has been left
+ unspecified.
  
-       This is similar to setting the attribute to `true`, but
-       also forces git to act as if `core.autocrlf` is set to
-       `input` for the path.
+ `eol`
+ ^^^^^
  
- Any other value set to `crlf` attribute is ignored and git acts
- as if the attribute is left unspecified.
+ This attribute sets a specific line-ending style to be used in the
+ working directory.  It enables end-of-line normalization without any
+ content checks, effectively setting the `text` attribute.
  
+ Set to string value "crlf"::
  
- The `core.autocrlf` conversion
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+       This setting forces git to normalize line endings for this
+       file on checkin and convert them to CRLF when the file is
+       checked out.
+ Set to string value "lf"::
+       This setting forces git to normalize line endings to LF on
+       checkin and prevents conversion to CRLF when the file is
+       checked out.
+ Backwards compatibility with `crlf` attribute
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ For backwards compatibility, the `crlf` attribute is interpreted as
+ follows:
+ ------------------------
+ crlf          text
+ -crlf         -text
+ crlf=input    eol=lf
+ ------------------------
+ End-of-line conversion
+ ^^^^^^^^^^^^^^^^^^^^^^
+ While git normally leaves file contents alone, it can be configured to
+ normalize line endings to LF in the repository and, optionally, to
+ convert them to CRLF when files are checked out.
+ Here is an example that will make git normalize .txt, .vcproj and .sh
+ files, ensure that .vcproj files have CRLF and .sh files have LF in
+ the working directory, and prevent .jpg files from being normalized
+ regardless of their content.
+ ------------------------
+ *.txt         text
+ *.vcproj      eol=crlf
+ *.sh          eol=lf
+ *.jpg         -text
+ ------------------------
+ Other source code management systems normalize all text files in their
+ repositories, and there are two ways to enable similar automatic
+ normalization in git.
+ If you simply want to have CRLF line endings in your working directory
+ regardless of the repository you are working with, you can set the
+ config variable "core.autocrlf" without changing any attributes.
+ ------------------------
+ [core]
+       autocrlf = true
+ ------------------------
+ This does not force normalization of all text files, but does ensure
+ that text files that you introduce to the repository have their line
+ endings normalized to LF when they are added, and that files that are
+ already normalized in the repository stay normalized.
+ If you want to interoperate with a source code management system that
+ enforces end-of-line normalization, or you simply want all text files
+ in your repository to be normalized, you should instead set the `text`
+ attribute to "auto" for _all_ files.
  
- If the configuration variable `core.autocrlf` is false, no
- conversion is done.
+ ------------------------
+ *     text=auto
+ ------------------------
+ This ensures that all files that git considers to be text will have
+ normalized (LF) line endings in the repository.  The `core.eol`
+ configuration variable controls which line endings git will use for
+ normalized files in your working directory; the default is to use the
+ native line ending for your platform, or CRLF if `core.autocrlf` is
+ set.
+ NOTE: When `text=auto` normalization is enabled in an existing
+ repository, any text files containing CRLFs should be normalized.  If
+ they are not they will be normalized the next time someone tries to
+ change them, causing unfortunate misattribution.  From a clean working
+ directory:
+ -------------------------------------------------
+ $ echo "* text=auto" >>.gitattributes
+ $ rm .git/index     # Remove the index to force git to
+ $ git reset         # re-scan the working directory
+ $ git status        # Show files that will be normalized
+ $ git add -u
+ $ git add .gitattributes
+ $ git commit -m "Introduce end-of-line normalization"
+ -------------------------------------------------
+ If any files that should not be normalized show up in 'git status',
+ unset their `text` attribute before running 'git add -u'.
+ ------------------------
+ manual.pdf    -text
+ ------------------------
  
- When `core.autocrlf` is true, it means that the platform wants
- CRLF line endings for files in the working tree, and you want to
- convert them back to the normal LF line endings when checking
- in to the repository.
+ Conversely, text files that git does not detect can have normalization
+ enabled manually.
  
- When `core.autocrlf` is set to "input", line endings are
- converted to LF upon checkin, but there is no conversion done
- upon checkout.
+ ------------------------
+ weirdchars.txt        text
+ ------------------------
  
  If `core.safecrlf` is set to "true" or "warn", git verifies if
  the conversion is reversible for the current setting of
@@@ -223,11 -324,11 +324,11 @@@ Interaction between checkin/checkout at
  In the check-in codepath, the worktree file is first converted
  with `filter` driver (if specified and corresponding driver
  defined), then the result is processed with `ident` (if
- specified), and then finally with `crlf` (again, if specified
+ specified), and then finally with `text` (again, if specified
  and applicable).
  
  In the check-out codepath, the blob content is first converted
- with `crlf`, and then `ident` and fed to `filter`.
+ with `text`, and then `ident` and fed to `filter`.
  
  
  Generating diff text
@@@ -360,7 -461,7 +461,7 @@@ patterns are available
  Customizing word diff
  ^^^^^^^^^^^^^^^^^^^^^
  
 -You can customize the rules that `git diff --color-words` uses to
 +You can customize the rules that `git diff --word-diff` uses to
  split words in a line, by specifying an appropriate regular expression
  in the "diff.*.wordRegex" configuration variable.  For example, in TeX
  a backslash followed by a sequence of letters forms a command, but
@@@ -414,26 -515,6 +515,26 @@@ because it quickly conveys the changes 
  should generate it separately and send it as a comment _in
  addition to_ the usual binary diff that you might send.
  
 +Because text conversion can be slow, especially when doing a
 +large number of them with `git log -p`, git provides a mechanism
 +to cache the output and use it in future diffs.  To enable
 +caching, set the "cachetextconv" variable in your diff driver's
 +config. For example:
 +
 +------------------------
 +[diff "jpg"]
 +      textconv = exif
 +      cachetextconv = true
 +------------------------
 +
 +This will cache the result of running "exif" on each blob
 +indefinitely. If you change the textconv config variable for a
 +diff driver, git will automatically invalidate the cache entries
 +and re-run the textconv filter. If you want to invalidate the
 +cache manually (e.g., because your version of "exif" was updated
 +and now produces better output), you can remove the cache
 +manually with `git update-ref -d refs/notes/textconv/jpg` (where
 +"jpg" is the name of the diff driver, as in the example above).
  
  Performing a three-way merge
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@@ -531,8 -612,7 +632,8 @@@ command to run to merge ancestor's vers
  version (`%A`) and the other branches' version (`%B`).  These
  three tokens are replaced with the names of temporary files that
  hold the contents of these versions when the command line is
 -built.
 +built. Additionally, %L will be replaced with the conflict marker
 +size (see below).
  
  The merge driver is expected to leave the result of the merge in
  the file named with `%A` by overwriting it, and exit with zero
@@@ -651,7 -731,7 +752,7 @@@ You do not want any end-of-line convers
  produced for, any binary file you track.  You would need to specify e.g.
  
  ------------
- *.jpg -crlf -diff
+ *.jpg -text -diff
  ------------
  
  but that may become cumbersome, when you have many attributes.  Using
@@@ -664,7 -744,7 +765,7 @@@ the same time.  The system knows a buil
  
  which is equivalent to the above.  Note that the attribute macros can only
  be "Set" (see the above example that sets "binary" macro as if it were an
- ordinary attribute --- setting it in turn unsets "crlf" and "diff").
+ ordinary attribute --- setting it in turn unsets "text" and "diff").
  
  
  DEFINING ATTRIBUTE MACROS
@@@ -675,7 -755,7 +776,7 @@@ at the toplevel (i.e. not in any subdir
  macro "binary" is equivalent to:
  
  ------------
- [attr]binary -diff -crlf
+ [attr]binary -diff -text
  ------------
  
  
diff --combined Makefile
index 3dc072fc8162be1b1d57db207a976b8b78928f04,bf5f8a7b0e8520e2f1b493ad357cb832d3502dca..9aca8a16d955e904b4a8f07e70fba754ac65fcc3
+++ b/Makefile
@@@ -8,12 -8,6 +8,12 @@@ all:
  # Define SANE_TOOL_PATH to a colon-separated list of paths to prepend
  # to PATH if your tools in /usr/bin are broken.
  #
 +# Define SOCKLEN_T to a suitable type (such as 'size_t') if your
 +# system headers do not define a socklen_t type.
 +#
 +# Define INLINE to a suitable substitute (such as '__inline' or '') if git
 +# fails to compile with errors about undefined inline functions or similar.
 +#
  # Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
  # or vsnprintf() return -1 instead of number of characters which would
  # have been written to the final string if enough space had been available.
  # 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
 -# d_type in struct dirent (latest Cygwin -- will be fixed soonish).
 +# d_type in struct dirent (Cygwin 1.5, fixed in Cygwin 1.7).
  #
  # Define NO_C99_FORMAT if your formatted IO functions (printf/scanf et.al.)
  # do not support the 'size specifiers' introduced by C99, namely ll, hh,
  # Define NO_PTHREADS if you do not have or do not want to use Pthreads.
  #
  # Define NO_PREAD if you have a problem with pread() system call (e.g.
 -# cygwin.dll before v1.5.22).
 +# cygwin1.dll before v1.5.22).
  #
  # Define NO_FAST_WORKING_DIRECTORY if accessing objects in pack files is
  # generally faster on your platform than accessing the working directory.
  # Define JSMIN to point to JavaScript minifier that functions as
  # a filter to have gitweb.js minified.
  #
 +# Define CSSMIN to point to a CSS minifier in order to generate a minified
 +# version of gitweb.css
 +#
  # Define DEFAULT_PAGER to a sensible pager command (defaults to "less") if
  # you want to use something different.  The value will be interpreted by the
  # shell at runtime when it is used.
  #   DEFAULT_EDITOR='$GIT_FALLBACK_EDITOR',
  #   DEFAULT_EDITOR='"C:\Program Files\Vim\gvim.exe" --nofork'
  #
 +# Define COMPUTE_HEADER_DEPENDENCIES if your compiler supports the -MMD option
 +# and you want to avoid rebuilding objects when an unrelated header file
 +# changes.
 +#
 +# Define CHECK_HEADER_DEPENDENCIES to check for problems in the hard-coded
 +# dependency rules.
++#
+ # Define NATIVE_CRLF if your platform uses CRLF for line endings.
  
  GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@@ -255,7 -238,7 +257,7 @@@ endi
  
  CFLAGS = -g -O2 -Wall
  LDFLAGS =
 -ALL_CFLAGS = $(CFLAGS)
 +ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS)
  ALL_LDFLAGS = $(LDFLAGS)
  STRIP ?= strip
  
@@@ -278,7 -261,6 +280,7 @@@ mandir = share/ma
  infodir = share/info
  gitexecdir = libexec/git-core
  sharedir = $(prefix)/share
 +gitwebdir = $(sharedir)/gitweb
  template_dir = share/git-core/templates
  htmldir = share/doc/git-doc
  ifeq ($(prefix),/usr)
@@@ -292,12 -274,14 +294,12 @@@ lib = li
  # DESTDIR=
  pathsep = :
  
 -# JavaScript minifier invocation that can function as filter
 -JSMIN =
 -
 -export prefix bindir sharedir sysconfdir
 +export prefix bindir sharedir sysconfdir gitwebdir
  
  CC = gcc
  AR = ar
  RM = rm -f
 +DIFF = diff
  TAR = tar
  FIND = find
  INSTALL = install
@@@ -305,7 -289,6 +307,7 @@@ RPMBUILD = rpmbuil
  TCL_PATH = tclsh
  TCLTK_PATH = wish
  PTHREAD_LIBS = -lpthread
 +PTHREAD_CFLAGS =
  
  export TCL_PATH TCLTK_PATH
  
@@@ -320,7 -303,7 +322,7 @@@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__pow
  # Those must not be GNU-specific; they are shared with perl/ which may
  # be built by a different compiler. (Note that this is an artifact now
  # but it still might be nice to keep that distinction.)
 -BASIC_CFLAGS =
 +BASIC_CFLAGS = -I.
  BASIC_LDFLAGS =
  
  # Guard against environment variables
@@@ -328,22 -311,13 +330,22 @@@ BUILTIN_OBJS 
  BUILT_INS =
  COMPAT_CFLAGS =
  COMPAT_OBJS =
 +EXTRA_CPPFLAGS =
  LIB_H =
  LIB_OBJS =
 +PROGRAM_OBJS =
  PROGRAMS =
  SCRIPT_PERL =
  SCRIPT_PYTHON =
  SCRIPT_SH =
 -TEST_PROGRAMS =
 +SCRIPT_LIB =
 +TEST_PROGRAMS_NEED_X =
 +
 +# Having this variable in your environment would break pipelines because
 +# you cause "cd" to echo its destination to stdout.  It can also take
 +# scripts to unexpected places.  If you like CDPATH, define it for your
 +# interactive shell sessions without exporting it.
 +unexport CDPATH
  
  SCRIPT_SH += git-am.sh
  SCRIPT_SH += git-bisect.sh
@@@ -354,20 -328,20 +356,20 @@@ SCRIPT_SH += git-merge-octopus.s
  SCRIPT_SH += git-merge-one-file.sh
  SCRIPT_SH += git-merge-resolve.sh
  SCRIPT_SH += git-mergetool.sh
 -SCRIPT_SH += git-mergetool--lib.sh
 -SCRIPT_SH += git-notes.sh
 -SCRIPT_SH += git-parse-remote.sh
  SCRIPT_SH += git-pull.sh
  SCRIPT_SH += git-quiltimport.sh
  SCRIPT_SH += git-rebase--interactive.sh
  SCRIPT_SH += git-rebase.sh
  SCRIPT_SH += git-repack.sh
  SCRIPT_SH += git-request-pull.sh
 -SCRIPT_SH += git-sh-setup.sh
  SCRIPT_SH += git-stash.sh
  SCRIPT_SH += git-submodule.sh
  SCRIPT_SH += git-web--browse.sh
  
 +SCRIPT_LIB += git-mergetool--lib
 +SCRIPT_LIB += git-parse-remote
 +SCRIPT_LIB += git-sh-setup
 +
  SCRIPT_PERL += git-add--interactive.perl
  SCRIPT_PERL += git-difftool.perl
  SCRIPT_PERL += git-archimport.perl
@@@ -378,8 -352,6 +380,8 @@@ SCRIPT_PERL += git-relink.per
  SCRIPT_PERL += git-send-email.perl
  SCRIPT_PERL += git-svn.perl
  
 +SCRIPT_PYTHON += git-remote-testgit.py
 +
  SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
          $(patsubst %.perl,%,$(SCRIPT_PERL)) \
          $(patsubst %.py,%,$(SCRIPT_PYTHON)) \
@@@ -390,35 -362,16 +392,35 @@@ EXTRA_PROGRAMS 
  
  # ... and all the rest that could be moved out of bindir to gitexecdir
  PROGRAMS += $(EXTRA_PROGRAMS)
 -PROGRAMS += git-fast-import$X
 -PROGRAMS += git-imap-send$X
 -PROGRAMS += git-shell$X
 -PROGRAMS += git-show-index$X
 -PROGRAMS += git-upload-pack$X
 -PROGRAMS += git-http-backend$X
 +
 +PROGRAM_OBJS += fast-import.o
 +PROGRAM_OBJS += imap-send.o
 +PROGRAM_OBJS += shell.o
 +PROGRAM_OBJS += show-index.o
 +PROGRAM_OBJS += upload-pack.o
 +PROGRAM_OBJS += http-backend.o
 +
 +PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
 +
 +TEST_PROGRAMS_NEED_X += test-chmtime
 +TEST_PROGRAMS_NEED_X += test-ctype
 +TEST_PROGRAMS_NEED_X += test-date
 +TEST_PROGRAMS_NEED_X += test-delta
 +TEST_PROGRAMS_NEED_X += test-dump-cache-tree
 +TEST_PROGRAMS_NEED_X += test-genrandom
 +TEST_PROGRAMS_NEED_X += test-match-trees
 +TEST_PROGRAMS_NEED_X += test-parse-options
 +TEST_PROGRAMS_NEED_X += test-path-utils
 +TEST_PROGRAMS_NEED_X += test-run-command
 +TEST_PROGRAMS_NEED_X += test-sha1
 +TEST_PROGRAMS_NEED_X += test-sigchain
 +TEST_PROGRAMS_NEED_X += test-index-version
 +
 +TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
  
  # List built-in command $C whose implementation cmd_$C() is not in
 -# builtin-$C.o but is linked in as part of some other command.
 -BUILT_INS += $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
 +# builtin/$C.o but is linked in as part of some other command.
 +BUILT_INS += $(patsubst builtin/%.o,git-%$X,$(BUILTIN_OBJS))
  
  BUILT_INS += git-cherry$X
  BUILT_INS += git-cherry-pick$X
@@@ -474,7 -427,6 +476,7 @@@ LIB_H += blob.
  LIB_H += builtin.h
  LIB_H += cache.h
  LIB_H += cache-tree.h
 +LIB_H += color.h
  LIB_H += commit.h
  LIB_H += compat/bswap.h
  LIB_H += compat/cygwin.h
@@@ -486,7 -438,6 +488,7 @@@ LIB_H += delta.
  LIB_H += diffcore.h
  LIB_H += diff.h
  LIB_H += dir.h
 +LIB_H += exec_cmd.h
  LIB_H += fsck.h
  LIB_H += git-compat-util.h
  LIB_H += graph.h
@@@ -500,7 -451,6 +502,7 @@@ LIB_H += log-tree.
  LIB_H += mailmap.h
  LIB_H += merge-recursive.h
  LIB_H += notes.h
 +LIB_H += notes-cache.h
  LIB_H += object.h
  LIB_H += pack.h
  LIB_H += pack-refs.h
@@@ -530,8 -480,7 +532,8 @@@ LIB_H += tree-walk.
  LIB_H += unpack-trees.h
  LIB_H += userdiff.h
  LIB_H += utf8.h
 -LIB_H += wt-status.h
 +LIB_H += xdiff-interface.h
 +LIB_H += xdiff/xdiff.h
  
  LIB_OBJS += abspath.o
  LIB_OBJS += advice.o
@@@ -590,7 -539,6 +592,7 @@@ LIB_OBJS += merge-file.
  LIB_OBJS += merge-recursive.o
  LIB_OBJS += name-hash.o
  LIB_OBJS += notes.o
 +LIB_OBJS += notes-cache.o
  LIB_OBJS += object.o
  LIB_OBJS += pack-check.o
  LIB_OBJS += pack-refs.o
@@@ -636,7 -584,6 +638,7 @@@ LIB_OBJS += tree-diff.
  LIB_OBJS += tree.o
  LIB_OBJS += tree-walk.o
  LIB_OBJS += unpack-trees.o
 +LIB_OBJS += url.o
  LIB_OBJS += usage.o
  LIB_OBJS += userdiff.o
  LIB_OBJS += utf8.o
@@@ -647,96 -594,95 +649,96 @@@ LIB_OBJS += ws.
  LIB_OBJS += wt-status.o
  LIB_OBJS += xdiff-interface.o
  
 -BUILTIN_OBJS += builtin-add.o
 -BUILTIN_OBJS += builtin-annotate.o
 -BUILTIN_OBJS += builtin-apply.o
 -BUILTIN_OBJS += builtin-archive.o
 -BUILTIN_OBJS += builtin-bisect--helper.o
 -BUILTIN_OBJS += builtin-blame.o
 -BUILTIN_OBJS += builtin-branch.o
 -BUILTIN_OBJS += builtin-bundle.o
 -BUILTIN_OBJS += builtin-cat-file.o
 -BUILTIN_OBJS += builtin-check-attr.o
 -BUILTIN_OBJS += builtin-check-ref-format.o
 -BUILTIN_OBJS += builtin-checkout-index.o
 -BUILTIN_OBJS += builtin-checkout.o
 -BUILTIN_OBJS += builtin-clean.o
 -BUILTIN_OBJS += builtin-clone.o
 -BUILTIN_OBJS += builtin-commit-tree.o
 -BUILTIN_OBJS += builtin-commit.o
 -BUILTIN_OBJS += builtin-config.o
 -BUILTIN_OBJS += builtin-count-objects.o
 -BUILTIN_OBJS += builtin-describe.o
 -BUILTIN_OBJS += builtin-diff-files.o
 -BUILTIN_OBJS += builtin-diff-index.o
 -BUILTIN_OBJS += builtin-diff-tree.o
 -BUILTIN_OBJS += builtin-diff.o
 -BUILTIN_OBJS += builtin-fast-export.o
 -BUILTIN_OBJS += builtin-fetch-pack.o
 -BUILTIN_OBJS += builtin-fetch.o
 -BUILTIN_OBJS += builtin-fmt-merge-msg.o
 -BUILTIN_OBJS += builtin-for-each-ref.o
 -BUILTIN_OBJS += builtin-fsck.o
 -BUILTIN_OBJS += builtin-gc.o
 -BUILTIN_OBJS += builtin-grep.o
 -BUILTIN_OBJS += builtin-hash-object.o
 -BUILTIN_OBJS += builtin-help.o
 -BUILTIN_OBJS += builtin-index-pack.o
 -BUILTIN_OBJS += builtin-init-db.o
 -BUILTIN_OBJS += builtin-log.o
 -BUILTIN_OBJS += builtin-ls-files.o
 -BUILTIN_OBJS += builtin-ls-remote.o
 -BUILTIN_OBJS += builtin-ls-tree.o
 -BUILTIN_OBJS += builtin-mailinfo.o
 -BUILTIN_OBJS += builtin-mailsplit.o
 -BUILTIN_OBJS += builtin-merge.o
 -BUILTIN_OBJS += builtin-merge-base.o
 -BUILTIN_OBJS += builtin-merge-file.o
 -BUILTIN_OBJS += builtin-merge-index.o
 -BUILTIN_OBJS += builtin-merge-ours.o
 -BUILTIN_OBJS += builtin-merge-recursive.o
 -BUILTIN_OBJS += builtin-merge-tree.o
 -BUILTIN_OBJS += builtin-mktag.o
 -BUILTIN_OBJS += builtin-mktree.o
 -BUILTIN_OBJS += builtin-mv.o
 -BUILTIN_OBJS += builtin-name-rev.o
 -BUILTIN_OBJS += builtin-pack-objects.o
 -BUILTIN_OBJS += builtin-pack-redundant.o
 -BUILTIN_OBJS += builtin-pack-refs.o
 -BUILTIN_OBJS += builtin-patch-id.o
 -BUILTIN_OBJS += builtin-prune-packed.o
 -BUILTIN_OBJS += builtin-prune.o
 -BUILTIN_OBJS += builtin-push.o
 -BUILTIN_OBJS += builtin-read-tree.o
 -BUILTIN_OBJS += builtin-receive-pack.o
 -BUILTIN_OBJS += builtin-reflog.o
 -BUILTIN_OBJS += builtin-remote.o
 -BUILTIN_OBJS += builtin-replace.o
 -BUILTIN_OBJS += builtin-rerere.o
 -BUILTIN_OBJS += builtin-reset.o
 -BUILTIN_OBJS += builtin-rev-list.o
 -BUILTIN_OBJS += builtin-rev-parse.o
 -BUILTIN_OBJS += builtin-revert.o
 -BUILTIN_OBJS += builtin-rm.o
 -BUILTIN_OBJS += builtin-send-pack.o
 -BUILTIN_OBJS += builtin-shortlog.o
 -BUILTIN_OBJS += builtin-show-branch.o
 -BUILTIN_OBJS += builtin-show-ref.o
 -BUILTIN_OBJS += builtin-stripspace.o
 -BUILTIN_OBJS += builtin-symbolic-ref.o
 -BUILTIN_OBJS += builtin-tag.o
 -BUILTIN_OBJS += builtin-tar-tree.o
 -BUILTIN_OBJS += builtin-unpack-file.o
 -BUILTIN_OBJS += builtin-unpack-objects.o
 -BUILTIN_OBJS += builtin-update-index.o
 -BUILTIN_OBJS += builtin-update-ref.o
 -BUILTIN_OBJS += builtin-update-server-info.o
 -BUILTIN_OBJS += builtin-upload-archive.o
 -BUILTIN_OBJS += builtin-var.o
 -BUILTIN_OBJS += builtin-verify-pack.o
 -BUILTIN_OBJS += builtin-verify-tag.o
 -BUILTIN_OBJS += builtin-write-tree.o
 +BUILTIN_OBJS += builtin/add.o
 +BUILTIN_OBJS += builtin/annotate.o
 +BUILTIN_OBJS += builtin/apply.o
 +BUILTIN_OBJS += builtin/archive.o
 +BUILTIN_OBJS += builtin/bisect--helper.o
 +BUILTIN_OBJS += builtin/blame.o
 +BUILTIN_OBJS += builtin/branch.o
 +BUILTIN_OBJS += builtin/bundle.o
 +BUILTIN_OBJS += builtin/cat-file.o
 +BUILTIN_OBJS += builtin/check-attr.o
 +BUILTIN_OBJS += builtin/check-ref-format.o
 +BUILTIN_OBJS += builtin/checkout-index.o
 +BUILTIN_OBJS += builtin/checkout.o
 +BUILTIN_OBJS += builtin/clean.o
 +BUILTIN_OBJS += builtin/clone.o
 +BUILTIN_OBJS += builtin/commit-tree.o
 +BUILTIN_OBJS += builtin/commit.o
 +BUILTIN_OBJS += builtin/config.o
 +BUILTIN_OBJS += builtin/count-objects.o
 +BUILTIN_OBJS += builtin/describe.o
 +BUILTIN_OBJS += builtin/diff-files.o
 +BUILTIN_OBJS += builtin/diff-index.o
 +BUILTIN_OBJS += builtin/diff-tree.o
 +BUILTIN_OBJS += builtin/diff.o
 +BUILTIN_OBJS += builtin/fast-export.o
 +BUILTIN_OBJS += builtin/fetch-pack.o
 +BUILTIN_OBJS += builtin/fetch.o
 +BUILTIN_OBJS += builtin/fmt-merge-msg.o
 +BUILTIN_OBJS += builtin/for-each-ref.o
 +BUILTIN_OBJS += builtin/fsck.o
 +BUILTIN_OBJS += builtin/gc.o
 +BUILTIN_OBJS += builtin/grep.o
 +BUILTIN_OBJS += builtin/hash-object.o
 +BUILTIN_OBJS += builtin/help.o
 +BUILTIN_OBJS += builtin/index-pack.o
 +BUILTIN_OBJS += builtin/init-db.o
 +BUILTIN_OBJS += builtin/log.o
 +BUILTIN_OBJS += builtin/ls-files.o
 +BUILTIN_OBJS += builtin/ls-remote.o
 +BUILTIN_OBJS += builtin/ls-tree.o
 +BUILTIN_OBJS += builtin/mailinfo.o
 +BUILTIN_OBJS += builtin/mailsplit.o
 +BUILTIN_OBJS += builtin/merge.o
 +BUILTIN_OBJS += builtin/merge-base.o
 +BUILTIN_OBJS += builtin/merge-file.o
 +BUILTIN_OBJS += builtin/merge-index.o
 +BUILTIN_OBJS += builtin/merge-ours.o
 +BUILTIN_OBJS += builtin/merge-recursive.o
 +BUILTIN_OBJS += builtin/merge-tree.o
 +BUILTIN_OBJS += builtin/mktag.o
 +BUILTIN_OBJS += builtin/mktree.o
 +BUILTIN_OBJS += builtin/mv.o
 +BUILTIN_OBJS += builtin/name-rev.o
 +BUILTIN_OBJS += builtin/notes.o
 +BUILTIN_OBJS += builtin/pack-objects.o
 +BUILTIN_OBJS += builtin/pack-redundant.o
 +BUILTIN_OBJS += builtin/pack-refs.o
 +BUILTIN_OBJS += builtin/patch-id.o
 +BUILTIN_OBJS += builtin/prune-packed.o
 +BUILTIN_OBJS += builtin/prune.o
 +BUILTIN_OBJS += builtin/push.o
 +BUILTIN_OBJS += builtin/read-tree.o
 +BUILTIN_OBJS += builtin/receive-pack.o
 +BUILTIN_OBJS += builtin/reflog.o
 +BUILTIN_OBJS += builtin/remote.o
 +BUILTIN_OBJS += builtin/replace.o
 +BUILTIN_OBJS += builtin/rerere.o
 +BUILTIN_OBJS += builtin/reset.o
 +BUILTIN_OBJS += builtin/rev-list.o
 +BUILTIN_OBJS += builtin/rev-parse.o
 +BUILTIN_OBJS += builtin/revert.o
 +BUILTIN_OBJS += builtin/rm.o
 +BUILTIN_OBJS += builtin/send-pack.o
 +BUILTIN_OBJS += builtin/shortlog.o
 +BUILTIN_OBJS += builtin/show-branch.o
 +BUILTIN_OBJS += builtin/show-ref.o
 +BUILTIN_OBJS += builtin/stripspace.o
 +BUILTIN_OBJS += builtin/symbolic-ref.o
 +BUILTIN_OBJS += builtin/tag.o
 +BUILTIN_OBJS += builtin/tar-tree.o
 +BUILTIN_OBJS += builtin/unpack-file.o
 +BUILTIN_OBJS += builtin/unpack-objects.o
 +BUILTIN_OBJS += builtin/update-index.o
 +BUILTIN_OBJS += builtin/update-ref.o
 +BUILTIN_OBJS += builtin/update-server-info.o
 +BUILTIN_OBJS += builtin/upload-archive.o
 +BUILTIN_OBJS += builtin/var.o
 +BUILTIN_OBJS += builtin/verify-pack.o
 +BUILTIN_OBJS += builtin/verify-tag.o
 +BUILTIN_OBJS += builtin/write-tree.o
  
  GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
  EXTLIBS =
  # because maintaining the nesting to match is a pain.  If
  # we had "elif" things would have been much nicer...
  
 +ifeq ($(uname_S),OSF1)
 +      # Need this for u_short definitions et al
 +      BASIC_CFLAGS += -D_OSF_SOURCE
 +      SOCKLEN_T = int
 +      NO_STRTOULL = YesPlease
 +      NO_NSEC = YesPlease
 +endif
  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
@@@ -830,18 -767,6 +832,18 @@@ ifeq ($(uname_S),SunOS
        NO_MKDTEMP = YesPlease
        NO_MKSTEMPS = YesPlease
        NO_REGEX = YesPlease
 +      ifeq ($(uname_R),5.6)
 +              SOCKLEN_T = int
 +              NO_HSTRERROR = YesPlease
 +              NO_IPV6 = YesPlease
 +              NO_SOCKADDR_STORAGE = YesPlease
 +              NO_UNSETENV = YesPlease
 +              NO_SETENV = YesPlease
 +              NO_STRLCPY = YesPlease
 +              NO_C99_FORMAT = YesPlease
 +              NO_STRTOUMAX = YesPlease
 +              GIT_TEST_CMP = cmp
 +      endif
        ifeq ($(uname_R),5.7)
                NEEDS_RESOLV = YesPlease
                NO_IPV6 = YesPlease
                NO_STRLCPY = YesPlease
                NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
 +              GIT_TEST_CMP = cmp
        endif
        ifeq ($(uname_R),5.8)
                NO_UNSETENV = YesPlease
                NO_SETENV = YesPlease
                NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
 +              GIT_TEST_CMP = cmp
        endif
        ifeq ($(uname_R),5.9)
                NO_UNSETENV = YesPlease
                NO_SETENV = YesPlease
                NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
 +              GIT_TEST_CMP = cmp
        endif
        INSTALL = /usr/ucb/install
        TAR = gtar
        BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
  endif
  ifeq ($(uname_O),Cygwin)
 -      NO_D_TYPE_IN_DIRENT = YesPlease
 -      NO_D_INO_IN_DIRENT = YesPlease
 -      NO_STRCASESTR = YesPlease
 -      NO_MEMMEM = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      NO_SYMLINK_HEAD = YesPlease
 +      ifeq ($(shell expr "$(uname_R)" : '1\.[1-6]\.'),4)
 +              NO_D_TYPE_IN_DIRENT = YesPlease
 +              NO_D_INO_IN_DIRENT = YesPlease
 +              NO_STRCASESTR = YesPlease
 +              NO_MEMMEM = YesPlease
 +              NO_MKSTEMPS = YesPlease
 +              NO_SYMLINK_HEAD = YesPlease
 +              NO_IPV6 = YesPlease
 +              OLD_ICONV = UnfortunatelyYes
 +      endif
        NEEDS_LIBICONV = YesPlease
        NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
        NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
 -      OLD_ICONV = UnfortunatelyYes
        NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
        # There are conflicting reports about this.
        # On some boxes NO_MMAP is needed, and not so elsewhere.
        # Try commenting this out if you suspect MMAP is more efficient
        NO_MMAP = YesPlease
 -      NO_IPV6 = YesPlease
        X = .exe
        COMPAT_OBJS += compat/cygwin.o
        UNRELIABLE_FSTAT = UnfortunatelyYes
@@@ -907,8 -827,6 +909,8 @@@ ifeq ($(uname_S),FreeBSD
                NO_UINTMAX_T = YesPlease
                NO_STRTOUMAX = YesPlease
        endif
 +      PYTHON_PATH = /usr/local/bin/python
 +      HAVE_PATHS_H = YesPlease
  endif
  ifeq ($(uname_S),OpenBSD)
        NO_STRCASESTR = YesPlease
        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)
        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
        BASIC_CFLAGS += -D_LARGE_FILES
        ifeq ($(shell expr "$(uname_V)" : '[1234]'),1)
                NO_PTHREADS = YesPlease
 +      else
 +              PTHREAD_LIBS = -lpthread
        endif
 +      ifeq ($(shell expr "$(uname_V).$(uname_R)" : '5\.1'),3)
 +              INLINE=''
 +      endif
 +      GIT_TEST_CMP = cmp
  endif
  ifeq ($(uname_S),GNU)
        # GNU/Hurd
        NO_STRLCPY=YesPlease
        NO_MKSTEMPS = YesPlease
 +      HAVE_PATHS_H = YesPlease
  endif
  ifeq ($(uname_S),IRIX)
        NO_SETENV = YesPlease
@@@ -994,7 -902,6 +996,7 @@@ ifeq ($(uname_S),IRIX64
        NEEDS_LIBGEN = YesPlease
  endif
  ifeq ($(uname_S),HP-UX)
 +      INLINE = __inline
        NO_IPV6=YesPlease
        NO_SETENV=YesPlease
        NO_STRCASESTR=YesPlease
        NO_HSTRERROR = YesPlease
        NO_SYS_SELECT_H = YesPlease
        SNPRINTF_RETURNS_BOGUS = YesPlease
 +      NO_NSEC = YesPlease
 +      ifeq ($(uname_R),B.11.00)
 +              NO_INET_NTOP = YesPlease
 +              NO_INET_PTON = YesPlease
 +      endif
 +      ifeq ($(uname_R),B.10.20)
 +              # Override HP-UX 11.x setting:
 +              INLINE =
 +              SOCKLEN_T = size_t
 +              NO_PREAD = YesPlease
 +              NO_INET_NTOP = YesPlease
 +              NO_INET_PTON = YesPlease
 +      endif
 +      GIT_TEST_CMP = cmp
  endif
  ifeq ($(uname_S),Windows)
        GIT_VERSION := $(GIT_VERSION).MSVC
        NO_CURL = YesPlease
        NO_PYTHON = YesPlease
        BLK_SHA1 = YesPlease
+       NATIVE_CRLF = YesPlease
  
        CC = compat/vcbuild/scripts/clink.pl
        AR = compat/vcbuild/scripts/lib.pl
@@@ -1093,6 -987,7 +1096,6 @@@ ifneq (,$(findstring MINGW,$(uname_S))
        NO_STRTOUMAX = YesPlease
        NO_MKDTEMP = YesPlease
        NO_MKSTEMPS = YesPlease
 -      SNPRINTF_RETURNS_BOGUS = YesPlease
        NO_SVN_TESTS = YesPlease
        NO_PERL_MAKEMAKER = YesPlease
        RUNTIME_PREFIX = YesPlease
@@@ -1128,15 -1023,6 +1131,15 @@@ endi
  -include config.mak.autogen
  -include config.mak
  
 +ifdef CHECK_HEADER_DEPENDENCIES
 +COMPUTE_HEADER_DEPENDENCIES =
 +USE_COMPUTED_HEADER_DEPENDENCIES =
 +endif
 +
 +ifdef COMPUTE_HEADER_DEPENDENCIES
 +USE_COMPUTED_HEADER_DEPENDENCIES = YesPlease
 +endif
 +
  ifdef SANE_TOOL_PATH
  SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
  BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix $(SANE_TOOL_PATH_SQ)|'
  BROKEN_PATH_FIX = '/^\# @@BROKEN_PATH_FIX@@$$/d'
  endif
  
 +ifneq (,$(INLINE))
 +      BASIC_CFLAGS += -Dinline=$(INLINE)
 +endif
 +
 +ifneq (,$(SOCKLEN_T))
 +      BASIC_CFLAGS += -Dsocklen_t=$(SOCKLEN_T)
 +endif
 +
  ifeq ($(uname_S),Darwin)
        ifndef NO_FINK
                ifeq ($(shell test -d /sw/lib && echo y),y)
        REMOTE_CURL_PRIMARY = git-remote-http$X
        REMOTE_CURL_ALIASES = git-remote-https$X git-remote-ftp$X git-remote-ftps$X
        REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES)
 -      PROGRAMS += $(REMOTE_CURL_NAMES) git-http-fetch$X
 +      PROGRAM_OBJS += http-fetch.o
 +      PROGRAMS += $(REMOTE_CURL_NAMES)
        curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
        ifeq "$(curl_check)" "070908"
                ifndef NO_EXPAT
 -                      PROGRAMS += git-http-push$X
 +                      PROGRAM_OBJS += http-push.o
                endif
        endif
        ifndef NO_EXPAT
@@@ -1225,7 -1102,7 +1228,7 @@@ endi
  EXTLIBS += -lz
  
  ifndef NO_POSIX_ONLY_PROGRAMS
 -      PROGRAMS += git-daemon$X
 +      PROGRAM_OBJS += daemon.o
  endif
  ifndef NO_OPENSSL
        OPENSSL_LIBSSL = -lssl
@@@ -1326,6 -1203,7 +1329,6 @@@ ifdef NO_MKDTEM
  endif
  ifdef NO_MKSTEMPS
        COMPAT_CFLAGS += -DNO_MKSTEMPS
 -      COMPAT_OBJS += compat/mkstemps.o
  endif
  ifdef NO_UNSETENV
        COMPAT_CFLAGS += -DNO_UNSETENV
@@@ -1391,12 -1269,10 +1394,12 @@@ endi
  ifdef BLK_SHA1
        SHA1_HEADER = "block-sha1/sha1.h"
        LIB_OBJS += block-sha1/sha1.o
 +      LIB_H += block-sha1/sha1.h
  else
  ifdef PPC_SHA1
        SHA1_HEADER = "ppc/sha1.h"
        LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
 +      LIB_H += ppc/sha1.h
  else
        SHA1_HEADER = <openssl/sha.h>
        EXTLIBS += $(LIB_4_CRYPTO)
@@@ -1424,15 -1300,10 +1427,15 @@@ endi
  ifdef NO_PTHREADS
        BASIC_CFLAGS += -DNO_PTHREADS
  else
 +      BASIC_CFLAGS += $(PTHREAD_CFLAGS)
        EXTLIBS += $(PTHREAD_LIBS)
        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
@@@ -1449,10 -1320,6 +1452,10 @@@ ifdef USE_NED_ALLOCATO
         COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
  endif
  
 +ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
 +      export GIT_TEST_CMP_USE_COPIED_CONTEXT
 +endif
 +
  ifeq ($(TCLTK_PATH),)
  NO_TCLTK=NoThanks
  endif
@@@ -1509,13 -1376,11 +1512,13 @@@ gitexecdir_SQ = $(subst ','\'',$(gitexe
  template_dir_SQ = $(subst ','\'',$(template_dir))
  htmldir_SQ = $(subst ','\'',$(htmldir))
  prefix_SQ = $(subst ','\'',$(prefix))
 +gitwebdir_SQ = $(subst ','\'',$(gitwebdir))
  
  SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
  PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
  PYTHON_PATH_SQ = $(subst ','\'',$(PYTHON_PATH))
  TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
 +DIFF_SQ = $(subst ','\'',$(DIFF))
  
  LIBS = $(GITLIBS) $(EXTLIBS)
  
@@@ -1542,14 -1407,14 +1545,14 @@@ endi
  ALL_CFLAGS += $(BASIC_CFLAGS)
  ALL_LDFLAGS += $(BASIC_LDFLAGS)
  
 -export TAR INSTALL DESTDIR SHELL_PATH
 +export DIFF TAR INSTALL DESTDIR SHELL_PATH
  
  
  ### Build rules
  
  SHELL = $(SHELL_PATH)
  
 -all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
 +all:: shell_compatibility_test $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
  ifneq (,$X)
        $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';)
  endif
@@@ -1565,7 -1430,7 +1568,7 @@@ endi
  ifndef NO_PYTHON
        $(QUIET_SUBDIR0)git_remote_helpers $(QUIET_SUBDIR1) PYTHON_PATH='$(PYTHON_PATH_SQ)' prefix='$(prefix_SQ)' all
  endif
 -      $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)
 +      $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)'
  
  please_set_SHELL_PATH_to_a_more_modern_shell:
        @$$(:)
@@@ -1576,15 -1441,15 +1579,15 @@@ strip: $(PROGRAMS) git$
        $(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
  
  git.o: common-cmds.h
 -git.s git.o: ALL_CFLAGS += -DGIT_VERSION='"$(GIT_VERSION)"' \
 +git.s git.o: EXTRA_CPPFLAGS = -DGIT_VERSION='"$(GIT_VERSION)"' \
        '-DGIT_HTML_PATH="$(htmldir_SQ)"'
  
  git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \
                $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
  
 -builtin-help.o: common-cmds.h
 -builtin-help.s builtin-help.o: ALL_CFLAGS += \
 +builtin/help.o: common-cmds.h
 +builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
        '-DGIT_HTML_PATH="$(htmldir_SQ)"' \
        '-DGIT_MAN_PATH="$(mandir_SQ)"' \
        '-DGIT_INFO_PATH="$(infodir_SQ)"'
@@@ -1600,26 -1465,17 +1603,26 @@@ common-cmds.h: ./generate-cmdlist.sh co
  common-cmds.h: $(wildcard Documentation/git-*.txt)
        $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
  
 +define cmd_munge_script
 +$(RM) $@ $@+ && \
 +sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
 +    -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
 +    -e 's|@@DIFF@@|$(DIFF_SQ)|' \
 +    -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
 +    -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
 +    -e $(BROKEN_PATH_FIX) \
 +    $@.sh >$@+
 +endef
 +
  $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
 -      $(QUIET_GEN)$(RM) $@ $@+ && \
 -      sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
 -          -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
 -          -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
 -          -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
 -          -e $(BROKEN_PATH_FIX) \
 -          $@.sh >$@+ && \
 +      $(QUIET_GEN)$(cmd_munge_script) && \
        chmod +x $@+ && \
        mv $@+ $@
  
 +$(SCRIPT_LIB) : % : %.sh
 +      $(QUIET_GEN)$(cmd_munge_script) && \
 +      mv $@+ $@
 +
  ifndef NO_PERL
  $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
  
@@@ -1632,10 -1488,11 +1635,10 @@@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % 
        sed -e '1{' \
            -e '        s|#!.*perl|#!$(PERL_PATH_SQ)|' \
            -e '        h' \
 -          -e '        s=.*=use lib (split(/$(pathsep)/, $$ENV{GITPERLLIB} || "@@INSTLIBDIR@@"));=' \
 +          -e '        s=.*=use lib (split(/$(pathsep)/, $$ENV{GITPERLLIB} || "'"$$INSTLIBDIR"'"));=' \
            -e '        H' \
            -e '        x' \
            -e '}' \
 -          -e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \
            -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
            $@.perl >$@+ && \
        chmod +x $@+ && \
@@@ -1647,37 -1504,31 +1650,37 @@@ gitweb
        $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) all
  
  ifdef JSMIN
 -OTHER_PROGRAMS += gitweb/gitweb.cgi   gitweb/gitweb.min.js
 -gitweb/gitweb.cgi: gitweb/gitweb.perl gitweb/gitweb.min.js
 +GITWEB_PROGRAMS += gitweb/static/gitweb.min.js
 +GITWEB_JS = gitweb/static/gitweb.min.js
 +else
 +GITWEB_JS = gitweb/static/gitweb.js
 +endif
 +ifdef CSSMIN
 +GITWEB_PROGRAMS += gitweb/static/gitweb.min.css
 +GITWEB_CSS = gitweb/static/gitweb.min.css
  else
 -OTHER_PROGRAMS += gitweb/gitweb.cgi
 -gitweb/gitweb.cgi: gitweb/gitweb.perl
 +GITWEB_CSS = gitweb/static/gitweb.css
  endif
 +OTHER_PROGRAMS +=  gitweb/gitweb.cgi  $(GITWEB_PROGRAMS)
 +gitweb/gitweb.cgi: gitweb/gitweb.perl $(GITWEB_PROGRAMS)
        $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@)
  
  ifdef JSMIN
 -gitweb/gitweb.min.js: gitweb/gitweb.js
 +gitweb/static/gitweb.min.js: gitweb/static/gitweb.js
        $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@)
  endif # JSMIN
 +ifdef CSSMIN
 +gitweb/static/gitweb.min.css: gitweb/static/gitweb.css
 +      $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@)
 +endif # CSSMIN
  
  
 -git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css gitweb/gitweb.js
 +git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/static/gitweb.css gitweb/static/gitweb.js
        $(QUIET_GEN)$(RM) $@ $@+ && \
        sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
            -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
            -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
 -          -e '/@@GITWEB_CGI@@/r gitweb/gitweb.cgi' \
 -          -e '/@@GITWEB_CGI@@/d' \
 -          -e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \
 -          -e '/@@GITWEB_CSS@@/d' \
 -          -e '/@@GITWEB_JS@@/r gitweb/gitweb.js' \
 -          -e '/@@GITWEB_JS@@/d' \
 +          -e 's|@@GITWEBDIR@@|$(gitwebdir_SQ)|g' \
            -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
            $@.sh > $@+ && \
        chmod +x $@+ && \
@@@ -1699,8 -1550,14 +1702,8 @@@ $(patsubst %.py,%,$(SCRIPT_PYTHON)): % 
        INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C git_remote_helpers -s \
                --no-print-directory prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' \
                instlibdir` && \
 -      sed -e '1{' \
 -          -e '        s|#!.*python|#!$(PYTHON_PATH_SQ)|' \
 -          -e '}' \
 -          -e 's|^import sys.*|&; \\\
 -                 import os; \\\
 -                 sys.path[0] = os.environ.has_key("GITPYTHONLIB") and \\\
 -                               os.environ["GITPYTHONLIB"] or \\\
 -                               "@@INSTLIBDIR@@"|' \
 +      sed -e '1s|#!.*python|#!$(PYTHON_PATH_SQ)|' \
 +          -e 's|\(os\.getenv("GITPYTHONLIB"\)[^)]*)|\1,"@@INSTLIBDIR@@")|' \
            -e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \
            $@.py >$@+ && \
        chmod +x $@+ && \
@@@ -1728,151 -1585,28 +1731,151 @@@ git.o git.spec 
        $(patsubst %.perl,%,$(SCRIPT_PERL)) \
        : GIT-VERSION-FILE
  
 -%.o: %.c GIT-CFLAGS
 -      $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
 +TEST_OBJS := $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
 +GIT_OBJS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
 +      git.o
 +ifndef NO_CURL
 +      GIT_OBJS += http.o http-walker.o remote-curl.o
 +endif
 +XDIFF_OBJS = xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
 +      xdiff/xmerge.o xdiff/xpatience.o
 +OBJECTS := $(GIT_OBJS) $(XDIFF_OBJS)
 +
 +dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
 +dep_dirs := $(addsuffix .depend,$(sort $(dir $(OBJECTS))))
 +
 +ifdef COMPUTE_HEADER_DEPENDENCIES
 +$(dep_dirs):
 +      mkdir -p $@
 +
 +missing_dep_dirs := $(filter-out $(wildcard $(dep_dirs)),$(dep_dirs))
 +dep_file = $(dir $@).depend/$(notdir $@).d
 +dep_args = -MF $(dep_file) -MMD -MP
 +ifdef CHECK_HEADER_DEPENDENCIES
 +$(error cannot compute header dependencies outside a normal build. \
 +Please unset CHECK_HEADER_DEPENDENCIES and try again)
 +endif
 +endif
 +
 +ifndef COMPUTE_HEADER_DEPENDENCIES
 +ifndef CHECK_HEADER_DEPENDENCIES
 +dep_dirs =
 +missing_dep_dirs =
 +dep_args =
 +endif
 +endif
 +
 +ifdef CHECK_HEADER_DEPENDENCIES
 +ifndef PRINT_HEADER_DEPENDENCIES
 +missing_deps = $(filter-out $(notdir $^), \
 +      $(notdir $(shell $(MAKE) -s $@ \
 +              CHECK_HEADER_DEPENDENCIES=YesPlease \
 +              USE_COMPUTED_HEADER_DEPENDENCIES=YesPlease \
 +              PRINT_HEADER_DEPENDENCIES=YesPlease)))
 +endif
 +endif
 +
 +ASM_SRC := $(wildcard $(OBJECTS:o=S))
 +ASM_OBJ := $(ASM_SRC:S=o)
 +C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS))
 +
 +.SUFFIXES:
 +
 +ifdef PRINT_HEADER_DEPENDENCIES
 +$(C_OBJ): %.o: %.c FORCE
 +      echo $^
 +$(ASM_OBJ): %.o: %.S FORCE
 +      echo $^
 +
 +ifndef CHECK_HEADER_DEPENDENCIES
 +$(error cannot print header dependencies during a normal build. \
 +Please set CHECK_HEADER_DEPENDENCIES and try again)
 +endif
 +endif
 +
 +ifndef PRINT_HEADER_DEPENDENCIES
 +ifdef CHECK_HEADER_DEPENDENCIES
 +$(C_OBJ): %.o: %.c $(dep_files) FORCE
 +      @set -e; echo CHECK $@; \
 +      missing_deps="$(missing_deps)"; \
 +      if test "$$missing_deps"; \
 +      then \
 +              echo missing dependencies: $$missing_deps; \
 +              false; \
 +      fi
 +$(ASM_OBJ): %.o: %.S $(dep_files) FORCE
 +      @set -e; echo CHECK $@; \
 +      missing_deps="$(missing_deps)"; \
 +      if test "$$missing_deps"; \
 +      then \
 +              echo missing dependencies: $$missing_deps; \
 +              false; \
 +      fi
 +endif
 +endif
 +
 +ifndef CHECK_HEADER_DEPENDENCIES
 +$(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs)
 +      $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
 +$(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs)
 +      $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
 +endif
 +
  %.s: %.c GIT-CFLAGS FORCE
 -      $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
 -%.o: %.S GIT-CFLAGS
 -      $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
 +      $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
  
 -exec_cmd.s exec_cmd.o: ALL_CFLAGS += \
 +ifdef USE_COMPUTED_HEADER_DEPENDENCIES
 +# Take advantage of gcc's on-the-fly dependency generation
 +# See <http://gcc.gnu.org/gcc-3.0/features.html>.
 +dep_files_present := $(wildcard $(dep_files))
 +ifneq ($(dep_files_present),)
 +include $(dep_files_present)
 +endif
 +else
 +# Dependencies on header files, for platforms that do not support
 +# the gcc -MMD option.
 +#
 +# Dependencies on automatically generated headers such as common-cmds.h
 +# should _not_ be included here, since they are necessary even when
 +# building an object for the first time.
 +#
 +# XXX. Please check occasionally that these include all dependencies
 +# gcc detects!
 +
 +$(GIT_OBJS): $(LIB_H)
 +builtin/branch.o builtin/checkout.o builtin/clone.o builtin/reset.o branch.o transport.o: branch.h
 +builtin/bundle.o bundle.o transport.o: bundle.h
 +builtin/bisect--helper.o builtin/rev-list.o bisect.o: bisect.h
 +builtin/clone.o builtin/fetch-pack.o transport.o: fetch-pack.h
 +builtin/grep.o: thread-utils.h
 +builtin/send-pack.o transport.o: send-pack.h
 +builtin/log.o builtin/shortlog.o: shortlog.h
 +builtin/prune.o builtin/reflog.o reachable.o: reachable.h
 +builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
 +builtin/tar-tree.o archive-tar.o: tar.h
 +builtin/pack-objects.o: thread-utils.h
 +http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
 +http.o http-walker.o http-push.o remote-curl.o: http.h
 +
 +xdiff-interface.o $(XDIFF_OBJS): \
 +      xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
 +      xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
 +endif
 +
 +exec_cmd.s exec_cmd.o: EXTRA_CPPFLAGS = \
        '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \
        '-DBINDIR="$(bindir_relative_SQ)"' \
        '-DPREFIX="$(prefix_SQ)"'
  
 -builtin-init-db.s builtin-init-db.o: ALL_CFLAGS += \
 +builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \
        -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"'
  
 -config.s config.o: ALL_CFLAGS += -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"'
 +config.s config.o: EXTRA_CPPFLAGS = -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"'
  
 -http.s http.o: ALL_CFLAGS += -DGIT_USER_AGENT='"git/$(GIT_VERSION)"'
 +http.s http.o: EXTRA_CPPFLAGS = -DGIT_USER_AGENT='"git/$(GIT_VERSION)"'
  
  ifdef NO_EXPAT
 -http-walker.o: http.h
 -http-walker.s http-walker.o: ALL_CFLAGS += -DNO_EXPAT
 +http-walker.s http-walker.o: EXTRA_CPPFLAGS = -DNO_EXPAT
  endif
  
  git-%$X: %.o $(GITLIBS)
@@@ -1882,6 -1616,10 +1885,6 @@@ git-imap-send$X: imap-send.o $(GITLIBS
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
  
 -http.o http-walker.o http-push.o: http.h
 -
 -http.o http-walker.o: $(LIB_H)
 -
  git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL)
@@@ -1899,9 -1637,18 +1902,9 @@@ $(REMOTE_CURL_PRIMARY): remote-curl.o h
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
  
 -$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
 -$(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h)
 -builtin-revert.o wt-status.o: wt-status.h
 -
  $(LIB_FILE): $(LIB_OBJS)
        $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
  
 -XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
 -      xdiff/xmerge.o xdiff/xpatience.o
 -$(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
 -      xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
 -
  $(XDIFF_LIB): $(XDIFF_OBJS)
        $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(XDIFF_OBJS)
  
@@@ -1950,18 -1697,10 +1953,18 @@@ GIT-CFLAGS: FORC
  GIT-BUILD-OPTIONS: FORCE
        @echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@
        @echo PERL_PATH=\''$(subst ','\'',$(PERL_PATH_SQ))'\' >>$@
 +      @echo DIFF=\''$(subst ','\'',$(subst ','\'',$(DIFF)))'\' >>$@
 +      @echo PYTHON_PATH=\''$(subst ','\'',$(PYTHON_PATH_SQ))'\' >>$@
        @echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@
        @echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@
        @echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@
        @echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@
 +ifdef GIT_TEST_CMP
 +      @echo GIT_TEST_CMP=\''$(subst ','\'',$(subst ','\'',$(GIT_TEST_CMP)))'\' >>$@
 +endif
 +ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
 +      @echo GIT_TEST_CMP_USE_COPIED_CONTEXT=YesPlease >>$@
 +endif
  
  ### Detect Tck/Tk interpreter path changes
  ifndef NO_TCLTK
@@@ -1975,6 -1714,24 +1978,6 @@@ GIT-GUI-VARS: FORC
              fi
  endif
  
 -### Testing rules
 -
 -TEST_PROGRAMS_NEED_X += test-chmtime
 -TEST_PROGRAMS_NEED_X += test-ctype
 -TEST_PROGRAMS_NEED_X += test-date
 -TEST_PROGRAMS_NEED_X += test-delta
 -TEST_PROGRAMS_NEED_X += test-dump-cache-tree
 -TEST_PROGRAMS_NEED_X += test-genrandom
 -TEST_PROGRAMS_NEED_X += test-match-trees
 -TEST_PROGRAMS_NEED_X += test-parse-options
 -TEST_PROGRAMS_NEED_X += test-path-utils
 -TEST_PROGRAMS_NEED_X += test-run-command
 -TEST_PROGRAMS_NEED_X += test-sha1
 -TEST_PROGRAMS_NEED_X += test-sigchain
 -TEST_PROGRAMS_NEED_X += test-index-version
 -
 -TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
 -
  test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
  
  all:: $(TEST_PROGRAMS) $(test_bindir_programs)
@@@ -1992,8 -1749,6 +1995,8 @@@ bin-wrappers/%: wrap-for-bin.s
  
  export NO_SVN_TESTS
  
 +### Testing rules
 +
  test: all
        $(MAKE) -C t/ all
  
@@@ -2005,7 -1760,9 +2008,7 @@@ test-delta$X: diff-delta.o patch-delta.
  
  test-parse-options$X: parse-options.o
  
 -test-parse-options.o: parse-options.h
 -
 -.PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
 +.PRECIOUS: $(TEST_OBJS)
  
  test-%$X: test-%.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
@@@ -2051,12 -1808,10 +2054,12 @@@ install: al
        $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
        $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
        $(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
 +      $(INSTALL) -m 644 $(SCRIPT_LIB) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
        $(INSTALL) $(install_bindir_programs) '$(DESTDIR_SQ)$(bindir_SQ)'
        $(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
  ifndef NO_PERL
        $(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
 +      $(MAKE) -C gitweb install
  endif
  ifndef NO_PYTHON
        $(MAKE) -C git_remote_helpers prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
@@@ -2082,18 -1837,14 +2085,18 @@@ endi
                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-gitweb:
 +      $(MAKE) -C gitweb install
 +
  install-doc:
        $(MAKE) -C Documentation install
  
@@@ -2175,11 -1926,10 +2178,11 @@@ distclean: clea
  
  clean:
        $(RM) *.o block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \
 -              $(LIB_FILE) $(XDIFF_LIB)
 -      $(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
 +              builtin/*.o $(LIB_FILE) $(XDIFF_LIB)
 +      $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS)
        $(RM) -r bin-wrappers
 +      $(RM) -r $(dep_dirs)
        $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope*
        $(RM) -r autom4te.cache
        $(RM) config.log config.mak.autogen config.mak.append config.status config.cache
        $(RM) $(htmldocs).tar.gz $(manpages).tar.gz
        $(MAKE) -C Documentation/ clean
  ifndef NO_PERL
 -      $(RM) gitweb/gitweb.cgi
 +      $(MAKE) -C gitweb clean
        $(MAKE) -C perl clean
  endif
  ifndef NO_PYTHON
@@@ -2209,13 -1959,12 +2212,13 @@@ endi
  ### Check documentation
  #
  check-docs::
 -      @(for v in $(ALL_PROGRAMS) $(BUILT_INS) git gitk; \
 +      @(for v in $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git gitk; \
        do \
                case "$$v" in \
                git-merge-octopus | git-merge-ours | git-merge-recursive | \
                git-merge-resolve | git-merge-subtree | \
                git-fsck-objects | git-init-db | \
 +              git-remote-* | git-stage | \
                git-?*--?* ) continue ;; \
                esac ; \
                test -f "Documentation/$$v.txt" || \
                documented,gitrepository-layout | \
                documented,gittutorial | \
                documented,gittutorial-2 | \
 +              documented,git-bisect-lk2009 | \
 +              documented,git-remote-helpers | \
 +              documented,gitworkflows | \
                sentinel,not,matching,is,ok ) continue ;; \
                esac; \
 -              case " $(ALL_PROGRAMS) $(BUILT_INS) git gitk " in \
 +              case " $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git gitk " in \
                *" $$cmd "*)    ;; \
                *) echo "removed but $$how: $$cmd" ;; \
                esac; \
diff --combined attr.c
index 7467baf2d6c81f94a7d043dcde13d463b3b46272,bf00469ecce6a3f74f7ef87f362b768b2bd9f05c..8ba606c933088e27ac08aabb546b764745f8187e
--- 1/attr.c
--- 2/attr.c
+++ b/attr.c
@@@ -287,7 -287,7 +287,7 @@@ static void free_attr_elem(struct attr_
  }
  
  static const char *builtin_attr[] = {
-       "[attr]binary -diff -crlf",
+       "[attr]binary -diff -text",
        NULL,
  };
  
@@@ -594,25 -594,20 +594,25 @@@ static int path_matches(const char *pat
        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;
@@@ -634,27 -629,19 +634,27 @@@ static int fill(const char *path, int p
        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;
  }
  
@@@ -679,6 -666,9 +679,6 @@@ int git_checkattr(const char *path, in
        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)
diff --combined cache.h
index 5e55367bf596d49a0e507d820aa3c104b9a7b6d5,ebe71c7e873599e53cff10d4f99ba6792fc60093..ff4a7c26d3b4dc6c9b28d8a28919b11fd71443bb
+++ b/cache.h
@@@ -361,7 -361,7 +361,7 @@@ enum object_type 
        OBJ_OFS_DELTA = 6,
        OBJ_REF_DELTA = 7,
        OBJ_ANY,
 -      OBJ_MAX,
 +      OBJ_MAX
  };
  
  static inline enum object_type object_type(unsigned int mode)
  #define ATTRIBUTE_MACRO_PREFIX "[attr]"
  #define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
  #define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
 +#define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
 +#define GIT_NOTES_REWRITE_REF_ENVIRONMENT "GIT_NOTES_REWRITE_REF"
 +#define GIT_NOTES_REWRITE_MODE_ENVIRONMENT "GIT_NOTES_REWRITE_MODE"
 +
 +/*
 + * Repository-local GIT_* environment variables
 + * The array is NULL-terminated to simplify its usage in contexts such
 + * environment creation or simple walk of the list.
 + * The number of non-NULL entries is available as a macro.
 + */
 +#define LOCAL_REPO_ENV_SIZE 8
 +extern const char *const local_repo_env[LOCAL_REPO_ENV_SIZE + 1];
  
  extern int is_bare_repository_cfg;
  extern int is_bare_repository(void);
@@@ -547,7 -535,6 +547,6 @@@ extern int core_compression_seen
  extern size_t packed_git_window_size;
  extern size_t packed_git_limit;
  extern size_t delta_base_cache_limit;
- extern int auto_crlf;
  extern int read_replace_refs;
  extern int fsync_object_files;
  extern int core_preload_index;
@@@ -556,32 -543,53 +555,53 @@@ extern int core_apply_sparse_checkout
  enum safe_crlf {
        SAFE_CRLF_FALSE = 0,
        SAFE_CRLF_FAIL = 1,
 -      SAFE_CRLF_WARN = 2,
 +      SAFE_CRLF_WARN = 2
  };
  
  extern enum safe_crlf safe_crlf;
  
+ enum auto_crlf {
+       AUTO_CRLF_FALSE = 0,
+       AUTO_CRLF_TRUE = 1,
+       AUTO_CRLF_INPUT = -1,
+ };
+ extern enum auto_crlf auto_crlf;
+ enum eol {
+       EOL_UNSET,
+       EOL_CRLF,
+       EOL_LF,
+ #ifdef NATIVE_CRLF
+       EOL_NATIVE = EOL_CRLF
+ #else
+       EOL_NATIVE = EOL_LF
+ #endif
+ };
+ extern enum eol eol;
  enum branch_track {
        BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,
        BRANCH_TRACK_REMOTE,
        BRANCH_TRACK_ALWAYS,
        BRANCH_TRACK_EXPLICIT,
 -      BRANCH_TRACK_OVERRIDE,
 +      BRANCH_TRACK_OVERRIDE
  };
  
  enum rebase_setup_type {
        AUTOREBASE_NEVER = 0,
        AUTOREBASE_LOCAL,
        AUTOREBASE_REMOTE,
 -      AUTOREBASE_ALWAYS,
 +      AUTOREBASE_ALWAYS
  };
  
  enum push_default_type {
        PUSH_DEFAULT_NOTHING = 0,
        PUSH_DEFAULT_MATCHING,
        PUSH_DEFAULT_TRACKING,
 -      PUSH_DEFAULT_CURRENT,
 +      PUSH_DEFAULT_CURRENT
  };
  
  extern enum branch_track git_branch_track;
@@@ -590,7 -598,7 +610,7 @@@ extern enum push_default_type push_defa
  
  enum object_creation_mode {
        OBJECT_CREATION_USES_HARDLINKS = 0,
 -      OBJECT_CREATION_USES_RENAMES = 1,
 +      OBJECT_CREATION_USES_RENAMES = 1
  };
  
  extern enum object_creation_mode object_creation_mode;
@@@ -653,10 -661,6 +673,10 @@@ int git_mkstemp(char *path, size_t n, c
  
  int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);
  
 +/* set default permissions by passing mode arguments to open(2) */
 +int git_mkstemps_mode(char *pattern, int suffix_len, int mode);
 +int git_mkstemp_mode(char *pattern, int mode);
 +
  /*
   * NOTE NOTE NOTE!!
   *
@@@ -670,7 -674,7 +690,7 @@@ enum sharedrepo 
        OLD_PERM_GROUP      = 1,
        OLD_PERM_EVERYBODY  = 2,
        PERM_GROUP          = 0660,
 -      PERM_EVERYBODY      = 0664,
 +      PERM_EVERYBODY      = 0664
  };
  int git_config_perm(const char *var, const char *value);
  int set_shared_perm(const char *path, int mode);
@@@ -691,7 -695,6 +711,7 @@@ int normalize_path_copy(char *dst, cons
  int longest_ancestor_length(const char *path, const char *prefix_list);
  char *strip_path_suffix(const char *path, const char *suffix);
  int daemon_avoid_alias(const char *path);
 +int offset_1st_component(const char *path);
  
  /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
  extern int sha1_object_info(const unsigned char *, unsigned long *);
@@@ -701,7 -704,7 +721,7 @@@ static inline void *read_sha1_file(cons
        return read_sha1_file_repl(sha1, type, size, NULL);
  }
  extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1);
 -extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
 +extern int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
  extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
  extern int force_object_loose(const unsigned char *sha1, time_t mtime);
  
@@@ -718,8 -721,6 +738,8 @@@ extern int has_loose_object_nonlocal(co
  
  extern int has_pack_index(const unsigned char *sha1);
  
 +extern void assert_sha1_type(const unsigned char *sha1, enum object_type expect);
 +
  extern const signed char hexval_table[256];
  static inline unsigned int hexval(unsigned char c)
  {
@@@ -794,7 -795,7 +814,7 @@@ extern const char *git_committer_info(i
  extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
  extern const char *fmt_name(const char *name, const char *email);
  extern const char *git_editor(void);
 -extern const char *git_pager(void);
 +extern const char *git_pager(int stdout_is_tty);
  
  struct checkout {
        const char *base_dir;
@@@ -882,7 -883,7 +902,7 @@@ struct ref 
                REF_STATUS_REJECT_NODELETE,
                REF_STATUS_UPTODATE,
                REF_STATUS_REMOTE_REJECT,
 -              REF_STATUS_EXPECTING_REPORT,
 +              REF_STATUS_EXPECTING_REPORT
        } status;
        char *remote_status;
        struct ref *peer_ref; /* when renaming */
  extern struct ref *find_ref_by_name(const struct ref *list, const char *name);
  
  #define CONNECT_VERBOSE       (1u << 0)
 +extern char *git_getpass(const char *prompt);
  extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
  extern int finish_connect(struct child_process *conn);
  extern int path_match(const char *path, int nr, char **match);
@@@ -907,7 -907,7 +927,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);
@@@ -918,7 -918,6 +938,7 @@@ extern struct packed_git *find_sha1_pac
  
  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 **);
@@@ -939,15 -938,12 +959,15 @@@ extern int update_server_info(int)
  typedef int (*config_fn_t)(const char *, const char *, void *);
  extern int git_default_config(const char *, const char *, void *);
  extern int git_config_from_file(config_fn_t fn, const char *, void *);
 +extern int git_config_parse_parameter(const char *text);
 +extern int git_config_from_parameters(config_fn_t fn, void *data);
  extern int git_config(config_fn_t fn, void *);
  extern int git_parse_ulong(const char *, unsigned long *);
  extern int git_config_int(const char *, const char *);
  extern unsigned long git_config_ulong(const char *, const char *);
  extern int git_config_bool_or_int(const char *, const char *, int *);
  extern int git_config_bool(const char *, const char *);
 +extern int git_config_maybe_bool(const char *, const char *);
  extern int git_config_string(const char **, const char *, const char *);
  extern int git_config_pathname(const char **, const char *, const char *);
  extern int git_config_set(const char *, const char *);
@@@ -955,7 -951,6 +975,7 @@@ extern int git_config_set_multivar(cons
  extern int git_config_rename_section(const char *, const char *);
  extern const char *git_etc_gitconfig(void);
  extern int check_repository_format_version(const char *var, const char *value, void *cb);
 +extern int git_env_bool(const char *, int);
  extern int git_config_system(void);
  extern int git_config_global(void);
  extern int config_error_nonbool(const char *);
@@@ -1047,7 -1042,6 +1067,7 @@@ void shift_tree_by(const unsigned char 
  #define WS_INDENT_WITH_NON_TAB        04
  #define WS_CR_AT_EOL           010
  #define WS_BLANK_AT_EOF        020
 +#define WS_TAB_IN_INDENT       040
  #define WS_TRAILING_SPACE      (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
  #define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB)
  extern unsigned whitespace_rule_cfg;
@@@ -1056,7 -1050,7 +1076,7 @@@ extern unsigned parse_whitespace_rule(c
  extern unsigned ws_check(const char *line, int len, unsigned ws_rule);
  extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
  extern char *whitespace_error_string(unsigned ws);
 -extern int ws_fix_copy(char *, const char *, int, unsigned, int *);
 +extern void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
  extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
  
  /* ls-files */
@@@ -1066,7 -1060,4 +1086,7 @@@ void overlay_tree_on_cache(const char *
  char *alias_lookup(const char *alias);
  int split_cmdline(char *cmdline, const char ***argv);
  
 +/* builtin/merge.c */
 +int checkout_fast_forward(const unsigned char *from, const unsigned char *to);
 +
  #endif /* CACHE_H */
diff --combined config.c
index 9b6b1df212252901b2e577009651ba8d26e4f25a,1479ee6ed4ae4c30e869bf576371a7cb9271fc64..cdcf5836c6c374eb59e80f89dbcf525fd6bf780f
+++ b/config.c
@@@ -7,7 -7,6 +7,7 @@@
   */
  #include "cache.h"
  #include "exec_cmd.h"
 +#include "strbuf.h"
  
  #define MAXNAME (256)
  
@@@ -19,48 -18,6 +19,48 @@@ static int zlib_compression_seen
  
  const char *config_exclusive_filename = NULL;
  
 +struct config_item
 +{
 +      struct config_item *next;
 +      char *name;
 +      char *value;
 +};
 +static struct config_item *config_parameters;
 +static struct config_item **config_parameters_tail = &config_parameters;
 +
 +static void lowercase(char *p)
 +{
 +      for (; *p; p++)
 +              *p = tolower(*p);
 +}
 +
 +int git_config_parse_parameter(const char *text)
 +{
 +      struct config_item *ct;
 +      struct strbuf tmp = STRBUF_INIT;
 +      struct strbuf **pair;
 +      strbuf_addstr(&tmp, text);
 +      pair = strbuf_split(&tmp, '=');
 +      if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=')
 +              strbuf_setlen(pair[0], pair[0]->len - 1);
 +      strbuf_trim(pair[0]);
 +      if (!pair[0]->len) {
 +              strbuf_list_free(pair);
 +              return -1;
 +      }
 +      ct = xcalloc(1, sizeof(struct config_item));
 +      ct->name = strbuf_detach(pair[0], NULL);
 +      if (pair[1]) {
 +              strbuf_trim(pair[1]);
 +              ct->value = strbuf_detach(pair[1], NULL);
 +      }
 +      strbuf_list_free(pair);
 +      lowercase(ct->name);
 +      *config_parameters_tail = ct;
 +      config_parameters_tail = &ct->next;
 +      return 0;
 +}
 +
  static int get_next_char(void)
  {
        int c;
@@@ -365,30 -322,17 +365,30 @@@ unsigned long git_config_ulong(const ch
        return ret;
  }
  
 -int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
 +int git_config_maybe_bool(const char *name, const char *value)
  {
 -      *is_bool = 1;
        if (!value)
                return 1;
        if (!*value)
                return 0;
 -      if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on"))
 +      if (!strcasecmp(value, "true")
 +          || !strcasecmp(value, "yes")
 +          || !strcasecmp(value, "on"))
                return 1;
 -      if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off"))
 +      if (!strcasecmp(value, "false")
 +          || !strcasecmp(value, "no")
 +          || !strcasecmp(value, "off"))
                return 0;
 +      return -1;
 +}
 +
 +int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
 +{
 +      int v = git_config_maybe_bool(name, value);
 +      if (0 <= v) {
 +              *is_bool = 1;
 +              return v;
 +      }
        *is_bool = 0;
        return git_config_int(name, value);
  }
@@@ -517,7 -461,9 +517,9 @@@ static int git_default_core_config(cons
  
        if (!strcmp(var, "core.autocrlf")) {
                if (value && !strcasecmp(value, "input")) {
-                       auto_crlf = -1;
+                       if (eol == EOL_CRLF)
+                               return error("core.autocrlf=input conflicts with core.eol=crlf");
+                       auto_crlf = AUTO_CRLF_INPUT;
                        return 0;
                }
                auto_crlf = git_config_bool(var, value);
                return 0;
        }
  
+       if (!strcmp(var, "core.eol")) {
+               if (value && !strcasecmp(value, "lf"))
+                       eol = EOL_LF;
+               else if (value && !strcasecmp(value, "crlf"))
+                       eol = EOL_CRLF;
+               else if (value && !strcasecmp(value, "native"))
+                       eol = EOL_NATIVE;
+               else
+                       eol = EOL_UNSET;
+               if (eol == EOL_CRLF && auto_crlf == AUTO_CRLF_INPUT)
+                       return error("core.autocrlf=input conflicts with core.eol=crlf");
+               return 0;
+       }
        if (!strcmp(var, "core.notesref")) {
                notes_ref_name = xstrdup(value);
                return 0;
@@@ -739,7 -699,7 +755,7 @@@ const char *git_etc_gitconfig(void
        return system_wide;
  }
  
 -static int git_env_bool(const char *k, int def)
 +int git_env_bool(const char *k, int def)
  {
        const char *v = getenv(k);
        return v ? git_config_bool(k, v) : def;
@@@ -755,15 -715,6 +771,15 @@@ int git_config_global(void
        return !git_env_bool("GIT_CONFIG_NOGLOBAL", 0);
  }
  
 +int git_config_from_parameters(config_fn_t fn, void *data)
 +{
 +      const struct config_item *ct;
 +      for (ct = config_parameters; ct; ct = ct->next)
 +              if (fn(ct->name, ct->value, data) < 0)
 +                      return -1;
 +      return 0;
 +}
 +
  int git_config(config_fn_t fn, void *data)
  {
        int ret = 0, found = 0;
                found += 1;
        }
        free(repo_config);
 +
 +      if (config_parameters) {
 +              ret += git_config_from_parameters(fn, data);
 +              found += 1;
 +      }
 +
        if (found == 0)
                return -1;
        return ret;
diff --combined convert.c
index 64dce3ff5741bc0e15ddb2daefcc521bb4075f4d,061fb23d6a196ce96d1d5b3e514d173a58ffe425..e41a31e4807e92e210854214d46767b9752c5181
+++ b/convert.c
@@@ -8,13 -8,17 +8,17 @@@
   * This should use the pathname to decide on whether it wants to do some
   * more interesting conversions (automatic gzip/unzip, general format
   * conversions etc etc), but by default it just does automatic CRLF<->LF
-  * translation when the "auto_crlf" option is set.
+  * translation when the "text" attribute or "auto_crlf" option is set.
   */
  
- #define CRLF_GUESS    (-1)
- #define CRLF_BINARY   0
- #define CRLF_TEXT     1
- #define CRLF_INPUT    2
+ enum action {
+       CRLF_GUESS = -1,
+       CRLF_BINARY = 0,
+       CRLF_TEXT,
+       CRLF_INPUT,
+       CRLF_CRLF,
+       CRLF_AUTO,
+ };
  
  struct text_stat {
        /* NUL, CR, LF and CRLF counts */
@@@ -89,31 -93,55 +93,55 @@@ static int is_binary(unsigned long size
        return 0;
  }
  
- static void check_safe_crlf(const char *path, int action,
+ static enum eol determine_output_conversion(enum action action) {
+       switch (action) {
+       case CRLF_BINARY:
+               return EOL_UNSET;
+       case CRLF_CRLF:
+               return EOL_CRLF;
+       case CRLF_INPUT:
+               return EOL_LF;
+       case CRLF_GUESS:
+               if (!auto_crlf)
+                       return EOL_UNSET;
+               /* fall through */
+       case CRLF_TEXT:
+       case CRLF_AUTO:
+               if (auto_crlf == AUTO_CRLF_TRUE)
+                       return EOL_CRLF;
+               else if (auto_crlf == AUTO_CRLF_INPUT)
+                       return EOL_LF;
+               else if (eol == EOL_UNSET)
+                       return EOL_NATIVE;
+       }
+       return eol;
+ }
+ static void check_safe_crlf(const char *path, enum action action,
                              struct text_stat *stats, enum safe_crlf checksafe)
  {
        if (!checksafe)
                return;
  
-       if (action == CRLF_INPUT || auto_crlf <= 0) {
+       if (determine_output_conversion(action) == EOL_LF) {
                /*
                 * CRLFs would not be restored by checkout:
                 * check if we'd remove CRLFs
                 */
                if (stats->crlf) {
                        if (checksafe == SAFE_CRLF_WARN)
-                               warning("CRLF will be replaced by LF in %s.", path);
+                               warning("CRLF will be replaced by LF in %s.\nThe file will have its original line endings in your working directory.", path);
                        else /* i.e. SAFE_CRLF_FAIL */
                                die("CRLF would be replaced by LF in %s.", path);
                }
-       } else if (auto_crlf > 0) {
+       } else if (determine_output_conversion(action) == EOL_CRLF) {
                /*
                 * CRLFs would be added by checkout:
                 * check if we have "naked" LFs
                 */
                if (stats->lf != stats->crlf) {
                        if (checksafe == SAFE_CRLF_WARN)
-                               warning("LF will be replaced by CRLF in %s", path);
+                               warning("LF will be replaced by CRLF in %s.\nThe file will have its original line endings in your working directory.", path);
                        else /* i.e. SAFE_CRLF_FAIL */
                                die("LF would be replaced by CRLF in %s", path);
                }
@@@ -158,17 -186,18 +186,18 @@@ static int has_cr_in_index(const char *
  }
  
  static int crlf_to_git(const char *path, const char *src, size_t len,
-                        struct strbuf *buf, int action, enum safe_crlf checksafe)
+                      struct strbuf *buf, enum action action, enum safe_crlf checksafe)
  {
        struct text_stat stats;
        char *dst;
  
-       if ((action == CRLF_BINARY) || !auto_crlf || !len)
+       if (action == CRLF_BINARY ||
+           (action == CRLF_GUESS && auto_crlf == AUTO_CRLF_FALSE) || !len)
                return 0;
  
        gather_stats(src, len, &stats);
  
-       if (action == CRLF_GUESS) {
+       if (action == CRLF_AUTO || action == CRLF_GUESS) {
                /*
                 * We're currently not going to even try to convert stuff
                 * that has bare CR characters. Does anybody do that crazy
                if (is_binary(len, &stats))
                        return 0;
  
-               /*
-                * If the file in the index has any CR in it, do not convert.
-                * This is the new safer autocrlf handling.
-                */
-               if (has_cr_in_index(path))
-                       return 0;
+               if (action == CRLF_GUESS) {
+                       /*
+                        * If the file in the index has any CR in it, do not convert.
+                        * This is the new safer autocrlf handling.
+                        */
+                       if (has_cr_in_index(path))
+                               return 0;
+               }
        }
  
        check_safe_crlf(path, action, &stats, checksafe);
        if (strbuf_avail(buf) + buf->len < len)
                strbuf_grow(buf, len - buf->len);
        dst = buf->buf;
-       if (action == CRLF_GUESS) {
+       if (action == CRLF_AUTO || action == CRLF_GUESS) {
                /*
                 * If we guessed, we already know we rejected a file with
                 * lone CR, and we can strip a CR without looking at what
  }
  
  static int crlf_to_worktree(const char *path, const char *src, size_t len,
-                             struct strbuf *buf, int action)
+                           struct strbuf *buf, enum action action)
  {
        char *to_free = NULL;
        struct text_stat stats;
  
-       if ((action == CRLF_BINARY) || (action == CRLF_INPUT) ||
-           auto_crlf <= 0)
-               return 0;
-       if (!len)
+       if (!len || determine_output_conversion(action) != EOL_CRLF)
                return 0;
  
        gather_stats(src, len, &stats);
        if (stats.lf == stats.crlf)
                return 0;
  
-       if (action == CRLF_GUESS) {
-               /* If we have any CR or CRLF line endings, we do not touch it */
-               /* This is the new safer autocrlf-handling */
-               if (stats.cr > 0 || stats.crlf > 0)
-                       return 0;
+       if (action == CRLF_AUTO || action == CRLF_GUESS) {
+               if (action == CRLF_GUESS) {
+                       /* If we have any CR or CRLF line endings, we do not touch it */
+                       /* This is the new safer autocrlf-handling */
+                       if (stats.cr > 0 || stats.crlf > 0)
+                               return 0;
+               }
  
                /* If we have any bare CR characters, we're not going to touch it */
                if (stats.cr != stats.crlf)
@@@ -290,7 -319,7 +319,7 @@@ struct filter_params 
        const char *cmd;
  };
  
 -static int filter_buffer(int fd, void *data)
 +static int filter_buffer(int in, int out, void *data)
  {
        /*
         * Spawn cmd and feed the buffer contents through its stdin.
        struct child_process child_process;
        struct filter_params *params = (struct filter_params *)data;
        int write_err, status;
 -      const char *argv[] = { params->cmd, NULL };
 +      const char *argv[] = { NULL, NULL };
 +
 +      argv[0] = params->cmd;
  
        memset(&child_process, 0, sizeof(child_process));
        child_process.argv = argv;
        child_process.use_shell = 1;
        child_process.in = -1;
 -      child_process.out = fd;
 +      child_process.out = out;
  
        if (start_command(&child_process))
                return error("cannot fork to run external filter %s", params->cmd);
@@@ -343,7 -370,6 +372,7 @@@ static int apply_filter(const char *pat
        memset(&async, 0, sizeof(async));
        async.proc = filter_buffer;
        async.data = &params;
 +      async.out = -1;
        params.src = src;
        params.size = len;
        params.cmd = cmd;
@@@ -425,12 -451,16 +454,16 @@@ static int read_convert_config(const ch
  
  static void setup_convert_check(struct git_attr_check *check)
  {
+       static struct git_attr *attr_text;
        static struct git_attr *attr_crlf;
+       static struct git_attr *attr_eol;
        static struct git_attr *attr_ident;
        static struct git_attr *attr_filter;
  
-       if (!attr_crlf) {
+       if (!attr_text) {
+               attr_text = git_attr("text");
                attr_crlf = git_attr("crlf");
+               attr_eol = git_attr("eol");
                attr_ident = git_attr("ident");
                attr_filter = git_attr("filter");
                user_convert_tail = &user_convert;
        check[0].attr = attr_crlf;
        check[1].attr = attr_ident;
        check[2].attr = attr_filter;
+       check[3].attr = attr_eol;
+       check[4].attr = attr_text;
  }
  
  static int count_ident(const char *cp, unsigned long size)
                                cnt++;
                                break;
                        }
 +                      if (ch == '\n')
 +                              break;
                }
        }
        return cnt;
@@@ -508,11 -538,6 +543,11 @@@ static int ident_to_git(const char *pat
                        dollar = memchr(src + 3, '$', len - 3);
                        if (!dollar)
                                break;
 +                      if (memchr(src + 3, '\n', dollar - src - 3)) {
 +                              /* Line break before the next dollar. */
 +                              continue;
 +                      }
 +
                        memcpy(dst, "Id$", 3);
                        dst += 3;
                        len -= dollar + 1 - src;
@@@ -528,7 -553,7 +563,7 @@@ static int ident_to_worktree(const cha
                               struct strbuf *buf, int ident)
  {
        unsigned char sha1[20];
 -      char *to_free = NULL, *dollar;
 +      char *to_free = NULL, *dollar, *spc;
        int cnt;
  
        if (!ident)
                } else if (src[2] == ':') {
                        /*
                         * It's possible that an expanded Id has crept its way into the
 -                       * repository, we cope with that by stripping the expansion out
 +                       * repository, we cope with that by stripping the expansion out.
 +                       * This is probably not a good idea, since it will cause changes
 +                       * on checkout, which won't go away by stash, but let's keep it
 +                       * for git-style ids.
                         */
                        dollar = memchr(src + 3, '$', len - 3);
                        if (!dollar) {
                                break;
                        }
  
 +                      if (memchr(src + 3, '\n', dollar - src - 3)) {
 +                              /* Line break before the next dollar. */
 +                              continue;
 +                      }
 +
 +                      spc = memchr(src + 4, ' ', dollar - src - 4);
 +                      if (spc && spc < dollar-1) {
 +                              /* There are spaces in unexpected places.
 +                               * This is probably an id from some other
 +                               * versioning system. Keep it for now.
 +                               */
 +                              continue;
 +                      }
 +
                        len -= dollar + 1 - src;
                        src  = dollar + 1;
                } else {
@@@ -619,9 -627,24 +654,24 @@@ static int git_path_check_crlf(const ch
                ;
        else if (!strcmp(value, "input"))
                return CRLF_INPUT;
+       else if (!strcmp(value, "auto"))
+               return CRLF_AUTO;
        return CRLF_GUESS;
  }
  
+ static int git_path_check_eol(const char *path, struct git_attr_check *check)
+ {
+       const char *value = check->value;
+       if (ATTR_UNSET(value))
+               ;
+       else if (!strcmp(value, "lf"))
+               return EOL_LF;
+       else if (!strcmp(value, "crlf"))
+               return EOL_CRLF;
+       return EOL_UNSET;
+ }
  static struct convert_driver *git_path_check_convert(const char *path,
                                             struct git_attr_check *check)
  {
@@@ -643,20 -666,34 +693,34 @@@ static int git_path_check_ident(const c
        return !!ATTR_TRUE(value);
  }
  
+ enum action determine_action(enum action text_attr, enum eol eol_attr) {
+       if (text_attr == CRLF_BINARY)
+               return CRLF_BINARY;
+       if (eol_attr == EOL_LF)
+               return CRLF_INPUT;
+       if (eol_attr == EOL_CRLF)
+               return CRLF_CRLF;
+       return text_attr;
+ }
  int convert_to_git(const char *path, const char *src, size_t len,
                     struct strbuf *dst, enum safe_crlf checksafe)
  {
-       struct git_attr_check check[3];
-       int crlf = CRLF_GUESS;
+       struct git_attr_check check[5];
+       enum action action = CRLF_GUESS;
+       enum eol eol_attr = EOL_UNSET;
        int ident = 0, ret = 0;
        const char *filter = NULL;
  
        setup_convert_check(check);
        if (!git_checkattr(path, ARRAY_SIZE(check), check)) {
                struct convert_driver *drv;
-               crlf = git_path_check_crlf(path, check + 0);
+               action = git_path_check_crlf(path, check + 4);
+               if (action == CRLF_GUESS)
+                       action = git_path_check_crlf(path, check + 0);
                ident = git_path_check_ident(path, check + 1);
                drv = git_path_check_convert(path, check + 2);
+               eol_attr = git_path_check_eol(path, check + 3);
                if (drv && drv->clean)
                        filter = drv->clean;
        }
                src = dst->buf;
                len = dst->len;
        }
-       ret |= crlf_to_git(path, src, len, dst, crlf, checksafe);
+       action = determine_action(action, eol_attr);
+       ret |= crlf_to_git(path, src, len, dst, action, checksafe);
        if (ret) {
                src = dst->buf;
                len = dst->len;
  
  int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)
  {
-       struct git_attr_check check[3];
-       int crlf = CRLF_GUESS;
+       struct git_attr_check check[5];
+       enum action action = CRLF_GUESS;
+       enum eol eol_attr = EOL_UNSET;
        int ident = 0, ret = 0;
        const char *filter = NULL;
  
        setup_convert_check(check);
        if (!git_checkattr(path, ARRAY_SIZE(check), check)) {
                struct convert_driver *drv;
-               crlf = git_path_check_crlf(path, check + 0);
+               action = git_path_check_crlf(path, check + 4);
+               if (action == CRLF_GUESS)
+                       action = git_path_check_crlf(path, check + 0);
                ident = git_path_check_ident(path, check + 1);
                drv = git_path_check_convert(path, check + 2);
+               eol_attr = git_path_check_eol(path, check + 3);
                if (drv && drv->smudge)
                        filter = drv->smudge;
        }
                src = dst->buf;
                len = dst->len;
        }
-       ret |= crlf_to_worktree(path, src, len, dst, crlf);
+       action = determine_action(action, eol_attr);
+       ret |= crlf_to_worktree(path, src, len, dst, action);
        if (ret) {
                src = dst->buf;
                len = dst->len;
diff --combined environment.c
index 876c5e53410250b5f2744671e39907c234771af3,5bafcd83a5b521ba3242fbaba5610b4ae4b9289c..83d38d3c2354e8582d5af91c6d529a2f2836dc2c
@@@ -38,8 -38,9 +38,9 @@@ const char *pager_program
  int pager_use_color = 1;
  const char *editor_program;
  const char *excludes_file;
- int auto_crlf = 0;    /* 1: both ways, -1: only when adding git objects */
+ enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
  int read_replace_refs = 1;
+ enum eol eol = EOL_UNSET;
  enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
  unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
  enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
@@@ -63,23 -64,6 +64,23 @@@ static char *work_tree
  static const char *git_dir;
  static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
  
 +/*
 + * Repository-local GIT_* environment variables
 + * Remember to update local_repo_env_size in cache.h when
 + * the size of the list changes
 + */
 +const char * const local_repo_env[LOCAL_REPO_ENV_SIZE + 1] = {
 +      ALTERNATE_DB_ENVIRONMENT,
 +      CONFIG_ENVIRONMENT,
 +      DB_ENVIRONMENT,
 +      GIT_DIR_ENVIRONMENT,
 +      GIT_WORK_TREE_ENVIRONMENT,
 +      GRAFT_ENVIRONMENT,
 +      INDEX_ENVIRONMENT,
 +      NO_REPLACE_OBJECTS_ENVIRONMENT,
 +      NULL
 +};
 +
  static void setup_git_env(void)
  {
        git_dir = getenv(GIT_DIR_ENVIRONMENT);
diff --combined git-cvsserver.perl
index 0f45c395098f2e19b7ce93ac17c45d128f05ff0d,4e55041ec79c6cb128ba2e8ebe30a3a7037ce29c..e9f3037df351ceed0262a8995f19903464163af8
@@@ -183,58 -183,12 +183,58 @@@ if ($state->{method} eq 'pserver') 
         exit 1;
      }
      $line = <STDIN>; chomp $line;
 -    unless ($line eq 'anonymous') {
 -       print "E Only anonymous user allowed via pserver\n";
 -       print "I HATE YOU\n";
 -       exit 1;
 +    my $user = $line;
 +    $line = <STDIN>; chomp $line;
 +    my $password = $line;
 +
 +    if ($user eq 'anonymous') {
 +        # "A" will be 1 byte, use length instead in case the
 +        # encryption method ever changes (yeah, right!)
 +        if (length($password) > 1 ) {
 +            print "E Don't supply a password for the `anonymous' user\n";
 +            print "I HATE YOU\n";
 +            exit 1;
 +        }
 +
 +        # Fall through to LOVE
 +    } else {
 +        # Trying to authenticate a user
 +        if (not exists $cfg->{gitcvs}->{authdb}) {
 +            print "E the repo config file needs a [gitcvs] section with an 'authdb' parameter set to the filename of the authentication database\n";
 +            print "I HATE YOU\n";
 +            exit 1;
 +        }
 +
 +        my $authdb = $cfg->{gitcvs}->{authdb};
 +
 +        unless (-e $authdb) {
 +            print "E The authentication database specified in [gitcvs.authdb] does not exist\n";
 +            print "I HATE YOU\n";
 +            exit 1;
 +        }
 +
 +        my $auth_ok;
 +        open my $passwd, "<", $authdb or die $!;
 +        while (<$passwd>) {
 +            if (m{^\Q$user\E:(.*)}) {
 +                if (crypt($user, descramble($password)) eq $1) {
 +                    $auth_ok = 1;
 +                }
 +            };
 +        }
 +        close $passwd;
 +
 +        unless ($auth_ok) {
 +            print "I HATE YOU\n";
 +            exit 1;
 +        }
 +
 +        # Fall through to LOVE
      }
 -    $line = <STDIN>; chomp $line;    # validate the password?
 +
 +    # For checking whether the user is anonymous on commit
 +    $state->{user} = $user;
 +
      $line = <STDIN>; chomp $line;
      unless ($line eq "END $request REQUEST") {
         die "E Do not understand $line -- expecting END $request REQUEST\n";
@@@ -1317,9 -1271,9 +1317,9 @@@ sub req_c
  
      $log->info("req_ci : " . ( defined($data) ? $data : "[NULL]" ));
  
 -    if ( $state->{method} eq 'pserver')
 +    if ( $state->{method} eq 'pserver' and $state->{user} eq 'anonymous' )
      {
 -        print "error 1 pserver access cannot commit\n";
 +        print "error 1 anonymous user cannot commit via pserver\n";
          cleanupWorkTree();
          exit;
      }
@@@ -2415,15 -2369,20 +2415,20 @@@ sub kopts_from_pat
      if ( defined ( $cfg->{gitcvs}{usecrlfattr} ) and
           $cfg->{gitcvs}{usecrlfattr} =~ /\s*(1|true|yes)\s*$/i )
      {
-         my ($val) = check_attr( "crlf", $path );
-         if ( $val eq "set" )
+         my ($val) = check_attr( "text", $path );
+         if ( $val eq "unspecified" )
          {
-             return "";
+             $val = check_attr( "crlf", $path );
          }
-         elsif ( $val eq "unset" )
+         if ( $val eq "unset" )
          {
              return "-kb"
          }
+         elsif ( check_attr( "eol", $path ) ne "unspecified" ||
+                 $val eq "set" || $val eq "input" )
+         {
+             return "";
+         }
          else
          {
              $log->info("Unrecognized check_attr crlf $path : $val");
@@@ -2632,43 -2591,6 +2637,43 @@@ sub cvs_autho
      $author;
  }
  
 +
 +sub descramble
 +{
 +    # This table is from src/scramble.c in the CVS source
 +    my @SHIFTS = (
 +        0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 +        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 +        114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
 +        111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
 +        41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
 +        125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
 +        36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
 +        58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
 +        225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
 +        199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
 +        174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
 +        207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
 +        192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
 +        227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
 +        182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
 +        243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152
 +    );
 +    my ($str) = @_;
 +
 +    # This should never happen, the same password format (A) has been
 +    # used by CVS since the beginning of time
 +    {
 +        my $fmt = substr($str, 0, 1);
 +        die "invalid password format `$fmt'" unless $fmt eq 'A';
 +    }
 +
 +    my @str = unpack "C*", substr($str, 1);
 +    my $ret = join '', map { chr $SHIFTS[$_] } @str;
 +    return $ret;
 +}
 +
 +
  package GITCVS::log;
  
  ####