summaryrefslogtreecommitdiff
path: root/refs.c
AgeCommit message (Collapse)AuthorFilesLines
2014-07-10Merge branch 'dt/refs-check-refname-component-sse-fix'Libravatar Junio C Hamano1-1/+2
Fixes to a topic that is already in 'master'. * dt/refs-check-refname-component-sse-fix: refs: fix valgrind suppression file refs.c: handle REFNAME_REFSPEC_PATTERN at end of page
2014-07-07refs.c: handle REFNAME_REFSPEC_PATTERN at end of pageLibravatar David Turner1-1/+2
When a ref crosses a memory page boundary, we restart the parsing at the beginning with the bytewise code. Pass the original flags to that code, rather than the current flags. Reported-By: Øyvind A. Holm <sunny@sunbase.org> Signed-off-by: David Turner <dturner@twitter.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-07-02Merge branch 'dt/refs-check-refname-component-sse'Libravatar Junio C Hamano1-18/+216
Further micro-optimization of a leaf-function. * dt/refs-check-refname-component-sse: refs.c: SSE2 optimizations for check_refname_component
2014-06-18refs.c: SSE2 optimizations for check_refname_componentLibravatar David Turner1-18/+216
Optimize check_refname_component using SSE2 on x86_64. git rev-parse HEAD is a good test-case for this, since it does almost nothing except parse refs. For one particular repo with about 60k refs, almost all packed, the timings are: Look up table: 29 ms SSE2: 23 ms This cuts about 20% off of the runtime. Ondřej Bílka <neleai@seznam.cz> suggested an SSE2 approach to the substring searches, which netted a speed boost over the SSE4.2 code I had initially written. Signed-off-by: David Turner <dturner@twitter.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-16Merge branch 'dt/refs-check-refname-component-optim'Libravatar Junio C Hamano1-28/+39
* dt/refs-check-refname-component-optim: refs.c: optimize check_refname_component()
2014-06-16Merge branch 'rs/read-ref-at'Libravatar Junio C Hamano1-105/+103
* rs/read-ref-at: refs.c: change read_ref_at to use the reflog iterators
2014-06-16Merge branch 'jl/remote-rm-prune'Libravatar Junio C Hamano1-2/+19
"git remote rm" and "git remote prune" can involve removing many refs at once, which is not a very efficient thing to do when very many refs exist in the packed-refs file. * jl/remote-rm-prune: remote prune: optimize "dangling symref" check/warning remote: repack packed-refs once when deleting multiple refs remote rm: delete remote configuration as the last
2014-06-06Merge branch 'rs/reflog-exists'Libravatar Junio C Hamano1-6/+15
* rs/reflog-exists: checkout.c: use ref_exists instead of file_exist refs.c: add new functions reflog_exists and delete_reflog
2014-06-05refs.c: optimize check_refname_component()Libravatar David Turner1-28/+39
In a repository with many refs, check_refname_component can be a major contributor to the runtime of some git commands. One such command is git rev-parse HEAD Timings for one particular repo, with about 60k refs, almost all packed, are: Old: 35 ms New: 29 ms Many other commands which read refs are also sped up. Signed-off-by: David Turner <dturner@twitter.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-03refs.c: change read_ref_at to use the reflog iteratorsLibravatar Ronnie Sahlberg1-105/+103
read_ref_at has its own parsing of the reflog file for no really good reason so lets change this to use the existing reflog iterators. This removes one instance where we manually unmarshall the reflog file format. Remove the now redundant ref_msg function. Log messages for errors are changed slightly. We no longer print the file name for the reflog, instead we refer to it as 'Log for ref <refname>'. This might be a minor useability regression, but I don't really think so, since experienced users would know where the log is anyway and inexperienced users would not know what to do about/how to repair 'Log ... has gap ...' anyway. Adapt the t1400 test to handle the change in log messages. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-05-27remote prune: optimize "dangling symref" check/warningLibravatar Jens Lindström1-1/+18
When 'git remote prune' was used to delete many refs in a repository with many refs, a lot of time was spent checking for (now) dangling symbolic refs pointing to the deleted ref, since warn_dangling_symref() was once per deleted ref to check all other refs in the repository. Avoid this using the new warn_dangling_symrefs() function which makes one pass over all refs and checks for all the deleted refs in one go, after they have all been deleted. Signed-off-by: Jens Lindström <jl@opera.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-05-27remote: repack packed-refs once when deleting multiple refsLibravatar Jens Lindström1-1/+1
When 'git remote rm' or 'git remote prune' were used in a repository with many refs, and needed to delete many remote-tracking refs, a lot of time was spent deleting those refs since for each deleted ref, repack_without_refs() was called to rewrite packed-refs without just that deleted ref. To avoid this, call repack_without_refs() first to repack without all the refs that will be deleted, before calling delete_ref() to delete each one completely. The call to repack_without_ref() in delete_ref() then becomes a no-op, since packed-refs already won't contain any of the deleted refs. Signed-off-by: Jens Lindström <jl@opera.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-05-08refs.c: add new functions reflog_exists and delete_reflogLibravatar Ronnie Sahlberg1-6/+15
Add two new functions, reflog_exists and delete_reflog, to hide the internal reflog implementation (that they are files under .git/logs/...) from callers. Update checkout.c to use these functions in update_refs_for_switch instead of building pathnames and calling out to file access functions. Update reflog.c to use these to check if the reflog exists. Now there are still many places in reflog.c where we are still leaking the reflog storage implementation but this at least reduces the number of such dependencies by one. Finally change two places in refs.c itself to use the new function to check if a ref exists or not isntead of build-path-and-stat(). Now, this is strictly not all that important since these are in parts of refs that are implementing the actual file storage backend but on the other hand it will not hurt either. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Acked-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07ref_transaction_commit(): work with transaction->updates in placeLibravatar Michael Haggerty1-4/+1
Now that we free the transaction when we are done, there is no need to make a copy of transaction->updates before working with it. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07struct ref_update: add a type fieldLibravatar Michael Haggerty1-5/+3
It used to be that ref_transaction_commit() allocated a temporary array to hold the types of references while it is working. Instead, add a type field to ref_update that ref_transaction_commit() can use as its scratch space. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07struct ref_update: add a lock fieldLibravatar Michael Haggerty1-17/+19
Now that we manage ref_update objects internally, we can use them to hold some of the scratch space we need when actually carrying out the updates. Store the (struct ref_lock *) there. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07ref_transaction_commit(): simplify code using temporary variablesLibravatar Michael Haggerty1-8/+13
Use temporary variables in the for-loop blocks to simplify expressions in the rest of the loop. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07struct ref_update: store refname as a FLEX_ARRAYLibravatar Michael Haggerty1-9/+6
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07struct ref_update: rename field "ref_name" to "refname"Libravatar Michael Haggerty1-9/+9
This is consistent with the usual nomenclature. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07refs: remove API function update_refs()Libravatar Michael Haggerty1-13/+20
It has been superseded by reference transactions. This also means that struct ref_update can become private. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07refs: add a concept of a reference transactionLibravatar Michael Haggerty1-0/+99
Build out the API for dealing with a bunch of reference checks and changes within a transaction. Define an opaque ref_transaction type that is managed entirely within refs.c. Introduce functions for beginning a transaction, adding updates to a transaction, and committing/rolling back a transaction. This API will soon replace update_refs(). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07update_refs(): fix constnessLibravatar Michael Haggerty1-1/+1
The old signature of update_refs() required a (const struct ref_update **) for its updates_orig argument. The "const" is presumably there to promise that the function will not modify the contents of the structures. But this declaration does not permit the function to be called with a (struct ref_update **), which is perfectly legitimate. C's type system is not powerful enough to express what we'd like. So remove the first "const" from the declaration. On the other hand, the function *can* promise not to modify the pointers within the array that is passed to it without inconveniencing its callers. So add a "const" that has that effect, making the final declaration (struct ref_update * const *). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07refs.h: rename the action_on_err constantsLibravatar Michael Haggerty1-9/+9
Given that these constants are only being used when updating references, it is inappropriate to give them such generic names as "DIE_ON_ERR". So prefix their names with "UPDATE_REFS_". Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-03-18Merge branch 'sh/use-hashcpy'Libravatar Junio C Hamano1-1/+1
* sh/use-hashcpy: Use hashcpy() when copying object names
2014-03-06Use hashcpy() when copying object namesLibravatar Sun He1-1/+1
We invented hashcpy() to keep the abstraction of "object name" behind it. Use it instead of calling memcpy() with hard-coded 20-byte length when moving object names between pieces of memory. Leave ppc/sha1.c as-is, because the function is about the SHA-1 hash algorithm whose output is and will always be 20 bytes. Helped-by: Michael Haggerty <mhagger@alum.mit.edu> Helped-by: Duy Nguyen <pclouds@gmail.com> Signed-off-by: Sun He <sunheehnus@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-20use wildmatch() directly without fnmatch() wrapperLibravatar Nguyễn Thái Ngọc Duy1-1/+1
Make it clear that we don't use fnmatch() anymore. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-27Merge branch 'mh/safe-create-leading-directories'Libravatar Junio C Hamano1-24/+68
Code clean-up and protection against concurrent write access to the ref namespace. * mh/safe-create-leading-directories: rename_tmp_log(): on SCLD_VANISHED, retry rename_tmp_log(): limit the number of remote_empty_directories() attempts rename_tmp_log(): handle a possible mkdir/rmdir race rename_ref(): extract function rename_tmp_log() remove_dir_recurse(): handle disappearing files and directories remove_dir_recurse(): tighten condition for removing unreadable dir lock_ref_sha1_basic(): if locking fails with ENOENT, retry lock_ref_sha1_basic(): on SCLD_VANISHED, retry safe_create_leading_directories(): add new error value SCLD_VANISHED cmd_init_db(): when creating directories, handle errors conservatively safe_create_leading_directories(): introduce enum for return values safe_create_leading_directories(): always restore slash at end of loop safe_create_leading_directories(): split on first of multiple slashes safe_create_leading_directories(): rename local variable safe_create_leading_directories(): add explicit "slash" pointer safe_create_leading_directories(): reduce scope of local variable safe_create_leading_directories(): fix format of "if" chaining
2014-01-27Merge branch 'mh/retire-ref-fetch-rules'Libravatar Junio C Hamano1-3/+3
Code simplification. * mh/retire-ref-fetch-rules: refname_match(): always use the rules in ref_rev_parse_rules
2014-01-21rename_tmp_log(): on SCLD_VANISHED, retryLibravatar Michael Haggerty1-1/+8
If safe_create_leading_directories() fails because a file along the path unexpectedly vanished, try again from the beginning. Try at most 4 times. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21rename_tmp_log(): limit the number of remote_empty_directories() attemptsLibravatar Michael Haggerty1-2/+2
This doesn't seem to be a likely error, but we've got the counter anyway, so we might as well use it for an added bit of safety. Please note that the first call to rename() is optimistic, and it is normal for it to fail if there is a directory in the way. So bump the total number of allowed attempts to 4, to be sure that we can still have at least 3 retries in the case of a race. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21rename_tmp_log(): handle a possible mkdir/rmdir raceLibravatar Michael Haggerty1-1/+10
If a directory vanishes while renaming the temporary reflog file, retry (up to 3 times). This could happen if another process deletes the directory created by safe_create_leading_directories() just before we rename the file into the directory. As far as I can tell, this race could not occur internal to git. The only time that a directory under $GIT_DIR/logs is deleted is if room has to be made for a log file for a reference with the same name; for example, in the following sequence: git branch foo/bar # Creates file .git/logs/refs/heads/foo/bar git branch -d foo/bar # Deletes file but leaves .git/logs/refs/heads/foo/ git branch foo # Deletes .git/logs/refs/heads/foo/ But the only reason the last command deletes the directory is because it wants to create a file with the same name. So if another process (e.g., git branch foo/baz ) wants to create that directory, one of the two is doomed to failure anyway because of a D/F conflict. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21rename_ref(): extract function rename_tmp_log()Libravatar Michael Haggerty1-22/+30
It's about to become a bit more complex. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21lock_ref_sha1_basic(): if locking fails with ENOENT, retryLibravatar Michael Haggerty1-1/+12
If hold_lock_file_for_update() fails with errno==ENOENT, it might be because somebody else (for example, a pack-refs process) has just deleted one of the lockfile's ancestor directories. So if this condition is detected, try again (up to 3 times). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21lock_ref_sha1_basic(): on SCLD_VANISHED, retryLibravatar Michael Haggerty1-1/+10
If safe_create_leading_directories() fails because a file along the path unexpectedly vanished, try again (up to 3 times). This can occur if another process is deleting directories at the same time as we are trying to make them. For example, "git pack-refs --all" tries to delete the loose refs and any empty directories that are left behind. If a pack-refs process is running, then it might delete a directory that we need to put a new loose reference in. If safe_create_leading_directories() thinks this might have happened, then take its advice and try again (maximum three attempts). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-14refname_match(): always use the rules in ref_rev_parse_rulesLibravatar Michael Haggerty1-3/+3
We used to use two separate rules for the normal ref resolution dwimming and dwimming done to decide which remote ref to grab. The third parameter to refname_match() selected which rules to use. When these two rules were harmonized in 2011-11-04 dd621df9cd refs DWIMmery: use the same rule for both "git fetch" and others , ref_fetch_rules was #defined to avoid potential breakages for in-flight topics. It is now safe to remove the backwards-compatibility code, so remove refname_match()'s third parameter, make ref_rev_parse_rules private to refs.c, and remove ref_fetch_rules entirely. Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-13Merge branch 'mh/shorten-unambigous-ref'Libravatar Junio C Hamano1-31/+14
* mh/shorten-unambigous-ref: shorten_unambiguous_ref(): tighten up pointer arithmetic gen_scanf_fmt(): delete function and use snprintf() instead shorten_unambiguous_ref(): introduce a new local variable
2014-01-09shorten_unambiguous_ref(): tighten up pointer arithmeticLibravatar Michael Haggerty1-2/+2
As long as we're being pathologically stingy with mallocs, we might as well do the math right and save 6 (!) bytes. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-09gen_scanf_fmt(): delete function and use snprintf() insteadLibravatar Michael Haggerty1-26/+9
To replace "%.*s" with "%s", all we have to do is use snprintf() to interpolate "%s" into the pattern. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-09shorten_unambiguous_ref(): introduce a new local variableLibravatar Michael Haggerty1-4/+4
When filling the scanf_fmts array, use a separate variable to keep track of the offset to avoid clobbering total_len (which we will need in the next commit). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-12-05replace {pre,suf}fixcmp() with {starts,ends}_with()Libravatar Christian Couder1-15/+15
Leaving only the function definitions and declarations so that any new topic in flight can still make use of the old functions, replace existing uses of the prefixcmp() and suffixcmp() with new API functions. The change can be recreated by mechanically applying this: $ git grep -l -e prefixcmp -e suffixcmp -- \*.c | grep -v strbuf\\.c | xargs perl -pi -e ' s|!prefixcmp\(|starts_with\(|g; s|prefixcmp\(|!starts_with\(|g; s|!suffixcmp\(|ends_with\(|g; s|suffixcmp\(|!ends_with\(|g; ' on the result of preparatory changes in this series. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-11-01Merge branch 'sb/refs-code-cleanup'Libravatar Junio C Hamano1-7/+0
* sb/refs-code-cleanup: cache: remove unused function 'have_git_dir' refs: remove unused function invalidate_ref_cache
2013-10-30Merge branch 'jk/refs-c-squelch-gcc'Libravatar Junio C Hamano1-1/+1
* jk/refs-c-squelch-gcc: silence gcc array-bounds warning
2013-10-28refs: remove unused function invalidate_ref_cacheLibravatar Stefan Beller1-7/+0
The function 'invalidate_ref_cache' was introduced in 79c7ca5 (2011-10-17, invalidate_ref_cache(): rename function from invalidate_cached_refs()) by a rename and elevated to be publicly usable in 8be8bde (2011-10-17, invalidate_ref_cache(): expose this function in the refs API) However it is not used anymore, as 8bf90dc (2011-10-17, write_ref_sha1(): only invalidate the loose ref cache) and (much) later 506a760 (2013-04-22, refs: change how packed refs are deleted) removed any calls to this function. So it seems as if we don't need that function any more, good bye! Signed-off-by: Stefan Beller <stefanbeller@googlemail.com> Acked-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-10-24silence gcc array-bounds warningLibravatar Jeff King1-1/+1
In shorten_unambiguous_ref, we build and cache a reverse-map of the rev-parse rules like this: static char **scanf_fmts; static int nr_rules; if (!nr_rules) { for (; ref_rev_parse_rules[nr_rules]; nr_rules++) ... generate scanf_fmts ... } where ref_rev_parse_rules is terminated with a NULL pointer. Compiling with "gcc -O2 -Wall" does not cause any problems, but compiling with "-O3 -Wall" generates: $ make CFLAGS='-O3 -Wall' refs.o refs.c: In function ‘shorten_unambiguous_ref’: refs.c:3379:29: warning: array subscript is above array bounds [-Warray-bounds] for (; ref_rev_parse_rules[nr_rules]; nr_rules++) Curiously, we can silence this by explicitly nr_rules to 0 in the beginning of the loop, even though the compiler should be able to tell that we follow this code path only when nr_rules is already 0. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-10-14refs.c: spell NULL pointer as NULLLibravatar Ramsay Jones1-1/+1
A call to update_ref_lock() passes '0' to the 'int *type_p' parameter. Noticed by sparse. ("Using plain integer as NULL pointer") Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
2013-09-20Merge branch 'fc/at-head'Libravatar Junio C Hamano1-1/+5
Instead of typing four capital letters "HEAD", you can say "@" now, e.g. "git log @". * fc/at-head: Add new @ shortcut for HEAD sha1-name: pass len argument to interpret_branch_name()
2013-09-20Merge branch 'bk/refs-multi-update'Libravatar Junio C Hamano1-27/+168
Give "update-refs" a "--stdin" option to read multiple update requests and perform them in an all-or-none fashion. * bk/refs-multi-update: update-ref: add test cases covering --stdin signature update-ref: support multiple simultaneous updates refs: add update_refs for multiple simultaneous updates refs: add function to repack without multiple refs refs: factor delete_ref loose ref step into a helper refs: factor update_ref steps into helpers refs: report ref type from lock_any_ref_for_update reset: rename update_refs to reset_refs
2013-09-12Add new @ shortcut for HEADLibravatar Felipe Contreras1-0/+4
Typing 'HEAD' is tedious, especially when we can use '@' instead. The reason for choosing '@' is that it follows naturally from the ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no operation, and when we don't have those, it makes sens to assume 'HEAD'. So now we can use 'git show @~1', and all that goody goodness. Until now '@' was a valid name, but it conflicts with this idea, so let's make it invalid. Probably very few people, if any, used this name. Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-09-09Merge branch 'jc/push-cas'Libravatar Junio C Hamano1-8/+0
Allow a safer "rewind of the remote tip" push than blind "--force", by requiring that the overwritten remote ref to be unchanged since the new history to replace it was prepared. The machinery is more or less ready. The "--force" option is again the big red button to override any safety, thanks to J6t's sanity (the original round allowed --lockref to defeat --force). The logic to choose the default implemented here is fragile (e.g. "git fetch" after seeing a failure will update the remote-tracking branch and will make the next "push" pass, defeating the safety pretty easily). It is suitable only for the simplest workflows, and it may hurt users more than it helps them. * jc/push-cas: push: teach --force-with-lease to smart-http transport send-pack: fix parsing of --force-with-lease option t5540/5541: smart-http does not support "--force-with-lease" t5533: test "push --force-with-lease" push --force-with-lease: tie it all together push --force-with-lease: implement logic to populate old_sha1_expect[] remote.c: add command line option parser for "--force-with-lease" builtin/push.c: use OPT_BOOL, not OPT_BOOLEAN cache.h: move remote/connect API out of it
2013-09-04refs: add update_refs for multiple simultaneous updatesLibravatar Brad King1-0/+100
Add 'struct ref_update' to encode the information needed to update or delete a ref (name, new sha1, optional old sha1, no-deref flag). Add function 'update_refs' accepting an array of updates to perform. First sort the input array to order locks consistently everywhere and reject multiple updates to the same ref. Then acquire locks on all refs with verified old values. Then update or delete all refs accordingly. Fail if any one lock cannot be obtained or any one old value does not match. Though the refs themselves cannot be modified together in a single atomic transaction, this function does enable some useful semantics. For example, a caller may create a new branch starting from the head of another branch and rewind the original branch at the same time. This transfers ownership of commits between branches without risk of losing commits added to the original branch by a concurrent process, or risk of a concurrent process creating the new branch first. Signed-off-by: Brad King <brad.king@kitware.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>