Merge branch 'jk/skip-prefix'
authorJunio C Hamano <gitster@pobox.com>
Wed, 9 Jul 2014 18:33:27 +0000 (11:33 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 9 Jul 2014 18:33:28 +0000 (11:33 -0700)
* jk/skip-prefix:
http-push: refactor parsing of remote object names
imap-send: use skip_prefix instead of using magic numbers
use skip_prefix to avoid repeated calculations
git: avoid magic number with skip_prefix
fetch-pack: refactor parsing in get_ack
fast-import: refactor parsing of spaces
stat_opt: check extra strlen call
daemon: use skip_prefix to avoid magic numbers
fast-import: use skip_prefix for parsing input
use skip_prefix to avoid repeating strings
use skip_prefix to avoid magic numbers
transport-helper: avoid reading past end-of-string
fast-import: fix read of uninitialized argv memory
apply: use skip_prefix instead of raw addition
refactor skip_prefix to return a boolean
avoid using skip_prefix as a boolean
daemon: mark some strings as const
parse_diff_color_slot: drop ofs parameter

104 files changed:
Documentation/RelNotes/2.0.1.txt [new file with mode: 0644]
Documentation/RelNotes/2.1.0.txt
Documentation/config.txt
Documentation/fetch-options.txt
Documentation/git-fetch.txt
Documentation/git-send-email.txt
Documentation/git-submodule.txt
Documentation/git.txt
Documentation/pull-fetch-param.txt
Documentation/technical/api-strbuf.txt
Documentation/technical/http-protocol.txt
alloc.c
builtin/blame.c
builtin/clean.c
builtin/commit-tree.c
builtin/commit.c
builtin/diff-tree.c
builtin/fast-export.c
builtin/fetch.c
builtin/fmt-merge-msg.c
builtin/for-each-ref.c
builtin/fsck.c
builtin/index-pack.c
builtin/log.c
builtin/merge.c
builtin/pack-objects.c
builtin/repack.c
builtin/reset.c
builtin/rev-list.c
builtin/tag.c
cache.h
check_bindir
commit-slab.h
commit.c
commit.h
contrib/completion/git-completion.bash
contrib/examples/git-clone.sh
contrib/examples/git-commit.sh
contrib/examples/git-merge.sh
contrib/examples/git-repack.sh
contrib/examples/git-resolve.sh
dir.c
fetch-pack.c
fsck.c
git-bisect.sh
git-compat-util.h
git-gui/git-gui.sh
git-gui/lib/diff.tcl
git-mergetool.sh
git-p4.py
git-rebase--interactive.sh
git-rebase--merge.sh
git-send-email.perl
git-submodule.sh
git.c
gitk-git/gitk
gitk-git/po/vi.po [new file with mode: 0644]
http.c
line-log.c
log-tree.c
merge-recursive.c
name-hash.c
notes-cache.c
notes-merge.c
notes-utils.c
notes-utils.h
object.c
pretty.c
read-cache.c
refs.c
remote.c
revision.c
sequencer.c
sha1_name.c
t/lib-httpd.sh
t/lib-httpd/error.sh
t/perf/p5310-pack-bitmaps.sh
t/t0001-init.sh
t/t0008-ignores.sh
t/t0021-conversion.sh
t/t0025-crlf-auto.sh
t/t0026-eol-config.sh
t/t1402-check-ref-format.sh
t/t3302-notes-index-expensive.sh
t/t3402-rebase-merge.sh
t/t3419-rebase-patch-id.sh
t/t4102-apply-rename.sh
t/t5000-tar-tree.sh
t/t5310-pack-bitmaps.sh
t/t5403-post-checkout-hook.sh
t/t5510-fetch.sh
t/t5550-http-fetch-dumb.sh
t/t5551-http-fetch-smart.sh
t/t7300-clean.sh
t/t7700-repack.sh
t/t9001-send-email.sh
t/t9814-git-p4-rename.sh
t/t9902-completion.sh
t/test-lib-functions.sh
t/test-lib.sh
t/valgrind/default.supp
tree-walk.c
unicode_width.h
unpack-trees.c
diff --git a/Documentation/RelNotes/2.0.1.txt b/Documentation/RelNotes/2.0.1.txt
new file mode 100644 (file)
index 0000000..ce5579d
--- /dev/null
@@ -0,0 +1,115 @@
+Git v2.0.1 Release Notes
+========================
+
+ * We used to unconditionally disable the pager in the pager process
+   we spawn to feed out output, but that prevented people who want to
+   run "less" within "less" from doing so.
+
+ * Tools that read diagnostic output in our standard error stream do
+   not want to see terminal control sequence (e.g. erase-to-eol).
+   Detect them by checking if the standard error stream is connected
+   to a tty.
+ * Reworded the error message given upon a failure to open an existing
+   loose object file due to e.g. permission issues; it was reported as
+   the object being corrupt, but that is not quite true.
+
+ * "git log -2master" is a common typo that shows two commits starting
+   from whichever random branch that is not 'master' that happens to
+   be checked out currently.
+
+ * The "%<(10,trunc)%s" pretty format specifier in the log family of
+   commands is used to truncate the string to a given length (e.g. 10
+   in the example) with padding to column-align the output, but did
+   not take into account that number of bytes and number of display
+   columns are different.
+
+ * The "mailmap.file" configuration option did not support the tilde
+   expansion (i.e. ~user/path and ~/path).
+
+ * The completion scripts (in contrib/) did not know about quite a few
+   options that are common between "git merge" and "git pull", and a
+   couple of options unique to "git merge".
+
+ * "--ignore-space-change" option of "git apply" ignored the spaces
+   at the beginning of line too aggressively, which is inconsistent
+   with the option of the same name "diff" and "git diff" have.
+
+ * "git blame" miscounted number of columns needed to show localized
+   timestamps, resulting in jaggy left-side-edge of the source code
+   lines in its output.
+
+ * "git blame" assigned the blame to the copy in the working-tree if
+   the repository is set to core.autocrlf=input and the file used CRLF
+   line endings.
+
+ * "git commit --allow-empty-message -C $commit" did not work when the
+   commit did not have any log message.
+
+ * "git diff --find-copies-harder" sometimes pretended as if the mode
+   bits have changed for paths that are marked with assume-unchanged
+   bit.
+
+ * "git format-patch" did not enforce the rule that the "--follow"
+   option from the log/diff family of commands must be used with
+   exactly one pathspec.
+
+ * "git gc --auto" was recently changed to run in the background to
+   give control back early to the end-user sitting in front of the
+   terminal, but it forgot that housekeeping involving reflogs should
+   be done without other processes competing for accesses to the refs.
+
+ * "git grep -O" to show the lines that hit in the pager did not work
+   well with case insensitive search.  We now spawn "less" with its
+   "-I" option when it is used as the pager (which is the default).
+
+ * We used to disable threaded "git index-pack" on platforms without
+   thread-safe pread(); use a different workaround for such
+   platforms to allow threaded "git index-pack".
+
+ * The error reporting from "git index-pack" has been improved to
+   distinguish missing objects from type errors.
+
+ * "git mailinfo" used to read beyond the end of header string while
+   parsing an incoming e-mail message to extract the patch.
+
+ * On a case insensitive filesystem, merge-recursive incorrectly
+   deleted the file that is to be renamed to a name that is the same
+   except for case differences.
+
+ * "git pack-objects" unnecessarily copied the previous contents when
+   extending the hashtable, even though it will populate the table
+   from scratch anyway.
+
+ * "git rerere forget" did not work well when merge.conflictstyle
+   was set to a non-default value.
+
+ * "git remote rm" and "git remote prune" can involve removing many
+   refs at once, which is not a very efficient thing to do when very
+   many refs exist in the packed-refs file.
+
+ * "git log --exclude=<glob> --all | git shortlog" worked as expected,
+   but "git shortlog --exclude=<glob> --all", which is supposed to be
+   identical to the above pipeline, was not accepted at the command
+   line argument parser level.
+
+ * The autostash mode of "git rebase -i" did not restore the dirty
+   working tree state if the user aborted the interactive rebase by
+   emptying the insn sheet.
+
+ * "git show -s" (i.e. show log message only) used to incorrectly emit
+   an extra blank line after a merge commit.
+
+ * "git status", even though it is a read-only operation, tries to
+   update the index with refreshed lstat(2) info to optimize future
+   accesses to the working tree opportunistically, but this could
+   race with a "read-write" operation that modify the index while it
+   is running.  Detect such a race and avoid overwriting the index.
+
+ * "git status" (and "git commit") behaved as if changes in a modified
+   submodule are not there if submodule.*.ignore configuration is set,
+   which was misleading.  The configuration is only to unclutter diff
+   output during the course of development, and should not to hide
+   changes in the "status" output to cause the users forget to commit
+   them.
+
+ * The mode to run tests with HTTP server tests disabled was broken.
index 17360e5d535dd7c472d07a7dd13b729a22159f17..828a439dc11e85fc5a7dbf57a4b602efa356e7b6 100644 (file)
@@ -37,11 +37,14 @@ UI, Workflows & Features
    shorter than a page).
 
  * The logic and data used to compute the display width needed for
-   UTF-8 strings have been updated to match Unicode 6.3 better.
+   UTF-8 strings have been updated to match Unicode 7.0 better.
 
  * HTTP-based transports learned to propagate the error messages from
    the webserver better to the client coming over the HTTP transport.
 
+ * The completion script for bash (in contrib/) has been updated to
+   handle aliases that define complex sequence of commands better.
+
  * The "core.preloadindex" configuration variable is by default
    enabled, allowing modern platforms to take advantage of the
    multiple cores they have.
@@ -92,6 +95,10 @@ UI, Workflows & Features
 
  * "git replace" learned the "--edit" subcommand.
 
+ * "git send-email" learned "--to-cover" and "--cc-cover" options, to
+   tell it to copy To: and Cc: headers found in the first input file
+   when emitting later input files.
+
  * "git svn" learned to cope with malformed timestamps with only one
    digit in the hour part, e.g. 2014-01-07T5:01:02.048176Z, emitted
    by some broken subversion server implementations.
@@ -147,13 +154,18 @@ notes for details).
  * Mishandling of patterns in .gitignore that has trailing SPs quoted
    with backslashes (e.g. ones that end with "\ ") have been
    corrected.
-   (merge e61a6c1 pb/trim-trailing-spaces later to maint).
+   (merge 97c1364be6b pb/trim-trailing-spaces later to maint).
 
  * Reworded the error message given upon a failure to open an existing
    loose object file due to e.g. permission issues; it was reported as
    the object being corrupt, but that is not quite true.
    (merge d6c8a05 jk/report-fail-to-read-objects-better later to maint).
 
+ * "git log -2master" is a common typo that shows two commits starting
+   from whichever random branch that is not 'master' that happens to
+   be checked out currently.
+   (merge e3fa568 jc/revision-dash-count-parsing later to maint).
+
  * The "%<(10,trunc)%s" pretty format specifier in the log family of
    commands is used to truncate the string to a given length (e.g. 10
    in the example) with padding to column-align the output, but did
@@ -233,6 +245,11 @@ notes for details).
    from scratch anyway.
    (merge fb79947 rs/pack-objects-no-unnecessary-realloc later to maint).
 
+ * Recent updates to "git repack" started to duplicate objects that
+   are in packfiles marked with .keep flag into the new packfile by
+   mistake.
+   (merge d078d85 jk/repack-pack-keep-objects later to maint).
+
  * "git rerere forget" did not work well when merge.conflictstyle
    was set to a non-default value.
    (merge de3d8bb fc/rerere-conflict-style later to maint).
@@ -272,6 +289,10 @@ notes for details).
    them.
    (merge c215d3d jl/status-added-submodule-is-never-ignored later to maint).
 
+ * Documentation for "git submodule sync" forgot to say that the subcommand
+   can take the "--recursive" option.
+   (merge 9393ae7 mc/doc-submodule-sync-recurse later to maint).
+
  * "git update-index --cacheinfo" in 2.0 release crashed on a
    malformed command line.
    (merge c8e1ee4 jc/rev-parse-argh-dashed-multi-words later to maint).
index 9f467d3820a40d1281d29707e98fa16c2bbde63f..1d718bdb9662735d9b446033607c5f2aa92f8a78 100644 (file)
@@ -1905,12 +1905,7 @@ pack.useBitmaps::
        you are debugging pack bitmaps.
 
 pack.writebitmaps::
-       When true, git will write a bitmap index when packing all
-       objects to disk (e.g., when `git repack -a` is run).  This
-       index can speed up the "counting objects" phase of subsequent
-       packs created for clones and fetches, at the cost of some disk
-       space and extra time spent on the initial repack.  Defaults to
-       false.
+       This is a deprecated synonym for `repack.writeBitmaps`.
 
 pack.writeBitmapHashCache::
        When true, git will include a "hash cache" section in the bitmap
@@ -2187,7 +2182,15 @@ repack.packKeptObjects::
        `--pack-kept-objects` was passed. See linkgit:git-repack[1] for
        details. Defaults to `false` normally, but `true` if a bitmap
        index is being written (either via `--write-bitmap-index` or
-       `pack.writeBitmaps`).
+       `repack.writeBitmaps`).
+
+repack.writeBitmaps::
+       When true, git will write a bitmap index when packing all
+       objects to disk (e.g., when `git repack -a` is run).  This
+       index can speed up the "counting objects" phase of subsequent
+       packs created for clones and fetches, at the cost of some disk
+       space and extra time spent on the initial repack.  Defaults to
+       false.
 
 rerere.autoupdate::
        When set to true, `git-rerere` updates the index with the
index 92c68c3fdabafd9ac5afe74256dbd2d56218c247..b09a783ee313bf67cb07db03bb3127d252ab70c3 100644 (file)
@@ -72,6 +72,14 @@ endif::git-pull[]
        setting. See linkgit:git-config[1].
 
 ifndef::git-pull[]
+--refmap=<refspec>::
+       When fetching refs listed on the command line, use the
+       specified refspec (can be given more than once) to map the
+       refs to remote-tracking branches, instead of the values of
+       `remote.*.fetch` configuration variables for the remote
+       repository.  See section on "Configured Remote-tracking
+       Branches" for details.
+
 -t::
 --tags::
        Fetch all tags from the remote (i.e., fetch remote tags
index 5809aa4eb94e969bf700806b1ef3df504ebcfd2b..8deb61469d9cbd8786c27567851158c90c31aa8a 100644 (file)
@@ -17,22 +17,20 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Fetches named heads or tags from one or more other repositories,
-along with the objects necessary to complete them.
+Fetch branches and/or tags (collectively, "refs") from one or more
+other repositories, along with the objects necessary to complete their
+histories.  Remote-tracking branches are updated (see the description
+of <refspec> below for ways to control this behavior).
 
-The ref names and their object names of fetched refs are stored
-in `.git/FETCH_HEAD`.  This information is left for a later merge
-operation done by 'git merge'.
-
-By default, tags are auto-followed.  This means that when fetching
-from a remote, any tags on the remote that point to objects that exist
-in the local repository are fetched.  The effect is to fetch tags that
+By default, any tag that points into the histories being fetched is
+also fetched; the effect is to fetch tags that
 point at branches that you are interested in.  This default behavior
-can be changed by using the --tags or --no-tags options, by
-configuring remote.<name>.tagopt, or by using a refspec that fetches
-tags explicitly.
+can be changed by using the --tags or --no-tags options or by
+configuring remote.<name>.tagopt.  By using a refspec that fetches tags
+explicitly, you can fetch tags that do not point into branches you
+are interested in as well.
 
-'git fetch' can fetch from either a single named repository,
+'git fetch' can fetch from either a single named repository or URL,
 or from several repositories at once if <group> is given and
 there is a remotes.<group> entry in the configuration file.
 (See linkgit:git-config[1]).
@@ -40,6 +38,10 @@ there is a remotes.<group> entry in the configuration file.
 When no remote is specified, by default the `origin` remote will be used,
 unless there's an upstream branch configured for the current branch.
 
+The names of refs that are fetched, together with the object names
+they point at, are written to `.git/FETCH_HEAD`.  This information
+may be used by scripts or other git commands, such as linkgit:git-pull[1].
+
 OPTIONS
 -------
 include::fetch-options.txt[]
@@ -49,6 +51,55 @@ include::pull-fetch-param.txt[]
 include::urls-remotes.txt[]
 
 
+CONFIGURED REMOTE-TRACKING BRANCHES[[CRTB]]
+-------------------------------------------
+
+You often interact with the same remote repository by
+regularly and repeatedly fetching from it.  In order to keep track
+of the progress of such a remote repository, `git fetch` allows you
+to configure `remote.<repository>.fetch` configuration variables.
+
+Typically such a variable may look like this:
+
+------------------------------------------------
+[remote "origin"]
+       fetch = +refs/heads/*:refs/remotes/origin/*
+------------------------------------------------
+
+This configuration is used in two ways:
+
+* When `git fetch` is run without specifying what branches
+  and/or tags to fetch on the command line, e.g. `git fetch origin`
+  or `git fetch`, `remote.<repository>.fetch` values are used as
+  the refspecs---they specify which refs to fetch and which local refs
+  to update.  The example above will fetch
+  all branches that exist in the `origin` (i.e. any ref that matches
+  the left-hand side of the value, `refs/heads/*`) and update the
+  corresponding remote-tracking branches in the `refs/remotes/origin/*`
+  hierarchy.
+
+* When `git fetch` is run with explicit branches and/or tags
+  to fetch on the command line, e.g. `git fetch origin master`, the
+  <refspec>s given on the command line determine what are to be
+  fetched (e.g. `master` in the example,
+  which is a short-hand for `master:`, which in turn means
+  "fetch the 'master' branch but I do not explicitly say what
+  remote-tracking branch to update with it from the command line"),
+  and the example command will
+  fetch _only_ the 'master' branch.  The `remote.<repository>.fetch`
+  values determine which
+  remote-tracking branch, if any, is updated.  When used in this
+  way, the `remote.<repository>.fetch` values do not have any
+  effect in deciding _what_ gets fetched (i.e. the values are not
+  used as refspecs when the command-line lists refspecs); they are
+  only used to decide _where_ the refs that are fetched are stored
+  by acting as a mapping.
+
+The latter use of the `remote.<repository>.fetch` values can be
+overridden by giving the `--refmap=<refspec>` parameter(s) on the
+command line.
+
+
 EXAMPLES
 --------
 
@@ -76,6 +127,19 @@ the local repository by fetching from the branches (respectively)
 The `pu` branch will be updated even if it is does not fast-forward,
 because it is prefixed with a plus sign; `tmp` will not be.
 
+* Peek at a remote's branch, without configuring the remote in your local
+repository:
++
+------------------------------------------------
+$ git fetch git://git.kernel.org/pub/scm/git/git.git maint
+$ git log FETCH_HEAD
+------------------------------------------------
++
+The first command fetches the `maint` branch from the repository at
+`git://git.kernel.org/pub/scm/git/git.git` and the second command uses
+`FETCH_HEAD` to examine the branch with linkgit:git-log[1].  The fetched
+objects will eventually be removed by git's built-in housekeeping (see
+linkgit:git-gc[1]).
 
 BUGS
 ----
index d0fa18aaa8b14f9171800a05742fb1fe326b547b..a60776eb579e10507814c643cc292dfa99750aa9 100644 (file)
@@ -248,6 +248,18 @@ Automating
        cc list. Default is the value of 'sendemail.signedoffbycc' configuration
        value; if that is unspecified, default to --signed-off-by-cc.
 
+--[no-]cc-cover::
+       If this is set, emails found in Cc: headers in the first patch of
+       the series (typically the cover letter) are added to the cc list
+       for each email set. Default is the value of 'sendemail.cccover'
+       configuration value; if that is unspecified, default to --no-cc-cover.
+
+--[no-]to-cover::
+       If this is set, emails found in To: headers in the first patch of
+       the series (typically the cover letter) are added to the to list
+       for each email set. Default is the value of 'sendemail.tocover'
+       configuration value; if that is unspecified, default to --no-to-cover.
+
 --suppress-cc=<category>::
        Specify an additional category of recipients to suppress the
        auto-cc of:
index 89c4d3e39474ed601255371c30b98bdd569f671d..8e6af65da0e0f234315c42391a8bab42fc39abb6 100644 (file)
@@ -20,7 +20,7 @@ SYNOPSIS
 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
              [commit] [--] [<path>...]
 'git submodule' [--quiet] foreach [--recursive] <command>
-'git submodule' [--quiet] sync [--] [<path>...]
+'git submodule' [--quiet] sync [--recursive] [--] [<path>...]
 
 
 DESCRIPTION
index 3bd68b016791ac082e2a556a4835b22ba241b92f..79242096714e90a385e9b63a60326a41f8bd983d 100644 (file)
@@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.0.0/git.html[documentation for release 2.0]
+* link:v2.0.1/git.html[documentation for release 2.0.1]
 
 * release notes for
+  link:RelNotes/2.0.1.txt[2.0.1],
   link:RelNotes/2.0.0.txt[2.0.0].
 
 * link:v1.9.4/git.html[documentation for release 1.9.4]
index 18cffc25b809fa3695b0cc60c732d058e8843ed6..1ebbf1d738403204b77a6b18547de25e94ab28be 100644 (file)
@@ -12,9 +12,23 @@ ifndef::git-pull[]
 endif::git-pull[]
 
 <refspec>::
-       The format of a <refspec> parameter is an optional plus
-       `+`, followed by the source ref <src>, followed
-       by a colon `:`, followed by the destination ref <dst>.
+       Specifies which refs to fetch and which local refs to update.
+       When no <refspec>s appear on the command line, the refs to fetch
+       are read from `remote.<repository>.fetch` variables instead
+ifndef::git-pull[]
+       (see <<CRTB,CONFIGURED REMOTE-TRACKING BRANCHES>> below).
+endif::git-pull[]
+ifdef::git-pull[]
+       (see linkgit:git-fetch[1]).
+endif::git-pull[]
++
+The format of a <refspec> parameter is an optional plus
+`+`, followed by the source ref <src>, followed
+by a colon `:`, followed by the destination ref <dst>.
+The colon can be omitted when <dst> is empty.
++
+`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`;
+it requests fetching everything up to the given tag.
 +
 The remote ref that matches <src>
 is fetched, and if <dst> is not empty string, the local
@@ -24,55 +38,34 @@ is updated even if it does not result in a fast-forward
 update.
 +
 [NOTE]
-If the remote branch from which you want to pull is
-modified in non-linear ways such as being rewound and
-rebased frequently, then a pull will attempt a merge with
-an older version of itself, likely conflict, and fail.
-It is under these conditions that you would want to use
-the `+` sign to indicate non-fast-forward updates will
-be needed.  There is currently no easy way to determine
-or declare that a branch will be made available in a
-repository with this behavior; the pulling user simply
+When the remote branch you want to fetch is known to
+be rewound and rebased regularly, it is expected that
+its new tip will not be descendant of its previous tip
+(as stored in your remote-tracking branch the last time
+you fetched).  You would want
+to use the `+` sign to indicate non-fast-forward updates
+will be needed for such branches.  There is no way to
+determine or declare that a branch will be made available
+in a repository with this behavior; the pulling user simply
 must know this is the expected usage pattern for a branch.
-+
-[NOTE]
-You never do your own development on branches that appear
-on the right hand side of a <refspec> colon on `Pull:` lines;
-they are to be updated by 'git fetch'.  If you intend to do
-development derived from a remote branch `B`, have a `Pull:`
-line to track it (i.e. `Pull: B:remote-B`), and have a separate
-branch `my-B` to do your development on top of it.  The latter
-is created by `git branch my-B remote-B` (or its equivalent `git
-checkout -b my-B remote-B`).  Run `git fetch` to keep track of
-the progress of the remote side, and when you see something new
-on the remote branch, merge it into your development branch with
-`git pull . remote-B`, while you are on `my-B` branch.
+ifdef::git-pull[]
 +
 [NOTE]
 There is a difference between listing multiple <refspec>
 directly on 'git pull' command line and having multiple
-`Pull:` <refspec> lines for a <repository> and running
+`remote.<repository>.fetch` entries in your configuration
+for a <repository> and running a
 'git pull' command without any explicit <refspec> parameters.
-<refspec> listed explicitly on the command line are always
+<refspec>s listed explicitly on the command line are always
 merged into the current branch after fetching.  In other words,
-if you list more than one remote refs, you would be making
-an Octopus.  While 'git pull' run without any explicit <refspec>
-parameter takes default <refspec>s from `Pull:` lines, it
-merges only the first <refspec> found into the current branch,
-after fetching all the remote refs.  This is because making an
+if you list more than one remote ref, 'git pull' will create
+an Octopus merge.  On the other hand, if you do not list any
+explicit <refspec> parameter on the command line, 'git pull'
+will fetch all the <refspec>s it finds in the
+`remote.<repository>.fetch` configuration and merge
+only the first <refspec> found into the current branch.
+This is because making an
 Octopus from remote refs is rarely done, while keeping track
 of multiple remote heads in one-go by fetching more than one
 is often useful.
-+
-Some short-cut notations are also supported.
-+
-* `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`;
-  it requests fetching everything up to the given tag.
-ifndef::git-pull[]
-* A parameter <ref> without a colon fetches that ref into FETCH_HEAD,
-endif::git-pull[]
-ifdef::git-pull[]
-* A parameter <ref> without a colon merges <ref> into the current
-  branch,
 endif::git-pull[]
-  and updates the remote-tracking branches (if any).
index 077a7096a4ba3c47a0cbc8981abdde1b7b35d924..f9c06a7573e9294a967d641cdfc2723b86c1c864 100644 (file)
@@ -7,10 +7,10 @@ use the mem* functions than a str* one (memchr vs. strchr e.g.).
 Though, one has to be careful about the fact that str* functions often
 stop on NULs and that strbufs may have embedded NULs.
 
-An strbuf is NUL terminated for convenience, but no function in the
+A strbuf is NUL terminated for convenience, but no function in the
 strbuf API actually relies on the string being free of NULs.
 
-strbufs has some invariants that are very important to keep in mind:
+strbufs have some invariants that are very important to keep in mind:
 
 . The `buf` member is never NULL, so it can be used in any usual C
 string operations safely. strbuf's _have_ to be initialized either by
@@ -56,8 +56,8 @@ Data structures
 * `struct strbuf`
 
 This is the string buffer structure. The `len` member can be used to
-determine the current length of the string, and `buf` member provides access to
-the string itself.
+determine the current length of the string, and `buf` member provides
+access to the string itself.
 
 Functions
 ---------
@@ -202,7 +202,7 @@ strbuf_addstr(sb, "immediate string");
 
 `strbuf_addbuf`::
 
-       Copy the contents of an other buffer at the end of the current one.
+       Copy the contents of another buffer at the end of the current one.
 
 `strbuf_adddup`::
 
index 59be59b0ebba8c24875643521c9135ab907a33ce..229f845dfa67b9c2e74b2eb1de80a224ea757b53 100644 (file)
@@ -60,7 +60,7 @@ Because Git repositories are accessed by standard path components
 server administrators MAY use directory based permissions within
 their HTTP server to control repository access.
 
-Clients SHOULD support Basic authentication as described by RFC 2616.
+Clients SHOULD support Basic authentication as described by RFC 2617.
 Servers SHOULD support Basic authentication by relying upon the
 HTTP server placed in front of the Git server software.
 
diff --git a/alloc.c b/alloc.c
index f3ee745695643c00f175288a9592ab073dd589b0..eb22a45c9d0acf08a6024094bd0a2090a7307945 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -47,23 +47,32 @@ union any_object {
 
 DEFINE_ALLOCATOR(blob, struct blob)
 DEFINE_ALLOCATOR(tree, struct tree)
-DEFINE_ALLOCATOR(commit, struct commit)
+DEFINE_ALLOCATOR(raw_commit, struct commit)
 DEFINE_ALLOCATOR(tag, struct tag)
 DEFINE_ALLOCATOR(object, union any_object)
 
+void *alloc_commit_node(void)
+{
+       static int commit_count;
+       struct commit *c = alloc_raw_commit_node();
+       c->index = commit_count++;
+       return c;
+}
+
 static void report(const char *name, unsigned int count, size_t size)
 {
        fprintf(stderr, "%10s: %8u (%"PRIuMAX" kB)\n",
                        name, count, (uintmax_t) size);
 }
 
-#define REPORT(name)   \
-    report(#name, name##_allocs, name##_allocs * sizeof(struct name) >> 10)
+#define REPORT(name, type)     \
+    report(#name, name##_allocs, name##_allocs * sizeof(type) >> 10)
 
 void alloc_report(void)
 {
-       REPORT(blob);
-       REPORT(tree);
-       REPORT(commit);
-       REPORT(tag);
+       REPORT(blob, struct blob);
+       REPORT(tree, struct tree);
+       REPORT(raw_commit, struct commit);
+       REPORT(tag, struct tag);
+       REPORT(object, union any_object);
 }
index a52a279144bec14f2b2a0795f30e0c5871f60c1b..d3b256e545a76b096682223539c4faec8d770b2f 100644 (file)
@@ -1655,7 +1655,7 @@ static void get_commit_info(struct commit *commit,
 {
        int len;
        const char *subject, *encoding;
-       char *message;
+       const char *message;
 
        commit_info_init(ret);
 
@@ -1666,7 +1666,7 @@ static void get_commit_info(struct commit *commit,
                    &ret->author_time, &ret->author_tz);
 
        if (!detailed) {
-               logmsg_free(message, commit);
+               unuse_commit_buffer(commit, message);
                return;
        }
 
@@ -1680,7 +1680,7 @@ static void get_commit_info(struct commit *commit,
        else
                strbuf_addf(&ret->summary, "(%s)", sha1_to_hex(commit->object.sha1));
 
-       logmsg_free(message, commit);
+       unuse_commit_buffer(commit, message);
 }
 
 /*
@@ -2008,6 +2008,12 @@ static void output(struct scoreboard *sb, int option)
        }
 }
 
+static const char *get_next_line(const char *start, const char *end)
+{
+       const char *nl = memchr(start, '\n', end - start);
+       return nl ? nl + 1 : end;
+}
+
 /*
  * To allow quick access to the contents of nth line in the
  * final image, prepare an index in the scoreboard.
@@ -2019,39 +2025,19 @@ static int prepare_lines(struct scoreboard *sb)
        const char *end = buf + len;
        const char *p;
        int *lineno;
-       int num = 0, incomplete = 0;
+       int num = 0;
 
-       for (p = buf;;) {
-               p = memchr(p, '\n', end - p);
-               if (p) {
-                       p++;
-                       num++;
-                       continue;
-               }
-               break;
-       }
+       for (p = buf; p < end; p = get_next_line(p, end))
+               num++;
 
-       if (len && end[-1] != '\n')
-               incomplete++; /* incomplete line at the end */
+       sb->lineno = lineno = xmalloc(sizeof(*sb->lineno) * (num + 1));
 
-       sb->lineno = xmalloc(sizeof(*sb->lineno) * (num + incomplete + 1));
-       lineno = sb->lineno;
+       for (p = buf; p < end; p = get_next_line(p, end))
+               *lineno++ = p - buf;
 
-       *lineno++ = 0;
-       for (p = buf;;) {
-               p = memchr(p, '\n', end - p);
-               if (p) {
-                       p++;
-                       *lineno++ = p - buf;
-                       continue;
-               }
-               break;
-       }
+       *lineno = len;
 
-       if (incomplete)
-               *lineno++ = len;
-
-       sb->num_lines = num + incomplete;
+       sb->num_lines = num;
        return sb->num_lines;
 }
 
@@ -2265,6 +2251,18 @@ static void append_merge_parents(struct commit_list **tail)
        strbuf_release(&line);
 }
 
+/*
+ * This isn't as simple as passing sb->buf and sb->len, because we
+ * want to transfer ownership of the buffer to the commit (so we
+ * must use detach).
+ */
+static void set_commit_buffer_from_strbuf(struct commit *c, struct strbuf *sb)
+{
+       size_t len;
+       void *buf = strbuf_detach(sb, &len);
+       set_commit_buffer(c, buf, len);
+}
+
 /*
  * Prepare a dummy commit that represents the work tree (or staged) item.
  * Note that annotating work tree item never works in the reverse.
@@ -2286,7 +2284,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
        struct strbuf msg = STRBUF_INIT;
 
        time(&now);
-       commit = xcalloc(1, sizeof(*commit));
+       commit = alloc_commit_node();
        commit->object.parsed = 1;
        commit->date = now;
        commit->object.type = OBJ_COMMIT;
@@ -2313,7 +2311,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
                    ident, ident, path,
                    (!contents_from ? path :
                     (!strcmp(contents_from, "-") ? "standard input" : contents_from)));
-       commit->buffer = strbuf_detach(&msg, NULL);
+       set_commit_buffer_from_strbuf(commit, &msg);
 
        if (!contents_from || strcmp("-", contents_from)) {
                struct stat st;
index 9a9151575d3a8d4eb16d73e432835d3cda4374b8..27701d222c78ed84691b65334a7909f90c589464 100644 (file)
@@ -48,7 +48,7 @@ enum color_clean {
        CLEAN_COLOR_PROMPT = 2,
        CLEAN_COLOR_HEADER = 3,
        CLEAN_COLOR_HELP = 4,
-       CLEAN_COLOR_ERROR = 5,
+       CLEAN_COLOR_ERROR = 5
 };
 
 #define MENU_OPTS_SINGLETON            01
index 987a4c3d731d7cf01f61e4fddec208b4cb51a4af..8a66c74e0fd405a06e6c767d385013ff7150db04 100644 (file)
@@ -123,8 +123,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
                        die_errno("git commit-tree: failed to read");
        }
 
-       if (commit_tree(&buffer, tree_sha1, parents, commit_sha1,
-                       NULL, sign_commit)) {
+       if (commit_tree(buffer.buf, buffer.len, tree_sha1, parents,
+                       commit_sha1, NULL, sign_commit)) {
                strbuf_release(&buffer);
                return 1;
        }
index ec753412381f26b29274805d32524515171bb39d..461c3b1cade4a995d3eb3cc212645791245865e0 100644 (file)
@@ -1744,8 +1744,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                append_merge_tag_headers(parents, &tail);
        }
 
-       if (commit_tree_extended(&sb, active_cache_tree->sha1, parents, sha1,
-                                author_ident.buf, sign_commit, extra)) {
+       if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->sha1,
+                        parents, sha1, author_ident.buf, sign_commit, extra)) {
                rollback_index_files();
                die(_("failed to write commit object"));
        }
index be6417d166abf428d379a70b9d67f894da4641d1..ce0e019e0caa358e1f5e39e5ed51bec3945197e0 100644 (file)
@@ -22,14 +22,10 @@ static int stdin_diff_commit(struct commit *commit, char *line, int len)
        if (isspace(line[40]) && !get_sha1_hex(line+41, sha1)) {
                /* Graft the fake parents locally to the commit */
                int pos = 41;
-               struct commit_list **pptr, *parents;
+               struct commit_list **pptr;
 
                /* Free the real parent list */
-               for (parents = commit->parents; parents; ) {
-                       struct commit_list *tmp = parents->next;
-                       free(parents);
-                       parents = tmp;
-               }
+               free_commit_list(commit->parents);
                commit->parents = NULL;
                pptr = &(commit->parents);
                while (line[pos] && !get_sha1_hex(line + pos, sha1)) {
index ef4481615fd2f4d60cd3cd6a4bbcceaca93c92d5..92b4624a4b93ff50c661e44242d508aed31877eb 100644 (file)
@@ -282,6 +282,7 @@ static const char *find_encoding(const char *begin, const char *end)
 static void handle_commit(struct commit *commit, struct rev_info *rev)
 {
        int saved_output_format = rev->diffopt.output_format;
+       const char *commit_buffer;
        const char *author, *author_end, *committer, *committer_end;
        const char *encoding, *message;
        char *reencoded = NULL;
@@ -291,7 +292,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
        rev->diffopt.output_format = DIFF_FORMAT_CALLBACK;
 
        parse_commit_or_die(commit);
-       author = strstr(commit->buffer, "\nauthor ");
+       commit_buffer = get_commit_buffer(commit, NULL);
+       author = strstr(commit_buffer, "\nauthor ");
        if (!author)
                die ("Could not find author in commit %s",
                     sha1_to_hex(commit->object.sha1));
@@ -338,6 +340,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
                          ? strlen(message) : 0),
               reencoded ? reencoded : message ? message : "");
        free(reencoded);
+       unuse_commit_buffer(commit, commit_buffer);
 
        for (i = 0, p = commit->parents; p; p = p->next) {
                int mark = get_object_mark(&p->item->object);
index 55f457c04f5c72ca31ab4fbc28e62ea48b6cb471..dd46b61d9a31475e3d5289e41e6d7f57a0264b6f 100644 (file)
@@ -45,6 +45,8 @@ static struct transport *gsecondary;
 static const char *submodule_prefix = "";
 static const char *recurse_submodules_default;
 static int shown_url = 0;
+static int refmap_alloc, refmap_nr;
+static const char **refmap_array;
 
 static int option_parse_recurse_submodules(const struct option *opt,
                                   const char *arg, int unset)
@@ -69,6 +71,19 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
        return 0;
 }
 
+static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
+{
+       ALLOC_GROW(refmap_array, refmap_nr + 1, refmap_alloc);
+
+       /*
+        * "git fetch --refmap='' origin foo"
+        * can be used to tell the command not to store anywhere
+        */
+       if (*arg)
+               refmap_array[refmap_nr++] = arg;
+       return 0;
+}
+
 static struct option builtin_fetch_options[] = {
        OPT__VERBOSITY(&verbosity),
        OPT_BOOL(0, "all", &all,
@@ -107,6 +122,8 @@ static struct option builtin_fetch_options[] = {
                   N_("default mode for recursion"), PARSE_OPT_HIDDEN },
        OPT_BOOL(0, "update-shallow", &update_shallow,
                 N_("accept refs that update .git/shallow")),
+       { OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"),
+         N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg },
        OPT_END()
 };
 
@@ -278,6 +295,9 @@ static struct ref *get_ref_map(struct transport *transport,
        const struct ref *remote_refs = transport_get_remote_refs(transport);
 
        if (refspec_count) {
+               struct refspec *fetch_refspec;
+               int fetch_refspec_nr;
+
                for (i = 0; i < refspec_count; i++) {
                        get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
                        if (refspecs[i].dst && refspecs[i].dst[0])
@@ -307,12 +327,21 @@ static struct ref *get_ref_map(struct transport *transport,
                 * by ref_remove_duplicates() in favor of one of these
                 * opportunistic entries with FETCH_HEAD_IGNORE.
                 */
-               for (i = 0; i < transport->remote->fetch_refspec_nr; i++)
-                       get_fetch_map(ref_map, &transport->remote->fetch[i],
-                                     &oref_tail, 1);
+               if (refmap_array) {
+                       fetch_refspec = parse_fetch_refspec(refmap_nr, refmap_array);
+                       fetch_refspec_nr = refmap_nr;
+               } else {
+                       fetch_refspec = transport->remote->fetch;
+                       fetch_refspec_nr = transport->remote->fetch_refspec_nr;
+               }
+
+               for (i = 0; i < fetch_refspec_nr; i++)
+                       get_fetch_map(ref_map, &fetch_refspec[i], &oref_tail, 1);
 
                if (tags == TAGS_SET)
                        get_fetch_map(remote_refs, tag_refspec, &tail, 0);
+       } else if (refmap_array) {
+               die("--refmap option is only meaningful with command-line refspec(s).");
        } else {
                /* Use the defaults */
                struct remote *remote = transport->remote;
index ad3bc58c74a2b6927d3604e458e01a14b9834946..971e802c6f2945cb6218b7a98c9a30fdc0c9f94b 100644 (file)
@@ -230,12 +230,14 @@ static void add_branch_desc(struct strbuf *out, const char *name)
 static void record_person(int which, struct string_list *people,
                          struct commit *commit)
 {
+       const char *buffer;
        char *name_buf, *name, *name_end;
        struct string_list_item *elem;
        const char *field;
 
        field = (which == 'a') ? "\nauthor " : "\ncommitter ";
-       name = strstr(commit->buffer, field);
+       buffer = get_commit_buffer(commit, NULL);
+       name = strstr(buffer, field);
        if (!name)
                return;
        name += strlen(field);
@@ -247,6 +249,7 @@ static void record_person(int which, struct string_list *people,
        if (name_end < name)
                return;
        name_buf = xmemdupz(name, name_end - name + 1);
+       unuse_commit_buffer(commit, buffer);
 
        elem = string_list_lookup(people, name_buf);
        if (!elem) {
index 3e1d5c3334e50035fdbf835cfdafbb39c0bacfd0..4135980f20786ef3320e334c4001fd67fc169056 100644 (file)
@@ -193,7 +193,7 @@ static int verify_format(const char *format)
                at = parse_atom(sp + 2, ep);
                cp = ep + 1;
 
-               if (!memcmp(used_atom[at], "color:", 6))
+               if (starts_with(used_atom[at], "color:"))
                        need_color_reset_at_eol = !!strcmp(used_atom[at], color_reset);
        }
        return 0;
index fc150c882122c53965fd246ad862e3a75d8768e2..8aadca160e857be8a87ec1f152e51eb6f51c90b5 100644 (file)
@@ -310,8 +310,7 @@ static int fsck_obj(struct object *obj)
        if (obj->type == OBJ_COMMIT) {
                struct commit *commit = (struct commit *) obj;
 
-               free(commit->buffer);
-               commit->buffer = NULL;
+               free_commit_buffer(commit);
 
                if (!commit->parents && show_root)
                        printf("root %s\n", sha1_to_hex(commit->object.sha1));
index 18f57de58b02de33909a40ea9720e6602cc9dcb5..8b3bd29dbcf22668040c53fffb6e2414ca090f5d 100644 (file)
@@ -786,7 +786,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
                        }
                        if (obj->type == OBJ_COMMIT) {
                                struct commit *commit = (struct commit *) obj;
-                               commit->buffer = NULL;
+                               if (detach_commit_buffer(commit, NULL) != data)
+                                       die("BUG: parse_object_buffer transmogrified our buffer");
                        }
                        obj->flags |= FLAG_CHECKED;
                }
index 0f59c25d362d8238786a884f0a154f29bd97d767..27c1b65db46bb1bead9045b7b6be08a1ee199835 100644 (file)
@@ -347,8 +347,7 @@ static int cmd_log_walk(struct rev_info *rev)
                        rev->max_count++;
                if (!rev->reflog_info) {
                        /* we allow cycles in reflog ancestry */
-                       free(commit->buffer);
-                       commit->buffer = NULL;
+                       free_commit_buffer(commit);
                }
                free_commit_list(commit->parents);
                commit->parents = NULL;
@@ -925,9 +924,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
        log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
                                &need_8bit_cte);
 
-       for (i = 0; !need_8bit_cte && i < nr; i++)
-               if (has_non_ascii(list[i]->buffer))
+       for (i = 0; !need_8bit_cte && i < nr; i++) {
+               const char *buf = get_commit_buffer(list[i], NULL);
+               if (has_non_ascii(buf))
                        need_8bit_cte = 1;
+               unuse_commit_buffer(list[i], buf);
+       }
 
        if (!branch_name)
                branch_name = find_branch_name(rev);
@@ -1528,8 +1530,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                    reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
                        die(_("Failed to create output files"));
                shown = log_tree_commit(&rev, commit);
-               free(commit->buffer);
-               commit->buffer = NULL;
+               free_commit_buffer(commit);
 
                /* We put one extra blank line between formatted
                 * patches and this flag is used by log-tree code
index 428ca247bd17e0f18776b46d40a09282b0b955de..b49c310866f76434c3838484c0bf997a1230c7ed 100644 (file)
@@ -852,8 +852,8 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
        parent->next->item = remoteheads->item;
        parent->next->next = NULL;
        prepare_to_commit(remoteheads);
-       if (commit_tree(&merge_msg, result_tree, parent, result_commit, NULL,
-                       sign_commit))
+       if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parent,
+                       result_commit, NULL, sign_commit))
                die(_("failed to write commit object"));
        finish(head, remoteheads, result_commit, "In-index merge");
        drop_save();
@@ -877,8 +877,8 @@ static int finish_automerge(struct commit *head,
                commit_list_insert(head, &parents);
        strbuf_addch(&merge_msg, '\n');
        prepare_to_commit(remoteheads);
-       if (commit_tree(&merge_msg, result_tree, parents, result_commit,
-                       NULL, sign_commit))
+       if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,
+                       result_commit, NULL, sign_commit))
                die(_("failed to write commit object"));
        strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
        finish(head, remoteheads, result_commit, buf.buf);
index de36c60ca11d248013c2de42d196f1aff8a2937b..238b5021eb105007a42061d5f8febc455530da45 100644 (file)
@@ -2214,10 +2214,6 @@ static int git_pack_config(const char *k, const char *v, void *cb)
                cache_max_small_delta_size = git_config_int(k, v);
                return 0;
        }
-       if (!strcmp(k, "pack.writebitmaps")) {
-               write_bitmap_index = git_config_bool(k, v);
-               return 0;
-       }
        if (!strcmp(k, "pack.writebitmaphashcache")) {
                if (git_config_bool(k, v))
                        write_bitmap_options |= BITMAP_OPT_HASH_CACHE;
index 6b0b62dcb2687e78ec433e7de1103f0c0f74a1fc..ff2216a7aaefa3b38385301e4e0d8bb8b94e4ea0 100644 (file)
@@ -10,6 +10,7 @@
 
 static int delta_base_offset = 1;
 static int pack_kept_objects = -1;
+static int write_bitmaps;
 static char *packdir, *packtmp;
 
 static const char *const git_repack_usage[] = {
@@ -27,6 +28,11 @@ static int repack_config(const char *var, const char *value, void *cb)
                pack_kept_objects = git_config_bool(var, value);
                return 0;
        }
+       if (!strcmp(var, "repack.writebitmaps") ||
+           !strcmp(var, "pack.writebitmaps")) {
+               write_bitmaps = git_config_bool(var, value);
+               return 0;
+       }
        return git_default_config(var, value, cb);
 }
 
@@ -149,7 +155,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
        int no_update_server_info = 0;
        int quiet = 0;
        int local = 0;
-       int write_bitmap = -1;
 
        struct option builtin_repack_options[] = {
                OPT_BIT('a', NULL, &pack_everything,
@@ -168,7 +173,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                OPT__QUIET(&quiet, N_("be quiet")),
                OPT_BOOL('l', "local", &local,
                                N_("pass --local to git-pack-objects")),
-               OPT_BOOL('b', "write-bitmap-index", &write_bitmap,
+               OPT_BOOL('b', "write-bitmap-index", &write_bitmaps,
                                N_("write bitmap index")),
                OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
                                N_("with -A, do not loosen objects older than this")),
@@ -191,7 +196,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                                git_repack_usage, 0);
 
        if (pack_kept_objects < 0)
-               pack_kept_objects = write_bitmap;
+               pack_kept_objects = write_bitmaps;
 
        packdir = mkpathdup("%s/pack", get_object_directory());
        packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
@@ -217,9 +222,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                argv_array_pushf(&cmd_args, "--no-reuse-delta");
        if (no_reuse_object)
                argv_array_pushf(&cmd_args, "--no-reuse-object");
-       if (write_bitmap >= 0)
-               argv_array_pushf(&cmd_args, "--%swrite-bitmap-index",
-                                write_bitmap ? "" : "no-");
+       if (write_bitmaps)
+               argv_array_push(&cmd_args, "--write-bitmap-index");
 
        if (pack_everything & ALL_INTO_ONE) {
                get_non_kept_pack_filenames(&existing_packs);
index f368266762fae1e6c783d7351e289e423e408b3c..850d53229a1ac757d294ffca6261c9a28af014df 100644 (file)
@@ -93,7 +93,7 @@ static int reset_index(const unsigned char *sha1, int reset_type, int quiet)
 static void print_new_head_line(struct commit *commit)
 {
        const char *hex, *body;
-       char *msg;
+       const char *msg;
 
        hex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
        printf(_("HEAD is now at %s"), hex);
@@ -109,7 +109,7 @@ static void print_new_head_line(struct commit *commit)
        }
        else
                printf("\n");
-       logmsg_free(msg, commit);
+       unuse_commit_buffer(commit, msg);
 }
 
 static void update_index_from_diff(struct diff_queue_struct *q,
index 9f92905379d1801a35bfad87bc05002d76dc23f4..ff84a825ff776abc01087f37782223ee26a1af7a 100644 (file)
@@ -106,7 +106,7 @@ static void show_commit(struct commit *commit, void *data)
        else
                putchar('\n');
 
-       if (revs->verbose_header && commit->buffer) {
+       if (revs->verbose_header && get_cached_commit_buffer(commit, NULL)) {
                struct strbuf buf = STRBUF_INIT;
                struct pretty_print_context ctx = {0};
                ctx.abbrev = revs->abbrev;
@@ -173,8 +173,7 @@ static void finish_commit(struct commit *commit, void *data)
                free_commit_list(commit->parents);
                commit->parents = NULL;
        }
-       free(commit->buffer);
-       commit->buffer = NULL;
+       free_commit_buffer(commit);
 }
 
 static void finish_object(struct object *obj,
index c6e8a7112700c03b2615f9c99c9858884128ab25..ef765563388c384a127d27eaf7ee6fd1badfe84f 100644 (file)
@@ -83,7 +83,7 @@ static int in_commit_list(const struct commit_list *want, struct commit *c)
 enum contains_result {
        CONTAINS_UNKNOWN = -1,
        CONTAINS_NO = 0,
-       CONTAINS_YES = 1,
+       CONTAINS_YES = 1
 };
 
 /*
diff --git a/cache.h b/cache.h
index cbe1935ba6b17b6ccc37a400ea7cf0f67830e1d0..df65231ac3db7ae08b5d9cfd37c505c4573c1675 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -999,7 +999,7 @@ extern int validate_headref(const char *ref);
 
 extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);
 extern int df_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);
-extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2);
+extern int name_compare(const char *name1, size_t len1, const char *name2, size_t len2);
 extern int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2);
 
 extern void *read_object_with_reference(const unsigned char *sha1,
index a1c4c3e8d845e8e791d7df0c1387e1b2262b5ecf..623eadcbb7dd2b7f58be0ef070b8c805a8101add 100755 (executable)
@@ -2,7 +2,7 @@
 bindir="$1"
 gitexecdir="$2"
 gitcmd="$3"
-if test "$bindir" != "$gitexecdir" -a -x "$gitcmd"
+if test "$bindir" != "$gitexecdir" && test -x "$gitcmd"
 then
        echo
        echo "!! You have installed git-* commands to new gitexecdir."
index cc114b53b096c6fc8574629b86659a639fdfed61..375c9c751adbf165c757832667102b761e1358c3 100644 (file)
@@ -117,4 +117,16 @@ static int stat_ ##slabname## realloc
  * catch because GCC silently parses it by default.
  */
 
+/*
+ * Statically initialize a commit slab named "var". Note that this
+ * evaluates "stride" multiple times! Example:
+ *
+ *   struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees);
+ *
+ */
+#define COMMIT_SLAB_INIT(stride, var) { \
+       COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \
+       (stride), 0, NULL \
+}
+
 #endif /* COMMIT_SLAB_H */
index dfc0eb02415edccba6195b4d2925196caa242a1a..fb7897c2a4cef3298c014cbac86081b1d6adc837 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -17,7 +17,6 @@ static struct commit_extra_header *read_commit_extra_header_lines(const char *bu
 int save_commit_buffer = 1;
 
 const char *commit_type = "commit";
-static int commit_count;
 
 static struct commit *check_commit(struct object *obj,
                                   const unsigned char *sha1,
@@ -64,7 +63,6 @@ struct commit *lookup_commit(const unsigned char *sha1)
        struct object *obj = lookup_object(sha1);
        if (!obj) {
                struct commit *c = alloc_commit_node();
-               c->index = commit_count++;
                return create_object(sha1, OBJ_COMMIT, c);
        }
        if (!obj->type)
@@ -247,6 +245,76 @@ int unregister_shallow(const unsigned char *sha1)
        return 0;
 }
 
+struct commit_buffer {
+       void *buffer;
+       unsigned long size;
+};
+define_commit_slab(buffer_slab, struct commit_buffer);
+static struct buffer_slab buffer_slab = COMMIT_SLAB_INIT(1, buffer_slab);
+
+void set_commit_buffer(struct commit *commit, void *buffer, unsigned long size)
+{
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       v->buffer = buffer;
+       v->size = size;
+}
+
+const void *get_cached_commit_buffer(const struct commit *commit, unsigned long *sizep)
+{
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       if (sizep)
+               *sizep = v->size;
+       return v->buffer;
+}
+
+const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
+{
+       const void *ret = get_cached_commit_buffer(commit, sizep);
+       if (!ret) {
+               enum object_type type;
+               unsigned long size;
+               ret = read_sha1_file(commit->object.sha1, &type, &size);
+               if (!ret)
+                       die("cannot read commit object %s",
+                           sha1_to_hex(commit->object.sha1));
+               if (type != OBJ_COMMIT)
+                       die("expected commit for %s, got %s",
+                           sha1_to_hex(commit->object.sha1), typename(type));
+               if (sizep)
+                       *sizep = size;
+       }
+       return ret;
+}
+
+void unuse_commit_buffer(const struct commit *commit, const void *buffer)
+{
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       if (v->buffer != buffer)
+               free((void *)buffer);
+}
+
+void free_commit_buffer(struct commit *commit)
+{
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       free(v->buffer);
+       v->buffer = NULL;
+       v->size = 0;
+}
+
+const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
+{
+       struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
+       void *ret;
+
+       ret = v->buffer;
+       if (sizep)
+               *sizep = v->size;
+
+       v->buffer = NULL;
+       v->size = 0;
+       return ret;
+}
+
 int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size)
 {
        const char *tail = buffer;
@@ -324,7 +392,7 @@ int parse_commit(struct commit *item)
        }
        ret = parse_commit_buffer(item, buffer, size);
        if (save_commit_buffer && !ret) {
-               item->buffer = buffer;
+               set_commit_buffer(item, buffer, size);
                return 0;
        }
        free(buffer);
@@ -539,22 +607,12 @@ static void record_author_date(struct author_date_slab *author_date,
                               struct commit *commit)
 {
        const char *buf, *line_end, *ident_line;
-       char *buffer = NULL;
+       const char *buffer = get_commit_buffer(commit, NULL);
        struct ident_split ident;
        char *date_end;
        unsigned long date;
 
-       if (!commit->buffer) {
-               unsigned long size;
-               enum object_type type;
-               buffer = read_sha1_file(commit->object.sha1, &type, &size);
-               if (!buffer)
-                       return;
-       }
-
-       for (buf = commit->buffer ? commit->buffer : buffer;
-            buf;
-            buf = line_end + 1) {
+       for (buf = buffer; buf; buf = line_end + 1) {
                line_end = strchrnul(buf, '\n');
                if (!skip_prefix(buf, "author ", &ident_line)) {
                        if (!line_end[0] || line_end[1] == '\n')
@@ -574,7 +632,7 @@ static void record_author_date(struct author_date_slab *author_date,
        *(author_date_slab_at(author_date, commit)) = date;
 
 fail_exit:
-       free(buffer);
+       unuse_commit_buffer(commit, buffer);
 }
 
 static int compare_commits_by_author_date(const void *a_, const void *b_,
@@ -1079,17 +1137,14 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)
        return 0;
 }
 
-int parse_signed_commit(const unsigned char *sha1,
+int parse_signed_commit(const struct commit *commit,
                        struct strbuf *payload, struct strbuf *signature)
 {
+
        unsigned long size;
-       enum object_type type;
-       char *buffer = read_sha1_file(sha1, &type, &size);
+       const char *buffer = get_commit_buffer(commit, &size);
        int in_signature, saw_signature = -1;
-       char *line, *tail;
-
-       if (!buffer || type != OBJ_COMMIT)
-               goto cleanup;
+       const char *line, *tail;
 
        line = buffer;
        tail = buffer + size;
@@ -1097,7 +1152,7 @@ int parse_signed_commit(const unsigned char *sha1,
        saw_signature = 0;
        while (line < tail) {
                const char *sig = NULL;
-               char *next = memchr(line, '\n', tail - line);
+               const char *next = memchr(line, '\n', tail - line);
 
                next = next ? next + 1 : tail;
                if (in_signature && line[0] == ' ')
@@ -1118,8 +1173,7 @@ int parse_signed_commit(const unsigned char *sha1,
                }
                line = next;
        }
- cleanup:
-       free(buffer);
+       unuse_commit_buffer(commit, buffer);
        return saw_signature;
 }
 
@@ -1209,8 +1263,7 @@ void check_commit_signature(const struct commit* commit, struct signature_check
 
        sigc->result = 'N';
 
-       if (parse_signed_commit(commit->object.sha1,
-                               &payload, &signature) <= 0)
+       if (parse_signed_commit(commit, &payload, &signature) <= 0)
                goto out;
        status = verify_signed_buffer(payload.buf, payload.len,
                                      signature.buf, signature.len,
@@ -1255,11 +1308,9 @@ struct commit_extra_header *read_commit_extra_headers(struct commit *commit,
 {
        struct commit_extra_header *extra = NULL;
        unsigned long size;
-       enum object_type type;
-       char *buffer = read_sha1_file(commit->object.sha1, &type, &size);
-       if (buffer && type == OBJ_COMMIT)
-               extra = read_commit_extra_header_lines(buffer, size, exclude);
-       free(buffer);
+       const char *buffer = get_commit_buffer(commit, &size);
+       extra = read_commit_extra_header_lines(buffer, size, exclude);
+       unuse_commit_buffer(commit, buffer);
        return extra;
 }
 
@@ -1342,7 +1393,8 @@ void free_commit_extra_headers(struct commit_extra_header *extra)
        }
 }
 
-int commit_tree(const struct strbuf *msg, const unsigned char *tree,
+int commit_tree(const char *msg, size_t msg_len,
+               const unsigned char *tree,
                struct commit_list *parents, unsigned char *ret,
                const char *author, const char *sign_commit)
 {
@@ -1350,7 +1402,7 @@ int commit_tree(const struct strbuf *msg, const unsigned char *tree,
        int result;
 
        append_merge_tag_headers(parents, &tail);
-       result = commit_tree_extended(msg, tree, parents, ret,
+       result = commit_tree_extended(msg, msg_len, tree, parents, ret,
                                      author, sign_commit, extra);
        free_commit_extra_headers(extra);
        return result;
@@ -1471,7 +1523,8 @@ static const char commit_utf8_warn[] =
 "You may want to amend it after fixing the message, or set the config\n"
 "variable i18n.commitencoding to the encoding your project uses.\n";
 
-int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
+int commit_tree_extended(const char *msg, size_t msg_len,
+                        const unsigned char *tree,
                         struct commit_list *parents, unsigned char *ret,
                         const char *author, const char *sign_commit,
                         struct commit_extra_header *extra)
@@ -1482,7 +1535,7 @@ int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
 
        assert_sha1_type(tree, OBJ_TREE);
 
-       if (memchr(msg->buf, '\0', msg->len))
+       if (memchr(msg, '\0', msg_len))
                return error("a NUL byte in commit log message not allowed.");
 
        /* Not having i18n.commitencoding is the same as having utf-8 */
@@ -1521,7 +1574,7 @@ int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
        strbuf_addch(&buffer, '\n');
 
        /* And add the comment */
-       strbuf_addbuf(&buffer, msg);
+       strbuf_add(&buffer, msg, msg_len);
 
        /* And check the encoding */
        if (encoding_is_utf8 && !verify_utf8(&buffer))
index a9f177ba488a7002409eb2cdee1f7e9c3673529f..2e1492a6e4d1c5fc5bea3a48180f128601c3461e 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -20,7 +20,6 @@ struct commit {
        unsigned long date;
        struct commit_list *parents;
        struct tree *tree;
-       char *buffer;
 };
 
 extern int save_commit_buffer;
@@ -51,6 +50,44 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s
 int parse_commit(struct commit *item);
 void parse_commit_or_die(struct commit *item);
 
+/*
+ * Associate an object buffer with the commit. The ownership of the
+ * memory is handed over to the commit, and must be free()-able.
+ */
+void set_commit_buffer(struct commit *, void *buffer, unsigned long size);
+
+/*
+ * Get any cached object buffer associated with the commit. Returns NULL
+ * if none. The resulting memory should not be freed.
+ */
+const void *get_cached_commit_buffer(const struct commit *, unsigned long *size);
+
+/*
+ * Get the commit's object contents, either from cache or by reading the object
+ * from disk. The resulting memory should not be modified, and must be given
+ * to unuse_commit_buffer when the caller is done.
+ */
+const void *get_commit_buffer(const struct commit *, unsigned long *size);
+
+/*
+ * Tell the commit subsytem that we are done with a particular commit buffer.
+ * The commit and buffer should be the input and return value, respectively,
+ * from an earlier call to get_commit_buffer.  The buffer may or may not be
+ * freed by this call; callers should not access the memory afterwards.
+ */
+void unuse_commit_buffer(const struct commit *, const void *buffer);
+
+/*
+ * Free any cached object buffer associated with the commit.
+ */
+void free_commit_buffer(struct commit *);
+
+/*
+ * Disassociate any cached object buffer from the commit, but do not free it.
+ * The buffer (or NULL, if none) is returned.
+ */
+const void *detach_commit_buffer(struct commit *, unsigned long *sizep);
+
 /* Find beginning and length of commit subject. */
 int find_commit_subject(const char *commit_buffer, const char **subject);
 
@@ -115,10 +152,9 @@ struct userformat_want {
 
 extern int has_non_ascii(const char *text);
 struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
-extern char *logmsg_reencode(const struct commit *commit,
-                            char **commit_encoding,
-                            const char *output_encoding);
-extern void logmsg_free(char *msg, const struct commit *commit);
+extern const char *logmsg_reencode(const struct commit *commit,
+                                  char **commit_encoding,
+                                  const char *output_encoding);
 extern void get_commit_format(const char *arg, struct rev_info *);
 extern const char *format_subject(struct strbuf *sb, const char *msg,
                                  const char *line_separator);
@@ -261,11 +297,13 @@ struct commit_extra_header {
 extern void append_merge_tag_headers(struct commit_list *parents,
                                     struct commit_extra_header ***tail);
 
-extern int commit_tree(const struct strbuf *msg, const unsigned char *tree,
+extern int commit_tree(const char *msg, size_t msg_len,
+                      const unsigned char *tree,
                       struct commit_list *parents, unsigned char *ret,
                       const char *author, const char *sign_commit);
 
-extern int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
+extern int commit_tree_extended(const char *msg, size_t msg_len,
+                               const unsigned char *tree,
                                struct commit_list *parents, unsigned char *ret,
                                const char *author, const char *sign_commit,
                                struct commit_extra_header *);
@@ -287,7 +325,7 @@ struct merge_remote_desc {
  */
 struct commit *get_merge_parent(const char *name);
 
-extern int parse_signed_commit(const unsigned char *sha1,
+extern int parse_signed_commit(const struct commit *commit,
                               struct strbuf *message, struct strbuf *signature);
 extern void print_commit_list(struct commit_list *list,
                              const char *format_cur,
index 019026efcbc5876d7aa3890eab5078a8bfbe2f7c..7a6e1d797a1ec95a17ad2a759acb85cbe25e9f10 100644 (file)
 #        source ~/.git-completion.sh
 #    3) Consider changing your PS1 to also show the current branch,
 #       see git-prompt.sh for details.
+#
+# If you use complex aliases of form '!f() { ... }; f', you can use the null
+# command ':' as the first command in the function body to declare the desired
+# completion style.  For example '!f() { : git commit ; ... }; f' will
+# tell the completion to use commit completion.  This also works with aliases
+# of form "!sh -c '...'".  For example, "!sh -c ': git commit ; ... '".
 
 case "$COMP_WORDBREAKS" in
 *:*) : great ;;
@@ -781,6 +787,10 @@ __git_aliased_command ()
                -*)     : option ;;
                *=*)    : setting env ;;
                git)    : git itself ;;
+               \(\))   : skip parens of shell function definition ;;
+               {)      : skip start of shell helper function ;;
+               :)      : skip null command ;;
+               \'*)    : skip opening quote after sh -c ;;
                *)
                        echo "$word"
                        return
index b4c9376a2cf1611d777e3f995cae9f20e6616e4d..08cf246bbb1c8306c20cd396ae6e6e80c3b8cbe7 100755 (executable)
@@ -516,7 +516,7 @@ then
 
        case "$no_checkout" in
        '')
-               test "z$quiet" = z -a "z$no_progress" = z && v=-v || v=
+               test "z$quiet" = z && test "z$no_progress" = z && v=-v || v=
                git read-tree -m -u $v HEAD HEAD
        esac
 fi
index 5cafe2eb7715123ba0d748be308f35731ea89ddb..934505bab9e6cf04a3536010ac31b1795c852c9f 100755 (executable)
@@ -51,7 +51,7 @@ run_status () {
                export GIT_INDEX_FILE
        fi
 
-       if test "$status_only" = "t" -o "$use_status_color" = "t"; then
+       if test "$status_only" = "t" || test "$use_status_color" = "t"; then
                color=
        else
                color=--nocolor
@@ -296,7 +296,7 @@ t,,,[1-9]*)
        die "No paths with -i does not make sense." ;;
 esac
 
-if test ! -z "$templatefile" -a -z "$log_given"
+if test ! -z "$templatefile" && test -z "$log_given"
 then
        if test ! -f "$templatefile"
        then
index 7e40f40c78e2b040ae5b85adb27ebd4828f42b4d..52f2aafb9d720723c1dc08e870f38ef495198fa3 100755 (executable)
@@ -161,7 +161,7 @@ merge_name () {
                        return
                fi
        fi
-       if test "$remote" = "FETCH_HEAD" -a -r "$GIT_DIR/FETCH_HEAD"
+       if test "$remote" = "FETCH_HEAD" && test -r "$GIT_DIR/FETCH_HEAD"
        then
                sed -e 's/      not-for-merge   /               /' -e 1q \
                        "$GIT_DIR/FETCH_HEAD"
@@ -527,7 +527,7 @@ do
                git diff-files --name-only
                git ls-files --unmerged
            } | wc -l`
-           if test $best_cnt -le 0 -o $cnt -le $best_cnt
+           if test $best_cnt -le 0 || test $cnt -le $best_cnt
            then
                best_strategy=$strategy
                best_cnt=$cnt
index f312405a251ddc42f0483fb3d1ccc92d8a266fd1..96e3fed326abeb293e9ef398989bce1054cbf855 100755 (executable)
@@ -76,8 +76,8 @@ case ",$all_into_one," in
                                existing="$existing $e"
                        fi
                done
-               if test -n "$existing" -a -n "$unpack_unreachable" -a \
-                       -n "$remove_redundant"
+               if test -n "$existing" && test -n "$unpack_unreachable" && \
+                       test -n "$remove_redundant"
                then
                        # This may have arbitrary user arguments, so we
                        # have to protect it against whitespace splitting
index 48d0fc971f9e7ec3b4b15608950217ad71c5ba94..70fdc27b724f28793c6a4bff713957a22689b78b 100755 (executable)
@@ -76,7 +76,7 @@ case "$common" in
                        2>/dev/null || continue
                # Count the paths that are unmerged.
                cnt=$(GIT_INDEX_FILE=$G git ls-files --unmerged | wc -l)
-               if test $best_cnt -le 0 -o $cnt -le $best_cnt
+               if test $best_cnt -le 0 || test $cnt -le $best_cnt
                then
                        best=$c
                        best_cnt=$cnt
diff --git a/dir.c b/dir.c
index 797805d6a1d33ef66ccb61155135cdcd1a53d9d0..e65888dfad187960bf77904708e60f532ef19e1a 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -1354,8 +1354,7 @@ static int cmp_name(const void *p1, const void *p2)
        const struct dir_entry *e1 = *(const struct dir_entry **)p1;
        const struct dir_entry *e2 = *(const struct dir_entry **)p2;
 
-       return cache_name_compare(e1->name, e1->len,
-                                 e2->name, e2->len);
+       return name_compare(e1->name, e1->len, e2->name, e2->len);
 }
 
 static struct path_simplify *create_simplify(const char **pathspec)
index 72ec520fda7124e49d41e03ea81310a231841a24..b8a58fa7a542fe166ad71c9b17a4908c81d24a4f 100644 (file)
@@ -511,7 +511,7 @@ static void filter_refs(struct fetch_pack_args *args,
                int keep = 0;
                next = ref->next;
 
-               if (!memcmp(ref->name, "refs/", 5) &&
+               if (starts_with(ref->name, "refs/") &&
                    check_refname_format(ref->name, 0))
                        ; /* trash */
                else {
diff --git a/fsck.c b/fsck.c
index bdbea2b995dd5714e8422e18c0bed08ae1a41afa..a4e8593e78c85c244d2dc8bac0cca838c14bbd4a 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -276,9 +276,9 @@ static int fsck_ident(const char **ident, struct object *obj, fsck_error error_f
        return 0;
 }
 
-static int fsck_commit(struct commit *commit, fsck_error error_func)
+static int fsck_commit_buffer(struct commit *commit, const char *buffer,
+                             fsck_error error_func)
 {
-       const char *buffer = commit->buffer;
        unsigned char tree_sha1[20], sha1[20];
        struct commit_graft *graft;
        int parents = 0;
@@ -332,6 +332,14 @@ static int fsck_commit(struct commit *commit, fsck_error error_func)
        return 0;
 }
 
+static int fsck_commit(struct commit *commit, fsck_error error_func)
+{
+       const char *buffer = get_commit_buffer(commit, NULL);
+       int ret = fsck_commit_buffer(commit, buffer, error_func);
+       unuse_commit_buffer(commit, buffer);
+       return ret;
+}
+
 static int fsck_tag(struct tag *tag, fsck_error error_func)
 {
        struct object *tagged = tag->tagged;
index af4d04c3be87423d3c9ef6078766fff679411766..1e0d602f4b156929b74d10546cf5a5ba0f8518dd 100755 (executable)
@@ -408,7 +408,7 @@ bisect_replay () {
        bisect_reset
        while read git bisect command rev
        do
-               test "$git $bisect" = "git bisect" -o "$git" = "git-bisect" || continue
+               test "$git $bisect" = "git bisect" || test "$git" = "git-bisect" || continue
                if test "$git" = "git-bisect"
                then
                        rev="$command"
index d29e1dff08de9caa2b37eff71bffe7d37225796e..9de31807108322aac327f66822d4929974d7ffd5 100644 (file)
@@ -704,6 +704,17 @@ void git_qsort(void *base, size_t nmemb, size_t size,
 #endif
 #endif
 
+#if defined(__GNUC__) && defined(__x86_64__)
+#include <emmintrin.h>
+/*
+ * This is the system memory page size; it's used so that we can read
+ * outside the bounds of an allocation without segfaulting.
+ */
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+#endif
+
 #ifdef UNRELIABLE_FSTAT
 #define fstat_is_reliable() 0
 #else
index 6a8907e7b327d066c616f8f77c2bc2096d618e06..b186329d28c07825992fad039746df8563a92c3b 100755 (executable)
@@ -1558,7 +1558,11 @@ proc rescan_stage2 {fd after} {
 
        set rescan_active 2
        ui_status [mc "Scanning for modified files ..."]
-       set fd_di [git_read diff-index --cached -z [PARENT]]
+       if {[git-version >= "1.7.2"]} {
+               set fd_di [git_read diff-index --cached --ignore-submodules=dirty -z [PARENT]]
+       } else {
+               set fd_di [git_read diff-index --cached -z [PARENT]]
+       }
        set fd_df [git_read diff-files -z]
 
        fconfigure $fd_di -blocking 0 -translation binary -encoding binary
index 30d9a797769b49cdd9d42fba925d8fa8ecbffb21..b0a5180af71ac04c58d2dd44664df98b67d3a770 100644 (file)
@@ -287,6 +287,9 @@ proc start_show_diff {cont_info {add_opts {}}} {
        if {$w eq $ui_index} {
                lappend cmd diff-index
                lappend cmd --cached
+               if {[git-version >= "1.7.2"]} {
+                       lappend cmd --ignore-submodules=dirty
+               }
        } elseif {$w eq $ui_workdir} {
                if {[string first {U} $m] >= 0} {
                        lappend cmd diff
index d08dc92589b366746965a0eab0727ce2befc579d..9a046b75d1dd810202d784d3fffe8afe6dd1963c 100755 (executable)
@@ -205,7 +205,7 @@ checkout_staged_file () {
                "$(git checkout-index --temp --stage="$1" "$2" 2>/dev/null)" \
                : '\([^ ]*\)    ')
 
-       if test $? -eq 0 -a -n "$tmpfile"
+       if test $? -eq 0 && test -n "$tmpfile"
        then
                mv -- "$(git rev-parse --show-cdup)$tmpfile" "$3"
        else
@@ -256,7 +256,7 @@ merge_file () {
        checkout_staged_file 2 "$MERGED" "$LOCAL"
        checkout_staged_file 3 "$MERGED" "$REMOTE"
 
-       if test -z "$local_mode" -o -z "$remote_mode"
+       if test -z "$local_mode" || test -z "$remote_mode"
        then
                echo "Deleted merge conflict for '$MERGED':"
                describe_file "$local_mode" "local" "$LOCAL"
index 7bb0f7313bc9d4d2ad1ae43ec68afe761334a59a..ff132b2117c5ed7529d6b1237a9f26069cb4ef8a 100755 (executable)
--- a/git-p4.py
+++ b/git-p4.py
@@ -1238,7 +1238,7 @@ def edit_template(self, template_file):
             if response == 'n':
                 return False
 
-    def get_diff_description(self, editedFiles):
+    def get_diff_description(self, editedFiles, filesToAdd):
         # diff
         if os.environ.has_key("P4DIFF"):
             del(os.environ["P4DIFF"])
@@ -1258,7 +1258,7 @@ def get_diff_description(self, editedFiles):
                 newdiff += "+" + line
             f.close()
 
-        return diff + newdiff
+        return (diff + newdiff).replace('\r\n', '\n')
 
     def applyCommit(self, id):
         """Apply one commit, return True if it succeeded."""
@@ -1422,10 +1422,10 @@ def applyCommit(self, id):
         separatorLine = "######## everything below this line is just the diff #######\n"
         if not self.prepare_p4_only:
             submitTemplate += separatorLine
-            submitTemplate += self.get_diff_description(editedFiles)
+            submitTemplate += self.get_diff_description(editedFiles, filesToAdd)
 
         (handle, fileName) = tempfile.mkstemp()
-        tmpFile = os.fdopen(handle, "w+")
+        tmpFile = os.fdopen(handle, "w+b")
         if self.isWindows:
             submitTemplate = submitTemplate.replace("\n", "\r\n")
         tmpFile.write(submitTemplate)
@@ -1475,9 +1475,9 @@ def applyCommit(self, id):
             tmpFile = open(fileName, "rb")
             message = tmpFile.read()
             tmpFile.close()
-            submitTemplate = message[:message.index(separatorLine)]
             if self.isWindows:
-                submitTemplate = submitTemplate.replace("\r\n", "\n")
+                message = message.replace("\r\n", "\n")
+            submitTemplate = message[:message.index(separatorLine)]
             p4_write_pipe(['submit', '-i'], submitTemplate)
 
             if self.preserveUser:
index f267d8b6c3eea5c557e63814e40a9ef38b776354..7e1eda008815cca80561d6013d41479ea8c90f4a 100644 (file)
@@ -1013,7 +1013,7 @@ then
        git rev-list $revisions |
        while read rev
        do
-               if test -f "$rewritten"/$rev -a "$(sane_grep "$rev" "$state_dir"/not-cherry-picks)" = ""
+               if test -f "$rewritten"/$rev && test "$(sane_grep "$rev" "$state_dir"/not-cherry-picks)" = ""
                then
                        # Use -f2 because if rev-list is telling us this commit is
                        # not worthwhile, we don't want to track its multiple heads,
index 6d77b3ca9118e6fdd36615757a24c109cf0530ee..d3fb67d75bd3cdfebd048594cdb67eb179b1c435 100644 (file)
@@ -53,11 +53,12 @@ continue_merge () {
 }
 
 call_merge () {
-       cmt="$(cat "$state_dir/cmt.$1")"
+       msgnum="$1"
+       echo "$msgnum" >"$state_dir/msgnum"
+       cmt="$(cat "$state_dir/cmt.$msgnum")"
        echo "$cmt" > "$state_dir/current"
        hd=$(git rev-parse --verify HEAD)
        cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD)
-       msgnum=$(cat "$state_dir/msgnum")
        eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
        eval GITHEAD_$hd='$onto_name'
        export GITHEAD_$cmt GITHEAD_$hd
index abd62b484cdaef8e6ab5ba366551c03959c08beb..9949db01e11959c81fae75fa018551601e6d5c3b 100755 (executable)
@@ -80,6 +80,8 @@ sub usage {
     --to-cmd                <str>  * Email To: via `<str> \$patch_path`
     --cc-cmd                <str>  * Email Cc: via `<str> \$patch_path`
     --suppress-cc           <str>  * author, self, sob, cc, cccmd, body, bodycc, all.
+    --[no-]cc-cover                * Email Cc: addresses in the cover letter.
+    --[no-]to-cover                * Email To: addresses in the cover letter.
     --[no-]signed-off-by-cc        * Send to Signed-off-by: addresses. Default on.
     --[no-]suppress-from           * Send to self. Default off.
     --[no-]chain-reply-to          * Chain In-Reply-To: fields. Default off.
@@ -195,6 +197,7 @@ sub do_edit {
 
 # Variables with corresponding config settings
 my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc);
+my ($cover_cc, $cover_to);
 my ($to_cmd, $cc_cmd);
 my ($smtp_server, $smtp_server_port, @smtp_server_options);
 my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
@@ -211,6 +214,8 @@ sub do_edit {
     "chainreplyto" => [\$chain_reply_to, 0],
     "suppressfrom" => [\$suppress_from, undef],
     "signedoffbycc" => [\$signed_off_by_cc, undef],
+    "cccover" => [\$cover_cc, undef],
+    "tocover" => [\$cover_to, undef],
     "signedoffcc" => [\$signed_off_by_cc, undef],      # Deprecated
     "validate" => [\$validate, 1],
     "multiedit" => [\$multiedit, undef],
@@ -302,6 +307,8 @@ sub signal_handler {
                    "suppress-from!" => \$suppress_from,
                    "suppress-cc=s" => \@suppress_cc,
                    "signed-off-cc|signed-off-by-cc!" => \$signed_off_by_cc,
+                   "cc-cover|cc-cover!" => \$cover_cc,
+                   "to-cover|to-cover!" => \$cover_to,
                    "confirm=s" => \$confirm,
                    "dry-run" => \$dry_run,
                    "envelope-sender=s" => \$envelope_sender,
@@ -1481,6 +1488,15 @@ sub send_message {
        @to = (@initial_to, @to);
        @cc = (@initial_cc, @cc);
 
+       if ($message_num == 1) {
+               if (defined $cover_cc and $cover_cc) {
+                       @initial_cc = @cc;
+               }
+               if (defined $cover_to and $cover_to) {
+                       @initial_to = @to;
+               }
+       }
+
        my $message_was_sent = send_message();
 
        # set up for the next message
index e146b833d163ab58984fec3d6fb9f45b148e0171..9245abfd4263881bdd6d0f21f648b46201b52a2d 100755 (executable)
@@ -235,7 +235,7 @@ module_name()
                sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
        test -z "$name" &&
        die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
-       echo "$name"
+       printf '%s\n' "$name"
 }
 
 #
@@ -305,10 +305,10 @@ module_clone()
        b=${b%/}
 
        # Turn each leading "*/" component into "../"
-       rel=$(echo $b | sed -e 's|[^/][^/]*|..|g')
-       echo "gitdir: $rel/$a" >"$sm_path/.git"
+       rel=$(printf '%s\n' "$b" | sed -e 's|[^/][^/]*|..|g')
+       printf '%s\n' "gitdir: $rel/$a" >"$sm_path/.git"
 
-       rel=$(echo $a | sed -e 's|[^/][^/]*|..|g')
+       rel=$(printf '%s\n' "$a" | sed -e 's|[^/][^/]*|..|g')
        (clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
 }
 
@@ -389,11 +389,11 @@ cmd_add()
        sm_path=$2
 
        if test -z "$sm_path"; then
-               sm_path=$(echo "$repo" |
+               sm_path=$(printf '%s\n' "$repo" |
                        sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
        fi
 
-       if test -z "$repo" -o -z "$sm_path"; then
+       if test -z "$repo" || test -z "$sm_path"; then
                usage
        fi
 
@@ -450,7 +450,7 @@ Use -f if you really want to add it." >&2
        # perhaps the path exists and is already a git repo, else clone it
        if test -e "$sm_path"
        then
-               if test -d "$sm_path"/.git -o -f "$sm_path"/.git
+               if test -d "$sm_path"/.git || test -f "$sm_path"/.git
                then
                        eval_gettextln "Adding existing repo at '\$sm_path' to the index"
                else
@@ -832,7 +832,7 @@ Maybe you want to use 'update --init'?")"
                        continue
                fi
 
-               if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
+               if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
                then
                        module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
                        cloned_modules="$cloned_modules;$name"
@@ -857,11 +857,11 @@ Maybe you want to use 'update --init'?")"
                        die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
                fi
 
-               if test "$subsha1" != "$sha1" -o -n "$force"
+               if test "$subsha1" != "$sha1" || test -n "$force"
                then
                        subforce=$force
                        # If we don't already have a -f flag and the submodule has never been checked out
-                       if test -z "$subsha1" -a -z "$force"
+                       if test -z "$subsha1" && test -z "$force"
                        then
                                subforce="-f"
                        fi
@@ -1031,7 +1031,7 @@ cmd_summary() {
        then
                head=$rev
                test $# = 0 || shift
-       elif test -z "$1" -o "$1" = "HEAD"
+       elif test -z "$1" || test "$1" = "HEAD"
        then
                # before the first commit: compare with an empty tree
                head=$(git hash-object -w -t tree --stdin </dev/null)
@@ -1056,17 +1056,21 @@ cmd_summary() {
                while read mod_src mod_dst sha1_src sha1_dst status sm_path
                do
                        # Always show modules deleted or type-changed (blob<->module)
-                       test $status = D -o $status = T && echo "$sm_path" && continue
+                       if test "$status" = D || test "$status" = T
+                       then
+                               printf '%s\n' "$sm_path"
+                               continue
+                       fi
                        # Respect the ignore setting for --for-status.
                        if test -n "$for_status"
                        then
                                name=$(module_name "$sm_path")
                                ignore_config=$(get_submodule_config "$name" ignore none)
-                               test $status != A -a $ignore_config = all && continue
+                               test $status != A && test $ignore_config = all && continue
                        fi
                        # Also show added or modified modules which are checked out
                        GIT_DIR="$sm_path/.git" git-rev-parse --git-dir >/dev/null 2>&1 &&
-                       echo "$sm_path"
+                       printf '%s\n' "$sm_path"
                done
        )
 
@@ -1122,7 +1126,7 @@ cmd_summary() {
                *)
                        errmsg=
                        total_commits=$(
-                       if test $mod_src = 160000 -a $mod_dst = 160000
+                       if test $mod_src = 160000 && test $mod_dst = 160000
                        then
                                range="$sha1_src...$sha1_dst"
                        elif test $mod_src = 160000
@@ -1159,7 +1163,7 @@ cmd_summary() {
                        # i.e. deleted or changed to blob
                        test $mod_dst = 160000 && echo "$errmsg"
                else
-                       if test $mod_src = 160000 -a $mod_dst = 160000
+                       if test $mod_src = 160000 && test $mod_dst = 160000
                        then
                                limit=
                                test $summary_limit -gt 0 && limit="-$summary_limit"
@@ -1230,7 +1234,11 @@ cmd_status()
                        say "U$sha1 $displaypath"
                        continue
                fi
-               if test -z "$url" || ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
+               if test -z "$url" ||
+               {
+                       ! test -d "$sm_path"/.git &&
+                       ! test -f "$sm_path"/.git
+               }
                then
                        say "-$sha1 $displaypath"
                        continue;
@@ -1303,7 +1311,7 @@ cmd_sync()
                ./*|../*)
                        # rewrite foo/bar as ../.. to find path from
                        # submodule work tree to superproject work tree
-                       up_path="$(echo "$sm_path" | sed "s/[^/][^/]*/../g")" &&
+                       up_path="$(printf '%s\n' "$sm_path" | sed "s/[^/][^/]*/../g")" &&
                        # guarantee a trailing /
                        up_path=${up_path%/}/ &&
                        # path from submodule work tree to submodule origin repo
@@ -1399,7 +1407,7 @@ then
 fi
 
 # "--cached" is accepted only by "status" and "summary"
-if test -n "$cached" && test "$command" != status -a "$command" != summary
+if test -n "$cached" && test "$command" != status && test "$command" != summary
 then
        usage
 fi
diff --git a/git.c b/git.c
index 1537f00bc7081aa800d390aecaf6d80ab7c546c9..dd54f5734a246d65436c823dd65fb224b240009f 100644 (file)
--- a/git.c
+++ b/git.c
@@ -20,6 +20,43 @@ const char git_more_info_string[] =
 
 static struct startup_info git_startup_info;
 static int use_pager = -1;
+static char orig_cwd[PATH_MAX];
+static const char *env_names[] = {
+       GIT_DIR_ENVIRONMENT,
+       GIT_WORK_TREE_ENVIRONMENT,
+       GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,
+       GIT_PREFIX_ENVIRONMENT
+};
+static char *orig_env[4];
+static int saved_environment;
+
+static void save_env(void)
+{
+       int i;
+       if (saved_environment)
+               return;
+       saved_environment = 1;
+       if (!getcwd(orig_cwd, sizeof(orig_cwd)))
+               die_errno("cannot getcwd");
+       for (i = 0; i < ARRAY_SIZE(env_names); i++) {
+               orig_env[i] = getenv(env_names[i]);
+               if (orig_env[i])
+                       orig_env[i] = xstrdup(orig_env[i]);
+       }
+}
+
+static void restore_env(void)
+{
+       int i;
+       if (*orig_cwd && chdir(orig_cwd))
+               die_errno("could not move to %s", orig_cwd);
+       for (i = 0; i < ARRAY_SIZE(env_names); i++) {
+               if (orig_env[i])
+                       setenv(env_names[i], orig_env[i], 1);
+               else
+                       unsetenv(env_names[i]);
+       }
+}
 
 static void commit_pager_choice(void) {
        switch (use_pager) {
@@ -271,6 +308,7 @@ static int handle_alias(int *argcp, const char ***argv)
  * RUN_SETUP for reading from the configuration file.
  */
 #define NEED_WORK_TREE         (1<<3)
+#define NO_SETUP               (1<<4)
 
 struct cmd_struct {
        const char *cmd;
@@ -351,7 +389,7 @@ static struct cmd_struct commands[] = {
        { "cherry", cmd_cherry, RUN_SETUP },
        { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
        { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
-       { "clone", cmd_clone },
+       { "clone", cmd_clone, NO_SETUP },
        { "column", cmd_column, RUN_SETUP_GENTLY },
        { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
        { "commit-tree", cmd_commit_tree, RUN_SETUP },
@@ -377,8 +415,8 @@ static struct cmd_struct commands[] = {
        { "hash-object", cmd_hash_object },
        { "help", cmd_help },
        { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
-       { "init", cmd_init_db },
-       { "init-db", cmd_init_db },
+       { "init", cmd_init_db, NO_SETUP },
+       { "init-db", cmd_init_db, NO_SETUP },
        { "log", cmd_log, RUN_SETUP },
        { "ls-files", cmd_ls_files, RUN_SETUP },
        { "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
@@ -483,6 +521,10 @@ static void handle_builtin(int argc, const char **argv)
                struct cmd_struct *p = commands+i;
                if (strcmp(p->cmd, cmd))
                        continue;
+               if (saved_environment && (p->option & NO_SETUP)) {
+                       restore_env();
+                       break;
+               }
                exit(run_builtin(p, argc, argv));
        }
 }
@@ -538,7 +580,10 @@ static int run_argv(int *argcp, const char ***argv)
                 * of overriding "git log" with "git show" by having
                 * alias.log = show
                 */
-               if (done_alias || !handle_alias(argcp, argv))
+               if (done_alias)
+                       break;
+               save_env();
+               if (!handle_alias(argcp, argv))
                        break;
                done_alias = 1;
        }
index 90764e8948f1f95aaddfb381664ecede328bc863..c8df35dee58aed6ba652ee9ab998f405539991eb 100755 (executable)
@@ -2585,6 +2585,7 @@ proc makewindow {} {
     bind $fstring <Key-Return> {dofind 1 1}
     bind $sha1entry <Key-Return> {gotocommit; break}
     bind $sha1entry <<PasteSelection>> clearsha1
+    bind $sha1entry <<Paste>> clearsha1
     bind $cflist <1> {sel_flist %W %x %y; break}
     bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
     bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
@@ -2786,7 +2787,7 @@ proc savestuff {w} {
     global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
     global linkfgcolor circleoutlinecolor
     global autoselect autosellen extdifftool perfile_attrs markbgcolor use_ttk
-    global hideremotes want_ttk maxrefs
+    global hideremotes want_ttk maxrefs visiblerefs
     global config_file config_file_tmp
 
     if {$stuffsaved} return
@@ -2812,6 +2813,7 @@ proc savestuff {w} {
        puts $f [list set autosellen $autosellen]
        puts $f [list set showneartags $showneartags]
        puts $f [list set maxrefs $maxrefs]
+       puts $f [list set visiblerefs $visiblerefs]
        puts $f [list set hideremotes $hideremotes]
        puts $f [list set showlocalchanges $showlocalchanges]
        puts $f [list set datetimeformat $datetimeformat]
@@ -3492,10 +3494,20 @@ proc flist_hl {only} {
 }
 
 proc gitknewtmpdir {} {
-    global diffnum gitktmpdir gitdir
+    global diffnum gitktmpdir gitdir env
 
     if {![info exists gitktmpdir]} {
-       set gitktmpdir [file join $gitdir [format ".gitk-tmp.%s" [pid]]]
+       if {[info exists env(GITK_TMPDIR)]} {
+           set tmpdir $env(GITK_TMPDIR)
+       } elseif {[info exists env(TMPDIR)]} {
+           set tmpdir $env(TMPDIR)
+       } else {
+           set tmpdir $gitdir
+       }
+       set gitktmpformat [file join $tmpdir ".gitk-tmp.XXXXXX"]
+       if {[catch {set gitktmpdir [exec mktemp -d $gitktmpformat]}]} {
+           set gitktmpdir [file join $gitdir [format ".gitk-tmp.%s" [pid]]]
+       }
        if {[catch {file mkdir $gitktmpdir} err]} {
            error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
            unset gitktmpdir
@@ -3870,7 +3882,7 @@ proc read_line_source {fd inst} {
            set id $nullid2
        }
        if {[commitinview $id $curview]} {
-           selectline [rowofcommit $id] 1 [list $fname $lnum]
+           selectline [rowofcommit $id] 1 [list $fname $lnum] 1
        } else {
            error_popup [mc "That line comes from commit %s, \
                             which is not in this view" [shortids $id]]
@@ -5205,11 +5217,15 @@ proc dohidelocalchanges {} {
 # spawn off a process to do git diff-index --cached HEAD
 proc dodiffindex {} {
     global lserial showlocalchanges vfilelimit curview
-    global hasworktree
+    global hasworktree git_version
 
     if {!$showlocalchanges || !$hasworktree} return
     incr lserial
-    set cmd "|git diff-index --cached HEAD"
+    if {[package vcompare $git_version "1.7.2"] >= 0} {
+       set cmd "|git diff-index --cached --ignore-submodules=dirty HEAD"
+    } else {
+       set cmd "|git diff-index --cached HEAD"
+    }
     if {$vfilelimit($curview) ne {}} {
        set cmd [concat $cmd -- $vfilelimit($curview)]
     }
@@ -7020,7 +7036,7 @@ proc viewnextline {dir} {
 # add a list of tag or branch names at position pos
 # returns the number of names inserted
 proc appendrefs {pos ids var} {
-    global ctext linknum curview $var maxrefs mainheadid
+    global ctext linknum curview $var maxrefs visiblerefs mainheadid
 
     if {[catch {$ctext index $pos}]} {
        return 0
@@ -7041,14 +7057,14 @@ proc appendrefs {pos ids var} {
     if {[llength $tags] > $maxrefs} {
        # If we are displaying heads, and there are too many,
        # see if there are some important heads to display.
-       # Currently this means "master" and the current head.
+       # Currently that are the current head and heads listed in $visiblerefs option
        set itags {}
        if {$var eq "idheads"} {
            set utags {}
            foreach ti $tags {
                set hname [lindex $ti 0]
                set id [lindex $ti 1]
-               if {($hname eq "master" || $id eq $mainheadid) &&
+               if {([lsearch -exact $visiblerefs $hname] != -1 || $id eq $mainheadid) &&
                    [llength $itags] < $maxrefs} {
                    lappend itags $ti
                } else {
@@ -7161,7 +7177,7 @@ proc make_idmark {id} {
     $canv raise $t
 }
 
-proc selectline {l isnew {desired_loc {}}} {
+proc selectline {l isnew {desired_loc {}} {switch_to_patch 0}} {
     global canv ctext commitinfo selectedline
     global canvy0 linespc parents children curview
     global currentid sha1entry
@@ -7187,6 +7203,10 @@ proc selectline {l isnew {desired_loc {}}} {
        setcanvscroll
     }
 
+    if {$cmitmode ne "patch" && $switch_to_patch} {
+        set cmitmode "patch"
+    }
+
     set y [expr {$canvy0 + $l * $linespc}]
     set ymax [lindex [$canv cget -scrollregion] 3]
     set ytop [expr {$y - $linespc - 1}]
@@ -7705,7 +7725,7 @@ proc addtocflist {ids} {
 }
 
 proc diffcmd {ids flags} {
-    global log_showroot nullid nullid2
+    global log_showroot nullid nullid2 git_version
 
     set i [lsearch -exact $ids $nullid]
     set j [lsearch -exact $ids $nullid2]
@@ -7726,6 +7746,9 @@ proc diffcmd {ids flags} {
            }
        }
     } elseif {$j >= 0} {
+       if {[package vcompare $git_version "1.7.2"] >= 0} {
+           set flags "$flags --ignore-submodules=dirty"
+       }
        set cmd [concat | git diff-index --cached $flags]
        if {[llength $ids] > 1} {
            # comparing index with specific revision
@@ -11575,7 +11598,29 @@ proc prefsok {} {
 proc formatdate {d} {
     global datetimeformat
     if {$d ne {}} {
-       set d [clock format [lindex $d 0] -format $datetimeformat]
+       # If $datetimeformat includes a timezone, display in the
+       # timezone of the argument.  Otherwise, display in local time.
+       if {[string match {*%[zZ]*} $datetimeformat]} {
+           if {[catch {set d [clock format [lindex $d 0] -timezone [lindex $d 1] -format $datetimeformat]}]} {
+               # Tcl < 8.5 does not support -timezone.  Emulate it by
+               # setting TZ (e.g. TZ=<-0430>+04:30).
+               global env
+               if {[info exists env(TZ)]} {
+                   set savedTZ $env(TZ)
+               }
+               set zone [lindex $d 1]
+               set sign [string map {+ - - +} [string index $zone 0]]
+               set env(TZ) <$zone>$sign[string range $zone 1 2]:[string range $zone 3 4]
+               set d [clock format [lindex $d 0] -format $datetimeformat]
+               if {[info exists savedTZ]} {
+                   set env(TZ) $savedTZ
+               } else {
+                   unset env(TZ)
+               }
+           }
+       } else {
+           set d [clock format [lindex $d 0] -format $datetimeformat]
+       }
     }
     return $d
 }
@@ -12001,6 +12046,7 @@ set wrapcomment "none"
 set showneartags 1
 set hideremotes 0
 set maxrefs 20
+set visiblerefs {"master"}
 set maxlinelen 200
 set showlocalchanges 1
 set limitdiffs 1
diff --git a/gitk-git/po/vi.po b/gitk-git/po/vi.po
new file mode 100644 (file)
index 0000000..4dfe125
--- /dev/null
@@ -0,0 +1,1351 @@
+# Vietnamese translations for gitk package.
+# Bản dịch tiếng Việt cho gói gitk.
+# This file is distributed under the same license as the gitk package.
+# Trần Ngọc Quân <vnwildman@gmail.com>, 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gitk @@GIT_VERSION@@\n"
+"Report-Msgid-Bugs-To: Paul Mackerras <paulus@samba.org>\n"
+"POT-Creation-Date: 2013-12-14 09:24+0700\n"
+"PO-Revision-Date: 2013-12-14 14:40+0700\n"
+"Last-Translator: Trần Ngọc Quân <vnwildman@gmail.com>\n"
+"Language-Team: Vietnamese <translation-team-vi@lists.sourceforge.net>\n"
+"Language: vi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: gitk:140
+msgid "Couldn't get list of unmerged files:"
+msgstr "Không thể lấy danh sách các tập-tin chưa được hòa trộn:"
+
+#: gitk:212 gitk:2353
+msgid "Color words"
+msgstr "Tô màu chữ"
+
+#: gitk:217 gitk:2353 gitk:8103 gitk:8136
+msgid "Markup words"
+msgstr "Đánh dấu chữ"
+
+#: gitk:322
+msgid "Error parsing revisions:"
+msgstr "Gặp lỗi khi phân tích điểm xét duyệt:"
+
+#: gitk:378
+msgid "Error executing --argscmd command:"
+msgstr "Gặp lỗi khi thực hiện lệnh --argscmd:"
+
+#: gitk:391
+msgid "No files selected: --merge specified but no files are unmerged."
+msgstr ""
+"Chưa chọn tập tin: --merge đã chỉ định nhưng không có tập tin chưa hòa trộn."
+
+#: gitk:394
+msgid ""
+"No files selected: --merge specified but no unmerged files are within file "
+"limit."
+msgstr ""
+"Chưa chọn tập tin: --merge đã chỉ định nhưng không có tập tin chưa hòa trộn "
+"trong giới hạn tập tin."
+
+#: gitk:416 gitk:564
+msgid "Error executing git log:"
+msgstr "Gặp lỗi khi thực hiện lệnh git log:"
+
+#: gitk:434 gitk:580
+msgid "Reading"
+msgstr "Đang đọc"
+
+#: gitk:494 gitk:4429
+msgid "Reading commits..."
+msgstr "Đang đọc các lần chuyển giao..."
+
+#: gitk:497 gitk:1635 gitk:4432
+msgid "No commits selected"
+msgstr "Chưa chọn các lần chuyển giao"
+
+#: gitk:1509
+msgid "Can't parse git log output:"
+msgstr "Không thể phân tích kết xuất từ lệnh git log:"
+
+#: gitk:1738
+msgid "No commit information available"
+msgstr "Không có thông tin về lần chuyển giao nào"
+
+#: gitk:1895
+msgid "mc"
+msgstr "mc"
+
+#: gitk:1930 gitk:4222 gitk:9552 gitk:11122 gitk:11401
+msgid "OK"
+msgstr "Đồng ý"
+
+#: gitk:1932 gitk:4224 gitk:9079 gitk:9158 gitk:9274 gitk:9323 gitk:9554
+#: gitk:11123 gitk:11402
+msgid "Cancel"
+msgstr "Thôi"
+
+#: gitk:2067
+msgid "Update"
+msgstr "Cập nhật"
+
+#: gitk:2068
+msgid "Reload"
+msgstr "Tải lại"
+
+#: gitk:2069
+msgid "Reread references"
+msgstr "Đọc lại tham chiếu"
+
+#: gitk:2070
+msgid "List references"
+msgstr "Liệt kê các tham chiếu"
+
+#: gitk:2072
+msgid "Start git gui"
+msgstr "Khởi chạy git gui"
+
+#: gitk:2074
+msgid "Quit"
+msgstr "Thoát"
+
+#: gitk:2066
+msgid "File"
+msgstr "Chính"
+
+#: gitk:2078
+msgid "Preferences"
+msgstr "Cá nhân hóa"
+
+#: gitk:2077
+msgid "Edit"
+msgstr "Chỉnh sửa"
+
+#: gitk:2082
+msgid "New view..."
+msgstr "Thêm trình bày mới..."
+
+#: gitk:2083
+msgid "Edit view..."
+msgstr "Sửa cách trình bày..."
+
+#: gitk:2084
+msgid "Delete view"
+msgstr "Xóa cách trình bày"
+
+#: gitk:2086
+msgid "All files"
+msgstr "Mọi tập tin"
+
+#: gitk:2081 gitk:3975
+msgid "View"
+msgstr "Trình bày"
+
+#: gitk:2091 gitk:2101 gitk:2945
+msgid "About gitk"
+msgstr "Giới thiệu về gitk"
+
+#: gitk:2092 gitk:2106
+msgid "Key bindings"
+msgstr "Tổ hợp phím"
+
+#: gitk:2090 gitk:2105
+msgid "Help"
+msgstr "Trợ giúp"
+
+#: gitk:2183 gitk:8535
+msgid "SHA1 ID:"
+msgstr "SHA1 ID:"
+
+#: gitk:2227
+msgid "Row"
+msgstr "Hàng"
+
+#: gitk:2265
+msgid "Find"
+msgstr "Tìm"
+
+#: gitk:2266
+msgid "next"
+msgstr "tiếp"
+
+#: gitk:2267
+msgid "prev"
+msgstr "trước"
+
+#: gitk:2268
+msgid "commit"
+msgstr "lần chuyển giao"
+
+#: gitk:2271 gitk:2273 gitk:4590 gitk:4613 gitk:4637 gitk:6653 gitk:6725
+#: gitk:6810
+msgid "containing:"
+msgstr "có chứa:"
+
+#: gitk:2274 gitk:3457 gitk:3462 gitk:4666
+msgid "touching paths:"
+msgstr "đang chạm đường dẫn:"
+
+#: gitk:2275 gitk:4680
+msgid "adding/removing string:"
+msgstr "thêm/gỡ bỏ chuỗi:"
+
+#: gitk:2276 gitk:4682
+msgid "changing lines matching:"
+msgstr "những dòng thay đổi khớp mẫu:"
+
+#: gitk:2285 gitk:2287 gitk:4669
+msgid "Exact"
+msgstr "Chính xác"
+
+#: gitk:2287 gitk:4757 gitk:6621
+msgid "IgnCase"
+msgstr "BquaHt"
+
+#: gitk:2287 gitk:4639 gitk:4755 gitk:6617
+msgid "Regexp"
+msgstr "BTCQ"
+
+#: gitk:2289 gitk:2290 gitk:4777 gitk:4807 gitk:4814 gitk:6746 gitk:6814
+msgid "All fields"
+msgstr "Mọi trường"
+
+#: gitk:2290 gitk:4774 gitk:4807 gitk:6684
+msgid "Headline"
+msgstr "Nội dung chính"
+
+#: gitk:2291 gitk:4774 gitk:6684 gitk:6814 gitk:7283
+msgid "Comments"
+msgstr "Ghi chú"
+
+#: gitk:2291 gitk:4774 gitk:4779 gitk:4814 gitk:6684 gitk:7218 gitk:8713
+#: gitk:8728
+msgid "Author"
+msgstr "Tác giả"
+
+#: gitk:2291 gitk:4774 gitk:6684 gitk:7220
+msgid "Committer"
+msgstr "Người chuyển giao"
+
+#: gitk:2322
+msgid "Search"
+msgstr "Tìm kiếm"
+
+#: gitk:2330
+msgid "Diff"
+msgstr "So sánh"
+
+#: gitk:2332
+msgid "Old version"
+msgstr "Phiên bản cũ"
+
+#: gitk:2334
+msgid "New version"
+msgstr "Phiên bản mới"
+
+#: gitk:2336
+msgid "Lines of context"
+msgstr "Các dòng của nội dung"
+
+#: gitk:2346
+msgid "Ignore space change"
+msgstr "Không xét đến thay đổi do khoảng trắng"
+
+#: gitk:2350 gitk:2352 gitk:7842 gitk:8089
+msgid "Line diff"
+msgstr "Khác biệt theo dòng"
+
+#: gitk:2417
+msgid "Patch"
+msgstr "Vá"
+
+#: gitk:2419
+msgid "Tree"
+msgstr "Cây"
+
+#: gitk:2577 gitk:2597
+msgid "Diff this -> selected"
+msgstr "So sánh cái này -> cái đã chọn"
+
+#: gitk:2578 gitk:2598
+msgid "Diff selected -> this"
+msgstr "So sánh cái đã chọn -> cái này"
+
+#: gitk:2579 gitk:2599
+msgid "Make patch"
+msgstr "Tạo miếng vá"
+
+#: gitk:2580 gitk:9137
+msgid "Create tag"
+msgstr "Tạo thẻ"
+
+#: gitk:2581 gitk:9254
+msgid "Write commit to file"
+msgstr "Ghi lần chuyển giao ra tập tin"
+
+#: gitk:2582 gitk:9311
+msgid "Create new branch"
+msgstr "Tạo nhánh mới"
+
+#: gitk:2583
+msgid "Cherry-pick this commit"
+msgstr "Cherry-pick lần chuyển giao này"
+
+#: gitk:2584
+msgid "Reset HEAD branch to here"
+msgstr "Đặt lại HEAD của nhánh vào đây"
+
+#: gitk:2585
+msgid "Mark this commit"
+msgstr "Đánh dấu lần chuyển giao này"
+
+#: gitk:2586
+msgid "Return to mark"
+msgstr "Quay lại vị trí dấu"
+
+#: gitk:2587
+msgid "Find descendant of this and mark"
+msgstr "Tìm con cháu của cái này và cái đã đánh dấu"
+
+#: gitk:2588
+msgid "Compare with marked commit"
+msgstr "So sánh với lần chuyển giao đã đánh dấu"
+
+#: gitk:2589 gitk:2600
+msgid "Diff this -> marked commit"
+msgstr "So sánh cái này -> lần chuyển giao đã đánh dấu"
+
+#: gitk:2590 gitk:2601
+msgid "Diff marked commit -> this"
+msgstr "So sánh lần chuyển giao đã đánh dấu -> cái này"
+
+#: gitk:2591
+msgid "Revert this commit"
+msgstr "Hoàn lại lần chuyển giao này"
+
+#: gitk:2607
+msgid "Check out this branch"
+msgstr "Checkout nhánh này"
+
+#: gitk:2608
+msgid "Remove this branch"
+msgstr "Gỡ bỏ nhánh này"
+
+#: gitk:2615
+msgid "Highlight this too"
+msgstr "Cũng tô sáng nó"
+
+#: gitk:2616
+msgid "Highlight this only"
+msgstr "Chỉ tô sáng cái này"
+
+#: gitk:2617
+msgid "External diff"
+msgstr "diff từ bên ngoài"
+
+#: gitk:2618
+msgid "Blame parent commit"
+msgstr "Xem công trạng lần chuyển giao cha mẹ"
+
+#: gitk:2625
+msgid "Show origin of this line"
+msgstr "Hiển thị nguyên gốc của dòng này"
+
+#: gitk:2626
+msgid "Run git gui blame on this line"
+msgstr "Chạy lệnh git gui blame cho dòng này"
+
+#: gitk:2947
+msgid ""
+"\n"
+"Gitk - a commit viewer for git\n"
+"\n"
+"Copyright © 2005-2011 Paul Mackerras\n"
+"\n"
+"Use and redistribute under the terms of the GNU General Public License"
+msgstr ""
+"\n"
+"Gitk - phần mềm xem các lần chuyển giao dành cho git\n"
+"\n"
+"Bản quyền © 2005-2011 Paul Mackerras\n"
+"\n"
+"Dùng và phân phối lại phần mềm này theo các điều khoản của Giấy Phép Công GNU"
+
+#: gitk:2955 gitk:3020 gitk:9738
+msgid "Close"
+msgstr "Đóng"
+
+#: gitk:2976
+msgid "Gitk key bindings"
+msgstr "Tổ hợp phím gitk"
+
+#: gitk:2979
+msgid "Gitk key bindings:"
+msgstr "Tổ hợp phím gitk:"
+
+#: gitk:2981
+#, tcl-format
+msgid "<%s-Q>\t\tQuit"
+msgstr "<%s-Q>\t\tThoát"
+
+#: gitk:2982
+#, tcl-format
+msgid "<%s-W>\t\tClose window"
+msgstr "<%s-W>\t\tĐóng cửa sổ"
+
+#: gitk:2983
+msgid "<Home>\t\tMove to first commit"
+msgstr "<Home>\t\tChuyển đến lần chuyển giao đầu tiên"
+
+#: gitk:2984
+msgid "<End>\t\tMove to last commit"
+msgstr "<End>\t\tChuyển đến lần chuyển giao cuối"
+
+#: gitk:2985
+msgid "<Up>, p, k\tMove up one commit"
+msgstr "<Up>, p, k\tDi chuyển lên một lần chuyển giao"
+
+#: gitk:2986
+msgid "<Down>, n, j\tMove down one commit"
+msgstr "<Down>, n, j\tDi chuyển xuống một lần chuyển giao"
+
+#: gitk:2987
+msgid "<Left>, z, h\tGo back in history list"
+msgstr "<Left>, z, h\tQuay trở lại danh sách lịch sử"
+
+#: gitk:2988
+msgid "<Right>, x, l\tGo forward in history list"
+msgstr "<Right>, x, l\tDi chuyển tiếp trong danh sách lịch sử"
+
+#: gitk:2989
+msgid "<PageUp>\tMove up one page in commit list"
+msgstr "<PageUp>\tDi chuyển lên một trang trong danh sách lần chuyển giao"
+
+#: gitk:2990
+msgid "<PageDown>\tMove down one page in commit list"
+msgstr "<PageDown>\tDi chuyển xuống một trang trong danh sách lần chuyển giao"
+
+#: gitk:2991
+#, tcl-format
+msgid "<%s-Home>\tScroll to top of commit list"
+msgstr "<%s-Home>\tCuộn lên trên cùng của danh sách lần chuyển giao"
+
+#: gitk:2992
+#, tcl-format
+msgid "<%s-End>\tScroll to bottom of commit list"
+msgstr "<%s-End>\tCuộn xuống dưới cùng của danh sách lần chuyển giao"
+
+#: gitk:2993
+#, tcl-format
+msgid "<%s-Up>\tScroll commit list up one line"
+msgstr "<%s-Up>\tCuộn danh sách lần chuyển giao lên một dòng"
+
+#: gitk:2994
+#, tcl-format
+msgid "<%s-Down>\tScroll commit list down one line"
+msgstr "<%s-Down>\tCuộn danh sách lần chuyển giao xuống một dòng"
+
+#: gitk:2995
+#, tcl-format
+msgid "<%s-PageUp>\tScroll commit list up one page"
+msgstr "<%s-PageUp>\tCuộn danh sách lần chuyển giao lên một trang"
+
+#: gitk:2996
+#, tcl-format
+msgid "<%s-PageDown>\tScroll commit list down one page"
+msgstr "<%s-PageDown>\tCuộn danh sách lần chuyển giao xuống một trang"
+
+#: gitk:2997
+msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
+msgstr "<Shift-Up>\tTìm về phía sau (hướng lên trên, lần chuyển giao sau này)"
+
+#: gitk:2998
+msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
+msgstr ""
+"<Shift-Down>\tTìm về phía trước (hướng xuống dưới, lần chuyển giao trước đây)"
+
+#: gitk:2999
+msgid "<Delete>, b\tScroll diff view up one page"
+msgstr "<Delete>, b\tCuộn phần trình bày diff lên một trang"
+
+#: gitk:3000
+msgid "<Backspace>\tScroll diff view up one page"
+msgstr "<Backspace>\tCuộn phần trình bày diff lên một trang"
+
+#: gitk:3001
+msgid "<Space>\t\tScroll diff view down one page"
+msgstr "<Space>\t\tCuộn phần trình bày diff xuống một trang"
+
+#: gitk:3002
+msgid "u\t\tScroll diff view up 18 lines"
+msgstr "u\t\tCuộn phần trình bày diff lên 18 dòng"
+
+#: gitk:3003
+msgid "d\t\tScroll diff view down 18 lines"
+msgstr "d\t\tCuộn phần trình bày diff xuống 18 dòng"
+
+#: gitk:3004
+#, tcl-format
+msgid "<%s-F>\t\tFind"
+msgstr "<%s-F>\t\tTìm kiếm"
+
+#: gitk:3005
+#, tcl-format
+msgid "<%s-G>\t\tMove to next find hit"
+msgstr "<%s-G>\t\tDi chuyển đến chỗ gặp kế tiếp"
+
+#: gitk:3006
+msgid "<Return>\tMove to next find hit"
+msgstr "<Return>\t\tDi chuyển đến chỗ gặp kế tiếp"
+
+#: gitk:3007
+msgid "/\t\tFocus the search box"
+msgstr "/\t\tĐưa con trỏ chuột vào ô tìm kiếm"
+
+#: gitk:3008
+msgid "?\t\tMove to previous find hit"
+msgstr "?\t\tDi chuyển đến chỗ gặp kế trước"
+
+#: gitk:3009
+msgid "f\t\tScroll diff view to next file"
+msgstr "f\t\tCuộn phần trình bày diff sang tập-tin kế"
+
+#: gitk:3010
+#, tcl-format
+msgid "<%s-S>\t\tSearch for next hit in diff view"
+msgstr "<%s-S>\t\tTìm đến chỗ khác biệt kế tiếp"
+
+#: gitk:3011
+#, tcl-format
+msgid "<%s-R>\t\tSearch for previous hit in diff view"
+msgstr "<%s-R>\t\tTìm đến chỗ khác biệt kế trước"
+
+#: gitk:3012
+#, tcl-format
+msgid "<%s-KP+>\tIncrease font size"
+msgstr "<%s-KP+>\tTăng cỡ chữ"
+
+#: gitk:3013
+#, tcl-format
+msgid "<%s-plus>\tIncrease font size"
+msgstr "<%s-plus>\tTăng cỡ chữ"
+
+#: gitk:3014
+#, tcl-format
+msgid "<%s-KP->\tDecrease font size"
+msgstr "<%s-KP->\tGiảm cỡ chữ"
+
+#: gitk:3015
+#, tcl-format
+msgid "<%s-minus>\tDecrease font size"
+msgstr "<%s-minus>\tGiảm cỡ chữ"
+
+#: gitk:3016
+msgid "<F5>\t\tUpdate"
+msgstr "<F5>\t\tCập nhật"
+
+#: gitk:3471 gitk:3480
+#, tcl-format
+msgid "Error creating temporary directory %s:"
+msgstr "Gặp lỗi khi tạo thư mục tạm %s:"
+
+#: gitk:3493
+#, tcl-format
+msgid "Error getting \"%s\" from %s:"
+msgstr "Lỗi chào hỏi \"%s\" từ %s:"
+
+#: gitk:3556
+msgid "command failed:"
+msgstr "lệnh gặp lỗi:"
+
+#: gitk:3705
+msgid "No such commit"
+msgstr "Không có lần chuyển giao như vậy"
+
+#: gitk:3719
+msgid "git gui blame: command failed:"
+msgstr "git gui blame: lệnh gặp lỗi:"
+
+#: gitk:3750
+#, tcl-format
+msgid "Couldn't read merge head: %s"
+msgstr "Không thể độc đầu của hòa trộn: %s"
+
+# tcl-format
+#: gitk:3758
+#, tcl-format
+msgid "Error reading index: %s"
+msgstr "Gặp lỗi khi đọc chỉ mục: %s"
+
+#: gitk:3783
+#, tcl-format
+msgid "Couldn't start git blame: %s"
+msgstr "Không thể khởi chạy git blame: %s"
+
+#: gitk:3786 gitk:6652
+msgid "Searching"
+msgstr "Đang tìm kiếm"
+
+#: gitk:3818
+#, tcl-format
+msgid "Error running git blame: %s"
+msgstr "Gặp lỗi khi chạy git blame: %s"
+
+#: gitk:3846
+#, tcl-format
+msgid "That line comes from commit %s,  which is not in this view"
+msgstr "Dòng đến từ lần chuyển giao %s, cái mà không trong trình bày này"
+
+#: gitk:3860
+msgid "External diff viewer failed:"
+msgstr "Bộ trình bày diff từ bên ngoài gặp lỗi:"
+
+#: gitk:3978
+msgid "Gitk view definition"
+msgstr "Định nghĩa cách trình bày gitk"
+
+#: gitk:3982
+msgid "Remember this view"
+msgstr "Nhớ cách trình bày này"
+
+#: gitk:3983
+msgid "References (space separated list):"
+msgstr "Tham chiếu (danh sách ngăn cách bằng dấu cách):"
+
+#: gitk:3984
+msgid "Branches & tags:"
+msgstr "Nhánh & thẻ:"
+
+#: gitk:3985
+msgid "All refs"
+msgstr "Mọi tham chiếu"
+
+#: gitk:3986
+msgid "All (local) branches"
+msgstr "Mọi nhánh (nội bộ)"
+
+#: gitk:3987
+msgid "All tags"
+msgstr "Mọi thẻ"
+
+#: gitk:3988
+msgid "All remote-tracking branches"
+msgstr "Mọi nhánh remote-tracking"
+
+#: gitk:3989
+msgid "Commit Info (regular expressions):"
+msgstr "Thông tin chuyển giao (biểu thức chính quy):"
+
+#: gitk:3990
+msgid "Author:"
+msgstr "Tác giả:"
+
+#: gitk:3991
+msgid "Committer:"
+msgstr "Người chuyển giao:"
+
+#: gitk:3992
+msgid "Commit Message:"
+msgstr "Chú thích của lần chuyển giao:"
+
+#: gitk:3993
+msgid "Matches all Commit Info criteria"
+msgstr "Khớp mọi điều kiện Thông tin Chuyển giao"
+
+#: gitk:3994
+msgid "Changes to Files:"
+msgstr "Đổi thành Tập tin:"
+
+#: gitk:3995
+msgid "Fixed String"
+msgstr "Chuỗi cố định"
+
+#: gitk:3996
+msgid "Regular Expression"
+msgstr "Biểu thức chính quy"
+
+#: gitk:3997
+msgid "Search string:"
+msgstr "Chuỗi tìm kiếm:"
+
+#: gitk:3998
+msgid ""
+"Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
+"15:27:38\"):"
+msgstr ""
+"Ngày chuyển giao (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
+"15:27:38\"):"
+
+#: gitk:3999
+msgid "Since:"
+msgstr "Kể từ:"
+
+#: gitk:4000
+msgid "Until:"
+msgstr "Đến:"
+
+#: gitk:4001
+msgid "Limit and/or skip a number of revisions (positive integer):"
+msgstr "Giới hạn và/hoặc bỏ số của điểm xét (số nguyên âm):"
+
+#: gitk:4002
+msgid "Number to show:"
+msgstr "Số lượng hiển thị:"
+
+#: gitk:4003
+msgid "Number to skip:"
+msgstr "Số lượng sẽ bỏ qua:"
+
+#: gitk:4004
+msgid "Miscellaneous options:"
+msgstr "Tuỳ chọn hỗn hợp:"
+
+#: gitk:4005
+msgid "Strictly sort by date"
+msgstr "Sắp xếp chặt chẽ theo ngày"
+
+#: gitk:4006
+msgid "Mark branch sides"
+msgstr "Đánh dấu các cạnh nhánh"
+
+#: gitk:4007
+msgid "Limit to first parent"
+msgstr "Giới hạn thành cha mẹ đầu tiên"
+
+#: gitk:4008
+msgid "Simple history"
+msgstr "Lịch sử dạng đơn giản"
+
+#: gitk:4009
+msgid "Additional arguments to git log:"
+msgstr "Đối số bổ xung cho lệnh git log:"
+
+#: gitk:4010
+msgid "Enter files and directories to include, one per line:"
+msgstr "Nhập vào các tập tin và thư mục bao gồm, mỗi dòng một cái:"
+
+#: gitk:4011
+msgid "Command to generate more commits to include:"
+msgstr "Lệnh tạo ra nhiều lần chuyển giao hơn bao gồm:"
+
+#: gitk:4135
+msgid "Gitk: edit view"
+msgstr "Gitk: sửa cách trình bày"
+
+#: gitk:4143
+msgid "-- criteria for selecting revisions"
+msgstr "-- tiêu chuẩn chọn điểm xét duyệt"
+
+#: gitk:4148
+msgid "View Name"
+msgstr "Tên cách trình bày"
+
+#: gitk:4223
+msgid "Apply (F5)"
+msgstr "Áp dụng (F5)"
+
+#: gitk:4261
+msgid "Error in commit selection arguments:"
+msgstr "Lỗi trong các đối số chọn chuyển giao:"
+
+#: gitk:4314 gitk:4366 gitk:4827 gitk:4841 gitk:6107 gitk:12184 gitk:12185
+msgid "None"
+msgstr "Không"
+
+#: gitk:4924 gitk:4929
+msgid "Descendant"
+msgstr "Con cháu"
+
+#: gitk:4925
+msgid "Not descendant"
+msgstr "Không có con cháu"
+
+#: gitk:4932 gitk:4937
+msgid "Ancestor"
+msgstr "Tổ tiên chung"
+
+#: gitk:4933
+msgid "Not ancestor"
+msgstr "Không có chung tổ tiên"
+
+#: gitk:5223
+msgid "Local changes checked in to index but not committed"
+msgstr ""
+"Có thay đổi nội bộ đã được đưa vào bảng mục lục, nhưng chưa được chuyển giao"
+
+#: gitk:5259
+msgid "Local uncommitted changes, not checked in to index"
+msgstr "Có thay đổi nội bộ, nhưng chưa được đưa vào bảng mục lục"
+
+#: gitk:7032
+msgid "and many more"
+msgstr "và nhiều nữa"
+
+#: gitk:7035
+msgid "many"
+msgstr "nhiều"
+
+#: gitk:7222
+msgid "Tags:"
+msgstr "Thẻ:"
+
+#: gitk:7239 gitk:7245 gitk:8708
+msgid "Parent"
+msgstr "Cha"
+
+#: gitk:7250
+msgid "Child"
+msgstr "Con"
+
+#: gitk:7259
+msgid "Branch"
+msgstr "Nhánh"
+
+#: gitk:7262
+msgid "Follows"
+msgstr "Đứng sau"
+
+#: gitk:7265
+msgid "Precedes"
+msgstr "Đứng trước"
+
+# tcl-format
+#: gitk:7849
+#, tcl-format
+msgid "Error getting diffs: %s"
+msgstr "Lỗi lấy diff: %s"
+
+#: gitk:8533
+msgid "Goto:"
+msgstr "Nhảy tới:"
+
+#: gitk:8554
+#, tcl-format
+msgid "Short SHA1 id %s is ambiguous"
+msgstr "Định danh SHA1 dạng ngắn %s là chưa đủ rõ ràng"
+
+#: gitk:8561
+#, tcl-format
+msgid "Revision %s is not known"
+msgstr "Không hiểu điểm xét duyệt %s"
+
+#: gitk:8571
+#, tcl-format
+msgid "SHA1 id %s is not known"
+msgstr "Không hiểu định danh SHA1 %s"
+
+#: gitk:8573
+#, tcl-format
+msgid "Revision %s is not in the current view"
+msgstr "Điểm %s không ở trong phần hiển thị hiện tại"
+
+#: gitk:8715 gitk:8730
+msgid "Date"
+msgstr "Ngày"
+
+#: gitk:8718
+msgid "Children"
+msgstr "Con cháu"
+
+#: gitk:8781
+#, tcl-format
+msgid "Reset %s branch to here"
+msgstr "Đặt lại nhánh %s tại đây"
+
+#: gitk:8783
+msgid "Detached head: can't reset"
+msgstr "Head đã bị tách rời: không thể đặt lại"
+
+#: gitk:8888 gitk:8894
+msgid "Skipping merge commit "
+msgstr "Bỏ qua lần chuyển giao hòa trộn "
+
+#: gitk:8903 gitk:8908
+msgid "Error getting patch ID for "
+msgstr "Gặp lỗi khi lấy ID miếng vá cho "
+
+#: gitk:8904 gitk:8909
+msgid " - stopping\n"
+msgstr " - dừng\n"
+
+#: gitk:8914 gitk:8917 gitk:8925 gitk:8939 gitk:8948
+msgid "Commit "
+msgstr "Commit "
+
+#: gitk:8918
+msgid ""
+" is the same patch as\n"
+"       "
+msgstr ""
+" là cùng một miếng vá với\n"
+"       "
+
+#: gitk:8926
+msgid ""
+" differs from\n"
+"       "
+msgstr ""
+" khác biệt từ\n"
+"       "
+
+#: gitk:8928
+msgid ""
+"Diff of commits:\n"
+"\n"
+msgstr ""
+"Khác biệt của lần chuyển giao (commit):\n"
+"\n"
+
+#: gitk:8940 gitk:8949
+#, tcl-format
+msgid " has %s children - stopping\n"
+msgstr " có %s con - dừng\n"
+
+#: gitk:8968
+#, tcl-format
+msgid "Error writing commit to file: %s"
+msgstr "Gặp lỗi trong quá trình ghi lần chuyển giao vào tập tin: %s"
+
+#: gitk:8974
+#, tcl-format
+msgid "Error diffing commits: %s"
+msgstr "Gặp lỗi khi so sánh sự khác biệt giữa các lần chuyển giao: %s"
+
+#: gitk:9020
+msgid "Top"
+msgstr "Đỉnh"
+
+#: gitk:9021
+msgid "From"
+msgstr "Từ"
+
+#: gitk:9026
+msgid "To"
+msgstr "Đến"
+
+#: gitk:9050
+msgid "Generate patch"
+msgstr "Tạo miếng vá"
+
+#: gitk:9052
+msgid "From:"
+msgstr "Từ:"
+
+#: gitk:9061
+msgid "To:"
+msgstr "Đến:"
+
+#: gitk:9070
+msgid "Reverse"
+msgstr "Đảo ngược"
+
+#: gitk:9072 gitk:9268
+msgid "Output file:"
+msgstr "Tập tin kết xuất:"
+
+#: gitk:9078
+msgid "Generate"
+msgstr "Tạo"
+
+#: gitk:9116
+msgid "Error creating patch:"
+msgstr "Gặp lỗi khi tạo miếng vá:"
+
+#: gitk:9139 gitk:9256 gitk:9313
+msgid "ID:"
+msgstr "ID:"
+
+#: gitk:9148
+msgid "Tag name:"
+msgstr "Tên thẻ:"
+
+#: gitk:9151
+msgid "Tag message is optional"
+msgstr "Ghi chú thẻ chỉ là tùy chọn"
+
+#: gitk:9153
+msgid "Tag message:"
+msgstr "Ghi chú cho thẻ:"
+
+#: gitk:9157 gitk:9322
+msgid "Create"
+msgstr "Tạo"
+
+#: gitk:9175
+msgid "No tag name specified"
+msgstr "Chưa chỉ ra tên của thẻ"
+
+#: gitk:9179
+#, tcl-format
+msgid "Tag \"%s\" already exists"
+msgstr "Thẻ “%s” đã có sẵn rồi"
+
+#: gitk:9189
+msgid "Error creating tag:"
+msgstr "Gặp lỗi khi tạo thẻ:"
+
+#: gitk:9265
+msgid "Command:"
+msgstr "Lệnh:"
+
+#: gitk:9273
+msgid "Write"
+msgstr "Ghi"
+
+#: gitk:9291
+msgid "Error writing commit:"
+msgstr "Gặp lỗi trong quá trình ghi chuyển giao:"
+
+#: gitk:9318
+msgid "Name:"
+msgstr "Tên:"
+
+#: gitk:9341
+msgid "Please specify a name for the new branch"
+msgstr "Vui lòng chỉ định tên cho nhánh mới"
+
+#: gitk:9346
+#, tcl-format
+msgid "Branch '%s' already exists. Overwrite?"
+msgstr "Nhánh “%s” đã có từ trước rồi. Ghi đè?"
+
+#: gitk:9413
+#, tcl-format
+msgid "Commit %s is already included in branch %s -- really re-apply it?"
+msgstr ""
+"Lần chuyển giao %s đã sẵn được bao gồm trong nhánh %s -- bạn có thực sự muốn "
+"áp dụng lại nó không?"
+
+#: gitk:9418
+msgid "Cherry-picking"
+msgstr "Đang cherry-pick"
+
+#: gitk:9427
+#, tcl-format
+msgid ""
+"Cherry-pick failed because of local changes to file '%s'.\n"
+"Please commit, reset or stash your changes and try again."
+msgstr ""
+"Cherry-pick gặp lỗi bởi vì các thay đổi nội bộ tập tin “%s”.\n"
+"Xin hãy chuyển giao, reset hay stash các thay đổi của bạn sau đó thử lại."
+
+#: gitk:9433
+msgid ""
+"Cherry-pick failed because of merge conflict.\n"
+"Do you wish to run git citool to resolve it?"
+msgstr ""
+"Cherry-pick gặp lỗi bởi vì xung đột trong hòa trộn.\n"
+"Bạn có muốn chạy lệnh “git citool” để giải quyết vấn đề này không?"
+
+#: gitk:9449 gitk:9507
+msgid "No changes committed"
+msgstr "Không có thay đổi nào cần chuyển giao"
+
+#: gitk:9476
+#, tcl-format
+msgid "Commit %s is not included in branch %s -- really revert it?"
+msgstr ""
+"Lần chuyển giao %s không được bao gồm trong nhánh %s -- bạn có thực sự muốn "
+"“revert” nó không?"
+
+#: gitk:9481
+msgid "Reverting"
+msgstr "Đang hoàn tác"
+
+#: gitk:9489
+#, tcl-format
+msgid ""
+"Revert failed because of local changes to the following files:%s Please "
+"commit, reset or stash  your changes and try again."
+msgstr ""
+"Revert gặp lỗi bởi vì tập tin sau đã được thay đổi nội bộ:%s\n"
+"Xin hãy chạy lệnh “commit”, “reset” hoặc “stash” rồi thử lại."
+
+#: gitk:9493
+msgid ""
+"Revert failed because of merge conflict.\n"
+" Do you wish to run git citool to resolve it?"
+msgstr ""
+"Revert gặp lỗi bởi vì xung đột hòa trộn.\n"
+" Bạn có muốn chạy lệnh “git citool” để phân giải nó không?"
+
+#: gitk:9536
+msgid "Confirm reset"
+msgstr "Xác nhật đặt lại"
+
+#: gitk:9538
+#, tcl-format
+msgid "Reset branch %s to %s?"
+msgstr "Đặt lại nhánh “%s” thành “%s”?"
+
+#: gitk:9540
+msgid "Reset type:"
+msgstr "Kiểu đặt lại:"
+
+#: gitk:9543
+msgid "Soft: Leave working tree and index untouched"
+msgstr "Mềm: Không động đến thư mục làm việc và bảng mục lục"
+
+#: gitk:9546
+msgid "Mixed: Leave working tree untouched, reset index"
+msgstr ""
+"Pha trộn: Không động chạm đến thư mục làm việc nhưng đặt lại bảng mục lục"
+
+#: gitk:9549
+msgid ""
+"Hard: Reset working tree and index\n"
+"(discard ALL local changes)"
+msgstr ""
+"Hard: Đặt lại cây làm việc và mục lục\n"
+"(hủy bỏ MỌI thay đổi nội bộ)"
+
+#: gitk:9566
+msgid "Resetting"
+msgstr "Đang đặt lại"
+
+#: gitk:9626
+msgid "Checking out"
+msgstr "Đang checkout"
+
+#: gitk:9679
+msgid "Cannot delete the currently checked-out branch"
+msgstr "Không thể xóa nhánh hiện tại đang được lấy ra"
+
+#: gitk:9685
+#, tcl-format
+msgid ""
+"The commits on branch %s aren't on any other branch.\n"
+"Really delete branch %s?"
+msgstr ""
+"Các lần chuyển giao trên nhánh %s không ở trên nhánh khác.\n"
+"Thực sự muốn xóa nhánh %s?"
+
+#: gitk:9716
+#, tcl-format
+msgid "Tags and heads: %s"
+msgstr "Thẻ và Đầu: %s"
+
+#: gitk:9731
+msgid "Filter"
+msgstr "Bộ lọc"
+
+#: gitk:10027
+msgid ""
+"Error reading commit topology information; branch and preceding/following "
+"tag information will be incomplete."
+msgstr ""
+"Gặp lỗi khi đọc thông tin hình học lần chuyển giao; thông tin nhánh và thẻ "
+"trước/sau sẽ không hoàn thiện."
+
+#: gitk:11004
+msgid "Tag"
+msgstr "Thẻ"
+
+#: gitk:11008
+msgid "Id"
+msgstr "Id"
+
+#: gitk:11091
+msgid "Gitk font chooser"
+msgstr "Hộp thoại chọn phông Gitk"
+
+#: gitk:11108
+msgid "B"
+msgstr "B"
+
+#: gitk:11111
+msgid "I"
+msgstr "I"
+
+#: gitk:11229
+msgid "Commit list display options"
+msgstr "Các tùy chọn về hiển thị danh sách lần chuyển giao"
+
+#: gitk:11232
+msgid "Maximum graph width (lines)"
+msgstr "Độ rộng biểu đồ tối đa (dòng)"
+
+#: gitk:11235
+#, tcl-format
+msgid "Maximum graph width (% of pane)"
+msgstr "Độ rộng biểu đồ tối đa (% của bảng)"
+
+#: gitk:11238
+msgid "Show local changes"
+msgstr "Hiển thị các thay đổi nội bộ"
+
+#: gitk:11241
+msgid "Auto-select SHA1 (length)"
+msgstr "Tự chọn SHA1 (độ dài)"
+
+#: gitk:11245
+msgid "Hide remote refs"
+msgstr "Ẩn tham chiếu đến máy chủ"
+
+#: gitk:11249
+msgid "Diff display options"
+msgstr "Các tùy chọn trình bày các khác biệt"
+
+#: gitk:11251
+msgid "Tab spacing"
+msgstr "Khoảng cách tab"
+
+#: gitk:11254
+msgid "Display nearby tags/heads"
+msgstr "Hiển thị các thẻ/đầu xung quanh"
+
+#: gitk:11257
+msgid "Maximum # tags/heads to show"
+msgstr "Số lượng thẻ/đầu tối đa sẽ hiển thị"
+
+#: gitk:11260
+msgid "Limit diffs to listed paths"
+msgstr "Giới hạn các khác biệt cho đường dẫn đã liệt kê"
+
+#: gitk:11263
+msgid "Support per-file encodings"
+msgstr "Hỗ trợ mã hóa mỗi-dòng"
+
+#: gitk:11269 gitk:11416
+msgid "External diff tool"
+msgstr "Công cụ so sánh từ bên ngoài"
+
+#: gitk:11270
+msgid "Choose..."
+msgstr "Chọn..."
+
+#: gitk:11275
+msgid "General options"
+msgstr "Các tùy chọn chung"
+
+#: gitk:11278
+msgid "Use themed widgets"
+msgstr "Dùng các widget chủ đề"
+
+#: gitk:11280
+msgid "(change requires restart)"
+msgstr "(để thay đổi cần khởi động lại)"
+
+#: gitk:11282
+msgid "(currently unavailable)"
+msgstr "(hiện tại không sẵn sàng)"
+
+#: gitk:11293
+msgid "Colors: press to choose"
+msgstr "Màu sắc: bấm vào nút phía dưới để chọn màu"
+
+#: gitk:11296
+msgid "Interface"
+msgstr "Giao diện"
+
+#: gitk:11297
+msgid "interface"
+msgstr "giao diện"
+
+#: gitk:11300
+msgid "Background"
+msgstr "Nền"
+
+#: gitk:11301 gitk:11331
+msgid "background"
+msgstr "nền"
+
+#: gitk:11304
+msgid "Foreground"
+msgstr "Tiền cảnh"
+
+#: gitk:11305
+msgid "foreground"
+msgstr "tiền cảnh"
+
+#: gitk:11308
+msgid "Diff: old lines"
+msgstr "So sánh: dòng cũ"
+
+#: gitk:11309
+msgid "diff old lines"
+msgstr "diff dòng cũ"
+
+#: gitk:11313
+msgid "Diff: new lines"
+msgstr "So sánh: dòng mới"
+
+#: gitk:11314
+msgid "diff new lines"
+msgstr "màu dòng mới"
+
+#: gitk:11318
+msgid "Diff: hunk header"
+msgstr "So sánh: phần đầu của đoạn"
+
+#: gitk:11320
+msgid "diff hunk header"
+msgstr "màu của phần đầu của đoạn khi so sánh"
+
+#: gitk:11324
+msgid "Marked line bg"
+msgstr "Nền dòng đánh dấu"
+
+#: gitk:11326
+msgid "marked line background"
+msgstr "nền dòng được đánh dấu"
+
+#: gitk:11330
+msgid "Select bg"
+msgstr "Màu nền"
+
+#: gitk:11339
+msgid "Fonts: press to choose"
+msgstr "Phông chữ: bấm vào các nút ở dưới để chọn"
+
+#: gitk:11341
+msgid "Main font"
+msgstr "Phông chữ chính"
+
+#: gitk:11342
+msgid "Diff display font"
+msgstr "Phông chữ dùng khi so sánh"
+
+#: gitk:11343
+msgid "User interface font"
+msgstr "Phông chữ giao diện"
+
+#: gitk:11365
+msgid "Gitk preferences"
+msgstr "Cá nhân hóa các cài đặt cho Gitk"
+
+#: gitk:11374
+msgid "General"
+msgstr "Chung"
+
+#: gitk:11375
+msgid "Colors"
+msgstr "Màu sắc"
+
+#: gitk:11376
+msgid "Fonts"
+msgstr "Phông chữ"
+
+#: gitk:11426
+#, tcl-format
+msgid "Gitk: choose color for %s"
+msgstr "Gitk: chọn màu cho %s"
+
+#: gitk:12080
+msgid "Cannot find a git repository here."
+msgstr "Không thể tìm thấy kho git ở đây."
+
+#: gitk:12127
+#, tcl-format
+msgid "Ambiguous argument '%s': both revision and filename"
+msgstr "Đối số “%s” chưa rõ ràng: vừa là điểm xét duyệt vừa là tên tập tin"
+
+#: gitk:12139
+msgid "Bad arguments to gitk:"
+msgstr "Đối số không hợp lệ cho gitk:"
+
+#: gitk:12242
+msgid "Command line"
+msgstr "Dòng lệnh"
diff --git a/http.c b/http.c
index f04621e61d157478f4100dc710118e1bd8634c70..c8cd50dd0c2b2213a86957cd4b24c03c0d85717d 100644 (file)
--- a/http.c
+++ b/http.c
@@ -927,7 +927,7 @@ static int extract_param(const char *raw, const char *name,
                return -1;
        raw++;
 
-       while (*raw && !isspace(*raw))
+       while (*raw && !isspace(*raw) && *raw != ';')
                strbuf_addch(out, *raw++);
        return 0;
 }
@@ -971,7 +971,7 @@ static void extract_content_type(struct strbuf *raw, struct strbuf *type,
 
        strbuf_reset(charset);
        while (*p) {
-               while (isspace(*p))
+               while (isspace(*p) || *p == ';')
                        p++;
                if (!extract_param(p, "charset", charset))
                        return;
index 150010105806291180d9e6bdfcf1939fb242f2ac..afcc98db930a36358283ff199a428b6c5bbbaf8f 100644 (file)
@@ -1174,9 +1174,7 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
                         */
                        add_line_range(rev, parents[i], cand[i]);
                        clear_commit_line_range(rev, commit);
-                       commit->parents = xmalloc(sizeof(struct commit_list));
-                       commit->parents->item = parents[i];
-                       commit->parents->next = NULL;
+                       commit_list_append(parents[i], &commit->parents);
                        free(parents);
                        free(cand);
                        free_diffqueues(nparents, diffqueues);
index cf2f86c86632c6df8862fc065299e6cc35aa4829..10e68442b35c9bd9ca1c00c52609a4827b8bace5 100644 (file)
@@ -376,7 +376,7 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
        struct strbuf gpg_output = STRBUF_INIT;
        int status;
 
-       if (parse_signed_commit(commit->object.sha1, &payload, &signature) <= 0)
+       if (parse_signed_commit(commit, &payload, &signature) <= 0)
                goto out;
 
        status = verify_signed_buffer(payload.buf, payload.len,
@@ -588,7 +588,7 @@ void show_log(struct rev_info *opt)
                show_mergetag(opt, commit);
        }
 
-       if (!commit->buffer)
+       if (!get_cached_commit_buffer(commit, NULL))
                return;
 
        if (opt->show_notes) {
index f8480018178c7eb8b88dcd3e1f166dc953bfbe11..e6e1fa33fdd0d7615c61a00d21111a5a83fe96cd 100644 (file)
@@ -40,7 +40,7 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two,
 
 static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
 {
-       struct commit *commit = xcalloc(1, sizeof(struct commit));
+       struct commit *commit = alloc_commit_node();
        struct merge_remote_desc *desc = xmalloc(sizeof(*desc));
 
        desc->name = comment;
@@ -190,9 +190,11 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)
                        printf(_("(bad commit)\n"));
                else {
                        const char *title;
-                       int len = find_commit_subject(commit->buffer, &title);
+                       const char *msg = get_commit_buffer(commit, NULL);
+                       int len = find_commit_subject(msg, &title);
                        if (len)
                                printf("%.*s\n", len, title);
+                       unuse_commit_buffer(commit, msg);
                }
        }
 }
index 97444d02010e13de1eab9abe6f1fc71287658faf..49fd508317ebbde5a76f6af64318920ae237c8fd 100644 (file)
@@ -179,7 +179,7 @@ static int same_name(const struct cache_entry *ce, const char *name, int namelen
         * Always do exact compare, even if we want a case-ignoring comparison;
         * we do the quick exact one first, because it will be the common case.
         */
-       if (len == namelen && !cache_name_compare(name, namelen, ce->name, len))
+       if (len == namelen && !memcmp(name, ce->name, len))
                return 1;
 
        if (!icase)
index 97dfd63c9bf564ac052addc4a3f62a325bbc1303..c4e9bb7f6c0bde97c7c6d34094baa5ef7e318157 100644 (file)
@@ -48,7 +48,6 @@ int notes_cache_write(struct notes_cache *c)
 {
        unsigned char tree_sha1[20];
        unsigned char commit_sha1[20];
-       struct strbuf msg = STRBUF_INIT;
 
        if (!c || !c->tree.initialized || !c->tree.ref || !*c->tree.ref)
                return -1;
@@ -57,9 +56,8 @@ int notes_cache_write(struct notes_cache *c)
 
        if (write_notes_tree(&c->tree, tree_sha1))
                return -1;
-       strbuf_attach(&msg, c->validity,
-                     strlen(c->validity), strlen(c->validity) + 1);
-       if (commit_tree(&msg, tree_sha1, NULL, commit_sha1, NULL, NULL) < 0)
+       if (commit_tree(c->validity, strlen(c->validity), tree_sha1, NULL,
+                       commit_sha1, NULL, NULL) < 0)
                return -1;
        if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL,
                       0, UPDATE_REFS_QUIET_ON_ERR) < 0)
index 94a1a8ae466733b207ae5030f8a8894d66535f91..fd5fae255d2760d6b7895e95cee627b5e28f776e 100644 (file)
@@ -644,7 +644,8 @@ int notes_merge(struct notes_merge_options *o,
                struct commit_list *parents = NULL;
                commit_list_insert(remote, &parents); /* LIFO order */
                commit_list_insert(local, &parents);
-               create_notes_commit(local_tree, parents, &o->commit_msg,
+               create_notes_commit(local_tree, parents,
+                                   o->commit_msg.buf, o->commit_msg.len,
                                    result_sha1);
        }
 
@@ -671,8 +672,8 @@ int notes_merge_commit(struct notes_merge_options *o,
        DIR *dir;
        struct dirent *e;
        struct strbuf path = STRBUF_INIT;
-       char *msg = strstr(partial_commit->buffer, "\n\n");
-       struct strbuf sb_msg = STRBUF_INIT;
+       const char *buffer = get_commit_buffer(partial_commit, NULL);
+       const char *msg = strstr(buffer, "\n\n");
        int baselen;
 
        strbuf_addstr(&path, git_path(NOTES_MERGE_WORKTREE));
@@ -719,9 +720,9 @@ int notes_merge_commit(struct notes_merge_options *o,
                strbuf_setlen(&path, baselen);
        }
 
-       strbuf_attach(&sb_msg, msg, strlen(msg), strlen(msg) + 1);
-       create_notes_commit(partial_tree, partial_commit->parents, &sb_msg,
-                           result_sha1);
+       create_notes_commit(partial_tree, partial_commit->parents,
+                           msg, strlen(msg), result_sha1);
+       unuse_commit_buffer(partial_commit, buffer);
        if (o->verbosity >= 4)
                printf("Finalized notes merge commit: %s\n",
                        sha1_to_hex(result_sha1));
index a0b1d7be98253368921a6e95653ceb36dbda28b2..b64dc1b0219928ac149894c99a63dcc9fd419668 100644 (file)
@@ -4,7 +4,8 @@
 #include "notes-utils.h"
 
 void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
-                        const struct strbuf *msg, unsigned char *result_sha1)
+                        const char *msg, size_t msg_len,
+                        unsigned char *result_sha1)
 {
        unsigned char tree_sha1[20];
 
@@ -25,7 +26,7 @@ void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
                /* else: t->ref points to nothing, assume root/orphan commit */
        }
 
-       if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL, NULL))
+       if (commit_tree(msg, msg_len, tree_sha1, parents, result_sha1, NULL, NULL))
                die("Failed to commit notes tree to database");
 }
 
@@ -46,7 +47,7 @@ void commit_notes(struct notes_tree *t, const char *msg)
        if (buf.buf[buf.len - 1] != '\n')
                strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */
 
-       create_notes_commit(t, NULL, &buf, commit_sha1);
+       create_notes_commit(t, NULL, buf.buf, buf.len, commit_sha1);
        strbuf_insert(&buf, 0, "notes: ", 7); /* commit message starts at index 7 */
        update_ref(buf.buf, t->ref, commit_sha1, NULL, 0,
                   UPDATE_REFS_DIE_ON_ERR);
index 564e30cccd550f9acbd493f43c940bab1abba427..890ddb33e13ad6b9d43887216acbe5430ed534cc 100644 (file)
@@ -15,7 +15,7 @@
  * The resulting commit SHA1 is stored in result_sha1.
  */
 void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
-                        const struct strbuf *msg, unsigned char *result_sha1);
+                        const char *msg, size_t msg_len, unsigned char *result_sha1);
 
 void commit_notes(struct notes_tree *t, const char *msg);
 
index 57a0890a87b66ea493337409606e57fd44d29f90..9c31e9a5e0e0d913044501089e09037e47894f03 100644 (file)
--- a/object.c
+++ b/object.c
@@ -197,8 +197,8 @@ struct object *parse_object_buffer(const unsigned char *sha1, enum object_type t
                if (commit) {
                        if (parse_commit_buffer(commit, buffer, size))
                                return NULL;
-                       if (!commit->buffer) {
-                               commit->buffer = buffer;
+                       if (!get_cached_commit_buffer(commit, NULL)) {
+                               set_commit_buffer(commit, buffer, size);
                                *eaten_p = 1;
                        }
                        obj = &commit->object;
index f24752a85bc101c117d91b86a0526ca4c1eceee0..b5cf3d52c3228a06689c847a3202bedf95f00dcf 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -273,7 +273,7 @@ static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
 
 enum rfc2047_type {
        RFC2047_SUBJECT,
-       RFC2047_ADDRESS,
+       RFC2047_ADDRESS
 };
 
 static int is_rfc2047_special(char ch, enum rfc2047_type type)
@@ -605,29 +605,16 @@ static char *replace_encoding_header(char *buf, const char *encoding)
        return strbuf_detach(&tmp, NULL);
 }
 
-char *logmsg_reencode(const struct commit *commit,
-                     char **commit_encoding,
-                     const char *output_encoding)
+const char *logmsg_reencode(const struct commit *commit,
+                           char **commit_encoding,
+                           const char *output_encoding)
 {
        static const char *utf8 = "UTF-8";
        const char *use_encoding;
        char *encoding;
-       char *msg = commit->buffer;
+       const char *msg = get_commit_buffer(commit, NULL);
        char *out;
 
-       if (!msg) {
-               enum object_type type;
-               unsigned long size;
-
-               msg = read_sha1_file(commit->object.sha1, &type, &size);
-               if (!msg)
-                       die("Cannot read commit object %s",
-                           sha1_to_hex(commit->object.sha1));
-               if (type != OBJ_COMMIT)
-                       die("Expected commit for '%s', got %s",
-                           sha1_to_hex(commit->object.sha1), typename(type));
-       }
-
        if (!output_encoding || !*output_encoding) {
                if (commit_encoding)
                        *commit_encoding =
@@ -651,12 +638,13 @@ char *logmsg_reencode(const struct commit *commit,
                 * Otherwise, we still want to munge the encoding header in the
                 * result, which will be done by modifying the buffer. If we
                 * are using a fresh copy, we can reuse it. But if we are using
-                * the cached copy from commit->buffer, we need to duplicate it
-                * to avoid munging commit->buffer.
+                * the cached copy from get_commit_buffer, we need to duplicate it
+                * to avoid munging the cached copy.
                 */
-               out = msg;
-               if (out == commit->buffer)
-                       out = xstrdup(out);
+               if (msg == get_cached_commit_buffer(commit, NULL))
+                       out = xstrdup(msg);
+               else
+                       out = (char *)msg;
        }
        else {
                /*
@@ -666,8 +654,8 @@ char *logmsg_reencode(const struct commit *commit,
                 * copy, we can free it.
                 */
                out = reencode_string(msg, output_encoding, use_encoding);
-               if (out && msg != commit->buffer)
-                       free(msg);
+               if (out)
+                       unuse_commit_buffer(commit, msg);
        }
 
        /*
@@ -686,12 +674,6 @@ char *logmsg_reencode(const struct commit *commit,
        return out ? out : msg;
 }
 
-void logmsg_free(char *msg, const struct commit *commit)
-{
-       if (msg != commit->buffer)
-               free(msg);
-}
-
 static int mailmap_name(const char **email, size_t *email_len,
                        const char **name, size_t *name_len)
 {
@@ -795,7 +777,7 @@ struct format_commit_context {
        struct signature_check signature_check;
        enum flush_type flush_type;
        enum trunc_type truncate;
-       char *message;
+       const char *message;
        char *commit_encoding;
        size_t width, indent1, indent2;
        int auto_color;
@@ -1535,7 +1517,7 @@ void format_commit_message(const struct commit *commit,
        }
 
        free(context.commit_encoding);
-       logmsg_free(context.message, commit);
+       unuse_commit_buffer(commit, context.message);
        free(context.signature_check.gpg_output);
        free(context.signature_check.signer);
 }
@@ -1704,7 +1686,7 @@ void pretty_print_commit(struct pretty_print_context *pp,
        unsigned long beginning_of_body;
        int indent = 4;
        const char *msg;
-       char *reencoded;
+       const char *reencoded;
        const char *encoding;
        int need_8bit_cte = pp->need_8bit_cte;
 
@@ -1771,7 +1753,7 @@ void pretty_print_commit(struct pretty_print_context *pp,
        if (pp->fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)
                strbuf_addch(sb, '\n');
 
-       logmsg_free(reencoded, commit);
+       unuse_commit_buffer(commit, reencoded);
 }
 
 void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
index 7f5645e74546e459efdb584dbf63e1fd75857317..6a45966ec499b47efbc76719046b53633e8839a1 100644 (file)
@@ -422,18 +422,26 @@ int df_name_compare(const char *name1, int len1, int mode1,
        return c1 - c2;
 }
 
-int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2)
+int name_compare(const char *name1, size_t len1, const char *name2, size_t len2)
 {
-       int len = len1 < len2 ? len1 : len2;
-       int cmp;
-
-       cmp = memcmp(name1, name2, len);
+       size_t min_len = (len1 < len2) ? len1 : len2;
+       int cmp = memcmp(name1, name2, min_len);
        if (cmp)
                return cmp;
        if (len1 < len2)
                return -1;
        if (len1 > len2)
                return 1;
+       return 0;
+}
+
+int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2)
+{
+       int cmp;
+
+       cmp = name_compare(name1, len1, name2, len2);
+       if (cmp)
+               return cmp;
 
        if (stage1 < stage2)
                return -1;
@@ -442,11 +450,6 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char
        return 0;
 }
 
-int cache_name_compare(const char *name1, int len1, const char *name2, int len2)
-{
-       return cache_name_stage_compare(name1, len1, 0, name2, len2, 0);
-}
-
 static int index_name_stage_pos(const struct index_state *istate, const char *name, int namelen, int stage)
 {
        int first, last;
diff --git a/refs.c b/refs.c
index dc457742eade241ec6b0001580d1ce1a880fee31..20e2bf18c9da51904d53ec594022eb75e7cefcf0 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -7,21 +7,27 @@
 
 /*
  * How to handle various characters in refnames:
+ * This table is used by both the SIMD and non-SIMD code.  It has
+ * some cases that are only useful for the SIMD; these are handled
+ * equivalently to the listed disposition in the non-SIMD code.
  * 0: An acceptable character for refs
- * 1: End-of-component
- * 2: ., look for a preceding . to reject .. in refs
- * 3: {, look for a preceding @ to reject @{ in refs
- * 4: A bad character: ASCII control characters, "~", "^", ":" or SP
+ * 1: @, look for a following { to reject @{ in refs (SIMD or = 0)
+ * 2: \0: End-of-component and string
+ * 3: /: End-of-component (SIMD or = 2)
+ * 4: ., look for a preceding . to reject .. in refs
+ * 5: {, look for a preceding @ to reject @{ in refs
+ * 6: *, usually a bad character except, once as a wildcard (SIMD or = 7)
+ * 7: A bad character except * (see check_refname_component below)
  */
 static unsigned char refname_disposition[256] = {
-       1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-       4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-       4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 1,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
+       2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+       7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 4, 3,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 7,
+       1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 7, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 7, 7
 };
 
 /*
@@ -33,8 +39,9 @@ static unsigned char refname_disposition[256] = {
  * - any path component of it begins with ".", or
  * - it has double dots "..", or
  * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
- * - it ends with a "/".
- * - it ends with ".lock"
+ * - it has pattern-matching notation "*", "?", "[", anywhere, or
+ * - it ends with a "/", or
+ * - it ends with ".lock", or
  * - it contains a "\" (backslash)
  */
 static int check_refname_component(const char *refname, int flags)
@@ -46,17 +53,19 @@ static int check_refname_component(const char *refname, int flags)
                int ch = *cp & 255;
                unsigned char disp = refname_disposition[ch];
                switch (disp) {
-               case 1:
+               case 2: /* fall-through */
+               case 3:
                        goto out;
-               case 2:
+               case 4:
                        if (last == '.')
                                return -1; /* Refname contains "..". */
                        break;
-               case 3:
+               case 5:
                        if (last == '@')
                                return -1; /* Refname contains "@{". */
                        break;
-               case 4:
+               case 6: /* fall-through */
+               case 7:
                        return -1;
                }
                last = ch;
@@ -79,7 +88,7 @@ static int check_refname_component(const char *refname, int flags)
        return cp - refname;
 }
 
-int check_refname_format(const char *refname, int flags)
+static int check_refname_format_bytewise(const char *refname, int flags)
 {
        int component_len, component_count = 0;
 
@@ -115,6 +124,195 @@ int check_refname_format(const char *refname, int flags)
        return 0;
 }
 
+#if defined(__GNUC__) && defined(__x86_64__)
+#define SSE_VECTOR_BYTES 16
+
+/* Vectorized version of check_refname_format. */
+int check_refname_format(const char *refname, int flags)
+{
+       const char *cp = refname;
+
+       const __m128i dot = _mm_set1_epi8('.');
+       const __m128i at = _mm_set1_epi8('@');
+       const __m128i curly = _mm_set1_epi8('{');
+       const __m128i slash = _mm_set1_epi8('/');
+       const __m128i zero = _mm_set1_epi8('\000');
+       const __m128i el = _mm_set1_epi8('l');
+
+       /* below '*', all characters are forbidden or rare */
+       const __m128i star_ub = _mm_set1_epi8('*' + 1);
+
+       const __m128i colon = _mm_set1_epi8(':');
+       const __m128i question = _mm_set1_epi8('?');
+
+       /* '['..'^' contains 4 characters: 3 forbidden and 1 rare */
+       const __m128i bracket_lb = _mm_set1_epi8('[' - 1);
+       const __m128i caret_ub = _mm_set1_epi8('^' + 1);
+
+       /* '~' and above are forbidden */
+       const __m128i tilde_lb = _mm_set1_epi8('~' - 1);
+
+       int component_count = 0;
+
+       if (refname[0] == 0 || refname[0] == '/') {
+               /* entirely empty ref or initial ref component */
+               return -1;
+       }
+
+       /*
+        * Initial ref component of '.'; below we look for /. so we'll
+        * miss this.
+        */
+       if (refname[0] == '.') {
+               if (refname[1] == '/' || refname[1] == '\0')
+                       return -1;
+               if (!(flags & REFNAME_DOT_COMPONENT))
+                       return -1;
+       }
+       while(1) {
+               __m128i tmp, tmp1, result;
+               uint64_t mask;
+
+               if ((uintptr_t) cp % PAGE_SIZE > PAGE_SIZE - SSE_VECTOR_BYTES  - 1)
+                       /*
+                        * End-of-page; fall back to slow method for
+                        * this entire ref.
+                        */
+                       return check_refname_format_bytewise(refname, flags);
+
+               tmp = _mm_loadu_si128((__m128i *)cp);
+               tmp1 = _mm_loadu_si128((__m128i *)(cp + 1));
+
+               /*
+                * This range (note the lt) contains some
+                * permissible-but-rare characters (including all
+                * characters >= 128), which we handle later.  It also
+                * includes \000.
+                */
+               result = _mm_cmplt_epi8(tmp, star_ub);
+
+               result = _mm_or_si128(result, _mm_cmpeq_epi8(tmp, question));
+               result = _mm_or_si128(result, _mm_cmpeq_epi8(tmp, colon));
+
+               /* This range contains the permissible ] as bycatch */
+               result = _mm_or_si128(result, _mm_and_si128(
+                                             _mm_cmpgt_epi8(tmp, bracket_lb),
+                                             _mm_cmplt_epi8(tmp, caret_ub)));
+
+               result = _mm_or_si128(result, _mm_cmpgt_epi8(tmp, tilde_lb));
+
+               /* .. */
+               result = _mm_or_si128(result, _mm_and_si128(
+                                             _mm_cmpeq_epi8(tmp, dot),
+                                             _mm_cmpeq_epi8(tmp1, dot)));
+               /* @{ */
+               result = _mm_or_si128(result, _mm_and_si128(
+                                             _mm_cmpeq_epi8(tmp, at),
+                                             _mm_cmpeq_epi8(tmp1, curly)));
+               /* // */
+               result = _mm_or_si128(result, _mm_and_si128(
+                                             _mm_cmpeq_epi8(tmp, slash),
+                                             _mm_cmpeq_epi8(tmp1, slash)));
+               /* trailing / */
+               result = _mm_or_si128(result, _mm_and_si128(
+                                             _mm_cmpeq_epi8(tmp, slash),
+                                             _mm_cmpeq_epi8(tmp1, zero)));
+               /* .l, beginning of .lock */
+               result = _mm_or_si128(result, _mm_and_si128(
+                                             _mm_cmpeq_epi8(tmp, dot),
+                                             _mm_cmpeq_epi8(tmp1, el)));
+               /*
+                * Even though /. is not necessarily an error, we flag
+                * it anyway. If we find it, we'll check if it's valid
+                * and if so we'll advance just past it.
+                */
+               result = _mm_or_si128(result, _mm_and_si128(
+                                             _mm_cmpeq_epi8(tmp, slash),
+                                             _mm_cmpeq_epi8(tmp1, dot)));
+
+               mask = _mm_movemask_epi8(result);
+               if (mask) {
+                       /*
+                        * We've found either end-of-string, or some
+                        * probably-bad character or substring.
+                        */
+                       int i = __builtin_ctz(mask);
+                       switch (refname_disposition[cp[i] & 255]) {
+                       case 0: /* fall-through */
+                       case 5:
+                               /*
+                                * bycatch: a good character that's in
+                                * one of the ranges of mostly-forbidden
+                                * characters
+                                */
+                               cp += i + 1;
+                               break;
+                       case 1:
+                               if (cp[i + 1] == '{')
+                                       return -1;
+                               cp += i + 1;
+                               break;
+                       case 2:
+                               if (!(flags & REFNAME_ALLOW_ONELEVEL)
+                                   && !component_count && !strchr(refname, '/'))
+                                       /* Refname has only one component. */
+                                       return -1;
+                               return 0;
+                       case 3:
+                               component_count ++;
+                               /*
+                                * Even if leading dots are allowed, don't
+                                * allow "." as a component (".." is
+                                * prevented by case 4 below).
+                                */
+                               if (cp[i + 1] == '.') {
+                                       if (cp[i + 2] == '\0')
+                                               return -1;
+                                       if (flags & REFNAME_DOT_COMPONENT) {
+                                               /* skip to just after the /. */
+                                               cp += i + 2;
+                                               break;
+                                       }
+                                       return -1;
+                               } else if (cp[i + 1] == '/' || cp[i + 1] == '\0')
+                                       return -1;
+                               break;
+                       case 4:
+                               if (cp[i + 1] == '.' || cp[i + 1] == '\0')
+                                       return -1;
+                               /* .lock as end-of-component or end-of-string */
+                               if ((!strncmp(cp + i, ".lock", 5))
+                                   && (cp[i + 5] == '/' || cp[i + 5] == 0))
+                                       return -1;
+                               cp += 1;
+                               break;
+                       case 6:
+                               if (((cp == refname + i) || cp[i - 1] == '/')
+                                   && (cp[i + 1] == '/' || cp[i + 1] == 0))
+                                       if (flags & REFNAME_REFSPEC_PATTERN) {
+                                               flags &= ~REFNAME_REFSPEC_PATTERN;
+                                               /* restart after the * */
+                                               cp += i + 1;
+                                               continue;
+                                       }
+                               /* fall-through */
+                       case 7:
+                               return -1;
+                       }
+               } else
+                       cp += SSE_VECTOR_BYTES;
+       }
+}
+
+#else
+
+int check_refname_format (const char *refname, int flags)
+{
+       return check_refname_format_bytewise(refname, flags);
+}
+
+#endif
+
 struct ref_entry;
 
 /*
index 30d2829c2b171f7af8891b5c07a0317c72de1871..a0c6ccf5b28e2dfaf4cfb41c22290de550b7cc7d 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1193,7 +1193,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
        case 1:
                break;
        case 0:
-               if (!memcmp(dst_value, "refs/", 5))
+               if (starts_with(dst_value, "refs/"))
                        matched_dst = make_linked_ref(dst_value, dst_tail);
                else if (is_null_sha1(matched_src->new_sha1))
                        error("unable to delete '%s': remote ref does not exist",
index 3818b4628d0b5b4fa74428decaa940bef2804856..2571ada6bf66ce6e945c539be4b0123e5b9648a9 100644 (file)
@@ -1649,8 +1649,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->skip_count = atoi(optarg);
                return argcount;
        } else if ((*arg == '-') && isdigit(arg[1])) {
-       /* accept -<digit>, like traditional "head" */
-               revs->max_count = atoi(arg + 1);
+               /* accept -<digit>, like traditional "head" */
+               if (strtol_i(arg + 1, 10, &revs->max_count) < 0 ||
+                   revs->max_count < 0)
+                       die("'%s': not a non-negative integer", arg + 1);
                revs->no_walk = 0;
        } else if (!strcmp(arg, "-n")) {
                if (argc <= 1)
@@ -2789,7 +2791,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
 {
        int retval;
        const char *encoding;
-       char *message;
+       const char *message;
        struct strbuf buf = STRBUF_INIT;
 
        if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
@@ -2831,14 +2833,21 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
                format_display_notes(commit->object.sha1, &buf, encoding, 1);
        }
 
-       /* Find either in the original commit message, or in the temporary */
+       /*
+        * Find either in the original commit message, or in the temporary.
+        * Note that we cast away the constness of "message" here. It is
+        * const because it may come from the cached commit buffer. That's OK,
+        * because we know that it is modifiable heap memory, and that while
+        * grep_buffer may modify it for speed, it will restore any
+        * changes before returning.
+        */
        if (buf.len)
                retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
        else
                retval = grep_buffer(&opt->grep_filter,
-                                    message, strlen(message));
+                                    (char *)message, strlen(message));
        strbuf_release(&buf);
-       logmsg_free(message, commit);
+       unuse_commit_buffer(commit, message);
        return retval;
 }
 
index 0a80c58d1194c3476dfd2861a98fbd08610597a3..c513d7eeb4d747cbc41950e3ff197aca8d81d6d4 100644 (file)
@@ -116,39 +116,23 @@ static const char *action_name(const struct replay_opts *opts)
        return opts->action == REPLAY_REVERT ? "revert" : "cherry-pick";
 }
 
-static char *get_encoding(const char *message);
-
 struct commit_message {
        char *parent_label;
        const char *label;
        const char *subject;
-       char *reencoded_message;
        const char *message;
 };
 
 static int get_message(struct commit *commit, struct commit_message *out)
 {
-       const char *encoding;
        const char *abbrev, *subject;
        int abbrev_len, subject_len;
        char *q;
 
-       if (!commit->buffer)
-               return -1;
-       encoding = get_encoding(commit->buffer);
-       if (!encoding)
-               encoding = "UTF-8";
        if (!git_commit_encoding)
                git_commit_encoding = "UTF-8";
 
-       out->reencoded_message = NULL;
-       out->message = commit->buffer;
-       if (same_encoding(encoding, git_commit_encoding))
-               out->reencoded_message = reencode_string(commit->buffer,
-                                       git_commit_encoding, encoding);
-       if (out->reencoded_message)
-               out->message = out->reencoded_message;
-
+       out->message = logmsg_reencode(commit, NULL, git_commit_encoding);
        abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
        abbrev_len = strlen(abbrev);
 
@@ -167,29 +151,10 @@ static int get_message(struct commit *commit, struct commit_message *out)
        return 0;
 }
 
-static void free_message(struct commit_message *msg)
+static void free_message(struct commit *commit, struct commit_message *msg)
 {
        free(msg->parent_label);
-       free(msg->reencoded_message);
-}
-
-static char *get_encoding(const char *message)
-{
-       const char *p = message, *eol;
-
-       while (*p && *p != '\n') {
-               for (eol = p + 1; *eol && *eol != '\n'; eol++)
-                       ; /* do nothing */
-               if (starts_with(p, "encoding ")) {
-                       char *result = xmalloc(eol - 8 - p);
-                       strlcpy(result, p + 9, eol - 8 - p);
-                       return result;
-               }
-               p = eol;
-               if (*p == '\n')
-                       p++;
-       }
-       return NULL;
+       unuse_commit_buffer(commit, msg->message);
 }
 
 static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
@@ -278,7 +243,7 @@ static int fast_forward_to(const unsigned char *to, const unsigned char *from,
 
        read_cache();
        if (checkout_fast_forward(from, to, 1))
-               exit(1); /* the callee should have complained already */
+               exit(128); /* the callee should have complained already */
        ref_lock = lock_any_ref_for_update("HEAD", unborn ? null_sha1 : from,
                                           0, NULL);
        if (!ref_lock)
@@ -489,7 +454,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
        unsigned char head[20];
        struct commit *base, *next, *parent;
        const char *base_label, *next_label;
-       struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
+       struct commit_message msg = { NULL, NULL, NULL, NULL };
        char *defmsg = NULL;
        struct strbuf msgbuf = STRBUF_INIT;
        int res, unborn = 0, allow;
@@ -654,7 +619,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
                res = run_git_commit(defmsg, opts, allow);
 
 leave:
-       free_message(&msg);
+       free_message(commit, &msg);
        free(defmsg);
 
        return res;
@@ -701,10 +666,12 @@ static int format_todo(struct strbuf *buf, struct commit_list *todo_list,
        int subject_len;
 
        for (cur = todo_list; cur; cur = cur->next) {
+               const char *commit_buffer = get_commit_buffer(cur->item, NULL);
                sha1_abbrev = find_unique_abbrev(cur->item->object.sha1, DEFAULT_ABBREV);
-               subject_len = find_commit_subject(cur->item->buffer, &subject);
+               subject_len = find_commit_subject(commit_buffer, &subject);
                strbuf_addf(buf, "%s %s %.*s\n", action_str, sha1_abbrev,
                        subject_len, subject);
+               unuse_commit_buffer(cur->item, commit_buffer);
        }
        return 0;
 }
index 72e6ac6a6e4f8573676084e443ce8fae038f4f56..a91e0c924b8d3b40a280de92fdded2a04a961221 100644 (file)
@@ -862,27 +862,17 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
                commit_list_insert(l->item, &backup);
        }
        while (list) {
-               char *p, *to_free = NULL;
+               const char *p, *buf;
                struct commit *commit;
-               enum object_type type;
-               unsigned long size;
                int matches;
 
                commit = pop_most_recent_commit(&list, ONELINE_SEEN);
                if (!parse_object(commit->object.sha1))
                        continue;
-               if (commit->buffer)
-                       p = commit->buffer;
-               else {
-                       p = read_sha1_file(commit->object.sha1, &type, &size);
-                       if (!p)
-                               continue;
-                       to_free = p;
-               }
-
-               p = strstr(p, "\n\n");
+               buf = get_commit_buffer(commit, NULL);
+               p = strstr(buf, "\n\n");
                matches = p && !regexec(&regex, p + 2, 0, NULL, 0);
-               free(to_free);
+               unuse_commit_buffer(commit, buf);
 
                if (matches) {
                        hashcpy(sha1, commit->object.sha1);
index 272fceef96c06e6e104d6341f36b1764e7d0c8db..fd53b5718780e25f03924e38438706acc54598db 100644 (file)
@@ -142,7 +142,7 @@ prepare_httpd() {
        HTTPD_URL_USER=$HTTPD_PROTO://user%40host@$HTTPD_DEST
        HTTPD_URL_USER_PASS=$HTTPD_PROTO://user%40host:pass%40host@$HTTPD_DEST
 
-       if test -n "$LIB_HTTPD_DAV" -o -n "$LIB_HTTPD_SVN"
+       if test -n "$LIB_HTTPD_DAV" || test -n "$LIB_HTTPD_SVN"
        then
                HTTPD_PARA="$HTTPD_PARA -DDAV"
 
index eafc9d2d90ff7646062edd9a376839e469334760..a77b8e546926308fbe348bf01d625bad4996a095 100755 (executable)
@@ -19,6 +19,10 @@ case "$PATH_INFO" in
        printf "text/plain; charset=utf-16"
        charset=utf-16
        ;;
+*odd-spacing*)
+       printf "text/plain; foo=bar ;charset=utf-16; other=nonsense"
+       charset=utf-16
+       ;;
 esac
 printf "\n"
 
index 685d46f8b75ae105d41e1b462c69f980fe1f61a8..f8ed8573b728e82f7f4afaee677758b736048ebe 100755 (executable)
@@ -8,6 +8,9 @@ test_perf_large_repo
 # note that we do everything through config,
 # since we want to be able to compare bitmap-aware
 # git versus non-bitmap git
+#
+# We intentionally use the deprecated pack.writebitmaps
+# config so that we can test against older versions of git.
 test_expect_success 'setup bitmap config' '
        git config pack.writebitmaps true &&
        git config pack.writebitmaphashcache true
index 2f3020342a75f0d382af88e6ad35691ad0f183d5..e62c0ffbc22cffffd9c29254a96222bfb5b85633 100755 (executable)
@@ -56,7 +56,7 @@ test_expect_success 'plain through aliased command, outside any git repo' '
        check_config plain-aliased/.git false unset
 '
 
-test_expect_failure 'plain nested through aliased command' '
+test_expect_success 'plain nested through aliased command' '
        (
                git init plain-ancestor-aliased &&
                cd plain-ancestor-aliased &&
@@ -68,7 +68,7 @@ test_expect_failure 'plain nested through aliased command' '
        check_config plain-ancestor-aliased/plain-nested/.git false unset
 '
 
-test_expect_failure 'plain nested in bare through aliased command' '
+test_expect_success 'plain nested in bare through aliased command' '
        (
                git init --bare bare-ancestor-aliased.git &&
                cd bare-ancestor-aliased.git &&
index 5ef5ad3db4f6c307e6bcf71f57dcdc4deaafc082..39e55a13c885399150094f9a2774f85e0acd63a6 100755 (executable)
@@ -816,12 +816,14 @@ test_expect_success NOT_MINGW,NOT_CYGWIN 'correct handling of backslashes' '
        >"whitespace/trailing 5 \\ \\ " &&
        >"whitespace/trailing 6 \\a\\" &&
        >whitespace/untracked &&
-       echo "whitespace/trailing 1 \\    " >ignore  &&
-       echo "whitespace/trailing 2 \\\\\\\\\\\\\\\\" >>ignore &&
-       echo "whitespace/trailing 3 \\\\\\\\\\\\\\\\ " >>ignore &&
-       echo "whitespace/trailing 4   \\\\\\\\\\\\    " >>ignore &&
-       echo "whitespace/trailing 5 \\\\\\\\ \\\\\\\\\\\\   " >>ignore &&
-       echo "whitespace/trailing 6 \\\\\\\\a\\\\\\\\" >>ignore &&
+       sed -e "s/Z$//" >ignore <<-\EOF &&
+       whitespace/trailing 1 \    Z
+       whitespace/trailing 2 \\\\Z
+       whitespace/trailing 3 \\\\ Z
+       whitespace/trailing 4   \\\    Z
+       whitespace/trailing 5 \\ \\\   Z
+       whitespace/trailing 6 \\a\\Z
+       EOF
        echo whitespace/untracked >expect &&
        >err.expect &&
        git ls-files -o -X ignore whitespace >actual 2>err &&
index b92e6cb0469ebb2e328c490cba9b8aaa7c1dbb84..f890c54d137aab021e6d6a61c5741af872555c1f 100755 (executable)
@@ -190,8 +190,6 @@ test_expect_success 'required filter clean failure' '
        test_must_fail git add test.fc
 '
 
-test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
-
 test_expect_success EXPENSIVE 'filter large file' '
        git config filter.largefile.smudge cat &&
        git config filter.largefile.clean cat &&
index b0e5694ebd07b59e80823cd87825cc9ec8187c21..28102de1a0f987b351a423516d394180175a1f13 100755 (executable)
@@ -36,7 +36,7 @@ test_expect_success 'default settings cause no changes' '
        onediff=$(git diff one) &&
        twodiff=$(git diff two) &&
        threediff=$(git diff three) &&
-       test -z "$onediff" -a -z "$twodiff" -a -z "$threediff"
+       test -z "$onediff" && test -z "$twodiff" && test -z "$threediff"
 '
 
 test_expect_success 'crlf=true causes a CRLF file to be normalized' '
@@ -111,7 +111,7 @@ test_expect_success 'autocrlf=true does not normalize CRLF files' '
        onediff=$(git diff one) &&
        twodiff=$(git diff two) &&
        threediff=$(git diff three) &&
-       test -z "$onediff" -a -z "$twodiff" -a -z "$threediff"
+       test -z "$onediff" && test -z "$twodiff" && test -z "$threediff"
 '
 
 test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' '
@@ -126,7 +126,7 @@ test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' '
        onediff=$(git diff one) &&
        twodiff=$(git diff two) &&
        threediff=$(git diff three) &&
-       test -z "$onediff" -a -n "$twodiff" -a -z "$threediff"
+       test -z "$onediff" && test -n "$twodiff" && test -z "$threediff"
 '
 
 test_expect_success 'text=auto, autocrlf=true does not normalize binary files' '
index e1126aa7cc05ff61ddf087fe13880da7f48219a6..4807b0f015d4b87aa762c0f7585d863a1dc34514 100755 (executable)
@@ -36,7 +36,7 @@ test_expect_success 'eol=lf puts LFs in normalized file' '
        ! has_cr two &&
        onediff=$(git diff one) &&
        twodiff=$(git diff two) &&
-       test -z "$onediff" -a -z "$twodiff"
+       test -z "$onediff" && test -z "$twodiff"
 '
 
 test_expect_success 'eol=crlf puts CRLFs in normalized file' '
@@ -49,7 +49,7 @@ test_expect_success 'eol=crlf puts CRLFs in normalized file' '
        ! has_cr two &&
        onediff=$(git diff one) &&
        twodiff=$(git diff two) &&
-       test -z "$onediff" -a -z "$twodiff"
+       test -z "$onediff" && test -z "$twodiff"
 '
 
 test_expect_success 'autocrlf=true overrides eol=lf' '
@@ -63,7 +63,7 @@ test_expect_success 'autocrlf=true overrides eol=lf' '
        has_cr two &&
        onediff=$(git diff one) &&
        twodiff=$(git diff two) &&
-       test -z "$onediff" -a -z "$twodiff"
+       test -z "$onediff" && test -z "$twodiff"
 '
 
 test_expect_success 'autocrlf=true overrides unset eol' '
@@ -77,7 +77,7 @@ test_expect_success 'autocrlf=true overrides unset eol' '
        has_cr two &&
        onediff=$(git diff one) &&
        twodiff=$(git diff two) &&
-       test -z "$onediff" -a -z "$twodiff"
+       test -z "$onediff" && test -z "$twodiff"
 '
 
 test_done
index 1a5a5f39fd94f9eb98824b3d84983782b9ff71bb..9aeb352b3dba3fd7e46a5a0732425cd2686fc9f3 100755 (executable)
@@ -64,6 +64,7 @@ valid_ref "$(printf 'heads/fu\303\237')"
 invalid_ref 'heads/*foo/bar' --refspec-pattern
 invalid_ref 'heads/foo*/bar' --refspec-pattern
 invalid_ref 'heads/f*o/bar' --refspec-pattern
+invalid_ref 'heads/foo*//bar' --refspec-pattern
 
 ref='foo'
 invalid_ref "$ref"
@@ -128,6 +129,20 @@ valid_ref NOT_MINGW "$ref" '--allow-onelevel --normalize'
 invalid_ref NOT_MINGW "$ref" '--refspec-pattern --normalize'
 valid_ref NOT_MINGW "$ref" '--refspec-pattern --allow-onelevel --normalize'
 
+
+valid_ref 'refs/heads/a-very-long-refname'
+invalid_ref 'refs/heads/.a-very-long-refname'
+invalid_ref 'refs/heads/abcdefgh0123..'
+invalid_ref 'refs/heads/abcdefgh01234..'
+invalid_ref 'refs/heads/abcdefgh012345..'
+invalid_ref 'refs/heads/abcdefgh0123456..'
+invalid_ref 'refs/heads/abcdefgh01234567..'
+valid_ref 'refs/heads/abcdefgh0123.a'
+valid_ref 'refs/heads/abcdefgh01234.a'
+valid_ref 'refs/heads/abcdefgh012345.a'
+valid_ref 'refs/heads/abcdefgh0123456.a'
+valid_ref 'refs/heads/abcdefgh01234567.a'
+
 test_expect_success "check-ref-format --branch @{-1}" '
        T=$(git write-tree) &&
        sha1=$(echo A | git commit-tree $T) &&
index e35d7811acc60415e38e58866b5488938d0372a4..8d44e04354f05856465904700ff0374dae74ba59 100755 (executable)
@@ -7,9 +7,7 @@ test_description='Test commit notes index (expensive!)'
 
 . ./test-lib.sh
 
-test_set_prereq NOT_EXPENSIVE
 test -n "$GIT_NOTES_TIMING_TESTS" && test_set_prereq EXPENSIVE
-test -x /usr/bin/time && test_set_prereq USR_BIN_TIME
 
 create_repo () {
        number_of_commits=$1
@@ -17,43 +15,43 @@ create_repo () {
        test -d .git || {
        git init &&
        (
-               while [ $nr -lt $number_of_commits ]; do
+               while test $nr -lt $number_of_commits
+               do
                        nr=$(($nr+1))
                        mark=$(($nr+$nr))
                        notemark=$(($mark+1))
                        test_tick &&
-                       cat <<INPUT_END &&
-commit refs/heads/master
-mark :$mark
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-commit #$nr
-COMMIT
-
-M 644 inline file
-data <<EOF
-file in commit #$nr
-EOF
-
-blob
-mark :$notemark
-data <<EOF
-note for commit #$nr
-EOF
-
-INPUT_END
-
-                       echo "N :$notemark :$mark" >> note_commit
+                       cat <<-INPUT_END &&
+                       commit refs/heads/master
+                       mark :$mark
+                       committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+                       data <<COMMIT
+                       commit #$nr
+                       COMMIT
+
+                       M 644 inline file
+                       data <<EOF
+                       file in commit #$nr
+                       EOF
+
+                       blob
+                       mark :$notemark
+                       data <<EOF
+                       note for commit #$nr
+                       EOF
+
+                       INPUT_END
+                       echo "N :$notemark :$mark" >>note_commit
                done &&
                test_tick &&
-               cat <<INPUT_END &&
-commit refs/notes/commits
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-notes
-COMMIT
+               cat <<-INPUT_END &&
+               commit refs/notes/commits
+               committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+               data <<COMMIT
+               notes
+               COMMIT
 
-INPUT_END
+               INPUT_END
 
                cat note_commit
        ) |
@@ -65,62 +63,74 @@ INPUT_END
 test_notes () {
        count=$1 &&
        git config core.notesRef refs/notes/commits &&
-       git log | grep "^    " > output &&
+       git log | grep "^    " >output &&
        i=$count &&
-       while [ $i -gt 0 ]; do
+       while test $i -gt 0
+       do
                echo "    commit #$i" &&
                echo "    note for commit #$i" &&
-               i=$(($i-1));
-       done > expect &&
+               i=$(($i-1))
+       done >expect &&
        test_cmp expect output
 }
 
-cat > time_notes << \EOF
+write_script time_notes <<\EOF
        mode=$1
        i=1
-       while [ $i -lt $2 ]; do
+       while test $i -lt $2
+       do
                case $1 in
                no-notes)
-                       GIT_NOTES_REF=non-existing; export GIT_NOTES_REF
-               ;;
+                       GIT_NOTES_REF=non-existing
+                       export GIT_NOTES_REF
+                       ;;
                notes)
                        unset GIT_NOTES_REF
-               ;;
+                       ;;
                esac
-               git log >/dev/null
+               git log
                i=$(($i+1))
-       done
+       done >/dev/null
 EOF
 
 time_notes () {
        for mode in no-notes notes
        do
                echo $mode
-               /usr/bin/time "$SHELL_PATH" ../time_notes $mode $1
+               /usr/bin/time ../time_notes $mode $1
        done
 }
 
 do_tests () {
-       pr=$1
-       count=$2
-
-       test_expect_success $pr 'setup / mkdir' '
-               mkdir $count &&
-               cd $count
+       count=$1 pr=${2-}
+
+       test_expect_success $pr "setup $count" '
+               mkdir "$count" &&
+               (
+                       cd "$count" &&
+                       create_repo "$count"
+               )
        '
 
-       test_expect_success $pr "setup $count" "create_repo $count"
-
-       test_expect_success $pr 'notes work' "test_notes $count"
-
-       test_expect_success USR_BIN_TIME,$pr 'notes timing with /usr/bin/time' "time_notes 100"
+       test_expect_success $pr 'notes work' '
+               (
+                       cd "$count" &&
+                       test_notes "$count"
+               )
+       '
 
-       test_expect_success $pr 'teardown / cd ..' 'cd ..'
+       test_expect_success "USR_BIN_TIME${pr:+,$pr}" 'notes timing with /usr/bin/time' '
+               (
+                       cd "$count" &&
+                       time_notes 100
+               )
+       '
 }
 
-do_tests NOT_EXPENSIVE 10
-for count in 100 1000 10000; do
-       do_tests EXPENSIVE $count
+do_tests 10
+for count in 100 1000 10000
+do
+       do_tests "$count" EXPENSIVE
 done
 
 test_done
index be8c1d5ef9fd650c128a9fe7126cbcd8db6c5a95..5a27ec9b5eb7c37145a098d878432948233ba756 100755 (executable)
@@ -33,6 +33,7 @@ test_expect_success setup '
        tr "[a-z]" "[A-Z]" <original >newfile &&
        git add newfile &&
        git commit -a -m"side edits further." &&
+       git branch second-side &&
 
        tr "[a-m]" "[A-M]" <original >newfile &&
        rm -f original &&
@@ -41,6 +42,7 @@ test_expect_success setup '
        git branch test-rebase side &&
        git branch test-rebase-pick side &&
        git branch test-reference-pick side &&
+       git branch test-conflicts side &&
        git checkout -b test-merge side
 '
 
@@ -138,4 +140,17 @@ test_expect_success 'rebase -s funny -Xopt' '
        test -f funny.was.run
 '
 
+test_expect_success 'rebase --skip works with two conflicts in a row' '
+       git checkout second-side  &&
+       tr "[A-Z]" "[a-z]" <newfile >tmp &&
+       mv tmp newfile &&
+       git commit -a -m"edit conflicting with side" &&
+       tr "[d-f]" "[D-F]" <newfile >tmp &&
+       mv tmp newfile &&
+       git commit -a -m"another edit conflicting with side" &&
+       test_must_fail git rebase --merge test-conflicts &&
+       test_must_fail git rebase --skip &&
+       git rebase --skip
+'
+
 test_done
index e70ac10a0cdbcd112b7b3c3e74aa89b09d46d1df..9292b499f39925b6832bccd826fb43a8818f155a 100755 (executable)
@@ -4,12 +4,9 @@ test_description='git rebase - test patch id computation'
 
 . ./test-lib.sh
 
-test_set_prereq NOT_EXPENSIVE
 test -n "$GIT_PATCHID_TIMING_TESTS" && test_set_prereq EXPENSIVE
-test -x /usr/bin/time && test_set_prereq USR_BIN_TIME
 
-count()
-{
+count () {
        i=0
        while test $i -lt $1
        do
@@ -18,8 +15,7 @@ count()
        done
 }
 
-scramble()
-{
+scramble () {
        i=0
        while read x
        do
@@ -28,12 +24,11 @@ scramble()
                        echo "$x"
                fi
                i=$((($i+1) % 10))
-       done < "$1" > "$1.new"
+       done <"$1" >"$1.new"
        mv -f "$1.new" "$1"
 }
 
-run()
-{
+run () {
        echo \$ "$@"
        /usr/bin/time "$@" >/dev/null
 }
@@ -43,10 +38,8 @@ test_expect_success 'setup' '
        git tag root
 '
 
-do_tests()
-{
-       pr=$1
-       nlines=$2
+do_tests () {
+       nlines=$1 pr=${2-}
 
        test_expect_success $pr "setup: $nlines lines" "
                rm -f .gitattributes &&
@@ -103,7 +96,7 @@ do_tests()
        "
 }
 
-do_tests NOT_EXPENSIVE 500
-do_tests EXPENSIVE 50000
+do_tests 500
+do_tests 50000 EXPENSIVE
 
 test_done
index 49e2d6c34983c7e4620739a52ecc03cf158efe3a..fae305979a88614bdf33963936d3fce32df83b8c 100755 (executable)
@@ -52,6 +52,6 @@ EOF
 
 test_expect_success 'apply copy' \
     'git apply --index --stat --summary --apply test-patch &&
-     test "$(cat bar)" = "This is bar" -a "$(cat foo)" = "This is foo"'
+     test "$(cat bar)" = "This is bar" && test "$(cat foo)" = "This is foo"'
 
 test_done
index bad84a36e81dbebbad89bf66cb1411ebf27fe66a..899c1c5bbcb2e994a1462eb8048344b68d23767d 100755 (executable)
@@ -72,7 +72,7 @@ check_tar() {
                        for header in *.paxheader
                        do
                                data=${header%.paxheader}.data &&
-                               if test -h $data -o -e $data
+                               if test -h $data || test -e $data
                                then
                                        path=$(get_pax_header $header path) &&
                                        if test -n "$path"
index f4f02ba918535d5c40a30585a54469bc12ab96d3..0580258c91a07aabe2773cce04df47d3c183b425 100755 (executable)
@@ -18,7 +18,7 @@ test_expect_success 'setup repo with moderate-sized history' '
        git checkout master &&
        blob=$(echo tagged-blob | git hash-object -w --stdin) &&
        git tag tagged-blob $blob &&
-       git config pack.writebitmaps true &&
+       git config repack.writebitmaps true &&
        git config pack.writebitmaphashcache true
 '
 
index 1753ef2b91e3e5846f12fc16e1209b1895210f3b..fc898c9eac704c934cfbef47fc1463f27dd50c6f 100755 (executable)
@@ -39,7 +39,7 @@ test_expect_success 'post-checkout receives the right arguments with HEAD unchan
        old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
        new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
        flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
-       test $old = $new -a $flag = 1
+       test $old = $new && test $flag = 1
 '
 
 test_expect_success 'post-checkout runs as expected ' '
@@ -52,7 +52,7 @@ test_expect_success 'post-checkout args are correct with git checkout -b ' '
        old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
        new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
        flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
-       test $old = $new -a $flag = 1
+       test $old = $new && test $flag = 1
 '
 
 test_expect_success 'post-checkout receives the right args with HEAD changed ' '
@@ -60,7 +60,7 @@ test_expect_success 'post-checkout receives the right args with HEAD changed ' '
        old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
        new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
        flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
-       test $old != $new -a $flag = 1
+       test $old != $new && test $flag = 1
 '
 
 test_expect_success 'post-checkout receives the right args when not switching branches ' '
@@ -68,7 +68,7 @@ test_expect_success 'post-checkout receives the right args when not switching br
        old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
        new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
        flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
-       test $old = $new -a $flag = 0
+       test $old = $new && test $flag = 0
 '
 
 if test "$(git config --bool core.filemode)" = true; then
index 29d59ef9fa2bf2bffb0075f07e03103387ab718e..d78f3201f423504bf5d53029492cc1bc056aab06 100755 (executable)
@@ -447,6 +447,43 @@ test_expect_success 'explicit pull should update tracking' '
        )
 '
 
+test_expect_success 'explicit --refmap is allowed only with command-line refspec' '
+       cd "$D" &&
+       (
+               cd three &&
+               test_must_fail git fetch --refmap="*:refs/remotes/none/*"
+       )
+'
+
+test_expect_success 'explicit --refmap option overrides remote.*.fetch' '
+       cd "$D" &&
+       git branch -f side &&
+       (
+               cd three &&
+               git update-ref refs/remotes/origin/master base-origin-master &&
+               o=$(git rev-parse --verify refs/remotes/origin/master) &&
+               git fetch --refmap="refs/heads/*:refs/remotes/other/*" origin master &&
+               n=$(git rev-parse --verify refs/remotes/origin/master) &&
+               test "$o" = "$n" &&
+               test_must_fail git rev-parse --verify refs/remotes/origin/side &&
+               git rev-parse --verify refs/remotes/other/master
+       )
+'
+
+test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '
+       cd "$D" &&
+       git branch -f side &&
+       (
+               cd three &&
+               git update-ref refs/remotes/origin/master base-origin-master &&
+               o=$(git rev-parse --verify refs/remotes/origin/master) &&
+               git fetch --refmap="" origin master &&
+               n=$(git rev-parse --verify refs/remotes/origin/master) &&
+               test "$o" = "$n" &&
+               test_must_fail git rev-parse --verify refs/remotes/origin/side
+       )
+'
+
 test_expect_success 'configured fetch updates tracking' '
 
        cd "$D" &&
index 01b8aae2ed12eab92ecbfb562cb616e0cfc47202..ac71418a1b26bc17a1252d6831869b96a8d8c176 100755 (executable)
@@ -191,5 +191,10 @@ test_expect_success 'http error messages are reencoded' '
        grep "this is the error message" stderr
 '
 
+test_expect_success 'reencoding is robust to whitespace oddities' '
+       test_must_fail git clone "$HTTPD_URL/error/odd-spacing" 2>stderr &&
+       grep "this is the error message" stderr
+'
+
 stop_httpd
 test_done
index e07eaf35f118893da9240f12d115da1affd5eb05..6cbc12d9a7ad059f77967c0bdb702d8a5ec75bb9 100755 (executable)
@@ -213,8 +213,6 @@ test_expect_success 'cookies stored in http.cookiefile when http.savecookies set
        test_cmp expect_cookies.txt cookies_tail.txt
 '
 
-test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
-
 test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
        (
        cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
@@ -240,8 +238,7 @@ test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
 '
 
 test_expect_success EXPENSIVE 'clone the 50,000 tag repo to check OS command line overflow' '
-       git clone $HTTPD_URL/smart/repo.git too-many-refs 2>err &&
-       test_line_count = 0 err &&
+       git clone $HTTPD_URL/smart/repo.git too-many-refs &&
        (
                cd too-many-refs &&
                test $(git for-each-ref refs/tags | wc -l) = 50000
index 74de814aec1465848ba316e867106a18635139f6..04118ad75be8462fa2ee1e5e870feb0a44ac0482 100755 (executable)
@@ -426,10 +426,10 @@ test_expect_success SANITY 'removal failure' '
 
        mkdir foo &&
        touch foo/bar &&
+       test_when_finished "chmod 755 foo" &&
        (exec <foo/bar &&
         chmod 0 foo &&
-        test_must_fail git clean -f -d &&
-        chmod 755 foo)
+        test_must_fail git clean -f -d)
 '
 
 test_expect_success 'nested git work tree' '
index 284018e3cdb31e7db179a93f7196fda47578c43c..021c5479bdf4665e815590dc05a0831e7d92c53c 100755 (executable)
@@ -21,7 +21,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
        objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |
                sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") &&
        mv pack-* .git/objects/pack/ &&
-       git repack --no-pack-kept-objects -A -d -l &&
+       git repack -A -d -l &&
        git prune-packed &&
        for p in .git/objects/pack/*.idx; do
                idx=$(basename $p)
@@ -35,9 +35,25 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
        test -z "$found_duplicate_object"
 '
 
-test_expect_success 'writing bitmaps can duplicate .keep objects' '
+test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '
        # build on $objsha1, $packsha1, and .keep state from previous
-       git repack -Adl &&
+       git repack -Adbl &&
+       test_when_finished "found_duplicate_object=" &&
+       for p in .git/objects/pack/*.idx; do
+               idx=$(basename $p)
+               test "pack-$packsha1.idx" = "$idx" && continue
+               if git verify-pack -v $p | egrep "^$objsha1"; then
+                       found_duplicate_object=1
+                       echo "DUPLICATE OBJECT FOUND"
+                       break
+               fi
+       done &&
+       test "$found_duplicate_object" = 1
+'
+
+test_expect_success 'writing bitmaps via config can duplicate .keep objects' '
+       # build on $objsha1, $packsha1, and .keep state from previous
+       git -c repack.writebitmaps=true repack -Adl &&
        test_when_finished "found_duplicate_object=" &&
        for p in .git/objects/pack/*.idx; do
                idx=$(basename $p)
index 1ecdacb6fd0ceb7e43e6ec3bad018e7b6dc8100b..19a3ced600a20d805d430533b275a8fa4269b835 100755 (executable)
@@ -1334,6 +1334,51 @@ test_expect_success $PREREQ '--force sends cover letter template anyway' '
        test -n "$(ls msgtxt*)"
 '
 
+test_cover_addresses () {
+       header="$1"
+       shift
+       clean_fake_sendmail &&
+       rm -fr outdir &&
+       git format-patch --cover-letter -2 -o outdir &&
+       cover=`echo outdir/0000-*.patch` &&
+       mv $cover cover-to-edit.patch &&
+       perl -pe "s/^From:/$header: extra\@address.com\nFrom:/" cover-to-edit.patch >"$cover" &&
+       git send-email \
+         --force \
+         --from="Example <nobody@example.com>" \
+         --no-to --no-cc \
+         "$@" \
+         --smtp-server="$(pwd)/fake.sendmail" \
+         outdir/0000-*.patch \
+         outdir/0001-*.patch \
+         outdir/0002-*.patch \
+         2>errors >out &&
+       grep "^$header: extra@address.com" msgtxt1 >to1 &&
+       grep "^$header: extra@address.com" msgtxt2 >to2 &&
+       grep "^$header: extra@address.com" msgtxt3 >to3 &&
+       test_line_count = 1 to1 &&
+       test_line_count = 1 to2 &&
+       test_line_count = 1 to3
+}
+
+test_expect_success $PREREQ 'to-cover adds To to all mail' '
+       test_cover_addresses "To" --to-cover
+'
+
+test_expect_success $PREREQ 'cc-cover adds Cc to all mail' '
+       test_cover_addresses "Cc" --cc-cover
+'
+
+test_expect_success $PREREQ 'tocover adds To to all mail' '
+       test_config sendemail.tocover true &&
+       test_cover_addresses "To"
+'
+
+test_expect_success $PREREQ 'cccover adds Cc to all mail' '
+       test_config sendemail.cccover true &&
+       test_cover_addresses "Cc"
+'
+
 test_expect_success $PREREQ 'sendemail.aliasfiletype=mailrc' '
        clean_fake_sendmail &&
        echo "alias sbd  somebody@example.org" >.mailrc &&
index be802e0e16f165f92d3526572a483d1287b19ef9..1fc1f5f2afcf205f10d04cd1deaf5708f727332e 100755 (executable)
@@ -177,7 +177,7 @@ test_expect_success 'detect copies' '
                level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
                test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
                src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
-               test "$src" = file10 -o "$src" = file11 &&
+               test "$src" = file10 || test "$src" = file11 &&
                git config git-p4.detectCopies $(($level + 2)) &&
                git p4 submit &&
                p4 filelog //depot/file12 &&
@@ -191,7 +191,7 @@ test_expect_success 'detect copies' '
                level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
                test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
                src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
-               test "$src" = file10 -o "$src" = file11 -o "$src" = file12 &&
+               test "$src" = file10 || test "$src" = file11 || test "$src" = file12 &&
                git config git-p4.detectCopies $(($level - 2)) &&
                git p4 submit &&
                p4 filelog //depot/file13 &&
index 2d4beb5e50c257fed2f4b6475cb5834425b5a64f..1d1c1063a38866f1792f9b451a4942d06c91edb4 100755 (executable)
@@ -550,6 +550,33 @@ test_expect_success 'complete files' '
        test_completion "git add mom" "momified"
 '
 
+test_expect_success "completion uses <cmd> completion for alias: !sh -c 'git <cmd> ...'" '
+       test_config alias.co "!sh -c '"'"'git checkout ...'"'"'" &&
+       test_completion "git co m" <<-\EOF
+       master Z
+       mybranch Z
+       mytag Z
+       EOF
+'
+
+test_expect_success 'completion uses <cmd> completion for alias: !f () { VAR=val git <cmd> ... }' '
+       test_config alias.co "!f () { VAR=val git checkout ... ; } f" &&
+       test_completion "git co m" <<-\EOF
+       master Z
+       mybranch Z
+       mytag Z
+       EOF
+'
+
+test_expect_success 'completion used <cmd> completion for alias: !f() { : git <cmd> ; ... }' '
+       test_config alias.co "!f() { : git checkout ; if ... } f" &&
+       test_completion "git co m" <<-\EOF
+       master Z
+       mybranch Z
+       mytag Z
+       EOF
+'
+
 test_expect_failure 'complete with tilde expansion' '
        git init tmp && cd tmp &&
        test_when_finished "cd .. && rm -rf tmp" &&
index c617c826db94f2e3c0ed01fe079d3ae14ac3b883..0377d3e2960cc282ce1a2c7cb629245728c82092 100644 (file)
@@ -542,7 +542,7 @@ test_must_fail () {
        if test $exit_code = 0; then
                echo >&2 "test_must_fail: command succeeded: $*"
                return 1
-       elif test $exit_code -gt 129 -a $exit_code -le 192; then
+       elif test $exit_code -gt 129 && test $exit_code -le 192; then
                echo >&2 "test_must_fail: died by signal: $*"
                return 1
        elif test $exit_code = 127; then
@@ -569,7 +569,7 @@ test_must_fail () {
 test_might_fail () {
        "$@"
        exit_code=$?
-       if test $exit_code -gt 129 -a $exit_code -le 192; then
+       if test $exit_code -gt 129 && test $exit_code -le 192; then
                echo >&2 "test_might_fail: died by signal: $*"
                return 1
        elif test $exit_code = 127; then
index 81394c8c7c859b1a46a765c05020e74bf0e2808e..a4795373a6a2e1f247b3cef9880f2a82309b3594 100644 (file)
@@ -976,6 +976,14 @@ test_lazy_prereq AUTOIDENT '
        git var GIT_AUTHOR_IDENT
 '
 
+test_lazy_prereq EXPENSIVE '
+       test -n "$GIT_TEST_LONG"
+'
+
+test_lazy_prereq USR_BIN_TIME '
+       test -x /usr/bin/time
+'
+
 # When the tests are run as root, permission tests will report that
 # things are writable when they shouldn't be.
 test -w / || test_set_prereq SANITY
index 0a6724fcc45eed89d612b0e641fd3fe6d4231fcb..332ab1a3b3ee2a2bfa7b25552f9b67f3ca51b2a1 100644 (file)
        Memcheck:Addr4
        fun:copy_ref
 }
+{
+       ignore-sse-check_refname_format
+       Memcheck:Addr8
+       fun:check_refname_format
+       fun:cmd_check_ref_format
+       fun:handle_builtin
+       fun:main
+}
index 4dc86c7fe5f66b858b6bd7834a76b1dbbb63a339..5dd9a718047bc14e9ae840a46d1f71cb435fd6d7 100644 (file)
@@ -144,16 +144,6 @@ struct tree_desc_x {
        struct tree_desc_skip *skip;
 };
 
-static int name_compare(const char *a, int a_len,
-                       const char *b, int b_len)
-{
-       int len = (a_len < b_len) ? a_len : b_len;
-       int cmp = memcmp(a, b, len);
-       if (cmp)
-               return cmp;
-       return (a_len - b_len);
-}
-
 static int check_entry_match(const char *a, int a_len, const char *b, int b_len)
 {
        /*
index 4db78038e43adac119d6b58c55e8cf7a8baa5308..47cdd2369d1919b7b7b267c622ad31e2ad6f24c0 100644 (file)
@@ -6,7 +6,7 @@ static const struct interval zero_width[] = {
 { 0x05C1, 0x05C2 },
 { 0x05C4, 0x05C5 },
 { 0x05C7, 0x05C7 },
-{ 0x0600, 0x0604 },
+{ 0x0600, 0x0605 },
 { 0x0610, 0x061A },
 { 0x061C, 0x061C },
 { 0x064B, 0x065F },
@@ -25,8 +25,7 @@ static const struct interval zero_width[] = {
 { 0x0825, 0x0827 },
 { 0x0829, 0x082D },
 { 0x0859, 0x085B },
-{ 0x08E4, 0x08FE },
-{ 0x0900, 0x0902 },
+{ 0x08E4, 0x0902 },
 { 0x093A, 0x093A },
 { 0x093C, 0x093C },
 { 0x0941, 0x0948 },
@@ -62,16 +61,19 @@ static const struct interval zero_width[] = {
 { 0x0B82, 0x0B82 },
 { 0x0BC0, 0x0BC0 },
 { 0x0BCD, 0x0BCD },
+{ 0x0C00, 0x0C00 },
 { 0x0C3E, 0x0C40 },
 { 0x0C46, 0x0C48 },
 { 0x0C4A, 0x0C4D },
 { 0x0C55, 0x0C56 },
 { 0x0C62, 0x0C63 },
+{ 0x0C81, 0x0C81 },
 { 0x0CBC, 0x0CBC },
 { 0x0CBF, 0x0CBF },
 { 0x0CC6, 0x0CC6 },
 { 0x0CCC, 0x0CCD },
 { 0x0CE2, 0x0CE3 },
+{ 0x0D01, 0x0D01 },
 { 0x0D41, 0x0D44 },
 { 0x0D4D, 0x0D4D },
 { 0x0D62, 0x0D63 },
@@ -132,6 +134,7 @@ static const struct interval zero_width[] = {
 { 0x1A65, 0x1A6C },
 { 0x1A73, 0x1A7C },
 { 0x1A7F, 0x1A7F },
+{ 0x1AB0, 0x1ABE },
 { 0x1B00, 0x1B03 },
 { 0x1B34, 0x1B34 },
 { 0x1B36, 0x1B3A },
@@ -141,7 +144,7 @@ static const struct interval zero_width[] = {
 { 0x1B80, 0x1B81 },
 { 0x1BA2, 0x1BA5 },
 { 0x1BA8, 0x1BA9 },
-{ 0x1BAB, 0x1BAB },
+{ 0x1BAB, 0x1BAD },
 { 0x1BE6, 0x1BE6 },
 { 0x1BE8, 0x1BE9 },
 { 0x1BED, 0x1BED },
@@ -153,7 +156,8 @@ static const struct interval zero_width[] = {
 { 0x1CE2, 0x1CE8 },
 { 0x1CED, 0x1CED },
 { 0x1CF4, 0x1CF4 },
-{ 0x1DC0, 0x1DE6 },
+{ 0x1CF8, 0x1CF9 },
+{ 0x1DC0, 0x1DF5 },
 { 0x1DFC, 0x1DFF },
 { 0x200B, 0x200F },
 { 0x202A, 0x202E },
@@ -181,11 +185,13 @@ static const struct interval zero_width[] = {
 { 0xA9B3, 0xA9B3 },
 { 0xA9B6, 0xA9B9 },
 { 0xA9BC, 0xA9BC },
+{ 0xA9E5, 0xA9E5 },
 { 0xAA29, 0xAA2E },
 { 0xAA31, 0xAA32 },
 { 0xAA35, 0xAA36 },
 { 0xAA43, 0xAA43 },
 { 0xAA4C, 0xAA4C },
+{ 0xAA7C, 0xAA7C },
 { 0xAAB0, 0xAAB0 },
 { 0xAAB2, 0xAAB4 },
 { 0xAAB7, 0xAAB8 },
@@ -198,36 +204,65 @@ static const struct interval zero_width[] = {
 { 0xABED, 0xABED },
 { 0xFB1E, 0xFB1E },
 { 0xFE00, 0xFE0F },
-{ 0xFE20, 0xFE26 },
+{ 0xFE20, 0xFE2D },
 { 0xFEFF, 0xFEFF },
 { 0xFFF9, 0xFFFB },
 { 0x101FD, 0x101FD },
+{ 0x102E0, 0x102E0 },
+{ 0x10376, 0x1037A },
 { 0x10A01, 0x10A03 },
 { 0x10A05, 0x10A06 },
 { 0x10A0C, 0x10A0F },
 { 0x10A38, 0x10A3A },
 { 0x10A3F, 0x10A3F },
+{ 0x10AE5, 0x10AE6 },
 { 0x11001, 0x11001 },
 { 0x11038, 0x11046 },
-{ 0x11080, 0x11081 },
+{ 0x1107F, 0x11081 },
 { 0x110B3, 0x110B6 },
 { 0x110B9, 0x110BA },
 { 0x110BD, 0x110BD },
 { 0x11100, 0x11102 },
 { 0x11127, 0x1112B },
 { 0x1112D, 0x11134 },
+{ 0x11173, 0x11173 },
 { 0x11180, 0x11181 },
 { 0x111B6, 0x111BE },
+{ 0x1122F, 0x11231 },
+{ 0x11234, 0x11234 },
+{ 0x11236, 0x11237 },
+{ 0x112DF, 0x112DF },
+{ 0x112E3, 0x112EA },
+{ 0x11301, 0x11301 },
+{ 0x1133C, 0x1133C },
+{ 0x11340, 0x11340 },
+{ 0x11366, 0x1136C },
+{ 0x11370, 0x11374 },
+{ 0x114B3, 0x114B8 },
+{ 0x114BA, 0x114BA },
+{ 0x114BF, 0x114C0 },
+{ 0x114C2, 0x114C3 },
+{ 0x115B2, 0x115B5 },
+{ 0x115BC, 0x115BD },
+{ 0x115BF, 0x115C0 },
+{ 0x11633, 0x1163A },
+{ 0x1163D, 0x1163D },
+{ 0x1163F, 0x11640 },
 { 0x116AB, 0x116AB },
 { 0x116AD, 0x116AD },
 { 0x116B0, 0x116B5 },
 { 0x116B7, 0x116B7 },
+{ 0x16AF0, 0x16AF4 },
+{ 0x16B30, 0x16B36 },
 { 0x16F8F, 0x16F92 },
+{ 0x1BC9D, 0x1BC9E },
+{ 0x1BCA0, 0x1BCA3 },
 { 0x1D167, 0x1D169 },
 { 0x1D173, 0x1D182 },
 { 0x1D185, 0x1D18B },
 { 0x1D1AA, 0x1D1AD },
 { 0x1D242, 0x1D244 },
+{ 0x1E8D0, 0x1E8D6 },
 { 0xE0001, 0xE0001 },
 { 0xE0020, 0xE007F },
 { 0xE0100, 0xE01EF }
index 97fc9954672f2c374541cad827bb5c459abebcdc..e9a05b908589a0fa8c446b1896821b77aa24596c 100644 (file)
@@ -622,17 +622,6 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
        return -1;
 }
 
-/* NEEDSWORK: give this a better name and share with tree-walk.c */
-static int name_compare(const char *a, int a_len,
-                       const char *b, int b_len)
-{
-       int len = (a_len < b_len) ? a_len : b_len;
-       int cmp = memcmp(a, b, len);
-       if (cmp)
-               return cmp;
-       return (a_len - b_len);
-}
-
 /*
  * The tree traversal is looking at name p.  If we have a matching entry,
  * return it.  If name p is a directory in the index, do not return