summaryrefslogtreecommitdiff
path: root/refs.c
AgeCommit message (Collapse)AuthorFilesLines
2014-12-01git_snpath(): retire and replace with strbuf_git_path()Libravatar Nguyễn Thái Ngọc Duy1-9/+42
In the previous patch, git_snpath() is modified to allocate a new strbuf buffer because vsnpath() needs that. But that makes it awkward because git_snpath() receives a pre-allocated buffer from outside and has to copy data back. Rename it to strbuf_git_path() and make it receive strbuf directly. Using git_path() in update_refs_for_switch() which used to call git_snpath() is safe because that function and all of its callers do not keep any pointer to the round-robin buffer pool allocated by get_pathname(). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-12-01path.c: make get_pathname() call sites return const char *Libravatar Nguyễn Thái Ngọc Duy1-4/+4
Before the previous commit, get_pathname returns an array of PATH_MAX length. Even if git_path() and similar functions does not use the whole array, git_path() caller can, in theory. After the commit, get_pathname() may return a buffer that has just enough room for the returned string and git_path() caller should never write beyond that. Make git_path(), mkpath() and git_path_submodule() return a const buffer to make sure callers do not write in it at all. This could have been part of the previous commit, but the "const" conversion is too much distraction from the core changes in path.c. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-06Merge branch 'jk/fetch-reflog-df-conflict'Libravatar Junio C Hamano1-2/+2
Corner-case bugfixes for "git fetch" around reflog handling. * jk/fetch-reflog-df-conflict: ignore stale directories when checking reflog existence fetch: load all default config at startup
2014-11-04ignore stale directories when checking reflog existenceLibravatar Jeff King1-2/+2
When we update a ref, we have two rules for whether or not we actually update the reflog: 1. If the reflog already exists, we will always append to it. 2. If log_all_ref_updates is set, we will create a new reflog file if necessary. We do the existence check by trying to open the reflog file, either with or without O_CREAT (depending on log_all_ref_updates). If it fails, then we check errno to see what happened. If we were not using O_CREAT and we got ENOENT, the file doesn't exist, and we return success (there isn't a reflog already, and we were not told to make a new one). If we get EISDIR, then there is likely a stale directory that needs to be removed (e.g., there used to be "foo/bar", it was deleted, and the directory "foo" was left. Now we want to create the ref "foo"). If O_CREAT is set, then we catch this case, try to remove the directory, and retry our open. So far so good. But if we get EISDIR and O_CREAT is not set, then we treat this as any other error, which is not right. Like ENOENT, EISDIR is an indication that we do not have a reflog, and we should silently return success (we were not told to create it). Instead, the current code reports this as an error, and we fail to update the ref at all. Note that this is relatively unlikely to happen, as you would have to have had reflogs turned on, and then later turned them off (it could also happen due to a bug in fetch, but that was fixed in the previous commit). However, it's quite easy to fix: we just need to treat EISDIR like ENOENT for the non-O_CREAT case, and silently return (note that this early return means we can also simplify the O_CREAT case). Our new tests cover both cases (O_CREAT and non-O_CREAT). The first one already worked, of course. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15ref_transaction_commit: bail out on failure to remove a refLibravatar Jonathan Nieder1-2/+6
When removal of a loose or packed ref fails, bail out instead of trying to finish the transaction. This way, a single error message can be printed (instead of multiple messages being concatenated by mistake) and the operator can try to solve the underlying problem before there is a chance to muck things up even more. In particular, when git fails to remove a ref, git goes on to try to delete the reflog. Exiting early lets us keep the reflog. When git succeeds in deleting a ref A and fails to remove a ref B, it goes on to try to delete both reflogs. It would be better to just remove the reflog for A, but that would be a more invasive change. Failing early means we keep both reflogs, which puts the operator in a good position to understand the problem and recover. A long term goal is to avoid these problems altogether and roll back the transaction on failure. That kind of transactionality will have to wait for a later series (the plan for which is to make all destructive work happen in a single update of the packed-refs file). Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Reviewed-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: do not permit err == NULLLibravatar Jonathan Nieder1-19/+27
Some functions that take a strbuf argument to append an error treat !err as an indication that the message should be suppressed (e.g., ref_update_reject_duplicates). Others write the message to stderr on !err (e.g., repack_without_refs). Others crash (e.g., ref_transaction_update). Some of these behaviors are for historical reasons and others were accidents. Luckily no callers pass err == NULL any more. Simplify by consistently requiring the strbuf argument. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Reviewed-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: allow listing and deleting badly named refsLibravatar Ronnie Sahlberg1-29/+119
We currently do not handle badly named refs well: $ cp .git/refs/heads/master .git/refs/heads/master.....@\*@\\. $ git branch fatal: Reference has invalid format: 'refs/heads/master.....@*@\.' $ git branch -D master.....@\*@\\. error: branch 'master.....@*@\.' not found. Users cannot recover from a badly named ref without manually finding and deleting the loose ref file or appropriate line in packed-refs. Making that easier will make it easier to tweak the ref naming rules in the future, for example to forbid shell metacharacters like '`' and '"', without putting people in a state that is hard to get out of. So allow "branch --list" to show these refs and allow "branch -d/-D" and "update-ref -d" to delete them. Other commands (for example to rename refs) will continue to not handle these refs but can be changed in later patches. Details: In resolving functions, refuse to resolve refs that don't pass the git-check-ref-format(1) check unless the new RESOLVE_REF_ALLOW_BAD_NAME flag is passed. Even with RESOLVE_REF_ALLOW_BAD_NAME, refuse to resolve refs that escape the refs/ directory and do not match the pattern [A-Z_]* (think "HEAD" and "MERGE_HEAD"). In locking functions, refuse to act on badly named refs unless they are being deleted and either are in the refs/ directory or match [A-Z_]*. Just like other invalid refs, flag resolved, badly named refs with the REF_ISBROKEN flag, treat them as resolving to null_sha1, and skip them in all iteration functions except for for_each_rawref. Flag badly named refs (but not symrefs pointing to badly named refs) with a REF_BAD_NAME flag to make it easier for future callers to notice and handle them specially. For example, in a later patch for-each-ref will use this flag to detect refs whose names can confuse callers parsing for-each-ref output. In the transaction API, refuse to create or update badly named refs, but allow deleting them (unless they try to escape refs/ and don't match [A-Z_]*). Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15packed-ref cache: forbid dot-components in refnamesLibravatar Jonathan Nieder1-11/+3
Since v1.7.9-rc1~10^2 (write_head_info(): handle "extra refs" locally, 2012-01-06), this trick to keep track of ".have" refs that are only valid on the wire and not on the filesystem is not needed any more. Simplify by removing support for the REFNAME_DOT_COMPONENT flag. This means we'll be slightly stricter with invalid refs found in a packed-refs file or during clone. read_loose_refs() already checks for and skips refnames with .components so it is not affected. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Reviewed-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15branch -d: avoid repeated symref resolutionLibravatar Jonathan Nieder1-2/+15
If a repository gets in a broken state with too much symref nesting, it cannot be repaired with "git branch -d": $ git symbolic-ref refs/heads/nonsense refs/heads/nonsense $ git branch -d nonsense error: branch 'nonsense' not found. Worse, "git update-ref --no-deref -d" doesn't work for such repairs either: $ git update-ref -d refs/heads/nonsense error: unable to resolve reference refs/heads/nonsense: Too many levels of symbolic links Fix both by teaching resolve_ref_unsafe a new RESOLVE_REF_NO_RECURSE flag and passing it when appropriate. Callers can still read the value of a symref (for example to print a message about it) with that flag set --- resolve_ref_unsafe will resolve one level of symrefs and stop there. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Reviewed-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: change resolve_ref_unsafe reading argument to be a flags fieldLibravatar Ronnie Sahlberg1-40/+53
resolve_ref_unsafe takes a boolean argument for reading (a nonexistent ref resolves successfully for writing but not for reading). Change this to be a flags field instead, and pass the new constant RESOLVE_REF_READING when we want this behaviour. While at it, swap two of the arguments in the function to put output arguments at the end. As a nice side effect, this ensures that we can catch callers that were unaware of the new API so they can be audited. Give the wrapper functions resolve_refdup and read_ref_full the same treatment for consistency. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: make write_ref_sha1 staticLibravatar Ronnie Sahlberg1-2/+8
No external users call write_ref_sha1 any more so let's declare it static. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: ref_transaction_commit: distinguish name conflicts from other errorsLibravatar Ronnie Sahlberg1-10/+16
In _commit, ENOTDIR can happen in the call to lock_ref_sha1_basic, either when we lstat the new refname or if the name checking function reports that the same type of conflict happened. In both cases, it means that we can not create the new ref due to a name conflict. Start defining specific return codes for _commit. TRANSACTION_NAME_CONFLICT refers to a failure to create a ref due to a name conflict with another ref. TRANSACTION_GENERIC_ERROR is for all other errors. When "git fetch" is creating refs, name conflicts differ from other errors in that they are likely to be resolved by running "git remote prune <remote>". "git fetch" currently inspects errno to decide whether to give that advice. Once it switches to the transaction API, it can check for TRANSACTION_NAME_CONFLICT instead. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: pass a list of names to skip to is_refname_availableLibravatar Ronnie Sahlberg1-18/+32
Change is_refname_available to take a list of strings to exclude when checking for conflicts instead of just one single name. We can already exclude a single name for the sake of renames. This generalizes that support. ref_transaction_commit already tracks a set of refs that are being deleted in an array. This array is then used to exclude refs from being written to the packed-refs file. At some stage we will want to change this array to a struct string_list and then we can pass it to is_refname_available via the call to lock_ref_sha1_basic. That will allow us to perform transactions that perform multiple renames as long as there are no conflicts within the starting or ending state. For example, that would allow a single transaction that contains two renames that are both individually conflicting: m -> n/n n -> m/m No functional change intended yet. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: call lock_ref_sha1_basic directly from commitLibravatar Ronnie Sahlberg1-6/+6
Skip using the lock_any_ref_for_update wrapper and call lock_ref_sha1_basic directly from the commit function. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: refuse to lock badly named refs in lock_ref_sha1_basicLibravatar Ronnie Sahlberg1-2/+5
Move the check for check_refname_format from lock_any_ref_for_update to lock_ref_sha1_basic. At some later stage we will get rid of lock_any_ref_for_update completely. This has no visible impact to callers except for the inability to lock badly named refs, which is not possible today already for other reasons.(*) Keep lock_any_ref_for_update as a no-op wrapper. It is the public facing version of this interface and keeping it as a separate function will make it easier to experiment with the internal lock_ref_sha1_basic signature. (*) For example, if lock_ref_sha1_basic checks the refname format and refuses to lock badly named refs, it will not be possible to delete such refs because the first step of deletion is to lock the ref. We currently already fail in that case because these refs are not recognized to exist: $ cp .git/refs/heads/master .git/refs/heads/echo...\*\* $ git branch -D .git/refs/heads/echo...\*\* error: branch '.git/refs/heads/echo...**' not found. This has been broken for a while. Later patches in the series will start repairing the handling of badly named refs. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15rename_ref: don't ask read_ref_full where the ref came fromLibravatar Ronnie Sahlberg1-1/+1
We call read_ref_full with a pointer to flags from rename_ref but since we never actually use the returned flags we can just pass NULL here instead. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: pass the ref log message to _create/delete/update instead of _commitLibravatar Ronnie Sahlberg1-13/+21
Change the ref transaction API so that we pass the reflog message to the create/delete/update functions instead of to ref_transaction_commit. This allows different reflog messages for each ref update in a multi-ref transaction. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: add an err argument to delete_ref_looseLibravatar Ronnie Sahlberg1-4/+5
Add an err argument to delete_ref_loose so that we can pass a descriptive error string back to the caller. Pass the err argument from transaction commit to this function so that transaction users will have a nice error string if the transaction failed due to delete_ref_loose. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15refs.c: lock_ref_sha1_basic is used for all refsLibravatar Ronnie Sahlberg1-1/+1
lock_ref_sha1_basic is used to lock refs that sit directly in the .git dir such as HEAD and MERGE_HEAD in addition to the more ordinary refs under "refs/". Remove the note claiming otherwise. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15wrapper.c: remove/unlink_or_warn: simplify, treat ENOENT as successLibravatar Ronnie Sahlberg1-1/+1
Simplify the function warn_if_unremovable slightly. Additionally, change behaviour slightly. If we failed to remove the object because the object does not exist, we can still return success back to the caller since none of the callers depend on "fail if the file did not exist". Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-01commit_packed_refs(): reimplement using fdopen_lock_file()Libravatar Michael Haggerty1-4/+1
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-01lockfile.h: extract new header file for the functions in lockfile.cLibravatar Michael Haggerty1-0/+1
Move the interface declaration for the functions in lockfile.c from cache.h to a new file, lockfile.h. Add #includes where necessary (and remove some redundant includes of cache.h by files that already include builtin.h). Move the documentation of the lock_file state diagram from lockfile.c to the new header file. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-01get_locked_file_path(): new functionLibravatar Michael Haggerty1-3/+1
Add a function to return the path of the file that is locked by a lock_file object. This reduces the knowledge that callers have to have about the lock_file layout. Suggested-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-01lockfile: rename LOCK_NODEREF to LOCK_NO_DEREFLibravatar Michael Haggerty1-1/+1
This makes it harder to misread the name as LOCK_NODE_REF. Suggested-by: Torsten Bögershausen <tboegi@web.de> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-01lockfile: change lock_file::filename into a strbufLibravatar Michael Haggerty1-3/+3
For now, we still make sure to allocate at least PATH_MAX characters for the strbuf because resolve_symlink() doesn't know how to expand the space for its return value. (That will be fixed in a moment.) Another alternative would be to just use a strbuf as scratch space in lock_file() but then store a pointer to the naked string in struct lock_file. But lock_file objects are often reused. By reusing the same strbuf, we can avoid having to reallocate the string most times when a lock_file object is reused. Helped-by: Torsten Bögershausen <tboegi@web.de> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-01delete_ref_loose(): don't muck around in the lock_file's filenameLibravatar Michael Haggerty1-6/+9
It's bad manners. Especially since there could be a signal during the call to unlink_or_warn(), in which case the signal handler will see the wrong filename and delete the reference file, leaving the lockfile behind. So make our own copy to work with. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-01cache.h: define constants LOCK_SUFFIX and LOCK_SUFFIX_LENLibravatar Michael Haggerty1-3/+4
There are a few places that use these values, so define constants for them. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-01unable_to_lock_die(): rename function from unable_to_lock_index_die()Libravatar Michael Haggerty1-1/+1
This function is used for other things besides the index, so rename it accordingly. Suggested-by: Jeff King <peff@peff.net> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Reviewed-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-29Merge branch 'da/rev-parse-verify-quiet'Libravatar Junio C Hamano1-3/+7
"rev-parse --verify --quiet $name" is meant to quietly exit with a non-zero status when $name is not a valid object name, but still gave error messages in some cases. * da/rev-parse-verify-quiet: stash: prefer --quiet over shell redirection of the standard error stream refs: make rev-parse --quiet actually quiet t1503: use test_must_be_empty Documentation: a note about stdout for git rev-parse --verify --quiet
2014-09-26Merge branch 'jk/faster-name-conflicts'Libravatar Junio C Hamano1-32/+90
Optimize the check to see if a ref $F can be created by making sure no existing ref has $F/ as its prefix, which especially matters in a repository with a large number of existing refs. * jk/faster-name-conflicts: refs: speed up is_refname_available
2014-09-26Merge branch 'jk/write-packed-refs-via-stdio'Libravatar Junio C Hamano1-23/+16
Optimize the code path to write out the packed-refs file, which especially matters in a repository with a large number of refs. * jk/write-packed-refs-via-stdio: refs: write packed_refs file using stdio
2014-09-19refs: make rev-parse --quiet actually quietLibravatar David Aguilar1-3/+7
When a reflog is deleted, e.g. when "git stash" clears its stashes, "git rev-parse --verify --quiet" dies: fatal: Log for refs/stash is empty. The reason is that the get_sha1() code path does not allow us to suppress this message. Pass the flags bitfield through get_sha1_with_context() so that read_ref_at() can suppress the message. Use get_sha1_with_context1() instead of get_sha1() in rev-parse so that the --quiet flag is honored. Signed-off-by: David Aguilar <davvid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-12refs: speed up is_refname_availableLibravatar Jeff King1-32/+90
Our filesystem ref storage does not allow D/F conflicts; so if "refs/heads/a/b" exists, we do not allow "refs/heads/a" to exist (and vice versa). This falls out naturally for loose refs, where the filesystem enforces the condition. But for packed-refs, we have to make the check ourselves. We do so by iterating over the entire packed-refs namespace and checking whether each name creates a conflict. If you have a very large number of refs, this is quite inefficient, as you end up doing a large number of comparisons with uninteresting bits of the ref tree (e.g., we know that all of "refs/tags" is uninteresting in the example above, yet we check each entry in it). Instead, let's take advantage of the fact that we have the packed refs stored as a trie of ref_entry structs. We can find each component of the proposed refname as we walk through the trie, checking for D/F conflicts as we go. For a refname of depth N (i.e., 4 in the above example), we only have to visit N nodes. And at each visit, we can binary search the M names at that level, for a total complexity of O(N lg M). ("M" is different at each level, of course, but we can take the worst-case "M" as a bound). In a pathological case of fetching 30,000 fresh refs into a repository with 8.5 million refs, this dropped the time to run "git fetch" from tens of minutes to ~30s. This may also help smaller cases in which we check against loose refs (which we do when renaming a ref), as we may avoid a disk access for unrelated loose directories. Note that the tests we add appear at first glance to be redundant with what is already in t3210. However, the early tests are not robust; they are run with reflogs turned on, meaning that we are not actually testing is_refname_available at all! The operations will still fail because the reflogs will hit D/F conflicts in the filesystem. To get a true test, we must turn off reflogs (but we don't want to do so for the entire script, because the point of turning them on was to cover some other cases). Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-11Merge branch 'jk/prune-top-level-refs-after-packing'Libravatar Junio C Hamano1-1/+1
After "pack-refs --prune" packed refs at the top-level, it failed to prune them. * jk/prune-top-level-refs-after-packing: pack-refs: prune top-level refs like "refs/foo"
2014-09-11Merge branch 'rs/ref-transaction-1'Libravatar Junio C Hamano1-105/+140
The second batch of the transactional ref update series. * rs/ref-transaction-1: (22 commits) update-ref --stdin: pass transaction around explicitly update-ref --stdin: narrow scope of err strbuf refs.c: make delete_ref use a transaction refs.c: make prune_ref use a transaction to delete the ref refs.c: remove lock_ref_sha1 refs.c: remove the update_ref_write function refs.c: remove the update_ref_lock function refs.c: make lock_ref_sha1 static walker.c: use ref transaction for ref updates fast-import.c: use a ref transaction when dumping tags receive-pack.c: use a reference transaction for updating the refs refs.c: change update_ref to use a transaction branch.c: use ref transaction for all ref updates fast-import.c: change update_branch to use ref transactions sequencer.c: use ref transactions for all ref updates commit.c: use ref transactions for updates replace.c: use the ref transaction functions for updates tag.c: use ref transactions when doing updates refs.c: add transaction.status and track OPEN/CLOSED refs.c: make ref_transaction_begin take an err argument ...
2014-09-10refs: write packed_refs file using stdioLibravatar Jeff King1-23/+16
We write each line of a new packed-refs file individually using a write() syscall (and sometimes 2, if the ref is peeled). Since each line is only about 50-100 bytes long, this creates a lot of system call overhead. We can instead open a stdio handle around our descriptor and use fprintf to write to it. The extra buffering is not a problem for us, because nobody will read our new packed-refs file until we call commit_lock_file (by which point we have flushed everything). On a pathological repository with 8.5 million refs, this dropped the time to run `git pack-refs` from 20s to 6s. Signed-off-by: Jeff King <peff@peff.net> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: make delete_ref use a transactionLibravatar Ronnie Sahlberg1-21/+14
Change delete_ref to use a ref transaction for the deletion. At the same time since we no longer have any callers of repack_without_ref we can now delete this function. Change delete_ref to return 0 on success and 1 on failure instead of the previous 0 on success either 1 or -1 on failure. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: make prune_ref use a transaction to delete the refLibravatar Ronnie Sahlberg1-7/+21
Change prune_ref to delete the ref using a ref transaction. To do this we also need to add a new flag REF_ISPRUNING that will tell the transaction that we do not want to delete this ref from the packed refs. This flag is private to refs.c and not exposed to external callers. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: remove lock_ref_sha1Libravatar Ronnie Sahlberg1-10/+5
lock_ref_sha1 was only called from one place in refs.c and only provided a check that the refname was sane before adding back the initial "refs/" part of the ref path name, the initial "refs/" that this caller had already stripped off before calling lock_ref_sha1. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: remove the update_ref_write functionLibravatar Ronnie Sahlberg1-26/+8
Since we only call update_ref_write from a single place and we only call it with onerr==QUIET_ON_ERR we can just as well get rid of it and just call write_ref_sha1 directly. This changes the return status for _commit from 1 to -1 on failures when writing to the ref. Eventually we will want _commit to start returning more detailed error conditions than the current simple success/failure. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: remove the update_ref_lock functionLibravatar Ronnie Sahlberg1-24/+6
Since we now only call update_ref_lock with onerr==QUIET_ON_ERR we no longer need this function and can replace it with just calling lock_any_ref_for_update directly. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: make lock_ref_sha1 staticLibravatar Ronnie Sahlberg1-2/+5
No external callers reference lock_ref_sha1 any more so let's declare it static. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: change update_ref to use a transactionLibravatar Ronnie Sahlberg1-4/+26
Change the update_ref helper function to use a ref transaction internally. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: add transaction.status and track OPEN/CLOSEDLibravatar Ronnie Sahlberg1-1/+33
Track the state of a transaction in a new state field. Check the field for sanity, i.e. that state must be OPEN when _commit/_create/_delete or _update is called or else die(BUG:...) Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: make ref_transaction_begin take an err argumentLibravatar Ronnie Sahlberg1-1/+1
Add an err argument to _begin so that on non-fatal failures in future ref backends we can report a nice error back to the caller. While _begin can currently never fail for other reasons than OOM, in which case we die() anyway, we may add other types of backends in the future. For example, a hypothetical MySQL backend could fail in _begin with "Can not connect to MySQL server. No route to host". Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: update ref_transaction_delete to check for error and return statusLibravatar Ronnie Sahlberg1-5/+11
Change ref_transaction_delete() to do basic error checking and return non-zero on error. Update all callers to check the return for ref_transaction_delete(). There are currently no conditions in _delete that will return error but there will be in the future. Add an err argument that will be updated on failure. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-03refs.c: change ref_transaction_create to do error checking and return statusLibravatar Ronnie Sahlberg1-6/+12
Do basic error checking in ref_transaction_create() and make it return non-zero on error. Update all callers to check the result of ref_transaction_create(). There are currently no conditions in _create that will return error but there will be in the future. Add an err argument that will be updated on failure. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-08-25pack-refs: prune top-level refs like "refs/foo"Libravatar Jeff King1-1/+2
After we have packed all refs, we prune any loose refs that correspond to what we packed. We do so by first taking a lock with lock_ref_sha1, and then deleting the loose ref file. However, lock_ref_sha1 will refuse to take a lock on any refs that exist at the top-level of the "refs/" directory, and we skip pruning the ref. This is almost certainly not what we want to happen here. The criteria to be pruned should not differ from that to be packed; if a ref makes it to prune_ref, it's because we want it both packed and pruned (if there are refs you do not want to be packed, they should be omitted much earlier by pack_ref_is_possible, which we do in this case if --all is not given). We can fix this by switching to lock_any_ref_for_update. This behaves exactly the same with the exception of this top-level check. Signed-off-by: Jeff King <peff@peff.net> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Reviewed-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-07-28Revert "Merge branch 'dt/refs-check-refname-component-sse'"Libravatar Junio C Hamano1-216/+18
This reverts commit 6f92e5ff3cdc813de8ef5327fd4bad492fb7d6c9, reversing changes made to a02ad882a17b9d45f63ea448391ac5e9f7948222.
2014-07-28Revert "Merge branch 'dt/refs-check-refname-component-sse-fix'"Libravatar Junio C Hamano1-2/+1
This reverts commit 779c99fd68dcdaff7d996a1985914154a36a272c, reversing changes made to df4d7d56461c19361a6f32b633e850c7ba6e55e6.