Merge branch 'jk/incore-lockfile-removal' into next
authorJunio C Hamano <gitster@pobox.com>
Thu, 14 Sep 2017 08:40:35 +0000 (17:40 +0900)
committerJunio C Hamano <gitster@pobox.com>
Thu, 14 Sep 2017 08:40:35 +0000 (17:40 +0900)
The long-standing rule that an in-core lockfile instance, once it
is used, must not be freed, has been lifted and the lockfile and
tempfile APIs have been updated to reduce the chance of programming
errors.

* jk/incore-lockfile-removal:
stop leaking lock structs in some simple cases
ref_lock: stop leaking lock_files
lockfile: update lifetime requirements in documentation
tempfile: auto-allocate tempfiles on heap
tempfile: remove deactivated list entries
tempfile: use list.h for linked list
tempfile: release deactivated strbufs instead of resetting
tempfile: robustify cleanup handler
tempfile: factor out deactivation
tempfile: factor out activation
tempfile: replace die("BUG") with BUG()
tempfile: handle NULL tempfile pointers gracefully
tempfile: prefer is_tempfile_active to bare access
lockfile: do not rollback lock on failed close
tempfile: do not delete tempfile on failed close
always check return value of close_tempfile
verify_signed_buffer: prefer close_tempfile() to close()
setup_temporary_shallow: move tempfile struct into function
setup_temporary_shallow: avoid using inactive tempfile
write_index_as_tree: cleanup tempfile on error

70 files changed:
.tsan-suppressions [new file with mode: 0644]
Documentation/RelNotes/2.14.2.txt
Documentation/RelNotes/2.15.0.txt
Documentation/git-apply.txt
Documentation/git-cvsserver.txt
Documentation/git-diff-index.txt
Documentation/git-merge.txt
Documentation/git-rebase.txt
Documentation/git-rerere.txt
Documentation/git-rm.txt
Documentation/git-svn.txt
Documentation/git-update-index.txt
Documentation/gitcore-tutorial.txt
Documentation/githooks.txt
Documentation/gitrepository-layout.txt
Documentation/gittutorial.txt
Documentation/merge-options.txt
Documentation/rev-list-options.txt
Documentation/technical/api-ref-iteration.txt
Documentation/technical/pack-protocol.txt
Documentation/technical/trivial-merge.txt
Documentation/user-manual.txt
Makefile
apply.c
branch.c
builtin/merge.c
builtin/name-rev.c
builtin/pack-objects.c
color.c
contrib/diff-highlight/Makefile
contrib/examples/git-merge.sh
contrib/examples/git-resolve.sh
contrib/subtree/t/t7900-subtree.sh
convert.c
entry.c
git-gui/po/README
git-merge-octopus.sh
git-p4.py
git-send-email.perl
hash.h
merge-recursive.c
notes-merge.c
notes.c
pathspec.c
pkt-line.c
reachable.c
refs.c
refs.h
refs/files-backend.c
remote.c
revision.c
revision.h
sha1-lookup.h
sha1dc_git.c
sha1dc_git.h
strbuf.h
submodule.c
t/t0027-auto-crlf.sh
t/t1407-worktree-ref-store.sh
t/t3200-branch.sh
t/t3600-rm.sh
t/t3700-add.sh
t/t5304-prune.sh
t/t6040-tracking-info.sh
t/t9001-send-email.sh
templates/hooks--pre-rebase.sample
transport-helper.c
unpack-trees.c
worktree.c
worktree.h
diff --git a/.tsan-suppressions b/.tsan-suppressions
new file mode 100644 (file)
index 0000000..8c85014
--- /dev/null
@@ -0,0 +1,10 @@
+# Suppressions for ThreadSanitizer (tsan).
+#
+# This file is used by setting the environment variable TSAN_OPTIONS to, e.g.,
+# "suppressions=$(pwd)/.tsan-suppressions". Observe that relative paths such as
+# ".tsan-suppressions" might not work.
+
+# A static variable is written to racily, but we always write the same value, so
+# in practice it (hopefully!) doesn't matter.
+race:^want_color$
+race:^transfer_debug$
index 5517afcf5920b8fa023e2ba0babf6c4a1d92509b..bcfe78f59dd0cfb24897d986499aa7c8ada12834 100644 (file)
@@ -32,4 +32,63 @@ Fixes since v2.14.1
    daemon is torn down were flaky.  This was fixed by reacting to
    ECONNRESET and behaving as if we got an EOF.
 
+ * Some versions of GnuPG fail to kill gpg-agent it auto-spawned
+   and such a left-over agent can interfere with a test.  Work it
+   around by attempting to kill one before starting a new test.
+
+ * "git log --tag=no-such-tag" showed log starting from HEAD, which
+   has been fixed---it now shows nothing.
+
+ * The "tag.pager" configuration variable was useless for those who
+   actually create tag objects, as it interfered with the use of an
+   editor.  A new mechanism has been introduced for commands to enable
+   pager depending on what operation is being carried out to fix this,
+   and then "git tag -l" is made to run pager by default.
+
+ * "git push --recurse-submodules $there HEAD:$target" was not
+   propagated down to the submodules, but now it is.
+
+ * Commands like "git rebase" accepted the --rerere-autoupdate option
+   from the command line, but did not always use it.  This has been
+   fixed.
+
+ * "git clone --recurse-submodules --quiet" did not pass the quiet
+   option down to submodules.
+
+ * "git am -s" has been taught that some input may end with a trailer
+   block that is not Signed-off-by: and it should refrain from adding
+   an extra blank line before adding a new sign-off in such a case.
+
+ * "git svn" used with "--localtime" option did not compute the tz
+   offset for the timestamp in question and instead always used the
+   current time, which has been corrected.
+
+ * Memory leaks in a few error codepaths have been plugged.
+
+ * bash 4.4 or newer gave a warning on NUL byte in command
+   substitution done in "git stash"; this has been squelched.
+
+ * "git grep -L" and "git grep --quiet -L" reported different exit
+   codes; this has been corrected.
+
+ * When handshake with a subprocess filter notices that the process
+   asked for an unknown capability, Git did not report what program
+   the offending subprocess was running.  This has been corrected.
+
+ * "git apply" that is used as a better "patch -p1" failed to apply a
+   taken from a file with CRLF line endings to a file with CRLF line
+   endings.  The root cause was because it misused convert_to_git()
+   that tried to do "safe-crlf" processing by looking at the index
+   entry at the same path, which is a nonsense---in that mode, "apply"
+   is not working on the data in (or derived from) the index at all.
+   This has been fixed.
+
+ * Killing "git merge --edit" before the editor returns control left
+   the repository in a state with MERGE_MSG but without MERGE_HEAD,
+   which incorrectly tells the subsequent "git commit" that there was
+   a squash merge in progress.  This has been fixed.
+
+ * "git archive" did not work well with pathspecs and the
+   export-ignore attribute.
+
 Also contains various documentation updates and code clean-ups.
index 4b3fd229e927aa57c166855df43863d1aef13517..31f7b0ed0395fa92e2ba4e854dd3390776a53f9a 100644 (file)
@@ -77,6 +77,9 @@ UI, Workflows & Features
  * "branch --set-upstream" that has been deprecated in Git 1.8 has
    finally been retired.
 
+ * The codepath to call external process filter for smudge/clean
+   operation learned to show the progress meter.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -161,7 +164,6 @@ Fixes since v2.14
  * Some versions of GnuPG fails to kill gpg-agent it auto-spawned
    and such a left-over agent can interfere with a test.  Work it
    around by attempting to kill one before starting a new test.
-   (merge 29ff1f8f74 st/lib-gpg-kill-stray-agent later to maint).
 
  * A recently added test for the "credential-cache" helper revealed
    that EOF detection done around the time the connection to the cache
@@ -170,49 +172,36 @@ Fixes since v2.14
 
  * "git log --tag=no-such-tag" showed log starting from HEAD, which
    has been fixed---it now shows nothing.
-   (merge 5d34d1ac06 jk/rev-list-empty-input later to maint).
 
  * The "tag.pager" configuration variable was useless for those who
    actually create tag objects, as it interfered with the use of an
    editor.  A new mechanism has been introduced for commands to enable
    pager depending on what operation is being carried out to fix this,
    and then "git tag -l" is made to run pager by default.
-   (merge 595d59e2b5 ma/pager-per-subcommand-action later to maint).
 
  * "git push --recurse-submodules $there HEAD:$target" was not
    propagated down to the submodules, but now it is.
-   (merge c7be7201a7 bw/push-options-recursively-to-submodules later to maint).
 
  * Commands like "git rebase" accepted the --rerere-autoupdate option
    from the command line, but did not always use it.  This has been
    fixed.
-   (merge f826fb799e pw/sequence-rerere-autoupdate later to maint).
 
  * "git clone --recurse-submodules --quiet" did not pass the quiet
    option down to submodules.
-   (merge 03c004c581 bw/clone-recursive-quiet later to maint).
 
  * Test portability fix for OBSD.
-   (merge bed67874e2 rs/obsd-getcwd-workaround later to maint).
-   (merge 4c7fda8fc1 rs/t4062-obsd later to maint).
 
  * Portability fix for OBSD.
-   (merge 29c2eda80b rs/in-obsd-basename-dirname-take-const later to maint).
 
  * "git am -s" has been taught that some input may end with a trailer
    block that is not Signed-off-by: and it should refrain from adding
    an extra blank line before adding a new sign-off in such a case.
-   (merge 735285b403 pw/am-signoff later to maint).
 
  * "git svn" used with "--localtime" option did not compute the tz
    offset for the timestamp in question and instead always used the
    current time, which has been corrected.
-   (merge 1adc4b9a58 ur/svn-local-zone later to maint).
 
  * Memory leak in an error codepath has been plugged.
-   (merge 83cd6f9017 rs/fsck-obj-leakfix later to maint).
-   (merge 896dca3ab7 rs/unpack-entry-leakfix later to maint).
-   (merge 149d8cbb2e rs/win32-syslog-leakfix later to maint).
 
  * "git stash -u" used the contents of the committed version of the
    ".gitignore" file to decide which paths are ignored, even when the
@@ -221,16 +210,13 @@ Fixes since v2.14
 
  * bash 4.4 or newer gave a warning on NUL byte in command
    substitution done in "git stash"; this has been squelched.
-   (merge 5fc92f8828 kd/stash-with-bash-4.4 later to maint).
 
  * "git grep -L" and "git grep --quiet -L" reported different exit
    codes; this has been corrected.
-   (merge e1f68c66d5 as/grep-quiet-no-match-exit-code-fix later to maint).
 
  * When handshake with a subprocess filter notices that the process
    asked for an unknown capability, Git did not report what program
    the offending subprocess was running.  This has been corrected.
-   (merge d3ba566342 cc/subprocess-handshake-missing-capabilities later to maint).
 
  * "git apply" that is used as a better "patch -p1" failed to apply a
    taken from a file with CRLF line endings to a file with CRLF line
@@ -239,38 +225,29 @@ Fixes since v2.14
    entry at the same path, which is a nonsense---in that mode, "apply"
    is not working on the data in (or derived from) the index at all.
    This has been fixed.
-   (merge c24f3abace tb/apply-with-crlf later to maint).
 
  * Killing "git merge --edit" before the editor returns control left
    the repository in a state with MERGE_MSG but without MERGE_HEAD,
    which incorrectly tells the subsequent "git commit" that there was
    a squash merge in progress.  This has been fixed.
-   (merge 9d89b35526 mg/killed-merge later to maint).
 
  * "git archive" did not work well with pathspecs and the
    export-ignore attribute.
-   (merge 5ff247ac0c rs/archive-excluded-directory later to maint).
+
+ * In addition to "cc: <a@dd.re.ss> # cruft", "cc: a@dd.re.ss # cruft"
+   was taught to "git send-email" as a valid way to tell it that it
+   needs to also send a carbon copy to <a@dd.re.ss> in the trailer
+   section.
+   (merge cc90750677 mm/send-email-cc-cruft later to maint).
+
+ * "git branch -M a b" while on a branch that is completely unrelated
+   to either branch a or branch b misbehaved when multiple worktree
+   was in use.  This has been fixed.
+   (merge 31824d180d nd/worktree-kill-parse-ref later to maint).
 
  * Other minor doc, test and build updates and code cleanups.
-   (merge dff2813391 ab/ref-filter-no-contains later to maint).
    (merge f094b89a4d ma/parse-maybe-bool later to maint).
-   (merge 974ce8078c mf/no-dashed-subcommands later to maint).
-   (merge f81935cc4d jc/perl-git-comment-typofix later to maint).
-   (merge 57ea241ef0 rs/t3700-clean-leftover later to maint).
    (merge 39b00fa4d4 jk/drop-sha1-entry-pos later to maint).
-   (merge 0b006014c8 jk/hashcmp-memcmp later to maint).
-   (merge 1e22a9917b rj/add-chmod-error-message later to maint).
-   (merge 881529c846 rs/apply-lose-prefix-length later to maint).
-   (merge 6355a76802 rs/find-pack-entry-bisection later to maint).
-   (merge de3ce210ed rs/merge-microcleanup later to maint).
-   (merge 7f0a02be2f ah/doc-empty-string-is-false later to maint).
-   (merge 70ec6bd63b rs/t1002-do-not-use-sum later to maint).
-   (merge 2456990dfd sb/sha1-file-cleanup later to maint).
-   (merge 2aac933c62 hv/t5526-andand-chain-fix later to maint).
-   (merge c8d0c4fe9b sb/submodule-parallel-update later to maint).
-   (merge 794b7e1674 mg/format-ref-doc-fix later to maint).
-   (merge 24da8a26a9 rs/commit-h-single-parent-cleanup later to maint).
-   (merge 4e36907fa3 jk/doc-the-this later to maint).
-   (merge 15d1d0951e bc/vcs-svn-cleanup later to maint).
-   (merge b8f43b120b jn/vcs-svn-cleanup later to maint).
-   (merge 4a4becfb23 jt/doc-pack-objects-fix later to maint).
+   (merge 6cdf8a7929 ma/ts-cleanups later to maint).
+   (merge 7560f547e6 ma/up-to-date later to maint).
+   (merge 0db3dc75f3 rs/apply-epoch later to maint).
index 631cbd840a08eb29add1e900ac9272992669a75c..4ebc3d32719dfefa988d34b41871f0e9fb969471 100644 (file)
@@ -66,7 +66,7 @@ OPTIONS
        disables it is in effect), make sure the patch is
        applicable to what the current index file records.  If
        the file to be patched in the working tree is not
-       up-to-date, it is flagged as an error.  This flag also
+       up to date, it is flagged as an error.  This flag also
        causes the index file to be updated.
 
 --cached::
@@ -259,7 +259,7 @@ treats these changes as follows.
 If `--index` is specified (explicitly or implicitly), then the submodule
 commits must match the index exactly for the patch to apply.  If any
 of the submodules are checked-out, then these check-outs are completely
-ignored, i.e., they are not required to be up-to-date or clean and they
+ignored, i.e., they are not required to be up to date or clean and they
 are not updated.
 
 If `--index` is not specified, then the submodule commits in the patch
index a336ae5f6fd5587aa8f778d2378783d0fe2e6dc4..ba90066f108cf525eb7781c1607d65358c617b0e 100644 (file)
@@ -223,7 +223,7 @@ access method and requested operation.
 That means that even if you offer only read access (e.g. by using
 the pserver method), 'git-cvsserver' should have write access to
 the database to work reliably (otherwise you need to make sure
-that the database is up-to-date any time 'git-cvsserver' is executed).
+that the database is up to date any time 'git-cvsserver' is executed).
 
 By default it uses SQLite databases in the Git directory, named
 `gitcvs.<module_name>.sqlite`. Note that the SQLite backend creates
index a1715069529eba9d143d527c058e962381efd743..b380677718ae129b4643814d7c1a16351ce4d779 100644 (file)
@@ -85,7 +85,7 @@ a 'git write-tree' + 'git diff-tree'. Thus that's the default mode.
 The non-cached version asks the question:
 
   show me the differences between HEAD and the currently checked out
-  tree - index contents _and_ files that aren't up-to-date
+  tree - index contents _and_ files that aren't up to date
 
 which is obviously a very useful question too, since that tells you what
 you *could* commit. Again, the output matches the 'git diff-tree -r'
@@ -100,8 +100,8 @@ have not actually done a 'git update-index' on it yet - there is no
   torvalds@ppc970:~/v2.6/linux> git diff-index --abbrev HEAD
   :100644 100664 7476bb... 000000...      kernel/sched.c
 
-i.e., it shows that the tree has changed, and that `kernel/sched.c` has is
-not up-to-date and may contain new stuff. The all-zero sha1 means that to
+i.e., it shows that the tree has changed, and that `kernel/sched.c` is
+not up to date and may contain new stuff. The all-zero sha1 means that to
 get the real diff, you need to look at the object in the working directory
 directly rather than do an object-to-object diff.
 
index 615e6bacde7355e3125268bc969d0fee2a06392e..4df6431c341a466f2cb9fef094607751b58c008d 100644 (file)
@@ -141,7 +141,7 @@ exception is when the changed index entries are in the state that
 would result from the merge already.)
 
 If all named commits are already ancestors of `HEAD`, 'git merge'
-will exit early with the message "Already up-to-date."
+will exit early with the message "Already up to date."
 
 FAST-FORWARD MERGE
 ------------------
index 4f6bed61a92b74e4540b71e0e0cac7cba60302ca..6805a74aec20cacd7b9320136b8648ad5b40ef5b 100644 (file)
@@ -334,7 +334,7 @@ which makes little sense.
 
 -f::
 --force-rebase::
-       Force a rebase even if the current branch is up-to-date and
+       Force a rebase even if the current branch is up to date and
        the command without `--force` would return without doing anything.
 +
 You may find this (or --no-ff with an interactive rebase) helpful after
index 9ee083c415a27dc499b75031d49df9e3f3856ec0..031f31fa471154f474b35448564aff6c8c2b3f51 100644 (file)
@@ -205,7 +205,7 @@ development on the topic branch:
 ------------
 
 you could run `git rebase master topic`, to bring yourself
-up-to-date before your topic is ready to be sent upstream.
+up to date before your topic is ready to be sent upstream.
 This would result in falling back to a three-way merge, and it
 would conflict the same way as the test merge you resolved earlier.
 'git rerere' will be run by 'git rebase' to help you resolve this
index 683e59133003536c776c476304e369bdd80e27a2..b5c46223c44b1b17673ae4782f74528b3d151bed 100644 (file)
@@ -146,7 +146,7 @@ the submodule's history. If it exists the submodule.<name> section
 in the linkgit:gitmodules[5] file will also be removed and that file
 will be staged (unless --cached or -n are used).
 
-A submodule is considered up-to-date when the HEAD is the same as
+A submodule is considered up to date when the HEAD is the same as
 recorded in the index, no tracked files are modified and no untracked
 files that aren't ignored are present in the submodules work tree.
 Ignored files are deemed expendable and won't stop a submodule's work
index aa2aeabb60209fabd772907a91c2812b2a305d7d..636e09048e8846b813166737ef58eef96eb3a3c4 100644 (file)
@@ -424,7 +424,7 @@ Any other arguments are passed directly to 'git log'
 'set-tree'::
        You should consider using 'dcommit' instead of this command.
        Commit specified commit or tree objects to SVN.  This relies on
-       your imported fetch data being up-to-date.  This makes
+       your imported fetch data being up to date.  This makes
        absolutely no attempts to do patching when committing to SVN, it
        simply overwrites files with those specified in the tree or
        commit.  All merging is assumed to have taken place
index 1579abf3c3b45f4e63f8f17746dde31a06a3a564..e19eba62cda292cc51407cbcd7e94675560f97f2 100644 (file)
@@ -214,7 +214,7 @@ will remove the intended effect of the option.
 Using --refresh
 ---------------
 `--refresh` does not calculate a new sha1 file or bring the index
-up-to-date for mode/content changes. But what it *does* do is to
+up to date for mode/content changes. But what it *does* do is to
 "re-match" the stat information of a file with the index, so that you
 can refresh the index for a file that hasn't been changed but where
 the stat entry is out of date.
index 7577f27ec20c90eabea2652a438ca09961559f6a..e29a9effccbcf439fec8a8fe9bfd1927f58439d7 100644 (file)
@@ -631,7 +631,7 @@ So after you do a `cp -a` to create a new copy, you'll want to do
 $ git update-index --refresh
 ----------------
 +
-in the new repository to make sure that the index file is up-to-date.
+in the new repository to make sure that the index file is up to date.
 
 Note that the second point is true even across machines. You can
 duplicate a remote Git repository with *any* regular copy mechanism, be it
@@ -701,7 +701,7 @@ $ git checkout-index -u -a
 ----------------
 
 where the `-u` flag means that you want the checkout to keep the index
-up-to-date (so that you don't have to refresh it afterward), and the
+up to date (so that you don't have to refresh it afterward), and the
 `-a` flag means "check out all files" (if you have a stale copy or an
 older version of a checked out tree you may also need to add the `-f`
 flag first, to tell 'git checkout-index' to *force* overwriting of any old
@@ -1283,7 +1283,7 @@ run a single command, 'git-receive-pack'.
 
 First, you need to create an empty repository on the remote
 machine that will house your public repository. This empty
-repository will be populated and be kept up-to-date by pushing
+repository will be populated and be kept up to date by pushing
 into it later. Obviously, this repository creation needs to be
 done only once.
 
@@ -1450,7 +1450,7 @@ transport protocols (HTTP), you need to keep this repository
 would contain a call to 'git update-server-info'
 but you need to manually enable the hook with
 `mv post-update.sample post-update`.  This makes sure
-'git update-server-info' keeps the necessary files up-to-date.
+'git update-server-info' keeps the necessary files up to date.
 
 3. Push into the public repository from your primary
    repository.
index 623ed1a13829188971531aa62c6e109e9d29ec44..1bb4f92d4d317e16929767066a61c123fee0f280 100644 (file)
@@ -369,7 +369,7 @@ them.
 
 When enabled, the default 'post-update' hook runs
 'git update-server-info' to keep the information used by dumb
-transports (e.g., HTTP) up-to-date.  If you are publishing
+transports (e.g., HTTP) up to date.  If you are publishing
 a Git repository that is accessible via HTTP, you should
 probably enable this hook.
 
index f51ed4e37cd3fad80bf855e6217906f094f894fb..adf9554ad2f84cb69a6b0a940e4d3e0e336df9ff 100644 (file)
@@ -71,7 +71,7 @@ objects/info/packs::
        This file is to help dumb transports discover what packs
        are available in this object store.  Whenever a pack is
        added or removed, `git update-server-info` should be run
-       to keep this file up-to-date if the repository is
+       to keep this file up to date if the repository is
        published for dumb transports.  'git repack' does this
        by default.
 
index 794b83393ea21a8d569c34791ee4af1dfb99a57a..242de31cb6ccc6600b94a68a9efd215df2cb71f7 100644 (file)
@@ -109,7 +109,7 @@ summary of the situation with 'git status':
 $ git status
 On branch master
 Changes to be committed:
-Your branch is up-to-date with 'origin/master'.
+Your branch is up to date with 'origin/master'.
   (use "git reset HEAD <file>..." to unstage)
 
        modified:   file1
index 5b4a62e93624bc8289c835631aab5d5f13dff708..4e323043017deee83d547e52e7797dd61a02cd5d 100644 (file)
@@ -39,7 +39,7 @@ set to `no` at the beginning of them.
 
 --ff-only::
        Refuse to merge and exit with a non-zero status unless the
-       current `HEAD` is already up-to-date or the merge can be
+       current `HEAD` is already up to date or the merge can be
        resolved as a fast-forward.
 
 --log[=<n>]::
index a6cf9eb380fabedd0e89b84d182e6e2c4798e503..7d860bfca1442e7957c41b7a7a5cd6f82141ed7e 100644 (file)
@@ -184,6 +184,14 @@ explicitly.
        Pretend as if all objects mentioned by reflogs are listed on the
        command line as `<commit>`.
 
+--single-worktree::
+       By default, all working trees will be examined by the
+       following options when there are more than one (see
+       linkgit:git-worktree[1]): `--all`, `--reflog` and
+       `--indexed-objects`.
+       This option forces them to examine the current working tree
+       only.
+
 --ignore-missing::
        Upon seeing an invalid object name in the input, pretend as if
        the bad input was not given.
index 37379d83376fc2342d1a81570b3de86b8e7dcd49..46c3d5c3550a1ba7c83b6937fe68538c3c12074e 100644 (file)
@@ -32,11 +32,8 @@ Iteration functions
 
 * `for_each_glob_ref_in()` the previous and `for_each_ref_in()` combined.
 
-* `head_ref_submodule()`, `for_each_ref_submodule()`,
-  `for_each_ref_in_submodule()`, `for_each_tag_ref_submodule()`,
-  `for_each_branch_ref_submodule()`, `for_each_remote_ref_submodule()`
-  do the same as the functions described above but for a specified
-  submodule.
+* Use `refs_` API for accessing submodules. The submodule ref store could
+  be obtained with `get_submodule_ref_store()`.
 
 * `for_each_rawref()` can be used to learn about broken ref and symref.
 
index a34917153fd3dc10fefe71a1ba05e5dacb9af7f9..ed1eae8b83a651d34f9ce2488f58d02a763fbfd4 100644 (file)
@@ -199,7 +199,7 @@ After reference and capabilities discovery, the client can decide to
 terminate the connection by sending a flush-pkt, telling the server it can
 now gracefully terminate, and disconnect, when it does not need any pack
 data. This can happen with the ls-remote command, and also can happen when
-the client already is up-to-date.
+the client already is up to date.
 
 Otherwise, it enters the negotiation phase, where the client and
 server determine what the minimal packfile necessary for transport is,
index c79d4a7c476da2c57c117529150de77646ed116e..1f1c33d0da30dbdf90c37bd808eb52059b598c84 100644 (file)
@@ -32,7 +32,7 @@ or the result.
 If multiple cases apply, the one used is listed first.
 
 A result which changes the index is an error if the index is not empty
-and not up-to-date.
+and not up to date.
 
 Entries marked '+' have stat information. Spaces marked '*' don't
 affect the result.
@@ -65,7 +65,7 @@ empty, no entry is left for that stage). Otherwise, the given entry is
 left in stage 0, and there are no other entries.
 
 A result of "no merge" is an error if the index is not empty and not
-up-to-date.
+up to date.
 
 *empty* means that the tree must not have a directory-file conflict
  with the entry.
index bc29298678a6d2d9f6b2927f97c40ba8978bd93b..b4d88af133e8eafd92f86443bd74de063bad4835 100644 (file)
@@ -2044,10 +2044,12 @@ If a push would not result in a <<fast-forwards,fast-forward>> of the
 remote branch, then it will fail with an error like:
 
 -------------------------------------------------
-error: remote 'refs/heads/master' is not an ancestor of
- local  'refs/heads/master'.
- Maybe you are not up-to-date and need to pull first?
-error: failed to push to 'ssh://yourserver.com/~you/proj.git'
+ ! [rejected]        master -> master (non-fast-forward)
+error: failed to push some refs to '...'
+hint: Updates were rejected because the tip of your current branch is behind
+hint: its remote counterpart. Integrate the remote changes (e.g.
+hint: 'git pull ...') before pushing again.
+hint: See the 'Note about fast-forwards' in 'git push --help' for details.
 -------------------------------------------------
 
 This can happen, for example, if you:
@@ -2193,7 +2195,7 @@ $ cd work
 Linus's tree will be stored in the remote-tracking branch named origin/master,
 and can be updated using linkgit:git-fetch[1]; you can track other
 public trees using linkgit:git-remote[1] to set up a "remote" and
-linkgit:git-fetch[1] to keep them up-to-date; see
+linkgit:git-fetch[1] to keep them up to date; see
 <<repositories-and-branches>>.
 
 Now create the branches in which you are going to work; these start out
index f2bb7f2f63e458af6261b4a151d87ef9e973222e..68948dfbf3f29531d41be591daa9a8ba8df72708 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -162,6 +162,11 @@ all::
 # algorithm. This is slower, but may detect attempted collision attacks.
 # Takes priority over other *_SHA1 knobs.
 #
+# Define DC_SHA1_EXTERNAL in addition to DC_SHA1 if you want to build / link
+# git with the external SHA1 collision-detect library.
+# Without this option, i.e. the default behavior is to build git with its
+# own built-in code (or submodule).
+#
 # Define DC_SHA1_SUBMODULE in addition to DC_SHA1 to use the
 # sha1collisiondetection shipped as a submodule instead of the
 # non-submodule copy in sha1dc/. This is an experimental option used
@@ -1475,6 +1480,15 @@ ifdef APPLE_COMMON_CRYPTO
        BASIC_CFLAGS += -DSHA1_APPLE
 else
        DC_SHA1 := YesPlease
+       BASIC_CFLAGS += -DSHA1_DC
+       LIB_OBJS += sha1dc_git.o
+ifdef DC_SHA1_EXTERNAL
+       ifdef DC_SHA1_SUBMODULE
+$(error Only set DC_SHA1_EXTERNAL or DC_SHA1_SUBMODULE, not both)
+       endif
+       BASIC_CFLAGS += -DDC_SHA1_EXTERNAL
+       EXTLIBS += -lsha1detectcoll
+else
 ifdef DC_SHA1_SUBMODULE
        LIB_OBJS += sha1collisiondetection/lib/sha1.o
        LIB_OBJS += sha1collisiondetection/lib/ubc_check.o
@@ -1484,17 +1498,15 @@ else
        LIB_OBJS += sha1dc/ubc_check.o
 endif
        BASIC_CFLAGS += \
-               -DSHA1_DC \
                -DSHA1DC_NO_STANDARD_INCLUDES \
                -DSHA1DC_INIT_SAFE_HASH_DEFAULT=0 \
                -DSHA1DC_CUSTOM_INCLUDE_SHA1_C="\"cache.h\"" \
-               -DSHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C="\"sha1dc_git.c\"" \
-               -DSHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H="\"sha1dc_git.h\"" \
                -DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C="\"git-compat-util.h\""
 endif
 endif
 endif
 endif
+endif
 
 ifdef SHA1_MAX_BLOCK_SIZE
        LIB_OBJS += compat/sha1-chunked.o
diff --git a/apply.c b/apply.c
index 86666217d4df0c8162c8d93d859ab5112c10f4b9..71cbbd141c73bd72778d71e1e2400413c11f492f 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -812,16 +812,13 @@ static int has_epoch_timestamp(const char *nameline)
         * 1970-01-01, and the seconds part must be "00".
         */
        const char stamp_regexp[] =
-               "^(1969-12-31|1970-01-01)"
-               " "
-               "[0-2][0-9]:[0-5][0-9]:00(\\.0+)?"
+               "^[0-2][0-9]:([0-5][0-9]):00(\\.0+)?"
                " "
                "([-+][0-2][0-9]:?[0-5][0-9])\n";
        const char *timestamp = NULL, *cp, *colon;
        static regex_t *stamp;
        regmatch_t m[10];
-       int zoneoffset;
-       int hourminute;
+       int zoneoffset, epoch_hour, hour, minute;
        int status;
 
        for (cp = nameline; *cp != '\n'; cp++) {
@@ -830,6 +827,18 @@ static int has_epoch_timestamp(const char *nameline)
        }
        if (!timestamp)
                return 0;
+
+       /*
+        * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31
+        * (west of GMT) or 1970-01-01 (east of GMT)
+        */
+       if (skip_prefix(timestamp, "1969-12-31 ", &timestamp))
+               epoch_hour = 24;
+       else if (skip_prefix(timestamp, "1970-01-01 ", &timestamp))
+               epoch_hour = 0;
+       else
+               return 0;
+
        if (!stamp) {
                stamp = xmalloc(sizeof(*stamp));
                if (regcomp(stamp, stamp_regexp, REG_EXTENDED)) {
@@ -847,6 +856,9 @@ static int has_epoch_timestamp(const char *nameline)
                return 0;
        }
 
+       hour = strtol(timestamp, NULL, 10);
+       minute = strtol(timestamp + m[1].rm_so, NULL, 10);
+
        zoneoffset = strtol(timestamp + m[3].rm_so + 1, (char **) &colon, 10);
        if (*colon == ':')
                zoneoffset = zoneoffset * 60 + strtol(colon + 1, NULL, 10);
@@ -855,20 +867,7 @@ static int has_epoch_timestamp(const char *nameline)
        if (timestamp[m[3].rm_so] == '-')
                zoneoffset = -zoneoffset;
 
-       /*
-        * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31
-        * (west of GMT) or 1970-01-01 (east of GMT)
-        */
-       if ((zoneoffset < 0 && memcmp(timestamp, "1969-12-31", 10)) ||
-           (0 <= zoneoffset && memcmp(timestamp, "1970-01-01", 10)))
-               return 0;
-
-       hourminute = (strtol(timestamp + 11, NULL, 10) * 60 +
-                     strtol(timestamp + 14, NULL, 10) -
-                     zoneoffset);
-
-       return ((zoneoffset < 0 && hourminute == 1440) ||
-               (0 <= zoneoffset && !hourminute));
+       return hour * 60 + minute - zoneoffset == epoch_hour * 60;
 }
 
 /*
index ce1f8bb58ebd4709e2b13e85232d7138d5cde0d6..703ded69ca2697f34bc1e225ccecebf33e5ad0b1 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -357,8 +357,9 @@ int replace_each_worktree_head_symref(const char *oldref, const char *newref,
 
                if (worktrees[i]->is_detached)
                        continue;
-               if (worktrees[i]->head_ref &&
-                   strcmp(oldref, worktrees[i]->head_ref))
+               if (!worktrees[i]->head_ref)
+                       continue;
+               if (strcmp(oldref, worktrees[i]->head_ref))
                        continue;
 
                refs = get_worktree_ref_store(worktrees[i]);
index 7df3fe3927ef8a1c65f7baad7d957602436315cd..3672e38974f094831c305d509b9582c146f94236 100644 (file)
@@ -1359,7 +1359,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                 * If head can reach all the merge then we are up to date.
                 * but first the most common case of merging one remote.
                 */
-               finish_up_to_date(_("Already up-to-date."));
+               finish_up_to_date(_("Already up to date."));
                goto done;
        } else if (fast_forward != FF_NO && !remoteheads->next &&
                        !common->next &&
@@ -1442,7 +1442,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        }
                }
                if (up_to_date) {
-                       finish_up_to_date(_("Already up-to-date. Yeeah!"));
+                       finish_up_to_date(_("Already up to date. Yeeah!"));
                        goto done;
                }
        }
index c41ea7c2a62ba868061884e511256c24f4d020d9..598da6c8bc75e9de50f85eac78d3051f27f96a6c 100644 (file)
@@ -253,7 +253,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
                struct commit *commit = (struct commit *)o;
                int from_tag = starts_with(path, "refs/tags/");
 
-               if (taggerdate == ULONG_MAX)
+               if (taggerdate == TIME_MAX)
                        taggerdate = ((struct commit *)o)->date;
                path = name_ref_abbrev(path, can_abbreviate_output);
                name_rev(commit, xstrdup(path), taggerdate, 0, 0,
index 82ad6e0c813375b480129c22035afc4d6674992a..a57b4f058dff3ceec80355560bf6a856f130b8c0 100644 (file)
@@ -2171,7 +2171,10 @@ static void *threaded_find_deltas(void *arg)
 {
        struct thread_params *me = arg;
 
+       progress_lock();
        while (me->remaining) {
+               progress_unlock();
+
                find_deltas(me->list, &me->remaining,
                            me->window, me->depth, me->processed);
 
@@ -2193,7 +2196,10 @@ static void *threaded_find_deltas(void *arg)
                        pthread_cond_wait(&me->cond, &me->mutex);
                me->data_ready = 0;
                pthread_mutex_unlock(&me->mutex);
+
+               progress_lock();
        }
+       progress_unlock();
        /* leave ->working 1 so that this doesn't get more work assigned */
        return NULL;
 }
diff --git a/color.c b/color.c
index 7aa8b076f045e5c0b74826153030e2923c0fc56e..9ccd954d6ba5cea1dd275cac23bb19966b9c6386 100644 (file)
--- a/color.c
+++ b/color.c
@@ -338,6 +338,13 @@ static int check_auto_color(void)
 
 int want_color(int var)
 {
+       /*
+        * NEEDSWORK: This function is sometimes used from multiple threads, and
+        * we end up using want_auto racily. That "should not matter" since
+        * we always write the same value, but it's still wrong. This function
+        * is listed in .tsan-suppressions for the time being.
+        */
+
        static int want_auto = -1;
 
        if (var < 0)
index fbf5c582496eece56b29a91a2f3085716f4b0e9f..f2be7cc92437191219d16ddf1536883da23541c0 100644 (file)
@@ -17,4 +17,7 @@ shebang.perl: FORCE
 test: all
        $(MAKE) -C t
 
+clean:
+       $(RM) diff-highlight
+
 .PHONY: FORCE
index ee99f1a4ee89a9e9f358b6cc89fc84cab554b439..932e78dbfee97750ae38afcf699e95f118f956dd 100755 (executable)
@@ -399,7 +399,7 @@ case "$allow_fast_forward,$#,$common,$no_commit" in
 ?,1,"$1",*)
        # If head can reach all the merge then we are up to date.
        # but first the most common case of merging one remote.
-       finish_up_to_date "Already up-to-date."
+       finish_up_to_date "Already up to date."
        exit 0
        ;;
 t,1,"$head",*)
@@ -459,7 +459,7 @@ t,1,"$head",*)
        done
        if test "$up_to_date" = t
        then
-               finish_up_to_date "Already up-to-date. Yeeah!"
+               finish_up_to_date "Already up to date. Yeeah!"
                exit 0
        fi
        ;;
index 70fdc27b724f28793c6a4bff713957a22689b78b..3099dc851ac26a9280e7e6d1a73638c05d01cc17 100755 (executable)
@@ -41,7 +41,7 @@ fi
 
 case "$common" in
 "$merge")
-       echo "Already up-to-date. Yeeah!"
+       echo "Already up to date. Yeeah!"
        dropheads
        exit 0
        ;;
index 3c87ebaf57baede9810c3b9b489eed9751189706..d05c613c9718697f64bc2334dc9ae85bf473f13e 100755 (executable)
@@ -253,7 +253,7 @@ test_expect_success 'merge the added subproj again, should do nothing' '
                # this shouldn not actually do anything, since FETCH_HEAD
                # is already a parent
                result=$(git merge -s ours -m "merge -s -ours" FETCH_HEAD) &&
-               check_equal "${result}" "Already up-to-date."
+               check_equal "${result}" "Already up to date."
        )
 '
 
index c5f0b210370c0ee83ef59298fa2260d627332399..02962261c58f71485a27f9799a5db29ec77e0bc7 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -1040,7 +1040,6 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
                ca->crlf_action = git_path_check_crlf(ccheck + 4);
                if (ca->crlf_action == CRLF_UNDEFINED)
                        ca->crlf_action = git_path_check_crlf(ccheck + 0);
-               ca->attr_action = ca->crlf_action;
                ca->ident = git_path_check_ident(ccheck + 1);
                ca->drv = git_path_check_convert(ccheck + 2);
                if (ca->crlf_action != CRLF_BINARY) {
@@ -1054,12 +1053,14 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
                        else if (eol_attr == EOL_CRLF)
                                ca->crlf_action = CRLF_TEXT_CRLF;
                }
-               ca->attr_action = ca->crlf_action;
        } else {
                ca->drv = NULL;
                ca->crlf_action = CRLF_UNDEFINED;
                ca->ident = 0;
        }
+
+       /* Save attr and make a decision for action */
+       ca->attr_action = ca->crlf_action;
        if (ca->crlf_action == CRLF_TEXT)
                ca->crlf_action = text_eol_is_crlf() ? CRLF_TEXT_CRLF : CRLF_TEXT_INPUT;
        if (ca->crlf_action == CRLF_UNDEFINED && auto_crlf == AUTO_CRLF_FALSE)
diff --git a/entry.c b/entry.c
index 65458f07a4453fa29731fe2b9c20848d6b192b20..cb291aa88bf148608184edeff68943315b44e6ab 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -3,6 +3,7 @@
 #include "dir.h"
 #include "streaming.h"
 #include "submodule.h"
+#include "progress.h"
 
 static void create_directories(const char *path, int path_len,
                               const struct checkout *state)
@@ -161,16 +162,22 @@ static int remove_available_paths(struct string_list_item *item, void *cb_data)
 int finish_delayed_checkout(struct checkout *state)
 {
        int errs = 0;
+       unsigned delayed_object_count;
+       off_t filtered_bytes = 0;
        struct string_list_item *filter, *path;
+       struct progress *progress;
        struct delayed_checkout *dco = state->delayed_checkout;
 
        if (!state->delayed_checkout)
                return errs;
 
        dco->state = CE_RETRY;
+       delayed_object_count = dco->paths.nr;
+       progress = start_delayed_progress(_("Filtering content"), delayed_object_count);
        while (dco->filters.nr > 0) {
                for_each_string_list_item(filter, &dco->filters) {
                        struct string_list available_paths = STRING_LIST_INIT_NODUP;
+                       display_progress(progress, delayed_object_count - dco->paths.nr);
 
                        if (!async_query_available_blobs(filter->string, &available_paths)) {
                                /* Filter reported an error */
@@ -216,11 +223,17 @@ int finish_delayed_checkout(struct checkout *state)
                                }
                                ce = index_file_exists(state->istate, path->string,
                                                       strlen(path->string), 0);
-                               errs |= (ce ? checkout_entry(ce, state, NULL) : 1);
+                               if (ce) {
+                                       errs |= checkout_entry(ce, state, NULL);
+                                       filtered_bytes += ce->ce_stat_data.sd_size;
+                                       display_throughput(progress, filtered_bytes);
+                               } else
+                                       errs = 1;
                        }
                }
                string_list_remove_empty_items(&dco->filters, 0);
        }
+       stop_progress(&progress);
        string_list_clear(&dco->filters, 0);
 
        /* At this point we should not have any delayed paths anymore. */
index 0f5837d48e7040e9d2b07513666b608353736645..2514bc22abf4aedfaa8d641976c96fbf222bb8a7 100644 (file)
@@ -165,7 +165,7 @@ to contribute an update.  This may be because you would want to improve
 the translation of existing messages, or because the git-gui software
 itself was updated and there are new messages that need translation.
 
-In any case, make sure you are up-to-date before starting your work:
+In any case, make sure you are up to date before starting your work:
 
        $ git checkout master
        $ git pull
index 6c390d6c229d7ef8cca8ae01d33b42b57e29c3b3..7d19d379512b52168d7c604002e872fc3eef9fd7 100755 (executable)
@@ -74,7 +74,7 @@ do
 
        case "$LF$common$LF" in
        *"$LF$SHA1$LF"*)
-               eval_gettextln "Already up-to-date with \$pretty_name"
+               eval_gettextln "Already up to date with \$pretty_name"
                continue
                ;;
        esac
index 2fa581789c5d9d4dd967e1783c513d64660f8a9c..76859b453afc2d5ba6897d15a680245b455f4f38 100755 (executable)
--- a/git-p4.py
+++ b/git-p4.py
@@ -3614,7 +3614,7 @@ def run(self, args):
 
     def rebase(self):
         if os.system("git update-index --refresh") != 0:
-            die("Some files in your working directory are modified and different than what is in your index. You can use git update-index <filename> to bring the index up-to-date or stash away all your changes with git stash.");
+            die("Some files in your working directory are modified and different than what is in your index. You can use git update-index <filename> to bring the index up to date or stash away all your changes with git stash.");
         if len(read_pipe("git diff-index HEAD --")) > 0:
             die("You have uncommitted changes. Please commit them before rebasing or stash them away with git stash.");
 
index fa6526986ed40143a12ffcd6563fd52b49d209e7..2208dcc2139be7130749fd3bae462320f17d3b21 100755 (executable)
@@ -155,7 +155,6 @@ sub format_2822_time {
 }
 
 my $have_email_valid = eval { require Email::Valid; 1 };
-my $have_mail_address = eval { require Mail::Address; 1 };
 my $smtp;
 my $auth;
 my $num_sent = 0;
@@ -490,11 +489,7 @@ sub read_config {
 ($repocommitter) = Git::ident_person(@repo, 'committer');
 
 sub parse_address_line {
-       if ($have_mail_address) {
-               return map { $_->format } Mail::Address->parse($_[0]);
-       } else {
-               return Git::parse_mailboxes($_[0]);
-       }
+       return Git::parse_mailboxes($_[0]);
 }
 
 sub split_addrs {
@@ -1089,6 +1084,26 @@ sub sanitize_address {
 
 }
 
+sub strip_garbage_one_address {
+       my ($addr) = @_;
+       chomp $addr;
+       if ($addr =~ /^(("[^"]*"|[^"<]*)? *<[^>]*>).*/) {
+               # "Foo Bar" <foobar@example.com> [possibly garbage here]
+               # Foo Bar <foobar@example.com> [possibly garbage here]
+               return $1;
+       }
+       if ($addr =~ /^(<[^>]*>).*/) {
+               # <foo@example.com> [possibly garbage here]
+               # if garbage contains other addresses, they are ignored.
+               return $1;
+       }
+       if ($addr =~ /^([^"#,\s]*)/) {
+               # address without quoting: remove anything after the address
+               return $1;
+       }
+       return $addr;
+}
+
 sub sanitize_address_list {
        return (map { sanitize_address($_) } @_);
 }
@@ -1590,10 +1605,12 @@ sub send_message {
        # Now parse the message body
        while(<$fh>) {
                $message .=  $_;
-               if (/^(Signed-off-by|Cc): ([^>]*>?)/i) {
+               if (/^(Signed-off-by|Cc): (.*)/i) {
                        chomp;
                        my ($what, $c) = ($1, $2);
-                       chomp $c;
+                       # strip garbage for the address we'll use:
+                       $c = strip_garbage_one_address($c);
+                       # sanitize a bit more to decide whether to suppress the address:
                        my $sc = sanitize_address($c);
                        if ($sc eq $sender) {
                                next if ($suppress_cc{'self'});
diff --git a/hash.h b/hash.h
index bef3e630a093b508e78419c5f4e228e836ecb88c..024d0d3d50b174aac1d948e9ecfa7ae92020355a 100644 (file)
--- a/hash.h
+++ b/hash.h
@@ -8,11 +8,7 @@
 #elif defined(SHA1_OPENSSL)
 #include <openssl/sha.h>
 #elif defined(SHA1_DC)
-#ifdef DC_SHA1_SUBMODULE
-#include "sha1collisiondetection/lib/sha1.h"
-#else
-#include "sha1dc/sha1.h"
-#endif
+#include "sha1dc_git.h"
 #else /* SHA1_BLK */
 #include "block-sha1/sha1.h"
 #endif
index 1494ffdb828106882053065e3ac8cc383136cf80..182626c02781384733b863b025bcfc5a1978e893 100644 (file)
@@ -1927,7 +1927,7 @@ int merge_trees(struct merge_options *o,
        }
 
        if (oid_eq(&common->object.oid, &merge->object.oid)) {
-               output(o, 0, _("Already up-to-date!"));
+               output(o, 0, _("Already up to date!"));
                *result = head;
                return 1;
        }
index 744c68557649ff1b1fbc007cd2bd2951fc09ab93..b04d2f213116a6413d564107a6e12e3f7317accb 100644 (file)
@@ -624,7 +624,7 @@ int notes_merge(struct notes_merge_options *o,
        if (!oidcmp(&remote->object.oid, base_oid)) {
                /* Already merged; result == local commit */
                if (o->verbosity >= 2)
-                       printf("Already up-to-date!\n");
+                       printf("Already up to date!\n");
                oidcpy(result_oid, &local->object.oid);
                goto found_result;
        }
diff --git a/notes.c b/notes.c
index f090c88363883e65cea66fd63b2c8dfb3f642b7d..5c62862574399acb486530d3fab5a7f659eb7c2f 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -64,7 +64,7 @@ struct non_note {
 #define CLR_PTR_TYPE(ptr)       ((void *) ((uintptr_t) (ptr) & ~3))
 #define SET_PTR_TYPE(ptr, type) ((void *) ((uintptr_t) (ptr) | (type)))
 
-#define GET_NIBBLE(n, sha1) (((sha1[(n) >> 1]) >> ((~(n) & 0x01) << 2)) & 0x0f)
+#define GET_NIBBLE(n, sha1) ((((sha1)[(n) >> 1]) >> ((~(n) & 0x01) << 2)) & 0x0f)
 
 #define KEY_INDEX (GIT_SHA1_RAWSZ - 1)
 #define FANOUT_PATH_SEPARATORS ((GIT_SHA1_HEXSZ / 2) - 1)
@@ -335,31 +335,20 @@ static void note_tree_free(struct int_node *tree)
 }
 
 /*
- * Convert a partial SHA1 hex string to the corresponding partial SHA1 value.
- * - hex      - Partial SHA1 segment in ASCII hex format
- * - hex_len  - Length of above segment. Must be multiple of 2 between 0 and 40
- * - sha1     - Partial SHA1 value is written here
- * - sha1_len - Max #bytes to store in sha1, Must be >= hex_len / 2, and < 20
- * Returns -1 on error (invalid arguments or invalid SHA1 (not in hex format)).
- * Otherwise, returns number of bytes written to sha1 (i.e. hex_len / 2).
- * Pads sha1 with NULs up to sha1_len (not included in returned length).
+ * Read `len` pairs of hexadecimal digits from `hex` and write the
+ * values to `binary` as `len` bytes. Return 0 on success, or -1 if
+ * the input does not consist of hex digits).
  */
-static int get_oid_hex_segment(const char *hex, unsigned int hex_len,
-               unsigned char *oid, unsigned int oid_len)
+static int hex_to_bytes(unsigned char *binary, const char *hex, size_t len)
 {
-       unsigned int i, len = hex_len >> 1;
-       if (hex_len % 2 != 0 || len > oid_len)
-               return -1;
-       for (i = 0; i < len; i++) {
+       for (; len; len--, hex += 2) {
                unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]);
+
                if (val & ~0xff)
                        return -1;
-               *oid++ = val;
-               hex += 2;
+               *binary++ = val;
        }
-       for (; i < oid_len; i++)
-               *oid++ = 0;
-       return len;
+       return 0;
 }
 
 static int non_note_cmp(const struct non_note *a, const struct non_note *b)
@@ -417,13 +406,10 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                struct int_node *node, unsigned int n)
 {
        struct object_id object_oid;
-       unsigned int prefix_len;
+       size_t prefix_len;
        void *buf;
        struct tree_desc desc;
        struct name_entry entry;
-       int len, path_len;
-       unsigned char type;
-       struct leaf_node *l;
 
        buf = fill_tree_descriptor(&desc, &subtree->val_oid);
        if (!buf)
@@ -431,66 +417,79 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                     oid_to_hex(&subtree->val_oid));
 
        prefix_len = subtree->key_oid.hash[KEY_INDEX];
-       assert(prefix_len * 2 >= n);
+       if (prefix_len >= GIT_SHA1_RAWSZ)
+               BUG("prefix_len (%"PRIuMAX") is out of range", (uintmax_t)prefix_len);
+       if (prefix_len * 2 < n)
+               BUG("prefix_len (%"PRIuMAX") is too small", (uintmax_t)prefix_len);
        memcpy(object_oid.hash, subtree->key_oid.hash, prefix_len);
        while (tree_entry(&desc, &entry)) {
-               path_len = strlen(entry.path);
-               len = get_oid_hex_segment(entry.path, path_len,
-                               object_oid.hash + prefix_len, GIT_SHA1_RAWSZ - prefix_len);
-               if (len < 0)
-                       goto handle_non_note; /* entry.path is not a SHA1 */
-               len += prefix_len;
+               unsigned char type;
+               struct leaf_node *l;
+               size_t path_len = strlen(entry.path);
+
+               if (path_len == 2 * (GIT_SHA1_RAWSZ - prefix_len)) {
+                       /* This is potentially the remainder of the SHA-1 */
+
+                       if (!S_ISREG(entry.mode))
+                               /* notes must be blobs */
+                               goto handle_non_note;
+
+                       if (hex_to_bytes(object_oid.hash + prefix_len, entry.path,
+                                        GIT_SHA1_RAWSZ - prefix_len))
+                               goto handle_non_note; /* entry.path is not a SHA1 */
 
-               /*
-                * If object SHA1 is complete (len == 20), assume note object
-                * If object SHA1 is incomplete (len < 20), and current
-                * component consists of 2 hex chars, assume note subtree
-                */
-               if (len <= GIT_SHA1_RAWSZ) {
                        type = PTR_TYPE_NOTE;
-                       l = (struct leaf_node *)
-                               xcalloc(1, sizeof(struct leaf_node));
-                       oidcpy(&l->key_oid, &object_oid);
-                       oidcpy(&l->val_oid, entry.oid);
-                       if (len < GIT_SHA1_RAWSZ) {
-                               if (!S_ISDIR(entry.mode) || path_len != 2)
-                                       goto handle_non_note; /* not subtree */
-                               l->key_oid.hash[KEY_INDEX] = (unsigned char) len;
-                               type = PTR_TYPE_SUBTREE;
-                       }
-                       if (note_tree_insert(t, node, n, l, type,
-                                            combine_notes_concatenate))
-                               die("Failed to load %s %s into notes tree "
-                                   "from %s",
-                                   type == PTR_TYPE_NOTE ? "note" : "subtree",
-                                   oid_to_hex(&l->key_oid), t->ref);
+               } else if (path_len == 2) {
+                       /* This is potentially an internal node */
+                       size_t len = prefix_len;
+
+                       if (!S_ISDIR(entry.mode))
+                               /* internal nodes must be trees */
+                               goto handle_non_note;
+
+                       if (hex_to_bytes(object_oid.hash + len++, entry.path, 1))
+                               goto handle_non_note; /* entry.path is not a SHA1 */
+
+                       /*
+                        * Pad the rest of the SHA-1 with zeros,
+                        * except for the last byte, where we write
+                        * the length:
+                        */
+                       memset(object_oid.hash + len, 0, GIT_SHA1_RAWSZ - len - 1);
+                       object_oid.hash[KEY_INDEX] = (unsigned char)len;
+
+                       type = PTR_TYPE_SUBTREE;
+               } else {
+                       /* This can't be part of a note */
+                       goto handle_non_note;
                }
+
+               l = xcalloc(1, sizeof(*l));
+               oidcpy(&l->key_oid, &object_oid);
+               oidcpy(&l->val_oid, entry.oid);
+               if (note_tree_insert(t, node, n, l, type,
+                                    combine_notes_concatenate))
+                       die("Failed to load %s %s into notes tree "
+                           "from %s",
+                           type == PTR_TYPE_NOTE ? "note" : "subtree",
+                           oid_to_hex(&l->key_oid), t->ref);
+
                continue;
 
 handle_non_note:
                /*
-                * Determine full path for this non-note entry:
-                * The filename is already found in entry.path, but the
-                * directory part of the path must be deduced from the subtree
-                * containing this entry. We assume here that the overall notes
-                * tree follows a strict byte-based progressive fanout
-                * structure (i.e. using 2/38, 2/2/36, etc. fanouts, and not
-                * e.g. 4/36 fanout). This means that if a non-note is found at
-                * path "dead/beef", the following code will register it as
-                * being found on "de/ad/beef".
-                * On the other hand, if you use such non-obvious non-note
-                * paths in the middle of a notes tree, you deserve what's
-                * coming to you ;). Note that for non-notes that are not
-                * SHA1-like at the top level, there will be no problems.
-                *
-                * To conclude, it is strongly advised to make sure non-notes
-                * have at least one non-hex character in the top-level path
-                * component.
+                * Determine full path for this non-note entry. The
+                * filename is already found in entry.path, but the
+                * directory part of the path must be deduced from the
+                * subtree containing this entry based on our
+                * knowledge that the overall notes tree follows a
+                * strict byte-based progressive fanout structure
+                * (i.e. using 2/38, 2/2/36, etc. fanouts).
                 */
                {
                        struct strbuf non_note_path = STRBUF_INIT;
                        const char *q = oid_to_hex(&subtree->key_oid);
-                       int i;
+                       size_t i;
                        for (i = 0; i < prefix_len; i++) {
                                strbuf_addch(&non_note_path, *q++);
                                strbuf_addch(&non_note_path, *q++);
index e2a23ebc9668b066d337391e96139af49907edfa..1079362450e2f4d8a054ef7cb155a0fbcbc065bc 100644 (file)
@@ -536,7 +536,7 @@ void parse_pathspec(struct pathspec *pathspec,
 {
        struct pathspec_item *item;
        const char *entry = argv ? *argv : NULL;
-       int i, n, prefixlen, warn_empty_string, nr_exclude = 0;
+       int i, n, prefixlen, nr_exclude = 0;
 
        memset(pathspec, 0, sizeof(*pathspec));
 
@@ -569,13 +569,10 @@ void parse_pathspec(struct pathspec *pathspec,
        }
 
        n = 0;
-       warn_empty_string = 1;
        while (argv[n]) {
-               if (*argv[n] == '\0' && warn_empty_string) {
-                       warning(_("empty strings as pathspecs will be made invalid in upcoming releases. "
-                                 "please use . instead if you meant to match all paths"));
-                       warn_empty_string = 0;
-               }
+               if (*argv[n] == '\0')
+                       die("empty string is not a valid pathspec. "
+                                 "please use . instead if you meant to match all paths");
                n++;
        }
 
index 7db9119573abe2c8308bd37c670c027c07b425c8..f364944b931a756b3b4819fb49ff5e9e01daf676 100644 (file)
@@ -136,9 +136,10 @@ static void format_packet(struct strbuf *out, const char *fmt, va_list args)
 static int packet_write_fmt_1(int fd, int gently,
                              const char *fmt, va_list args)
 {
-       struct strbuf buf = STRBUF_INIT;
+       static struct strbuf buf = STRBUF_INIT;
        ssize_t count;
 
+       strbuf_reset(&buf);
        format_packet(&buf, fmt, args);
        count = write_in_full(fd, buf.buf, buf.len);
        if (count == buf.len)
index d1ac5d97efdaff5dc971e38da278dcf1d820ef2c..88d7d679da9c837463f74d9a9277025b008635af 100644 (file)
@@ -10,6 +10,7 @@
 #include "progress.h"
 #include "list-objects.h"
 #include "packfile.h"
+#include "worktree.h"
 
 struct connectivity_progress {
        struct progress *progress;
@@ -177,6 +178,7 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
 
        /* detached HEAD is not included in the list above */
        head_ref(add_one_ref, revs);
+       other_head_refs(add_one_ref, revs);
 
        /* Add all reflog info */
        if (mark_reflog)
diff --git a/refs.c b/refs.c
index b0106b8162c7b8e3770e04c212abb05f1afbd0c3..a2b97fba780debe440203ff78f8203b5d140d3c2 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -336,12 +336,6 @@ int for_each_tag_ref(each_ref_fn fn, void *cb_data)
        return refs_for_each_tag_ref(get_main_ref_store(), fn, cb_data);
 }
 
-int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
-       return refs_for_each_tag_ref(get_submodule_ref_store(submodule),
-                                    fn, cb_data);
-}
-
 int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
        return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
@@ -352,12 +346,6 @@ int for_each_branch_ref(each_ref_fn fn, void *cb_data)
        return refs_for_each_branch_ref(get_main_ref_store(), fn, cb_data);
 }
 
-int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
-       return refs_for_each_branch_ref(get_submodule_ref_store(submodule),
-                                       fn, cb_data);
-}
-
 int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
        return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
@@ -368,12 +356,6 @@ int for_each_remote_ref(each_ref_fn fn, void *cb_data)
        return refs_for_each_remote_ref(get_main_ref_store(), fn, cb_data);
 }
 
-int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
-       return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
-                                       fn, cb_data);
-}
-
 int head_ref_namespaced(each_ref_fn fn, void *cb_data)
 {
        struct strbuf buf = STRBUF_INIT;
@@ -1266,19 +1248,13 @@ int refs_rename_ref_available(struct ref_store *refs,
        return ok;
 }
 
-int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
+int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
        struct object_id oid;
        int flag;
 
-       if (submodule) {
-               if (resolve_gitlink_ref(submodule, "HEAD", oid.hash) == 0)
-                       return fn("HEAD", &oid, 0, cb_data);
-
-               return 0;
-       }
-
-       if (!read_ref_full("HEAD", RESOLVE_REF_READING, oid.hash, &flag))
+       if (!refs_read_ref_full(refs, "HEAD", RESOLVE_REF_READING,
+                               oid.hash, &flag))
                return fn("HEAD", &oid, flag, cb_data);
 
        return 0;
@@ -1286,7 +1262,7 @@ int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
 
 int head_ref(each_ref_fn fn, void *cb_data)
 {
-       return head_ref_submodule(NULL, fn, cb_data);
+       return refs_head_ref(get_main_ref_store(), fn, cb_data);
 }
 
 struct ref_iterator *refs_ref_iterator_begin(
@@ -1344,11 +1320,6 @@ int for_each_ref(each_ref_fn fn, void *cb_data)
        return refs_for_each_ref(get_main_ref_store(), fn, cb_data);
 }
 
-int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
-       return refs_for_each_ref(get_submodule_ref_store(submodule), fn, cb_data);
-}
-
 int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
                         each_ref_fn fn, void *cb_data)
 {
@@ -1370,23 +1341,15 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsig
                               prefix, fn, 0, flag, cb_data);
 }
 
-int for_each_ref_in_submodule(const char *submodule, const char *prefix,
-                             each_ref_fn fn, void *cb_data)
-{
-       return refs_for_each_ref_in(get_submodule_ref_store(submodule),
-                                   prefix, fn, cb_data);
-}
-
-int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
-                                 each_ref_fn fn, void *cb_data,
-                                 unsigned int broken)
+int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
+                            each_ref_fn fn, void *cb_data,
+                            unsigned int broken)
 {
        unsigned int flag = 0;
 
        if (broken)
                flag = DO_FOR_EACH_INCLUDE_BROKEN;
-       return do_for_each_ref(get_submodule_ref_store(submodule),
-                              prefix, fn, 0, flag, cb_data);
+       return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
 }
 
 int for_each_replace_ref(each_ref_fn fn, void *cb_data)
@@ -1521,25 +1484,10 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
 int resolve_gitlink_ref(const char *submodule, const char *refname,
                        unsigned char *sha1)
 {
-       size_t len = strlen(submodule);
        struct ref_store *refs;
        int flags;
 
-       while (len && submodule[len - 1] == '/')
-               len--;
-
-       if (!len)
-               return -1;
-
-       if (submodule[len]) {
-               /* We need to strip off one or more trailing slashes */
-               char *stripped = xmemdupz(submodule, len);
-
-               refs = get_submodule_ref_store(stripped);
-               free(stripped);
-       } else {
-               refs = get_submodule_ref_store(submodule);
-       }
+       refs = get_submodule_ref_store(submodule);
 
        if (!refs)
                return -1;
@@ -1654,31 +1602,32 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
 {
        struct strbuf submodule_sb = STRBUF_INIT;
        struct ref_store *refs;
-       int ret;
+       char *to_free = NULL;
+       size_t len;
 
-       if (!submodule || !*submodule) {
-               /*
-                * FIXME: This case is ideally not allowed. But that
-                * can't happen until we clean up all the callers.
-                */
-               return get_main_ref_store();
-       }
+       if (!submodule)
+               return NULL;
+
+       len = strlen(submodule);
+       while (len && is_dir_sep(submodule[len - 1]))
+               len--;
+       if (!len)
+               return NULL;
+
+       if (submodule[len])
+               /* We need to strip off one or more trailing slashes */
+               submodule = to_free = xmemdupz(submodule, len);
 
        refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
        if (refs)
-               return refs;
+               goto done;
 
        strbuf_addstr(&submodule_sb, submodule);
-       ret = is_nonbare_repository_dir(&submodule_sb);
-       strbuf_release(&submodule_sb);
-       if (!ret)
-               return NULL;
+       if (!is_nonbare_repository_dir(&submodule_sb))
+               goto done;
 
-       ret = submodule_to_gitdir(&submodule_sb, submodule);
-       if (ret) {
-               strbuf_release(&submodule_sb);
-               return NULL;
-       }
+       if (submodule_to_gitdir(&submodule_sb, submodule))
+               goto done;
 
        /* assume that add_submodule_odb() has been called */
        refs = ref_store_init(submodule_sb.buf,
@@ -1686,7 +1635,10 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
        register_ref_store_map(&submodule_ref_stores, "submodule",
                               refs, submodule);
 
+done:
        strbuf_release(&submodule_sb);
+       free(to_free);
+
        return refs;
 }
 
diff --git a/refs.h b/refs.h
index 6daa78eb50ddc195c6d5bfb568d0b05ab08f7923..78a26400b61b0046c72a64b985b9aa6443f27021 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -275,6 +275,8 @@ typedef int each_ref_fn(const char *refname,
  * modifies the reference also returns a nonzero value to immediately
  * stop the iteration. Returned references are sorted.
  */
+int refs_head_ref(struct ref_store *refs,
+                 each_ref_fn fn, void *cb_data);
 int refs_for_each_ref(struct ref_store *refs,
                      each_ref_fn fn, void *cb_data);
 int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
@@ -289,6 +291,9 @@ int refs_for_each_remote_ref(struct ref_store *refs,
 int head_ref(each_ref_fn fn, void *cb_data);
 int for_each_ref(each_ref_fn fn, void *cb_data);
 int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
+int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
+                            each_ref_fn fn, void *cb_data,
+                            unsigned int broken);
 int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data,
                        unsigned int broken);
 int for_each_tag_ref(each_ref_fn fn, void *cb_data);
@@ -299,21 +304,6 @@ int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data);
 int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
                         const char *prefix, void *cb_data);
 
-int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data);
-int for_each_ref_submodule(const char *submodule,
-                          each_ref_fn fn, void *cb_data);
-int for_each_ref_in_submodule(const char *submodule, const char *prefix,
-                             each_ref_fn fn, void *cb_data);
-int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
-                                 each_ref_fn fn, void *cb_data,
-                                 unsigned int broken);
-int for_each_tag_ref_submodule(const char *submodule,
-                              each_ref_fn fn, void *cb_data);
-int for_each_branch_ref_submodule(const char *submodule,
-                                 each_ref_fn fn, void *cb_data);
-int for_each_remote_ref_submodule(const char *submodule,
-                                 each_ref_fn fn, void *cb_data);
-
 int head_ref_namespaced(each_ref_fn fn, void *cb_data);
 int for_each_namespaced_ref(each_ref_fn fn, void *cb_data);
 
index f3455609d658a55b20ca47026236cec17533ecca..a7cc65d0dee2dc5e8d3af6e447fc337e5958930f 100644 (file)
@@ -106,15 +106,6 @@ static void files_reflog_path(struct files_ref_store *refs,
                              struct strbuf *sb,
                              const char *refname)
 {
-       if (!refname) {
-               /*
-                * FIXME: of course this is wrong in multi worktree
-                * setting. To be fixed real soon.
-                */
-               strbuf_addf(sb, "%s/logs", refs->gitcommondir);
-               return;
-       }
-
        switch (ref_type(refname)) {
        case REF_TYPE_PER_WORKTREE:
        case REF_TYPE_PSEUDOREF:
@@ -2052,23 +2043,63 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {
        files_reflog_iterator_abort
 };
 
-static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
+static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store,
+                                                 const char *gitdir)
 {
-       struct files_ref_store *refs =
-               files_downcast(ref_store, REF_STORE_READ,
-                              "reflog_iterator_begin");
        struct files_reflog_iterator *iter = xcalloc(1, sizeof(*iter));
        struct ref_iterator *ref_iterator = &iter->base;
        struct strbuf sb = STRBUF_INIT;
 
        base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable);
-       files_reflog_path(refs, &sb, NULL);
+       strbuf_addf(&sb, "%s/logs", gitdir);
        iter->dir_iterator = dir_iterator_begin(sb.buf);
        iter->ref_store = ref_store;
        strbuf_release(&sb);
+
        return ref_iterator;
 }
 
+static enum iterator_selection reflog_iterator_select(
+       struct ref_iterator *iter_worktree,
+       struct ref_iterator *iter_common,
+       void *cb_data)
+{
+       if (iter_worktree) {
+               /*
+                * We're a bit loose here. We probably should ignore
+                * common refs if they are accidentally added as
+                * per-worktree refs.
+                */
+               return ITER_SELECT_0;
+       } else if (iter_common) {
+               if (ref_type(iter_common->refname) == REF_TYPE_NORMAL)
+                       return ITER_SELECT_1;
+
+               /*
+                * The main ref store may contain main worktree's
+                * per-worktree refs, which should be ignored
+                */
+               return ITER_SKIP_1;
+       } else
+               return ITER_DONE;
+}
+
+static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
+{
+       struct files_ref_store *refs =
+               files_downcast(ref_store, REF_STORE_READ,
+                              "reflog_iterator_begin");
+
+       if (!strcmp(refs->gitdir, refs->gitcommondir)) {
+               return reflog_iterator_begin(ref_store, refs->gitcommondir);
+       } else {
+               return merge_ref_iterator_begin(
+                       reflog_iterator_begin(ref_store, refs->gitdir),
+                       reflog_iterator_begin(ref_store, refs->gitcommondir),
+                       reflog_iterator_select, refs);
+       }
+}
+
 /*
  * If update is a direct update of head_ref (the reference pointed to
  * by HEAD), then add an extra REF_LOG_ONLY update for HEAD.
@@ -2092,11 +2123,10 @@ static int split_head_update(struct ref_update *update,
 
        /*
         * First make sure that HEAD is not already in the
-        * transaction. This insertion is O(N) in the transaction
+        * transaction. This check is O(lg N) in the transaction
         * size, but it happens at most once per transaction.
         */
-       item = string_list_insert(affected_refnames, "HEAD");
-       if (item->util) {
+       if (string_list_has_string(affected_refnames, "HEAD")) {
                /* An entry already existed */
                strbuf_addf(err,
                            "multiple updates for 'HEAD' (including one "
@@ -2111,6 +2141,14 @@ static int split_head_update(struct ref_update *update,
                        update->new_oid.hash, update->old_oid.hash,
                        update->msg);
 
+       /*
+        * Add "HEAD". This insertion is O(N) in the transaction
+        * size, but it happens at most once per transaction.
+        * Add new_update->refname instead of a literal "HEAD".
+        */
+       if (strcmp(new_update->refname, "HEAD"))
+               BUG("%s unexpectedly not 'HEAD'", new_update->refname);
+       item = string_list_insert(affected_refnames, new_update->refname);
        item->util = new_update;
 
        return 0;
@@ -2137,13 +2175,12 @@ static int split_symref_update(struct files_ref_store *refs,
 
        /*
         * First make sure that referent is not already in the
-        * transaction. This insertion is O(N) in the transaction
+        * transaction. This check is O(lg N) in the transaction
         * size, but it happens at most once per symref in a
         * transaction.
         */
-       item = string_list_insert(affected_refnames, referent);
-       if (item->util) {
-               /* An entry already existed */
+       if (string_list_has_string(affected_refnames, referent)) {
+               /* An entry already exists */
                strbuf_addf(err,
                            "multiple updates for '%s' (including one "
                            "via symref '%s') are not allowed",
@@ -2178,6 +2215,17 @@ static int split_symref_update(struct files_ref_store *refs,
        update->flags |= REF_LOG_ONLY | REF_NODEREF;
        update->flags &= ~REF_HAVE_OLD;
 
+       /*
+        * Add the referent. This insertion is O(N) in the transaction
+        * size, but it happens at most once per symref in a
+        * transaction. Make sure to add new_update->refname, which will
+        * be valid as long as affected_refnames is in use, and NOT
+        * referent, which might soon be freed by our caller.
+        */
+       item = string_list_insert(affected_refnames, new_update->refname);
+       if (item->util)
+               BUG("%s unexpectedly found in affected_refnames",
+                   new_update->refname);
        item->util = new_update;
 
        return 0;
@@ -2249,7 +2297,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
        struct strbuf referent = STRBUF_INIT;
        int mustexist = (update->flags & REF_HAVE_OLD) &&
                !is_null_oid(&update->old_oid);
-       int ret;
+       int ret = 0;
        struct ref_lock *lock;
 
        files_assert_main_repository(refs, "lock_ref_for_update");
@@ -2261,7 +2309,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                ret = split_head_update(update, transaction, head_ref,
                                        affected_refnames, err);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
        ret = lock_raw_ref(refs, update->refname, mustexist,
@@ -2275,7 +2323,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                strbuf_addf(err, "cannot lock ref '%s': %s",
                            original_update_refname(update), reason);
                free(reason);
-               return ret;
+               goto out;
        }
 
        update->backend_data = lock;
@@ -2294,10 +2342,12 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                                        strbuf_addf(err, "cannot lock ref '%s': "
                                                    "error reading reference",
                                                    original_update_refname(update));
-                                       return -1;
+                                       ret = TRANSACTION_GENERIC_ERROR;
+                                       goto out;
                                }
                        } else if (check_old_oid(update, &lock->old_oid, err)) {
-                               return TRANSACTION_GENERIC_ERROR;
+                               ret = TRANSACTION_GENERIC_ERROR;
+                               goto out;
                        }
                } else {
                        /*
@@ -2311,13 +2361,15 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                                                  referent.buf, transaction,
                                                  affected_refnames, err);
                        if (ret)
-                               return ret;
+                               goto out;
                }
        } else {
                struct ref_update *parent_update;
 
-               if (check_old_oid(update, &lock->old_oid, err))
-                       return TRANSACTION_GENERIC_ERROR;
+               if (check_old_oid(update, &lock->old_oid, err)) {
+                       ret = TRANSACTION_GENERIC_ERROR;
+                       goto out;
+               }
 
                /*
                 * If this update is happening indirectly because of a
@@ -2354,7 +2406,8 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                                    "cannot update ref '%s': %s",
                                    update->refname, write_err);
                        free(write_err);
-                       return TRANSACTION_GENERIC_ERROR;
+                       ret = TRANSACTION_GENERIC_ERROR;
+                       goto out;
                } else {
                        update->flags |= REF_NEEDS_COMMIT;
                }
@@ -2368,10 +2421,14 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                if (close_ref_gently(lock)) {
                        strbuf_addf(err, "couldn't close '%s.lock'",
                                    update->refname);
-                       return TRANSACTION_GENERIC_ERROR;
+                       ret = TRANSACTION_GENERIC_ERROR;
+                       goto out;
                }
        }
-       return 0;
+
+out:
+       strbuf_release(&referent);
+       return ret;
 }
 
 /*
index 43c317e4e9f6e67aa3e1d0ae245d097bdba664db..41130900698893f46dd18b817a7e6b6485c735a4 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -2084,7 +2084,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb)
                                _("  (use \"git branch --unset-upstream\" to fixup)\n"));
        } else if (!ours && !theirs) {
                strbuf_addf(sb,
-                       _("Your branch is up-to-date with '%s'.\n"),
+                       _("Your branch is up to date with '%s'.\n"),
                        base);
        } else if (!theirs) {
                strbuf_addf(sb,
index 94a5e98525187a2d7f1c6f4e9a22f4cb3bb0cf84..f9a90d71d2008415e80b30c9e5d3b2743af5438f 100644 (file)
@@ -20,6 +20,7 @@
 #include "cache-tree.h"
 #include "bisect.h"
 #include "packfile.h"
+#include "worktree.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -1132,6 +1133,7 @@ struct all_refs_cb {
        int warned_bad_reflog;
        struct rev_info *all_revs;
        const char *name_for_errormsg;
+       struct ref_store *refs;
 };
 
 int ref_excluded(struct string_list *ref_excludes, const char *path)
@@ -1168,6 +1170,7 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
        cb->all_revs = revs;
        cb->all_flags = flags;
        revs->rev_input_given = 1;
+       cb->refs = NULL;
 }
 
 void clear_ref_exclusion(struct string_list **ref_excludes_p)
@@ -1188,12 +1191,19 @@ void add_ref_exclusion(struct string_list **ref_excludes_p, const char *exclude)
        string_list_append(*ref_excludes_p, exclude);
 }
 
-static void handle_refs(const char *submodule, struct rev_info *revs, unsigned flags,
-               int (*for_each)(const char *, each_ref_fn, void *))
+static void handle_refs(struct ref_store *refs,
+                       struct rev_info *revs, unsigned flags,
+                       int (*for_each)(struct ref_store *, each_ref_fn, void *))
 {
        struct all_refs_cb cb;
+
+       if (!refs) {
+               /* this could happen with uninitialized submodules */
+               return;
+       }
+
        init_all_refs_cb(&cb, revs, flags);
-       for_each(submodule, handle_one_ref, &cb);
+       for_each(refs, handle_one_ref, &cb);
 }
 
 static void handle_one_reflog_commit(struct object_id *oid, void *cb_data)
@@ -1229,17 +1239,41 @@ static int handle_one_reflog(const char *path, const struct object_id *oid,
        struct all_refs_cb *cb = cb_data;
        cb->warned_bad_reflog = 0;
        cb->name_for_errormsg = path;
-       for_each_reflog_ent(path, handle_one_reflog_ent, cb_data);
+       refs_for_each_reflog_ent(cb->refs, path,
+                                handle_one_reflog_ent, cb_data);
        return 0;
 }
 
+static void add_other_reflogs_to_pending(struct all_refs_cb *cb)
+{
+       struct worktree **worktrees, **p;
+
+       worktrees = get_worktrees(0);
+       for (p = worktrees; *p; p++) {
+               struct worktree *wt = *p;
+
+               if (wt->is_current)
+                       continue;
+
+               cb->refs = get_worktree_ref_store(wt);
+               refs_for_each_reflog(cb->refs,
+                                    handle_one_reflog,
+                                    cb);
+       }
+       free_worktrees(worktrees);
+}
+
 void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
 {
        struct all_refs_cb cb;
 
        cb.all_revs = revs;
        cb.all_flags = flags;
+       cb.refs = get_main_ref_store();
        for_each_reflog(handle_one_reflog, &cb);
+
+       if (!revs->single_worktree)
+               add_other_reflogs_to_pending(&cb);
 }
 
 static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,
@@ -1263,13 +1297,13 @@ static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,
 
 }
 
-void add_index_objects_to_pending(struct rev_info *revs, unsigned flags)
+static void do_add_index_objects_to_pending(struct rev_info *revs,
+                                           struct index_state *istate)
 {
        int i;
 
-       read_cache();
-       for (i = 0; i < active_nr; i++) {
-               struct cache_entry *ce = active_cache[i];
+       for (i = 0; i < istate->cache_nr; i++) {
+               struct cache_entry *ce = istate->cache[i];
                struct blob *blob;
 
                if (S_ISGITLINK(ce->ce_mode))
@@ -1282,13 +1316,39 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned flags)
                                             ce->ce_mode, ce->name);
        }
 
-       if (active_cache_tree) {
+       if (istate->cache_tree) {
                struct strbuf path = STRBUF_INIT;
-               add_cache_tree(active_cache_tree, revs, &path);
+               add_cache_tree(istate->cache_tree, revs, &path);
                strbuf_release(&path);
        }
 }
 
+void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
+{
+       struct worktree **worktrees, **p;
+
+       read_cache();
+       do_add_index_objects_to_pending(revs, &the_index);
+
+       if (revs->single_worktree)
+               return;
+
+       worktrees = get_worktrees(0);
+       for (p = worktrees; *p; p++) {
+               struct worktree *wt = *p;
+               struct index_state istate = { NULL };
+
+               if (wt->is_current)
+                       continue; /* current index already taken care of */
+
+               if (read_index_from(&istate,
+                                   worktree_git_path(wt, "index")) > 0)
+                       do_add_index_objects_to_pending(revs, &istate);
+               discard_index(&istate);
+       }
+       free_worktrees(worktrees);
+}
+
 static int add_parents_only(struct rev_info *revs, const char *arg_, int flags,
                            int exclude_parent)
 {
@@ -2069,23 +2129,25 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
        ctx->argc -= n;
 }
 
-static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data, const char *term) {
+static int for_each_bisect_ref(struct ref_store *refs, each_ref_fn fn,
+                              void *cb_data, const char *term)
+{
        struct strbuf bisect_refs = STRBUF_INIT;
        int status;
        strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
-       status = for_each_fullref_in_submodule(submodule, bisect_refs.buf, fn, cb_data, 0);
+       status = refs_for_each_fullref_in(refs, bisect_refs.buf, fn, cb_data, 0);
        strbuf_release(&bisect_refs);
        return status;
 }
 
-static int for_each_bad_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
+static int for_each_bad_bisect_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
-       return for_each_bisect_ref(submodule, fn, cb_data, term_bad);
+       return for_each_bisect_ref(refs, fn, cb_data, term_bad);
 }
 
-static int for_each_good_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
+static int for_each_good_bisect_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
-       return for_each_bisect_ref(submodule, fn, cb_data, term_good);
+       return for_each_bisect_ref(refs, fn, cb_data, term_good);
 }
 
 static int handle_revision_pseudo_opt(const char *submodule,
@@ -2094,8 +2156,22 @@ static int handle_revision_pseudo_opt(const char *submodule,
 {
        const char *arg = argv[0];
        const char *optarg;
+       struct ref_store *refs;
        int argcount;
 
+       if (submodule) {
+               /*
+                * We need some something like get_submodule_worktrees()
+                * before we can go through all worktrees of a submodule,
+                * .e.g with adding all HEADs from --all, which is not
+                * supported right now, so stick to single worktree.
+                */
+               if (!revs->single_worktree)
+                       die("BUG: --single-worktree cannot be used together with submodule");
+               refs = get_submodule_ref_store(submodule);
+       } else
+               refs = get_main_ref_store();
+
        /*
         * NOTE!
         *
@@ -2107,22 +2183,29 @@ static int handle_revision_pseudo_opt(const char *submodule,
         * register it in the list at the top of handle_revision_opt.
         */
        if (!strcmp(arg, "--all")) {
-               handle_refs(submodule, revs, *flags, for_each_ref_submodule);
-               handle_refs(submodule, revs, *flags, head_ref_submodule);
+               handle_refs(refs, revs, *flags, refs_for_each_ref);
+               handle_refs(refs, revs, *flags, refs_head_ref);
+               if (!revs->single_worktree) {
+                       struct all_refs_cb cb;
+
+                       init_all_refs_cb(&cb, revs, *flags);
+                       other_head_refs(handle_one_ref, &cb);
+               }
                clear_ref_exclusion(&revs->ref_excludes);
        } else if (!strcmp(arg, "--branches")) {
-               handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
+               handle_refs(refs, revs, *flags, refs_for_each_branch_ref);
                clear_ref_exclusion(&revs->ref_excludes);
        } else if (!strcmp(arg, "--bisect")) {
                read_bisect_terms(&term_bad, &term_good);
-               handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref);
-               handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
+               handle_refs(refs, revs, *flags, for_each_bad_bisect_ref);
+               handle_refs(refs, revs, *flags ^ (UNINTERESTING | BOTTOM),
+                           for_each_good_bisect_ref);
                revs->bisect = 1;
        } else if (!strcmp(arg, "--tags")) {
-               handle_refs(submodule, revs, *flags, for_each_tag_ref_submodule);
+               handle_refs(refs, revs, *flags, refs_for_each_tag_ref);
                clear_ref_exclusion(&revs->ref_excludes);
        } else if (!strcmp(arg, "--remotes")) {
-               handle_refs(submodule, revs, *flags, for_each_remote_ref_submodule);
+               handle_refs(refs, revs, *flags, refs_for_each_remote_ref);
                clear_ref_exclusion(&revs->ref_excludes);
        } else if ((argcount = parse_long_opt("glob", argv, &optarg))) {
                struct all_refs_cb cb;
@@ -2169,6 +2252,8 @@ static int handle_revision_pseudo_opt(const char *submodule,
                        return error("invalid argument to --no-walk");
        } else if (!strcmp(arg, "--do-walk")) {
                revs->no_walk = 0;
+       } else if (!strcmp(arg, "--single-worktree")) {
+               revs->single_worktree = 1;
        } else {
                return 0;
        }
index bc18487d6fff5e86dff60748c084995a77d2b588..3a3d3e2cf824bf0ae404204c1ea81dad813d5f93 100644 (file)
@@ -96,6 +96,7 @@ struct rev_info {
                        topo_order:1,
                        simplify_merges:1,
                        simplify_by_decoration:1,
+                       single_worktree:1,
                        tag_objects:1,
                        tree_objects:1,
                        blob_objects:1,
index 20af2856818ed51b2afb1718a7e317133ee0d7bd..cf5314f402ce78f0d5ab2bd72ee7f334b6394e04 100644 (file)
@@ -7,10 +7,4 @@ extern int sha1_pos(const unsigned char *sha1,
                    void *table,
                    size_t nr,
                    sha1_access_fn fn);
-
-extern int sha1_entry_pos(const void *table,
-                         size_t elem_size,
-                         size_t key_offset,
-                         unsigned lo, unsigned hi, unsigned nr,
-                         const unsigned char *key);
 #endif
index 4d32b4f77e042f0da2b5181f753d0933ad438567..e0cc9d988c70337977853101c397960132af1981 100644 (file)
@@ -1,8 +1,19 @@
+#include "cache.h"
+
+#ifdef DC_SHA1_EXTERNAL
 /*
- * This code is included at the end of sha1dc/sha1.c with the
- * SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C macro.
+ * Same as SHA1DCInit, but with default save_hash=0
  */
+void git_SHA1DCInit(SHA1_CTX *ctx)
+{
+       SHA1DCInit(ctx);
+       SHA1DCSetSafeHash(ctx, 0);
+}
+#endif
 
+/*
+ * Same as SHA1DCFinal, but convert collision attack case into a verbose die().
+ */
 void git_SHA1DCFinal(unsigned char hash[20], SHA1_CTX *ctx)
 {
        if (!SHA1DCFinal(hash, ctx))
@@ -11,6 +22,9 @@ void git_SHA1DCFinal(unsigned char hash[20], SHA1_CTX *ctx)
            sha1_to_hex(hash));
 }
 
+/*
+ * Same as SHA1DCUpdate, but adjust types to match git's usual interface.
+ */
 void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *vdata, unsigned long len)
 {
        const char *data = vdata;
index a8a5c1da169e42360fa39851f27a8c4863d0e9ad..a8c272927842901190b07098911ef785a458bcf3 100644 (file)
@@ -1,19 +1,23 @@
-/*
- * This code is included at the end of sha1dc/sha1.h with the
- * SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H macro.
- */
+/* Plumbing with collition-detecting SHA1 code */
 
-/*
- * Same as SHA1DCFinal, but convert collision attack case into a verbose die().
- */
-void git_SHA1DCFinal(unsigned char [20], SHA1_CTX *);
+#ifdef DC_SHA1_SUBMODULE
+#include "sha1collisiondetection/lib/sha1.h"
+#elif defined(DC_SHA1_EXTERNAL)
+#include <sha1dc/sha1.h>
+#else
+#include "sha1dc/sha1.h"
+#endif
+
+#ifdef DC_SHA1_EXTERNAL
+void git_SHA1DCInit(SHA1_CTX *);
+#else
+#define git_SHA1DCInit SHA1DCInit
+#endif
 
-/*
- * Same as SHA1DCUpdate, but adjust types to match git's usual interface.
- */
+void git_SHA1DCFinal(unsigned char [20], SHA1_CTX *);
 void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *data, unsigned long len);
 
 #define platform_SHA_CTX SHA1_CTX
-#define platform_SHA1_Init SHA1DCInit
+#define platform_SHA1_Init git_SHA1DCInit
 #define platform_SHA1_Update git_SHA1DCUpdate
 #define platform_SHA1_Final git_SHA1DCFinal
index e705b94db55578aabb2063f7364220978cea5a40..7496cb8ec5a1f8baeda90f8653b2fcbbe2527390 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -147,7 +147,10 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len)
        if (len > (sb->alloc ? sb->alloc - 1 : 0))
                die("BUG: strbuf_setlen() beyond buffer");
        sb->len = len;
-       sb->buf[len] = '\0';
+       if (sb->buf != strbuf_slopbuf)
+               sb->buf[len] = '\0';
+       else
+               assert(!strbuf_slopbuf[0]);
 }
 
 /**
index 3cea8221e0bc3dbe77b157384adcecdfc077c7dc..075c55f3ca8101e06731ef3b45e51d11ec00c7f6 100644 (file)
@@ -69,6 +69,13 @@ int is_staging_gitmodules_ok(const struct index_state *istate)
        return 1;
 }
 
+static int for_each_remote_ref_submodule(const char *submodule,
+                                        each_ref_fn fn, void *cb_data)
+{
+       return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
+                                       fn, cb_data);
+}
+
 /*
  * Try to update the "path" entry in the "submodule.<name>" section of the
  * .gitmodules file. Return 0 only if a .gitmodules file was found, a section
@@ -1627,6 +1634,8 @@ static int find_first_merges(struct object_array *result, const char *path,
                        oid_to_hex(&a->object.oid));
        init_revisions(&revs, NULL);
        rev_opts.submodule = path;
+       /* FIXME: can't handle linked worktrees in submodules yet */
+       revs.single_worktree = path != NULL;
        setup_revisions(ARRAY_SIZE(rev_args)-1, rev_args, &revs, &rev_opts);
 
        /* save all revisions from the above list that contain b */
index deb3ae7813052d01b6dab92586e2c37d313ef8ff..68108d956a3f65c868b08ecb81bae87e9c1f5e67 100755 (executable)
@@ -315,7 +315,7 @@ test_expect_success 'setup master' '
        echo >.gitattributes &&
        git checkout -b master &&
        git add .gitattributes &&
-       git commit -m "add .gitattributes" "" &&
+       git commit -m "add .gitattributes" . &&
        printf "\$Id: 0000000000000000000000000000000000000000 \$\nLINEONE\nLINETWO\nLINETHREE"     >LF &&
        printf "\$Id: 0000000000000000000000000000000000000000 \$\r\nLINEONE\r\nLINETWO\r\nLINETHREE" >CRLF &&
        printf "\$Id: 0000000000000000000000000000000000000000 \$\nLINEONE\r\nLINETWO\nLINETHREE"   >CRLF_mix_LF &&
index 5df06f355641ad7a38daf34f9fc841e7fe4f8a0f..8842d0329fb7947e811d4ffccff3bba9e8885d5d 100755 (executable)
@@ -49,4 +49,34 @@ test_expect_success 'create_symref(FOO, refs/heads/master)' '
        test_cmp expected actual
 '
 
+test_expect_success 'for_each_reflog()' '
+       echo $_z40 > .git/logs/PSEUDO-MAIN &&
+       mkdir -p     .git/logs/refs/bisect &&
+       echo $_z40 > .git/logs/refs/bisect/random &&
+
+       echo $_z40 > .git/worktrees/wt/logs/PSEUDO-WT &&
+       mkdir -p     .git/worktrees/wt/logs/refs/bisect &&
+       echo $_z40 > .git/worktrees/wt/logs/refs/bisect/wt-random &&
+
+       $RWT for-each-reflog | cut -c 42- | sort >actual &&
+       cat >expected <<-\EOF &&
+       HEAD 0x1
+       PSEUDO-WT 0x0
+       refs/bisect/wt-random 0x0
+       refs/heads/master 0x0
+       refs/heads/wt-master 0x0
+       EOF
+       test_cmp expected actual &&
+
+       $RMAIN for-each-reflog | cut -c 42- | sort >actual &&
+       cat >expected <<-\EOF &&
+       HEAD 0x1
+       PSEUDO-MAIN 0x0
+       refs/bisect/random 0x0
+       refs/heads/master 0x0
+       refs/heads/wt-master 0x0
+       EOF
+       test_cmp expected actual
+'
+
 test_done
index 51738fb96943bbc475d0f71ba77e4786dd0aea11..d971649979fa2661923d9df797125cd4d997cf97 100755 (executable)
@@ -162,6 +162,19 @@ test_expect_success 'git branch -M baz bam should add entries to .git/logs/HEAD'
        grep "^0\{40\}.*$msg$" .git/logs/HEAD
 '
 
+test_expect_success 'git branch -M should leave orphaned HEAD alone' '
+       git init orphan &&
+       (
+               cd orphan &&
+               test_commit initial &&
+               git checkout --orphan lonely &&
+               grep lonely .git/HEAD &&
+               test_path_is_missing .git/refs/head/lonely &&
+               git branch -M master mistress &&
+               grep lonely .git/HEAD
+       )
+'
+
 test_expect_success 'resulting reflog can be shown by log -g' '
        oid=$(git rev-parse HEAD) &&
        cat >expect <<-EOF &&
index f8568f8841d34d17f3d8fdae4d8d2404a6693c4d..81c6059a2d9fe4d23e3fac11d765ecaf20aef756 100755 (executable)
@@ -858,9 +858,8 @@ test_expect_success 'rm files with two different errors' '
        test_i18ncmp expect actual
 '
 
-test_expect_success 'rm empty string should invoke warning' '
-       git rm -rf "" 2>output &&
-       test_i18ngrep "warning: empty strings" output
+test_expect_success 'rm empty string should fail' '
+       test_must_fail git rm -rf ""
 '
 
 test_done
index 0aae21d6984bf0bd5c7c7de425a021da6122beee..2748805642201d7c514792bab8d8b3940fb4086c 100755 (executable)
@@ -331,9 +331,8 @@ test_expect_success 'git add --dry-run --ignore-missing of non-existing file out
        test_i18ncmp expect.err actual.err
 '
 
-test_expect_success 'git add empty string should invoke warning' '
-       git add "" 2>output &&
-       test_i18ngrep "warning: empty strings" output
+test_expect_success 'git add empty string should fail' '
+       test_must_fail git add ""
 '
 
 test_expect_success 'git add --chmod=[+-]x stages correctly' '
index 133b5842b1aee8e8e00eb0ca7e1b2d32ff4a4c9a..6694c19a1eecf10117b843bbacbc5bb47924c9c8 100755 (executable)
@@ -283,4 +283,41 @@ test_expect_success 'prune: handle alternate object database' '
        git -C B prune
 '
 
+test_expect_success 'prune: handle index in multiple worktrees' '
+       git worktree add second-worktree &&
+       echo "new blob for second-worktree" >second-worktree/blob &&
+       git -C second-worktree add blob &&
+       git prune --expire=now &&
+       git -C second-worktree show :blob >actual &&
+       test_cmp second-worktree/blob actual
+'
+
+test_expect_success 'prune: handle HEAD in multiple worktrees' '
+       git worktree add --detach third-worktree &&
+       echo "new blob for third-worktree" >third-worktree/blob &&
+       git -C third-worktree add blob &&
+       git -C third-worktree commit -m "third" &&
+       rm .git/worktrees/third-worktree/index &&
+       test_must_fail git -C third-worktree show :blob &&
+       git prune --expire=now &&
+       git -C third-worktree show HEAD:blob >actual &&
+       test_cmp third-worktree/blob actual
+'
+
+test_expect_success 'prune: handle HEAD reflog in multiple worktrees' '
+       git config core.logAllRefUpdates true &&
+       echo "lost blob for third-worktree" >expected &&
+       (
+               cd third-worktree &&
+               cat ../expected >blob &&
+               git add blob &&
+               git commit -m "second commit in third" &&
+               git reset --hard HEAD^
+       ) &&
+       git prune --expire=now &&
+       SHA1=`git hash-object expected` &&
+       git -C third-worktree show "$SHA1" >actual &&
+       test_cmp expected actual
+'
+
 test_done
index be78cc4fad205d7f1da7cc864de3c6e04be51882..8f17fd9da8ef6b54ae0a97500f2154b1c9d968b3 100755 (executable)
@@ -100,7 +100,7 @@ test_expect_success 'checkout (up-to-date with upstream)' '
        (
                cd test && git checkout b6
        ) >actual &&
-       test_i18ngrep "Your branch is up-to-date with .origin/master" actual
+       test_i18ngrep "Your branch is up to date with .origin/master" actual
 '
 
 test_expect_success 'status (diverged from upstream)' '
@@ -130,7 +130,7 @@ test_expect_success 'status (up-to-date with upstream)' '
                # reports nothing to commit
                test_must_fail git commit --dry-run
        ) >actual &&
-       test_i18ngrep "Your branch is up-to-date with .origin/master" actual
+       test_i18ngrep "Your branch is up to date with .origin/master" actual
 '
 
 cat >expect <<\EOF
index d1e4e8ad19f3d3e005e177b98e4eee16f4ef1461..f30980895c2f1b93317870e6b471d67bc99b0fd2 100755 (executable)
@@ -148,6 +148,8 @@ cat >expected-cc <<\EOF
 !two@example.com!
 !three@example.com!
 !four@example.com!
+!five@example.com!
+!six@example.com!
 EOF
 "
 
@@ -161,6 +163,8 @@ test_expect_success $PREREQ 'cc trailer with various syntax' '
        Cc: <two@example.com> # trailing comments are ignored
        Cc: <three@example.com>, <not.four@example.com> one address per line
        Cc: "Some # Body" <four@example.com> [ <also.a.comment> ]
+       Cc: five@example.com # not.six@example.com
+       Cc: six@example.com, not.seven@example.com
        EOF
        clean_fake_sendmail &&
        git send-email -1 --to=recipient@example.com \
index b7f81c198e22e4ce578a6148fa3346becabbfb3b..db5feab8a1ee6433108ade9e165956678a3e260b 100755 (executable)
@@ -58,7 +58,7 @@ then
        not_in_topic=`git rev-list "^$topic" master`
        if test -z "$not_in_topic"
        then
-               echo >&2 "$topic is already up-to-date with master"
+               echo >&2 "$topic is already up to date with master"
                exit 1 ;# we could allow it, but there is no point.
        else
                exit 0
index 8f68d69a86bd919162b62514af0b1d1d55e204a1..f50b34df2dba4827db6a96cf97d1c4ac7ca811a0 100644 (file)
@@ -1117,6 +1117,13 @@ int transport_helper_init(struct transport *transport, const char *name)
 __attribute__((format (printf, 1, 2)))
 static void transfer_debug(const char *fmt, ...)
 {
+       /*
+        * NEEDSWORK: This function is sometimes used from multiple threads, and
+        * we end up using debug_enabled racily. That "should not matter" since
+        * we always write the same value, but it's still wrong. This function
+        * is listed in .tsan-suppressions for the time being.
+        */
+
        va_list args;
        char msgbuf[PBUFFERSIZE];
        static int debug_enabled = -1;
index 68d34259c6cf6ecb4de29c32621ddbe967b6dbf9..71b70ccb12756cde1f1c5aeda952be6e2b91f5b8 100644 (file)
@@ -163,7 +163,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
        msgs[ERROR_BIND_OVERLAP] = _("Entry '%s' overlaps with '%s'.  Cannot bind.");
 
        msgs[ERROR_SPARSE_NOT_UPTODATE_FILE] =
-               _("Cannot update sparse checkout: the following entries are not up-to-date:\n%s");
+               _("Cannot update sparse checkout: the following entries are not up to date:\n%s");
        msgs[ERROR_WOULD_LOSE_ORPHANED_OVERWRITTEN] =
                _("The following working tree files would be overwritten by sparse checkout update:\n%s");
        msgs[ERROR_WOULD_LOSE_ORPHANED_REMOVED] =
@@ -383,8 +383,8 @@ static int check_updates(struct unpack_trees_options *o)
                        }
                }
        }
-       errs |= finish_delayed_checkout(&state);
        stop_progress(&progress);
+       errs |= finish_delayed_checkout(&state);
        if (o->update)
                git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
        return errs != 0;
index e28ffbeb096a85d67b2e885c48ab096340b5d295..8aaeea03771cfefa9edd019d0dc5146fef17a9c7 100644 (file)
@@ -30,7 +30,7 @@ static void add_head_info(struct worktree *wt)
 
        target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt),
                                         "HEAD",
-                                        RESOLVE_REF_READING,
+                                        0,
                                         wt->head_sha1, &flags);
        if (!target)
                return;
@@ -386,3 +386,25 @@ int submodule_uses_worktrees(const char *path)
        closedir(dir);
        return ret;
 }
+
+int other_head_refs(each_ref_fn fn, void *cb_data)
+{
+       struct worktree **worktrees, **p;
+       int ret = 0;
+
+       worktrees = get_worktrees(0);
+       for (p = worktrees; *p; p++) {
+               struct worktree *wt = *p;
+               struct ref_store *refs;
+
+               if (wt->is_current)
+                       continue;
+
+               refs = get_worktree_ref_store(wt);
+               ret = refs_head_ref(refs, fn, cb_data);
+               if (ret)
+                       break;
+       }
+       free_worktrees(worktrees);
+       return ret;
+}
index 5ea5e503fbe491a76d3c8ce279b7e281a5d07d3e..9276c81ae7cb5c42a86fd9ebbdb28720be409e47 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef WORKTREE_H
 #define WORKTREE_H
 
+#include "refs.h"
+
 struct worktree {
        char *path;
        char *id;
@@ -70,6 +72,12 @@ extern void free_worktrees(struct worktree **);
 extern const struct worktree *find_shared_symref(const char *symref,
                                                 const char *target);
 
+/*
+ * Similar to head_ref() for all HEADs _except_ one from the current
+ * worktree, which is covered by head_ref().
+ */
+int other_head_refs(each_ref_fn fn, void *cb_data);
+
 int is_worktree_being_rebased(const struct worktree *wt, const char *target);
 int is_worktree_being_bisected(const struct worktree *wt, const char *target);